Bläddra i källkod

各大模块基本开发完毕,剩下细节UI优化

kln 2 veckor sedan
förälder
incheckning
9b467bbba7
100 ändrade filer med 10064 tillägg och 246 borttagningar
  1. 273 19
      AIPlayRingtones.xcodeproj/project.pbxproj
  2. 9 0
      AIPlayRingtones/AIPlayRingtones-Bridging-Header.h
  3. 1 1
      AIPlayRingtones/APConfig/APConfig+Color.swift
  4. 25 0
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+StackView.swift
  5. 98 0
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+Upload.swift
  6. 91 0
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+View.swift
  7. 92 0
      AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC.swift
  8. 58 0
      AIPlayRingtones/AppPage/APAudioToRingVC/VM/APAudioToRingVM.swift
  9. 190 0
      AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRFileView.swift
  10. 176 0
      AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRStyleView.swift
  11. 271 0
      AIPlayRingtones/AppPage/APMyRingVC/ASMyRingCell.swift
  12. 184 0
      AIPlayRingtones/AppPage/APMyRingVC/ASMyRingVC.swift
  13. 1 1
      AIPlayRingtones/AppPage/APRingTonesVC/APRingStyleVC/APRingStyleVC.swift
  14. 1 1
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC+View.swift
  15. 18 6
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC.swift
  16. 5 3
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/Model/ASGenerateStyleModel.swift
  17. 2 2
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/Model/ASRingGenerateSecModel.swift
  18. 10 2
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/VM/APRingTonesVM.swift
  19. 1 1
      AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/View/ASDurationColView.swift
  20. 137 0
      AIPlayRingtones/AppPage/APSettingVC/APSettingVC+Col.swift
  21. 172 0
      AIPlayRingtones/AppPage/APSettingVC/APSettingVC.swift
  22. 73 0
      AIPlayRingtones/AppPage/ASBusinessWebVC/ASBusinessWebVC.swift
  23. 111 0
      AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC+load.swift
  24. 180 206
      AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC.swift
  25. 4 4
      AIPlayRingtones/AppPage/ASTabBarVC/ASTabBarVC.swift
  26. 25 0
      AIPlayRingtones/AppPage/Common/ Notification+Ex.swift
  27. 7 0
      AIPlayRingtones/AppPage/Common/AIEnums.swift
  28. 176 0
      AIPlayRingtones/AppPage/Common/ASBusinessFileManager.swift
  29. 45 0
      AIPlayRingtones/AppPage/Common/ASDownloadManager/ASDownloadManager.swift
  30. 8 0
      AIPlayRingtones/AppPage/Common/Common.swift
  31. 394 0
      AIPlayRingtones/AppPage/Common/CpuMapManager.swift
  32. 294 0
      AIPlayRingtones/AppPage/Common/TSAudioPlayer/TSAudioPlayer.swift
  33. 337 0
      AIPlayRingtones/AppPage/Common/TSAudioPlayer/TSBusinessAudioPlayer.swift
  34. 26 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/AudioConverter.h
  35. 142 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/AudioConverter.m
  36. 48 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/AudioTool.swift
  37. 248 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/TSBandRingTool.swift
  38. 55 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHAudioProcessing.swift
  39. 37 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHCroppedDelegate.swift
  40. 36 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHTrackProcessing.swift
  41. 311 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHWaveformView.swift
  42. 19 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHWaveformViewDelegate.swift
  43. 37 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/ExtAudioConverter.h
  44. 446 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/ExtAudioConverter.m
  45. 1323 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/lame.h
  46. BIN
      AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/libmp3lame.a
  47. 1 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Contents/PkgInfo
  48. 0 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Media/kong.txt
  49. BIN
      AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/assetsmetadata.plist
  50. 74 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/metadata.plist
  51. 20 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/output.plist
  52. BIN
      AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/output.xyz
  53. 2570 0
      AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/projectData
  54. BIN
      AIPlayRingtones/AppPage/Common/TSBandRingTool/tutorial-ring.mp4
  55. 250 0
      AIPlayRingtones/AppPage/Common/TSNetWork/TSNetWork+Business.swift
  56. 111 0
      AIPlayRingtones/AppPage/Common/TSNetWork/TSNetWork+Error.swift
  57. 86 0
      AIPlayRingtones/AppPage/Common/TSNetWork/TSNetworkManager+Loading.swift
  58. 438 0
      AIPlayRingtones/AppPage/Common/TSNetWork/TSNetworkManager.swift
  59. 19 0
      AIPlayRingtones/AppPage/Common/TSPurchaseTool/TSPurchaseTool.swift
  60. 6 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/Contents.json
  61. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Disco.imageset/Contents.json
  62. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Disco.imageset/rtr_style_Disco@2x.png
  63. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Disco.imageset/rtr_style_Disco@3x.png
  64. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Dubstep.imageset/Contents.json
  65. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Dubstep.imageset/rtr_style_Dubstep@2x.png
  66. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Dubstep.imageset/rtr_style_Dubstep@3x.png
  67. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Electro.imageset/Contents.json
  68. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Electro.imageset/rtr_style_Electro@2x.png
  69. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Electro.imageset/rtr_style_Electro@3x.png
  70. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Funk.imageset/Contents.json
  71. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Funk.imageset/rtr_style_Funk@2x.png
  72. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Funk.imageset/rtr_style_Funk@3x.png
  73. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_HipHop.imageset/Contents.json
  74. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_HipHop.imageset/rtr_style_HipHop@2x.png
  75. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_HipHop.imageset/rtr_style_HipHop@3x.png
  76. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Jazz.imageset/Contents.json
  77. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Jazz.imageset/rtr_style_Jazz@2x.png
  78. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Jazz.imageset/rtr_style_Jazz@3x.png
  79. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Pop.imageset/Contents.json
  80. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Pop.imageset/rtr_style_Pop@2x.png
  81. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Pop.imageset/rtr_style_Pop@3x.png
  82. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Rock.imageset/Contents.json
  83. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Rock.imageset/rtr_style_Rock@2x.png
  84. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Rock.imageset/rtr_style_Rock@3x.png
  85. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/nav_title_audioRingtone.imageset/Contents.json
  86. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/nav_title_audioRingtone.imageset/nav_titile_audioRingtone@2x.png
  87. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/nav_title_audioRingtone.imageset/nav_titile_audioRingtone@3x.png
  88. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_add.imageset/Contents.json
  89. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_add.imageset/uploadFile_add@2x.png
  90. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_add.imageset/uploadFile_add@3x.png
  91. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_change.imageset/Contents.json
  92. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_change.imageset/uploadFile_change@2x.png
  93. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_change.imageset/uploadFile_change@3x.png
  94. 22 0
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_icon.imageset/Contents.json
  95. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_icon.imageset/uploadFile_icon@2x.png
  96. BIN
      AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_icon.imageset/uploadFile_icon@3x.png
  97. 6 0
      AIPlayRingtones/Assets.xcassets/CellPlay/Contents.json
  98. 22 0
      AIPlayRingtones/Assets.xcassets/CellPlay/ai_rintone_icon.imageset/Contents.json
  99. BIN
      AIPlayRingtones/Assets.xcassets/CellPlay/ai_rintone_icon.imageset/ai_rintone_icon@2x.png
  100. BIN
      AIPlayRingtones/Assets.xcassets/CellPlay/ai_rintone_icon.imageset/ai_rintone_icon@3x.png

+ 273 - 19
AIPlayRingtones.xcodeproj/project.pbxproj

@@ -7,6 +7,44 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		3DB4D4912DDC1F100082596A /* ASRingGeneratorVC+load.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4902DDC1F0C0082596A /* ASRingGeneratorVC+load.swift */; };
+		3DB4D4932DDC25C10082596A /* APAudioToRingVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4922DDC25BD0082596A /* APAudioToRingVM.swift */; };
+		3DB4D4972DDC28D40082596A /* APAudioToRingVC+View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4962DDC28D10082596A /* APAudioToRingVC+View.swift */; };
+		3DB4D4992DDC28E70082596A /* APAudioToRingVC+StackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4982DDC28DB0082596A /* APAudioToRingVC+StackView.swift */; };
+		3DB4D49B2DDC28F20082596A /* APAudioToRingVC+Upload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D49A2DDC28EC0082596A /* APAudioToRingVC+Upload.swift */; };
+		3DB4D49D2DDC29AC0082596A /* ASRTRStyleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D49C2DDC29AC0082596A /* ASRTRStyleView.swift */; };
+		3DB4D4A12DDC2CCE0082596A /* ring_rtr_style.json in Resources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A02DDC2CC90082596A /* ring_rtr_style.json */; };
+		3DB4D4A32DDC34100082596A /* ASRTRFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A22DDC34020082596A /* ASRTRFileView.swift */; };
+		3DB4D4A52DDC8E830082596A /* APSettingVC+Col.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A42DDC8E7B0082596A /* APSettingVC+Col.swift */; };
+		3DB4D4A82DDC92560082596A /* ASBusinessWebVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DB4D4A72DDC92530082596A /* ASBusinessWebVC.swift */; };
+		3DCD56F32DDAE3E3004AAB5B /* ASRingToneCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56F22DDAE3DF004AAB5B /* ASRingToneCellView.swift */; };
+		3DCD56F52DDAE42A004AAB5B /* ASViewTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56F42DDAE421004AAB5B /* ASViewTool.swift */; };
+		3DCD56F92DDAE481004AAB5B /* TSBusinessAudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56F62DDAE481004AAB5B /* TSBusinessAudioPlayer.swift */; };
+		3DCD56FA2DDAE481004AAB5B /* TSAudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56F72DDAE481004AAB5B /* TSAudioPlayer.swift */; };
+		3DCD56FD2DDAFBE5004AAB5B /* ASDownloadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56FC2DDAFBE4004AAB5B /* ASDownloadManager.swift */; };
+		3DCD56FF2DDAFC1B004AAB5B /* ASBusinessFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD56FE2DDAFC17004AAB5B /* ASBusinessFileManager.swift */; };
+		3DCD57012DDB1008004AAB5B /* CpuMapManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57002DDB1008004AAB5B /* CpuMapManager.swift */; };
+		3DCD57052DDB1120004AAB5B /* TSPurchaseTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57042DDB111F004AAB5B /* TSPurchaseTool.swift */; };
+		3DCD57182DDB1158004AAB5B /* libmp3lame.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DCD57092DDB1158004AAB5B /* libmp3lame.a */; };
+		3DCD57192DDB1158004AAB5B /* AudioTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD570D2DDB1158004AAB5B /* AudioTool.swift */; };
+		3DCD571A2DDB1158004AAB5B /* ExtAudioConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD570A2DDB1158004AAB5B /* ExtAudioConverter.m */; };
+		3DCD571B2DDB1158004AAB5B /* AudioConverter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57072DDB1158004AAB5B /* AudioConverter.m */; };
+		3DCD571C2DDB1158004AAB5B /* ZHCroppedDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57152DDB1158004AAB5B /* ZHCroppedDelegate.swift */; };
+		3DCD571D2DDB1158004AAB5B /* ZHAudioProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57112DDB1158004AAB5B /* ZHAudioProcessing.swift */; };
+		3DCD571E2DDB1158004AAB5B /* ZHWaveformViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57122DDB1158004AAB5B /* ZHWaveformViewDelegate.swift */; };
+		3DCD571F2DDB1158004AAB5B /* TSBandRingTool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD570F2DDB1158004AAB5B /* TSBandRingTool.swift */; };
+		3DCD57202DDB1158004AAB5B /* ZHTrackProcessing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57132DDB1158004AAB5B /* ZHTrackProcessing.swift */; };
+		3DCD57212DDB1158004AAB5B /* ZHWaveformView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57142DDB1158004AAB5B /* ZHWaveformView.swift */; };
+		3DCD57222DDB1158004AAB5B /* tutorial-ring.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 3DCD570E2DDB1158004AAB5B /* tutorial-ring.mp4 */; };
+		3DCD57232DDB1158004AAB5B /* placeholder.band in Resources */ = {isa = PBXBuildFile; fileRef = 3DCD57102DDB1158004AAB5B /* placeholder.band */; };
+		3DCD572F2DDB1D8A004AAB5B /* ASRingLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD572E2DDB1D87004AAB5B /* ASRingLoadingView.swift */; };
+		3DCD57312DDB2A66004AAB5B /* ASGenerateRingToRingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD57302DDB2A5D004AAB5B /* ASGenerateRingToRingOperation.swift */; };
+		3DCD57342DDB38E7004AAB5B /* ringAnimation.gif in Resources */ = {isa = PBXBuildFile; fileRef = 3DCD57322DDB38E7004AAB5B /* ringAnimation.gif */; };
+		3DCD57352DDB38E7004AAB5B /* rotatingAnimation.gif in Resources */ = {isa = PBXBuildFile; fileRef = 3DCD57332DDB38E7004AAB5B /* rotatingAnimation.gif */; };
+		3DCD57382DDB3FFA004AAB5B /* DanceRingtoneExample.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3DCD57362DDB3FFA004AAB5B /* DanceRingtoneExample.mp3 */; };
+		3DCD57392DDB3FFA004AAB5B /* GentleRingtoneExample.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = 3DCD57372DDB3FFA004AAB5B /* GentleRingtoneExample.mp3 */; };
+		3DCD573B2DDB4E61004AAB5B /* ASPageNullView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD573A2DDB4E5E004AAB5B /* ASPageNullView.swift */; };
+		3DCD573D2DDB5A3C004AAB5B /* ASMyRingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCD573C2DDB5A2E004AAB5B /* ASMyRingCell.swift */; };
 		A800FEB22DDAC100009DABDC /* ASGeneratorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A800FEB12DDAC0FC009DABDC /* ASGeneratorView.swift */; };
 		A800FEB42DDAC73E009DABDC /* ASGeneratorLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A800FEB32DDAC738009DABDC /* ASGeneratorLoadingView.swift */; };
 		A800FEB62DDAC764009DABDC /* ASGeneratorErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A800FEB52DDAC75D009DABDC /* ASGeneratorErrorView.swift */; };
@@ -24,7 +62,7 @@
 		A848F8A12DD6D59C00B746EC /* TSNetworkManager+Loading.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F89B2DD6D59C00B746EC /* TSNetworkManager+Loading.swift */; };
 		A848F8A42DD6D67000B746EC /* APRingTonesVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8A32DD6D66D00B746EC /* APRingTonesVC.swift */; };
 		A848F8A92DD6D74A00B746EC /* APAudioToRingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8A82DD6D74900B746EC /* APAudioToRingVC.swift */; };
-		A848F8AB2DD6D75300B746EC /* APMyRingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8AA2DD6D75200B746EC /* APMyRingVC.swift */; };
+		A848F8AB2DD6D75300B746EC /* ASMyRingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8AA2DD6D75200B746EC /* ASMyRingVC.swift */; };
 		A848F8AD2DD6D75900B746EC /* APSettingVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8AC2DD6D75800B746EC /* APSettingVC.swift */; };
 		A848F8B02DD6D77C00B746EC /* ASTabBarVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8AF2DD6D77B00B746EC /* ASTabBarVC.swift */; };
 		A848F8B32DD6D82300B746EC /* APConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8B22DD6D82300B746EC /* APConfig.swift */; };
@@ -42,7 +80,7 @@
 		A848F8D52DD719B600B746EC /* ring_duration.json in Resources */ = {isa = PBXBuildFile; fileRef = A848F8D42DD719AB00B746EC /* ring_duration.json */; };
 		A848F8D82DD71A3A00B746EC /* ASRingGenerateSecModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8D72DD71A3100B746EC /* ASRingGenerateSecModel.swift */; };
 		A848F8DB2DD7231E00B746EC /* APRingStyleVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8DA2DD7231C00B746EC /* APRingStyleVC.swift */; };
-		A848F8E12DD7271900B746EC /* ring_style.json in Resources */ = {isa = PBXBuildFile; fileRef = A848F8E02DD7271400B746EC /* ring_style.json */; };
+		A848F8E12DD7271900B746EC /* ring_ttr_style.json in Resources */ = {isa = PBXBuildFile; fileRef = A848F8E02DD7271400B746EC /* ring_ttr_style.json */; };
 		A848F8E32DD7286A00B746EC /* ASGenerateStyleModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8E22DD7286600B746EC /* ASGenerateStyleModel.swift */; };
 		A848F8E82DD74DFD00B746EC /* ASDBHistoryManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8E72DD74DF900B746EC /* ASDBHistoryManager.swift */; };
 		A848F8EA2DD74E3A00B746EC /* ASDBActionInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8E92DD74E3600B746EC /* ASDBActionInfoModel.swift */; };
@@ -51,13 +89,55 @@
 		A848F8F12DD7528800B746EC /* ASBaseOperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8F02DD7528200B746EC /* ASBaseOperationQueue.swift */; };
 		A848F8F32DD7528D00B746EC /* ASBaseOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8F22DD7528C00B746EC /* ASBaseOperation.swift */; };
 		A848F8F62DD752D700B746EC /* ASGenerateBaseOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8F52DD752C400B746EC /* ASGenerateBaseOperation.swift */; };
-		A848F8F82DD752E700B746EC /* ASGeneratePosterOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8F72DD752D900B746EC /* ASGeneratePosterOperation.swift */; };
+		A848F8F82DD752E700B746EC /* ASGenerateTextToRingOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8F72DD752D900B746EC /* ASGenerateTextToRingOperation.swift */; };
 		A848F8FA2DD7536700B746EC /*  Notification+Ex.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8F92DD7536300B746EC /*  Notification+Ex.swift */; };
 		A848F8FC2DD753A000B746EC /* ASProgressState.swift in Sources */ = {isa = PBXBuildFile; fileRef = A848F8FB2DD7539E00B746EC /* ASProgressState.swift */; };
 		C6F204E3DD79A0F96C8DB3FF /* Pods_AIPlayRingtones.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6EFB792FA59CD8536D0BD11F /* Pods_AIPlayRingtones.framework */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXFileReference section */
+		3DB4D4902DDC1F0C0082596A /* ASRingGeneratorVC+load.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ASRingGeneratorVC+load.swift"; sourceTree = "<group>"; };
+		3DB4D4922DDC25BD0082596A /* APAudioToRingVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APAudioToRingVM.swift; sourceTree = "<group>"; };
+		3DB4D4962DDC28D10082596A /* APAudioToRingVC+View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APAudioToRingVC+View.swift"; sourceTree = "<group>"; };
+		3DB4D4982DDC28DB0082596A /* APAudioToRingVC+StackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APAudioToRingVC+StackView.swift"; sourceTree = "<group>"; };
+		3DB4D49A2DDC28EC0082596A /* APAudioToRingVC+Upload.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APAudioToRingVC+Upload.swift"; sourceTree = "<group>"; };
+		3DB4D49C2DDC29AC0082596A /* ASRTRStyleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASRTRStyleView.swift; sourceTree = "<group>"; };
+		3DB4D4A02DDC2CC90082596A /* ring_rtr_style.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ring_rtr_style.json; sourceTree = "<group>"; };
+		3DB4D4A22DDC34020082596A /* ASRTRFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASRTRFileView.swift; sourceTree = "<group>"; };
+		3DB4D4A42DDC8E7B0082596A /* APSettingVC+Col.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APSettingVC+Col.swift"; sourceTree = "<group>"; };
+		3DB4D4A72DDC92530082596A /* ASBusinessWebVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASBusinessWebVC.swift; sourceTree = "<group>"; };
+		3DCD56F22DDAE3DF004AAB5B /* ASRingToneCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASRingToneCellView.swift; sourceTree = "<group>"; };
+		3DCD56F42DDAE421004AAB5B /* ASViewTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASViewTool.swift; sourceTree = "<group>"; };
+		3DCD56F62DDAE481004AAB5B /* TSBusinessAudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBusinessAudioPlayer.swift; sourceTree = "<group>"; };
+		3DCD56F72DDAE481004AAB5B /* TSAudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSAudioPlayer.swift; sourceTree = "<group>"; };
+		3DCD56FC2DDAFBE4004AAB5B /* ASDownloadManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASDownloadManager.swift; sourceTree = "<group>"; };
+		3DCD56FE2DDAFC17004AAB5B /* ASBusinessFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASBusinessFileManager.swift; sourceTree = "<group>"; };
+		3DCD57002DDB1008004AAB5B /* CpuMapManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CpuMapManager.swift; sourceTree = "<group>"; };
+		3DCD57042DDB111F004AAB5B /* TSPurchaseTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSPurchaseTool.swift; sourceTree = "<group>"; };
+		3DCD57062DDB1158004AAB5B /* AudioConverter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AudioConverter.h; sourceTree = "<group>"; };
+		3DCD57072DDB1158004AAB5B /* AudioConverter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AudioConverter.m; sourceTree = "<group>"; };
+		3DCD57082DDB1158004AAB5B /* ExtAudioConverter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExtAudioConverter.h; sourceTree = "<group>"; };
+		3DCD57092DDB1158004AAB5B /* libmp3lame.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libmp3lame.a; sourceTree = "<group>"; };
+		3DCD570A2DDB1158004AAB5B /* ExtAudioConverter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExtAudioConverter.m; sourceTree = "<group>"; };
+		3DCD570B2DDB1158004AAB5B /* lame.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lame.h; sourceTree = "<group>"; };
+		3DCD570D2DDB1158004AAB5B /* AudioTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioTool.swift; sourceTree = "<group>"; };
+		3DCD570E2DDB1158004AAB5B /* tutorial-ring.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = "tutorial-ring.mp4"; sourceTree = "<group>"; };
+		3DCD570F2DDB1158004AAB5B /* TSBandRingTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TSBandRingTool.swift; sourceTree = "<group>"; };
+		3DCD57102DDB1158004AAB5B /* placeholder.band */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = placeholder.band; sourceTree = "<group>"; };
+		3DCD57112DDB1158004AAB5B /* ZHAudioProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHAudioProcessing.swift; sourceTree = "<group>"; };
+		3DCD57122DDB1158004AAB5B /* ZHWaveformViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHWaveformViewDelegate.swift; sourceTree = "<group>"; };
+		3DCD57132DDB1158004AAB5B /* ZHTrackProcessing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHTrackProcessing.swift; sourceTree = "<group>"; };
+		3DCD57142DDB1158004AAB5B /* ZHWaveformView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHWaveformView.swift; sourceTree = "<group>"; };
+		3DCD57152DDB1158004AAB5B /* ZHCroppedDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZHCroppedDelegate.swift; sourceTree = "<group>"; };
+		3DCD572D2DDB1976004AAB5B /* AIPlayRingtones-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AIPlayRingtones-Bridging-Header.h"; sourceTree = "<group>"; };
+		3DCD572E2DDB1D87004AAB5B /* ASRingLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASRingLoadingView.swift; sourceTree = "<group>"; };
+		3DCD57302DDB2A5D004AAB5B /* ASGenerateRingToRingOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASGenerateRingToRingOperation.swift; sourceTree = "<group>"; };
+		3DCD57322DDB38E7004AAB5B /* ringAnimation.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = ringAnimation.gif; sourceTree = "<group>"; };
+		3DCD57332DDB38E7004AAB5B /* rotatingAnimation.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = rotatingAnimation.gif; sourceTree = "<group>"; };
+		3DCD57362DDB3FFA004AAB5B /* DanceRingtoneExample.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = DanceRingtoneExample.mp3; sourceTree = "<group>"; };
+		3DCD57372DDB3FFA004AAB5B /* GentleRingtoneExample.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = GentleRingtoneExample.mp3; sourceTree = "<group>"; };
+		3DCD573A2DDB4E5E004AAB5B /* ASPageNullView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASPageNullView.swift; sourceTree = "<group>"; };
+		3DCD573C2DDB5A2E004AAB5B /* ASMyRingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASMyRingCell.swift; sourceTree = "<group>"; };
 		6EFB792FA59CD8536D0BD11F /* Pods_AIPlayRingtones.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AIPlayRingtones.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 		A800FEB12DDAC0FC009DABDC /* ASGeneratorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASGeneratorView.swift; sourceTree = "<group>"; };
 		A800FEB32DDAC738009DABDC /* ASGeneratorLoadingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASGeneratorLoadingView.swift; sourceTree = "<group>"; };
@@ -78,7 +158,7 @@
 		A848F89B2DD6D59C00B746EC /* TSNetworkManager+Loading.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TSNetworkManager+Loading.swift"; sourceTree = "<group>"; };
 		A848F8A32DD6D66D00B746EC /* APRingTonesVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APRingTonesVC.swift; sourceTree = "<group>"; };
 		A848F8A82DD6D74900B746EC /* APAudioToRingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APAudioToRingVC.swift; sourceTree = "<group>"; };
-		A848F8AA2DD6D75200B746EC /* APMyRingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APMyRingVC.swift; sourceTree = "<group>"; };
+		A848F8AA2DD6D75200B746EC /* ASMyRingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASMyRingVC.swift; sourceTree = "<group>"; };
 		A848F8AC2DD6D75800B746EC /* APSettingVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APSettingVC.swift; sourceTree = "<group>"; };
 		A848F8AF2DD6D77B00B746EC /* ASTabBarVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASTabBarVC.swift; sourceTree = "<group>"; };
 		A848F8B22DD6D82300B746EC /* APConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APConfig.swift; sourceTree = "<group>"; };
@@ -96,7 +176,7 @@
 		A848F8D42DD719AB00B746EC /* ring_duration.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ring_duration.json; sourceTree = "<group>"; };
 		A848F8D72DD71A3100B746EC /* ASRingGenerateSecModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASRingGenerateSecModel.swift; sourceTree = "<group>"; };
 		A848F8DA2DD7231C00B746EC /* APRingStyleVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APRingStyleVC.swift; sourceTree = "<group>"; };
-		A848F8E02DD7271400B746EC /* ring_style.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ring_style.json; sourceTree = "<group>"; };
+		A848F8E02DD7271400B746EC /* ring_ttr_style.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = ring_ttr_style.json; sourceTree = "<group>"; };
 		A848F8E22DD7286600B746EC /* ASGenerateStyleModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASGenerateStyleModel.swift; sourceTree = "<group>"; };
 		A848F8E72DD74DF900B746EC /* ASDBHistoryManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASDBHistoryManager.swift; sourceTree = "<group>"; };
 		A848F8E92DD74E3600B746EC /* ASDBActionInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASDBActionInfoModel.swift; sourceTree = "<group>"; };
@@ -105,7 +185,7 @@
 		A848F8F02DD7528200B746EC /* ASBaseOperationQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASBaseOperationQueue.swift; sourceTree = "<group>"; };
 		A848F8F22DD7528C00B746EC /* ASBaseOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASBaseOperation.swift; sourceTree = "<group>"; };
 		A848F8F52DD752C400B746EC /* ASGenerateBaseOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASGenerateBaseOperation.swift; sourceTree = "<group>"; };
-		A848F8F72DD752D900B746EC /* ASGeneratePosterOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASGeneratePosterOperation.swift; sourceTree = "<group>"; };
+		A848F8F72DD752D900B746EC /* ASGenerateTextToRingOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASGenerateTextToRingOperation.swift; sourceTree = "<group>"; };
 		A848F8F92DD7536300B746EC /*  Notification+Ex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = " Notification+Ex.swift"; sourceTree = "<group>"; };
 		A848F8FB2DD7539E00B746EC /* ASProgressState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ASProgressState.swift; sourceTree = "<group>"; };
 		B4EF561F1D6A688DA6595B7A /* Pods-AIPlayRingtones.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AIPlayRingtones.debug.xcconfig"; path = "Target Support Files/Pods-AIPlayRingtones/Pods-AIPlayRingtones.debug.xcconfig"; sourceTree = "<group>"; };
@@ -118,12 +198,101 @@
 			buildActionMask = 2147483647;
 			files = (
 				C6F204E3DD79A0F96C8DB3FF /* Pods_AIPlayRingtones.framework in Frameworks */,
+				3DCD57182DDB1158004AAB5B /* libmp3lame.a in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		3DB4D4942DDC28AD0082596A /* VM */ = {
+			isa = PBXGroup;
+			children = (
+				3DB4D4922DDC25BD0082596A /* APAudioToRingVM.swift */,
+			);
+			path = VM;
+			sourceTree = "<group>";
+		};
+		3DB4D4952DDC28C60082596A /* View */ = {
+			isa = PBXGroup;
+			children = (
+				3DB4D4A22DDC34020082596A /* ASRTRFileView.swift */,
+				3DB4D49C2DDC29AC0082596A /* ASRTRStyleView.swift */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		3DB4D4A62DDC924B0082596A /* ASBusinessWebVC */ = {
+			isa = PBXGroup;
+			children = (
+				3DB4D4A72DDC92530082596A /* ASBusinessWebVC.swift */,
+			);
+			path = ASBusinessWebVC;
+			sourceTree = "<group>";
+		};
+		3DCD56F82DDAE481004AAB5B /* TSAudioPlayer */ = {
+			isa = PBXGroup;
+			children = (
+				3DCD56F62DDAE481004AAB5B /* TSBusinessAudioPlayer.swift */,
+				3DCD56F72DDAE481004AAB5B /* TSAudioPlayer.swift */,
+			);
+			path = TSAudioPlayer;
+			sourceTree = "<group>";
+		};
+		3DCD56FB2DDAFBD8004AAB5B /* ASDownloadManager */ = {
+			isa = PBXGroup;
+			children = (
+				3DCD56FC2DDAFBE4004AAB5B /* ASDownloadManager.swift */,
+			);
+			path = ASDownloadManager;
+			sourceTree = "<group>";
+		};
+		3DCD57032DDB1118004AAB5B /* TSPurchaseTool */ = {
+			isa = PBXGroup;
+			children = (
+				3DCD57042DDB111F004AAB5B /* TSPurchaseTool.swift */,
+			);
+			path = TSPurchaseTool;
+			sourceTree = "<group>";
+		};
+		3DCD570C2DDB1158004AAB5B /* libmp3 */ = {
+			isa = PBXGroup;
+			children = (
+				3DCD57082DDB1158004AAB5B /* ExtAudioConverter.h */,
+				3DCD57092DDB1158004AAB5B /* libmp3lame.a */,
+				3DCD570A2DDB1158004AAB5B /* ExtAudioConverter.m */,
+				3DCD570B2DDB1158004AAB5B /* lame.h */,
+			);
+			path = libmp3;
+			sourceTree = "<group>";
+		};
+		3DCD57162DDB1158004AAB5B /* ZHWaveform */ = {
+			isa = PBXGroup;
+			children = (
+				3DCD57112DDB1158004AAB5B /* ZHAudioProcessing.swift */,
+				3DCD57122DDB1158004AAB5B /* ZHWaveformViewDelegate.swift */,
+				3DCD57132DDB1158004AAB5B /* ZHTrackProcessing.swift */,
+				3DCD57142DDB1158004AAB5B /* ZHWaveformView.swift */,
+				3DCD57152DDB1158004AAB5B /* ZHCroppedDelegate.swift */,
+			);
+			path = ZHWaveform;
+			sourceTree = "<group>";
+		};
+		3DCD57172DDB1158004AAB5B /* TSBandRingTool */ = {
+			isa = PBXGroup;
+			children = (
+				3DCD57062DDB1158004AAB5B /* AudioConverter.h */,
+				3DCD57072DDB1158004AAB5B /* AudioConverter.m */,
+				3DCD570C2DDB1158004AAB5B /* libmp3 */,
+				3DCD570D2DDB1158004AAB5B /* AudioTool.swift */,
+				3DCD570E2DDB1158004AAB5B /* tutorial-ring.mp4 */,
+				3DCD570F2DDB1158004AAB5B /* TSBandRingTool.swift */,
+				3DCD57102DDB1158004AAB5B /* placeholder.band */,
+				3DCD57162DDB1158004AAB5B /* ZHWaveform */,
+			);
+			path = TSBandRingTool;
+			sourceTree = "<group>";
+		};
 		6B369F15FA74FED594C60569 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -135,6 +304,10 @@
 		A800FEAF2DDAC0E9009DABDC /* CommonView */ = {
 			isa = PBXGroup;
 			children = (
+				3DCD573A2DDB4E5E004AAB5B /* ASPageNullView.swift */,
+				3DCD572E2DDB1D87004AAB5B /* ASRingLoadingView.swift */,
+				3DCD56F42DDAE421004AAB5B /* ASViewTool.swift */,
+				3DCD56F22DDAE3DF004AAB5B /* ASRingToneCellView.swift */,
 				A800FEB02DDAC0F0009DABDC /* ASGeneratorView */,
 			);
 			path = CommonView;
@@ -155,6 +328,7 @@
 			children = (
 				A800FEBC2DDACCCF009DABDC /* ASRingGeneratorBaseVC.swift */,
 				A800FEBA2DDACAF2009DABDC /* ASRingGeneratorVC.swift */,
+				3DB4D4902DDC1F0C0082596A /* ASRingGeneratorVC+load.swift */,
 			);
 			path = ASRingGeneratorVC;
 			sourceTree = "<group>";
@@ -186,8 +360,8 @@
 				A848F8D32DD7198100B746EC /* Resources */,
 				A848F8B12DD6D80900B746EC /* APConfig */,
 				A848F88B2DD6D2C600B746EC /* AppPage */,
-				A848F88F2DD6D4E800B746EC /* Common */,
 				A848F8782DD6D1AF00B746EC /* AppDelegate.swift */,
+				3DCD572D2DDB1976004AAB5B /* AIPlayRingtones-Bridging-Header.h */,
 				A848F8792DD6D1AF00B746EC /* Assets.xcassets */,
 				A848F87A2DD6D1AF00B746EC /* Info.plist */,
 				A848F87C2DD6D1AF00B746EC /* LaunchScreen.storyboard */,
@@ -198,6 +372,7 @@
 		A848F88B2DD6D2C600B746EC /* AppPage */ = {
 			isa = PBXGroup;
 			children = (
+				3DB4D4A62DDC924B0082596A /* ASBusinessWebVC */,
 				A848F8B62DD6DF5500B746EC /* ASCommonView */,
 				A848F8AE2DD6D76F00B746EC /* ASTabBarVC */,
 				A848F8A72DD6D74300B746EC /* APSettingVC */,
@@ -206,6 +381,7 @@
 				A848F8A22DD6D65900B746EC /* APRingTonesVC */,
 				A848F88C2DD6D2F700B746EC /* APLaunchVC */,
 				A800FEB92DDACAE7009DABDC /* ASRingGeneratorVC */,
+				A848F88F2DD6D4E800B746EC /* Common */,
 			);
 			path = AppPage;
 			sourceTree = "<group>";
@@ -221,6 +397,12 @@
 		A848F88F2DD6D4E800B746EC /* Common */ = {
 			isa = PBXGroup;
 			children = (
+				3DCD57172DDB1158004AAB5B /* TSBandRingTool */,
+				3DCD57032DDB1118004AAB5B /* TSPurchaseTool */,
+				3DCD57002DDB1008004AAB5B /* CpuMapManager.swift */,
+				3DCD56FE2DDAFC17004AAB5B /* ASBusinessFileManager.swift */,
+				3DCD56FB2DDAFBD8004AAB5B /* ASDownloadManager */,
+				3DCD56F82DDAE481004AAB5B /* TSAudioPlayer */,
 				A848F8F92DD7536300B746EC /*  Notification+Ex.swift */,
 				A848F89D2DD6D59C00B746EC /* TSNetWork */,
 				A848F8922DD6D51900B746EC /* AIEnums.swift */,
@@ -252,7 +434,12 @@
 		A848F8A52DD6D73500B746EC /* APAudioToRingVC */ = {
 			isa = PBXGroup;
 			children = (
+				3DB4D4952DDC28C60082596A /* View */,
+				3DB4D4942DDC28AD0082596A /* VM */,
 				A848F8A82DD6D74900B746EC /* APAudioToRingVC.swift */,
+				3DB4D4962DDC28D10082596A /* APAudioToRingVC+View.swift */,
+				3DB4D4982DDC28DB0082596A /* APAudioToRingVC+StackView.swift */,
+				3DB4D49A2DDC28EC0082596A /* APAudioToRingVC+Upload.swift */,
 			);
 			path = APAudioToRingVC;
 			sourceTree = "<group>";
@@ -260,7 +447,8 @@
 		A848F8A62DD6D73E00B746EC /* APMyRingVC */ = {
 			isa = PBXGroup;
 			children = (
-				A848F8AA2DD6D75200B746EC /* APMyRingVC.swift */,
+				A848F8AA2DD6D75200B746EC /* ASMyRingVC.swift */,
+				3DCD573C2DDB5A2E004AAB5B /* ASMyRingCell.swift */,
 			);
 			path = APMyRingVC;
 			sourceTree = "<group>";
@@ -269,6 +457,7 @@
 			isa = PBXGroup;
 			children = (
 				A848F8AC2DD6D75800B746EC /* APSettingVC.swift */,
+				3DB4D4A42DDC8E7B0082596A /* APSettingVC+Col.swift */,
 			);
 			path = APSettingVC;
 			sourceTree = "<group>";
@@ -343,7 +532,12 @@
 		A848F8D32DD7198100B746EC /* Resources */ = {
 			isa = PBXGroup;
 			children = (
-				A848F8E02DD7271400B746EC /* ring_style.json */,
+				3DCD57362DDB3FFA004AAB5B /* DanceRingtoneExample.mp3 */,
+				3DCD57372DDB3FFA004AAB5B /* GentleRingtoneExample.mp3 */,
+				3DCD57322DDB38E7004AAB5B /* ringAnimation.gif */,
+				3DCD57332DDB38E7004AAB5B /* rotatingAnimation.gif */,
+				A848F8E02DD7271400B746EC /* ring_ttr_style.json */,
+				3DB4D4A02DDC2CC90082596A /* ring_rtr_style.json */,
 				A848F8D42DD719AB00B746EC /* ring_duration.json */,
 			);
 			path = Resources;
@@ -392,7 +586,8 @@
 			isa = PBXGroup;
 			children = (
 				A848F8F52DD752C400B746EC /* ASGenerateBaseOperation.swift */,
-				A848F8F72DD752D900B746EC /* ASGeneratePosterOperation.swift */,
+				A848F8F72DD752D900B746EC /* ASGenerateTextToRingOperation.swift */,
+				3DCD57302DDB2A5D004AAB5B /* ASGenerateRingToRingOperation.swift */,
 			);
 			path = Generate;
 			sourceTree = "<group>";
@@ -468,10 +663,17 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				3DCD57342DDB38E7004AAB5B /* ringAnimation.gif in Resources */,
+				3DCD57352DDB38E7004AAB5B /* rotatingAnimation.gif in Resources */,
 				A848F8822DD6D1AF00B746EC /* Assets.xcassets in Resources */,
 				A848F8D52DD719B600B746EC /* ring_duration.json in Resources */,
+				3DCD57222DDB1158004AAB5B /* tutorial-ring.mp4 in Resources */,
+				3DCD57232DDB1158004AAB5B /* placeholder.band in Resources */,
+				3DCD57382DDB3FFA004AAB5B /* DanceRingtoneExample.mp3 in Resources */,
+				3DCD57392DDB3FFA004AAB5B /* GentleRingtoneExample.mp3 in Resources */,
 				A848F8842DD6D1AF00B746EC /* LaunchScreen.storyboard in Resources */,
-				A848F8E12DD7271900B746EC /* ring_style.json in Resources */,
+				3DB4D4A12DDC2CCE0082596A /* ring_rtr_style.json in Resources */,
+				A848F8E12DD7271900B746EC /* ring_ttr_style.json in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -508,10 +710,14 @@
 			inputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-AIPlayRingtones/Pods-AIPlayRingtones-frameworks-${CONFIGURATION}-input-files.xcfilelist",
 			);
+			inputPaths = (
+			);
 			name = "[CP] Embed Pods Frameworks";
 			outputFileListPaths = (
 				"${PODS_ROOT}/Target Support Files/Pods-AIPlayRingtones/Pods-AIPlayRingtones-frameworks-${CONFIGURATION}-output-files.xcfilelist",
 			);
+			outputPaths = (
+			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AIPlayRingtones/Pods-AIPlayRingtones-frameworks.sh\"\n";
@@ -531,42 +737,72 @@
 				A848F8A42DD6D67000B746EC /* APRingTonesVC.swift in Sources */,
 				A848F8BD2DD6E38900B746EC /* ASLeftHeaderView.swift in Sources */,
 				A848F8D82DD71A3A00B746EC /* ASRingGenerateSecModel.swift in Sources */,
+				3DB4D4A32DDC34100082596A /* ASRTRFileView.swift in Sources */,
 				A848F8E82DD74DFD00B746EC /* ASDBHistoryManager.swift in Sources */,
 				A848F89E2DD6D59C00B746EC /* TSNetWork+Business.swift in Sources */,
-				A848F8AB2DD6D75300B746EC /* APMyRingVC.swift in Sources */,
+				A848F8AB2DD6D75300B746EC /* ASMyRingVC.swift in Sources */,
 				A848F89F2DD6D59C00B746EC /* TSNetworkManager.swift in Sources */,
 				A848F8E32DD7286A00B746EC /* ASGenerateStyleModel.swift in Sources */,
+				3DCD57052DDB1120004AAB5B /* TSPurchaseTool.swift in Sources */,
+				3DB4D4992DDC28E70082596A /* APAudioToRingVC+StackView.swift in Sources */,
 				A848F8A12DD6D59C00B746EC /* TSNetworkManager+Loading.swift in Sources */,
+				3DCD56F52DDAE42A004AAB5B /* ASViewTool.swift in Sources */,
+				3DB4D4972DDC28D40082596A /* APAudioToRingVC+View.swift in Sources */,
 				A800FEBD2DDACCD4009DABDC /* ASRingGeneratorBaseVC.swift in Sources */,
 				A800FEB62DDAC764009DABDC /* ASGeneratorErrorView.swift in Sources */,
+				3DB4D4A82DDC92560082596A /* ASBusinessWebVC.swift in Sources */,
 				A800FEB82DDAC826009DABDC /* TSNetWork+Error.swift in Sources */,
 				A848F8FA2DD7536700B746EC /*  Notification+Ex.swift in Sources */,
 				A848F8C02DD6E6FA00B746EC /* APRingTonesVC+TextView.swift in Sources */,
+				3DCD572F2DDB1D8A004AAB5B /* ASRingLoadingView.swift in Sources */,
+				3DB4D49D2DDC29AC0082596A /* ASRTRStyleView.swift in Sources */,
+				3DCD57312DDB2A66004AAB5B /* ASGenerateRingToRingOperation.swift in Sources */,
 				A848F8EA2DD74E3A00B746EC /* ASDBActionInfoModel.swift in Sources */,
+				3DCD573D2DDB5A3C004AAB5B /* ASMyRingCell.swift in Sources */,
 				A848F8B02DD6D77C00B746EC /* ASTabBarVC.swift in Sources */,
 				A848F8B32DD6D82300B746EC /* APConfig.swift in Sources */,
 				A848F8FC2DD753A000B746EC /* ASProgressState.swift in Sources */,
 				A848F8A92DD6D74A00B746EC /* APAudioToRingVC.swift in Sources */,
 				A848F8AD2DD6D75900B746EC /* APSettingVC.swift in Sources */,
 				A848F8912DD6D50000B746EC /* Common.swift in Sources */,
+				3DCD57192DDB1158004AAB5B /* AudioTool.swift in Sources */,
+				3DCD571A2DDB1158004AAB5B /* ExtAudioConverter.m in Sources */,
+				3DCD571B2DDB1158004AAB5B /* AudioConverter.m in Sources */,
+				3DB4D4932DDC25C10082596A /* APAudioToRingVM.swift in Sources */,
+				3DCD571C2DDB1158004AAB5B /* ZHCroppedDelegate.swift in Sources */,
+				3DCD571D2DDB1158004AAB5B /* ZHAudioProcessing.swift in Sources */,
+				3DCD571E2DDB1158004AAB5B /* ZHWaveformViewDelegate.swift in Sources */,
+				3DCD571F2DDB1158004AAB5B /* TSBandRingTool.swift in Sources */,
+				3DCD57202DDB1158004AAB5B /* ZHTrackProcessing.swift in Sources */,
+				3DCD57212DDB1158004AAB5B /* ZHWaveformView.swift in Sources */,
+				3DCD56F92DDAE481004AAB5B /* TSBusinessAudioPlayer.swift in Sources */,
+				3DCD56FA2DDAE481004AAB5B /* TSAudioPlayer.swift in Sources */,
 				A800FEBB2DDACAF3009DABDC /* ASRingGeneratorVC.swift in Sources */,
 				A848F8F32DD7528D00B746EC /* ASBaseOperation.swift in Sources */,
 				A848F8BB2DD6E30600B746EC /* APRingTonesVM.swift in Sources */,
+				3DB4D49B2DDC28F20082596A /* APAudioToRingVC+Upload.swift in Sources */,
+				3DCD56F32DDAE3E3004AAB5B /* ASRingToneCellView.swift in Sources */,
+				3DCD56FF2DDAFC1B004AAB5B /* ASBusinessFileManager.swift in Sources */,
 				A848F8C42DD6E70500B746EC /* APRingTonesVC+Style.swift in Sources */,
-				A848F8F82DD752E700B746EC /* ASGeneratePosterOperation.swift in Sources */,
+				A848F8F82DD752E700B746EC /* ASGenerateTextToRingOperation.swift in Sources */,
 				A800FEB42DDAC73E009DABDC /* ASGeneratorLoadingView.swift in Sources */,
 				A848F8EC2DD74EF800B746EC /* ASActionInfoModel.swift in Sources */,
 				A848F8F62DD752D700B746EC /* ASGenerateBaseOperation.swift in Sources */,
+				3DB4D4A52DDC8E830082596A /* APSettingVC+Col.swift in Sources */,
 				A848F8932DD6D52100B746EC /* AIEnums.swift in Sources */,
 				A848F8EE2DD7508300B746EC /* ASRealmManager.swift in Sources */,
 				A848F8B52DD6D83E00B746EC /* APConfig+Color.swift in Sources */,
 				A848F8B92DD6DF7900B746EC /* ASAppBtnView.swift in Sources */,
+				3DCD56FD2DDAFBE5004AAB5B /* ASDownloadManager.swift in Sources */,
+				3DCD573B2DDB4E61004AAB5B /* ASPageNullView.swift in Sources */,
 				A848F8F12DD7528800B746EC /* ASBaseOperationQueue.swift in Sources */,
 				A848F8CD2DD6EAD300B746EC /* ASPromptTextView.swift in Sources */,
+				3DCD57012DDB1008004AAB5B /* CpuMapManager.swift in Sources */,
 				A848F8DB2DD7231E00B746EC /* APRingStyleVC.swift in Sources */,
 				A848F8D22DD7149D00B746EC /* ASDurationColView.swift in Sources */,
 				A848F8C62DD6E72D00B746EC /* APRingTonesVC+View.swift in Sources */,
 				A848F8862DD6D1AF00B746EC /* AppDelegate.swift in Sources */,
+				3DB4D4912DDC1F100082596A /* ASRingGeneratorVC+load.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -594,20 +830,29 @@
 				CURRENT_PROJECT_VERSION = 1;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIPlayRingtones/Info.plist;
+				INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3",
+				);
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.tsts..AIPlayRingtones;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+				SUPPORTS_MACCATALYST = NO;
+				SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+				SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
 				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = "AIPlayRingtones/AIPlayRingtones-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
+				TARGETED_DEVICE_FAMILY = 1;
 			};
 			name = Debug;
 		};
@@ -621,20 +866,29 @@
 				CURRENT_PROJECT_VERSION = 1;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AIPlayRingtones/Info.plist;
+				INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
 				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
 				INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
-				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
 				);
+				LIBRARY_SEARCH_PATHS = (
+					"$(inherited)",
+					"$(PROJECT_DIR)/AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3",
+				);
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.tsts..AIPlayRingtones;
 				PRODUCT_NAME = "$(TARGET_NAME)";
+				SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
+				SUPPORTS_MACCATALYST = NO;
+				SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
+				SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
 				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_OBJC_BRIDGING_HEADER = "AIPlayRingtones/AIPlayRingtones-Bridging-Header.h";
 				SWIFT_VERSION = 5.0;
-				TARGETED_DEVICE_FAMILY = "1,2";
+				TARGETED_DEVICE_FAMILY = 1;
 			};
 			name = Release;
 		};

+ 9 - 0
AIPlayRingtones/AIPlayRingtones-Bridging-Header.h

@@ -0,0 +1,9 @@
+//
+//  AIPlayRingtones-Bridging-Header.h
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+#import "ExtAudioConverter.h"
+#import "AudioConverter.h"

+ 1 - 1
AIPlayRingtones/APConfig/APConfig+Color.swift

@@ -7,7 +7,7 @@
 
 extension UIColor {
     /// 背景色
-    static let mainBg = "#07080C".uiColor
+    static let mainBg = "#111018".uiColor
     
     /// 主色调
     static let themeColor = "#FECB34".uiColor

+ 25 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+StackView.swift

@@ -0,0 +1,25 @@
+//
+//  APAudioToRingVC+StackView.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+extension APAudioToRingVC {
+    
+    func creatCusStackView() -> TSCustomStackView {
+        let cusStackView = TSCustomStackView(axis: .vertical, spacing: 0)
+        cusStackView.scrollView.isScrollEnabled = true
+        return cusStackView
+    }
+
+    func setUpCusStackView() {
+        cusStackView.addSubviewToStack(ASLeftHeaderView.creatTitleView(title: "Audio Files".localized),length: kSectionTitleViewH)
+        cusStackView.addSubviewToStack(fileView)
+        cusStackView.addSubviewToStack(ASLeftHeaderView.creatTitleView(title: "Ringtone Genre".localized),length: kSectionTitleViewH)
+        cusStackView.addSubviewToStack(customTextView)
+        cusStackView.addSpacing(length: 16.0)
+        cusStackView.addSubviewToStack(ringStyleView)
+    }
+
+}

+ 98 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+Upload.swift

@@ -0,0 +1,98 @@
+//
+//  APAudioToRingVC+Style.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+extension APAudioToRingVC {
+ 
+    func creatFileView() -> ASRTRFileView {
+        let fileView = ASRTRFileView { [weak self] in
+            guard let self = self else { return }
+            selectAudioFile()
+        } clickPlayComplete: { [weak self] in
+            guard let self = self else { return }
+            clickPlay()
+        }
+        return fileView
+    }
+    
+    
+    func clickPlay() {
+        if TSBusinessAudioPlayer.shared.isLoading{
+            return
+        }
+        if TSBusinessAudioPlayer.shared.isPlaying{
+            TSBusinessAudioPlayer.shared.stop()
+        }else{
+            TSBusinessAudioPlayer.shared.playUrlString("",localURL:viewModel.ringFilePath,indexPath: nil)
+        }
+    }
+}
+
+
+extension APAudioToRingVC : UIDocumentPickerDelegate {
+
+  @objc func selectAudioFile() {
+      if viewModel.ringFilePath == nil {
+          if let url = Bundle.main.url(forResource: "DanceRingtoneExample", withExtension: "mp3") {
+              viewModel.ringFilePath = url
+              fileView.filePath = url
+          }
+      }else{
+          viewModel.ringFilePath = nil
+          fileView.filePath = nil
+      }
+      
+      return
+      let documentTypes = ["public.mp3"]
+      // 音频 mp3,wav,m4a
+      // .MP3; .AAC; .WAV; .WMA; .CDA; .FLAC; .M4A; .MID; .MKA; .MP2; .MPA; .MPC; .APE; .OFR; .OGG; .RA; .WV; .TTA; .AC3; .DTS
+      // 视频 mp4,avi, wmv,mov,mpg(mpeg)
+      
+      // 1. 创建文件选择器
+      let documentPicker = UIDocumentPickerViewController(
+          documentTypes: documentTypes,//[kUTTypeAudio as String], // 限定音频类型
+          in: .import//.open // 打开模式(只读)
+      )
+      documentPicker.delegate = self
+      documentPicker.modalPresentationStyle = .fullScreen
+      documentPicker.allowsMultipleSelection = false // 禁止多选
+      
+      // 2. 弹出文件选择器
+      present(documentPicker, animated: true, completion: nil)
+  }
+    
+    // 用户选中文件后回调
+    func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
+        guard let selectedFileURL = urls.first else { return }
+        
+        // 3. 处理选中的音频文件
+        print("选中的音频文件路径:", selectedFileURL.path)
+        
+        // 示例:读取文件数据(需处理权限)
+        if selectedFileURL.startAccessingSecurityScopedResource() {
+            defer { selectedFileURL.stopAccessingSecurityScopedResource() }
+            
+            do {
+                dePrint("selectedFileURL=\(selectedFileURL)")
+                let fileData = try Data(contentsOf: selectedFileURL)
+                print("文件大小:", fileData.count, "字节")
+                let cacheDirectory = TSFileManagerTool.cacheDirectory.appendingPathComponent(selectedFileURL.lastPathComponent)
+                TSFileManagerTool.copyFileWithOverwrite(from: selectedFileURL, to: cacheDirectory)
+                
+                viewModel.ringFilePath = cacheDirectory
+            } catch {
+                print("读取文件失败:", error.localizedDescription)
+            }
+        }
+    }
+
+    // 用户取消选择时回调
+    func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
+        print("用户取消了选择")
+    }
+
+}
+

+ 91 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC+View.swift

@@ -0,0 +1,91 @@
+//
+//  APAudioToRingVC+View.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+extension APAudioToRingVC {
+    
+//    func creatVipBtn()->UIButton{
+//        let vipBtn = UIButton.createButton(image: UIImage(named: "nav_vip")) { [weak self] in
+//            guard let self = self else { return }
+//            TSPurchaseVC.show(target: self) {}
+//        }
+//        return vipBtn
+//    }
+    
+    func creatNavBarView()->TSBaseNavContentBarView{
+        let navBarView = TSBaseNavContentBarView()
+
+        let titleImageView = UIImageView.createImageView(imageName: "nav_title_aiRingtone", contentMode: .scaleToFill)
+        navBarView.barView.addSubview(titleImageView)
+        titleImageView.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+
+//        navBarView.barView.addSubview(vipBtn)
+//        vipBtn.snp.makeConstraints { make in
+//            make.centerY.equalToSuperview()
+//            make.trailing.equalTo(-16) // (-60)
+//            make.width.height.equalTo(24)
+//        }
+
+        return navBarView
+    }
+    
+}
+
+extension APAudioToRingVC {
+    
+    func createRTRStyleView() -> ASRTRStyleView{
+        let rtrStyleView = ASRTRStyleView()
+        rtrStyleView.generateStyleIndex = viewModel.generateStyleIndex
+        rtrStyleView.generateStyleModels = viewModel.generateStyleModels
+        rtrStyleView.selectedCompleted = { [weak self] model,index in
+            guard let self = self else { return }
+            viewModel.selectedGenerateModel = model
+        }
+        return rtrStyleView
+    }
+    
+    func creatCreatBtnView() -> ASAppBtnView{
+        let creatBtnView = ASAppBtnView()
+        creatBtnView.setUpButton(style: .generate) { [weak self] in
+            guard let self = self else { return }
+            generateAI()
+        }
+        creatBtnView.setBtnEnabled(isEnabled: false)
+//        creatBtnView.isIconVipBlock = { [weak self] in
+//            guard let self = self else { return false }
+//            var showVip = kPurchaseDefault.generateVipShow(type: .picToPic)
+//            if showVip == false {
+//                showVip = self.viewModel.selectedPTPStyleModel.isVip
+//            }
+//            return showVip
+//        }
+//        creatBtnView.isClickVipBlock = { [weak self] in
+//            guard let self = self else { return false }
+//            var isVip = kPurchaseDefault.freeNumAvailable(type: .picToPic) == false
+//            if viewModel.selectedPTPStyleModel.isVip == true {
+//                isVip = true
+//            }
+//            return isVip
+//        }
+        return creatBtnView
+    }
+    
+}
+
+extension APAudioToRingVC {
+ 
+    func creatCustomTextView() -> ASPromptTextView {
+        
+        let promptTextView = ASPromptTextView(randomTextArray: kRandomTextToRintone) { [weak self] text in
+            guard let self = self else { return }
+            viewModel.promptText = text
+        }
+        return promptTextView
+    }
+    
+}

+ 92 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/APAudioToRingVC.swift

@@ -5,6 +5,98 @@
 //  Created by 100Years on 2025/5/15.
 //
 
+
+import MobileCoreServices // 用于定义文件类型
 class APAudioToRingVC: TSBaseVC {
+    lazy var navBarView: TSBaseNavContentBarView = {
+        let navBarView = TSBaseNavContentBarView()
+
+        let titleImageView = UIImageView.createImageView(imageName: "nav_title_audioRingtone", contentMode: .scaleToFill)
+        navBarView.barView.addSubview(titleImageView)
+        titleImageView.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+        return navBarView
+    }()
+    
+    lazy var viewModel: APAudioToRingVM = {
+        let viewModel = APAudioToRingVM()
+        return viewModel
+    }()
+    
+
+    //    lazy var vipBtn: UIButton = creatVipBtn()
+    lazy var cusStackView: TSCustomStackView = creatCusStackView()
+    lazy var fileView: ASRTRFileView = creatFileView()
+    lazy var customTextView: ASPromptTextView = creatCustomTextView()
+    lazy var ringStyleView: ASRTRStyleView = createRTRStyleView()
+    lazy var creatBtnView: ASAppBtnView = creatCreatBtnView()
+    
+    override func createView() {
+        
+        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(clickView))
+        tapGesture.cancelsTouchesInView = false
+        view.addGestureRecognizer(tapGesture)
+
+        navBarContentView.addSubview(navBarView)
+        navBarView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+
+        contentView.addSubview(cusStackView)
+        cusStackView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+
+        contentView.addSubview(creatBtnView)
+        creatBtnView.snp.makeConstraints { make in
+            make.centerX.equalToSuperview()
+            make.bottom.equalTo(-16)
+            make.size.equalTo(creatBtnView.btnSize)
+        }
+
+        setUpCusStackView()
+        
+    }
     
+    override func dealThings() {
+        viewModel.$isCanGennerate.receive(on: DispatchQueue.main).sink { [weak self] enble in
+            guard let self = self else { return }
+            creatBtnView.setBtnEnabled(isEnabled: enble)
+        }.store(in: &cancellable)
+    }
 }
+
+extension APAudioToRingVC {
+    @objc func clickView() {
+        view.endEditing(true)
+    }
+    
+    
+    func generateAI() {
+        view.endEditing(true)
+        
+        let gennerateVC = ASRingGeneratorVC(generateStyleModel: viewModel.generateStyleModel) { [weak self] _ in
+            guard let self = self else { return }
+//            updateVipView()
+        }
+
+        gennerateVC.reloadViewBlock = { [weak self] in
+            guard let self = self else { return }
+//            updataCollectionView()
+        }
+        
+        gennerateVC.closePageComplete = {
+            [weak self] in
+            guard let self = self else { return }
+//            updataCollectionView()
+        }
+
+        kPresentModalVC(target: self, modelVC: gennerateVC, transitionStyle: .crossDissolve)
+
+      
+    }
+    
+}
+
+

+ 58 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/VM/APAudioToRingVM.swift

@@ -0,0 +1,58 @@
+//
+//  APAudioToRingVM.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+import Combine
+import ObjectMapper
+
+class APAudioToRingVM {
+    private var cancellables = Set<AnyCancellable>()
+    //输入框内容
+    @Published var promptText:String = ""
+    
+    @Published var ringFilePath:URL?
+    
+    //选择生成类类型
+    var generateStyleIndex:Int = 0
+    @Published var selectedGenerateModel:ASGenerateStyleModel?
+    lazy var generateStyleModels: [ASGenerateStyleModel] = {
+        var ptpStyleModels = [ASGenerateStyleModel]()
+        if let dataArray = Mapper<ASGenerateStyleModel>().mapArray(JSONfile: "ring_rtr_style.json"){
+            ptpStyleModels = dataArray
+            
+            if let model = dataArray.safeObj(At: generateStyleIndex) {
+                selectedGenerateModel = model //加上默认的选择
+            }
+        }
+        
+        return ptpStyleModels
+    }()
+    
+    
+    @Published private(set) var isCanGennerate: Bool = false
+    init(){
+        
+       
+        Publishers.CombineLatest3($promptText, $ringFilePath,$selectedGenerateModel)
+              .map { promptText, ringFilePath,generateStyleModel in
+                  // 当两者长度都 > 0 时返回 true
+                  return !promptText.isEmpty && ringFilePath != nil && generateStyleModel != nil
+              }
+              .assign(to: \.isCanGennerate, on: self)
+              .store(in: &cancellables)
+    }
+
+    
+    //用户生成图片的TSGenerateStyleModel
+    var generateStyleModel:ASGenerateStyleModel{
+        let generateStyleModel = selectedGenerateModel!
+        generateStyleModel.inputText = promptText
+        generateStyleModel.duration = 10
+        generateStyleModel.upLoadFilePath = ringFilePath
+        generateStyleModel.generateType = .ringToRing
+        return generateStyleModel
+    }
+}

+ 190 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRFileView.swift

@@ -0,0 +1,190 @@
+//
+//  ASRTRFileView.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+
+
+
+class ASRTRFileUploadView: TSBaseView {
+    
+    var clickComplete:(()->Void)?
+    var clickPlayComplete:(()->Void)?
+    lazy var imageView: UIImageView = {
+        let imageView = UIImageView.createImageView(image: .uploadFileIcon)
+        return imageView
+    }()
+    
+    lazy var textLab: UILabel = {
+        let textLab = UILabel.createLabel(text: "Upload audio files to generate new ringtones".localized ,font: .font(size:14,weight: .regular),textColor: .white,textAlignment: .left)
+        return textLab
+    }()
+    
+    lazy var btn: UIButton = {
+        let imageView = UIButton.createButton(image: .uploadFileAdd){ [weak self]  in
+            guard let self = self else { return }
+            clickComplete?()
+        }
+        return imageView
+    }()
+    
+    override func creatUI() {
+  
+        contentView.addSubview(imageView)
+        imageView.snp.makeConstraints { make in
+            make.leading.equalTo(12)
+            make.centerY.equalToSuperview()
+            make.width.equalTo(80)
+            make.height.equalTo(60)
+        }
+        
+        contentView.addSubview(btn)
+        btn.snp.makeConstraints { make in
+            make.trailing.equalTo(-12)
+            make.centerY.equalToSuperview()
+            make.width.equalTo(40)
+            make.height.equalTo(40)
+        }
+        
+        contentView.addSubview(textLab)
+        textLab.snp.makeConstraints { make in
+            make.leading.equalTo(imageView.snp.trailing).offset(12)
+            make.trailing.equalTo(btn.snp.leading).offset(-12)
+            make.centerY.equalToSuperview()
+        }
+    }
+}
+
+
+class ASRTRFileplayView: TSBaseView {
+    
+    var clickComplete:(()->Void)?
+    var clickPlayComplete:(()->Void)?
+
+    lazy var ringView: ASRingToneCellView = {
+        let ringToneView = ASRingToneCellView()
+        ringToneView.cornerRadius = 0.0
+        ringToneView.setRingBtn.isHidden = true
+        ringToneView.editBtn.isHidden = true
+        ringToneView.clickPlayHandel = { [weak self] isplay in
+            guard let self = self else { return }
+            clickPlayComplete?()
+        }
+        ringToneView.rightShade.isHidden = true
+        ringToneView.bgImageView.isHidden = true
+        ringToneView.selectedBoardImageView.isHidden = true
+        ringToneView.timeLab.textColor = .white.withAlphaComponent(0.8)
+        ringToneView.nameLab.snp.updateConstraints { make in
+            make.top.equalTo(20)
+        }
+        ringToneView.timeLab.snp.updateConstraints { make in
+            make.bottom.equalTo(-20)
+        }
+        
+        return ringToneView
+    }()
+    
+    lazy var btn: UIButton = {
+        let imageView = UIButton.createButton(image: .uploadFileChange){ [weak self]  in
+            guard let self = self else { return }
+            clickComplete?()
+        }
+        return imageView
+    }()
+    
+    override func creatUI() {
+        contentView.addSubview(ringView)
+        ringView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        contentView.addSubview(btn)
+        btn.snp.makeConstraints { make in
+            make.trailing.equalTo(-12)
+            make.centerY.equalToSuperview()
+            make.width.equalTo(40)
+            make.height.equalTo(40)
+        }
+        
+    }
+    
+    override func dealThings() {
+        ringView.monitorPlayStateDefaultHandle()
+    }
+
+}
+
+class ASRTRFileView: TSBaseView {
+    
+    var clickUpFileComplete:(()->Void)
+    var clickPlayComplete:(()->Void)
+    
+    
+    init(clickUpFileComplete: @escaping () -> Void, clickPlayComplete: @escaping () -> Void, filePath: URL? = nil) {
+        self.clickUpFileComplete = clickUpFileComplete
+        self.clickPlayComplete = clickPlayComplete
+        self.filePath = filePath
+        super.init(frame: .zero)
+    }
+    
+    @MainActor required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    
+    var filePath:URL?{
+        didSet{
+            playView.isHidden = filePath == nil ? true : false
+            uploadView.isHidden = !playView.isHidden
+            
+            if let filePath = filePath {
+                if let info = TSBusinessAudioPlayer.getAudioFileInfo(path: filePath.path()){
+                    playView.ringView.nameLab.text = info.songName
+                    playView.ringView.timeLab.text = Float(info.durationInSeconds ?? 0).floatToMinuteSecond()
+                }
+            }
+        }
+    }
+    lazy var bgImageView: UIImageView = {
+        let bgImageView = UIImageView.createImageView(image: .textViewBg,contentMode: .scaleToFill)
+        return bgImageView
+    }()
+    
+    lazy var uploadView: ASRTRFileUploadView = {
+        let uploadView = ASRTRFileUploadView()
+        uploadView.clickComplete = clickUpFileComplete
+        return uploadView
+    }()
+    
+    lazy var playView: ASRTRFileplayView = {
+        let playView = ASRTRFileplayView()
+        playView.isHidden = true
+        playView.clickComplete = clickUpFileComplete
+        playView.clickPlayComplete = clickPlayComplete
+        return playView
+    }()
+    
+    override func creatUI() {
+        contentView.snp.remakeConstraints { make in
+            make.height.equalTo(84)
+            make.edges.equalTo(UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16))
+        }
+        contentView.addSubview(bgImageView)
+        contentView.addSubview(playView)
+        contentView.addSubview(uploadView)
+        
+        bgImageView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        playView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        uploadView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+    }
+}

+ 176 - 0
AIPlayRingtones/AppPage/APAudioToRingVC/View/ASRTRStyleView.swift

@@ -0,0 +1,176 @@
+//
+//  ASRTRStyleView.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+class ASRTRStyleView: TSBaseView {
+    
+    var selectedCompleted:((ASGenerateStyleModel,Int)->Void)?
+
+    //选择生成类类型组
+    var generateStyleIndex:Int = 0{
+        didSet{
+            if generateStyleModels.count <= 0 { return }
+            DispatchQueue.main.async {
+                self.colView.collectionView.selectItem(at: IndexPath(item: self.generateStyleIndex, section: 0), animated: true, scrollPosition: .centeredVertically)
+            }
+        }
+    }
+    
+    var generateStyleModels:[ASGenerateStyleModel] = []
+    {
+        didSet{
+            colView.reload(with: [TSSimpleSectionData(items: generateStyleModels)])
+            self.generateStyleIndex = abs(generateStyleIndex)
+        }
+    }
+    var generateStyleModel:ASGenerateStyleModel?{
+        didSet{
+            if let generateStyleModel = generateStyleModel {
+                selectedCompleted?(generateStyleModel,generateStyleIndex)
+            }
+        }
+    }
+
+    private var collectionViewObserver: TSCollectionViewObserver!
+    lazy var colView: TSSimpleCollectionView = {
+        let identifier = "ASRTRStyleViewCell"
+
+        let layout = UICollectionViewFlowLayout()
+        let cp = TSSimpleCollectionView()
+        cp.layout.minimumLineSpacing = 16
+        cp.layout.minimumInteritemSpacing = 8
+        cp.layout.scrollDirection = .vertical
+        cp.delegate = self
+        let contentInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
+        cp.collectionView.contentInset = contentInset
+        cp.layout.itemSize = kGetCollectionViewCellSize(sectionInset: contentInset, itemSpacing: 16, originalSize: CGSize(width: 80, height: 104), cellRowNum: 4)
+        cp.registerCell(ASRTRStyleViewCell.self,identifier:identifier)
+        cp.cellIdentifierForItem = { data in
+            return identifier
+        }
+
+        return cp
+    }()
+    
+    override func creatUI() {
+        contentView.addSubview(colView)
+        colView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+            make.height.equalTo(0)
+        }
+    }
+
+    override func dealThings() {
+
+        // 监听collectionView 的 contentSize
+        collectionViewObserver = TSCollectionViewObserver(collectionView: colView.collectionView)
+        collectionViewObserver.onContentSizeChange = { [weak self] size in
+            guard let self = self else { return }
+            print("collectionViewObserver 内容大小变化: \(size)")
+            self.colView.snp.updateConstraints { make in
+                make.height.equalTo(size.height)
+            }
+        }
+    }
+}
+
+extension ASRTRStyleView: TSSimpleCollectionViewDelegate {
+    
+    func collectionView(didTrigger event: TSSmalCoacopods.TSSimpleCellEvent) {
+        switch event.action {
+        case .tap:
+            generateStyleIndex = event.indexPath.row
+            if let model = generateStyleModels.safeObj(At: generateStyleIndex) {
+                generateStyleModel = model
+            }
+        default:
+            break
+        }
+    }
+    
+}
+
+
+class ASRTRStyleViewCell: TSBaseCollectionCell ,TSSimpleConfigurableView {
+    
+    weak var delegate: (any TSSmalCoacopods.TSSimpleCollectionViewDelegate)?
+    var indexPath: IndexPath = IndexPath(item: 0, section: 0)
+    var data: Any? {
+        didSet {
+            if let model = data as? ASGenerateStyleModel {
+                proImageView.isHidden = !model.vip
+                textLab.text = model.imageText.localized
+                imageView.image = UIImage(named: model.imageName)
+            }
+        }
+    }
+    
+    override var isSelected: Bool{
+        didSet{
+            textLab.textColor = .white.withAlphaComponent( isSelected ? 1.0 : 0.7)
+            boardImageView.isHidden = !isSelected
+        }
+    }
+
+    lazy var boardImageView: UIImageView = {
+        let boardImageView = UIImageView.createImageView(image: .ringTextSelectedBoard)
+        boardImageView.isHidden = true
+        return boardImageView
+    }()
+
+    lazy var imageView: UIImageView = {
+        let imageView = UIImageView()
+        imageView.cornerRadius = 12
+        return imageView
+    }()
+    
+    lazy var proImageView:UIImageView = {
+        let proImageView = UIImageView.createImageView(image: .PRO)
+        return proImageView
+    }()
+    
+
+    lazy var textLab: UILabel = {
+        let textLab = UILabel.createLabel(font: .font(size:14,weight: .regular),textColor: .white.withAlphaComponent(0.6),textAlignment: .center)
+        return textLab
+    }()
+    
+    
+    override func creatUI() {
+        
+        contentView.addSubview(boardImageView)
+        boardImageView.snp.makeConstraints { make in
+            make.width.height.equalTo(72.0*kDesignScale)
+            make.top.equalTo(0)
+            make.centerX.equalToSuperview()
+        }
+    
+        contentView.addSubview(imageView)
+        imageView.snp.makeConstraints { make in
+            make.width.height.equalTo(64.0*kDesignScale)
+            make.top.equalTo(4)
+            make.centerX.equalToSuperview()
+        }
+        
+
+        contentView.addSubview(textLab)
+        textLab.snp.makeConstraints { make in
+            make.top.equalTo(boardImageView.snp.bottom)
+            make.leading.trailing.equalTo(0)
+            make.bottom.equalTo(0)
+        }
+        
+        imageView.addSubview(proImageView)
+        proImageView.snp.makeConstraints { make in
+            make.top.equalTo(6)
+            make.trailing.equalTo(-8)
+            make.width.equalTo(21)
+            make.height.equalTo(10)
+        }
+ 
+
+    }
+}

+ 271 - 0
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingCell.swift

@@ -0,0 +1,271 @@
+//
+//  ASMyRingCell.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+import Combine
+import SwipeCellKit
+class ASMyRingCell: SwipeCollectionViewCell  {
+
+    weak var targetVC:UIViewController?
+    var indexPath:IndexPath = IndexPath(item: 0, section: 0)
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+        creatUI()
+        dealThings()
+    }
+    
+    required public init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    static let cellID = "ASMyRingCell"
+
+    lazy var ringView: ASRingToneCellView = {
+        let ringToneView = ASRingToneCellView()
+        ringToneView.cornerRadius = 0.0
+        ringToneView.setRingBtn.isHidden = false
+        ringToneView.editBtn.isHidden = true
+        ringToneView.clickPlayHandel = { [weak self] isplay in
+            guard let self = self else { return }
+            clickPlay()
+        }
+        
+//        ringToneView.clickEditHandel = { [weak self] in
+//            guard let self = self else { return }
+//            clickEidtBtn()
+//        }
+        
+        ringToneView.clickSetUpHandel = { [weak self] in
+            guard let self = self else { return }
+            clickSetRingBtn()
+      
+        }
+        return ringToneView
+    }()
+    
+    lazy var generateView: TSRingToneGenerateView = {
+        let generateView = TSRingToneGenerateView()
+        generateView.isHidden = true
+        generateView.refreshHandel = { [weak self]  in
+            guard let self = self else { return }
+            guard let oldModel = model else { return }
+//            if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones){ return }//判断 vip
+//            TSGenerateRintoneOperationQueue.shared.creatOperation(uuid: oldModel.uuid).creatRintone(oldModel: oldModel, prompt: oldModel.request.prompt, promptSort: oldModel.request.promptSort)
+        }
+        return generateView
+    }()
+    
+    
+    lazy var exampleView: UIView = {
+        let exampleView = UIView()
+        exampleView.backgroundColor = "#7E57F4".uiColor
+        
+        let textLabel = UILabel.createLabel(
+            text: "Example".localized,
+            font: .font(size: 12),
+            textColor: .white
+        )
+        
+        exampleView.addSubview(textLabel)
+        textLabel.snp.makeConstraints { make in
+            make.top.edges.equalTo(UIEdgeInsets(top: 4, left: 6, bottom: 4, right: 6))
+        }
+        
+        kDelayMainShort {
+            exampleView.makeCorner([.topLeft,.bottomLeft], radius: 10)
+        }
+        return exampleView
+    }()
+    
+    
+    lazy var vipView: UIImageView = {
+        let vipView = UIImageView.createImageView(imageName: "ring_vip")
+        vipView.isHidden = true
+        return vipView
+    }()
+    
+    var model:ASActionInfoModel?{
+        didSet{
+            modelDidSet()
+        }
+    }
+
+    func creatUI() {
+        cornerRadius = 16.0
+        backgroundColor = .cardColor
+        
+        contentView.addSubview(ringView)
+        ringView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+    
+        contentView.addSubview(vipView)
+        vipView.snp.makeConstraints { make in
+            make.top.trailing.equalTo(0)
+            make.width.height.equalTo(24)
+        }
+        
+        contentView.addSubview(exampleView)
+        exampleView.snp.makeConstraints { make in
+            make.trailing.equalToSuperview()
+            make.top.equalTo(0)
+            make.height.equalTo(20)
+        }
+  
+        contentView.addSubview(generateView)
+        generateView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+    }
+    
+    func setTargetVC(targetVC:UIViewController?,indexPath:IndexPath) {
+        self.targetVC = targetVC
+        self.indexPath = indexPath
+        
+        if let vc = targetVC as? any SwipeCollectionViewCellDelegate {
+          self.delegate = vc
+        }
+    }
+    
+    func dealThings(){
+        
+    }
+    
+}
+
+
+extension ASMyRingCell {
+    
+    func modelDidSet(){
+        guard let model = model else { return }
+        if let rintoneOperation = ASGenerateTextToRingOperationQueue.shared.findOperation(uuid: model.uuid) as? ASGenerateTextToRingOperation {
+            rintoneOperation.currentActionInfoModelChanged = { [weak self] actionInfoModel in
+                guard let self = self else { return }
+                DispatchQueue.main.async {
+                    self.updataActionInfoModelView(model: actionInfoModel)
+                }
+            }
+        }
+
+        updataActionInfoModelView(model: model)
+        dePrint("model actionStatus 收到=\(model.actionStatus)")
+        
+        if playSelf{
+            setPlayerStateChangedHandle()
+        }else{
+            changePlayerState(state: .stop)
+        }
+    }
+
+    func setPlayerStateChangedHandle(){
+        
+        TSBusinessAudioPlayer.shared.stateChangedHandle = { [weak self] playerState in
+            guard let self = self else { return }
+            self.changePlayerState(state: playerState)
+        }
+        self.changePlayerState(state: TSBusinessAudioPlayer.shared.currentPlayerState)
+    }
+    
+}
+extension ASMyRingCell {
+    
+    
+}
+
+extension ASMyRingCell {
+    func clickPlay() {
+        if playSelf{
+            if TSBusinessAudioPlayer.shared.isLoading{
+                return
+            }
+            if TSBusinessAudioPlayer.shared.isPlaying{
+                TSBusinessAudioPlayer.shared.stop()
+            }else{
+                TSBusinessAudioPlayer.shared.playUrlString(modelUrlString,localURL: modelLocalURL,indexPath: indexPath)
+            }
+            
+        }else{
+            TSBusinessAudioPlayer.shared.stop()//让上一个对象停止播放
+            setPlayerStateChangedHandle()//更换监听
+            TSBusinessAudioPlayer.shared.playUrlString(modelUrlString,localURL: modelLocalURL,indexPath: indexPath)
+        }
+    }
+    
+
+    func changePlayerState(state:TSBusinessAudioPlayer.PlayerState){
+        ringView.handelAudioPlayerStateChange(state: state)
+    }
+    
+    
+    func updataActionInfoModelView(model:ASActionInfoModel){
+        
+        if model.modelType == .example {
+            model.actionStatus = .success
+        }
+        
+        switch model.actionStatus {
+        case .pending,.running:
+            generateView.isHidden = false
+            generateView.setProgress(progress: model.percent)
+        case .success:
+            generateView.isHidden = true
+            
+            ringView.timeLab.text = Float(model.response.duration).floatToMinuteSecond()
+            ringView.nameLab.text = model.response.title
+            ringView.setCoverImageView(urlString: model.response.coverUrl)
+            exampleView.isHidden = model.modelType != .example
+            vipView.isHidden = true
+            
+            self.changePlayerState(state: TSBusinessAudioPlayer.shared.currentPlayerState)
+            
+        case .failed:
+            generateView.isHidden = false
+            generateView.setFail()
+        }
+    }
+
+    var playSelf:Bool{
+        return TSBusinessAudioPlayer.shared.isPlayURLString(string: modelUrlString,localURL: modelLocalURL,indexPath: indexPath)
+    }
+
+    var modelUrlString:String{
+        var urlString:String = ""
+        if let model = model{
+            urlString = model.response.musicUrl
+        }
+        return urlString
+    }
+
+    var modelLocalURL:URL?{
+        return model?.localURL
+    }
+    
+}
+//点击编辑和设置按钮
+extension ASMyRingCell {
+    
+    @objc func clickSetRingBtn(){
+        if let model = model {
+            setShareBand(infoModel: model)
+        }
+    
+        TSBusinessAudioPlayer.shared.stop()
+    }
+    
+    func setShareBand(infoModel:ASActionInfoModel){
+        guard let targetVC = targetVC else { return }
+        let needVip = infoModel.response.vip
+        let urlString = infoModel.response.musicUrl
+        let fileName = infoModel.response.title
+
+        ASDownloadManager.getDownLoadRing(urlString: urlString){ url,downLoad in
+            if let path = url {
+                _ = kshareBand(needVip: needVip, vc: targetVC, fileURL: path, fileName: fileName)
+            }
+        }
+    }
+}

+ 184 - 0
AIPlayRingtones/AppPage/APMyRingVC/ASMyRingVC.swift

@@ -0,0 +1,184 @@
+//
+//  APMyRingVC.swift
+//  AIPlayRingtones
+//
+//  Created by 100Years on 2025/5/15.
+//
+import SwipeCellKit
+class APMyRingVC: TSBaseVC {
+    
+    var listModelArray: [ASActionInfoModel] = []
+    var dataChangedBlock:(()->Void)?
+    
+    lazy var navBarView: TSBaseNavContentBarView = {
+        let navBarView = TSBaseNavContentBarView()
+
+        let titleImageView = UIImageView.createImageView(imageName: "nav_title_myRingtones", contentMode: .scaleToFill)
+        navBarView.barView.addSubview(titleImageView)
+        titleImageView.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+        return navBarView
+    }()
+    
+    lazy var layout: UICollectionViewFlowLayout = {
+        let layout = UICollectionViewFlowLayout()
+        layout.scrollDirection = .vertical
+        layout.itemSize = CGSize(width: k_ScreenWidth-32, height: 74)
+        layout.minimumInteritemSpacing = 10.0
+        layout.minimumLineSpacing = 18.0
+        return layout
+    }()
+    
+    lazy var collectionView: UICollectionView = {
+        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+        collectionView.delegate = self
+        collectionView.dataSource = self
+        collectionView.showsVerticalScrollIndicator = false
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.backgroundColor = .clear
+        collectionView.contentInset = UIEdgeInsets(top: 16, left: 0, bottom: 16, right: 0)
+        collectionView.register(ASMyRingCell.self, forCellWithReuseIdentifier: ASMyRingCell.cellID)
+        if #available(iOS 11.0, *) {
+            collectionView.contentInsetAdjustmentBehavior = .never
+        }
+        return collectionView
+    }()
+    
+    
+    lazy var pageNullView: ASPageNullView = {
+        let pageNullView = ASPageNullView()
+        pageNullView.isHidden = true
+        return pageNullView
+    }()
+    
+    
+    override func createView() {
+        
+        navBarContentView.addSubview(navBarView)
+        navBarView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        contentView.addSubview(collectionView)
+        collectionView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+    }
+    
+    override func viewWillAppear(_ animated: Bool) {
+        super.viewWillAppear(animated)
+    }
+    
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        TSBusinessAudioPlayer.shared.stop()
+    }
+    
+    override func dealThings() {
+        updateListView()
+        
+        NotificationCenter.default.addObserver(forName: .kGenerateRingOperationChanged, object: nil, queue: nil) {[weak self] notification in
+            guard let self = self else { return }
+            if let userInfo = notification.userInfo as? [String: Any],let state = userInfo["state"] as? ASProgressState {
+                switch state {
+                case .start, .success(_),.failed(_),.none:
+                    self.updateListView()
+                default:break
+                }
+            }
+        }
+    }
+    
+    func updateListView(){
+        dbHistory.getModelList { [weak self] array in
+            guard let self = self else { return }
+            listModelArray = array
+            updateView()
+        }
+    }
+    
+    func updateView() {
+        collectionView.reloadData()
+        pageNullView.isHidden = listModelArray.count > 0
+    }
+}
+
+
+extension APMyRingVC: UICollectionViewDataSource ,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {
+    
+    public func numberOfSections(in collectionView: UICollectionView) -> Int {
+        return 1
+    }
+    
+    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        return listModelArray.count
+    }
+    
+    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ASMyRingCell.cellID, for: indexPath) as! ASMyRingCell
+        if let model = listModelArray.safeObj(At: indexPath.item){
+            cell.setTargetVC(targetVC: self, indexPath: indexPath)
+            cell.model = model
+        }
+        return cell
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        
+    }
+    
+}
+
+extension APMyRingVC{
+    
+    var dbHistory:ASDBHistory{
+        return ASRMShared.ringDBHistory
+    }
+}
+
+extension APMyRingVC: SwipeCollectionViewCellDelegate {
+    
+    func collectionView(_ collectionView: UICollectionView, editActionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
+        guard orientation == .right else { return nil }
+        
+        if indexPath.section != 0 {
+            return nil
+        }
+        
+
+        if let model = listModelArray.safeObj(At: indexPath.item) {
+            switch model.actionStatus {
+            case .pending,.running:
+                return nil
+            default:break
+            }
+        }
+        
+        // 删除操作
+        let deleteAction = SwipeAction(style: .destructive, title: nil) {[weak self] action, indexPath in
+            guard let self = self else { return }
+            showCustomAlert(message: "Are you sure to delete".localized, deleteHandler:  { [weak self]  in
+                guard let self = self else { return }
+                if let model = listModelArray.safeObj(At: indexPath.item) {
+                    dbHistory.deleteListModel(id: model.id)
+                    updateListView()
+                    TSBusinessAudioPlayer.shared.stop()
+                }
+            })
+        }
+        
+        deleteAction.backgroundColor = "#E83E3E".uiColor
+        deleteAction.image = UIImage(named: "delete_white")
+        
+        return [deleteAction]
+    }
+    
+    func collectionView(_ collectionView: UICollectionView, editActionsOptionsForItemAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
+        var options = SwipeOptions()
+        options.transitionStyle = .border // 滑动动画样式
+        return options
+    }
+    
+}

+ 1 - 1
AIPlayRingtones/AppPage/APRingTonesVC/APRingStyleVC/APRingStyleVC.swift

@@ -28,7 +28,7 @@ class APRingStyleVC: TSBaseVC {
     }
     lazy var generateStyleModels: [ASGenerateStyleModel] = {
         var ptpStyleModels = [ASGenerateStyleModel]()
-        if let dataArray = Mapper<ASGenerateStyleModel>().mapArray(JSONfile: "ring_style.json"){
+        if let dataArray = Mapper<ASGenerateStyleModel>().mapArray(JSONfile: "ring_ttr_style.json"){
             ptpStyleModels = dataArray
             
             if let model = dataArray.safeObj(At: generateStyleIndex) {

+ 1 - 1
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC+View.swift

@@ -44,7 +44,7 @@ extension APRingTonesVC {
         let ringStyleVC = APRingStyleVC()
         ringStyleVC.selectedCompleted = { [weak self] model,index in
             guard let self = self else { return }
-            viewModel.generateStyleModel = model
+            viewModel.selectedGenerateModel = model
         }
         return ringStyleVC
     }

+ 18 - 6
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/APRingTonesVC.swift

@@ -9,10 +9,6 @@ import Combine
 class APRingTonesVC: TSBaseVC {
     lazy var viewModel: APRingTonesVM = {
         let viewModel = APRingTonesVM()
-//        viewModel.isCanGennerateBlock = { [weak self] _ in
-//            guard let self = self else { return }
-//            setCreatBtnEnabled()
-//        }
         return viewModel
     }()
 
@@ -70,9 +66,25 @@ extension APRingTonesVC {
     func generateAI() {
         view.endEditing(true)
         
+        let gennerateVC = ASRingGeneratorVC(generateStyleModel: viewModel.generateStyleModel) { [weak self] _ in
+            guard let self = self else { return }
+//            updateVipView()
+        }
+
+        gennerateVC.reloadViewBlock = { [weak self] in
+            guard let self = self else { return }
+//            updataCollectionView()
+        }
         
-        
-        TSToastShared.showToast(text: "nihao")
+        gennerateVC.closePageComplete = {
+            [weak self] in
+            guard let self = self else { return }
+//            updataCollectionView()
+        }
+
+        kPresentModalVC(target: self, modelVC: gennerateVC, transitionStyle: .crossDissolve)
+
+      
     }
     
 }

+ 5 - 3
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/Model/ASGenerateStyleModel.swift

@@ -25,8 +25,10 @@ class ASGenerateStyleModel: TSBaseModel {
         prompt                  <- map["prompt"]
         vip                     <- map["vip"]
     }
-
-    var upLoadData:Data?
-    var upLoadRingUrl:String?
+    
+    var duration:Int = 5 //音乐秒数
+    var inputText:String = ""
+    var upLoadFilePath:URL? //待上查的文件
+    var upLoadUrl:String?   //已上传到服务器的网络地址
     var generateType:ASGenerateType = .textToRing
 }

+ 2 - 2
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/Model/ASRingGenerateSecModel.swift

@@ -6,11 +6,11 @@
 //
 import ObjectMapper
 class ASRingGenerateSecModel: TSBaseModel {
-    var sec:Int = 5
+    var duration:Int = 5
     var vip:Bool = false
     
     override func mapping(map: Map) {
-        sec <- map["sec"]
+        duration <- map["duration"]
         vip <- map["vip"]
     }
 }

+ 10 - 2
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/VM/APRingTonesVM.swift

@@ -44,13 +44,13 @@ class APRingTonesVM {
     
     
     //选择生成类类型
-    @Published var generateStyleModel:ASGenerateStyleModel?
+    @Published var selectedGenerateModel:ASGenerateStyleModel?
     
     @Published private(set) var isCanGennerate: Bool = false
     init(){
         
        
-        Publishers.CombineLatest3($promptText, $generateSecModel,$generateStyleModel)
+        Publishers.CombineLatest3($promptText, $generateSecModel,$selectedGenerateModel)
               .map { promptText, generateSecModel,generateStyleModel in
                   // 当两者长度都 > 0 时返回 true
                   return !promptText.isEmpty && generateSecModel != nil && generateStyleModel != nil
@@ -59,4 +59,12 @@ class APRingTonesVM {
               .store(in: &cancellables)
     }
 
+    
+    //用户生成图片的TSGenerateStyleModel
+    var generateStyleModel:ASGenerateStyleModel{
+        let generateStyleModel = selectedGenerateModel!
+        generateStyleModel.inputText = promptText
+        generateStyleModel.duration = generateSecModel?.duration ?? 5
+        return generateStyleModel
+    }
 }

+ 1 - 1
AIPlayRingtones/AppPage/APRingTonesVC/APRingTonesVC/View/ASDurationColView.swift

@@ -76,7 +76,7 @@ class ASDurationColViewCell: TSBaseCollectionCell ,TSSimpleConfigurableView {
     var data: Any? {
         didSet {
             if let model = data as? ASRingGenerateSecModel {
-                textLab.text = "\(model.sec) Sec"
+                textLab.text = "\(model.duration) Sec"
                 proImageView.isHidden = !model.vip
             }
         }

+ 137 - 0
AIPlayRingtones/AppPage/APSettingVC/APSettingVC+Col.swift

@@ -0,0 +1,137 @@
+//
+//  APSettingVC+Col.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/20.
+//
+
+extension APSettingVC {
+ 
+    func creatCollectionView() -> UICollectionView{
+        let layout = UICollectionViewFlowLayout()
+        layout.scrollDirection = .vertical
+        layout.itemSize = CGSize(width: k_ScreenWidth-32, height: 64)
+        layout.minimumInteritemSpacing = 16.0
+        layout.minimumLineSpacing = 16.0
+        
+        layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
+        
+        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
+        collectionView.delegate = self
+        collectionView.dataSource = self
+        collectionView.showsVerticalScrollIndicator = false
+        collectionView.showsHorizontalScrollIndicator = false
+        collectionView.backgroundColor = .clear
+        collectionView.register(APSettingCell.self, forCellWithReuseIdentifier: APSettingCell.cellID)
+        if #available(iOS 11.0, *) {
+            collectionView.contentInsetAdjustmentBehavior = .never
+        }
+        return collectionView
+    }
+    
+    func createItemModel(leftTitle: String,
+                         rightIsHave: Bool,
+                        tapBlock: @escaping ((TSBasicItemModel, Int, Any?) -> Void)) -> TSBasicItemModel {
+        let model = TSBasicItemModel()
+        model.leftTitle = leftTitle
+        model.rightIsHave = rightIsHave
+        model.tapBlock = tapBlock
+        return model
+    }
+    
+}
+
+extension APSettingVC: UICollectionViewDataSource ,UICollectionViewDelegate {
+    
+    public func numberOfSections(in collectionView: UICollectionView) -> Int {
+        return dataArray.count
+    }
+    
+    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+        if let sectionModel = dataArray.safeObj(At: section){
+            return sectionModel.itemsArray.count
+        }
+        return 0
+    }
+    
+    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+        
+        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: APSettingCell.cellID, for: indexPath)
+        if let cell = cell as? APSettingCell {
+            if let sectionModel = dataArray.safeObj(At: indexPath.section),let itemModel = sectionModel.itemsArray.safeObj(At: indexPath.row){
+                cell.itemModel = itemModel
+            }
+        }
+        
+        return cell
+    }
+
+    public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+        if let sectionModel = dataArray.safeObj(At: indexPath.section),let itemModel = sectionModel.itemsArray.safeObj(At: indexPath.row){
+            itemModel.tapBlock?(itemModel,indexPath.row,nil)
+        }
+    }
+}
+
+
+class APSettingCell: TSBaseCollectionCell {
+    
+    static let cellID = "APSettingCell"
+    var itemModel:TSBasicItemModel = TSBasicItemModel(){
+        didSet{
+            titleLab.text = itemModel.leftTitle
+            if itemModel.rightIsHave {
+                infoLab.isHidden = true
+                arrowImageView.isHidden = false
+            }else{
+                infoLab.isHidden = false
+                arrowImageView.isHidden = true
+            }
+        }
+    }
+    
+    lazy var arrowImageView: UIImageView = {
+        let arrowImageView = UIImageView.createImageView(image: .rightArrowWhite)
+        return arrowImageView
+    }()
+
+    
+    lazy var titleLab: UILabel = {
+        let titleLab = UILabel.createLabel(font: .font(size: 16,weight: .regular),textColor: .white,textAlignment: .left,numberOfLines: 0)
+        return titleLab
+    }()
+    
+    lazy var infoLab: UILabel = {
+        let infoLab = UILabel.createLabel(text: appVersion(),font: .font(size: 14,weight: .regular),textColor: .white.withAlphaComponent(0.8),numberOfLines: 0)
+        return infoLab
+    }()
+    
+    override func creatUI() {
+        bgContentView.clipsToBounds = true
+        bgContentView.cornerRadius = 16.0
+        bgContentView.layer.borderWidth = 1
+        bgContentView.layer.borderColor = UIColor.white.withAlphaComponent(0.2).cgColor
+        
+        bgContentView.addSubview(titleLab)
+        titleLab.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.leading.equalTo(16)
+            make.trailing.equalTo(-40)
+        }
+        
+        bgContentView.addSubview(infoLab)
+        infoLab.snp.makeConstraints { make in
+            make.centerY.equalToSuperview()
+            make.trailing.equalTo(-16)
+        }
+
+        bgContentView.addSubview(arrowImageView)
+        arrowImageView.snp.makeConstraints { make in
+            make.trailing.equalTo(-16)
+            make.centerY.equalToSuperview()
+            make.width.height.equalTo(24.0)
+        }
+    }
+    
+}
+

+ 172 - 0
AIPlayRingtones/AppPage/APSettingVC/APSettingVC.swift

@@ -5,6 +5,178 @@
 //  Created by 100Years on 2025/5/15.
 //
 
+import StoreKit
+
 class APSettingVC: TSBaseVC {
     
+    lazy var navBarView: TSBaseNavContentBarView = {
+        let navBarView = TSBaseNavContentBarView()
+
+        let titleImageView = UIImageView.createImageView(imageName: "nav_title_setting", contentMode: .scaleToFill)
+        navBarView.barView.addSubview(titleImageView)
+        titleImageView.snp.makeConstraints { make in
+            make.center.equalToSuperview()
+        }
+        return navBarView
+    }()
+    
+    lazy var cusStackView: TSCustomStackView = {
+        let cusStackView = TSCustomStackView(axis: .vertical, spacing: 0)
+        return cusStackView
+    }()
+    
+    private var collectionViewObserver: TSCollectionViewObserver!
+    lazy var collectionView = creatCollectionView()
+    
+    
+    let appid = "6740220736"
+    lazy var dataArray: [TSBasicSectionModel] = {
+        var dataArray = [TSBasicSectionModel]()
+        let sectionModel = TSBasicSectionModel()
+        dataArray.append(sectionModel)
+
+        //教程
+        sectionModel.addSubItemModel(
+            createItemModel(
+                leftTitle: "How to use?".localized,
+                rightIsHave: true,
+                tapBlock: { [weak self] model, _, _ in
+                   guard let self = self else { return }
+                    TSToastShared.showToast(text: "教程")
+        }))
+        
+        //评价
+        sectionModel.addSubItemModel(
+            createItemModel(
+                leftTitle: "Rate us".localized,
+                rightIsHave: true,
+                tapBlock: { [weak self] model, _, _ in
+                   guard let self = self else { return }
+                    
+                    let countKey = "ProcessCompletedCountKey"
+                    var count = UserDefaults.standard.integer(forKey: countKey)
+                    count += 1
+                    UserDefaults.standard.set(count, forKey: countKey)
+                    /// 如果当前版本 弹过一次 那么下一次就走url
+                    /// 如果当前版本 没弹过,那就弹
+                    if count >= 4 {
+                        let openStr = "itms-apps://itunes.apple.com/app/\(appid)?action=write-review"
+                        if let url = URL(string: openStr), UIApplication.shared.canOpenURL(url) {
+                            if #available(iOS 10.0, *) {
+                                UIApplication.shared.open(url, options: [:], completionHandler: nil)
+                            } else {
+                                UIApplication.shared.canOpenURL(url)
+                            }
+                        } else {
+                            print("链接出错")
+                        }
+                    } else {
+                        SKStoreReviewController.requestReview()
+                    }
+      
+        }))
+        
+        //分享
+        sectionModel.addSubItemModel(
+            createItemModel(
+                leftTitle: "Share us".localized,
+                rightIsHave: true,
+                tapBlock: { [weak self] model, _, _ in
+                   guard let self = self else { return }
+                    
+                    let httpAppStoreLink = "https://apps.apple.com/app/id\(appid)"
+                    let text = "Space"
+                    let url = URL(string: httpAppStoreLink)!
+                    let image = UIImage(named: "App-Icon")!.compressImageSize(to: CGSize(width: 100, height: 100))
+                    let final = ShareActivityItemProvider(placeholderItem: image)
+                    let vc = UIActivityViewController(activityItems: [url, final, text], applicationActivities: nil)
+                    vc.completionWithItemsHandler = { activity, _, _, _ in
+                        if let type = activity, type == .copyToPasteboard {
+                            UIPasteboard.general.string = httpAppStoreLink
+                        }
+                    }
+
+                    present(vc, animated: true)
+      
+        }))
+        
+        //隐私协议
+        sectionModel.addSubItemModel(
+            createItemModel(
+                leftTitle: "Privacy Policy".localized,
+                rightIsHave: true,
+                tapBlock: { [weak self] model, _, _ in
+                guard let self = self else { return }
+                 let vc = ASBusinessWebVC(urlType: .privacy)
+                 vc.hidesBottomBarWhenPushed = true
+                 navigationController?.pushViewController(vc, animated: true)
+        }))
+        
+        //服务条框
+        sectionModel.addSubItemModel(
+            createItemModel(
+                leftTitle: "Terms of Service".localized,
+                rightIsHave: true,
+                tapBlock: { [weak self] model, _, _ in
+                   guard let self = self else { return }
+                    let vc = ASBusinessWebVC(urlType: .terms)
+                    vc.hidesBottomBarWhenPushed = true
+                    navigationController?.pushViewController(vc, animated: true)
+        }))
+        
+        //关于我们
+        sectionModel.addSubItemModel(
+            createItemModel(
+                leftTitle: "About us".localized,
+                rightIsHave: true,
+                tapBlock: { [weak self] model, _, _ in
+                   guard let self = self else { return }
+      
+        }))
+        
+        return dataArray
+
+    }()
+    
+    override func createView() {
+        
+        navBarContentView.addSubview(navBarView)
+        navBarView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        contentView.addSubview(cusStackView)
+        cusStackView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+        
+        cusStackView.addSubviewToStack(collectionView,length: 0)
+    }
+    
+    override func dealThings() {
+
+        // 监听collectionView 的 contentSize
+        collectionViewObserver = TSCollectionViewObserver(collectionView: collectionView)
+        collectionViewObserver.onContentSizeChange = { [weak self] size in
+            guard let self = self else { return }
+            print("collectionViewObserver 内容大小变化: \(size)")
+            self.collectionView.snp.updateConstraints { make in
+                make.height.equalTo(size.height)
+            }
+        }
+        collectionView.reloadData()
+        
+    }
+    
+}
+
+
+class ShareActivityItemProvider: UIActivityItemProvider {
+    // 解决AirDrop分享app失败的问题
+    override func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
+        if activityType == .airDrop {
+            return nil
+        }
+        return placeholderItem
+    }
 }

+ 73 - 0
AIPlayRingtones/AppPage/ASBusinessWebVC/ASBusinessWebVC.swift

@@ -0,0 +1,73 @@
+//
+//  ASBusinessWebVC.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/20.
+//
+
+
+import UIKit
+import WebKit
+class ASBusinessWebVC: TSBaseVC , WKNavigationDelegate {
+    
+    enum UrlType:String {
+        case privacy = "http://100yearslater.com/Privacy.html"
+        case terms = "https://doc-hosting.flycricket.io/hahaemoji-terms-of-use/7488c423-9bb6-480e-9a38-f52fba511335/terms"
+
+        func getTitle() -> String {
+            switch self {
+            case .privacy:
+                return "Privacy Policy".localized
+            case .terms:
+                return "Terms of Service".localized
+            }
+        }
+    }
+    
+    private var webView: WKWebView!
+    private var urlType: UrlType
+    private var progressView: UIProgressView!
+    
+    init(urlType: UrlType) {
+        self.urlType = urlType
+        super.init(nibName: nil, bundle: nil)
+    }
+    
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    override func createView() {
+        addNormalNavBarView()
+        setPageTitle(urlType.getTitle())
+    }
+    
+    override func viewDidLoad() {
+        super.viewDidLoad()
+        setupWebView()
+        loadURL()
+    }
+    
+    private func setupWebView() {
+        // 初始化 WKWebView
+        let webConfiguration = WKWebViewConfiguration()
+        webView = WKWebView(frame: .zero, configuration: webConfiguration)
+        webView.navigationDelegate = self
+        webView.translatesAutoresizingMaskIntoConstraints = false
+        contentView.addSubview(webView)
+        webView.snp.makeConstraints { make in
+            make.edges.equalToSuperview()
+        }
+
+    }
+
+    private func loadURL() {
+        guard let url = URL(string: urlType.rawValue) else {
+            debugPrint("无效的 URL")
+            return
+        }
+        let request = URLRequest(url: url)
+        webView.load(request)
+    }
+    
+}

+ 111 - 0
AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC+load.swift

@@ -0,0 +1,111 @@
+//
+//  ASRingGeneratorVC+load.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+extension ASRingGeneratorVC {
+    
+    func createGeneratorView() -> ASGeneratorView{
+        let generateInView = ASGeneratorView()
+        generateInView.animationView.setText(time: String(format: "~ %d min".localized, 2), info: "Lots of people are creating images right now, so this might take a bit.".localized)
+
+        
+        generateInView.clickBackstageBlock = { [weak self]  in
+            guard let self = self else { return }
+            clickBackstageBtn()
+        }
+        
+        generateInView.clickErrorBlock = { [weak self] style in
+            guard let self = self else { return }
+            
+            switch style {
+            case .netWorkError:
+//                clickTryAgainBtn()
+                self.dismiss(animated: true, completion: nil)
+            case .sensitiveError:
+//                pickSinglePhoto()
+                self.dismiss(animated: true, completion: nil)
+            case .generalError:
+                self.dismiss(animated: true, completion: nil)
+            default:
+                break
+            }
+        }
+        return generateInView
+    }
+    
+    
+    func upDateView(state:ASProgressState,model:ASActionInfoModel?){
+        updateInfoModel(model: model)
+        progressState = state
+        switch state {
+            case .failed(let errorStr,let code):
+                showError(text: errorStr,code:code)
+            case .success:
+                if let model = model {
+                    showSuccess(model: model)
+                }else{
+                    showError(text: "")
+                }
+            case .progress(let progress, let string):
+                showProgress(text: string)
+            default:
+                showLoading()
+        }
+    }
+    
+    func showProgress(text:String) {
+        generateInView.updateShowProgress(text: text)
+        
+        bottomView.isHidden = true
+        isClickTheBlankClosePage = false
+    }
+    
+    func showLoading(){
+        generateInView.updateShowLoading(text: "Generating".localized + " ...")
+        
+        bottomView.isHidden = true
+        isClickTheBlankClosePage = false
+        
+        xBtn.isHidden = true
+    }
+    
+    func showError(text:String,code:Int = 0){
+        generateInView.updateShowError(text: text,code: code)
+    
+        bottomView.isHidden = true
+        isClickTheBlankClosePage = false
+        xBtn.isHidden = false
+//        againBtn.isHidden = false//重试
+//        failView.isHidden = false
+////        failLabel.text = msg
+//        saveBtn.isHidden = true
+//        successTopView.isHidden = true
+//
+//        ringView.isHidden = true
+//        regenerateBtn.isHidden = true
+//
+//        isClickTheBlankClosePage = true
+    }
+    
+    func showSuccess(model:ASActionInfoModel){
+        generateInView.updateShowSuccess()
+        
+        bottomView.isHidden = false
+        
+        xBtn.isHidden = false
+        againBtn.isHidden = true//重试
+        failView.isHidden = true
+        saveBtn.isHidden = false
+        successTopView.isHidden = false
+
+        infoModel = model
+        isClickTheBlankClosePage = true
+        
+        ringView.isHidden = false
+        regenerateBtn.isHidden = false
+        
+    }
+}

+ 180 - 206
AIPlayRingtones/AppPage/ASRingGeneratorVC/ASRingGeneratorVC.swift

@@ -9,16 +9,9 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
     var infoModel:ASActionInfoModel?
     var complete:((ASActionInfoModel)->Void)
     var reloadViewBlock:(()->Void)?
-    var changeImageBlock:((UIImage)->Void)?
     var progressState = ASProgressState.none
 
-    
-    // 1. 定义历史记录类型枚举
-    enum generateType: String,CaseIterable {
-        case texToRing = "texToRingHistoryListString"  //图生图
-        case ringToRing = "ringToRingHistoryListString"       //文生图
-    }
-    
+
     var generateStyleModel:ASGenerateStyleModel
     init(generateStyleModel:ASGenerateStyleModel,infoModel:ASActionInfoModel? = nil,complete:@escaping ((ASActionInfoModel)->Void)) {
         self.generateStyleModel = generateStyleModel
@@ -31,46 +24,56 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
         fatalError("init(coder:) has not been implemented")
     }
     
-    lazy var generateInView : ASGeneratorView = {
-        let generateInView = ASGeneratorView()
-        generateInView.animationView.setText(time: String(format: "~ %d min".localized, 2), info: "Lots of people are creating images right now, so this might take a bit.".localized)
+    lazy var generateInView : ASGeneratorView = createGeneratorView()
+    lazy var audioPlayer = TSBusinessAudioPlayer.shared
+    var uuidString:String = UUID().uuidString
 
-        
-        generateInView.clickBackstageBlock = { [weak self]  in
+    lazy var ringView: ASRingToneCellView = {
+        let ringToneView = ASRingToneCellView()
+        ringToneView.isSelectedChangeColor = false
+        ringToneView.clickPlayHandel = { [weak self] play  in
             guard let self = self else { return }
-            clickBackstageBtn()
+            clickPlay()
         }
-        
-        generateInView.clickErrorBlock = { [weak self] style in
-            guard let self = self else { return }
-            
-            switch style {
-            case .netWorkError:
-//                clickTryAgainBtn()
-                self.dismiss(animated: true, completion: nil)
-            case .sensitiveError:
-//                pickSinglePhoto()
-                self.dismiss(animated: true, completion: nil)
-            case .generalError:
-                self.dismiss(animated: true, completion: nil)
-            default:
-                break
-            }
-        }
-        return generateInView
+        return ringToneView
     }()
     
-
+    var operation:ASBaseOperation?
     override func createView() {
-
-        contentView.addSubview(generateInView)
+        super.createView()
+        
+        view.addSubview(generateInView)
         generateInView.snp.makeConstraints { make in
-            make.edges.equalToSuperview()
+            make.top.bottom.leading.trailing.equalTo(0)
+        }
+
+        diyView.addSubview(ringView)
+        ringView.snp.makeConstraints { make in
+            make.top.equalTo(98)
+            make.centerX.equalToSuperview()
+            make.width.equalTo(k_ScreenWidth - 40)
+            make.height.equalTo(72)
         }
         
-        super.createView()
+        diyView.addSubview(regenerateBtn)
+        regenerateBtn.snp.makeConstraints { make in
+            make.top.equalTo(ringView.snp.bottom).offset(16)
+            make.centerX.equalToSuperview()
+        }
+        saveBtn.setTitle("Set As Ringtone".localized, for: .normal)
+        resultIconImageView.image = resultIcon
+        bottomViewH = 340.0
+        bgImageView.addShadow(shadowColor: "#E6E229".uiColor.cgColor, shadowOffset: .zero, shadowRadius: 20, shadowOpacity: 0.8)
         
-//        xBtn.isHidden = true
+        diyView.addSubview(failView)
+        failView.snp.updateConstraints { make in
+            make.centerY.equalToSuperview().offset(0)
+        }
+    }
+    
+    @objc func clickBackstageBtn() {
+        NotificationCenter.default.post(name: .kRingDataChanged, object: nil)
+        self.dismiss(animated: true, completion: nil)
     }
     
     override func closePage() {
@@ -91,9 +94,10 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
                 cancelAction: { [weak self]  in
                     guard let self = self else { return }
                     print("用户点击了Leave")
-//                    operation.cancel()
+                    operation?.cancel()
                     if let model = infoModel{
-                        ASRMShared.texToRingDBHistory.deleteListModel(id: model.id)
+                        dbHistory.deleteListModel(id: model.id)
+                        NotificationCenter.default.post(name: .kRingDataChanged, object: nil)
                     }
                     self.dismiss(animated: true, completion: nil)
                 },
@@ -104,203 +108,173 @@ class ASRingGeneratorVC: ASRingGeneratorBaseVC {
         }
     }
     
-//    override func closePage() {
-//        self.dismiss(animated: true, completion: nil)
-//    }
+    override func clickAgainBtn() {
+        audioPlayer.stop()
+//        if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones, vc: self){ return }//判断 vip
+        creatRintone()
+    }
     
-//    //重试
-//    @objc override func clickTryAgainBtn(){
-//        clickRegenerateBtn()
-//    }
+    @objc override func clickSubmitBtn(){
+        
+        guard let model = infoModel else {
+            kShowToastDataMissing()
+            return
+        }
+        audioPlayer.stop()
+        ASDownloadManager.getDownLoadRing(urlString: model.response.musicUrl){ url,downLoad in
+            if let path = url {
+                _ = kshareBand(needVip: model.response.vip, vc: self, fileURL: path, fileName: model.response.title)
+            }
+        }
+    }
     
-    //后台生成
-    @objc func clickBackstageBtn() {
-//        self.operation.isSaveDB = true //后台生成,让数据库保存数据
-        if let model = infoModel {
-            dbHistory.updateData(model)
-            debugPrint("图生图进入后台,保存数据listModels.first=\(dbHistory.listModels.first)")
-            NotificationCenter.default.post(name: dataChangedNotification, object: nil)
-        }else{
-            debugPrint("进入后台,但是没有新数据")
+    @objc func clickPlay(){
+        
+        guard let infoModel = infoModel else { return }
+        
+        if  TSBusinessAudioPlayer.shared.isPlayURLString(string: infoModel.response.musicUrl) {
+            if TSBusinessAudioPlayer.shared.isLoading{
+                return
+            }
+            if TSBusinessAudioPlayer.shared.isPlaying{
+                TSBusinessAudioPlayer.shared.stop()
+            }else{
+                audioPlayer.playUrlString(infoModel.response.musicUrl)
+            }
+        }else {
+            TSBusinessAudioPlayer.shared.stop()//让上一个对象停止播放
+            ringView.monitorPlayStateDefaultHandle()//更换监听
+            audioPlayer.playUrlString(infoModel.response.musicUrl)
         }
 
-        self.dismiss(animated: true, completion: nil)
     }
     
-//    //重新生成
-//    @objc override func clickRegenerateBtn(){
-//        //判断 vip
-//        if kJudgeVip(externalBool: kPurchaseDefault.freeNumAvailable(type: .picToPic) == false, vc: self) { return }
-//        
-//        if let model = self.infoModel {
-//            if model.actionStatus == .success  {
-//                model.id = Date.timestampInt //如果是成功,且再生成一个,则更换一个 id ,作为新数据保存
-//            }
-//            creatOperation(infoModel: model)
-//        }else {
-//            uploadImageCreatOperation()
-//        }
-//        
-//    }
-    
-//    //保存功能
-//    @objc override func clickSaveBtn(){
-//        if let image = getSuccessImage() {
-//            PhotoManagerShared.saveImageToAlbum(image) { success, error in
-//                if success {
-//                    kSaveSuccesswShared.show(atView:self.view)
-//                    kFirstSaveRateAction()
-//                }else{
-//                    debugPrint(error)
-//                }
-//            }
-//        }
-//    }
+    override func viewWillDisappear(_ animated: Bool) {
+        super.viewWillDisappear(animated)
+        audioPlayer.stop()
+    }
     
     override func dealThings() {
-//        creatImage()
+        creatRintone()
     }
-    
-    
-//    func creatImage() {
-//        if let model = self.infoModel{
-//            if model.actionStatus == .failed{
-//                creatOperation(infoModel: model)
-//            }else if model.response.resultUrl.count > 0 {
-//                upDateView(state: .success(model), model: model)
-//            }
-//        }else{
-//            uploadImageCreatOperation()
-//        }
-//    }
-//    var operation:ASGeneratePTPOperation = TSGeneratePTPOperation(uuid: UUID().uuidString)
-//    func creatOperation(infoModel: ASActionInfoModel) {
-//        operation = TSGeneratePTPOperationQueue.shared.creatOperation(uuid: UUID().uuidString)
-//        operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
-//            guard let self = self else { return }
-//            self.upDateView(state: state, model: model)
-//        }.store(in: &cancellable)
-//        operation.creatImage(oldModel: infoModel)
-//        generateInView.setBackgroundGenerateBtnHidden(false)
-//        xBtn.isHidden = false
-//    }
-//    
-//    func uploadImageCreatOperation() {
-//        operation = TSGeneratePTPOperationQueue.shared.creatOperation(uuid: UUID().uuidString)
-//        operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
-//            guard let self = self else { return }
-//            self.upDateView(state: state, model: model)
-//        }.store(in: &cancellable)
-//        operation.uploadImage(generateStyleModel: viewModel.generateStyleModel) {[weak self] actionInfoModel in
-//            guard let self = self else { return }
-//            if let actionInfoModel = actionInfoModel{
-//                operation.creatImage(oldModel: actionInfoModel)
-//                generateInView.setBackgroundGenerateBtnHidden(false)
-//                xBtn.isHidden = false
-//            }
-//        }
-//    }
-    
-    
-    deinit {
-//        operation.isShowSuccessView = true
+
+ 
+    func creatRintone() {
+        self.uuidString = UUID().uuidString
+        if let model = self.infoModel{
+            if model.actionStatus == .failed{
+                generatorCreatRing(oldModel: model)
+            }else if model.response.musicUrl.count > 0 {
+                upDateView(state: .success(model), model: model)
+                return
+            }
+        }else{
+            generatorNew()
+        }
+//        if kPurchaseToolShared.kJudgeVipFreeType(vipFreeNumType: .ringtones, vc: self){ return }//判断 vip
     }
-}
 
-extension ASRingGeneratorVC {
+}
 
+extension ASRingGeneratorVC{
+    
     var dbHistory:ASDBHistory{
-        switch generateStyleModel.generateType {
-        case .textToRing:
-            return ASRMShared.texToRingDBHistory
-        case .ringToRing:
-            return ASRMShared.ringToRingDBHistory
+        ASRMShared.ringDBHistory
+    }
+
+    func generatorNew(){
+        if generateStyleModel.generateType == .textToRing {
+            generatorNewTTR()
+        }else{
+            generatorNewRTR()
         }
     }
     
-    var dataChangedNotification:Notification.Name{
-        switch generateStyleModel.generateType {
-        case .textToRing:
-            return .kTextToRingDataChanged
-        case .ringToRing:
-            return .kRingToRingDataChanged
+    func generatorCreatRing(oldModel:ASActionInfoModel) {
+        if generateStyleModel.generateType == .textToRing {
+            generatorTTRCreatRing(oldModel: oldModel)
+        }else{
+            generatorRTRCreatRing(oldModel: oldModel)
         }
     }
-    
 }
-extension ASRingGeneratorVC {
+
+extension ASRingGeneratorVC{
     
-    func upDateView(state:ASProgressState,model:ASActionInfoModel?){
-        infoModel = model
-        progressState = state
-        switch state {
-            case .failed(let errorStr,let code):
-                showError(text: errorStr,code:code)
-            case .success:
-                if let model = model {
-                    showSuccess(model: model)
-                }else{
-                    showError(text: "")
-                }
-            case .progressString(let string):
-                showProgress(text: string)
-            case .none:
-                break
-            default:
-                showLoading()
-        }
+    func generatorNewTTR() {
+        let operation:ASGenerateTextToRingOperation = ASGenerateTextToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        let oldModel = operation.createActionInfoModel(generateStyleModel: generateStyleModel)
+        generatorTTRCreatRing(oldModel: oldModel)
     }
     
-    func showProgress(text:String) {
-        generateInView.updateShowProgress(text: text)
+    func generatorTTRCreatRing(oldModel:ASActionInfoModel) {
+        let operation:ASGenerateTextToRingOperation = ASGenerateTextToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
+            guard let self = self else { return }
+            self.upDateView(state: state, model: model)
+        }.store(in: &cancellable)
         
-        isClickTheBlankClosePage = false
-        bottomView.isHidden = true
-//        netWorkImageView.isHidden = true
-//        rotatingPictureBtn.isHidden = true
+        operation.creatRing(oldModel: oldModel){ [weak self]  success in
+            guard let self = self else { return }
+            if success {
+                generateInView.setBackgroundGenerateBtnHidden(false)
+                xBtn.isHidden = false
+            }
+        }
     }
-    
-    func showLoading(){
-        generateInView.updateShowLoading(text: "Generating".localized + " ...")
+}
 
-        isClickTheBlankClosePage = false
-        bottomView.isHidden = true
-//        netWorkImageView.isHidden = true
-//        rotatingPictureBtn.isHidden = true
+extension ASRingGeneratorVC{
+    func generatorNewRTR() {
+        let operation:ASGenerateRingToRingOperation = ASGenerateRingToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
+            guard let self = self else { return }
+            self.upDateView(state: state, model: model)
+        }.store(in: &cancellable)
+        
+        operation.uploadFile(generateStyleModel: generateStyleModel)  { [weak self] actionInfoModel in
+            guard let self = self else { return }
+            guard let oldModel = actionInfoModel else {return}
+            generatorRTRCreatRing(oldModel: oldModel)
+        }
     }
     
-    func showError(text:String,code:Int = 0){
-        generateInView.updateShowError(text: text,code: code)
-
-        isClickTheBlankClosePage = true
+    func generatorRTRCreatRing(oldModel:ASActionInfoModel) {
+        let operation:ASGenerateRingToRingOperation = ASGenerateRingToRingOperationQueue.shared.creatOperation(uuid: self.uuidString)
+        operation.$stateDatauPblished.receive(on: DispatchQueue.main).sink {[weak self]  (state,model) in
+            guard let self = self else { return }
+            self.upDateView(state: state, model: model)
+        }.store(in: &cancellable)
         
-        xBtn.isHidden = false
-//        tryAgainBtn.isHidden = true
-//        bigSaveBtn.isHidden = true
-        bottomView.isHidden = true
-//        netWorkImageView.isHidden = true
-//        rotatingPictureBtn.isHidden = true
+        operation.creatRing(oldModel: oldModel){ [weak self]  success in
+            guard let self = self else { return }
+            if success {
+                generateInView.setBackgroundGenerateBtnHidden(false)
+                xBtn.isHidden = false
+            }
+        }
     }
-    
-    func showSuccess(model:ASActionInfoModel){
-        generateInView.updateShowSuccess()
+}
 
-        isClickTheBlankClosePage = true
-        
-        xBtn.isHidden = false
-//        tryAgainBtn.isHidden = false
-//        bigSaveBtn.isHidden = false
-        bottomView.isHidden = false
-//        netWorkImageView.isHidden = false
-//        rotatingPictureBtn.isHidden = false
-        
-        
-        dbHistory.updateData(model)
-//        self.netWorkImageView.setAsyncImage(urlString: model.response.resultUrl,placeholder:kPlaceholderImage,backgroundColor:netWorkImageView.backgroundColor!)
-        
-        if let model = infoModel {
+
+extension ASRingGeneratorVC{
+
+    var resultIcon:UIImage?{
+        return UIImage(named: "ai_rintone_icon")
+    }
+    
+    func updateInfoModel(model:ASActionInfoModel?){
+        infoModel = model
+        if let model = model {
             complete(model)
+            setRingViewData(model: model)
         }
     }
-    
+
+    func setRingViewData(model:ASActionInfoModel) {
+        ringView.timeLab.text = Float(model.request.duration).floatToMinuteSecond()
+        ringView.nameLab.text = model.response.title
+        ringView.setCoverImageView(urlString: model.response.coverUrl)
+    }
 }
+

+ 4 - 4
AIPlayRingtones/AppPage/ASTabBarVC/ASTabBarVC.swift

@@ -23,18 +23,18 @@ class ASTabBarVC: UITabBarController {
     }
 
     @objc private func setUpData() {
-        viewControllerArray = ["APRingTonesVC","APAudioToRingVC","APMyRingVC","APSettingVC"]
+        viewControllerArray = ["APAudioToRingVC","APRingTonesVC","APMyRingVC","APSettingVC"]
 
-        titleArray = ["Audio","Create","Mine","Setting"]
+        titleArray = ["Create","Audio","Mine","Setting"]
         selectedImageArray = [
-            "tabbar_selected_create",
             "tabbar_selected_audio",
+            "tabbar_selected_create",
             "tabbar_selected_mine",
             "tabbar_selected_setting"
         ]
         unselectedImageArray = [
-            "tabbar_unSelect_create",
             "tabbar_unSelect_audio",
+            "tabbar_unSelect_create",
             "tabbar_unSelect_mine",
             "tabbar_unSelect_setting"
         ]

+ 25 - 0
AIPlayRingtones/AppPage/Common/ Notification+Ex.swift

@@ -0,0 +1,25 @@
+//
+//   Notification+Ex.swift
+//  AIPlayRingtones
+//
+//  Created by 100Years on 2025/5/16.
+//
+
+import Foundation
+
+extension Notification.Name {
+    static let kApplicationWillTerminate = Notification.Name("applicationWillTerminate")
+    static let kVipFreeNumChanged = Notification.Name("kVipFreeNumChanged")   //Vip免费次数发生变化
+    static let kRefreshSettingView = Notification.Name("kRefreshSettingView")   //刷新设置按钮
+    
+    static let kBaseOperationQueueCountChanged = Notification.Name("kBaseOperationQueueCountChanged") //任务数量放生变化
+    
+    static let kGenerateRingOperationChanged = Notification.Name("kGeneratePTPOperationChanged") //生成铃声任务发生变化
+    static let kGenerateTTROperationChanged = Notification.Name("kGeneratePTPOperationChanged") //生成文生铃声任务发生变化
+    static let kGenerateRTROperationChanged = Notification.Name("kGeneratePTPOperationChanged") //生成铃声生铃声任务发生变化
+    
+    static let kRingDataChanged = Notification.Name("kGeneratePTPOperationChanged") //铃声数据发生变化
+    static let kTextToRingDataChanged = Notification.Name("kTextToRingDataChanged") //文生铃声数据改变
+    static let kRingToRingDataChanged = Notification.Name("kRingToRingDataChanged") //铃声生铃声数据改变
+
+}

+ 7 - 0
AIPlayRingtones/AppPage/Common/AIEnums.swift

@@ -0,0 +1,7 @@
+//
+//  AIEnums.swift
+//  AIPlayRingtones
+//
+//  Created by 100Years on 2025/5/15.
+//
+

+ 176 - 0
AIPlayRingtones/AppPage/Common/ASBusinessFileManager.swift

@@ -0,0 +1,176 @@
+//
+//  ASBusinessFileManager.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/18.
+//
+
+
+class ASBusinessFileManager {
+    
+    /// 获取 Video 下载后保存的的文件件路径
+    static var saveRingPathURL:URL = {
+        let saveRingPathURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!.appendingPathComponent("ring")
+        return saveRingPathURL
+    }()
+    
+    static var saveCacheAllPathURL:URL = {
+        let saveRingPathURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!.appendingPathComponent("cacheAll")
+        return saveRingPathURL
+    }()
+    
+    public static func generateFileName(
+        urlString: String,
+        fileEx:String? = nil,
+    missingEx:String? = nil
+    )->String?{
+        guard let url = URL(string: urlString) else{
+            return nil
+        }
+        
+        var fileName = url.path.md5
+
+        // 使用 URL 的 MD5 哈希值作为缓存文件名,附加 URL 的后缀名
+        var fileExtension = ""
+        if let fileEx = fileEx {
+            fileExtension = fileEx
+        }else{
+            var missingExStr = ""
+            if let missingEx = missingEx {
+                missingExStr = missingEx
+            }
+            fileExtension = url.pathExtension.isEmpty ? missingExStr : url.pathExtension
+        }
+
+        if fileExtension.count > 0 {
+            fileName = url.path.md5 + ".\(fileExtension)"
+        }
+         
+        return fileName
+    }
+    
+    //获取 urlstring 本地的缓存 url path
+    public static func getLocalURL(
+        urlString: String,
+        fileEx:String? = nil,
+    missingEx:String? = nil)->URL?{
+        
+        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
+            return nil
+        }
+        
+        //检查文件是否已存在于缓存中
+        let ringFileURL = saveRingPathURL.appendingPathComponent(fileName)
+        if FileManager.default.fileExists(atPath: ringFileURL.path) {
+            print("文件已存在于缓存中: \(ringFileURL)")
+            return ringFileURL
+        }
+        
+        let cachedFileURL = saveCacheAllPathURL.appendingPathComponent(fileName)
+        if FileManager.default.fileExists(atPath: cachedFileURL.path) {
+            print("文件已存在于缓存中: \(cachedFileURL)")
+            return cachedFileURL
+        }
+        
+        return nil
+    }
+    
+
+}
+
+//缓存路径
+extension ASBusinessFileManager {
+    
+    //检查 url 对不对
+    public static func generateLocalURL(
+        from urlString: String,
+        fileEx:String? = nil,
+        missingEx:String? = nil,
+        frontPathURL:URL,
+        completion:((String?, Error?) -> Void)? = nil
+    )->URL?
+    {
+        guard let url = URL(string: urlString) else{
+            completion?(nil, NSError(domain: "url null", code: 0))
+            return nil
+        }
+        
+        if !urlString.contains("http") && urlString.contains("/"){
+            completion?(urlString.fillCachePath, nil)
+            return nil
+        }
+        
+        let fileManager = FileManager.default
+        let cacheAllDirectory = frontPathURL
+        
+        // 创建 `cacheAll` 文件夹(如果不存在)
+        if !fileManager.fileExists(atPath: cacheAllDirectory.path) {
+            do {
+                try fileManager.createDirectory(at: cacheAllDirectory, withIntermediateDirectories: true, attributes: nil)
+            } catch {
+                completion?(nil, error)
+                return nil
+            }
+        }
+        
+        
+        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
+            completion?(nil, NSError(domain: "url error", code: 0))
+            return nil
+        }
+        
+        let cachedFileURL = cacheAllDirectory.appendingPathComponent(fileName)
+        return cachedFileURL
+    }
+    
+}
+//
+////缓存路径
+//extension ASBusinessFileManager {
+//    
+//    //检查 url 对不对
+//    public static func generateCachesURL(
+//        from urlString: String,
+//        fileEx:String? = nil,
+//    missingEx:String? = nil,
+//        cacheDirectory:String = "cacheAll",
+//        completion:((String?, Error?) -> Void)? = nil
+//    )->URL?
+//    {
+//        guard let url = URL(string: urlString) else{
+//            completion?(nil, NSError(domain: "url null", code: 0))
+//            return nil
+//        }
+//        
+//        if !urlString.contains("http") && urlString.contains("/"){
+//            completion?(urlString.fillCachePath, nil)
+//            return nil
+//        }
+//        
+//        let fileManager = FileManager.default
+//        
+//        // 获取缓存目录下的 `cacheAll` 文件夹路径
+//        let cachesDirectory = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
+//        let cacheAllDirectory = cachesDirectory.appendingPathComponent(cacheDirectory)
+//        
+//        // 创建 `cacheAll` 文件夹(如果不存在)
+//        if !fileManager.fileExists(atPath: cacheAllDirectory.path) {
+//            do {
+//                try fileManager.createDirectory(at: cacheAllDirectory, withIntermediateDirectories: true, attributes: nil)
+//            } catch {
+//                completion?(nil, error)
+//                return nil
+//            }
+//        }
+//        
+//        
+//        guard let fileName = generateFileName(urlString: urlString,fileEx:fileEx,missingEx: missingEx) else{
+//            completion?(nil, NSError(domain: "url error", code: 0))
+//            return nil
+//        }
+//
+//        let cachedFileURL = cacheAllDirectory.appendingPathComponent(fileName)
+//        return cachedFileURL
+//    }
+//    
+//}

+ 45 - 0
AIPlayRingtones/AppPage/Common/ASDownloadManager/ASDownloadManager.swift

@@ -0,0 +1,45 @@
+//
+//  ASDownloadManager.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/18.
+//
+
+import AVFoundation
+import Alamofire
+
+class ASDownloadManager {
+    
+    static func getDownLoadRing(urlString:String,progressHandler: ((Double) -> Void)? = nil,complete:@escaping (URL?,Bool)->Void){
+        if let path = ASBusinessFileManager.getLocalURL(urlString: urlString,fileEx:nil,missingEx: "mp3") {
+            complete(path,false)
+        }else{
+            _ = ASDownloadManager.downloadRing(urlString:urlString,missingEx: "mp3",progressHandler: progressHandler) { url, error in
+                if let path = url {
+                    complete(path,true)
+                }else{
+                    complete(nil,true)
+                }
+            }
+        }
+    }
+    
+    static func downloadRing(
+        urlString: String,
+        fileEx:String? = nil,
+    missingEx:String? = nil,
+        progressHandler: ((Double) -> Void)? = nil,
+        completion: @escaping (URL?, Error?) -> Void
+    ) -> DownloadRequest? {
+        
+        if let fileName = ASBusinessFileManager.getLocalURL(urlString: urlString,fileEx:fileEx,missingEx:missingEx){
+            completion(fileName,nil)
+            return nil
+        }
+        guard let savePath = ASBusinessFileManager.generateLocalURL(from: urlString, fileEx: fileEx, missingEx: missingEx,frontPathURL: ASBusinessFileManager.saveRingPathURL,completion: { string, error in
+            completion(nil,error)
+        })else { return nil }
+        
+        return TSNetworkShared.downloadFile(urlString: urlString,to: savePath, progressHandler:progressHandler,completion: completion)
+    }
+}

+ 8 - 0
AIPlayRingtones/AppPage/Common/Common.swift

@@ -0,0 +1,8 @@
+//
+//  Common.swift
+//  AIPlayRingtones
+//
+//  Created by 100Years on 2025/5/15.
+//
+
+@_exported import TSSmalCoacopods

+ 394 - 0
AIPlayRingtones/AppPage/Common/CpuMapManager.swift

@@ -0,0 +1,394 @@
+//
+//  CpuMapManager.swift
+//  ClockWidget
+//
+//  Created by fff on 2023/7/28.
+//
+
+import UIKit
+
+class CpuMapManager: NSObject {
+    static let shared = CpuMapManager()
+    
+    /// 数据来源 https://kylebing.cn/tools/iphone/
+    ///         http://kylebing.cn/tools/iphone/
+    ///
+    private let deviceMap: [String: [String: String]] = [
+        
+        "iPhone 16 Pro Max" : ["CPU":"A18 Pro",
+                               "Freq": "4.04GHz",
+                               "Battery": "4685 mah"],
+        "iPhone 16 Pro"     : ["CPU":"A18 Pro",
+                               "Freq": "4.04GHz",
+                               "Battery": "3582 mah"],
+        "iPhone 16 Plus"    : ["CPU":"A18",
+                               "Freq": "3.78GHz",
+                               "Battery": "4674 mah"],
+        "iPhone 16"         : ["CPU":"A18",
+                               "Freq": "3.78GHz",
+                               "Battery": "3561 mah"],
+        
+        "iPhone 15 Pro Max" : ["CPU":"A17 Pro",
+                               "Freq": "3.77GHz",
+                               "Battery": "4422 mah"],
+        "iPhone 15 Pro"     : ["CPU":"A17 Pro",
+                               "Freq": "3.77GHz",
+                               "Battery": "3274 mah"],
+        "iPhone 15 Plus"    : ["CPU":"A16",
+                               "Freq": "3.46GHz",
+                               "Battery": "4383 mah"],
+        "iPhone 15"         : ["CPU":"A16",
+                               "Freq": "3.46GHz",
+                               "Battery": "3349 mah"],
+        
+        "iPhone 14 Pro Max" : ["CPU":"A16",
+                               "Freq": "3.46GHz",
+                               "Battery": "4323 mah"],
+        "iPhone 14 Pro"     : ["CPU":"A16",
+                               "Freq": "3.46GHz",
+                               "Battery": "3200 mah"],
+        "iPhone 14 Plus"    : ["CPU":"A15",
+                               "Freq": "3.20GHz",
+                               "Battery": "4325 mah"],
+        "iPhone 14"         : ["CPU":"A15",
+                               "Freq": "3.20GHz",
+                               "Battery": "3279 mah"],
+        
+        "iPhone SE3"        : ["CPU":"A15",
+                               "Freq": "3.20GHz",
+                               "Battery": "2018 mah"],
+        "iPhone 13 Pro Max" : ["CPU":"A15",
+                               "Freq": "3.20GHz",
+                               "Battery": "4352 mah"],
+        "iPhone 13 Pro"     : ["CPU":"A15",
+                               "Freq": "3.20GHz",
+                               "Battery": "3095 mah"],
+        "iPhone 13"         : ["CPU":"A15",
+                               "Freq": "3.20GHz",
+                               "Battery": "3227 mah"],
+        "iPhone 13 Mini"    : ["CPU":"A15",
+                               "Freq": "3.20GHz",
+                               "Battery": "2406 mah"],
+        
+        "iPhone 12 Pro Max" : ["CPU":"A14",
+                               "Freq": "3.00GHz",
+                               "Battery": "3687 mah"],
+        "iPhone 12 Pro"     : ["CPU":"A14",
+                               "Freq": "3.00GHz",
+                               "Battery": "2815 mah"],
+        "iPhone 12"         : ["CPU":"A14",
+                               "Freq": "3.00GHz",
+                               "Battery": "2851 mah"],
+        "iPhone 12 Mini"    : ["CPU":"A14",
+                               "Freq": "3.00GHz",
+                               "Battery": "2227 mah"],
+        
+        "iPhone SE2"        : ["CPU":"A13",
+                               "Freq": "2.0GHz",
+                               "Battery": "1821 mah"],
+        
+        "iPhone 11 Pro Max" : ["CPU":"A13",
+                               "Freq": "2.0GHz",
+                               "Battery": "3969 mah"],
+        "iPhone 11 Pro"     : ["CPU":"A13",
+                               "Freq": "2.0GHz",
+                               "Battery": "3046 mah"],
+        "iPhone 11"         : ["CPU":"A13",
+                               "Freq": "2.0GHz",
+                               "Battery": "3110 mah"],
+        
+        "iPhone XR"         : ["CPU":"A13",
+                               "Freq": "2.0GHz",
+                               "Battery": "2942 mah"],
+        "iPhone XS Max"     : ["CPU":"A12",
+                               "Freq": "2.49GHz",
+                               "Battery": "3174 mah"],
+        "iPhone XS"         : ["CPU":"A12",
+                               "Freq": "2.49GHz",
+                               "Battery": "2658 mah"],
+        "iPhone X"          : ["CPU":"A11",
+                               "Freq": "1.4GHz",
+                               "Battery": "2716 mah"],
+        
+        "iPhone 8 Plus"     : ["CPU":"A11",
+                               "Freq": "1.4GHz",
+                               "Battery": "2691 mah"],
+        "iPhone 8"          : ["CPU":"A11",
+                               "Freq": "1.4GHz",
+                               "Battery": "1821 mah"],
+        "iPhone 7 Plus"     : ["CPU":"A11",
+                               "Freq": "1.4GHz",
+                               "Battery": "2900 mah"],
+        "iPhone 7"          : ["CPU":"A10",
+                               "Freq": "1.3GHz",
+                               "Battery": "1960 mah"],
+        "iPhone SE"         : ["CPU":"A9",
+                               "Freq": "1.85GHz",
+                               "Battery": "1624 mah"],
+        "iPhone 6s Plus"    : ["CPU":"A9",
+                               "Freq": "1.85GHz",
+                               "Battery": "2750 mah"],
+        "iPhone 6s"         : ["CPU":"A9",
+                               "Freq": "1.85GHz",
+                               "Battery": "1715 mah"],
+    ]
+    
+    private(set) var modelName: String
+    private(set) var cpuName: String?
+    /// CPU频率
+    private(set) var cpuFreq: String?
+    private(set) var batteryCapacity: String?
+    
+    override init() {
+        
+        modelName = UIDevice.current.modelName
+        cpuName = deviceMap[modelName]?["CPU"]
+        cpuFreq = deviceMap[modelName]? ["Freq"]
+        batteryCapacity = deviceMap[modelName]?["Battery"]
+        
+        super.init()
+    }
+}
+
+extension UIDevice {
+    
+    var modelIdentifier: String {
+        var systemInfo = utsname()
+        uname(&systemInfo)
+        
+        let machineMirror = Mirror(reflecting: systemInfo.machine)
+        let identifier = machineMirror.children.reduce("") { (identifier, element) in
+            guard let value = element.value as? Int8, value != 0 else {
+                return identifier
+            }
+            return identifier + String(UnicodeScalar(UInt8(value)))
+        }
+        
+        return identifier
+    }
+    
+    /// 数据来源 https://www.jianshu.com/p/d9068fee295e
+    var modelName: String {
+        
+        let identifier = modelIdentifier
+        
+        switch identifier {
+        case "iPhone8,1":
+            return "iPhone 6s"
+        case "iPhone8,2":
+            return "iPhone 6s Plus"
+        case "iPhone8,4":
+            return "iPhone SE"
+        case "iPhone9,1":
+            return "iPhone 7"; //国行、日版、港行
+        case "iPhone9,2":
+            return "iPhone 7 Plus"; //国行、港行
+        case "iPhone9,3":
+            return "iPhone 7"; //美版、台版
+        case "iPhone9,4":
+            return "iPhone 7 Plus"; //美版、台版
+        case "iPhone10,1":
+            return "iPhone 8"; //国行(A1863)、日行(A1906)
+        case "iPhone10,2":
+            return "iPhone 8 Plus"; //国行(A1864)、日行(A1898)
+        case "iPhone10,3":
+            return "iPhone X"; //国行(A1865)、日行(A1902)
+        case "iPhone10,4":
+            return "iPhone 8"; //美版(Global/A1905)
+        case "iPhone10,5":
+            return "iPhone 8 Plus"; //美版(Global/A1897)
+        case "iPhone10,6":
+            return "iPhone X";//美版(Global/A1901)
+            
+        // 刘海屏(除SE外)
+        case "iPhone11,8":
+            return "iPhone XR"
+        case "iPhone11,2":
+            return "iPhone XS"
+        case "iPhone11,6":
+            return "iPhone XS Max"
+        case "iPhone11,4":
+            return "iPhone XS Max"
+        case "iPhone12,1":
+            return "iPhone 11"
+        case "iPhone12,3":
+            return "iPhone 11 Pro"
+        case "iPhone12,5":
+            return "iPhone 11 Pro Max"
+        case "iPhone12,8":
+            return "iPhone SE2"; //(2nd generation)
+        case "iPhone13,1":
+            return "iPhone 12 mini"
+        case "iPhone13,2":
+            return "iPhone 12"
+        case "iPhone13,3":
+            return "iPhone 12 Pro"
+        case "iPhone13,4":
+            return "iPhone 12 Pro Max"
+        case "iPhone14,2":
+            return "iPhone 13 Pro"
+        case "iPhone14,3":
+            return "iPhone 13 Pro Max"
+        case "iPhone14,4":
+            return "iPhone 13 mini"
+        case "iPhone14,5":
+            return "iPhone 13"
+        case "iPhone14,6":
+            return "iPhone SE3"; //(2nd generation)
+        case "iPhone14,7":
+            return "iPhone 14"
+        case "iPhone14,8":
+            return "iPhone 14 Plus"
+            
+        // 灵动岛
+        case "iPhone15,2":
+            return "iPhone 14 Pro"
+        case "iPhone15,3":
+            return "iPhone 14 Pro Max"
+            
+        case "iPhone16,2":
+            return "iPhone 15 Pro Max"
+        case "iPhone16,1":
+            return "iPhone 15 Pro"
+        case "iPhone15,5":
+            return "iPhone 15 Plus"
+        case "iPhone15,4":
+            return "iPhone 15"
+
+            
+        case "iPhone17,3":
+            return "iPhone 16"
+        case "iPhone17,4":
+            return "iPhone 16 Plus"
+        case "iPhone17,1":
+            return "iPhone 16 Pro"
+        case "iPhone17,2":
+            return "iPhone 16 Pro Max"
+            
+            
+            
+        default:
+            return "--"
+        }
+    }
+    
+    var currentSysVersion: Int {
+        let version = UIDevice.current.systemVersion
+        let v1 = version.components(separatedBy: ".").first ?? "0"
+        let doubleVersion = Double(v1)
+        if let doubleVersion = doubleVersion {
+            return Int(doubleVersion)
+        }
+        return 0
+    }
+    
+    // 版本判断
+    func currentSysVersionEqualOrGreater(than version: String) -> Bool {
+        var sysValues = UIDevice.current.systemVersion.components(separatedBy: ".")
+        var values = version.components(separatedBy: ".")
+        
+        // 位数不同,少的补0
+        let count = max(sysValues.count, values.count)
+        if sysValues.count < count {
+            let more = Array(repeating: "0", count: count-sysValues.count)
+            sysValues.append(contentsOf: more)
+        }
+        if values.count < count {
+            let more = Array(repeating: "0", count: count-values.count)
+            values.append(contentsOf: more)
+        }
+        
+        for idx in 0..<count {
+            if let sv = Int(sysValues.safeObj(At: idx) ?? "0"),
+                let v = Int(values.safeObj(At: idx) ?? "0") {
+                if sv > v {
+                    return true
+                } else if sv < v {
+                    return false
+                }
+            }
+        }
+        return true
+    }
+    
+    var iPhoneXids: [String] {
+        return ["iPhone10,3", "iPhone10,6"]
+    }
+    
+    var iPhoneSEids: [String] {
+        return ["iPhone8,4", "iPhone12,8", "iPhone14,6"]
+    }
+}
+
+// 传感器样式: 无 | 刘海 | 灵动岛
+enum DeviceSensorStyle {
+    case none
+    case bang
+    case island
+}
+
+extension UIDevice {
+    func sensorStyle() -> DeviceSensorStyle {
+#if targetEnvironment(simulator)
+        return .island
+#endif
+        let identifier = UIDevice.current.modelIdentifier
+        // SE
+        if iPhoneSEids.contains(identifier) {
+            return .none
+        }
+        // X
+        if iPhoneXids.contains(identifier) {
+            return .bang
+        }
+        if identifier.hasPrefix("iPhone") {
+            let digital = identifier.replacingOccurrences(of: "iPhone", with: "")
+            let arr = digital.components(separatedBy: ",")
+            if let v1 = arr.safeObj(At: 0),
+               let vv1 = Double(v1) {
+                if vv1 >= 15 {
+                    return .island
+                } else {
+                    if vv1 < 11 {
+                        return .none
+                    }
+                    return .bang
+                }
+            }
+        }
+        return .none
+    }
+    
+    // 刘海屏 及以后设备才可以升级到16.1
+    var supportLiveActivity: Bool {
+        guard #available(iOS 16.1, *) else {
+            return false
+        }
+        let style = sensorStyle()
+        return style != .none
+    }
+    
+    var sensorSize: CGSize {
+        let style = sensorStyle()
+        switch style {
+        case .none:
+            return .zero
+        case .bang:
+            let ratio: CGFloat = UIScreen.main.bounds.width/375.0
+            return CGSize(width: 219*ratio, height: 30*ratio)
+        case .island:
+            return CGSize(width: 125, height: 36.7)//16s 和 16sp 是 126*37.3
+        }
+    }
+    
+    var sensorTop:Double{
+        let kScreenWidth = UIScreen.main.bounds.size.width
+        let kScreenHeight = UIScreen.main.bounds.size.height
+        //16s和 16sp
+        if (kScreenWidth == 440 && kScreenHeight == 956) || (kScreenWidth == 402 && kScreenHeight == 874) ||  modelName.contains("iPhone 16 Pro") {
+            return 14.0
+        } else {
+            return 11.3
+        }
+    }
+}

+ 294 - 0
AIPlayRingtones/AppPage/Common/TSAudioPlayer/TSAudioPlayer.swift

@@ -0,0 +1,294 @@
+//
+//  TSAudioPlayer.swift
+//  Girly
+//
+//  Created by 100Years on 2025/1/9.
+//
+
+import AVFoundation
+
+class TSAudioPlayer: NSObject {
+    private var player: AVPlayer?
+    private var timeObserverToken: Any?
+    var isLooping: Bool = false
+    
+    override init() {
+        super.init()
+    }
+    
+    var isPlaying: Bool {
+//        return player?.rate != 0 && player?.error == nil
+        
+        if let player = player {
+            if #available(iOS 10.0, *) {
+                return player.timeControlStatus == .playing
+            } else {
+                return player.rate > 0
+            }
+        }
+        return false
+    }
+    
+    var duration: Double {
+        if let currentItem = player?.currentItem {
+            return CMTimeGetSeconds(currentItem.asset.duration)
+        }
+        return 0.0
+    }
+    
+    var volume: Float {
+        get {
+            return player?.volume ?? 0.0
+        }
+        set {
+            player?.volume = max(0.0, min(newValue, 1.0))
+        }
+    }
+    
+    var currentTime: Double {
+        if let currentItem = player?.currentItem {
+            return CMTimeGetSeconds(currentItem.currentTime())
+        }
+        return 0.0
+    }
+    
+    var playerUsable: Bool {
+        return player != nil
+    }
+    
+    var currentTimeChanged: ((Double,Double) -> Void)?
+    var audioPlayerDidFinishHandle: ((Bool) -> Void)?
+    
+    /// 初始化播放器
+    /// - Parameter url: 音频文件的 URL
+    init?(url: URL) {
+        super.init()
+        
+        let playerItem = AVPlayerItem(url: url)
+        player = AVPlayer(playerItem: playerItem)
+        
+        // 监听播放完成事件
+        NotificationCenter.default.addObserver(
+            self,
+            selector: #selector(playerDidFinishPlaying),
+            name: .AVPlayerItemDidPlayToEndTime,
+            object: playerItem
+        )
+        
+        // 设置音频会话
+        do {
+            let audioSession = AVAudioSession.sharedInstance()
+            try audioSession.setCategory(.playback)
+            try audioSession.setActive(true)
+        } catch {
+            print("TSAudioPlayer 音频会话设置失败: \(error.localizedDescription)")
+            return nil
+        }
+    }
+    
+    deinit {
+        stop()
+    }
+    
+    /// 开始播放音频
+    func play() {
+        guard let player = player else { return }
+        
+        let outputVolume = AVAudioSession.sharedInstance().outputVolume
+        print("TSAudioPlayer outputVolume: \(outputVolume)")
+        
+        if outputVolume == 0.0 {
+            print("Please turn up the volume".localized)
+        }
+        
+        player.play()
+        
+        // 监听播放进度
+        addTimeObserver()
+    }
+    
+    /// 暂停播放音频
+    func pause() {
+        player?.pause()
+    }
+    
+    /// 停止并销毁播放器
+    func stop() {
+        player?.pause()
+        player?.replaceCurrentItem(with: nil)
+        player = nil
+        removeTimeObserver()
+    }
+    
+    /// 设置是否重复播放
+    /// - Parameter loop: 是否循环播放
+    func setLoop(_ loop: Bool) {
+        isLooping = loop
+    }
+    
+    /// 跳转到指定时间
+    /// - Parameter time: 目标时间(秒)
+    func seek(to time: Double) {
+        if let player = player {
+            let targetTime = CMTimeMakeWithSeconds(time, preferredTimescale: 600)
+            player.seek(to: targetTime)
+        }
+    }
+    
+    /// 监听播放完成
+    @objc private func playerDidFinishPlaying() {
+        if isLooping {
+            seek(to: 0.0)
+            play()
+        }
+        audioPlayerDidFinishHandle?(true)
+    }
+    
+    /// 添加时间观察者
+    private func addTimeObserver() {
+        let interval = CMTime(seconds: 0.1, preferredTimescale: CMTimeScale(NSEC_PER_SEC))
+        timeObserverToken = player?.addPeriodicTimeObserver(forInterval: interval, queue: .main) { [weak self] time in
+            guard let self = self else { return }
+            let currentTime = CMTimeGetSeconds(time)
+            self.currentTimeChanged?(currentTime,duration)
+        }
+    }
+    
+    /// 移除时间观察者
+    private func removeTimeObserver() {
+        if let token = timeObserverToken {
+            player?.removeTimeObserver(token)
+            timeObserverToken = nil
+        }
+    }
+}
+
+//class TSAudioPlayer : NSObject, AVAudioPlayerDelegate{
+//    private var audioPlayer: AVAudioPlayer?
+//    var isLooping: Bool = false
+//    
+//    override init() {
+//        super.init()
+//    }
+//    
+//    var isPlaying:Bool{
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.isPlaying
+//        }
+//        return false
+//    }
+//    
+//    var duration:Double{
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.duration
+//        }
+//        return 0.0
+//    }
+//    
+//    var volume:Float{
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.volume
+//        }
+//        return 0
+//    }
+//    
+//    var currentTime:Double{
+//        if let audioPlayer = audioPlayer {
+//            return audioPlayer.currentTime
+//        }
+//        return 0.0
+//    }
+//    
+//    //播放器是否可用
+//    var playerUsable:Bool {
+//        if audioPlayer != nil  {
+//            return true
+//        }
+//        return false
+//    }
+//
+//    var timer:GCDTimer = GCDTimer()
+//    
+//    var currentTimeChanged:((Double)->Void)?
+//    
+//    /// 初始化播放器
+//    /// - Parameter url: 音频文件的 URL
+//    init?(url: URL) {
+//        super.init()
+//        do {
+//            audioPlayer = try AVAudioPlayer(contentsOf: url)
+//            audioPlayer?.prepareToPlay()
+//            audioPlayer?.delegate = self
+//            let audioSession = AVAudioSession.sharedInstance()
+//            try audioSession.setCategory(.playback) // 设置类别为 playback
+//            try audioSession.setActive(true) // 激活音频会话
+//
+//        } catch {
+//            dePrint("TSAudioPlayer 音频文件加载失败: \(error.localizedDescription)")
+//            return nil
+//        }
+//    }
+//    
+//    /// 开始播放音频
+//    func play() {
+//        guard let audioPlayer = audioPlayer else { return }
+//        let outputVolume = AVAudioSession.sharedInstance().outputVolume
+//        dePrint("TSAudioPlayer outputVolume\(outputVolume)")
+//        
+//        if outputVolume == 0.0 {
+//            TSToastShared.showToast(text: "Please turn up the volume".localized)
+//        }
+//    
+//        audioPlayer.numberOfLoops = isLooping ? -1 : 0
+//        audioPlayer.play()
+//        
+//        timer.start(interval: 0.5, repeats: true) { [weak self]  in
+//            guard let self = self else { return }
+//            
+//            let currentTime = audioPlayer.currentTime
+//            dePrint("TSAudioPlayer Current playback time: \(currentTime) seconds")
+//            currentTimeChanged?(currentTime)
+//          }
+//    }
+//    
+//    /// 暂停播放音频
+//    func pause() {
+//        audioPlayer?.pause()
+//    }
+//    
+//    /// 停止并销毁播放器
+//    func stop() {
+//        audioPlayer?.stop()
+//        audioPlayer = nil
+//        timer.stop()
+//    }
+//    
+//    /// 设置是否重复播放
+//    /// - Parameter loop: 是否循环播放
+//    func setLoop(_ loop: Bool) {
+//        isLooping = loop
+//        audioPlayer?.numberOfLoops = loop ? -1 : 0
+//    }
+//    
+//    /// 设置音量
+//    /// - Parameter volume: 音量大小 (0.0 静音, 1.0 最大)
+//    func setVolume(_ volume: Float) {
+//        audioPlayer?.volume = max(0.0, min(volume, 1.0))
+//    }
+//    
+//    deinit {
+//        stop()
+//    }
+//
+//    var audioPlayerDidFinishHandle:((Bool)->Void)?
+//    // 实现 AVAudioPlayerDelegate 方法
+//    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
+//        if flag {
+//            print("TSAudioPlayer 音频播放完成")
+//            
+//        } else {
+//            print("TSAudioPlayer 音频播放中断")
+//        }
+//        audioPlayerDidFinishHandle?(flag)
+//    }
+//}

+ 337 - 0
AIPlayRingtones/AppPage/Common/TSAudioPlayer/TSBusinessAudioPlayer.swift

@@ -0,0 +1,337 @@
+//
+//  TSBusinessAudioPlayer.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/7.
+//
+
+import AVFoundation
+class TSBusinessAudioPlayer {
+    
+    static let shared = TSBusinessAudioPlayer()
+    
+    enum PlayerState:Equatable {
+        case play
+        case pause
+        case stop
+        case loading(Float)
+        case volume(Float)
+        case currentTime(Double)
+    }
+    
+    private var audioPlayer: TSAudioPlayer?
+    
+    var stateChangedHandle:((PlayerState) -> Void)?
+    var currentTimeChangedHandle:((Double,Double) -> Void)?
+    
+    var currentPlayerState:PlayerState = .stop
+    var duration:Double{
+        if let audioPlayer = audioPlayer {
+            return audioPlayer.duration
+        }
+        return 0.0
+    }
+
+    var isPlaying:Bool{
+        if let audioPlayer = audioPlayer {
+            return audioPlayer.isPlaying
+        }
+        return false
+    }
+    
+    var isLoading:Bool{
+        switch currentPlayerState {
+        case .loading(let float):
+            return float < 1.0 ? true : false
+        default:
+            return false
+        }
+    }
+    
+    var currentTime:Double{
+        if let audioPlayer = audioPlayer {
+            return audioPlayer.currentTime
+        }
+        return 0.0
+    }
+    
+    /// 跳转到指定时间
+    /// - Parameter time: 目标时间(秒)
+    func seek(to time: Double) {
+        audioPlayer?.seek(to: time)
+    }
+    
+    var playProgress:Double{
+        let playProgress = currentTime / duration
+//        dePrint("TSAudioPlayer playProgress = \(playProgress)")
+        return playProgress
+    }
+    
+    //播放器是否可用
+    var playerUsable:Bool {
+        if let audioPlayer = audioPlayer {
+            return audioPlayer.playerUsable
+        }
+        return false
+    }
+    var currentURLString:String = ""
+    var currentLocalURL:URL? = nil
+    var currentIndexPath:IndexPath? = nil
+    
+    //加载音乐可能 2-3 秒有结果,停止加载后播放.
+    private var isStopPlayingAfterLoading:Bool = false
+
+    func isPlayURLString(string:String,localURL:URL? = nil,indexPath:IndexPath? = nil) -> Bool {
+
+        if currentURLString == string {
+            
+            if let currentIndexPath = currentIndexPath,
+               let indexPath = indexPath,
+               indexPath != currentIndexPath
+            {
+                return false
+            }else if let currentLocalURL = currentLocalURL,
+                let localURL = localURL,
+                currentLocalURL != localURL
+             {
+                 return false
+             }else{
+                return true
+            }
+        }
+        return false
+    }
+    
+    func loadLoactionURL(url:URL){
+        self.audioPlayer = TSAudioPlayer(url: url)
+    }
+
+    func playUrlString(_ urlString:String?,localURL:URL? = nil,loop:Bool = false,indexPath:IndexPath? = nil) {
+        self.stop()
+        if let urlString = urlString {
+            
+            self.currentURLString = urlString
+            self.currentLocalURL = localURL
+            self.currentIndexPath = indexPath
+
+            let palyFile:(URL)->Void = { [weak self] url in
+                guard let self = self else { return }
+                debugPrint("TSAudioPlayer 正在播放url:\(currentURLString)")
+                debugPrint("TSAudioPlayer 正在播放path:\(url)")
+                self.audioPlayer = TSAudioPlayer(url: url)
+                self.audioPlayer?.setLoop(loop)
+                
+                if self.audioPlayer?.volume == 0 {
+                    setVolume(volume: 1.0)
+                }
+                
+                self.audioPlayer?.currentTimeChanged = { [weak self] currentTime,duration in
+                    guard let self = self else { return }
+                    currentTimeChangedHandle?(currentTime,duration)
+                    changePlayerState(.currentTime(currentTime))
+                }
+                
+                self.play()
+                dePrint(self.audioPlayer?.duration)
+                
+                self.audioPlayer?.audioPlayerDidFinishHandle = { [weak self] flag in
+                    guard let self = self else { return }
+                    if flag == true, self.audioPlayer?.isLooping == false{
+                        stop()
+                    }
+                }
+            }
+            
+            isStopPlayingAfterLoading = false
+            
+            if let path = self.currentLocalURL,TSFileManagerTool.fileExists(at: path){
+                palyFile(path) //播放
+                
+            }else{
+                self.changePlayerState(.loading(0.0))
+                
+                _ = ASDownloadManager.getDownLoadRing(urlString: urlString, progressHandler: { progress in
+                    dePrint("ASDownloadManager.etDownLoadRing progress = \(progress)")
+                }, complete: {[weak self] url, success in
+                    
+                    guard let self = self else { return }
+                    
+                    self.changePlayerState(.loading(1.0))
+                
+                    if isStopPlayingAfterLoading == true || currentURLString != urlString{
+                        isStopPlayingAfterLoading = false
+                        return
+                    }
+                    
+                    if let url = url {
+                        palyFile(url) //播放
+                    }else{
+                        //暂停
+                        self.stop()
+                    }
+                })
+            }
+        }
+    }
+    
+
+    func play() {
+        self.audioPlayer?.play()
+        changePlayerState(.play)
+    }
+    
+    func stop() {
+        self.audioPlayer?.currentTimeChanged = nil
+        isStopPlayingAfterLoading = true
+        currentURLString = ""
+        self.audioPlayer?.stop()
+        changePlayerState(.stop)
+    }
+    
+    func pause() {
+        isStopPlayingAfterLoading = true
+        self.audioPlayer?.pause()
+        changePlayerState(.pause)
+    }
+    
+    func setVolume(volume:Float){
+        self.audioPlayer?.volume = volume
+        changePlayerState(.volume(volume))
+    }
+    
+
+    func changeAudioSwitch()->Float {
+        let volume:Float = self.audioPlayer?.volume == 0.0 ? 1.0 : 0.0
+        setVolume(volume: volume)
+        return volume
+    }
+    
+    func changePlayerState(_ state:PlayerState){
+
+        if case .currentTime(let time) = state {} else {
+            debugPrint("TSAudioPlayer changePlayerState=\(state)")
+        }
+        currentPlayerState = state
+        kExecuteOnMainThread{
+            self.stateChangedHandle?(state)
+//            NotificationCenter.default.post(name: .kBusinessAudioStateChange, object: nil, userInfo: ["PlayerState": state])
+        }
+    }
+     
+    deinit {
+        dePrint("TSAudioPlayer TSBusinessAudioPlayer deinit")
+    }
+}
+
+
+extension TSBusinessAudioPlayer{
+    struct AudioFileInfo {
+        let sizeInBytes: UInt64?    // 文件大小(字节)
+        let durationInSeconds: Double?  // 音频时长(秒)
+        let songName: String?  // 音频时长(秒)
+    }
+
+    static func getAudioFileInfo(path: String) -> AudioFileInfo? {
+        // 1. 检查URL有效性
+        guard let url = URL(string: path) else {
+            print("getAudioFileInfo 无效的URL字符串")
+            return nil
+        }
+        
+        // 2. 检查文件是否存在(仅限本地文件)
+        guard FileManager.default.fileExists(atPath: url.path) else {
+            print("getAudioFileInfo 文件不存在或不是本地路径")
+            return nil
+        }
+        
+        // 3. 获取文件大小
+        let fileSize: UInt64? = {
+            do {
+                let attributes = try FileManager.default.attributesOfItem(atPath: url.path)
+                return attributes[.size] as? UInt64
+            } catch {
+                print("获取文件大小失败: \(error.localizedDescription)")
+                return nil
+            }
+        }()
+        
+        // 4. 获取音频时长
+        let duration: Double? = {
+            return getAudioDurationWithAudioFile(url: url)
+        }()
+        
+        // 5. 获取音频名称
+        let songName: String? = {
+            return getSongNameFromLocalFile(fileURL: url)
+        }()
+        
+        return AudioFileInfo(sizeInBytes: fileSize, durationInSeconds: duration,songName: songName)
+    }
+    
+    /// 同步获取音频时长(可能阻塞线程!)
+    /// 使用 AudioFile 同步获取音频时长
+    static func getAudioDurationWithAudioFile(url: URL) -> TimeInterval? {
+        var audioFile: AudioFileID?
+        let status = AudioFileOpenURL(url as CFURL, .readPermission, 0, &audioFile)
+        
+        guard status == noErr, let file = audioFile else {
+            print("⚠️ 打开音频文件失败: \(status)")
+            return nil
+        }
+        
+        // 获取音频时长(单位:秒)
+        var duration: Float64 = 0
+        var propertySize = UInt32(MemoryLayout.size(ofValue: duration))
+        let durationStatus = AudioFileGetProperty(
+            file,
+            kAudioFilePropertyEstimatedDuration,
+            &propertySize,
+            &duration
+        )
+        
+        AudioFileClose(file)
+        
+        return durationStatus == noErr ? duration : nil
+    }
+    
+    //获取音频的名称
+    static func getSongNameFromLocalFile(fileURL: URL) -> String? {
+        // 1. 检查文件是否存在
+        guard FileManager.default.fileExists(atPath: fileURL.path) else {
+            print("文件不存在")
+            return nil
+        }
+        
+        // 2. 创建 AVAsset 对象(代表音频文件)
+        let asset = AVAsset(url: fileURL)
+        
+        // 3. 同步读取元数据(适用于本地文件)
+        var songName: String? = nil
+        let metadataFormats = asset.availableMetadataFormats
+        
+        for format in metadataFormats {
+            let metadata = asset.metadata(forFormat: format)
+            
+            // 4. 遍历元数据项,查找歌曲标题
+            for item in metadata {
+                if item.commonKey == .commonKeyTitle, // 标准键:标题
+                   let value = item.value as? String { // 确保值是字符串
+                    songName = value
+                    break
+                }
+                
+                // 额外检查 ID3 标签(某些 MP3 文件可能用非标准键)
+                if item.key as? String == "TIT2", // ID3v2 标题键
+                   let value = item.value as? String {
+                    songName = value
+                    break
+                }
+            }
+            
+            if songName != nil { break }
+        }
+        
+        // 5. 返回结果(若未找到,则尝试从文件名推断)
+        return songName ?? fileURL.deletingPathExtension().lastPathComponent
+    }
+}

+ 26 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/AudioConverter.h

@@ -0,0 +1,26 @@
+//
+//  AudioConverter.h
+//  ContactPoster
+//
+//  Created by TSYH on 2024/1/25.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^ConvertCompletionHandler) (NSString *__nullable, NSString *__nullable);
+
+@interface AudioConverter : NSObject
+
++ (void)convenrtToMp3WithResult:(NSString *)originalPath
+                        outPath:(NSString *)outPath
+                     completion:(ConvertCompletionHandler)completion;
+
++ (void)convertM4aToWav:(NSString *)originalPath
+                outPath:(NSString *)outPath
+              compltion:(ConvertCompletionHandler)compltion;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 142 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/AudioConverter.m

@@ -0,0 +1,142 @@
+//
+//  AudioConverter.m
+//  ContactPoster
+//
+//  Created by TSYH on 2024/1/25.
+//
+
+#import "AudioConverter.h"
+#import "lame.h"
+#import <AVFoundation/AVFoundation.h>
+
+@implementation AudioConverter
+// 转换为mp3
++ (void)convenrtToMp3WithResult:(NSString *)originalPath
+                        outPath:(NSString *)outPath
+                     completion:(ConvertCompletionHandler)completion {
+    
+    [[NSFileManager defaultManager] removeItemAtPath:outPath error:nil];
+  
+    @try {
+        int read, write;
+        
+        FILE *pcm = fopen([originalPath cStringUsingEncoding:1], "rb");//被转换的文件
+        fseek(pcm, 4*1024, SEEK_CUR);                                   //skip file header
+        FILE *mp3 = fopen([outPath cStringUsingEncoding:1], "wb");//转换后文件的存放位置
+        
+        const int PCM_SIZE = 8192;
+        const int MP3_SIZE = 8192;
+        short int pcm_buffer[PCM_SIZE*2];
+        unsigned char mp3_buffer[MP3_SIZE];
+        
+        lame_t lame = lame_init();
+        lame_set_num_channels (lame, 2 ); // 设置 1 为单通道,默认为 2 双通道
+        lame_set_in_samplerate(lame, 44100);//
+        lame_set_brate (lame, 8);
+        lame_set_mode (lame, 3);
+        lame_set_VBR(lame, vbr_default);
+        lame_set_quality (lame, 2); /* 2=high  5 = medium  7=low 音 质 */
+        lame_init_params(lame);
+        
+        do {
+            read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
+            if (read == 0)
+                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
+            else
+                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
+            
+            fwrite(mp3_buffer, write, 1, mp3);
+            
+        } while (read != 0);
+        
+        lame_close(lame);
+        fclose(mp3);
+        fclose(pcm);
+    }
+    @catch (NSException *exception) {
+        // NSLog(@"%@",[exception description]);
+        completion(nil, exception.reason);
+    }
+    @finally {
+        completion(outPath, nil);
+    }
+}
+
++ (void)convertM4aToWav:(NSString *)originalPath
+                outPath:(NSString *)outPath
+              compltion:(ConvertCompletionHandler)compltion {
+    if ([[NSFileManager defaultManager] fileExistsAtPath:outPath]) {
+        NSError *error;
+        [[NSFileManager defaultManager] removeItemAtPath:outPath error:&error];
+    }
+    NSURL *originalUrl = [NSURL fileURLWithPath:originalPath];
+    NSURL *outPutUrl = [NSURL fileURLWithPath:outPath];
+    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL:originalUrl options:nil];    //读取原始文件信息
+    NSError *error = nil;
+    AVAssetReader *assetReader = [AVAssetReader assetReaderWithAsset:songAsset error:&error];
+    if (error) {
+        NSLog (@"error: %@", error);
+        compltion(nil, error.description);
+        return;
+    }
+    AVAssetReaderOutput *assetReaderOutput = [AVAssetReaderAudioMixOutput                                                assetReaderAudioMixOutputWithAudioTracks:songAsset.tracks                                                audioSettings: nil];
+    if (![assetReader canAddOutput:assetReaderOutput]) {
+        NSLog (@"can't add reader output... die!");
+        compltion(nil, @"can't add reader output... die!");
+        return;
+    }
+    [assetReader addOutput:assetReaderOutput];
+    
+    AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:outPutUrl                                                            fileType:AVFileTypeCoreAudioFormat error:&error];
+    if (error) {
+        NSLog (@"error: %@", error);
+        compltion(nil, error.description);
+        return;
+    }
+    AudioChannelLayout channelLayout;
+    memset(&channelLayout, 0, sizeof(AudioChannelLayout));
+    channelLayout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
+    
+    /** 配置音频参数 */
+    NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:
+                                    [NSNumber numberWithInt:kAudioFormatLinearPCM], AVFormatIDKey,                                     [NSNumber numberWithFloat:44100.0], AVSampleRateKey,                                     [NSNumber numberWithInt:2], AVNumberOfChannelsKey,                                     [NSData dataWithBytes:&channelLayout length:sizeof(AudioChannelLayout)], AVChannelLayoutKey,[NSNumber numberWithInt:16], AVLinearPCMBitDepthKey,                                     [NSNumber numberWithBool:NO], AVLinearPCMIsNonInterleaved,                                     [NSNumber numberWithBool:NO],AVLinearPCMIsFloatKey,                                     [NSNumber numberWithBool:NO], AVLinearPCMIsBigEndianKey,                                    nil];
+    AVAssetWriterInput *assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:outputSettings];
+    if ([assetWriter canAddInput:assetWriterInput]) {
+        [assetWriter addInput:assetWriterInput];
+    } else {
+        NSLog (@"can't add asset writer input... die!");
+        compltion(nil, @"can't add asset writer input... die!");
+        return;
+    }
+    assetWriterInput.expectsMediaDataInRealTime = NO;
+    [assetWriter startWriting];
+    [assetReader startReading];
+    AVAssetTrack *soundTrack = [songAsset.tracks objectAtIndex:0];
+    CMTime startTime = CMTimeMake (0, soundTrack.naturalTimeScale);
+    [assetWriter startSessionAtSourceTime:startTime];
+    __block UInt64 convertedByteCount = 0;
+    dispatch_queue_t mediaInputQueue = dispatch_queue_create("mediaInputQueue", NULL);
+    [assetWriterInput requestMediaDataWhenReadyOnQueue:mediaInputQueue  usingBlock: ^      {
+        while (assetWriterInput.readyForMoreMediaData) {
+            CMSampleBufferRef nextBuffer = [assetReaderOutput copyNextSampleBuffer];
+            if (nextBuffer) {
+                // append buffer
+                [assetWriterInput appendSampleBuffer: nextBuffer];
+                convertedByteCount += CMSampleBufferGetTotalSampleSize (nextBuffer);
+            } else {
+                [assetWriterInput markAsFinished];
+                [assetWriter finishWritingWithCompletionHandler:^{
+                }];
+                [assetReader cancelReading];
+                
+                NSDictionary *outputFileAttributes = [[NSFileManager defaultManager]                                                        attributesOfItemAtPath:[outPutUrl path]                                                        error:nil];
+                NSLog (@"FlyElephant %lld",[outputFileAttributes fileSize]);
+                
+                compltion(outPath, nil);
+                break;
+            }
+        }
+    }];
+}
+
+@end

+ 48 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/AudioTool.swift

@@ -0,0 +1,48 @@
+//
+//  AudioTool.swift
+//  ContactPoster
+//
+//  Created by TSYH on 2024/1/24.
+//
+
+import AVFoundation
+typealias AudioCompletionHandler = (URL?, String?) -> Void
+
+class AudioTool {
+
+    /// 创建用于分享库乐队的band文件
+    func convertToBand(from fileURL: URL, to filePath: String,
+                       bandFileURL: URL,
+                       completion: ((URL?) -> Void)?) {
+        
+        let copyBandURL = URL(fileURLWithPath: filePath).deletingPathExtension().appendingPathExtension("band")
+        // 步骤3:复制band文件
+        try? FileManager.default.copyItem(atPath: bandFileURL.path, toPath: copyBandURL.path)
+        
+        guard FileManager.default.fileExists(atPath: copyBandURL.path) else {
+            // 复制失败
+            completion?(nil)
+            return
+        }
+        
+        // 步骤4:格式转换为aiff
+        let converter = ExtAudioConverter()
+        converter.inputFile = fileURL.path
+        converter.outputFile = copyBandURL.path.appending("/Media/ringtone.aiff")
+        converter.outputFileType = kAudioFileAIFFType
+        let success = converter.convert()
+        
+        guard success,
+              FileManager.default.fileExists(atPath: copyBandURL.path) else {
+            // 转换失败
+            completion?(nil)
+            return
+        }
+        
+        completion?(copyBandURL)
+        debugPrint("===bandPath: \(copyBandURL)")
+    }
+    
+
+
+}

+ 248 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/TSBandRingTool.swift

@@ -0,0 +1,248 @@
+//
+//  TSBandRingTool.swift
+//  AIRingtone
+//
+//  Created by 100Years on 2025/3/4.
+//
+import AVKit
+import AVFoundation
+class TSBandRingTool:NSObject {
+    static var shared = TSBandRingTool()
+    private var tutorialPlayer: AVPlayer?
+    private var pictureController: AVPictureInPictureController?
+    private lazy var playContentView = UIView(frame: UIScreen.main.bounds)
+    private lazy var audioConvertTool = AudioTool()
+    
+    lazy var ringLoadingView: ASRingLoadingView = {
+        let ringLoadingView = ASRingLoadingView(frame: CGRectMake(0, 0, k_ScreenWidth, k_ScreenHeight))
+        return ringLoadingView
+    }()
+    weak var targetVC:UIViewController?
+
+    static func creatBandRingTool() -> TSBandRingTool{
+        TSBandRingTool.shared = TSBandRingTool()
+        return TSBandRingTool.shared
+    }
+    
+    deinit {
+        dePrint("TSBandRingTool deinit")
+    }
+    func checkGarageBandInstallation() -> Bool {
+        // GarageBand 的 URL Scheme
+        let garageBandScheme = "garageband://"
+
+        if let url = URL(string: garageBandScheme), UIApplication.shared.canOpenURL(url) {
+            print("GarageBand 已安装")
+            return true
+        } else {
+            let ac = UIAlertController(title: nil,
+                                       message: "GarageBand is not installed, you need to install it.", preferredStyle: .alert)
+            ac.addAction(UIAlertAction(title: "Cancel", style: .cancel))
+            ac.addAction(UIAlertAction(title: "Download", style: .default, handler: { _ in
+                // GarageBand 在 App Store 的链接
+                let garageBandAppStoreURL = URL(string: "https://apps.apple.com/app/id408709785")!
+                if UIApplication.shared.canOpenURL(garageBandAppStoreURL) {
+                    UIApplication.shared.open(garageBandAppStoreURL, options: [:], completionHandler: nil)
+                }
+            }))
+            targetVC?.present(ac, animated: true)
+          
+            return false
+        }
+    }
+    
+    func shareBandVC(vc:UIViewController,
+                     fileURL: URL,
+                   fileName:String?,
+                   completion: ((Bool) -> Void)? = nil) {
+        self.targetVC = vc
+
+        if checkGarageBandInstallation() == false {
+            completion?(false)
+            return
+        }
+        if TSFileManagerTool.fileExists(at: fileURL) == false{
+            completion?(false)
+            return
+        }
+
+        self.createBand(with: fileURL, fileName: fileName) { [weak self]  bandURL in
+            guard let self = self else { return }
+            if let url = bandURL {
+                completion?(true)
+                self.shareRing(fileUrl: url)
+            }else{
+                completion?(false)
+                dePrint("Failed to set, please try another")
+            }
+        }
+    }
+    
+    // 创建用于分享库乐队的band文件
+    func createBand(with fileURL: URL?, fileName: String?,
+                    completion: ((URL?) -> Void)?) {
+        let fileName = fileName ?? "Ringtone"
+        guard let fileURL = fileURL,
+              let bandPath = Self.bandPlacefolder,
+              let directory = Self.ringDirectory else {
+            completion?(nil)
+            return
+        }
+        
+        let bandURL = URL(fileURLWithPath: bandPath)
+        let outputURL = URL(fileURLWithPath: directory).appendingPathComponent(fileName)
+        
+        audioConvertTool.convertToBand(from: fileURL, to: outputURL.path, bandFileURL: bandURL) { shareBandURL in
+            completion?(shareBandURL)
+        }
+    }
+    
+    func shareRing(fileUrl: URL) {
+        DispatchQueue.main.async {
+            guard let targetVC = self.targetVC else { return }
+            
+            self.showTutorialVideo()
+            
+            let vc = UIActivityViewController(activityItems: [fileUrl], applicationActivities: nil)
+            targetVC.present(vc, animated: true, completion: {
+                self.tryStartPictureInPicture()
+            })
+            
+            // 延迟检查是否真正弹出
+            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
+                if self.targetVC?.presentedViewController != vc {
+                    dePrint("⚠️ present 失败:系统未正确响应")
+                    // 这里可以触发回调或通知
+                    self.playContentView.removeFromSuperview()
+                }
+            }
+        }
+    }
+    
+}
+
+extension TSBandRingTool : AVPlayerViewControllerDelegate, AVPictureInPictureControllerDelegate {
+    
+    func tryStartPictureInPicture() {
+        guard let player = tutorialPlayer else {
+            return
+        }
+        if player.status == .readyToPlay {
+            self.pictureController?.startPictureInPicture()
+            tutorialPlayer?.play()
+            return
+        }
+        DispatchQueue.main.asyncAfter(deadline: .now()+0.1) {
+            self.tryStartPictureInPicture()
+        }
+    }
+    
+    func showTutorialVideo() {
+        guard let url = Bundle.main.url(forResource: "tutorial-ring", withExtension: "mp4") else {
+            return
+        }
+        guard AVPictureInPictureController.isPictureInPictureSupported() else {
+            return
+        }
+        do {
+            try AVAudioSession.sharedInstance().setCategory(.playback, options: .mixWithOthers)
+        } catch {
+            
+        }
+        
+        let playerItem = AVPlayerItem(asset: AVAsset(url: url))
+        if tutorialPlayer == nil {
+            tutorialPlayer = AVPlayer(playerItem: playerItem)
+        } else {
+            tutorialPlayer?.replaceCurrentItem(with: playerItem)
+        }
+        tutorialPlayer?.allowsExternalPlayback = true
+//        playContentView.backgroundColor = .black.withAlphaComponent(0.1)
+        targetVC?.view.addSubview(playContentView)
+        
+        let layer = AVPlayerLayer(player: tutorialPlayer)
+        layer.frame = CGRect(x: 0, y: 0, width: 1, height: 1)
+//        layer.backgroundColor = UIColor.yellow.cgColor
+        playContentView.layer.addSublayer(layer)
+
+        let pictureVC = AVPictureInPictureController(playerLayer: layer)
+        pictureVC?.delegate = self
+        pictureController = pictureVC
+        
+    }
+    
+    func pictureInPictureControllerWillStartPictureInPicture(_ pictureInPictureController: AVPictureInPictureController) {
+        playContentView.removeFromSuperview()
+    }
+    
+    func playerViewControllerWillStartPictureInPicture(_ playerViewController: AVPlayerViewController) {
+        
+    }
+    
+    func playerViewControllerShouldAutomaticallyDismissAtPictureInPictureStart(_ playerViewController: AVPlayerViewController) -> Bool {
+        return true
+    }
+    
+    func playerViewController(_ playerViewController: AVPlayerViewController, restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void) {
+        DispatchQueue.main.async {
+            if playerViewController.presentingViewController == nil {
+                self.targetVC?.present(playerViewController, animated: false)
+            }
+            completionHandler(true)
+        }
+    }
+    
+    
+}
+extension TSBandRingTool {
+    
+    static var bandPlacefolder: String? {
+        guard let cacheDirectory = ringDirectory else {
+            return nil
+        }
+        let path = NSString(string: cacheDirectory).appendingPathComponent("placeHolderBand.band")
+        
+        // 步骤1
+        if !FileManager.default.fileExists(atPath: path),
+            let localFile = Bundle.main.path(forResource: "placeholder.band", ofType: nil) {
+            try? FileManager.default.copyItem(atPath: localFile, toPath: path)
+        }
+        return path
+    }
+    
+    // 铃声文件夹
+    static var ringDirectory: String? {
+        guard let documentUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
+            return nil
+        }
+        let ringDirectory = documentUrl.appendingPathComponent("ringDirectory")
+        
+        // 创建文件夹
+        return FileManager.default.getFolder(at: ringDirectory)?.path
+    }
+}
+
+
+extension FileManager {
+    // 获取文件夹,如果不存在,则创建, 返回空则意味着创建失败
+    func getFolder(at url: URL) -> URL? {
+        guard !isFolderExists(at: url) else {
+            return url
+        }
+        do {
+            try createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
+            return url
+        } catch {
+            return nil
+        }
+    }
+    
+    func isFolderExists(at url: URL) -> Bool {
+        var isDirectory: ObjCBool = false
+        if fileExists(atPath: url.path, isDirectory: &isDirectory) && isDirectory.boolValue == true {
+            return true // 文件夹已存在
+        } else {
+            return false // 文件夹不存在或者路径错误
+        }
+    }
+}

+ 55 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHAudioProcessing.swift

@@ -0,0 +1,55 @@
+//
+//  ZHAudioProcessing.swift
+//  ZHWaveform_Example
+//
+//  Created by wow250250 on 2018/1/2.
+//  Copyright © 2018年 wow250250. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+
+struct ZHAudioProcessing {
+    
+    typealias BufferRefSuccessHandler = (NSMutableData) -> Swift.Void
+    typealias BufferRefFailureHandler = (Error?) -> Swift.Void
+    
+    public static func bufferRef(
+        asset: AVAsset,
+        track: AVAssetTrack,
+        success: BufferRefSuccessHandler?,
+        failure: BufferRefFailureHandler?
+        ) {
+        let data = NSMutableData()
+        let dict: [String: Any] = [AVFormatIDKey: kAudioFormatLinearPCM,
+                                   AVLinearPCMIsBigEndianKey: false,
+                                   AVLinearPCMIsFloatKey: false,
+                                   AVLinearPCMBitDepthKey: 16]
+        do {
+            let reader: AVAssetReader = try AVAssetReader(asset: asset)
+            let output: AVAssetReaderTrackOutput = AVAssetReaderTrackOutput(track: track, outputSettings: dict)
+            reader.add(output)
+            reader.startReading()
+            while reader.status == .reading {
+                if let sampleBuffer: CMSampleBuffer = output.copyNextSampleBuffer() {
+                    if let blockBuffer: CMBlockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) {
+                        let length: Int = CMBlockBufferGetDataLength(blockBuffer)
+                        var sampleBytes = [Int16](repeating: Int16(), count: length)
+                        CMBlockBufferCopyDataBytes(blockBuffer, atOffset: 0, dataLength: length, destination: &sampleBytes)
+//                        CMBlockBufferCopyDataBytes(blockBuffer, 0, length, &sampleBytes)
+                        data.append(&sampleBytes, length: length)
+                        CMSampleBufferInvalidate(sampleBuffer)
+                    }
+                }
+            }
+            if reader.status == .completed {
+                print("读取结束")
+                success?(data)
+            } else {
+                failure?(nil)
+            }
+        } catch let err {
+            failure?(err)
+        }
+    }
+}

+ 37 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHCroppedDelegate.swift

@@ -0,0 +1,37 @@
+//
+//  ZHCroppedDelegate.swift
+//  ZHWaveform_Example
+//
+//  Created by wow250250 on 2018/1/2.
+//  Copyright © 2018年 wow250250. All rights reserved.
+//
+
+import UIKit
+
+@objc public protocol ZHCroppedDelegate {
+    /**
+     start cropped
+     */
+    @objc optional func waveformView(startCropped: UIView, progress rate: CGFloat)
+    
+    /**
+     end cropped
+     */
+    @objc optional func waveformView(endCropped: UIView, progress rate: CGFloat)
+    
+    /**
+     will
+     */
+    @objc optional func waveformView(croppedStartDragging cropped: UIView)
+    
+    /**
+     ing
+     */
+    @objc optional func waveformView(croppedDragIn cropped: UIView)
+    
+    /**
+     ed
+     */
+    @objc optional func waveformView(croppedDragFinish cropped: UIView)
+    
+}

+ 36 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHTrackProcessing.swift

@@ -0,0 +1,36 @@
+//
+//  ZHTrackProcessing.swift
+//  ZHWaveform_Example
+//
+//  Created by wow250250 on 2018/1/2.
+//  Copyright © 2018年 wow250250. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+
+struct ZHTrackProcessing {
+    public static func cutAudioData(size: CGSize, recorder data: NSMutableData, scale: CGFloat) -> [CGFloat] {
+        var filteredSamplesMA: [CGFloat] = []
+        let sampleCount = data.length / MemoryLayout<Int>.size
+        let binSize = CGFloat(sampleCount) / (size.width * scale)
+        var i = 0
+        while i < sampleCount {
+            let rangeData = data.subdata(with: NSRange(location: i, length: 1))
+            let item = rangeData.withUnsafeBytes({ (ptr: UnsafePointer<Int>) -> Int in
+                return ptr.pointee
+            })
+            filteredSamplesMA.append(CGFloat(item))
+            i += Int(binSize)
+        }
+        return trackScale(size: size, source: filteredSamplesMA)
+    }
+    
+    private static func trackScale(size: CGSize, source: [CGFloat]) -> [CGFloat] {
+        if let max = source.max() {
+            let k = size.height / max
+            return source.map{ $0 * k }
+        }
+        return source
+    }
+}

+ 311 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHWaveformView.swift

@@ -0,0 +1,311 @@
+//
+//  ZHWaveformView.swift
+//  ZHWaveform_Example
+//
+//  Created by wow250250 on 2018/1/2.
+//  Copyright © 2018年 wow250250. All rights reserved.
+//
+
+import UIKit
+import AVFoundation
+
+public class ZHWaveformView: UIView {
+    
+    /** waves color */
+    public var wavesColor: UIColor = .red {
+        didSet {
+            DispatchQueue.main.async {
+                _ = self.trackLayer.map({ [unowned self] in
+                    $0.strokeColor = self.wavesColor.cgColor
+                })
+            }
+        }
+    }
+    
+    /** Cut off the beginning part color */
+    public var beginningPartColor: UIColor = .gray
+    
+    /** Cut out the end part color */
+    public var endPartColor: UIColor = .gray
+    
+    /** Track Scale normal 0.5, max 1*/
+    public var trackScale: CGFloat = 0.5 {
+        didSet {
+            if let `assetMutableData` = assetMutableData {
+                croppedViewZero()
+                trackProcessingCut = ZHTrackProcessing.cutAudioData(size: self.frame.size, recorder: assetMutableData, scale: trackScale)
+                drawTrack(
+                    with: CGRect(x: (startCroppedView?.bounds.width ?? 0),
+                                 y: 0,
+                                 width: self.frame.width - (startCroppedView?.bounds.width ?? 0) - (endCroppedView?.bounds.width ?? 0),
+                                 height: self.frame.height),
+                    filerSamples: trackProcessingCut ?? []
+                )
+            }
+        }
+    }
+    
+    public weak var croppedDelegate: ZHCroppedDelegate? {
+        didSet { layoutIfNeeded() }
+    }
+    
+    public weak var waveformDelegate: ZHWaveformViewDelegate?
+    
+    private var fileURL: URL
+    
+    private var asset: AVAsset?
+    
+    private var track: AVAssetTrack?
+    
+    private var trackLayer: [CAShapeLayer] = []
+    
+    private var startCroppedView: UIView?
+    
+    private var endCroppedView: UIView?
+    
+    private var leftCorppedCurrentX: CGFloat = 0
+    
+    private var rightCorppedCurrentX: CGFloat = 0
+    
+    private var trackWidth: CGFloat = 0
+    
+    private var startCorppedIndex: Int = 0
+    
+    private var endCorppedIndex: Int = 0
+    
+    private var trackProcessingCut: [CGFloat]?
+    
+    private var assetMutableData: NSMutableData?
+    
+    private(set) var startCroppedRate: CGFloat = 0
+    private(set) var endCroppedRate: CGFloat = 0
+    
+    public init(frame: CGRect, fileURL: URL) {
+        self.fileURL = fileURL
+        super.init(frame: frame)
+        waveformDelegate?.waveformViewStartDrawing?(waveformView: self)
+        backgroundColor = .white
+        
+        let asset = AVAsset(url: fileURL)
+        guard let track = asset.tracks(withMediaType: .audio).first else {
+            return
+        }
+        self.asset = asset
+        self.track = track
+        ZHAudioProcessing.bufferRef(asset: asset, track: track, success: { [unowned self] (data) in
+            self.assetMutableData = data
+            self.trackProcessingCut = ZHTrackProcessing.cutAudioData(size: frame.size, recorder: data, scale: self.trackScale)
+            self.drawTrack(with: CGRect(origin: .zero, size: frame.size), filerSamples: self.trackProcessingCut ?? [])
+            self.waveformDelegate?.waveformViewDrawComplete?(waveformView: self)
+        }) { (error) in
+            assert(true, error?.localizedDescription ?? "Error, AudioProcessing.bufferRef")
+        }
+    }
+    
+    override public func layoutIfNeeded() {
+        super.layoutIfNeeded()
+        if let samples = trackProcessingCut {
+            creatCroppedView()
+            drawTrack(
+                with: CGRect(x: startCroppedView?.bounds.width ?? 0,
+                             y: 0,
+                             width: frame.width - (startCroppedView?.bounds.width ?? 0) - (endCroppedView?.bounds.width ?? 0),
+                             height: frame.height),
+                filerSamples: samples
+            )
+        }
+    }
+    
+    private func drawTrack(with rect: CGRect, filerSamples: [CGFloat]) {
+        _ = trackLayer.map{ $0.removeFromSuperlayer() }
+        trackLayer.removeAll()
+        startCroppedView?.removeFromSuperview()
+        endCroppedView?.removeFromSuperview()
+        // bezier width
+        trackWidth = rect.width / (CGFloat(filerSamples.count - 1) + CGFloat(filerSamples.count))
+        endCorppedIndex = filerSamples.count
+        for t in 0..<filerSamples.count {
+            let layer = CAShapeLayer()
+            layer.frame = CGRect(
+                x: CGFloat(t) * trackWidth * 2 + (startCroppedView?.bounds.width ?? 0),
+                y: 0,
+                width: trackWidth,
+                height: rect.height
+            )
+            layer.lineCap = CAShapeLayerLineCap.butt
+            layer.lineJoin = CAShapeLayerLineJoin.round
+            layer.lineWidth = trackWidth
+            layer.strokeColor = wavesColor.cgColor
+            self.layer.addSublayer(layer)
+            self.trackLayer.append(layer)
+        }
+        
+        for i in 0..<filerSamples.count {
+            let itemLinePath = UIBezierPath()
+            let y: CGFloat = (rect.height - filerSamples[i]) / 2
+            let height: CGFloat = filerSamples[i] + y
+            itemLinePath.move(to: CGPoint(x: 0, y: y))
+            itemLinePath.addLine(to: CGPoint(x: 0, y: height))
+            itemLinePath.close()
+            itemLinePath.lineWidth = trackWidth
+            let itemLayer = trackLayer[i]
+            itemLayer.path = itemLinePath.cgPath
+        }
+        if let l = startCroppedView {
+            addSubview(l)
+        }
+        if let r = endCroppedView {
+            addSubview(r)
+        }
+        
+    }
+    
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+}
+
+extension ZHWaveformView {
+    
+    private func croppedViewZero() {
+        if let leftCropped = startCroppedView {
+            leftCropped.frame = CGRect(x: 0, y: leftCropped.frame.origin.y, width: leftCropped.bounds.width, height: leftCropped.bounds.height)
+        }
+        if let rightCropped = endCroppedView {
+            rightCropped.frame = CGRect(x: bounds.width - rightCropped.bounds.width, y: rightCropped.frame.origin.y, width: rightCropped.bounds.width, height: rightCropped.bounds.height)
+        }
+        
+    }
+    
+    private func creatCroppedView() {
+//        if let leftCropped = croppedDelegate?.waveformView(startCropped: self) {
+//            leftCropped.frame = CGRect(x: 0, y: leftCropped.frame.origin.y, width: leftCropped.bounds.width, height: leftCropped.bounds.height)
+//            leftCorppedCurrentX = 0
+//            let leftPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.leftCroppedPanRecognizer(sender:)))
+//            leftCropped.addGestureRecognizer(leftPanRecognizer)
+//            leftCropped.isUserInteractionEnabled = true
+//            startCroppedView = leftCropped
+//        }
+        
+//        if let rightCropped = croppedDelegate?.waveformView(endCropped: self) {
+//            rightCropped.frame = CGRect(x: bounds.width - rightCropped.bounds.width, y: rightCropped.frame.origin.y, width: rightCropped.bounds.width, height: rightCropped.bounds.height)
+//            rightCorppedCurrentX = bounds.width - rightCropped.bounds.width
+//            let rightPanRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.rightCroppedPanRecognizer(sender:)))
+//            rightCropped.addGestureRecognizer(rightPanRecognizer)
+//            rightCropped.isUserInteractionEnabled = true
+//            endCroppedView = rightCropped
+//        }
+    }
+    
+    @objc private func leftCroppedPanRecognizer(sender: UIPanGestureRecognizer) {
+        let limitMinX: CGFloat = frame.minX
+        let limitMaxX: CGFloat = endCroppedView?.frame.minX ?? bounds.width
+        if sender.state == .began {
+            croppedDelegate?.waveformView?(croppedDragIn: startCroppedView ?? UIView())
+        } else if sender.state == .changed {
+            croppedDelegate?.waveformView?(croppedDragIn: startCroppedView ?? UIView())
+            let newPoint = sender.translation(in: self)
+            var center = startCroppedView?.center
+            center?.x = leftCorppedCurrentX + newPoint.x
+            guard (center?.x ?? 0) > limitMinX && (center?.x ?? 0) < limitMaxX else { return }
+            startCroppedView?.center = center ?? .zero
+        } else if sender.state == .ended || sender.state == .failed {
+            croppedDelegate?.waveformView?(croppedDragFinish: startCroppedView ?? UIView())
+            leftCorppedCurrentX = startCroppedView?.center.x ?? 0
+        }
+        if (startCroppedView?.frame.minX ?? 0) < 0 {
+            var leftFrame = startCroppedView?.frame
+            leftFrame?.origin.x = 0
+            startCroppedView?.frame = leftFrame ?? .zero
+        }
+        
+        if (startCroppedView?.frame.maxX ?? 0) > limitMaxX {
+            var leftFrame = startCroppedView?.frame
+            leftFrame?.origin.x = limitMaxX - (startCroppedView?.bounds.width ?? 0)
+            startCroppedView?.frame = leftFrame ?? .zero
+        } // floorf ceilf
+        let lenght = ceilf(Float((((startCroppedView?.frame.maxX ?? 0) - (startCroppedView?.bounds.width ?? 0)) / trackWidth)))
+        let bzrLenght = ceilf(lenght/2)
+        startCorppedIndex = Int(bzrLenght) > trackLayer.count ? trackLayer.count : Int(bzrLenght)
+        self.croppedWaveform(start: startCorppedIndex, end: endCorppedIndex)
+        let bezierWidth = self.frame.width - (startCroppedView?.frame.width ?? 0) - (endCroppedView?.frame.width ?? 0)
+        croppedDelegate?.waveformView?(startCropped: startCroppedView ?? UIView(), progress: ((startCroppedView?.frame.maxX ?? 0) - 20)/bezierWidth)
+    }
+    
+    func updateLeftCroppedPosition(_ position: CGFloat) {
+        let lenght = ceilf(Float((position / trackWidth)))
+        let bzrLenght = ceilf(lenght/2)
+        startCorppedIndex = Int(bzrLenght) > trackLayer.count ? trackLayer.count : Int(bzrLenght)
+        self.croppedWaveform(start: startCorppedIndex, end: endCorppedIndex)
+        let bezierWidth = self.frame.width
+        self.startCroppedRate = position/bezierWidth
+    }
+    
+    func updateRightCroppedPosition(_ position: CGFloat) {
+        let lenght = ceilf(Float(position / trackWidth))
+        let bzrLenght = floorf(lenght/2) < 0 ? 0 : ceilf(lenght/2)
+        endCorppedIndex = Int(bzrLenght)
+        self.croppedWaveform(start: startCorppedIndex, end: endCorppedIndex)
+        let bezierWidth = self.frame.width
+        self.endCroppedRate = position/bezierWidth
+    }
+    
+    @objc private func rightCroppedPanRecognizer(sender: UIPanGestureRecognizer) {
+        let limitMinX: CGFloat = startCroppedView?.frame.maxX ?? 0
+        let limitMaxX: CGFloat = frame.maxX
+        if sender.state == .began {
+            croppedDelegate?.waveformView?(croppedStartDragging: endCroppedView ?? UIView())
+        } else if sender.state == .changed {
+            croppedDelegate?.waveformView?(croppedDragIn: endCroppedView ?? UIView())
+            let newPoint = sender.translation(in: self)
+            var center = endCroppedView?.center
+            center?.x = rightCorppedCurrentX + newPoint.x
+            guard (center?.x ?? 0) > limitMinX && (center?.x ?? 0) < limitMaxX else { return }
+            endCroppedView?.center = center ?? .zero
+        } else if sender.state == .ended || sender.state == .failed {
+            croppedDelegate?.waveformView?(croppedDragFinish: endCroppedView ?? UIView())
+            rightCorppedCurrentX = endCroppedView?.center.x ?? (bounds.width - (endCroppedView?.bounds.width ?? 0))
+        }
+        if (endCroppedView?.frame.maxX ?? 0) > frame.maxX {
+            var rightFrame = endCroppedView?.frame
+            rightFrame?.origin.x = frame.maxX - (endCroppedView?.bounds.width ?? 0)
+            endCroppedView?.frame = rightFrame ?? .zero
+        }
+        if (endCroppedView?.frame.minX ?? 0) < limitMinX {
+            var rightFrame = endCroppedView?.frame
+            rightFrame?.origin.x = limitMinX
+            endCroppedView?.frame = rightFrame ?? .zero
+        }
+        let lenght = ceilf(Float(((endCroppedView?.frame.minX ?? 0) - (startCroppedView?.bounds.width ?? 0)) / trackWidth))
+        let bzrLenght = floorf(lenght/2) < 0 ? 0 : ceilf(lenght/2)
+        endCorppedIndex = Int(bzrLenght)
+        self.croppedWaveform(start: startCorppedIndex, end: endCorppedIndex)
+        let bezierWidth = self.frame.width - (startCroppedView?.frame.width ?? 0) - (endCroppedView?.frame.width ?? 0)
+        croppedDelegate?.waveformView?(endCropped: endCroppedView ?? UIView(), progress: ((endCroppedView?.frame.minX ?? 0)-20)/bezierWidth)
+    }
+    
+    typealias TrackIndex = Int
+    
+    func croppedWaveform(start: TrackIndex, end: TrackIndex) {
+        guard start > 0, start < trackLayer.count,
+              end > start, end <= trackLayer.count else {
+            return
+        }
+        let beginLayers = trackLayer[0..<start]
+        let wavesLayers = trackLayer[start..<end]
+        let endLayers = trackLayer[end..<trackLayer.count]
+        DispatchQueue.main.async {
+            _ = beginLayers.map({ [unowned self] in
+                $0.strokeColor = self.beginningPartColor.cgColor
+            })
+            _ = wavesLayers.map({ [unowned self] in
+                $0.strokeColor = self.wavesColor.cgColor
+            })
+            _ = endLayers.map({ [unowned self] in
+                $0.strokeColor = self.endPartColor.cgColor
+            })
+        }
+    }
+    
+}

+ 19 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/ZHWaveform/ZHWaveformViewDelegate.swift

@@ -0,0 +1,19 @@
+//
+//  ZHWaveformViewDelegate.swift
+//  ZHWaveform_Example
+//
+//  Created by wow250250 on 2018/1/2.
+//  Copyright © 2018年 wow250250. All rights reserved.
+//
+
+import UIKit
+
+@objc public protocol ZHWaveformViewDelegate {
+    
+    // start
+    @objc optional func waveformViewStartDrawing(waveformView: ZHWaveformView)
+    
+    // complete
+    @objc optional func waveformViewDrawComplete(waveformView: ZHWaveformView)
+    
+}

+ 37 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/ExtAudioConverter.h

@@ -0,0 +1,37 @@
+//
+//  ExtAudioConverter.h
+//  ExtAudioConverter
+//
+//  Created by 李 行 on 15/4/9.
+//  Copyright (c) 2015年 lixing123.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <AudioToolbox/AudioToolbox.h>
+
+enum BitDepth{
+    BitDepth_8  = 8,
+    BitDepth_16 = 16,
+    BitDepth_24 = 24,
+    BitDepth_32 = 32
+};
+
+//TODO:Add delegate
+
+@interface ExtAudioConverter : NSObject
+
+//Must set
+@property(nonatomic,retain)NSString* inputFile;//Absolute path
+@property(nonatomic,retain)NSString* outputFile;//Absolute path
+
+//optional
+@property(nonatomic,assign)int outputSampleRate;//Default 44100.0
+@property(nonatomic,assign)int outputNumberChannels;//Default 2
+@property(nonatomic,assign)enum BitDepth outputBitDepth;//Default BitDepth_16
+@property(nonatomic,assign)AudioFormatID outputFormatID;//Default Linear PCM
+@property(nonatomic,assign)AudioFileTypeID outputFileType;//Default kAudioFileCAFType
+//TODO:add bit rate parameter
+
+-(BOOL)convert;
+
+@end

+ 446 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/ExtAudioConverter.m

@@ -0,0 +1,446 @@
+//
+//  ExtAudioConverter.m
+//  ExtAudioConverter
+//
+//  Created by 李 行 on 15/4/9.
+//  Copyright (c) 2015年 lixing123.com. All rights reserved.
+//
+
+#import "ExtAudioConverter.h"
+#import "lame.h"
+
+typedef struct ExtAudioConverterSettings{
+    AudioStreamBasicDescription   inputPCMFormat;
+    AudioStreamBasicDescription   outputFormat;
+    
+    ExtAudioFileRef               inputFile;
+    CFStringRef                   outputFilePath;
+    ExtAudioFileRef               outputFile;
+    
+    AudioStreamPacketDescription* inputPacketDescriptions;
+}ExtAudioConverterSettings;
+
+static BOOL CheckError(OSStatus error, const char *operation)
+{
+    if (error == noErr) return YES;
+    char errorString[20];
+    // See if it appears to be a 4-char-code
+    *(UInt32 *)(errorString + 1) = CFSwapInt32HostToBig(error);
+    if (isprint(errorString[1]) && isprint(errorString[2]) &&
+        isprint(errorString[3]) && isprint(errorString[4])) {
+        errorString[0] = errorString[5] = '\'';
+        errorString[6] = '\0';
+        return YES;
+    } else {
+        // No, format it as an integer
+        sprintf(errorString, "%d", (int)error);
+        fprintf(stderr, "Error: %s (%s)\n", operation, errorString);
+        return NO;
+    }
+}
+
+BOOL startConvert(ExtAudioConverterSettings* settings) {
+    //Determine the proper buffer size and calculate number of packets per buffer
+    //for CBR and VBR format
+    UInt32 sizePerBuffer = 32*1024;//32KB is a good starting point
+    UInt32 framesPerBuffer = sizePerBuffer/sizeof(SInt16);
+    
+    // allocate destination buffer
+    SInt16 *outputBuffer = (SInt16 *)malloc(sizeof(SInt16) * sizePerBuffer);
+    
+    while (1) {
+        AudioBufferList outputBufferList;
+        outputBufferList.mNumberBuffers              = 1;
+        outputBufferList.mBuffers[0].mNumberChannels = settings->outputFormat.mChannelsPerFrame;
+        outputBufferList.mBuffers[0].mDataByteSize   = sizePerBuffer;
+        outputBufferList.mBuffers[0].mData           = outputBuffer;
+        
+        UInt32 framesCount = framesPerBuffer;
+        
+        if (!CheckError(ExtAudioFileRead(settings->inputFile,
+                                    &framesCount,
+                                    &outputBufferList),
+                        "ExtAudioFileRead failed")) {
+            return NO;
+        }
+        
+        if (framesCount==0) {
+            printf("Done reading from input file\n");
+            return YES;
+        }
+        
+        if (!CheckError(ExtAudioFileWrite(settings->outputFile,
+                                     framesCount,
+                                     &outputBufferList),
+                        "ExtAudioFileWrite failed")) {
+            return NO;
+        }
+    }
+}
+
+void startConvertMP3(ExtAudioConverterSettings* settings){
+    //Init lame and set parameters
+    lame_t lame = lame_init();
+    lame_set_in_samplerate(lame, settings->inputPCMFormat.mSampleRate);
+    lame_set_num_channels(lame, settings->inputPCMFormat.mChannelsPerFrame);
+    lame_set_VBR(lame, vbr_default);
+    lame_init_params(lame);
+    
+    NSString* outputFilePath = (__bridge NSString*)settings->outputFilePath;
+    FILE* outputFile = fopen([outputFilePath cStringUsingEncoding:1], "wb");
+    
+    UInt32 sizePerBuffer = 32*1024;
+    UInt32 framesPerBuffer = sizePerBuffer/sizeof(SInt16);
+    
+    int write;
+    
+    // allocate destination buffer
+    SInt16 *outputBuffer = (SInt16 *)malloc(sizeof(SInt16) * sizePerBuffer);
+    
+    while (1) {
+        AudioBufferList outputBufferList;
+        outputBufferList.mNumberBuffers              = 1;
+        outputBufferList.mBuffers[0].mNumberChannels = settings->outputFormat.mChannelsPerFrame;
+        outputBufferList.mBuffers[0].mDataByteSize   = sizePerBuffer;
+        outputBufferList.mBuffers[0].mData           = outputBuffer;
+        
+        UInt32 framesCount = framesPerBuffer;
+        
+        CheckError(ExtAudioFileRead(settings->inputFile,
+                                    &framesCount,
+                                    &outputBufferList),
+                   "ExtAudioFileRead failed");
+        
+        SInt16 pcm_buffer[framesCount];
+        unsigned char mp3_buffer[framesCount];
+        memcpy(pcm_buffer,
+               outputBufferList.mBuffers[0].mData,
+               framesCount);
+        if (framesCount==0) {
+            printf("Done reading from input file\n");
+            //TODO:Add lame_encode_flush for end of file
+            return;
+        }
+        
+        //the 3rd parameter means number of samples per channel, not number of sample in pcm_buffer
+        write = lame_encode_buffer_interleaved(lame,
+                                               outputBufferList.mBuffers[0].mData,
+                                               framesCount,
+                                               mp3_buffer,
+                                               0);
+        size_t result = fwrite(mp3_buffer,
+                               1,
+                               write,
+                               outputFile);
+    }
+}
+
+@implementation ExtAudioConverter
+
+@synthesize inputFile;
+@synthesize outputFile;
+@synthesize outputSampleRate;
+@synthesize outputNumberChannels;
+@synthesize outputBitDepth;
+
+
+- (BOOL)convert {
+    ExtAudioConverterSettings settings = {0};
+    
+    //Check if source file or output file is null
+    if (self.inputFile==NULL) {
+        NSLog(@"Source file is not set");
+        return NO;
+    }
+    
+    if (self.outputFile==NULL) {
+        NSLog(@"Output file is no set");
+        return NO;
+    }
+    
+    //Create ExtAudioFileRef
+    NSURL* sourceURL = [NSURL fileURLWithPath:self.inputFile];
+    if (!CheckError(ExtAudioFileOpenURL((__bridge CFURLRef)sourceURL,
+                                   &settings.inputFile),
+                   "ExtAudioFileOpenURL failed")) {
+        return NO;
+    }
+    
+    if (![self validateInput:&settings]) {
+        return NO;
+    }
+    
+    settings.outputFormat.mSampleRate       = self.outputSampleRate;
+    settings.outputFormat.mBitsPerChannel   = self.outputBitDepth;
+    if (self.outputFormatID==kAudioFormatMPEG4AAC) {
+        settings.outputFormat.mBitsPerChannel = 0;
+    }
+    settings.outputFormat.mChannelsPerFrame = self.outputNumberChannels;
+    settings.outputFormat.mFormatID         = self.outputFormatID;
+    
+    if (self.outputFormatID==kAudioFormatLinearPCM) {
+        settings.outputFormat.mBytesPerFrame   = settings.outputFormat.mChannelsPerFrame * settings.outputFormat.mBitsPerChannel/8;
+        settings.outputFormat.mBytesPerPacket  = settings.outputFormat.mBytesPerFrame;
+        settings.outputFormat.mFramesPerPacket = 1;
+        settings.outputFormat.mFormatFlags     = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
+        //some file type only support big-endian
+        if (self.outputFileType==kAudioFileAIFFType || self.outputFileType==kAudioFileSoundDesigner2Type || self.outputFileType==kAudioFileAIFCType || self.outputFileType==kAudioFileNextType) {
+            settings.outputFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian;
+        }
+    }else{
+        UInt32 size = sizeof(settings.outputFormat);
+        if (!CheckError(AudioFormatGetProperty(kAudioFormatProperty_FormatInfo,
+                                          0,
+                                          NULL,
+                                          &size,
+                                          &settings.outputFormat),
+                        "AudioFormatGetProperty kAudioFormatProperty_FormatInfo failed")) {
+            return NO;
+        }
+    }
+    NSLog(@"output format:%@",[self descriptionForAudioFormat:settings.outputFormat]);
+    
+    //Create output file
+    //if output file path is invalid, this returns an error with 'wht?'
+    NSURL* outputURL = [NSURL fileURLWithPath:self.outputFile];
+    
+    //create output file
+    settings.outputFilePath = (__bridge CFStringRef)(self.outputFile);
+    if (settings.outputFormat.mFormatID!=kAudioFormatMPEGLayer3) {
+        if (!CheckError(ExtAudioFileCreateWithURL((__bridge CFURLRef)outputURL,
+                                             self.outputFileType,
+                                             &settings.outputFormat,
+                                             NULL,
+                                             kAudioFileFlags_EraseFile,
+                                             &settings.outputFile),
+                        "Create output file failed, the output file type and output format pair may not match")) {
+            return NO;
+        }
+    }
+    
+    //Set input file's client data format
+    //Must be PCM, thus as we say, "when you convert data, I want to receive PCM format"
+    if (settings.outputFormat.mFormatID==kAudioFormatLinearPCM) {
+        settings.inputPCMFormat = settings.outputFormat;
+    }else{
+        settings.inputPCMFormat.mFormatID = kAudioFormatLinearPCM;
+        settings.inputPCMFormat.mSampleRate = settings.outputFormat.mSampleRate;
+        //TODO:set format flags for both OS X and iOS, for all versions
+        settings.inputPCMFormat.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;
+        //TODO:check if size of SInt16 is always suitable
+        settings.inputPCMFormat.mBitsPerChannel = 8 * sizeof(SInt16);
+        settings.inputPCMFormat.mChannelsPerFrame = settings.outputFormat.mChannelsPerFrame;
+        //TODO:check if this is suitable for both interleaved/noninterleaved
+        settings.inputPCMFormat.mBytesPerPacket = settings.inputPCMFormat.mBytesPerFrame = settings.inputPCMFormat.mChannelsPerFrame*sizeof(SInt16);
+        settings.inputPCMFormat.mFramesPerPacket = 1;
+    }
+    NSLog(@"Client data format:%@",[self descriptionForAudioFormat:settings.inputPCMFormat]);
+    
+    if (!CheckError(ExtAudioFileSetProperty(settings.inputFile,
+                                       kExtAudioFileProperty_ClientDataFormat,
+                                       sizeof(settings.inputPCMFormat),
+                                       &settings.inputPCMFormat),
+                    "Setting client data format of input file failed")) {
+        return NO;
+    }
+    
+    //If the file has a client data format, then the audio data in ioData is translated from the client format to the file data format, via theExtAudioFile's internal AudioConverter.
+    if (settings.outputFormat.mFormatID!=kAudioFormatMPEGLayer3) {
+        if (!CheckError(ExtAudioFileSetProperty(settings.outputFile,
+                                           kExtAudioFileProperty_ClientDataFormat,
+                                           sizeof(settings.inputPCMFormat),
+                                           &settings.inputPCMFormat),
+                        "Setting client data format of output file failed")) {
+            return NO;
+        }
+    }
+    
+    
+    printf("Start converting...\n");
+    if (settings.outputFormat.mFormatID==kAudioFormatMPEGLayer3) {
+        startConvertMP3(&settings);
+    }else{
+        BOOL success = startConvert(&settings);
+        if (!success) {
+            return NO;
+        }
+    }
+    
+    
+    ExtAudioFileDispose(settings.inputFile);
+    //AudioFileClose/ExtAudioFileDispose function is needed, or else for .wav output file the duration will be 0
+    ExtAudioFileDispose(settings.outputFile);
+    return YES;
+}
+
+//Check if the input combination is valid
+-(BOOL)validateInput:(ExtAudioConverterSettings*)settigs{
+    //Set default output format
+    if (self.outputSampleRate==0) {
+        self.outputSampleRate = 44100;
+    }
+    
+    if (self.outputNumberChannels==0) {
+        self.outputNumberChannels = 2;
+    }
+    
+    if (self.outputBitDepth==0) {
+        self.outputBitDepth = 16;
+    }
+    
+    if (self.outputFormatID==0) {
+        self.outputFormatID = kAudioFormatLinearPCM;
+    }
+    
+    if (self.outputFileType==0) {
+        //caf type is the most powerful file format
+        self.outputFileType = kAudioFileCAFType;
+    }
+    
+    BOOL valid = YES;
+    //The file format and data format match documentatin is at: https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/CoreAudioOverview/SupportedAudioFormatsMacOSX/SupportedAudioFormatsMacOSX.html
+    switch (self.outputFileType) {
+        case kAudioFileWAVEType:{//for wave file format
+            //WAVE file type only support PCM, alaw and ulaw
+            valid = self.outputFormatID==kAudioFormatLinearPCM || self.outputFormatID==kAudioFormatALaw || self.outputFormatID==kAudioFormatULaw;
+            break;
+        }
+        case kAudioFileAIFFType:{
+            //AIFF only support PCM format
+            valid = self.outputFormatID==kAudioFormatLinearPCM;
+            break;
+        }
+        case kAudioFileAAC_ADTSType:{
+            //aac only support aac data format
+            valid = self.outputFormatID==kAudioFormatMPEG4AAC;
+            break;
+        }
+        case kAudioFileAC3Type:{
+            //convert from PCM to ac3 format is not supported
+            valid = NO;
+            break;
+        }
+        case kAudioFileAIFCType:{
+            //TODO:kAudioFileAIFCType together with kAudioFormatMACE3/kAudioFormatMACE6/kAudioFormatQDesign2/kAudioFormatQUALCOMM pair failed
+            //Since MACE3:1/MACE6:1 is obsolete, they're not supported yet
+            valid = self.outputFormatID==kAudioFormatLinearPCM || self.outputFormatID==kAudioFormatULaw || self.outputFormatID==kAudioFormatALaw || self.outputFormatID==kAudioFormatAppleIMA4 || self.outputFormatID==kAudioFormatQDesign2 || self.outputFormatID==kAudioFormatQUALCOMM;
+            break;
+        }
+        case kAudioFileCAFType:{
+            //caf file type support almost all data format
+            //TODO:not all foramt are supported, check them out
+            valid = YES;
+            break;
+        }
+        case kAudioFileMP3Type:{
+            //TODO:support mp3 type
+            valid = self.outputFormatID==kAudioFormatMPEGLayer3;
+            break;
+        }
+        case kAudioFileMPEG4Type:{
+            valid = self.outputFormatID==kAudioFormatMPEG4AAC;
+            break;
+        }
+        case kAudioFileM4AType:{
+            valid = self.outputFormatID==kAudioFormatMPEG4AAC || self.outputFormatID==kAudioFormatAppleLossless;
+            break;
+        }
+        case kAudioFileNextType:{
+            valid = self.outputFormatID==kAudioFormatLinearPCM || self.outputFormatID==kAudioFormatULaw;
+            break;
+        }
+        case kAudioFileSoundDesigner2Type:{
+            valid = self.outputFormatID==kAudioFormatLinearPCM;
+            break;
+        }
+            //TODO:check iLBC format
+        default:
+            break;
+    }
+    
+    if (!valid) {
+        NSLog(@"the file format and data format pair is not valid");
+    }
+    return valid;
+}
+
+-(NSString*)descriptionForAudioFormat:(AudioStreamBasicDescription) audioFormat
+{
+    NSMutableString *description = [NSMutableString new];
+    
+    // From https://developer.apple.com/library/ios/documentation/MusicAudio/Conceptual/AudioUnitHostingGuide_iOS/ConstructingAudioUnitApps/ConstructingAudioUnitApps.html (Listing 2-8)
+    char formatIDString[5];
+    UInt32 formatID = CFSwapInt32HostToBig (audioFormat.mFormatID);
+    bcopy (&formatID, formatIDString, 4);
+    formatIDString[4] = '\0';
+    
+    [description appendString:@"\n"];
+    [description appendFormat:@"Sample Rate:         %10.0f \n",  audioFormat.mSampleRate];
+    [description appendFormat:@"Format ID:           %10s \n",    formatIDString];
+    [description appendFormat:@"Format Flags:        %10d \n",    (unsigned int)audioFormat.mFormatFlags];
+    [description appendFormat:@"Bytes per Packet:    %10d \n",    (unsigned int)audioFormat.mBytesPerPacket];
+    [description appendFormat:@"Frames per Packet:   %10d \n",    (unsigned int)audioFormat.mFramesPerPacket];
+    [description appendFormat:@"Bytes per Frame:     %10d \n",    (unsigned int)audioFormat.mBytesPerFrame];
+    [description appendFormat:@"Channels per Frame:  %10d \n",    (unsigned int)audioFormat.mChannelsPerFrame];
+    [description appendFormat:@"Bits per Channel:    %10d \n",    (unsigned int)audioFormat.mBitsPerChannel];
+    
+    // Add flags (supposing standard flags).
+    [description appendString:[self descriptionForStandardFlags:audioFormat.mFormatFlags]];
+    
+    return [NSString stringWithString:description];
+}
+
+-(NSString*)descriptionForStandardFlags:(UInt32) mFormatFlags
+{
+    NSMutableString *description = [NSMutableString new];
+    
+    if (mFormatFlags & kAudioFormatFlagIsFloat)
+    { [description appendString:@"kAudioFormatFlagIsFloat \n"]; }
+    if (mFormatFlags & kAudioFormatFlagIsBigEndian)
+    { [description appendString:@"kAudioFormatFlagIsBigEndian \n"]; }
+    if (mFormatFlags & kAudioFormatFlagIsSignedInteger)
+    { [description appendString:@"kAudioFormatFlagIsSignedInteger \n"]; }
+    if (mFormatFlags & kAudioFormatFlagIsPacked)
+    { [description appendString:@"kAudioFormatFlagIsPacked \n"]; }
+    if (mFormatFlags & kAudioFormatFlagIsAlignedHigh)
+    { [description appendString:@"kAudioFormatFlagIsAlignedHigh \n"]; }
+    if (mFormatFlags & kAudioFormatFlagIsNonInterleaved)
+    { [description appendString:@"kAudioFormatFlagIsNonInterleaved \n"]; }
+    if (mFormatFlags & kAudioFormatFlagIsNonMixable)
+    { [description appendString:@"kAudioFormatFlagIsNonMixable \n"]; }
+    if (mFormatFlags & kAudioFormatFlagsAreAllClear)
+    { [description appendString:@"kAudioFormatFlagsAreAllClear \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagIsFloat)
+    { [description appendString:@"kLinearPCMFormatFlagIsFloat \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagIsBigEndian)
+    { [description appendString:@"kLinearPCMFormatFlagIsBigEndian \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagIsSignedInteger)
+    { [description appendString:@"kLinearPCMFormatFlagIsSignedInteger \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagIsPacked)
+    { [description appendString:@"kLinearPCMFormatFlagIsPacked \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagIsAlignedHigh)
+    { [description appendString:@"kLinearPCMFormatFlagIsAlignedHigh \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagIsNonInterleaved)
+    { [description appendString:@"kLinearPCMFormatFlagIsNonInterleaved \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagIsNonMixable)
+    { [description appendString:@"kLinearPCMFormatFlagIsNonMixable \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagsSampleFractionShift)
+    { [description appendString:@"kLinearPCMFormatFlagsSampleFractionShift \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagsSampleFractionMask)
+    { [description appendString:@"kLinearPCMFormatFlagsSampleFractionMask \n"]; }
+    if (mFormatFlags & kLinearPCMFormatFlagsAreAllClear)
+    { [description appendString:@"kLinearPCMFormatFlagsAreAllClear \n"]; }
+    if (mFormatFlags & kAppleLosslessFormatFlag_16BitSourceData)
+    { [description appendString:@"kAppleLosslessFormatFlag_16BitSourceData \n"]; }
+    if (mFormatFlags & kAppleLosslessFormatFlag_20BitSourceData)
+    { [description appendString:@"kAppleLosslessFormatFlag_20BitSourceData \n"]; }
+    if (mFormatFlags & kAppleLosslessFormatFlag_24BitSourceData)
+    { [description appendString:@"kAppleLosslessFormatFlag_24BitSourceData \n"]; }
+    if (mFormatFlags & kAppleLosslessFormatFlag_32BitSourceData)
+    { [description appendString:@"kAppleLosslessFormatFlag_32BitSourceData \n"]; }
+    
+    return [NSString stringWithString:description];
+}
+
+
+@end

+ 1323 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/lame.h

@@ -0,0 +1,1323 @@
+/*
+ *	Interface to MP3 LAME encoding engine
+ *
+ *	Copyright (c) 1999 Mark Taylor
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* $Id: lame.h,v 1.189.2.1 2012/01/08 23:49:58 robert Exp $ */
+
+#ifndef LAME_LAME_H
+#define LAME_LAME_H
+
+/* for size_t typedef */
+#include <stddef.h>
+/* for va_list typedef */
+#include <stdarg.h>
+/* for FILE typedef, TODO: remove when removing lame_mp3_tags_fid */
+#include <stdio.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+typedef void (*lame_report_function)(const char *format, va_list ap);
+
+#if defined(WIN32) || defined(_WIN32)
+#undef CDECL
+#define CDECL __cdecl
+#else
+#define CDECL
+#endif
+
+#define DEPRECATED_OR_OBSOLETE_CODE_REMOVED 1
+
+typedef enum vbr_mode_e {
+  vbr_off=0,
+  vbr_mt,               /* obsolete, same as vbr_mtrh */
+  vbr_rh,
+  vbr_abr,
+  vbr_mtrh,
+  vbr_max_indicator,    /* Don't use this! It's used for sanity checks.       */
+  vbr_default=vbr_mtrh    /* change this to change the default VBR mode of LAME */
+} vbr_mode;
+
+
+/* MPEG modes */
+typedef enum MPEG_mode_e {
+  STEREO = 0,
+  JOINT_STEREO,
+  DUAL_CHANNEL,   /* LAME doesn't supports this! */
+  MONO,
+  NOT_SET,
+  MAX_INDICATOR   /* Don't use this! It's used for sanity checks. */
+} MPEG_mode;
+
+/* Padding types */
+typedef enum Padding_type_e {
+  PAD_NO = 0,
+  PAD_ALL,
+  PAD_ADJUST,
+  PAD_MAX_INDICATOR   /* Don't use this! It's used for sanity checks. */
+} Padding_type;
+
+
+
+/*presets*/
+typedef enum preset_mode_e {
+    /*values from 8 to 320 should be reserved for abr bitrates*/
+    /*for abr I'd suggest to directly use the targeted bitrate as a value*/
+    ABR_8 = 8,
+    ABR_320 = 320,
+
+    V9 = 410, /*Vx to match Lame and VBR_xx to match FhG*/
+    VBR_10 = 410,
+    V8 = 420,
+    VBR_20 = 420,
+    V7 = 430,
+    VBR_30 = 430,
+    V6 = 440,
+    VBR_40 = 440,
+    V5 = 450,
+    VBR_50 = 450,
+    V4 = 460,
+    VBR_60 = 460,
+    V3 = 470,
+    VBR_70 = 470,
+    V2 = 480,
+    VBR_80 = 480,
+    V1 = 490,
+    VBR_90 = 490,
+    V0 = 500,
+    VBR_100 = 500,
+
+
+
+    /*still there for compatibility*/
+    R3MIX = 1000,
+    STANDARD = 1001,
+    EXTREME = 1002,
+    INSANE = 1003,
+    STANDARD_FAST = 1004,
+    EXTREME_FAST = 1005,
+    MEDIUM = 1006,
+    MEDIUM_FAST = 1007
+} preset_mode;
+
+
+/*asm optimizations*/
+typedef enum asm_optimizations_e {
+    MMX = 1,
+    AMD_3DNOW = 2,
+    SSE = 3
+} asm_optimizations;
+
+
+/* psychoacoustic model */
+typedef enum Psy_model_e {
+    PSY_GPSYCHO = 1,
+    PSY_NSPSYTUNE = 2
+} Psy_model;
+
+
+/* buffer considerations */
+typedef enum buffer_constraint_e {
+    MDB_DEFAULT=0,
+    MDB_STRICT_ISO=1,
+    MDB_MAXIMUM=2
+} buffer_constraint;
+
+
+struct lame_global_struct;
+typedef struct lame_global_struct lame_global_flags;
+typedef lame_global_flags *lame_t;
+
+
+
+
+/***********************************************************************
+ *
+ *  The LAME API
+ *  These functions should be called, in this order, for each
+ *  MP3 file to be encoded.  See the file "API" for more documentation
+ *
+ ***********************************************************************/
+
+
+/*
+ * REQUIRED:
+ * initialize the encoder.  sets default for all encoder parameters,
+ * returns NULL if some malloc()'s failed
+ * otherwise returns pointer to structure needed for all future
+ * API calls.
+ */
+lame_global_flags * CDECL lame_init(void);
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/* obsolete version */
+int CDECL lame_init_old(lame_global_flags *);
+#endif
+
+/*
+ * OPTIONAL:
+ * set as needed to override defaults
+ */
+
+/********************************************************************
+ *  input stream description
+ ***********************************************************************/
+/* number of samples.  default = 2^32-1   */
+int CDECL lame_set_num_samples(lame_global_flags *, unsigned long);
+unsigned long CDECL lame_get_num_samples(const lame_global_flags *);
+
+/* input sample rate in Hz.  default = 44100hz */
+int CDECL lame_set_in_samplerate(lame_global_flags *, int);
+int CDECL lame_get_in_samplerate(const lame_global_flags *);
+
+/* number of channels in input stream. default=2  */
+int CDECL lame_set_num_channels(lame_global_flags *, int);
+int CDECL lame_get_num_channels(const lame_global_flags *);
+
+/*
+  scale the input by this amount before encoding.  default=1
+  (not used by decoding routines)
+*/
+int CDECL lame_set_scale(lame_global_flags *, float);
+float CDECL lame_get_scale(const lame_global_flags *);
+
+/*
+  scale the channel 0 (left) input by this amount before encoding.  default=1
+  (not used by decoding routines)
+*/
+int CDECL lame_set_scale_left(lame_global_flags *, float);
+float CDECL lame_get_scale_left(const lame_global_flags *);
+
+/*
+  scale the channel 1 (right) input by this amount before encoding.  default=1
+  (not used by decoding routines)
+*/
+int CDECL lame_set_scale_right(lame_global_flags *, float);
+float CDECL lame_get_scale_right(const lame_global_flags *);
+
+/*
+  output sample rate in Hz.  default = 0, which means LAME picks best value
+  based on the amount of compression.  MPEG only allows:
+  MPEG1    32, 44.1,   48khz
+  MPEG2    16, 22.05,  24
+  MPEG2.5   8, 11.025, 12
+  (not used by decoding routines)
+*/
+int CDECL lame_set_out_samplerate(lame_global_flags *, int);
+int CDECL lame_get_out_samplerate(const lame_global_flags *);
+
+
+/********************************************************************
+ *  general control parameters
+ ***********************************************************************/
+/* 1=cause LAME to collect data for an MP3 frame analyzer. default=0 */
+int CDECL lame_set_analysis(lame_global_flags *, int);
+int CDECL lame_get_analysis(const lame_global_flags *);
+
+/*
+  1 = write a Xing VBR header frame.
+  default = 1
+  this variable must have been added by a Hungarian notation Windows programmer :-)
+*/
+int CDECL lame_set_bWriteVbrTag(lame_global_flags *, int);
+int CDECL lame_get_bWriteVbrTag(const lame_global_flags *);
+
+/* 1=decode only.  use lame/mpglib to convert mp3/ogg to wav.  default=0 */
+int CDECL lame_set_decode_only(lame_global_flags *, int);
+int CDECL lame_get_decode_only(const lame_global_flags *);
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/* 1=encode a Vorbis .ogg file.  default=0 */
+/* DEPRECATED */
+int CDECL lame_set_ogg(lame_global_flags *, int);
+int CDECL lame_get_ogg(const lame_global_flags *);
+#endif
+
+/*
+  internal algorithm selection.  True quality is determined by the bitrate
+  but this variable will effect quality by selecting expensive or cheap algorithms.
+  quality=0..9.  0=best (very slow).  9=worst.
+  recommended:  2     near-best quality, not too slow
+                5     good quality, fast
+                7     ok quality, really fast
+*/
+int CDECL lame_set_quality(lame_global_flags *, int);
+int CDECL lame_get_quality(const lame_global_flags *);
+
+/*
+  mode = 0,1,2,3 = stereo, jstereo, dual channel (not supported), mono
+  default: lame picks based on compression ration and input channels
+*/
+int CDECL lame_set_mode(lame_global_flags *, MPEG_mode);
+MPEG_mode CDECL lame_get_mode(const lame_global_flags *);
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/*
+  mode_automs.  Use a M/S mode with a switching threshold based on
+  compression ratio
+  DEPRECATED
+*/
+int CDECL lame_set_mode_automs(lame_global_flags *, int);
+int CDECL lame_get_mode_automs(const lame_global_flags *);
+#endif
+
+/*
+  force_ms.  Force M/S for all frames.  For testing only.
+  default = 0 (disabled)
+*/
+int CDECL lame_set_force_ms(lame_global_flags *, int);
+int CDECL lame_get_force_ms(const lame_global_flags *);
+
+/* use free_format?  default = 0 (disabled) */
+int CDECL lame_set_free_format(lame_global_flags *, int);
+int CDECL lame_get_free_format(const lame_global_flags *);
+
+/* perform ReplayGain analysis?  default = 0 (disabled) */
+int CDECL lame_set_findReplayGain(lame_global_flags *, int);
+int CDECL lame_get_findReplayGain(const lame_global_flags *);
+
+/* decode on the fly. Search for the peak sample. If the ReplayGain
+ * analysis is enabled then perform the analysis on the decoded data
+ * stream. default = 0 (disabled)
+ * NOTE: if this option is set the build-in decoder should not be used */
+int CDECL lame_set_decode_on_the_fly(lame_global_flags *, int);
+int CDECL lame_get_decode_on_the_fly(const lame_global_flags *);
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/* DEPRECATED: now does the same as lame_set_findReplayGain()
+   default = 0 (disabled) */
+int CDECL lame_set_ReplayGain_input(lame_global_flags *, int);
+int CDECL lame_get_ReplayGain_input(const lame_global_flags *);
+
+/* DEPRECATED: now does the same as
+   lame_set_decode_on_the_fly() && lame_set_findReplayGain()
+   default = 0 (disabled) */
+int CDECL lame_set_ReplayGain_decode(lame_global_flags *, int);
+int CDECL lame_get_ReplayGain_decode(const lame_global_flags *);
+
+/* DEPRECATED: now does the same as lame_set_decode_on_the_fly()
+   default = 0 (disabled) */
+int CDECL lame_set_findPeakSample(lame_global_flags *, int);
+int CDECL lame_get_findPeakSample(const lame_global_flags *);
+#endif
+
+/* counters for gapless encoding */
+int CDECL lame_set_nogap_total(lame_global_flags*, int);
+int CDECL lame_get_nogap_total(const lame_global_flags*);
+
+int CDECL lame_set_nogap_currentindex(lame_global_flags* , int);
+int CDECL lame_get_nogap_currentindex(const lame_global_flags*);
+
+
+/*
+ * OPTIONAL:
+ * Set printf like error/debug/message reporting functions.
+ * The second argument has to be a pointer to a function which looks like
+ *   void my_debugf(const char *format, va_list ap)
+ *   {
+ *       (void) vfprintf(stdout, format, ap);
+ *   }
+ * If you use NULL as the value of the pointer in the set function, the
+ * lame buildin function will be used (prints to stderr).
+ * To quiet any output you have to replace the body of the example function
+ * with just "return;" and use it in the set function.
+ */
+int CDECL lame_set_errorf(lame_global_flags *, lame_report_function);
+int CDECL lame_set_debugf(lame_global_flags *, lame_report_function);
+int CDECL lame_set_msgf  (lame_global_flags *, lame_report_function);
+
+
+
+/* set one of brate compression ratio.  default is compression ratio of 11.  */
+int CDECL lame_set_brate(lame_global_flags *, int);
+int CDECL lame_get_brate(const lame_global_flags *);
+int CDECL lame_set_compression_ratio(lame_global_flags *, float);
+float CDECL lame_get_compression_ratio(const lame_global_flags *);
+
+
+int CDECL lame_set_preset( lame_global_flags*  gfp, int );
+int CDECL lame_set_asm_optimizations( lame_global_flags*  gfp, int, int );
+
+
+
+/********************************************************************
+ *  frame params
+ ***********************************************************************/
+/* mark as copyright.  default=0 */
+int CDECL lame_set_copyright(lame_global_flags *, int);
+int CDECL lame_get_copyright(const lame_global_flags *);
+
+/* mark as original.  default=1 */
+int CDECL lame_set_original(lame_global_flags *, int);
+int CDECL lame_get_original(const lame_global_flags *);
+
+/* error_protection.  Use 2 bytes from each frame for CRC checksum. default=0 */
+int CDECL lame_set_error_protection(lame_global_flags *, int);
+int CDECL lame_get_error_protection(const lame_global_flags *);
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/* padding_type. 0=pad no frames  1=pad all frames 2=adjust padding(default) */
+int CDECL lame_set_padding_type(lame_global_flags *, Padding_type);
+Padding_type CDECL lame_get_padding_type(const lame_global_flags *);
+#endif
+
+/* MP3 'private extension' bit  Meaningless.  default=0 */
+int CDECL lame_set_extension(lame_global_flags *, int);
+int CDECL lame_get_extension(const lame_global_flags *);
+
+/* enforce strict ISO compliance.  default=0 */
+int CDECL lame_set_strict_ISO(lame_global_flags *, int);
+int CDECL lame_get_strict_ISO(const lame_global_flags *);
+
+
+/********************************************************************
+ * quantization/noise shaping
+ ***********************************************************************/
+
+/* disable the bit reservoir. For testing only. default=0 */
+int CDECL lame_set_disable_reservoir(lame_global_flags *, int);
+int CDECL lame_get_disable_reservoir(const lame_global_flags *);
+
+/* select a different "best quantization" function. default=0  */
+int CDECL lame_set_quant_comp(lame_global_flags *, int);
+int CDECL lame_get_quant_comp(const lame_global_flags *);
+int CDECL lame_set_quant_comp_short(lame_global_flags *, int);
+int CDECL lame_get_quant_comp_short(const lame_global_flags *);
+
+int CDECL lame_set_experimentalX(lame_global_flags *, int); /* compatibility*/
+int CDECL lame_get_experimentalX(const lame_global_flags *);
+
+/* another experimental option.  for testing only */
+int CDECL lame_set_experimentalY(lame_global_flags *, int);
+int CDECL lame_get_experimentalY(const lame_global_flags *);
+
+/* another experimental option.  for testing only */
+int CDECL lame_set_experimentalZ(lame_global_flags *, int);
+int CDECL lame_get_experimentalZ(const lame_global_flags *);
+
+/* Naoki's psycho acoustic model.  default=0 */
+int CDECL lame_set_exp_nspsytune(lame_global_flags *, int);
+int CDECL lame_get_exp_nspsytune(const lame_global_flags *);
+
+void CDECL lame_set_msfix(lame_global_flags *, double);
+float CDECL lame_get_msfix(const lame_global_flags *);
+
+
+/********************************************************************
+ * VBR control
+ ***********************************************************************/
+/* Types of VBR.  default = vbr_off = CBR */
+int CDECL lame_set_VBR(lame_global_flags *, vbr_mode);
+vbr_mode CDECL lame_get_VBR(const lame_global_flags *);
+
+/* VBR quality level.  0=highest  9=lowest  */
+int CDECL lame_set_VBR_q(lame_global_flags *, int);
+int CDECL lame_get_VBR_q(const lame_global_flags *);
+
+/* VBR quality level.  0=highest  9=lowest, Range [0,...,10[  */
+int CDECL lame_set_VBR_quality(lame_global_flags *, float);
+float CDECL lame_get_VBR_quality(const lame_global_flags *);
+
+/* Ignored except for VBR=vbr_abr (ABR mode) */
+int CDECL lame_set_VBR_mean_bitrate_kbps(lame_global_flags *, int);
+int CDECL lame_get_VBR_mean_bitrate_kbps(const lame_global_flags *);
+
+int CDECL lame_set_VBR_min_bitrate_kbps(lame_global_flags *, int);
+int CDECL lame_get_VBR_min_bitrate_kbps(const lame_global_flags *);
+
+int CDECL lame_set_VBR_max_bitrate_kbps(lame_global_flags *, int);
+int CDECL lame_get_VBR_max_bitrate_kbps(const lame_global_flags *);
+
+/*
+  1=strictly enforce VBR_min_bitrate.  Normally it will be violated for
+  analog silence
+*/
+int CDECL lame_set_VBR_hard_min(lame_global_flags *, int);
+int CDECL lame_get_VBR_hard_min(const lame_global_flags *);
+
+/* for preset */
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+int CDECL lame_set_preset_expopts(lame_global_flags *, int);
+#endif
+
+/********************************************************************
+ * Filtering control
+ ***********************************************************************/
+/* freq in Hz to apply lowpass. Default = 0 = lame chooses.  -1 = disabled */
+int CDECL lame_set_lowpassfreq(lame_global_flags *, int);
+int CDECL lame_get_lowpassfreq(const lame_global_flags *);
+/* width of transition band, in Hz.  Default = one polyphase filter band */
+int CDECL lame_set_lowpasswidth(lame_global_flags *, int);
+int CDECL lame_get_lowpasswidth(const lame_global_flags *);
+
+/* freq in Hz to apply highpass. Default = 0 = lame chooses.  -1 = disabled */
+int CDECL lame_set_highpassfreq(lame_global_flags *, int);
+int CDECL lame_get_highpassfreq(const lame_global_flags *);
+/* width of transition band, in Hz.  Default = one polyphase filter band */
+int CDECL lame_set_highpasswidth(lame_global_flags *, int);
+int CDECL lame_get_highpasswidth(const lame_global_flags *);
+
+
+/********************************************************************
+ * psycho acoustics and other arguments which you should not change
+ * unless you know what you are doing
+ ***********************************************************************/
+
+/* only use ATH for masking */
+int CDECL lame_set_ATHonly(lame_global_flags *, int);
+int CDECL lame_get_ATHonly(const lame_global_flags *);
+
+/* only use ATH for short blocks */
+int CDECL lame_set_ATHshort(lame_global_flags *, int);
+int CDECL lame_get_ATHshort(const lame_global_flags *);
+
+/* disable ATH */
+int CDECL lame_set_noATH(lame_global_flags *, int);
+int CDECL lame_get_noATH(const lame_global_flags *);
+
+/* select ATH formula */
+int CDECL lame_set_ATHtype(lame_global_flags *, int);
+int CDECL lame_get_ATHtype(const lame_global_flags *);
+
+/* lower ATH by this many db */
+int CDECL lame_set_ATHlower(lame_global_flags *, float);
+float CDECL lame_get_ATHlower(const lame_global_flags *);
+
+/* select ATH adaptive adjustment type */
+int CDECL lame_set_athaa_type( lame_global_flags *, int);
+int CDECL lame_get_athaa_type( const lame_global_flags *);
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/* select the loudness approximation used by the ATH adaptive auto-leveling  */
+int CDECL lame_set_athaa_loudapprox( lame_global_flags *, int);
+int CDECL lame_get_athaa_loudapprox( const lame_global_flags *);
+#endif
+
+/* adjust (in dB) the point below which adaptive ATH level adjustment occurs */
+int CDECL lame_set_athaa_sensitivity( lame_global_flags *, float);
+float CDECL lame_get_athaa_sensitivity( const lame_global_flags* );
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/* OBSOLETE: predictability limit (ISO tonality formula) */
+int CDECL lame_set_cwlimit(lame_global_flags *, int);
+int CDECL lame_get_cwlimit(const lame_global_flags *);
+#endif
+
+/*
+  allow blocktypes to differ between channels?
+  default: 0 for jstereo, 1 for stereo
+*/
+int CDECL lame_set_allow_diff_short(lame_global_flags *, int);
+int CDECL lame_get_allow_diff_short(const lame_global_flags *);
+
+/* use temporal masking effect (default = 1) */
+int CDECL lame_set_useTemporal(lame_global_flags *, int);
+int CDECL lame_get_useTemporal(const lame_global_flags *);
+
+/* use temporal masking effect (default = 1) */
+int CDECL lame_set_interChRatio(lame_global_flags *, float);
+float CDECL lame_get_interChRatio(const lame_global_flags *);
+
+/* disable short blocks */
+int CDECL lame_set_no_short_blocks(lame_global_flags *, int);
+int CDECL lame_get_no_short_blocks(const lame_global_flags *);
+
+/* force short blocks */
+int CDECL lame_set_force_short_blocks(lame_global_flags *, int);
+int CDECL lame_get_force_short_blocks(const lame_global_flags *);
+
+/* Input PCM is emphased PCM (for instance from one of the rarely
+   emphased CDs), it is STRONGLY not recommended to use this, because
+   psycho does not take it into account, and last but not least many decoders
+   ignore these bits */
+int CDECL lame_set_emphasis(lame_global_flags *, int);
+int CDECL lame_get_emphasis(const lame_global_flags *);
+
+
+
+/************************************************************************/
+/* internal variables, cannot be set...                                 */
+/* provided because they may be of use to calling application           */
+/************************************************************************/
+/* version  0=MPEG-2  1=MPEG-1  (2=MPEG-2.5)     */
+int CDECL lame_get_version(const lame_global_flags *);
+
+/* encoder delay   */
+int CDECL lame_get_encoder_delay(const lame_global_flags *);
+
+/*
+  padding appended to the input to make sure decoder can fully decode
+  all input.  Note that this value can only be calculated during the
+  call to lame_encoder_flush().  Before lame_encoder_flush() has
+  been called, the value of encoder_padding = 0.
+*/
+int CDECL lame_get_encoder_padding(const lame_global_flags *);
+
+/* size of MPEG frame */
+int CDECL lame_get_framesize(const lame_global_flags *);
+
+/* number of PCM samples buffered, but not yet encoded to mp3 data. */
+int CDECL lame_get_mf_samples_to_encode( const lame_global_flags*  gfp );
+
+/*
+  size (bytes) of mp3 data buffered, but not yet encoded.
+  this is the number of bytes which would be output by a call to
+  lame_encode_flush_nogap.  NOTE: lame_encode_flush() will return
+  more bytes than this because it will encode the reamining buffered
+  PCM samples before flushing the mp3 buffers.
+*/
+int CDECL lame_get_size_mp3buffer( const lame_global_flags*  gfp );
+
+/* number of frames encoded so far */
+int CDECL lame_get_frameNum(const lame_global_flags *);
+
+/*
+  lame's estimate of the total number of frames to be encoded
+   only valid if calling program set num_samples
+*/
+int CDECL lame_get_totalframes(const lame_global_flags *);
+
+/* RadioGain value. Multiplied by 10 and rounded to the nearest. */
+int CDECL lame_get_RadioGain(const lame_global_flags *);
+
+/* AudiophileGain value. Multipled by 10 and rounded to the nearest. */
+int CDECL lame_get_AudiophileGain(const lame_global_flags *);
+
+/* the peak sample */
+float CDECL lame_get_PeakSample(const lame_global_flags *);
+
+/* Gain change required for preventing clipping. The value is correct only if
+   peak sample searching was enabled. If negative then the waveform
+   already does not clip. The value is multiplied by 10 and rounded up. */
+int CDECL lame_get_noclipGainChange(const lame_global_flags *);
+
+/* user-specified scale factor required for preventing clipping. Value is
+   correct only if peak sample searching was enabled and no user-specified
+   scaling was performed. If negative then either the waveform already does
+   not clip or the value cannot be determined */
+float CDECL lame_get_noclipScale(const lame_global_flags *);
+
+
+
+
+
+
+
+/*
+ * REQUIRED:
+ * sets more internal configuration based on data provided above.
+ * returns -1 if something failed.
+ */
+int CDECL lame_init_params(lame_global_flags *);
+
+
+/*
+ * OPTIONAL:
+ * get the version number, in a string. of the form:
+ * "3.63 (beta)" or just "3.63".
+ */
+const char*  CDECL get_lame_version       ( void );
+const char*  CDECL get_lame_short_version ( void );
+const char*  CDECL get_lame_very_short_version ( void );
+const char*  CDECL get_psy_version        ( void );
+const char*  CDECL get_lame_url           ( void );
+const char*  CDECL get_lame_os_bitness    ( void );
+
+/*
+ * OPTIONAL:
+ * get the version numbers in numerical form.
+ */
+typedef struct {
+    /* generic LAME version */
+    int major;
+    int minor;
+    int alpha;               /* 0 if not an alpha version                  */
+    int beta;                /* 0 if not a beta version                    */
+
+    /* version of the psy model */
+    int psy_major;
+    int psy_minor;
+    int psy_alpha;           /* 0 if not an alpha version                  */
+    int psy_beta;            /* 0 if not a beta version                    */
+
+    /* compile time features */
+    const char *features;    /* Don't make assumptions about the contents! */
+} lame_version_t;
+void CDECL get_lame_version_numerical(lame_version_t *);
+
+
+/*
+ * OPTIONAL:
+ * print internal lame configuration to message handler
+ */
+void CDECL lame_print_config(const lame_global_flags*  gfp);
+
+void CDECL lame_print_internals( const lame_global_flags *gfp);
+
+
+/*
+ * input pcm data, output (maybe) mp3 frames.
+ * This routine handles all buffering, resampling and filtering for you.
+ *
+ * return code     number of bytes output in mp3buf. Can be 0
+ *                 -1:  mp3buf was too small
+ *                 -2:  malloc() problem
+ *                 -3:  lame_init_params() not called
+ *                 -4:  psycho acoustic problems
+ *
+ * The required mp3buf_size can be computed from num_samples,
+ * samplerate and encoding rate, but here is a worst case estimate:
+ *
+ * mp3buf_size in bytes = 1.25*num_samples + 7200
+ *
+ * I think a tighter bound could be:  (mt, March 2000)
+ * MPEG1:
+ *    num_samples*(bitrate/8)/samplerate + 4*1152*(bitrate/8)/samplerate + 512
+ * MPEG2:
+ *    num_samples*(bitrate/8)/samplerate + 4*576*(bitrate/8)/samplerate + 256
+ *
+ * but test first if you use that!
+ *
+ * set mp3buf_size = 0 and LAME will not check if mp3buf_size is
+ * large enough.
+ *
+ * NOTE:
+ * if gfp->num_channels=2, but gfp->mode = 3 (mono), the L & R channels
+ * will be averaged into the L channel before encoding only the L channel
+ * This will overwrite the data in buffer_l[] and buffer_r[].
+ *
+*/
+int CDECL lame_encode_buffer (
+        lame_global_flags*  gfp,           /* global context handle         */
+        const short int     buffer_l [],   /* PCM data for left channel     */
+        const short int     buffer_r [],   /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+/*
+ * as above, but input has L & R channel data interleaved.
+ * NOTE:
+ * num_samples = number of samples in the L (or R)
+ * channel, not the total number of samples in pcm[]
+ */
+int CDECL lame_encode_buffer_interleaved(
+        lame_global_flags*  gfp,           /* global context handlei        */
+        short int           pcm[],         /* PCM data for left and right
+                                              channel, interleaved          */
+        int                 num_samples,   /* number of samples per channel,
+                                              _not_ number of samples in
+                                              pcm[]                         */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        int                 mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+
+/* as lame_encode_buffer, but for 'float's.
+ * !! NOTE: !! data must still be scaled to be in the same range as
+ * short int, +/- 32768
+ */
+int CDECL lame_encode_buffer_float(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const float         pcm_l [],      /* PCM data for left channel     */
+        const float         pcm_r [],      /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+/* as lame_encode_buffer, but for 'float's.
+ * !! NOTE: !! data must be scaled to +/- 1 full scale
+ */
+int CDECL lame_encode_buffer_ieee_float(
+        lame_t          gfp,
+        const float     pcm_l [],          /* PCM data for left channel     */
+        const float     pcm_r [],          /* PCM data for right channel    */
+        const int       nsamples,
+        unsigned char * mp3buf,
+        const int       mp3buf_size);
+int CDECL lame_encode_buffer_interleaved_ieee_float(
+        lame_t          gfp,
+        const float     pcm[],             /* PCM data for left and right
+                                              channel, interleaved          */
+        const int       nsamples,
+        unsigned char * mp3buf,
+        const int       mp3buf_size);
+
+/* as lame_encode_buffer, but for 'double's.
+ * !! NOTE: !! data must be scaled to +/- 1 full scale
+ */
+int CDECL lame_encode_buffer_ieee_double(
+        lame_t          gfp,
+        const double    pcm_l [],          /* PCM data for left channel     */
+        const double    pcm_r [],          /* PCM data for right channel    */
+        const int       nsamples,
+        unsigned char * mp3buf,
+        const int       mp3buf_size);
+int CDECL lame_encode_buffer_interleaved_ieee_double(
+        lame_t          gfp,
+        const double    pcm[],             /* PCM data for left and right
+                                              channel, interleaved          */
+        const int       nsamples,
+        unsigned char * mp3buf,
+        const int       mp3buf_size);
+
+/* as lame_encode_buffer, but for long's
+ * !! NOTE: !! data must still be scaled to be in the same range as
+ * short int, +/- 32768
+ *
+ * This scaling was a mistake (doesn't allow one to exploit full
+ * precision of type 'long'.  Use lame_encode_buffer_long2() instead.
+ *
+ */
+int CDECL lame_encode_buffer_long(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const long     buffer_l [],       /* PCM data for left channel     */
+        const long     buffer_r [],       /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+/* Same as lame_encode_buffer_long(), but with correct scaling.
+ * !! NOTE: !! data must still be scaled to be in the same range as
+ * type 'long'.   Data should be in the range:  +/- 2^(8*size(long)-1)
+ *
+ */
+int CDECL lame_encode_buffer_long2(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const long     buffer_l [],       /* PCM data for left channel     */
+        const long     buffer_r [],       /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+/* as lame_encode_buffer, but for int's
+ * !! NOTE: !! input should be scaled to the maximum range of 'int'
+ * If int is 4 bytes, then the values should range from
+ * +/- 2147483648.
+ *
+ * This routine does not (and cannot, without loosing precision) use
+ * the same scaling as the rest of the lame_encode_buffer() routines.
+ *
+ */
+int CDECL lame_encode_buffer_int(
+        lame_global_flags*  gfp,           /* global context handle         */
+        const int      buffer_l [],       /* PCM data for left channel     */
+        const int      buffer_r [],       /* PCM data for right channel    */
+        const int           nsamples,      /* number of samples per channel */
+        unsigned char*      mp3buf,        /* pointer to encoded MP3 stream */
+        const int           mp3buf_size ); /* number of valid octets in this
+                                              stream                        */
+
+
+
+
+
+/*
+ * REQUIRED:
+ * lame_encode_flush will flush the intenal PCM buffers, padding with
+ * 0's to make sure the final frame is complete, and then flush
+ * the internal MP3 buffers, and thus may return a
+ * final few mp3 frames.  'mp3buf' should be at least 7200 bytes long
+ * to hold all possible emitted data.
+ *
+ * will also write id3v1 tags (if any) into the bitstream
+ *
+ * return code = number of bytes output to mp3buf. Can be 0
+ */
+int CDECL lame_encode_flush(
+        lame_global_flags *  gfp,    /* global context handle                 */
+        unsigned char*       mp3buf, /* pointer to encoded MP3 stream         */
+        int                  size);  /* number of valid octets in this stream */
+
+/*
+ * OPTIONAL:
+ * lame_encode_flush_nogap will flush the internal mp3 buffers and pad
+ * the last frame with ancillary data so it is a complete mp3 frame.
+ *
+ * 'mp3buf' should be at least 7200 bytes long
+ * to hold all possible emitted data.
+ *
+ * After a call to this routine, the outputed mp3 data is complete, but
+ * you may continue to encode new PCM samples and write future mp3 data
+ * to a different file.  The two mp3 files will play back with no gaps
+ * if they are concatenated together.
+ *
+ * This routine will NOT write id3v1 tags into the bitstream.
+ *
+ * return code = number of bytes output to mp3buf. Can be 0
+ */
+int CDECL lame_encode_flush_nogap(
+        lame_global_flags *  gfp,    /* global context handle                 */
+        unsigned char*       mp3buf, /* pointer to encoded MP3 stream         */
+        int                  size);  /* number of valid octets in this stream */
+
+/*
+ * OPTIONAL:
+ * Normally, this is called by lame_init_params().  It writes id3v2 and
+ * Xing headers into the front of the bitstream, and sets frame counters
+ * and bitrate histogram data to 0.  You can also call this after
+ * lame_encode_flush_nogap().
+ */
+int CDECL lame_init_bitstream(
+        lame_global_flags *  gfp);    /* global context handle                 */
+
+
+
+/*
+ * OPTIONAL:    some simple statistics
+ * a bitrate histogram to visualize the distribution of used frame sizes
+ * a stereo mode histogram to visualize the distribution of used stereo
+ *   modes, useful in joint-stereo mode only
+ *   0: LR    left-right encoded
+ *   1: LR-I  left-right and intensity encoded (currently not supported)
+ *   2: MS    mid-side encoded
+ *   3: MS-I  mid-side and intensity encoded (currently not supported)
+ *
+ * attention: don't call them after lame_encode_finish
+ * suggested: lame_encode_flush -> lame_*_hist -> lame_close
+ */
+
+void CDECL lame_bitrate_hist(
+        const lame_global_flags * gfp,
+        int bitrate_count[14] );
+void CDECL lame_bitrate_kbps(
+        const lame_global_flags * gfp,
+        int bitrate_kbps [14] );
+void CDECL lame_stereo_mode_hist(
+        const lame_global_flags * gfp,
+        int stereo_mode_count[4] );
+
+void CDECL lame_bitrate_stereo_mode_hist (
+        const lame_global_flags * gfp,
+        int bitrate_stmode_count[14][4] );
+
+void CDECL lame_block_type_hist (
+        const lame_global_flags * gfp,
+        int btype_count[6] );
+
+void CDECL lame_bitrate_block_type_hist (
+        const lame_global_flags * gfp,
+        int bitrate_btype_count[14][6] );
+
+#if (DEPRECATED_OR_OBSOLETE_CODE_REMOVED && 0)
+#else
+/*
+ * OPTIONAL:
+ * lame_mp3_tags_fid will rewrite a Xing VBR tag to the mp3 file with file
+ * pointer fid.  These calls perform forward and backwards seeks, so make
+ * sure fid is a real file.  Make sure lame_encode_flush has been called,
+ * and all mp3 data has been written to the file before calling this
+ * function.
+ * NOTE:
+ * if VBR  tags are turned off by the user, or turned off by LAME because
+ * the output is not a regular file, this call does nothing
+ * NOTE:
+ * LAME wants to read from the file to skip an optional ID3v2 tag, so
+ * make sure you opened the file for writing and reading.
+ * NOTE:
+ * You can call lame_get_lametag_frame instead, if you want to insert
+ * the lametag yourself.
+*/
+void CDECL lame_mp3_tags_fid(lame_global_flags *, FILE* fid);
+#endif
+
+/*
+ * OPTIONAL:
+ * lame_get_lametag_frame copies the final LAME-tag into 'buffer'.
+ * The function returns the number of bytes copied into buffer, or
+ * the required buffer size, if the provided buffer is too small.
+ * Function failed, if the return value is larger than 'size'!
+ * Make sure lame_encode flush has been called before calling this function.
+ * NOTE:
+ * if VBR  tags are turned off by the user, or turned off by LAME,
+ * this call does nothing and returns 0.
+ * NOTE:
+ * LAME inserted an empty frame in the beginning of mp3 audio data,
+ * which you have to replace by the final LAME-tag frame after encoding.
+ * In case there is no ID3v2 tag, usually this frame will be the very first
+ * data in your mp3 file. If you put some other leading data into your
+ * file, you'll have to do some bookkeeping about where to write this buffer.
+ */
+size_t CDECL lame_get_lametag_frame(
+        const lame_global_flags *, unsigned char* buffer, size_t size);
+
+/*
+ * REQUIRED:
+ * final call to free all remaining buffers
+ */
+int  CDECL lame_close (lame_global_flags *);
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/*
+ * OBSOLETE:
+ * lame_encode_finish combines lame_encode_flush() and lame_close() in
+ * one call.  However, once this call is made, the statistics routines
+ * will no longer work because the data will have been cleared, and
+ * lame_mp3_tags_fid() cannot be called to add data to the VBR header
+ */
+int CDECL lame_encode_finish(
+        lame_global_flags*  gfp,
+        unsigned char*      mp3buf,
+        int                 size );
+#endif
+
+
+
+
+
+
+/*********************************************************************
+ *
+ * decoding
+ *
+ * a simple interface to mpglib, part of mpg123, is also included if
+ * libmp3lame is compiled with HAVE_MPGLIB
+ *
+ *********************************************************************/
+
+struct hip_global_struct;
+typedef struct hip_global_struct hip_global_flags;
+typedef hip_global_flags *hip_t;
+
+
+typedef struct {
+  int header_parsed;   /* 1 if header was parsed and following data was
+                          computed                                       */
+  int stereo;          /* number of channels                             */
+  int samplerate;      /* sample rate                                    */
+  int bitrate;         /* bitrate                                        */
+  int mode;            /* mp3 frame type                                 */
+  int mode_ext;        /* mp3 frame type                                 */
+  int framesize;       /* number of samples per mp3 frame                */
+
+  /* this data is only computed if mpglib detects a Xing VBR header */
+  unsigned long nsamp; /* number of samples in mp3 file.                 */
+  int totalframes;     /* total number of frames in mp3 file             */
+
+  /* this data is not currently computed by the mpglib routines */
+  int framenum;        /* frames decoded counter                         */
+} mp3data_struct;
+
+/* required call to initialize decoder */
+hip_t CDECL hip_decode_init(void);
+
+/* cleanup call to exit decoder  */
+int CDECL hip_decode_exit(hip_t gfp);
+
+/* HIP reporting functions */
+void CDECL hip_set_errorf(hip_t gfp, lame_report_function f);
+void CDECL hip_set_debugf(hip_t gfp, lame_report_function f);
+void CDECL hip_set_msgf  (hip_t gfp, lame_report_function f);
+
+/*********************************************************************
+ * input 1 mp3 frame, output (maybe) pcm data.
+ *
+ *  nout = hip_decode(hip, mp3buf,len,pcm_l,pcm_r);
+ *
+ * input:
+ *    len          :  number of bytes of mp3 data in mp3buf
+ *    mp3buf[len]  :  mp3 data to be decoded
+ *
+ * output:
+ *    nout:  -1    : decoding error
+ *            0    : need more data before we can complete the decode
+ *           >0    : returned 'nout' samples worth of data in pcm_l,pcm_r
+ *    pcm_l[nout]  : left channel data
+ *    pcm_r[nout]  : right channel data
+ *
+ *********************************************************************/
+int CDECL hip_decode( hip_t           gfp
+                    , unsigned char * mp3buf
+                    , size_t          len
+                    , short           pcm_l[]
+                    , short           pcm_r[]
+                    );
+
+/* same as hip_decode, and also returns mp3 header data */
+int CDECL hip_decode_headers( hip_t           gfp
+                            , unsigned char*  mp3buf
+                            , size_t          len
+                            , short           pcm_l[]
+                            , short           pcm_r[]
+                            , mp3data_struct* mp3data
+                            );
+
+/* same as hip_decode, but returns at most one frame */
+int CDECL hip_decode1( hip_t          gfp
+                     , unsigned char* mp3buf
+                     , size_t         len
+                     , short          pcm_l[]
+                     , short          pcm_r[]
+                     );
+
+/* same as hip_decode1, but returns at most one frame and mp3 header data */
+int CDECL hip_decode1_headers( hip_t           gfp
+                             , unsigned char*  mp3buf
+                             , size_t          len
+                             , short           pcm_l[]
+                             , short           pcm_r[]
+                             , mp3data_struct* mp3data
+                             );
+
+/* same as hip_decode1_headers, but also returns enc_delay and enc_padding
+   from VBR Info tag, (-1 if no info tag was found) */
+int CDECL hip_decode1_headersB( hip_t gfp
+                              , unsigned char*   mp3buf
+                              , size_t           len
+                              , short            pcm_l[]
+                              , short            pcm_r[]
+                              , mp3data_struct*  mp3data
+                              , int             *enc_delay
+                              , int             *enc_padding
+                              );
+
+
+
+/* OBSOLETE:
+ * lame_decode... functions are there to keep old code working
+ * but it is strongly recommended to replace calls by hip_decode...
+ * function calls, see above.
+ */
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+int CDECL lame_decode_init(void);
+int CDECL lame_decode(
+        unsigned char *  mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[] );
+int CDECL lame_decode_headers(
+        unsigned char*   mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[],
+        mp3data_struct*  mp3data );
+int CDECL lame_decode1(
+        unsigned char*  mp3buf,
+        int             len,
+        short           pcm_l[],
+        short           pcm_r[] );
+int CDECL lame_decode1_headers(
+        unsigned char*   mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[],
+        mp3data_struct*  mp3data );
+int CDECL lame_decode1_headersB(
+        unsigned char*   mp3buf,
+        int              len,
+        short            pcm_l[],
+        short            pcm_r[],
+        mp3data_struct*  mp3data,
+        int              *enc_delay,
+        int              *enc_padding );
+int CDECL lame_decode_exit(void);
+
+#endif /* obsolete lame_decode API calls */
+
+
+/*********************************************************************
+ *
+ * id3tag stuff
+ *
+ *********************************************************************/
+
+/*
+ * id3tag.h -- Interface to write ID3 version 1 and 2 tags.
+ *
+ * Copyright (C) 2000 Don Melton.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/* utility to obtain alphabetically sorted list of genre names with numbers */
+void CDECL id3tag_genre_list(
+        void (*handler)(int, const char *, void *),
+        void*  cookie);
+
+void CDECL id3tag_init     (lame_t gfp);
+
+/* force addition of version 2 tag */
+void CDECL id3tag_add_v2   (lame_t gfp);
+
+/* add only a version 1 tag */
+void CDECL id3tag_v1_only  (lame_t gfp);
+
+/* add only a version 2 tag */
+void CDECL id3tag_v2_only  (lame_t gfp);
+
+/* pad version 1 tag with spaces instead of nulls */
+void CDECL id3tag_space_v1 (lame_t gfp);
+
+/* pad version 2 tag with extra 128 bytes */
+void CDECL id3tag_pad_v2   (lame_t gfp);
+
+/* pad version 2 tag with extra n bytes */
+void CDECL id3tag_set_pad  (lame_t gfp, size_t n);
+
+void CDECL id3tag_set_title(lame_t gfp, const char* title);
+void CDECL id3tag_set_artist(lame_t gfp, const char* artist);
+void CDECL id3tag_set_album(lame_t gfp, const char* album);
+void CDECL id3tag_set_year(lame_t gfp, const char* year);
+void CDECL id3tag_set_comment(lame_t gfp, const char* comment);
+            
+/* return -1 result if track number is out of ID3v1 range
+                    and ignored for ID3v1 */
+int CDECL id3tag_set_track(lame_t gfp, const char* track);
+
+/* return non-zero result if genre name or number is invalid
+  result 0: OK
+  result -1: genre number out of range
+  result -2: no valid ID3v1 genre name, mapped to ID3v1 'Other'
+             but taken as-is for ID3v2 genre tag */
+int CDECL id3tag_set_genre(lame_t gfp, const char* genre);
+
+/* return non-zero result if field name is invalid */
+int CDECL id3tag_set_fieldvalue(lame_t gfp, const char* fieldvalue);
+
+/* return non-zero result if image type is invalid */
+int CDECL id3tag_set_albumart(lame_t gfp, const char* image, size_t size);
+
+/* lame_get_id3v1_tag copies ID3v1 tag into buffer.
+ * Function returns number of bytes copied into buffer, or number
+ * of bytes rquired if buffer 'size' is too small.
+ * Function fails, if returned value is larger than 'size'.
+ * NOTE:
+ * This functions does nothing, if user/LAME disabled ID3v1 tag.
+ */
+size_t CDECL lame_get_id3v1_tag(lame_t gfp, unsigned char* buffer, size_t size);
+
+/* lame_get_id3v2_tag copies ID3v2 tag into buffer.
+ * Function returns number of bytes copied into buffer, or number
+ * of bytes rquired if buffer 'size' is too small.
+ * Function fails, if returned value is larger than 'size'.
+ * NOTE:
+ * This functions does nothing, if user/LAME disabled ID3v2 tag.
+ */
+size_t CDECL lame_get_id3v2_tag(lame_t gfp, unsigned char* buffer, size_t size);
+
+/* normaly lame_init_param writes ID3v2 tags into the audio stream
+ * Call lame_set_write_id3tag_automatic(gfp, 0) before lame_init_param
+ * to turn off this behaviour and get ID3v2 tag with above function
+ * write it yourself into your file.
+ */
+void CDECL lame_set_write_id3tag_automatic(lame_global_flags * gfp, int);
+int CDECL lame_get_write_id3tag_automatic(lame_global_flags const* gfp);
+
+/* experimental */
+int CDECL id3tag_set_textinfo_latin1(lame_t gfp, char const *id, char const *text);
+
+/* experimental */
+int CDECL id3tag_set_comment_latin1(lame_t gfp, char const *lang, char const *desc, char const *text);
+
+#if DEPRECATED_OR_OBSOLETE_CODE_REMOVED
+#else
+/* experimental */
+int CDECL id3tag_set_textinfo_ucs2(lame_t gfp, char const *id, unsigned short const *text);
+
+/* experimental */
+int CDECL id3tag_set_comment_ucs2(lame_t gfp, char const *lang,
+                                  unsigned short const *desc, unsigned short const *text);
+
+/* experimental */
+int CDECL id3tag_set_fieldvalue_ucs2(lame_t gfp, const unsigned short *fieldvalue);
+#endif
+
+/* experimental */
+int CDECL id3tag_set_fieldvalue_utf16(lame_t gfp, const unsigned short *fieldvalue);
+
+/* experimental */
+int CDECL id3tag_set_textinfo_utf16(lame_t gfp, char const *id, unsigned short const *text);
+
+/* experimental */
+int CDECL id3tag_set_comment_utf16(lame_t gfp, char const *lang, unsigned short const *desc, unsigned short const *text);
+
+
+/***********************************************************************
+*
+*  list of valid bitrates [kbps] & sample frequencies [Hz].
+*  first index: 0: MPEG-2   values  (sample frequencies 16...24 kHz)
+*               1: MPEG-1   values  (sample frequencies 32...48 kHz)
+*               2: MPEG-2.5 values  (sample frequencies  8...12 kHz)
+***********************************************************************/
+
+extern const int     bitrate_table    [3][16];
+extern const int     samplerate_table [3][ 4];
+
+/* access functions for use in DLL, global vars are not exported */
+int CDECL lame_get_bitrate(int mpeg_version, int table_index);
+int CDECL lame_get_samplerate(int mpeg_version, int table_index);
+
+
+/* maximum size of albumart image (128KB), which affects LAME_MAXMP3BUFFER
+   as well since lame_encode_buffer() also returns ID3v2 tag data */
+#define LAME_MAXALBUMART    (128 * 1024)
+
+/* maximum size of mp3buffer needed if you encode at most 1152 samples for
+   each call to lame_encode_buffer.  see lame_encode_buffer() below  
+   (LAME_MAXMP3BUFFER is now obsolete)  */
+#define LAME_MAXMP3BUFFER   (16384 + LAME_MAXALBUMART)
+
+
+typedef enum {
+    LAME_OKAY             =   0,
+    LAME_NOERROR          =   0,
+    LAME_GENERICERROR     =  -1,
+    LAME_NOMEM            = -10,
+    LAME_BADBITRATE       = -11,
+    LAME_BADSAMPFREQ      = -12,
+    LAME_INTERNALERROR    = -13,
+
+    FRONTEND_READERROR    = -80,
+    FRONTEND_WRITEERROR   = -81,
+    FRONTEND_FILETOOLARGE = -82
+
+} lame_errorcodes_t;
+
+#if defined(__cplusplus)
+}
+#endif
+#endif /* LAME_LAME_H */
+

BIN
AIPlayRingtones/AppPage/Common/TSBandRingTool/libmp3/libmp3lame.a


+ 1 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Contents/PkgInfo

@@ -0,0 +1 @@
+BNDLband

+ 0 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Media/kong.txt


BIN
AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/assetsmetadata.plist


+ 74 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/metadata.plist

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>com_apple_garageband_metadata_appid</key>
+	<string>com.apple.mobilegarageband</string>
+	<key>com_apple_garageband_metadata_artistName</key>
+	<string></string>
+	<key>com_apple_garageband_metadata_composer</key>
+	<string></string>
+	<key>com_apple_garageband_metadata_createdinappid</key>
+	<string>com.apple.mobilegarageband</string>
+	<key>com_apple_garageband_metadata_hasMasterRTPlugIn</key>
+	<false/>
+	<key>com_apple_garageband_metadata_hasMasterRTRegions</key>
+	<false/>
+	<key>com_apple_garageband_metadata_machine</key>
+	<string>iPhone11,8</string>
+	<key>com_apple_garageband_metadata_mediaTrackType</key>
+	<string>Undefined</string>
+	<key>com_apple_garageband_metadata_numberOfArrangeAlchemyTracks</key>
+	<integer>0</integer>
+	<key>com_apple_garageband_metadata_numberOfArrangeDrummerTracks</key>
+	<integer>0</integer>
+	<key>com_apple_garageband_metadata_numberOfArrangeTracks</key>
+	<integer>1</integer>
+	<key>com_apple_garageband_metadata_numberOfAudioUnitTracks</key>
+	<integer>0</integer>
+	<key>com_apple_garageband_metadata_numberOfGridColumns</key>
+	<integer>-1</integer>
+	<key>com_apple_garageband_metadata_numberOfGridRows</key>
+	<integer>-1</integer>
+	<key>com_apple_garageband_metadata_numberOfRIClips</key>
+	<integer>-1</integer>
+	<key>com_apple_garageband_metadata_numberOfRIGridRows</key>
+	<integer>-1</integer>
+	<key>com_apple_garageband_metadata_numberOfRITracks</key>
+	<integer>1</integer>
+	<key>com_apple_garageband_metadata_numberOfSIClips</key>
+	<integer>-1</integer>
+	<key>com_apple_garageband_metadata_numberOfSIGridRows</key>
+	<integer>-1</integer>
+	<key>com_apple_garageband_metadata_numberOfSITracks</key>
+	<integer>0</integer>
+	<key>com_apple_garageband_metadata_numberOfVisibleArrangeTracks</key>
+	<integer>1</integer>
+	<key>com_apple_garageband_metadata_songDuration</key>
+	<real>45.4545578231292</real>
+	<key>com_apple_garageband_metadata_songGender</key>
+	<string>major</string>
+	<key>com_apple_garageband_metadata_songKey</key>
+	<string>C</string>
+	<key>com_apple_garageband_metadata_songSignatureDeNominator</key>
+	<integer>4</integer>
+	<key>com_apple_garageband_metadata_songSignatureNominator</key>
+	<integer>4</integer>
+	<key>com_apple_garageband_metadata_songTempo</key>
+	<integer>110</integer>
+	<key>com_apple_garageband_metadata_songTitle</key>
+	<string>我的乐曲</string>
+	<key>com_apple_garageband_metadata_songVersionNumber</key>
+	<integer>9</integer>
+	<key>com_apple_garageband_metadata_system</key>
+	<string>ios</string>
+	<key>com_apple_mobileGarageBand_metadata_contentVersionNumber</key>
+	<integer>2</integer>
+	<key>com_apple_mobilegarageband_metadata_songVersionNumber</key>
+	<integer>11</integer>
+	<key>kDfMetaDataKey_numberOfRootRegions</key>
+	<integer>1</integer>
+	<key>plistVersion</key>
+	<integer>1050</integer>
+</dict>
+</plist>

+ 20 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/output.plist

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>encoding application</key>
+	<string>GarageBand for iOS 2.3.6</string>
+	<key>maxLength</key>
+	<real>29.5</real>
+	<key>settings</key>
+	<string>CbPrefs_exportPreset_aacSongMediumQuality</string>
+	<key>tempo</key>
+	<string>110</string>
+	<key>title</key>
+	<string>template</string>
+	<key>video</key>
+	<false/>
+	<key>year</key>
+	<string>2018</string>
+</dict>
+</plist>

BIN
AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/Output/output.xyz


+ 2570 - 0
AIPlayRingtones/AppPage/Common/TSBandRingTool/placeholder.band/projectData

@@ -0,0 +1,2570 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>$archiver</key>
+	<string>NSKeyedArchiver</string>
+	<key>$objects</key>
+	<array>
+		<string>$null</string>
+		<string>ios</string>
+		<string>iPhone5,4</string>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>6</integer>
+			</dict>
+			<key>DfLogicModelLogicSong</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>4</integer>
+			</dict>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>5</integer>
+			</dict>
+			<key>NS.data</key>
+			<data>
+			I0fAq68GAwAEAAAAAQAEAFpYAQAAAAAAZ25vUwEA////////////
+			/////////wIAAAABABQOAAAAAAAAI0fAq68GEAAPAAAAAAAAAAQA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEAAQABAAgAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEgA
+			AAAAAAAAAAAAAAAAAADgyBAAgE8SAAAAAAAAAAAA/////wAAAAAA
+			AAAAAAAAAAIBBQAAAAAAAAAAAAAAAAAAAAAAAwMEAAQoAAAAAAAA
+			ZAAAAAAASAAAAAAAAAAAAAQCBwEBAAAI4MgQAAAAAAAEAAAAAQAB
+			AAEAAADEAgAABABZCAMFAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA
+			AAAAAAAAAACAAwAAAAAAQAAABwpbXUpHBQAAAAAAAQQAAHDpcOkA
+			AAAAAIAAAABAAAAAAACWAAAAAAAAAJYAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAD///8/AAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAMIBAAAAAAAAlgAAAAAAAACWAAAAAAAA
+			AMIBAAAAAAAApQAAAAAAAADDAAAAAAAAAIcAAAAAAAAAAAAAAAAA
+			AAAAAQAAAIA/AAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAABwAAAAAAAAAAAAAEAgcBAQAACODIEAAAAAAABAAAAAEAAQAA
+			AAAAxAIAAAUAWQgDBQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA
+			AAAAAAAAgAMAAAAAAAAAAAcKW11KRwUAAAAAAAEAAAAAAAAA//8A
+			AACAAAAAAAAAAAAAlgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAADCAQAAAAAAAJYAAAAAAAAAlgAAAAAAAADC
+			AQAAAAAAAKUAAAAAAAAAwwAAAAAAAACHAAAAAAAAAAAAAAAAAAAA
+			AAEAAACAPwAA//8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAVAAAAAQAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAYAAAAABooAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFl
+			U00CAAEAAAAAAAAA//////////8CAAAAAQAuAQAAAAAAAC4DQQAA
+			AAAAAgAAAAAAAAAJAOacquWRveWQjQAAAAAAAAAAAEAAAAAAAAAA
+			AAAAACCWopa9lrwAkmkAAJwB3gUAABROhRYAAAAA6NLwAAAAAAAA
+			AAAAAAAAMHUAAAAAAAAAAAAAAABUAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAGigAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAgAAAAAA/wAAAAAAcVN2RQEAAQAAAAAAAAAC
+			AAAA/////wIAAAABAGAAAAAAAAAAMAAAAAAAAAAAAAACBAAAADAA
+			AAAAAACI9v8AAAAAAAAAAAAAAAAAiAAAAAAEAAAAMgAAAAAAAAAA
+			AAAABwAAAAAAAAAAAACIAAAAAAAAAADxAAAA////PwAAAAAAAAAA
+			cWVTTQIAAwAAAAAAAAD//////////wIAAAABAC4BAAAAAAAALgNB
+			AAAAAAADAAAAAAAAAAkA5pyq5ZG95ZCNAAAAAAAAAAAAQAAAAAAA
+			AAAAAAAAIJailr2WvACSaQAAnAHeBQAAFE6FFgAAAADo0vAAAAAA
+			AAAAAAAAAAAwdQAAAAAAAAAAAAAAAFQAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAaKAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAACAAAAAAD/AAAAAABxU3ZFAQADAAAAAAAA
+			AAMAAAD/////AgAAAAEAMAAAAAAAAABgAAAAAJYAAAAAAAB/AACA
+			4MgQAAAAQIgAAAAAAAAAAPEAAAD///8/AAAAAAAAAABxZVNNAgAD
+			AAAABAAAAP//////////AgAAAAEALgEAAAAAAAAuA0EAAAAAAAsA
+			AAAAAAAACQDmnKrlkb3lkI0AAAAAAAAAAABAAAAAAAAAAAAAAAAg
+			lqKWvZa8AJJpAACcAd4FAAAUToUWAAAAAOjS8AAAAAAAAAAAAAAA
+			ADB1AAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAABooAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAIAAAAAAP8AAAAAAHFTdkUBAAMAAAAEAAAACwAAAP//
+			//8CAAAAAQAwAAAAAAAAAGAAAAAAlgAAAAAAAH8AAADgyBAAAABA
+			iAAAAAAAAAAA8QAAAP///z8AAAAAAAAAAHRTeFQBAAQAAAAAAAAA
+			//////////8CAAAAAQCYAAAAAAAAAGwGAAAAAAAAHgAeAAAAU3Ry
+			U2N0eHx8fFBsYWluIFRleHQAAAAAAAAAAAAAAAAAAAAAAABUaW1l
+			cwBvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAA
+			AAAAAAAUAFN0clNjdHh8fHxQbGFpbiBUZXh0DABhYmNBQkMxMjM0
+			NTYFAFRpbWVzAP////8AAAAAdFN4VAEABAAAAAQAAAD/////////
+			/wIAAAABAJoAAAAAAAAAbAYAAAAAAAAeAB4AAABTdHJTY3R4fHx8
+			UGFnZSBOdW1iZXJzAAAAAAAAAAAAAAAAAAAAAFRpbWVzAG8AAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAABAAAAAAAAABYA
+			U3RyU2N0eHx8fFBhZ2UgTnVtYmVycwwAYWJjQUJDMTIzNDU2BQBU
+			aW1lcwD/////AAAAAHRTeFQBAAQAAAAIAAAA//////////8CAAAA
+			AQCaAAAAAAAAAGwGAAAAAAAAHgAeAAAAU3RyU2N0eHx8fEJhciBO
+			dW1iZXJzAAAAAAAAAAAAAAAAAAAAAABUaW1lcwBvAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAAAAAAVAFN0clNj
+			dHh8fHxCYXIgTnVtYmVycwAMAGFiY0FCQzEyMzQ1NgUAVGltZXMA
+			/////wAAAAB0U3hUAQAEAAAADAAAAP//////////AgAAAAEAngAA
+			AAAAAABsBgAAAAAAAB4AHgAAAFN0clNjdHh8fHxJbnN0cnVtZW50
+			IE5hAAAAAAAAAAAAAAAAAAAAVGltZXMAbwAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAACgAAAAEAAAAAAAAAGgBTdHJTY3R4fHx8
+			SW5zdHJ1bWVudCBOYW1lcwwAYWJjQUJDMTIzNDU2BQBUaW1lcwD/
+			////AAAAAHRTeFQBAAQAAAAQAAAA//////////8CAAAAAQCoAAAA
+			AAAAAGwGAAAAAAAAHgAeAAAAU3RyU2N0eHx8fFR1cGxldHMAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABUaW1lc05ld1JvbWFuUFMtSXRhbGlj
+			TVQAAAAAAAAAAAAAAAAKAAIAAQAAAAAAAAARAFN0clNjdHh8fHxU
+			dXBsZXRzAAwAYWJjQUJDMTIzNDU2GABUaW1lc05ld1JvbWFuUFMt
+			SXRhbGljTVT/////AAAAAHRTeFQBAAQAAAAUAAAA//////////8C
+			AAAAAQCcAAAAAAAAAGwGAAAAAAAAHgAeAAAAU3RyU2N0eHx8fFJl
+			cGVhdCBFbmRpbmcAAAAAAAAAAAAAAAAAAABUaW1lcwBvAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAAAQAAAAAAAAAYAFN0
+			clNjdHh8fHxSZXBlYXQgRW5kaW5ncwwAYWJjQUJDMTIzNDU2BQBU
+			aW1lcwD/////AAAAAHRTeFQBAAQAAAAYAAAA//////////8CAAAA
+			AQCYAAAAAAAAAGwGAAAAAAAAHgAeAAAAU3RyU2N0eHx8fENob3Jk
+			IFJvb3QAAAAAAAAAAAAAAAAAAAAAAABUaW1lcwBvAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAOAAAAAQAAAAAAAAAUAFN0clNj
+			dHh8fHxDaG9yZCBSb290DABhYmNBQkMxMjM0NTYFAFRpbWVzAP//
+			//8AAAAAdFN4VAEABAAAABwAAAD//////////wIAAAABAJgAAAAA
+			AAAAbAYAAAAAAAAeAB4AAABTdHJTY3R4fHx8Q2hvcmQgRXh0LgAA
+			AAAAAAAAAAAAAAAAAAAAAFRpbWVzAG8AAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAoAAAABAAAAAAAAABQAU3RyU2N0eHx8fENo
+			b3JkIEV4dC4MAGFiY0FCQzEyMzQ1NgUAVGltZXMA/////wAAAAB0
+			U3hUAQAEAAAAIAAAAP//////////AgAAAAEAmgAAAAAAAABsBgAA
+			AAAAAB4AHgAAAFN0clNjdHh8fHxNdWx0LiBSZXN0cwAAAAAAAAAA
+			AAAAAAAAAAAAVGltZXMAbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAADAAAAAEAAAAAAAAAFQBTdHJTY3R4fHx8TXVsdC4gUmVz
+			dHMADABhYmNBQkMxMjM0NTYFAFRpbWVzAP////8AAAAAdFN4VAEA
+			BAAAACQAAAD//////////wIAAAABAJgAAAAAAAAAbAYAAAAAAAAe
+			AB4AAABTdHJTY3R4fHx8VGFibGF0dXJlAAAAAAAAAAAAAAAAAAAA
+			AAAAAFRpbWVzAG8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAgAAAABAAAAAAAAABMAU3RyU2N0eHx8fFRhYmxhdHVyZQAMAGFi
+			Y0FCQzEyMzQ1NgUAVGltZXMA/////wAAAAB0U3hUAQAEAAAAKAAA
+			AP//////////AgAAAAEAnAAAAAAAAABsBgAAAAAAAB4AHgAAAFN0
+			clNjdHh8fHxUZW1wbyBTeW1ib2xzAAAAAAAAAAAAAAAAAAAAVGlt
+			ZXMAbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACgAAAAEA
+			AAAAAAAAFwBTdHJTY3R4fHx8VGVtcG8gU3ltYm9scwAMAGFiY0FC
+			QzEyMzQ1NgUAVGltZXMA/////wAAAAB0U3hUAQAEAAAALAAAAP//
+			////////AgAAAAEArgAAAAAAAABsBgAAAAAAAB4AHgAAAFN0clNj
+			dHh8fHxPY3RhdmUgU3ltYm9sAAAAAAAAAAAAAAAAAAAAVGltZXNO
+			ZXdSb21hblBTLUl0YWxpY01UAAAAAAAAAAAAAAAACQACAAEAAAAA
+			AAAAGABTdHJTY3R4fHx8T2N0YXZlIFN5bWJvbHMMAGFiY0FCQzEy
+			MzQ1NhgAVGltZXNOZXdSb21hblBTLUl0YWxpY01U/////wAAAAB0
+			U3hUAQAEAAAAMAAAAP//////////AgAAAAEAmAAAAAAAAABsBgAA
+			AAAAAB4AHgAAAFN0clNjdHh8fHxOb3RlIEhlYWRzAAAAAAAAAAAA
+			AAAAAAAAAAAAVGltZXMAbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAACAAAAAEAAAAAAAAAFABTdHJTY3R4fHx8Tm90ZSBIZWFk
+			cwwAYWJjQUJDMTIzNDU2BQBUaW1lcwD/////AAAAAHRTeFQBAAQA
+			AAA0AAAA//////////8CAAAAAQCkAAAAAAAAAGwGAAAAAAAAHgAe
+			AAAAU3RyU2N0eHx8fEd1aXRhciBHcmlkIEYAAAAAAAAAAAAAAAAA
+			AABUaW1lcwBvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI
+			AAAAAQAAAAAAAAAgAFN0clNjdHh8fHxHdWl0YXIgR3JpZCBGaW5n
+			ZXJpbmdzDABhYmNBQkMxMjM0NTYFAFRpbWVzAP////8AAAAAdFN4
+			VAEABAAAADgAAAD//////////wIAAAABAJ4AAAAAAAAAbAYAAAAA
+			AAAeAB4AAABTdHJTY3R4fHx8R3VpdGFyIE1hcmtpbgAAAAAAAAAA
+			AAAAAAAAAFRpbWVzAG8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAgAAAABAAAAAAAAABkAU3RyU2N0eHx8fEd1aXRhciBNYXJr
+			aW5ncwAMAGFiY0FCQzEyMzQ1NgUAVGltZXMA/////wAAAAB0U3hU
+			AQAEAAAAPAAAAP//////////AgAAAAEAmAAAAAAAAABsBgAAAAAA
+			AB4AHgAAAFN0clNjdHh8fHxGaW5nZXJpbmdzAAAAAAAAAAAAAAAA
+			AAAAAAAAVGltZXMAbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAACAAAAAEAAAAAAAAAFABTdHJTY3R4fHx8RmluZ2VyaW5ncwwA
+			YWJjQUJDMTIzNDU2BQBUaW1lcwD/////AAAAAHRTeFQBAAQAAABA
+			AAAA//////////8CAAAAAQCOAAAAAAAAAGwGAAAAAAAAHgAeAAAA
+			cmVzZXJ2ZWQxNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABU
+			aW1lcwBvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAA
+			BAAAAAAAAAAKAHJlc2VydmVkMTYMAGFiY0FCQzEyMzQ1NgUAVGlt
+			ZXMA/////wAAAAB0U3hUAQAEAAAARAAAAP//////////AgAAAAEA
+			jgAAAAAAAABsBgAAAAAAAB4AHgAAAHJlc2VydmVkMTcAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAVGltZXMAbwAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAACgByZXNlcnZl
+			ZDE3DABhYmNBQkMxMjM0NTYFAFRpbWVzAP////8AAAAAdFN4VAEA
+			BAAAAEgAAAD//////////wIAAAABAI4AAAAAAAAAbAYAAAAAAAAe
+			AB4AAAByZXNlcnZlZDE4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAFRpbWVzAG8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAgAAAAEAAAAAAAAAAoAcmVzZXJ2ZWQxOAwAYWJjQUJDMTIzNDU2
+			BQBUaW1lcwD/////AAAAAHRTeFQBAAQAAABMAAAA//////////8C
+			AAAAAQCOAAAAAAAAAGwGAAAAAAAAHgAeAAAAcmVzZXJ2ZWQxOQAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUaW1lcwBvAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAKAHJl
+			c2VydmVkMTkMAGFiY0FCQzEyMzQ1NgUAVGltZXMA/////wAAAAB0
+			U3hUAQAEAAAAUAAAAP//////////AgAAAAEAjgAAAAAAAABsBgAA
+			AAAAAB4AHgAAAHJlc2VydmVkMjAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAVGltZXMAbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAACAAAAAQAAAAAAAAACgByZXNlcnZlZDIwDABhYmNBQkMx
+			MjM0NTYFAFRpbWVzAP////8AAAAAdFN4VAEABAAAAFQAAAD/////
+			/////wIAAAABAI4AAAAAAAAAbAYAAAAAAAAeAB4AAAByZXNlcnZl
+			ZDIxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRpbWVzAG8A
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAAAAAA
+			AAoAcmVzZXJ2ZWQyMQwAYWJjQUJDMTIzNDU2BQBUaW1lcwD/////
+			AAAAAHRTeFQBAAQAAABYAAAA//////////8CAAAAAQCOAAAAAAAA
+			AGwGAAAAAAAAHgAeAAAAcmVzZXJ2ZWQyMgAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAABUaW1lcwBvAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAIAAAABAAAAAAAAAAKAHJlc2VydmVkMjIMAGFi
+			Y0FCQzEyMzQ1NgUAVGltZXMA/////wAAAAB0U3hUAQAEAAAAXAAA
+			AP//////////AgAAAAEAjgAAAAAAAABsBgAAAAAAAB4AHgAAAHJl
+			c2VydmVkMjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVGlt
+			ZXMAbwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQA
+			AAAAAAAACgByZXNlcnZlZDIzDABhYmNBQkMxMjM0NTYFAFRpbWVz
+			AP////8AAAAAdFN4VAEABAAAAGAAAAD//////////wIAAAABAI4A
+			AAAAAAAAbAYAAAAAAAAeAB4AAAByZXNlcnZlZDI0AAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAFRpbWVzAG8AAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAAAAAAAAoAcmVzZXJ2ZWQy
+			NAwAYWJjQUJDMTIzNDU2BQBUaW1lcwD/////AAAAAHRTeFQBAAQA
+			AABkAAAA//////////8CAAAAAQCOAAAAAAAAAGwGAAAAAAAAHgAe
+			AAAAcmVzZXJ2ZWQyNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AABUaW1lcwBvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI
+			AAAABAAAAAAAAAAKAHJlc2VydmVkMjUMAGFiY0FCQzEyMzQ1NgUA
+			VGltZXMA/////wAAAAB0U3hUAQAEAAAAaAAAAP//////////AgAA
+			AAEAjgAAAAAAAABsBgAAAAAAAB4AHgAAAHJlc2VydmVkMjYAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVGltZXMAbwAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAQAAAAAAAAACgByZXNl
+			cnZlZDI2DABhYmNBQkMxMjM0NTYFAFRpbWVzAP////8AAAAAdFN4
+			VAEABAAAAGwAAAD//////////wIAAAABAI4AAAAAAAAAbAYAAAAA
+			AAAeAB4AAAByZXNlcnZlZDI3AAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAFRpbWVzAG8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAgAAAAEAAAAAAAAAAoAcmVzZXJ2ZWQyNwwAYWJjQUJDMTIz
+			NDU2BQBUaW1lcwD/////AAAAAHRTeFQBAAQAAABwAAAA////////
+			//8CAAAAAQCOAAAAAAAAAGwGAAAAAAAAHgAeAAAAcmVzZXJ2ZWQy
+			OAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUaW1lcwBvAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAK
+			AHJlc2VydmVkMjgMAGFiY0FCQzEyMzQ1NgUAVGltZXMA/////wAA
+			AAB0U3hUAQAEAAAAdAAAAP//////////AgAAAAEAjgAAAAAAAABs
+			BgAAAAAAAB4AHgAAAHJlc2VydmVkMjkAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAVGltZXMAbwAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAACAAAAAQAAAAAAAAACgByZXNlcnZlZDI5DABhYmNB
+			QkMxMjM0NTYFAFRpbWVzAP////8AAAAAdFN4VAEABAAAAHgAAAD/
+			/////////wIAAAABAI4AAAAAAAAAbAYAAAAAAAAeAB4AAAByZXNl
+			cnZlZDMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFRpbWVz
+			AG8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAEAAAA
+			AAAAAAoAcmVzZXJ2ZWQzMAwAYWJjQUJDMTIzNDU2BQBUaW1lcwD/
+			////AAAAAHRTeFQBAAQAAAB8AAAA//////////8CAAAAAQCOAAAA
+			AAAAAGwGAAAAAAAAHgAeAAAAcmVzZXJ2ZWQzMQAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABUaW1lcwBvAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAIAAAABAAAAAAAAAAKAHJlc2VydmVkMzEM
+			AGFiY0FCQzEyMzQ1NgUAVGltZXMA/////wAAAABsRnVBAQALAAAA
+			AAAAAP//////////AgAAAAEAUgIAAAAAAAAaB///GgcAAA0AcgBp
+			AG4AZwB0AG8AbgBlAC4AYQBpAGYAZgBMRlVBAQUAAQAAcmluZ3Rv
+			bmUuYWlmZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAvdmFyL21vYmlsZS9Db250YWluZXJzL0RhdGEvQXBwbGlj
+			YXRpb24vNzc2N0Q0MzUtMDJEQy00NDQ0LThDQzItRjI3RjUyMTQ4
+			Njg5L0xpYnJhcnkvQXBwbGljYXRpb24gU3VwcG9ydC9Eb2N1bWVu
+			dHMv5oiR55qE5LmQ5puyLmJhbmQvTWVkaWEAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAgAAAAAA
+			5AySAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABG
+			RklBAAAAAAACAAC5giQAAAAAAESsAAACABAAx8Y/yd52TfKqjZmX
+			uy7T9gAAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAADkkAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABnUnVB
+			AQALAAAAAAAAAAAAAAD/////AgAAAAEAzgAAAAAAAAABAAAoAAAA
+			AAAAAAAAAAAAAAAAAAAADF0dAAAAAAAAAAAAAAAAAAEAAAAgcmlu
+			Z3RvbmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAcmluZ3RvbmUA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAP////8AAAAAAAAAAAAAAAAAAAAA
+			AAAAAGx5dFMBAAwAAAAAAAAA//////////8CAAAAAQBgAAAAAAAA
+			AFwCAAAAAAAAAAAAAAAAIEF1dG8AdHlsZQAAAAAAAAAAAAAAAAAA
+			BQAgQXV0bwA2AAEBAAAAAAAAAH8AfwcARgBGAAIIAAD/PP//AH8A
+			CgEIAAAAAAAAAAAAAAAAAAAAAGx5dFMBAAwAAAAEAAAA////////
+			//8CAAAAAQCEAAAAAAAAAIQCAAEAAAAAAAAAAAAAIFBpYW5vAHls
+			ZQAAAAAAAAAAAAAAAAAABgAgUGlhbm9eAAECAAAAAAAAAH8AfwcA
+			PAAyAAIIAAD/PP//PH8ACgEIAAAAAAAAAAAAAAAAAAAAAD84MgA8
+			AAEIAAD/PP//ADsACgEIAAAAAAAAAAAAAAAAAAAAAGx5dFMBAAwA
+			AAAIAAAA//////////8CAAAAAQCIAAAAAAAAAIQCAAEAAAAAAAAA
+			AAAAUGlhbm8gMS8zAAAAAAAAAAAAAAAAAAAACQBQaWFubyAxLzMA
+			XgABAgAAAAAAAAB/AH8HADwAMgACCAAAADwBAAB/AAoBCAAAAAAA
+			AAAAAAAAAAAAAAA/ODIAPAABCAAAAjwEAAB/AAoBCAAAAAAAAAAA
+			AAAAAAAAAABseXRTAQAMAAAADAAAAP//////////AgAAAAEArgAA
+			AAAAAACsAgABAAAAAAAAAAAAAFBpYW5vIDErMi8zAAAAAAAAAAAA
+			AAAAAAsAUGlhbm8gMSsyLzMAhgABAwAAAAAAAAB/AH8HADwAMgAC
+			CAAAADwBAAB/AAoBCQAAAAAAAAAAAAAAAAAAAAADADwAMgACCAAA
+			ATwCAAB/AAoBCgAAAAAAAAAAAAAAAAAAAAA/ODIAPAABCAAAAjwE
+			AAB/AAoBCAAAAAAAAAAAAAAAAAAAAABseXRTAQAMAAAAEAAAAP//
+			////////AgAAAAEArgAAAAAAAACsAgABAAAAAAAAAAAAAFBpYW5v
+			IDEvMys0AAAAAAAAAAAAAAAAAAsAUGlhbm8gMS8zKzQAhgABAwAA
+			AAAAAAB/AH8HADwAMgACCAAAADwBAAB/AAoBCAAAAAAAAAAAAAAA
+			AAAAAAA/ODIAPAABCAAAAjwEAAB/AAoBCQAAAAAAAAAAAAAAAAAA
+			AAA7ADIAPAABCAAAAzwIAAB/AAoBCgAAAAAAAAAAAAAAAAAAAABs
+			eXRTAQAMAAAAFAAAAP//////////AgAAAAEA1AAAAAAAAADUAgAB
+			AAAAAAAAAAAAAFBpYW5vIDErMi8zKzQAAAAAAAAAAAAAAA0AUGlh
+			bm8gMSsyLzMrNACuAAEEAAAAAAAAAH8AfwcAPAAyAAIIAAAAPAEA
+			AH8ACgEJAAAAAAAAAAAAAAAAAAAAAAMAPAAyAAIIAAABPAIAAH8A
+			CgEKAAAAAAAAAAAAAAAAAAAAAD84MgA8AAEIAAACPAQAAH8ACgEJ
+			AAAAAAAAAAAAAAAAAAAAADsAMgA8AAEIAAADPAgAAH8ACgEKAAAA
+			AAAAAAAAAAAAAAAAAGx5dFMBAAwAAAAYAAAA//////////8CAAAA
+			AQCuAAAAAAAAAKwCAAEAAAAAAAAAAAAAT3JnYW4gMS8xLzUAAAAA
+			AAAAAAAAAAAACwBPcmdhbiAxLzEvNQCGAAEDAAAAAAAAAH8AfwcA
+			PAAyAAIIAAAAPAEAPH8ACgEIAAAAAAAAAAAAAAAAAAAAAD8wMgA8
+			AAEIAAAAPAEAADsACgEIAAAAAAAAAAAAAAAAAAAAAA8IMgA8AAEI
+			AAAEPBAAAH8ACgEIAAAAAAAAAAAAAAAAAAAAAGx5dFMBAAwAAAAc
+			AAAA//////////8CAAAAAQCuAAAAAAAAAKwCAAEAAAAAAAAAAAAA
+			T3JnYW4gMS8zLzUAAAAAAAAAAAAAAAAACwBPcmdhbiAxLzMvNQCG
+			AAEDAAAAAAAAAH8AfwcAPAAyAAIIAAAAPAEAAH8ACgEIAAAAAAAA
+			AAAAAAAAAAAAAD8wMgA8AAEIAAACPAQAAH8ACgEIAAAAAAAAAAAA
+			AAAAAAAAAA8IMgA8AAEIAAAEPBAAAH8ACgEIAAAAAAAAAAAAAAAA
+			AAAAAGx5dFMBAAwAAAAgAAAA//////////8CAAAAAQDUAAAAAAAA
+			ANQCAAEAAAAAAAAAAAAAT3JnYW4gMSsyLzMvNQAAAAAAAAAAAAAA
+			DQBPcmdhbiAxKzIvMy81AK4AAQQAAAAAAAAAfwB/BwA8ADIAAggA
+			AAA8AQAAfwAKAQkAAAAAAAAAAAAAAAAAAAAAAwA8ADIAAggAAAE8
+			AgAAfwAKAQoAAAAAAAAAAAAAAAAAAAAAPzAyADwAAQgAAAI8BAAA
+			fwAKAQgAAAAAAAAAAAAAAAAAAAAADwgyADwAAQgAAAQ8EAAAfwAK
+			AQgAAAAAAAAAAAAAAAAAAAAAbHl0UwEADAAAACQAAAD/////////
+			/wIAAAABANQAAAAAAAAA1AIAAQAAAAAAAAAAAABPcmdhbiAxLzMr
+			NC81AAAAAAAAAAAAAAANAE9yZ2FuIDEvMys0LzUArgABBAAAAAAA
+			AAB/AH8HADwAMgACCAAAADwBAAB/AAoBCAAAAAAAAAAAAAAAAAAA
+			AAA/MDIAPAABCAAAAjwEAAB/AAoBCQAAAAAAAAAAAAAAAAAAAAA7
+			ADIAPAABCAAAAzwIAAB/AAoBCgAAAAAAAAAAAAAAAAAAAAAPCDIA
+			PAABCAAABDwQAAB/AAoBCAAAAAAAAAAAAAAAAAAAAABseXRTAQAM
+			AAAAKAAAAP//////////AgAAAAEA+gAAAAAAAAD8AgABAAAAAAAA
+			AAAAAE9yZ2FuIDErMi8zKzQvNQAAAAAAAAAAAA8AT3JnYW4gMSsy
+			LzMrNC81ANYAAQUAAAAAAAAAfwB/BwA8ADIAAggAAAA8AQAAfwAK
+			AQkAAAAAAAAAAAAAAAAAAAAAAwA8ADIAAggAAAE8AgAAfwAKAQoA
+			AAAAAAAAAAAAAAAAAAAAPzAyADwAAQgAAAI8BAAAfwAKAQkAAAAA
+			AAAAAAAAAAAAAAAAOwAyADwAAQgAAAM8CAAAfwAKAQoAAAAAAAAA
+			AAAAAAAAAAAADwgyADwAAQgAAAQ8EAAAfwAKAQgAAAAAAAAAAAAA
+			AAAAAAAAbHl0UwEADAAAACwAAAD//////////wIAAAABAGAAAAAA
+			AAAAXAIAAAAAAAAAAAAAAAAgQmFzcwB0eWxlAAAAAAAAAAAAAAAA
+			AAAFACBCYXNzADYAAQEAAAAAAAAAfwB/BwBGAEYAAQgAAP88//8A
+			fwAKAQgAAAAAAAAAAAAAAAAAAAAAbHl0UwEADAAAADAAAAD/////
+			/////wIAAAABAGQAAAAAAAAAXAIAAAAAAAAAAAAAAAAgVHJlYmxl
+			KzgAAAAAAAAAAAAAAAAAAAAJACBUcmVibGUrOAA2AAEBAAAAAAAA
+			AH8AfwcARgBGAAMIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAA
+			AGx5dFMBAAwAAAA0AAAA//////////8CAAAAAQBoAAAAAAAAAFwC
+			AAAAAAAAAAAAAAAAVHJ1bXBldCBpbiBCYgAAAAAAAAAAAAAADQBU
+			cnVtcGV0IGluIEJiADYAAQEAAAAAAAAAfwB/BwBGAEYAAggAAP88
+			//8AfwIKAQgAAAAAAAAAAAAAAAAAAAAAbHl0UwEADAAAADgAAAD/
+			/////////wIAAAABAGYAAAAAAAAAXAIAAAAAAAAAAAAAAABUcnVt
+			cGV0IGluIEEAAAAAAAAAAAAAAAAMAFRydW1wZXQgaW4gQTYAAQEA
+			AAAAAAAAfwB/BwBGAEYAAggAAP88//8AfwMKAQgAAAAAAAAAAAAA
+			AAAAAAAAbHl0UwEADAAAADwAAAD//////////wIAAAABAGQAAAAA
+			AAAAXAIAAAAAAAAAAAAAAABIb3JuIGluIEYAAAAAAAAAAAAAAAAA
+			AAAJAEhvcm4gaW4gRgA2AAEBAAAAAAAAAH8AfwcARgBGAAIIAAD/
+			PP//AH8HCgEIAAAAAAAAAAAAAAAAAAAAAGx5dFMBAAwAAABAAAAA
+			//////////8CAAAAAQBkAAAAAAAAAFwCAAAAAAAAAAAAAAAASG9y
+			biBpbiBFYgAAAAAAAAAAAAAAAAAACgBIb3JuIGluIEViNgABAQAA
+			AAAAAAB/AH8HAEYARgACCAAA/zz//wB//QoBCAAAAAAAAAAAAAAA
+			AAAAAABseXRTAQAMAAAARAAAAP//////////AgAAAAEAYgAAAAAA
+			AABcAgAAAAAAAAAAAAAAAFBpY2NvbG8AbGUAAAAAAAAAAAAAAAAA
+			AAcAUGljY29sbwA2AAEBAAAAAAAAAH8AfwcARgBGAAIIAAD/PP//
+			AH/0CgEIAAAAAAAAAAAAAAAAAAAAAGx5dFMBAAwAAABIAAAA////
+			//////8CAAAAAQBmAAAAAAAAAFwCAAAAAAAAAAAAAAAAQmFyaXRv
+			biBTYXgAAAAAAAAAAAAAAAAACwBCYXJpdG9uIFNheAA2AAEBAAAA
+			AAAAAH8AfwcARgBGAAIIAAD/PP//AH8VCgEIAAAAAAAAAAAAAAAA
+			AAAAAGx5dFMBAAwAAABMAAAA//////////8CAAAAAQBkAAAAAAAA
+			AFwCAAAAAAAAAAAAAAAAVGVub3IgU2F4AAAAAAAAAAAAAAAAAAAA
+			CQBUZW5vciBTYXgANgABAQAAAAAAAAB/AH8HAEYARgACCAAA/zz/
+			/wB/DgoBCAAAAAAAAAAAAAAAAAAAAABseXRTAQAMAAAAUAAAAP//
+			////////AgAAAAEAYgAAAAAAAABcAgAAAAAAAAAAAAAAAEFsdG8g
+			U2F4AGUAAAAAAAAAAAAAAAAAAAgAQWx0byBTYXg2AAEBAAAAAAAA
+			AH8AfwcARgBGAAIIAAD/PP//AH8JCgEIAAAAAAAAAAAAAAAAAAAA
+			AGx5dFMBAAwAAABUAAAA//////////8CAAAAAQBmAAAAAAAAAFwC
+			AAAAAAAAAAAAAAAAU29wcmFubyBTYXgAAAAAAAAAAAAAAAAACwBT
+			b3ByYW5vIFNheAA2AAEBAAAAAAAAAH8AfwcARgBGAAIIAAD/PP//
+			AH8CCgEIAAAAAAAAAAAAAAAAAAAAAGx5dFMBAAwAAABYAAAA////
+			//////8CAAAAAQBgAAAAAAAAAFwCAAAAAAAAAAAAAAAAVmlvbGEA
+			dHlsZQAAAAAAAAAAAAAAAAAABQBWaW9sYQA2AAEBAAAAAAAAAH8A
+			fwcARgBGAAcIAAD/PP//AH8ACgEIAAAAAAAAAAAAAAAAAAAAAGx5
+			dFMBAAwAAABcAAAA//////////8CAAAAAQBmAAAAAAAAAFwCAAAA
+			AAAAAAAAAAAAVmlvbG9uY2VsbG8AAAAAAAAAAAAAAAAACwBWaW9s
+			b25jZWxsbwA2AAEBAAAAAAAAAH8AfwcARgBGAAEIAAD/PP//AH8A
+			CgEIAAAAAAAAAAAAAAAAAAAAAGx5dFMBAAwAAABgAAAA////////
+			//8CAAAAAQBkAAAAAAAAAFwCAAAAAAAAAAAAAAAAQ29udHJhYmFz
+			cwAAAAAAAAAAAAAAAAAACgBDb250cmFiYXNzNgABAQAAAAAAAAB/
+			AH8HAEYARgAACAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAABs
+			eXRTAQAMAAAAZAAAAP//////////AgAAAAEAZAAAAAAAAABcAgAA
+			AAAAAAAAAAAAACBUcmVibGUtOAAAAAAAAAAAAAAAAAAAAAkAIFRy
+			ZWJsZS04ADYAAQEAAAAAAAAAfwB/BwBGAEYABAgAAP88//8AfwAK
+			AQgAAAAAAAAAAAAAAAAAAAAAbHl0UwEADAAAAGgAAAD/////////
+			/wIAAAABAGIAAAAAAAAAXAIAAAAAAAAAAAAAAAAgVHJlYmxlAGxl
+			AAAAAAAAAAAAAAAAAAAHACBUcmVibGUANgABAQAAAAAAAAB/AH8H
+			AEYARgACCAAA/zz//wB/AAoBCAAAAAAAAAAAAAAAAAAAAABseXRT
+			AQAMAAAAbAAAAP//////////AgAAAAEA8AAAAAAAAAD8AgABAAAA
+			AAAAAAAAAERydW1zAHR5bGUAAAAAAAAAAAAAAAAAAAUARHJ1bXMA
+			1gACBQAAAAAAAAB/AH8HADwAMgAPCAAAAjwEAAB/AAoBBQAAAAAA
+			AAAAAAAAAAAAAAABADwAMgAPCAAABDwQAAB/AgoBCAAAAAAAAAAA
+			AAAAAAAAAAABADwAMgAPCAAAAzwIAAB//woBCAAAAAAAAAAAAAAA
+			AAAAAAADADwAMgAPCAAAATwCAAB//AoBBgAAAAAAAAAAAAAAAAAA
+			AAABADwAMgAPCAAAADwBAAB/+AoBCAAAAAAAAAAAAAAAAAAAAABs
+			eXRTAQAMAAAAcAAAAP//////////AgAAAAEAYAAAAAAAAABcAgAA
+			AAAAAAAAAAAAAEd1aXRhcgB5bGUAAAAAAAAAAAAAAAAAAAYAR3Vp
+			dGFyNgABAQAAAAAAAAB/AH8HAEYARgAcCgAA/zz//wB/AAoBBgAA
+			AAAAAAAAAAAAAAAAAABseXRTAQAMAAAAdAAAAP//////////AgAA
+			AAEAiAAAAAAAAACEAgABAAAAAAAAAAAAAEd1aXRhciBNaXgAAAAA
+			AAAAAAAAAAAAAAoAR3VpdGFyIE1peF4AAQIAAAAAAAAAfwB/BwA8
+			ADIAHAoAAP88//8AfwAKAQYAAAAAAAAAAAAAAAAAAAAAPzgyADwA
+			BAgAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAbHl0UwEADAAA
+			AHgAAAD//////////wIAAAABAGYAAAAAAAAAXAIAAAAAAAAAAAAA
+			AAAgTGVhZCBTaGVldAAAAAAAAAAAAAAAAAALACBMZWFkIFNoZWV0
+			ADYAAQEAAAAAAAAAfwB/BwBGAEYAAggAAP88//8AfwAKAggAAAAA
+			AAAAAAAAAAAAAAAAbHl0UwEADAAAAHwAAAD//////////wIAAAAB
+			AIoAAAAAAAAAhAIAAQAAAAAAAAAAAABHdWl0YXIgTWl4IDIAAAAA
+			AAAAAAAAAAAMAEd1aXRhciBNaXggMl4AAQIAAAAAAAAAfwB/BwA8
+			ADIABAgAAP88//8AfwAKAQgAAAAAAAAAAAAAAAAAAAAAPzgyADwA
+			HAoAAP88//8AfwAKAQYAAAAAAAAAAAAAAAAAAAAAcnlhTAEADgAA
+			AAgAAAD//////////wIAAAABAOQAAAAAAAAAoAoAAAAAAAAAAAAA
+			AAAAACBBbGwgT2JqZWN0cwAAAAALAEFsbCBPYmplY3RzAAAAAAAA
+			AAAAAAAAAAAAAAAgR2xvYmFsIE9iamVjdHMADgBHbG9iYWwgT2Jq
+			ZWN0cwAAAAAAAAAAAAAAAAAAAAAgQ2xpY2sgJiBQb3J0cwAADQBD
+			bGljayAmIFBvcnRzAAAAAAAAAAAAAAAAAAAAAAAgTUlESSBJbnN0
+			ci4AAAAACwBNSURJIEluc3RyLgAAAAAAAAAAAAAAAAAAAAAAIE1p
+			eGVyAAAAAAAAAAAAAAUATWl4ZXIAdFNjUwEADgAAAAwAAAD/////
+			/////wIAAAABAKgOAAAAAAAAme0AAAbWAAAAAAAAAAAAAAAAFAAU
+			AAcAAAAAIBAgF/4AAQQEAAAQEMkAyQDJAMkAAACTAUd1aXRhcgAA
+			AAAAAAAAAAAAAAAAAAAAADQ5PkNHTFFWIygtMjc8QUYABgAAAAAA
+			AAAAAAAAAAYAR3VpdGFyR3VpdGFyIEQAAAAAAAAAAAAAAAAAAAAA
+			Mjk+QkVKUVYjKC0yNzxBRgAGAAAAAAAAAAAAAAAACABHdWl0YXIg
+			REd1aXRhciBHAAAAAAAAAAAAAAAAAAAAADI3PkNHSlFWIygtMjc8
+			QUYABgAAAAAAAAAAAAAAAAgAR3VpdGFyIEdHdWl0YXIgbG8gRwAA
+			AAAAAAAAAAAAAAArNz5DR0pRViMoLTI3PEFGAAYAAAAAAAAAAAAA
+			AAALAEd1aXRhciBsbyBHAEd1aXRhciBENwAAAAAAAAAAAAAAAAAA
+			ADI5PEJFSlFWIygtMjc8QUYABgAAAAAAAAAAAAAAAAkAR3VpdGFy
+			IEQ3AEd1aXRhciBDRwAAAAAAAAAAAAAAAAAAADA3PkNHSlFWIygt
+			Mjc8QUYABgAAAAAAAAAAAAAAAAkAR3VpdGFyIENHAEd1aXRhciBD
+			RAAAAAAAAAAAAAAAAAAAADA3PkFITFFWIygtMjc8QUYABgAAAAAA
+			AAAAAAAAAAkAR3VpdGFyIENEAEJhc3MgNAAAAAAAAAAAAAAAAAAA
+			AAAAACgtMjc8QUYAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAYAQmFz
+			cyA0QmFzcyA1L0MAAAAAAAAAAAAAAAAAAAAAJCgtMjc8QUYAAAAA
+			AAAAAAAFAAAAAAAAAAAAAAAACABCYXNzIDUvQ0Jhc3MgNS9CAAAA
+			AAAAAAAAAAAAAAAAACMoLTI3PEFGAAAAAAAAAAAABQAAAAAAAAAA
+			AAAAAAgAQmFzcyA1L0JCYXNzIDYvQwAAAAAAAAAAAAAAAAAAAAAk
+			KC0yNzxBRgAAAAAAAAAAAAYAAAAAAAAAAAAAAAAIAEJhc3MgNi9D
+			QmFzcyA2L0IAAAAAAAAAAAAAAAAAAAAAIygtMjc8QUYAAAAAAAAA
+			AAAGAAAAAAAAAAAAAAAACABCYXNzIDYvQgAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAS2ljawAAAAAAAAAAU25hcmUAAAAAAAAA
+			SGlIYXQAAAAAAAAAVG9tcwAAAAAAAAAAQ3ltYmFscwAAAAAAQ29u
+			Z2FzAAAAAAAAQ293YmVsbHMAAAAAQm9uZ29zAAAAAAAAKiBOZXcg
+			R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv
+			dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAA
+			KiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO
+			ZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg
+			R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv
+			dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAA
+			KiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO
+			ZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg
+			R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv
+			dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAA
+			KiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO
+			ZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg
+			R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv
+			dXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAA
+			KiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBO
+			ZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcg
+			R3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3JvdXAAKiBOZXcgR3Jv
+			dXAAAAABAAAAkAAEAAMAAAAAAAAAS2R9BktkfQAFAAAABQMHAAIA
+			AgwCAgICAgICAgICAAAGBQAAABAQDAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAADJAMkAyQDJAGQA6AMAAMkAyQDJAMkAAADoAwAA
+			yQDJAMkAyQAAAOgDAADJAMkAyQDJAAAAkwEBAAAAAAAAAAD/AAAA
+			AAAAAP8AAAAAAAAA/wBkAJYAAABkAAAAlgAAAGQAlgCWAGQAAACW
+			AAAAZAAAAJYAZAAyAMgAAAAyAAAAyAAAADIAyACWAGQAAACWAAAA
+			ZAAAAJYAZAAyAMgAAAD/AAAAAAAAAP8AAAAAAAAA/wBkAJYAAABk
+			AAAAlgAAAGQAlgCWAGQAAACWAAAAZAAAAJYAZAAyAMgAAAAyAAAA
+			yAAAADIAyAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAENvbG9yIDAAAAAAAAAAAABDb2xvciAx
+			AAAAAAAAAAAAQ29sb3IgMgAAAAAAAAAAAENvbG9yIDMAAAAAAAAA
+			AABDb2xvciA0AAAAAAAAAAAAQ29sb3IgNQAAAAAAAAAAAENvbG9y
+			IDYAAAAAAAAAAABDb2xvciA3AAAAAAAAAAAAQ29sb3IgOAAAAAAA
+			AAAAAENvbG9yIDkAAAAAAAAAAABDb2xvciAxMAAAAAAAAAAAQ29s
+			b3IgMTEAAAAAAAAAAENvbG9yIDEyAAAAAAAAAABDb2xvciAxMwAA
+			AAAAAAAAQ29sb3IgMTQAAAAAAAAAAENvbG9yIDE1AAAAAAAAAABM
+			b2NvAAAAAAAAAAAAAAAAOHZhAAAAAAAAAAAAAAAAADE1bWEAAAAA
+			AAAAAAAAAAA4dmEgYmFzc2EAAAAAAAAAMTVtYSBiYXNzYQAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAABABLaWNrBQBTbmFyZQAFAEhp
+			SGF0AAQAVG9tcwcAQ3ltYmFscwAGAENvbmdhcwgAQ293YmVsbHMG
+			AEJvbmdvcwsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91cAALACog
+			TmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91cAAL
+			ACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91
+			cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBH
+			cm91cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5l
+			dyBHcm91cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAq
+			IE5ldyBHcm91cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAA
+			CwAqIE5ldyBHcm91cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3Jv
+			dXAACwAqIE5ldyBHcm91cAALACogTmV3IEdyb3VwAAsAKiBOZXcg
+			R3JvdXAACwAqIE5ldyBHcm91cAALACogTmV3IEdyb3VwAAsAKiBO
+			ZXcgR3JvdXAACwAqIE5ldyBHcm91cAALACogTmV3IEdyb3VwAAsA
+			KiBOZXcgR3JvdXAACwAqIE5ldyBHcm91cAALACogTmV3IEdyb3Vw
+			AAsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91cAALACogTmV3IEdy
+			b3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91cAALACogTmV3
+			IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91cAALACog
+			TmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91cAAL
+			ACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBHcm91
+			cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5ldyBH
+			cm91cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAqIE5l
+			dyBHcm91cAALACogTmV3IEdyb3VwAAsAKiBOZXcgR3JvdXAACwAq
+			IE5ldyBHcm91cAAHAENvbG9yIDAABwBDb2xvciAxAAcAQ29sb3Ig
+			MgAHAENvbG9yIDMABwBDb2xvciA0AAcAQ29sb3IgNQAHAENvbG9y
+			IDYABwBDb2xvciA3AAcAQ29sb3IgOAAHAENvbG9yIDkACABDb2xv
+			ciAxMAgAQ29sb3IgMTEIAENvbG9yIDEyCABDb2xvciAxMwgAQ29s
+			b3IgMTQIAENvbG9yIDE1BABMb2NvAwA4dmEABAAxNW1hCQA4dmEg
+			YmFzc2EACgAxNW1hIGJhc3NhAABQLk0uAAAAAAAAAAAAAAAAbGV0
+			IHJpbmcAAAAAAAAAAHNsYXAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABuQ3VBAQAOAAAAIAAA
+			AP//////////AgAAAAEAhAAAAAAAAACIAAAAwAAAAAAANRIAAAAA
+			iAAAAAMAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFEBAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABP
+			Q3VBAQAOAAAAIAAAAAAAAAD/////AgAAAAEADgAAAAAAAAAQAAAA
+			//8AAAAANRIAAG5DdUEBAA4AAAAkAAAA//////////8CAAAAAQDE
+			AQAAAAAAAMgBAADAAAAAAAA1EgAAAADKfgAAAwABAAEAUAAiAAIA
+			AwAiAAIAAgABAAAAAAABAAAAAAABAAAAAAAAAAIJAgEAAQABAAAA
+			AAAAAAAJXdGVAAAAAAAAAAAAAAAAIgACAAQAIgACAAIAAQAAAAAA
+			AQAAAAAAAQAAAAAAAAACDwgAAAAAAMgBAABODgAAbg8AAI4QAACu
+			EQAAzhIAAO4TAAAOFQAALhYAAE4XAABuGAAAjhkAAK4aAADOGwAA
+			7hwAAA4eAAAuHwAATiAAAG4hAACOIgAAriMAAM4kAADuJQAADicA
+			AC4oAABOKQAAbioAAI4rAACuLAAAzi0AAO4uAAAOMAAALjEAAE4y
+			AABuMwAANjQAAP40AADGNQAAAn4AAI42AACuNwAAzjgAAO45AAAO
+			OwAALjwAAE49AABuPgAAjj8AAK5AAADOQQAA7kIAAA5EAAAuRQAA
+			TkYAAG5HAACOSAAArkkAAM5KAADuSwAADk0AAC5OAABOTwAAblAA
+			AI5RAACuUgAAzlMAAO5UAAAOVgAALlcAAE5YAABuWQAAjloAAK5b
+			AADWaQAAnmoAAGZrAABubgAARnEAAA5yAADWcgAAT0N1QQEADgAA
+			ACQAAAAAAAAA/////wIAAAABAMQAAAAAAAAAyAAAAEAAAAAAADUS
+			AAAAAIYMAAADAAEAAQEQAAIACQACAAEAAAABAAAAAQAAAAAAAAAA
+			AAAAAAAAAAAAIEF1ZGlvIDEAAAAAAAAAAKv/058AAAAAAFoBAABA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEIAAAAAAABaBgB/AQAAAAAA
+			AAAAyAAAAPQAAAAAAAAAAAAAAAAAAADABgAAQAgAAAAAAAAAAAAA
+			jAIAAAAAAAAAAAAAAAAAACABAADcAQAAoAoAAFVDdUEBAA4AAAAk
+			AAAAAAAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAA
+			AAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAA
+			ACQAAAAAAAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUS
+			AAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAO
+			AAAAJAAAAAAAAAAFAAAAAgAAAAEAuAAAAAAAAAC8AAAAAwAAAAAA
+			NRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAAAAAABgAA
+			AAIAAAABALAAAAAAAAAAsAAAAAUAAAAAADUSAAAAAEF1ZGlvIFJl
+			Y29yZGVyLmNzdAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABCYXNpYyBUcmFjawAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VB
+			AQAOAAAAJAAAAAAAAAAJAAAAAgAAAAEALAQAAAAAAAA0BAAAAQAH
+			AAAANRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEB
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA5AEYAAQFDaGFu
+			bmVsIEVRAABHQU1FAAAAAOwAAAAAACUAAAAAANQAAAABAAAAAAAA
+			AAAAAAAAAAAAAAAAAAEAAAAAAAAAHAAAAN8BAAAcAAAAAwAAAAUA
+			AAADAAAAJAAAAH8AAAAkAAAAAQAAAAEAAAABAAAAYAAAAN8BAABg
+			AAAAMAAAAGAAAAAwAAAAKgAAADQAAAAqAAAAAQAAAAEAAAABAAAA
+			oAAAAN8BAACgAAAAMAAAAGAAAAAwAAAAKgAAAH8AAAAqAAAAAQAA
+			AAEAAAABAAAA3wAAAN8BAADfAAAAMAAAAGAAAAAwAAAAJAAAAH8A
+			AAAkAAAAAQAAAAEAAAABAAAAHAEAAN8BAAAcAQAAMAAAAGAAAAAw
+			AAAAJAAAAH8AAAAkAAAAAQAAAAEAAAABAAAAZgEAAN8BAABmAQAA
+			MAAAAGAAAAAwAAAAJAAAAH8AAAAkAAAAAQAAAAEAAAABAAAArwEA
+			AN8BAACvAQAAMAAAAGAAAAAwAAAAIgAAADQAAAAiAAAAAAAAAAEA
+			AAAAAAAA1AEAAN8BAADUAQAAAQAAAAUAAAABAAAAJAAAAH8AAAAk
+			AAAAMAAAAGAAAAAwAAAAAAAAAAEAAAAAAAAAAAAAAAIAAAAAAAAA
+			BAAAAAwAAAAEAAAAAAAAACgAAAAAAAAAAAAAAAgAAAAAAAAAAQAA
+			AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1AAAAAEAAAAt
+			AAAAR0FNRVRTUFDsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/
+			AACgQgAAAADNzIw/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAHpDAAAA
+			AM3MzD8AAIA/AABIRAAAAACuR2E/AAAAAAAAAAAAAAAAAAAAAAAA
+			gD8AgDtGAAAAAM3MjD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACa
+			mTFBAAAAAAAAAAAAAIC/AAAAQAAAAAAAACBBAACAPwAAgD8AAAAA
+			eDRCRwgAAABVQ3VBAQAOAAAAJAAAAAAAAAANAAAAAgAAAAEAeAEA
+			AAAAAACAAQAAAQADAAAANRIAAC5kZWZhdWx0LmRlZgAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAACAgECAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AQALACMAAgJOb2lzZSBHYXRlAABHQU1FAAAAALMAAAAAABQAAAAA
+			AEgAAAACAgAAAAAAAAAAAAAAAAAAUAAAAGQAAABQAAAAGgAAACgA
+			AAAaAAAAAAAAAHgAAAAAAAAAAQAAAGQAAAABAAAACgAAAGQAAAAK
+			AAAASgAAAMgAAABKAAAAZAAAAGQAAABkAAAAAAAAAGQAAAAAAAAA
+			AQAAAGQAAAABAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAASAAA
+			AAEAAAAMAAAAR0FNRVRTUFCzAAAAAAAAAAAAyMIAAMDAAADIwgAA
+			gD8AACBD1HjYQQBAnEYAAKBBmpkZPwAAAAAAAIA/VUN1QQEADgAA
+			ACQAAAAAAAAADgAAAAIAAAABAFgCAAAAAAAAYAIAAAEABAAAADUS
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQIBAQAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAGQAgAAEBQ29tcHJlc3Nv
+			cgAAR0FNRQAAAACaAAAAAAATAAAAAACAAAAAAQEAAAAAAAAAAAAA
+			AAAAADwAAABkAAAAPAAAAAUAAABVAAAABQAAAAQAAABkAAAABAAA
+			AEMAAAB3AAAAQwAAACAAAABuAAAAIAAAAAoAAAAKAAAACgAAAAEA
+			AAABAAAAAQAAAAEAAAABAAAAAQAAAAAAAAACAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAABAAAA
+			GgAAAEdBTUVUU1BQmgAAAAAAAAAAALzBAACAPwAAIEEAAEBCAACA
+			QDMzMz8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAA3EUAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAA
+			AMhCVUN1QQEADgAAACQAAAAAAAAADwAAAAIAAAABAOIBAAAAAAAA
+			5gEAAAcAAAAAADUSAAAAAM4BAABicGxpc3QwMNQBAgMEBQgoKVQk
+			dG9wWCRvYmplY3RzWCR2ZXJzaW9uWSRhcmNoaXZlctEGB1pkaWN0
+			aW9uYXJ5gAGpCQoXGBkaGxwgVSRudWxs0wsMDQ4SFlpOUy5vYmpl
+			Y3RzV05TLmtleXNWJGNsYXNzow8QEYAFgAaAB6MTFBWAAoADgASA
+			CF1Ccm93c2VySWNvbklkXmlucHV0TWV0aG9kS2V5XxATaW5wdXRN
+			ZXRob2RTZXR0aW5nc1pBUl9EZWZhdWx0XxAPQ2JBdWRpb1JlY29y
+			ZGVy0wsMDR0eFqCggAjSISIjJ1gkY2xhc3Nlc1okY2xhc3NuYW1l
+			oyQlJl8QE05TTXV0YWJsZURpY3Rpb25hcnlcTlNEaWN0aW9uYXJ5
+			WE5TT2JqZWN0XxATTlNNdXRhYmxlRGljdGlvbmFyeRIAAYagXxAP
+			TlNLZXllZEFyY2hpdmVyAAgAEQAWAB8AKAAyADUAQABCAEwAUgBZ
+			AGQAbABzAHcAeQB7AH0AgQCDAIUAhwCJAJcApgC8AMcA2QDgAOEA
+			4gDkAOkA8gD9AQEBFwEkAS0BQwFIAAAAAAAAAgEAAAAAAAAAKgAA
+			AAAAAAAAAAAAAAAAAVpPQ3VBAQAOAAAAJAAAAAEAAAD/////AgAA
+			AAEAxAAAAAAAAADIAAAAQAABAAAANRIAAAAAIAEAAAMAAQAAABAA
+			AgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgQXVkaW8g
+			MgAAAAAAAAAAq//TnwAAAAAAWgAAAEAAAAAAAQAAAAAAAAAAAAAA
+			AAAAAAAAABAAAAAAAFoGAH8BAAAAAAAAAADIAAAA9AAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAABAAAAAAAAAAIAAAAB
+			ACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIAAAAAAAAA
+			AAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAAEAAAABAAAAAgAA
+			AAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMAAgAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAAAgAAAP////8C
+			AAAAAQDEAAAAAAAAAMgAAABAAAIAAAA1EgAAAAAgAQAAAwABAAAA
+			EAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBBdWRp
+			byAzAAAAAAAAAACr/9OfAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAAAAAAAMgAAAD0AAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAAIAAAAAAAAAAgAA
+			AAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIAAgAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAAgAAAAEAAAAC
+			AAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAAAwACAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAAADAAAA////
+			/wIAAAABAMQAAAAAAAAAyAAAAEAAAwAAADUSAAAAACABAAADAAEA
+			AAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAIEF1
+			ZGlvIDQAAAAAAAAAAKv/058AAAAAAFoAAABAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAAAAAAyAAAAPQAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAAwAAAAAAAAAC
+			AAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgACAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAADAAAAAQAA
+			AAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAADAAIA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAAAAQAAAD/
+			////AgAAAAEAxAAAAAAAAADIAAAAQAAEAAAANRIAAAAAIAEAAAMA
+			AQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAg
+			QXVkaW8gNQAAAAAAAAAAq//TnwAAAAAAWgAAAEAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAAAAAADIAAAA9AAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAEAAAAAAAA
+			AAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAAQAAAAB
+			AAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMA
+			AgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAABQAA
+			AP////8CAAAAAQDEAAAAAAAAAMgAAABAAAUAAAA1EgAAAAAgAQAA
+			AwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA
+			ACBBdWRpbyA2AAAAAAAAAACr/9OfAAAAAABaAAAAQAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAAAAAAAMgAAAD0
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAAUAAAAA
+			AAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIA
+			AgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAABQAA
+			AAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAA
+			AwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAAAG
+			AAAA/////wIAAAABAMQAAAAAAAAAyAAAAEAABgAAADUSAAAAACAB
+			AAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAA
+			AAAAIEF1ZGlvIDcAAAAAAAAAAKv/058AAAAAAFoAAABAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAAAAAAyAAA
+			APQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAABgAA
+			AAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAA
+			AgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAG
+			AAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAA
+			AAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAA
+			AAcAAAD/////AgAAAAEAxAAAAAAAAADIAAAAQAAHAAAANRIAAAAA
+			IAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAA
+			AAAAAAAgQXVkaW8gOAAAAAAAAAAAq//TnwAAAAAAWgAAAEAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAAAAAADI
+			AAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAH
+			AAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAA
+			AAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAA
+			AAcAAAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAA
+			AAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAk
+			AAAACAAAAP////8CAAAAAQDEAAAAAAAAAMgAAABAAAgAAAA1EgAA
+			AAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAA
+			AAAAAAAAACBBdWRpbyA5AAAAAAAAAACr/9OfAAAAAABaAAAAQAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAAAAAA
+			AMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAA
+			AAgAAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAA
+			AAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAk
+			AAAACAAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAA
+			AAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAA
+			ACQAAAAJAAAA/////wIAAAABAMQAAAAAAAAAyAAAAEAACQAAADUS
+			AAAAACABAAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAA
+			AAAAAAAAAAAAIEF1ZGlvIDEwAAAAAAAAAKv/058AAAAAAFoAAABA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAA
+			AAAAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAk
+			AAAACQAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAA
+			AAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAA
+			ACQAAAAJAAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUS
+			AAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAO
+			AAAAJAAAAAoAAAD/////AgAAAAEAxAAAAAAAAADIAAAAQAAKAAAA
+			NRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAA
+			AAAAAAAAAAAAAAAgQXVkaW8gMTEAAAAAAAAAq//TnwAAAAAAWgAA
+			AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAA
+			AAAAAADIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAA
+			ACQAAAAKAAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUS
+			AAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAO
+			AAAAJAAAAAoAAAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAA
+			NRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEB
+			AA4AAAAkAAAACwAAAP////8CAAAAAQDEAAAAAAAAAMgAAABAAAsA
+			AAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAA
+			AAAAAAAAAAAAAAAAACBBdWRpbyAxMgAAAAAAAACr/9OfAAAAAABa
+			AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEA
+			AAAAAAAAAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAO
+			AAAAJAAAAAsAAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAA
+			NRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEB
+			AA4AAAAkAAAACwAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEA
+			AAA1EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1
+			QQEADgAAACQAAAAMAAAA/////wIAAAABAMQAAAAAAAAAyAAAAEAA
+			DAAAADUSAAAAACABAAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAA
+			AAAAAAAAAAAAAAAAAAAAIEF1ZGlvIDEzAAAAAAAAAKv/058AAAAA
+			AFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/
+			AQAAAAAAAAAAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEB
+			AA4AAAAkAAAADAAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAA
+			AAA1EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1
+			QQEADgAAACQAAAAMAAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAA
+			AQAAADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABP
+			Q3VBAQAOAAAAJAAAAA0AAAD/////AgAAAAEAxAAAAAAAAADIAAAA
+			QAANAAAANRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAAB
+			AAAAAAAAAAAAAAAAAAAAAAAgQXVkaW8gMTQAAAAAAAAAq//TnwAA
+			AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoG
+			AH8BAAAAAAAAAADIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1
+			QQEADgAAACQAAAANAAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAA
+			AAAAADUSAAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABV
+			Q3VBAQAOAAAAJAAAAA0AAAABAAAAAgAAAAEALAAAAAAAAAAsAAAA
+			AAABAAAANRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AE9DdUEBAA4AAAAkAAAADgAAAP////8CAAAAAQDEAAAAAAAAAMgA
+			AABAAA4AAAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAA
+			AAEAAAAAAAAAAAAAAAAAAAAAACBBdWRpbyAxNQAAAAAAAACr/9Of
+			AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA
+			WgYAfwEAAAAAAAAAAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABV
+			Q3VBAQAOAAAAJAAAAA4AAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAA
+			AAAAAAAANRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AFVDdUEBAA4AAAAkAAAADgAAAAEAAAACAAAAAQAsAAAAAAAAACwA
+			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
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAFQAAAAAAAAACAAAA
+			AQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgACAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAVAAAAAQAAAAIA
+			AAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAADAAIAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAAABYAAAD/////
+			AgAAAAEAxAAAAAAAAADIAAAAQAAWAAAANRIAAAAAIAEAAAMAAQAA
+			ABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgQXVk
+			aW8gMjMAAAAAAAAAq//TnwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAAAAAADIAAAA9AAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAWAAAAAAAAAAIA
+			AAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAABYAAAABAAAA
+			AgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMAAgAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAAFwAAAP//
+			//8CAAAAAQDEAAAAAAAAAMgAAABAABcAAAA1EgAAAAAgAQAAAwAB
+			AAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBB
+			dWRpbyAyNAAAAAAAAACr/9OfAAAAAABaAAAAQAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAAAAAAAMgAAAD0AAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAABcAAAAAAAAA
+			AgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIAAgAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAFwAAAAEA
+			AAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAAAwAC
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAAAYAAAA
+			/////wIAAAABAMQAAAAAAAAAyAAAAEAAGAAAADUSAAAAACABAAAD
+			AAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA
+			IEF1ZGlvIDI1AAAAAAAAAKv/058AAAAAAFoAAABAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAAAAAAyAAAAPQA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAGAAAAAAA
+			AAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgAC
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAYAAAA
+			AQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAAD
+			AAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAAABkA
+			AAD/////AgAAAAEAxAAAAAAAAADIAAAAQAAZAAAANRIAAAAAIAEA
+			AAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAA
+			AAAgQXVkaW8gMjYAAAAAAAAAq//TnwAAAAAAWgAAAEAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAAAAAADIAAAA
+			9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAZAAAA
+			AAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAAC
+			AAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAABkA
+			AAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAA
+			AAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAA
+			GgAAAP////8CAAAAAQDEAAAAAAAAAMgAAABAABoAAAA1EgAAAAAg
+			AQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAA
+			AAAAACBBdWRpbyAyNwAAAAAAAACr/9OfAAAAAABaAAAAQAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAAAAAAAMgA
+			AAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAABoA
+			AAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAA
+			AAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAA
+			GgAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAA
+			AAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQA
+			AAAbAAAA/////wIAAAABAMQAAAAAAAAAyAAAAEAAGwAAADUSAAAA
+			ACABAAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAA
+			AAAAAAAAIEF1ZGlvIDI4AAAAAAAAAKv/058AAAAAAFoAAABAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAAAAAA
+			yAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAA
+			GwAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAA
+			AAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQA
+			AAAbAAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAA
+			AAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAA
+			JAAAABwAAAD/////AgAAAAEAxAAAAAAAAADIAAAAQAAcAAAANRIA
+			AAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAA
+			AAAAAAAAAAAgQXVkaW8gMjkAAAAAAAAAq//TnwAAAAAAWgAAAEAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAAAA
+			AADIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQA
+			AAAcAAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAA
+			AAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAA
+			JAAAABwAAAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIA
+			AAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4A
+			AAAkAAAAHQAAAP////8CAAAAAQDEAAAAAAAAAMgAAABAAB0AAAA1
+			EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAA
+			AAAAAAAAAAAAACBBdWRpbyAzMAAAAAAAAACr/9OfAAAAAABaAAAA
+			QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAA
+			AAAAAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAA
+			JAAAAB0AAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIA
+			AAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4A
+			AAAkAAAAHQAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1
+			EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEA
+			DgAAACQAAAAeAAAA/////wIAAAABAMQAAAAAAAAAyAAAAEAAHgAA
+			ADUSAAAAACABAAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAA
+			AAAAAAAAAAAAAAAAIEF1ZGlvIDMxAAAAAAAAAKv/058AAAAAAFoA
+			AABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAA
+			AAAAAAAAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4A
+			AAAkAAAAHgAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1
+			EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEA
+			DgAAACQAAAAeAAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAA
+			ADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VB
+			AQAOAAAAJAAAAB8AAAD/////AgAAAAEAxAAAAAAAAADIAAAAQAAf
+			AAAANRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAA
+			AAAAAAAAAAAAAAAAAAAgQXVkaW8gMzIAAAAAAAAAq//TnwAAAAAA
+			WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8B
+			AAAAAAAAAADIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEA
+			DgAAACQAAAAfAAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAA
+			ADUSAAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VB
+			AQAOAAAAJAAAAB8AAAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAB
+			AAAANRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9D
+			dUEBAA4AAAAkAAAAIAAAAP////8CAAAAAQDEAAAAAAAAAMgAAABA
+			ACAAAAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEA
+			AAAAAAAAAAAAAAAAAAAAACBBdWRpbyAzMwAAAAAAAACr/9OfAAAA
+			AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYA
+			fwEAAAAAAAAAAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VB
+			AQAOAAAAJAAAACAAAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAA
+			AAAANRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVD
+			dUEBAA4AAAAkAAAAIAAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAA
+			AAEAAAA1EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			T0N1QQEADgAAACQAAAAhAAAA/////wIAAAABAMQAAAAAAAAAyAAA
+			AEAAIQABADUSAAAAACABAAADAAEAAQEQAAIACQACAAEAAAABAAAA
+			AQAAAAAAAAAAAAAAAAAAAAAAIEF1ZGlvIDM0AAAAAAAAAKv/058A
+			AAAAAFkAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABZ
+			BgB/AQAAAAAAAAAAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVD
+			dUEBAA4AAAAkAAAAIQAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAA
+			AAAAAAA1EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			VUN1QQEADgAAACQAAAAhAAAAAQAAAAIAAAABACwAAAAAAAAALAAA
+			AAAAAQAAADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAA
+			AABPQ3VBAQAOAAAAJAAAACIAAAD/////AgAAAAEAxAAAAAAAAADI
+			AAAAQQAAAAAANRIAAAAAyAAAAAMAAQAAABAAAgAJAAIAAQAAAAEA
+			AAABAAAAAAAAAAAAAAAAAAAAAAAgSW5wdXQgMQAAAAAAAAAAKf3T
+			nxAAAAAAAAAAAEAAAP//AAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA
+			AAAGAH8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			T0N1QQEADgAAACQAAAAjAAAA/////wIAAAABAMQAAAAAAAAAyAAA
+			AEEAAQAAADUSAAAAAMgAAAADAAEAAAAQAAIACQACAAEAAAABAAAA
+			AQAAAAAAAAAAAAAAAAAAAAAAIElucHV0IDIAAAAAAAAAACn9058A
+			AAAAAAAAAABAAAD//wEAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAA
+			BgB/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9D
+			dUEBAA4AAAAkAAAAJAAAAP////8CAAAAAQDEAAAAAAAAAMgAAABC
+			AAAAAQA1EgAAAADIAAAAAwABAAEBEAACAAkAAgABAAAAAQAAAAEA
+			AAAAAAAAAAAAAAAAAAAAACBBdXggMQAAAAAAAAAAAACr/defAAAA
+			AABaAQAAQAAAAAD//wAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYA
+			fwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VB
+			AQAOAAAAJAAAACUAAAD/////AgAAAAEAxAAAAAAAAADIAAAAQgAB
+			AAAANRIAAAAAyAAAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAA
+			AAAAAAAAAAAAAAAAAAAgQXV4IDIAAAAAAAAAAAAAq/3TnwAAAAAA
+			WgAAAEAAAAAA//8AAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8B
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEA
+			DgAAACQAAAAmAAAA/////wIAAAABAMQAAAAAAAAAyAAAAEMAAAAA
+			ADUSAAAAACABAAADAAEAAQEQAAIACQACAAEAAAABAAAAAQAAAAAA
+			AAAAAAAAAAAAAAAAIEluc3QgMQAAAAAAAAAAACn9958QAAAAAFoB
+			AABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAA
+			AAAAAAIAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4A
+			AAAkAAAAJgAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1
+			EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEA
+			DgAAACQAAAAmAAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAA
+			ADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VB
+			AQAOAAAAJAAAACcAAAD/////AgAAAAEAxAAAAAAAAADIAAAAQwAB
+			AAAANRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAA
+			AAAAAAAAAAAAAAAAAAAgSW5zdCAyAAAAAAAAAAAAKf3znwAAAAAA
+			WgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8B
+			AAAAAAEAAgDIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEA
+			DgAAACQAAAAnAAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAA
+			ADUSAAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VB
+			AQAOAAAAJAAAACcAAAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAB
+			AAAANRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9D
+			dUEBAA4AAAAkAAAAKAAAAP////8CAAAAAQDEAAAAAAAAAMgAAABD
+			AAIAAAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEA
+			AAAAAAAAAAAAAAAAAAAAACBJbnN0IDMAAAAAAAAAAAAp/fOfAAAA
+			AABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYA
+			fwEAAAAAAgACAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VB
+			AQAOAAAAJAAAACgAAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAA
+			AAAANRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVD
+			dUEBAA4AAAAkAAAAKAAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAA
+			AAEAAAA1EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			T0N1QQEADgAAACQAAAApAAAA/////wIAAAABAMQAAAAAAAAAyAAA
+			AEMAAwAAADUSAAAAACABAAADAAEAAAAQAAIACQACAAEAAAABAAAA
+			AQAAAAAAAAAAAAAAAAAAAAAAIEluc3QgNAAAAAAAAAAAACn9858A
+			AAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABa
+			BgB/AQAAAAADAAIAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVD
+			dUEBAA4AAAAkAAAAKQAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAA
+			AAAAAAA1EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			VUN1QQEADgAAACQAAAApAAAAAQAAAAIAAAABACwAAAAAAAAALAAA
+			AAAAAQAAADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAA
+			AABPQ3VBAQAOAAAAJAAAACoAAAD/////AgAAAAEAxAAAAAAAAADI
+			AAAAQwAEAAAANRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEA
+			AAABAAAAAAAAAAAAAAAAAAAAAAAgSW5zdCA1AAAAAAAAAAAAKf3z
+			nwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAA
+			AFoGAH8BAAAAAAQAAgDIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			VUN1QQEADgAAACQAAAAqAAAAAAAAAAIAAAABACwAAAAAAAAALAAA
+			AAAAAAAAADUSAAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAA
+			AABVQ3VBAQAOAAAAJAAAACoAAAABAAAAAgAAAAEALAAAAAAAAAAs
+			AAAAAAABAAAANRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAE9DdUEBAA4AAAAkAAAAKwAAAP////8CAAAAAQDEAAAAAAAA
+			AMgAAABDAAUAAAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAA
+			AQAAAAEAAAAAAAAAAAAAAAAAAAAAACBJbnN0IDYAAAAAAAAAAAAp
+			/fOfAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAA
+			AAAAWgYAfwEAAAAABQACAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AABVQ3VBAQAOAAAAJAAAACsAAAAAAAAAAgAAAAEALAAAAAAAAAAs
+			AAAAAAAAAAAANRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAFVDdUEBAA4AAAAkAAAAKwAAAAEAAAACAAAAAQAsAAAAAAAA
+			ACwAAAAAAAEAAAA1EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAT0N1QQEADgAAACQAAAAsAAAA/////wIAAAABAMQAAAAA
+			AAAAyAAAAEMABgAAADUSAAAAACABAAADAAEAAAAQAAIACQACAAEA
+			AAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAIEluc3QgNwAAAAAAAAAA
+			ACn9858AAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ
+			AAAAAABaBgB/AQAAAAAGAAIAyAAAAPQAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAFVDdUEBAA4AAAAkAAAALAAAAAAAAAACAAAAAQAsAAAAAAAA
+			ACwAAAAAAAAAAAA1EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAVUN1QQEADgAAACQAAAAsAAAAAQAAAAIAAAABACwAAAAA
+			AAAALAAAAAAAAQAAADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAA
+			AAAAAAAAAABPQ3VBAQAOAAAAJAAAAC0AAAD/////AgAAAAEAxAAA
+			AAAAAADIAAAAQwAHAAAANRIAAAAAIAEAAAMAAQAAABAAAgAJAAIA
+			AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgSW5zdCA4AAAAAAAA
+			AAAAKf3znwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			ABAAAAAAAFoGAH8BAAAAAAcAAgDIAAAA9AAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAVUN1QQEADgAAACQAAAAtAAAAAAAAAAIAAAABACwAAAAA
+			AAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIAAAAAAAAAAAAAAAAA
+			AAAAAAAAAABVQ3VBAQAOAAAAJAAAAC0AAAABAAAAAgAAAAEALAAA
+			AAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAALgAAAP////8CAAAAAQDE
+			AAAAAAAAAMgAAABDAAgAAAA1EgAAAAAgAQAAAwABAAAAEAACAAkA
+			AgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBJbnN0IDkAAAAA
+			AAAAAAAp/fOfAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAEAAAAAAAWgYAfwEAAAAACAACAMgAAAD0AAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAABVQ3VBAQAOAAAAJAAAAC4AAAAAAAAAAgAAAAEALAAA
+			AAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAALgAAAAEAAAACAAAAAQAs
+			AAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAAAwACAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAAAvAAAA/////wIAAAAB
+			AMQAAAAAAAAAyAAAAEMACQAAADUSAAAAACABAAADAAEAAAAQAAIA
+			CQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAIEluc3QgMTAA
+			AAAAAAAAACn9858AAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAQAAAAAABaBgB/AQAAAAAJAAIAyAAAAPQAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAALwAAAAAAAAACAAAAAQAs
+			AAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgACAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAvAAAAAQAAAAIAAAAB
+			ACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAADAAIAAAAAAAAA
+			AAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAAADAAAAD/////AgAA
+			AAEAxAAAAAAAAADIAAAAQwAKAAAANRIAAAAAIAEAAAMAAQAAABAA
+			AgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgSW5zdCAx
+			MQAAAAAAAAAAKf3znwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAABAAAAAAAFoGAH8BAAAAAAoAAgDIAAAA9AAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAwAAAAAAAAAAIAAAAB
+			ACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIAAAAAAAAA
+			AAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAADAAAAABAAAAAgAA
+			AAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMAAgAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAAMQAAAP////8C
+			AAAAAQDEAAAAAAAAAMgAAABDAAsAAAA1EgAAAAAgAQAAAwABAAAA
+			EAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBJbnN0
+			IDEyAAAAAAAAAAAp/fOfAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAACwACAMgAAAD0AAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAADEAAAAAAAAAAgAA
+			AAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIAAgAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAMQAAAAEAAAAC
+			AAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAAAwACAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAAAyAAAA////
+			/wIAAAABAMQAAAAAAAAAyAAAAEMADAAAADUSAAAAACABAAADAAEA
+			AAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAIElu
+			c3QgMTMAAAAAAAAAACn9858AAAAAAFoAAABAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAMAAIAyAAAAPQAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAMgAAAAAAAAAC
+			AAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgACAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAyAAAAAQAA
+			AAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAADAAIA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAAADMAAAD/
+			////AgAAAAEAxAAAAAAAAADIAAAAQwANAAAANRIAAAAAIAEAAAMA
+			AQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAg
+			SW5zdCAxNAAAAAAAAAAAKf3znwAAAAAAWgAAAEAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAA0AAgDIAAAA9AAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAAzAAAAAAAA
+			AAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAADMAAAAB
+			AAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMA
+			AgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAANAAA
+			AP////8CAAAAAQDEAAAAAAAAAMgAAABDAA4AAAA1EgAAAAAgAQAA
+			AwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAA
+			ACBJbnN0IDE1AAAAAAAAAAAp/fOfAAAAAABaAAAAQAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAADgACAMgAAAD0
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAADQAAAAA
+			AAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIA
+			AgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAANAAA
+			AAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAA
+			AwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAAA1
+			AAAA/////wIAAAABAMQAAAAAAAAAyAAAAEMADwAAADUSAAAAACAB
+			AAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAA
+			AAAAIEluc3QgMTYAAAAAAAAAACn9858AAAAAAFoAAABAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAPAAIAyAAA
+			APQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAANQAA
+			AAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAA
+			AgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAA1
+			AAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAA
+			AAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAA
+			ADYAAAD/////AgAAAAEAxAAAAAAAAADIAAAAQwAQAAAANRIAAAAA
+			IAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAA
+			AAAAAAAgSW5zdCAxNwAAAAAAAAAAKf3znwAAAAAAWgAAAEAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAABAAAgDI
+			AAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAAA2
+			AAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAA
+			AAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAA
+			ADYAAAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAA
+			AAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAk
+			AAAANwAAAP////8CAAAAAQDEAAAAAAAAAMgAAABDABEAAAA1EgAA
+			AAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAA
+			AAAAAAAAACBJbnN0IDE4AAAAAAAAAAAp/fOfAAAAAABaAAAAQAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAAEQAC
+			AMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAA
+			ADcAAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAA
+			AAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAk
+			AAAANwAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAA
+			AAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAA
+			ACQAAAA4AAAA/////wIAAAABAMQAAAAAAAAAyAAAAEMAEgAAADUS
+			AAAAACABAAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAA
+			AAAAAAAAAAAAIEluc3QgMTkAAAAAAAAAACn9858AAAAAAFoAAABA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/AQAAAAAS
+			AAIAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAk
+			AAAAOAAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAA
+			AAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAA
+			ACQAAAA4AAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUS
+			AAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAO
+			AAAAJAAAADkAAAD/////AgAAAAEAxAAAAAAAAADIAAAAQwATAAAA
+			NRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAABAAAAAAAA
+			AAAAAAAAAAAAAAAgSW5zdCAyMAAAAAAAAAAAKf3znwAAAAAAWgAA
+			AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8BAAAA
+			ABMAAgDIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAA
+			ACQAAAA5AAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAAAAAAADUS
+			AAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAO
+			AAAAJAAAADkAAAABAAAAAgAAAAEALAAAAAAAAAAsAAAAAAABAAAA
+			NRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEB
+			AA4AAAAkAAAAOgAAAP////8CAAAAAQDEAAAAAAAAAMgAAABDABQA
+			AAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAA
+			AAAAAAAAAAAAAAAAACBJbnN0IDIxAAAAAAAAAAAp/fOfAAAAAABa
+			AAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEA
+			AAAAFAACAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAO
+			AAAAJAAAADoAAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAAAAAAAAAA
+			NRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEB
+			AA4AAAAkAAAAOgAAAAEAAAACAAAAAQAsAAAAAAAAACwAAAAAAAEA
+			AAA1EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1
+			QQEADgAAACQAAAA7AAAA/////wIAAAABAMQAAAAAAAAAyAAAAEMA
+			FQAAADUSAAAAACABAAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAA
+			AAAAAAAAAAAAAAAAAAAAIEluc3QgMjIAAAAAAAAAACn9858AAAAA
+			AFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaBgB/
+			AQAAAAAVAAIAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEB
+			AA4AAAAkAAAAOwAAAAAAAAACAAAAAQAsAAAAAAAAACwAAAAAAAAA
+			AAA1EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1
+			QQEADgAAACQAAAA7AAAAAQAAAAIAAAABACwAAAAAAAAALAAAAAAA
+			AQAAADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABP
+			Q3VBAQAOAAAAJAAAADwAAAD/////AgAAAAEAxAAAAAAAAADIAAAA
+			QwAWAAAANRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAAAAEAAAAB
+			AAAAAAAAAAAAAAAAAAAAAAAgSW5zdCAyMwAAAAAAAAAAKf3znwAA
+			AAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoG
+			AH8BAAAAABYAAgDIAAAA9AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1
+			QQEADgAAACQAAAA8AAAAAAAAAAIAAAABACwAAAAAAAAALAAAAAAA
+			AAAAADUSAAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAAAAAAAABV
+			Q3VBAQAOAAAAJAAAADwAAAABAAAAAgAAAAEALAAAAAAAAAAsAAAA
+			AAABAAAANRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AE9DdUEBAA4AAAAkAAAAPQAAAP////8CAAAAAQDEAAAAAAAAAMgA
+			AABDABcAAAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgABAAAAAQAA
+			AAEAAAAAAAAAAAAAAAAAAAAAACBJbnN0IDI0AAAAAAAAAAAp/fOf
+			AAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAA
+			WgYAfwEAAAAAFwACAMgAAAD0AAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABV
+			Q3VBAQAOAAAAJAAAAD0AAAAAAAAAAgAAAAEALAAAAAAAAAAsAAAA
+			AAAAAAAANRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AFVDdUEBAA4AAAAkAAAAPQAAAAEAAAACAAAAAQAsAAAAAAAAACwA
+			AAAAAAEAAAA1EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAT0N1QQEADgAAACQAAAA+AAAA/////wIAAAABAMQAAAAAAAAA
+			yAAAAEMAGAAAADUSAAAAACABAAADAAEAAAAQAAIACQACAAEAAAAB
+			AAAAAQAAAAAAAAAAAAAAAAAAAAAAIEluc3QgMjUAAAAAAAAAACn9
+			858AAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA
+			AABaBgB/AQAAAAAYAAIAyAAAAPQAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AFVDdUEBAA4AAAAkAAAAPgAAAAAAAAACAAAAAQAsAAAAAAAAACwA
+			AAAAAAAAAAA1EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAVUN1QQEADgAAACQAAAA+AAAAAQAAAAIAAAABACwAAAAAAAAA
+			LAAAAAAAAQAAADUSAAAAAAAAAAADAAIAAAAAAAAAAAAAAAAAAAAA
+			AAAAAABPQ3VBAQAOAAAAJAAAAD8AAAD/////AgAAAAEAxAAAAAAA
+			AADIAAAAQwAZAAAANRIAAAAAIAEAAAMAAQAAABAAAgAJAAIAAQAA
+			AAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgSW5zdCAyNgAAAAAAAAAA
+			Kf3znwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAA
+			AAAAAFoGAH8BAAAAABkAAgDIAAAA9AAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAVUN1QQEADgAAACQAAAA/AAAAAAAAAAIAAAABACwAAAAAAAAA
+			LAAAAAAAAAAAADUSAAAAAAAAAAACAAIAAAAAAAAAAAAAAAAAAAAA
+			AAAAAABVQ3VBAQAOAAAAJAAAAD8AAAABAAAAAgAAAAEALAAAAAAA
+			AAAsAAAAAAABAAAANRIAAAAAAAAAAAMAAgAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAE9DdUEBAA4AAAAkAAAAQAAAAP////8CAAAAAQDEAAAA
+			AAAAAMgAAABDABoAAAA1EgAAAAAgAQAAAwABAAAAEAACAAkAAgAB
+			AAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBJbnN0IDI3AAAAAAAA
+			AAAp/fOfAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			EAAAAAAAWgYAfwEAAAAAGgACAMgAAAD0AAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAABVQ3VBAQAOAAAAJAAAAEAAAAAAAAAAAgAAAAEALAAAAAAA
+			AAAsAAAAAAAAAAAANRIAAAAAAAAAAAIAAgAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAFVDdUEBAA4AAAAkAAAAQAAAAAEAAAACAAAAAQAsAAAA
+			AAAAACwAAAAAAAEAAAA1EgAAAAAAAAAAAwACAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAT0N1QQEADgAAACQAAABBAAAA/////wIAAAABAMQA
+			AAAAAAAAyAAAAEMAGwAAADUSAAAAACABAAADAAEAAAAQAAIACQAC
+			AAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAIEluc3QgMjgAAAAA
+			AAAAACn9858AAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAQAAAAAABaBgB/AQAAAAAbAAIAyAAAAPQAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAFVDdUEBAA4AAAAkAAAAQQAAAAAAAAACAAAAAQAsAAAA
+			AAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgACAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAVUN1QQEADgAAACQAAABBAAAAAQAAAAIAAAABACwA
+			AAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAADAAIAAAAAAAAAAAAA
+			AAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAAAEIAAAD/////AgAAAAEA
+			xAAAAAAAAADIAAAAQwAcAAAANRIAAAAAIAEAAAMAAQAAABAAAgAJ
+			AAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgSW5zdCAyOQAA
+			AAAAAAAAKf3znwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAABAAAAAAAFoGAH8BAAAAABwAAgDIAAAA9AAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAVUN1QQEADgAAACQAAABCAAAAAAAAAAIAAAABACwA
+			AAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIAAAAAAAAAAAAA
+			AAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAEIAAAABAAAAAgAAAAEA
+			LAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMAAgAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAAQwAAAP////8CAAAA
+			AQDEAAAAAAAAAMgAAABDAB0AAAA1EgAAAAAgAQAAAwABAAAAEAAC
+			AAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBJbnN0IDMw
+			AAAAAAAAAAAp/fOfAAAAAABaAAAAQAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAEAAAAAAAWgYAfwEAAAAAHQACAMgAAAD0AAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAEMAAAAAAAAAAgAAAAEA
+			LAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIAAgAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAAQwAAAAEAAAACAAAA
+			AQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAAAwACAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAABEAAAA/////wIA
+			AAABAMQAAAAAAAAAyAAAAEMAHgAAADUSAAAAACABAAADAAEAAAAQ
+			AAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAIEluc3Qg
+			MzEAAAAAAAAAACn9858AAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAQAAAAAABaBgB/AQAAAAAeAAIAyAAAAPQAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAARAAAAAAAAAACAAAA
+			AQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgACAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAABEAAAAAQAAAAIA
+			AAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAADAAIAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAAAEUAAAD/////
+			AgAAAAEAxAAAAAAAAADIAAAAQwAfAAAANRIAAAAAIAEAAAMAAQAA
+			ABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgSW5z
+			dCAzMgAAAAAAAAAAKf3znwAAAAAAWgAAAEAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAB8AAgDIAAAA9AAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAABFAAAAAAAAAAIA
+			AAABACwAAAAAAAAALAAAAAAAAAAAADUSAAAAAAAAAAACAAIAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAEUAAAABAAAA
+			AgAAAAEALAAAAAAAAAAsAAAAAAABAAAANRIAAAAAAAAAAAMAAgAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAARgAAAP//
+			//8CAAAAAQDEAAAAAAAAAMgAAABDACAAAAA1EgAAAAAgAQAAAwAB
+			AAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBJ
+			bnN0IDMzAAAAAAAAAAAp/fOfAAAAAABaAAAAQAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAEAAAAAAAWgYAfwEAAAAAIAACAMgAAAD0AAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAEYAAAAAAAAA
+			AgAAAAEALAAAAAAAAAAsAAAAAAAAAAAANRIAAAAAAAAAAAIAAgAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAARgAAAAEA
+			AAACAAAAAQAsAAAAAAAAACwAAAAAAAEAAAA1EgAAAAAAAAAAAwAC
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAABHAAAA
+			/////wIAAAABAMQAAAAAAAAAyAAAAEMAIQABADUSAAAAACgOAAAD
+			AAEAAQEQAAIACQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAA
+			IEluc3QgMzQAAAAAAAAAACn9958AAAAAgFoBAAJAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABaBgB/AgAAAAAhAAIAyAAAAPQA
+			AADQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAgAQAAAAAAAFVDdUEBAA4AAAAkAAAARwAAAAAA
+			AAACAAAAAQAsAAAAAAAAACwAAAAAAAAAAAA1EgAAAAAAAAAAAgAC
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAABHAAAA
+			AQAAAAIAAAABACwAAAAAAAAALAAAAAAAAQAAADUSAAAAAAAAAAAD
+			AAIAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAEcA
+			AAACAAAAAgAAAAEAsAAAAAAAAACwAAAABQAAAAAANRIAAAAATWV0
+			cm9ub21lIFdvb2RibG9jay5jc3QAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAE1ldHJvbm9tZXMAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AFVDdUEBAA4AAAAkAAAARwAAAA4AAAACAAAAAQBQDAAAAAAAAFgM
+			AAABAAAAAAA1EgAATWV0cm9ub21lIFdvb2RibG9jayAyLnBzdAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAEAAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKUAEAAA
+			AkRydW0gS2l0cwAAAE1FTEMPAAAAMU1BUwAACgAAAP8J6AMAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAbgEAAAAAAAAAAAAAAQAAAAAAAAAA
+			AAAAGwAAAAAAAAA2AAAAPAAAADYAAAAYAAAAMAAAABgAAAACAAAA
+			DAAAAAIAAAAAAAAAJQAAAAAAAAAAAAAAAgAAAAAAAAAPAAAAPwAA
+			AA8AAAAAAAAAfwAAAAAAAAAAAAAAfwAAAAAAAAAYAAAAMAAAABgA
+			AAAYAAAAMAAAABgAAAAyAAAAZAAAADIAAAAAAAAAfwAAAAAAAAAM
+			AAAAGAAAAAwAAAAMAAAAGAAAAAwAAAAAAAAAAQAAAAAAAAAAAAAA
+			fwAAAAAAAAAsAAAAfwAAACwAAAAAAAAAAQAAAAAAAAAAAAAABQAA
+			AAAAAAAAAAAAAQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAA
+			AADoAwAA6AMAAOgDAAAAAAAA6AMAAAAAAABkAAAA6AMAAGQAAAAA
+			AAAA6AMAAAAAAAAAAAAA6AMAAAAAAABkAAAAyAAAAGQAAABkAAAA
+			yAAAAGQAAAAkAAAAYAAAACQAAABgAAAAYAAAAGAAAAABAAAAAQAA
+			AAEAAABkAAAAyAAAAGQAAABkAAAAyAAAAGQAAAAPJwAAHk4AAA8n
+			AABiAAAAfwAAAGIAAAAAAAAABgAAAAAAAAAAAAAABgAAAAAAAAAi
+			AAAAfwAAACIAAAAAAAAAfwAAAAAAAAAAAAAAfwAAAAAAAAAAAAAA
+			fwAAAAAAAAAAAAAAfwAAAAAAAAAAAAAAfwAAAAAAAAAAAAAAZAAA
+			AAAAAABjAAAAxgAAAGMAAAAAAAAAfwAAAAAAAAAAAAAAfwAAAAAA
+			AAAAAAAAfwAAAAAAAAB/AAAAfwAAAH8AAAAAAAAAfwAAAAAAAAB/
+			AAAA/gAAAH8AAAAAAAAAMgAAAAAAAAAAAAAAfwAAAAAAAAABAAAA
+			AgAAAAEAAAAAAAAAAQAAAAAAAABiAAAAfwAAAGIAAAAAAAAAgAAA
+			AAAAAABRAAAAiQAAAFEAAAAAAAAAAAAAAAAAAAACAAAAHAAAAAAA
+			AAAOAAAAiQAAABAAAAAQAAAAiQAAABAAAADQBwAA0AcAAOgDAADQ
+			BwAA0AcAAOgDAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAA
+			AQAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAHAAAAAAAAAAFAAAAiQAA
+			ABAAAAASAAAAiQAAABAAAADoAwAA0AcAAOgDAAA/BQAA0AcAAOgD
+			AAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAQAAAAiQAAABAAAAAQAAAA
+			iQAAABAAAADoAwAA0AcAAOgDAADoAwAA0AcAAOgDAAAAAAAAAQAA
+			AAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAHAAAAAAAAAAQAAAAiQAAABAAAAAQAAAAiQAAABAAAADo
+			AwAA0AcAAOgDAADoAwAA0AcAAOgDAAAAAAAAAQAAAAAAAAAAAAAA
+			AQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAA
+			AAAAAAAQAAAAiQAAABAAAAAQAAAAiQAAABAAAADoAwAA0AcAAOgD
+			AADoAwAA0AcAAOgDAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAA
+			AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAQAAAA
+			iQAAABAAAAAQAAAAiQAAABAAAADoAwAA0AcAAOgDAADoAwAA0AcA
+			AOgDAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAQAAAAiQAAABAAAAAQ
+			AAAAiQAAABAAAADoAwAA0AcAAOgDAADoAwAA0AcAAOgDAAAAAAAA
+			AQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAHAAAAAAAAAAQAAAAiQAAABAAAAAQAAAAiQAAABAA
+			AADoAwAA0AcAAOgDAADoAwAA0AcAAOgDAAAAAAAAAQAAAAAAAAAA
+			AAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			HAAAAAAAAAAQAAAAiQAAABAAAAAQAAAAiQAAABAAAADoAwAA0AcA
+			AOgDAADoAwAA0AcAAOgDAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAA
+			AAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAQ
+			AAAAiQAAABAAAAAQAAAAiQAAABAAAADoAwAA0AcAAOgDAADoAwAA
+			0AcAAOgDAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAA
+			AAAAAAAAAgAAAAAAAAAYAAAAGAAAABgAAADoAwAA6AMAAOgDAAAA
+			AAAAAQAAAAAAAABJAAAAYAAAAEkAAAAAAAAAAQAAAAAAAAAAAAAA
+			AgAAAAAAAAACAAAAAgAAAAIAAABjAAAAxgAAAGMAAADoAwAA6AMA
+			AOgDAADoAwAAAgABD1wAAABNRUxDUE1BUzFNQVNNZXRyb25vbWUg
+			V29vZGJsb2NrIDIuZXhzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAKBmBwAAAPr///8IAAAAAAAAAAMAAAACAAAA
+			BAAAAP////8FAAAAQAAAABQAAAAAAAAASAAAAAAAAABJAAAAAAAA
+			APMAAAAAAAAAHgAAAOgDAAAdAAAAAAAAAEsAAAAAAAAALgAAAAAA
+			AABaAAAAxf///1kAAAAAAAAAPAAAAAAAAAA9AAAAYgAAAD4AAAAA
+			AAAAQAAAAAAAAAA/AAAAIgAAAEwAAAAAAAAATQAAAAAAAABOAAAA
+			AAAAAE8AAAAAAAAAUAAAAAAAAABcAAAAAAAAAFsAAAAAAAAAUgAA
+			AAAAAABTAAAAAAAAAFQAAAB/AAAAUQAAAAAAAABVAAAAIQAAAF8A
+			AAAAAAAAYgAAAAAAAABhAAAAAAAAAKUAAAABAAAApwAAAGIAAACm
+			AAAA/////6wAAABAAAAArQAAAAIAAACuAAAA/f///68AAAD/////
+			sAAAAOgDAACxAAAA6AMAALMAAAAGAAAAtAAAAPT///+1AAAAAQAA
+			ALYAAAAAAAAAtwAAAFoBAAC5AAAAAAAAALoAAAD/////uwAAAP//
+			//+8AAAAAAAAAL0AAAAAAAAAvwAAAAAAAADAAAAA/////8EAAAD/
+			////wgAAAAAAAADDAAAAAAAAAMUAAAAAAAAAxgAAAP/////HAAAA
+			/////8gAAAAAAAAAyQAAAAAAAADLAAAAAAAAAMwAAAD/////zQAA
+			AP/////OAAAAAAAAAM8AAAAAAAAA0QAAAAAAAADSAAAA/////9MA
+			AAD/////1AAAAAAAAADVAAAAAAAAANcAAAAAAAAA2AAAAP/////Z
+			AAAA/////9oAAAAAAAAA2wAAAAAAAADdAAAAAAAAAN4AAAD/////
+			3wAAAP/////gAAAAAAAAAOEAAAAAAAAA4wAAAAAAAADkAAAA////
+			/+UAAAD/////5gAAAAAAAADnAAAAAAAAABYBAAAAAAAAFwEAABgA
+			AAD+AAAA6AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAA
+			ACQAAABIAAAA/////wIAAAABAMQAAAAAAAAAyAAAAEQAAAABADUS
+			AAAAAMgAAAADAAEAAAAQAAIACQACAAEAAAABAAAAAQAAAAAAAAAA
+			AAAAAAAAAAAApU91dHB1dCAxAAAAAAAAAAl/050AAAAAAFoAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAABaAAAAAQAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAk
+			AAAASQAAAP////8CAAAAAQDEAAAAAAAAAMgAAABEAAEAAQA1EgAA
+			AADIAAAAAwABAAAAEAACAAkAAgABAAAAAQAAAAEAAAAAAAAAAAAA
+			AAAAAAAAAKVPdXRwdXQgMgAAAAAAAAAJf9OdAAAAAABaAAAAfwAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAWgAAAAEAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAJAAA
+			AEoAAAD/////AgAAAAEAxAAAAAAAAADIAAAARQAAAAAANRIAAAAA
+			CAMAAAMAAQABARAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAA
+			AAAAAAAgQnVzIDEAAAAAAAAAAAAA6f3XnRAAAACAWgEAAEAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAFoGAH8CAAAAAAAAAAAA
+			AAAAAAAAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVUN1QQEADgAAACQAAABK
+			AAAAAgAAAAIAAAABADgCAAAAAAAAQAIAAAEAAAAAADUSAAAuZGVm
+			YXVsdC5kZWYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEBAgAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAFwBRAAICRWNobwAAAAAAAAAAR0FN
+			RSEAAACTAAAAAAAqAAAA/wB4AAAAAgAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAL
+			AAAABwAAABQAAABkAAAAFAAAAGQAAADIAAAAZAAAADIAAABkAAAA
+			MgAAADIAAABkAAAAMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AHgAAAABAAAhGAAAAEdBTUVUU1BQkwAAAAAAAAAAAMhCAAD6QwAA
+			AAAAAAhCAEAcRgAAoEEAAIA/AACAQAAASEIAACBCAAAAAAAAAADM
+			zEw+AAAAAAAAAAAAAPBCAACAQAAAGEIAADDBAAAAAAAAyEIAAIA/
+			uP75Q09DdUEBAA4AAAAkAAAASwAAAP////8CAAAAAQDEAAAAAAAA
+			AMgAAABFAAEAAAA1EgAAAADYAgAAAwABAAEBEAACAAkAAgABAAAA
+			AQAAAAEAAAAAAAAAAAAAAAAAAAAAACBCdXMgMgAAAAAAAAAAAADp
+			/dedEAAAAIBaAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAA
+			AAAAWgYAfwIAAAAAAAAAAAAAAAAAAAAAAAAAAMgAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AABVQ3VBAQAOAAAAJAAAAEsAAAADAAAAAgAAAAEACAIAAAAAAAAQ
+			AgAAAQABAAAANRIAAC5kZWZhdWx0LmRlZgAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAACAQECAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUADQA
+			AQJSZXZlcmIAAAAAAABHQU1FAAAAAJcAAAAAABsAAAAAAGwAAAAB
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAFAAAAGQAAAAUAAAAZAAAAMgAAABkAAAAUAAA
+			AGQAAABQAAAAFAAAAGQAAAAUAAAAbAAAAAEAAAAVAAAAR0FNRVRT
+			UFCXAAAAAAAAAAAAyEIAAAAAAAAgQQAAoEDNzEw+AADIQgAAUEEA
+			AGhCAADgPwAAyEIAAEhCAADIQwCwAUYAACDBAADIQgAAyEIAAKhB
+			AADIQgAAAAAAAMhCT0N1QQEADgAAACQAAABMAAAA/////wIAAAAB
+			AMQAAAAAAAAAyAAAAEYAAAAAADUSAAAAAMgAAAADAAEAAQEQAAIA
+			CQACAAEAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAIE1hc3RlcgAA
+			AAAAAAAAAIl92ZUAAAAAAFoAAABAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAQAAAAAABaAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAE9DdUEBAA4AAAAkAAAATQAAAP////8CAAAAAQDE
+			AAAAAAAAAMgAAABJAAAAAAA1EgAAAADIAAAAAwABAAAAEAACAAkA
+			AgABAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAACBJbnB1dCAxLTIA
+			AAAAAAAp/defAAAAAAAAAAAAQAAA//8AAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAYAfwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAABPQ3VBAQAOAAAAJAAAAE4AAAD/////AgAAAAEAxAAA
+			AAAAAADIAAAATAAAAAEANRIAAAAALAsAAAMAAQABARAAAgAJAAIA
+			AQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgT3V0cHV0IDEtMgAA
+			AAAACf/fnQAAAAAAWgAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAFoAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAB4AQAArAUAAAAAAAAMCgAAAAAAAAAAAAAAAAAAAAAAAMgA
+			AAAAAAAAVUN1QQEADgAAACQAAABOAAAABgAAAAIAAAABALAAAAAA
+			AAAAsAAAAAUAAAAAADUSAAAAACBEZWZhdWx0LmNzdAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAgQmFzaWMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVQ3VBAQAOAAAAJAAAAE4A
+			AAAHAAAAAgAAAAEALAQAAAAAAAA0BAAAAQAEAAAANRIAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQECAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAQA5AEcAAgJDaGFubmVsIEVRAABHQU1F
+			AAAAAOwAAAAAACUAAAAAANQAAAACAAAAAAAAAAAAAAAAAAAAAAAA
+			AAEAAAAAAAAAcAAAAN8BAABwAAAAAAAAAAUAAAAAAAAAKgAAAH8A
+			AAAqAAAAAQAAAAEAAAABAAAAYAAAAN8BAABgAAAAMAAAAGAAAAAw
+			AAAAKgAAADQAAAAqAAAAAQAAAAEAAAABAAAAPwEAAN8BAAA/AQAA
+			MAAAAGAAAAAwAAAAKgAAAH8AAAAqAAAAAAAAAAEAAAAAAAAAPwEA
+			AN8BAAA/AQAAMAAAAGAAAAAwAAAAKgAAAH8AAAAqAAAAAAAAAAEA
+			AAAAAAAAPwEAAN8BAAA/AQAAMAAAAGAAAAAwAAAAKgAAAH8AAAAq
+			AAAAAAAAAAEAAAAAAAAAPwEAAN8BAAA/AQAAMAAAAGAAAAAwAAAA
+			KgAAAH8AAAAqAAAAAQAAAAEAAAABAAAAvAEAAN8BAAC8AQAAMAAA
+			AGAAAAAwAAAAKgAAADQAAAAqAAAAAAAAAAEAAAAAAAAADwEAAN8B
+			AAAPAQAAAAAAAAUAAAAAAAAAKgAAAH8AAAAqAAAAMAAAAGAAAAAw
+			AAAAAAAAAAEAAAAAAAAAAAAAAAIAAAAAAAAABAAAAAwAAAAEAAAA
+			AAAAACgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAEAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAA1AAAAAEAAAAtAAAAR0FNRVRTUFDs
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/AACgQgAAAADNzIw/
+			AAAAAAAAAAAAAAAAAAAAAAAAgD8AAHpDAAAAAM3MzD8AAIA/AAAl
+			RAAAAACuR2E/AAAAAAAAAAAAAAAAAAAAAAAAgD8AgDtGAAAAAM3M
+			jD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACamTFBAAAAAAAAAAAA
+			AIC/AAAAQAAAAAAAACBBAACAPwAAgD8AAAAAeDRCRwgAAABVQ3VB
+			AQAOAAAAJAAAAE4AAAAJAAAAAgAAAAEAWAQAAAAAAABgBAAAAQAF
+			AAAANRIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAQEC
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQA5AD0AAgJNdWx0
+			aXByAAAAAABHQU1FAAAAAMIAAAAAAB8AAAAAAAABAAACAAAAAAAA
+			AAAAAAAAAAAAAgAAAAIAAAACAAAAGQAAAGQAAAAZAAAAawAAAHcA
+			AABrAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAAAAAAGQAAAAA
+			AAAAQgAAAGQAAABCAAAAPAAAAGQAAAA8AAAAAAAAAFUAAAAAAAAA
+			KAAAACgAAAAoAAAAAAAAAGQAAAAAAAAAQwAAAHcAAABDAAAAAQAA
+			AAEAAAABAAAAQwAAAHcAAABDAAAAZAAAAGQAAABkAAAAZAAAAGQA
+			AABkAAAAAAAAAGQAAAAAAAAAQgAAAGQAAABCAAAAPAAAAGQAAAA8
+			AAAAAAAAAFUAAAAAAAAAKAAAACgAAAAoAAAAAAAAAGQAAAAAAAAA
+			QwAAAHcAAABDAAAAAQAAAAEAAAABAAAAHAAAAHcAAAAcAAAAZAAA
+			AGQAAABkAAAAZAAAAGQAAABkAAAAAAAAAGQAAAAAAAAAQgAAAGQA
+			AABCAAAAPAAAAGQAAAA8AAAAAAAAAFUAAAAAAAAAKAAAACgAAAAo
+			AAAAFAAAAGQAAAAUAAAAQwAAAHcAAABDAAAAAQAAAAEAAAABAAAA
+			EAAAAHcAAAAQAAAAZAAAAGQAAABkAAAAZAAAAGQAAABkAAAAAAAA
+			AGQAAAAAAAAAQgAAAGQAAABCAAAAPAAAAGQAAAA8AAAAAAAAAFUA
+			AAAAAAAAKAAAACgAAAAoAAAAKwAAAGQAAAArAAAAQwAAAHcAAABD
+			AAAAAQAAAAEAAAABAAAAMgAAAGQAAAAyAAAAAAAAAAkAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEAAAA6
+			AAAAR0FNRVRTUFDCAAAAAAAAAAAAgEAAAKBAAEAcRgAASEMAAAAA
+			AABIwvUoPEAAAKDBAACAPwAAAAAAAAAAAADEQgAAgD8AAHVEAABI
+			QwAAAAAAAEjC9Sg8QAAAoMEAAIA/AAAAAAAAAAAAAMRCAACAPwAA
+			yEIAAEhDAAAAAAAASML1KDxAAACgwQAAgD8AAAAAAAAgQQAAxEIA
+			AIA/AABMQgAASEMAAAAAAABIwvUoPEAAAKDBAACAPwAAAAAAAOhB
+			AADEQgAAgD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAFVDdUEBAA4AAAAkAAAATgAAAA4AAAACAAAA
+			AQAYAQAAAAAAACABAAABAAcAAAA1EgAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAIBAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAABAAUAPwACAkxpbWl0ZXIAAAAAAEdBTUUAAAAAxwAAAAAA
+			IAAAAAAAMAAAAAIAAAAAAAAAAAAAAAAAAAAoAAAAUAAAACgAAAAU
+			AAAAZAAAABQAAAABAAAAAQAAAAEAAAAAAAAAdwAAAAAAAABkAAAA
+			bgAAAGQAAAAwAAAAAQAAAAYAAABHQU1FVFNQUMcAAAAAAAAAAAAA
+			AJqZmT4AAAAAAADrQwAAAABPQ3VBAQAOAAAAJAAAAE8AAAD/////
+			AgAAAAEAxAAAAAAAAADIAAAAQgACAAAANRIAAAAAyAAAAAMAAQAA
+			ABAAAgAJAAIAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAgQXV4
+			IDMAAAAAAAAAAAAAq/3XnwAAAAAAWgAAAEAAAAAA//8AAAAAAAAA
+			AAAAAAAAAAAAABAAAAAAAFoGAH8BAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAACQAAABQAAAA/////wIA
+			AAABAA4AAAAAAAAAEAAAAP//AAAAADUSAABuQ3VBAQAOAAAAKAAA
+			AP//////////AgAAAAEAhAAAAAAAAACIAAAAwAAAAAAANRIAAAAA
+			iAAAAAMAAgABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAFEBAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABP
+			Q3VBAQAOAAAAKAAAAAAAAAD/////AgAAAAEADgAAAAAAAAAQAAAA
+			//8AAAAANRIAAG5DdUEBAA4AAAAsAAAA//////////8CAAAAAQCE
+			AAAAAAAAAIgAAADAAAAAAAA1EgAAAACIAAAAAwADAAEAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAUQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEBAA4AAAAsAAAAAAAA
+			AP////8CAAAAAQAOAAAAAAAAABAAAAD//wAAAAA1EgAAbkN1QQEA
+			DgAAADAAAAD//////////wIAAAABAIQAAAAAAAAAiAAAAMAAAAAA
+			ADUSAAAAAIgAAAADAAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRAQAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAT0N1QQEADgAAADAAAAAAAAAA/////wIAAAABAA4AAAAA
+			AAAAEAAAAP//AAAAADUSAABuQ3VBAQAOAAAANAAAAP//////////
+			AgAAAAEAhAAAAAAAAACIAAAAwAAAAAAANRIAAAAAiAAAAAMABQAB
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAFEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAA
+			NAAAAAAAAAD/////AgAAAAEADgAAAAAAAAAQAAAA//8AAAAANRIA
+			AG5DdUEBAA4AAAA4AAAA//////////8CAAAAAQCEAAAAAAAAAIgA
+			AADAAAAAAAA1EgAAAACIAAAAAwAGAAEAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQEA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAE9DdUEBAA4AAAA4AAAAAAAAAP////8CAAAA
+			AQAOAAAAAAAAABAAAAD//wAAAAA1EgAAbkN1QQEADgAAADwAAAD/
+			/////////wIAAAABAIQAAAAAAAAAiAAAAMAAAAAAADUSAAAAAIgA
+			AAADAAcAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABRAQAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1
+			QQEADgAAADwAAAAAAAAA/////wIAAAABAA4AAAAAAAAAEAAAAP//
+			AAAAADUSAABuQ3VBAQAOAAAAQAAAAP//////////AgAAAAEAhAAA
+			AAAAAACIAAAAwAAAAAAANRIAAAAAiAAAAAMACAABAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAFEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABPQ3VBAQAOAAAAQAAAAAAAAAD/
+			////AgAAAAEADgAAAAAAAAAQAAAA//8AAAAANRIAAG5DdUEBAA4A
+			AABEAAAA//////////8CAAAAAQCEAAAAAAAAAIgAAADAAAAAAAA1
+			EgAAAACIAAAAAwAJAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUQEAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAE9DdUEBAA4AAABEAAAAAAAAAP////8CAAAAAQAOAAAAAAAA
+			ABAAAAD//wAAAAA1EgAAbkN1QQEADgAAAHgAAAD//////////wIA
+			AAABAIQAAAAAAAAAiAAAAMAAAAAAADUSAAAAAIgAAAADAAoAAQAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAABRAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAT0N1QQEADgAAAHgA
+			AAAAAAAA/////wIAAAABAA4AAAAAAAAAEAAAAP//AAAAADUSAABu
+			Q3VBAQAOAAAAfAAAAP//////////AgAAAAEAhAAAAAAAAACIAAAA
+			wAAAAAAANRIAAAAAiAAAAAMACwABAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFEBAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAABPQ3VBAQAOAAAAfAAAAAAAAAD/////AgAAAAEA
+			DgAAAAAAAAAQAAAA//8AAAAANRIAAG5DdUEBAA4AAACAAAAA////
+			//////8CAAAAAQCEAAAAAAAAAIgAAADAAAAAAAA1EgAAAACIAAAA
+			AwAMAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAUQEAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE9DdUEB
+			AA4AAACAAAAAAAAAAP////8CAAAAAQAOAAAAAAAAABAAAAD//wAA
+			AAA1EgAAT2duUwEADgAAAOAAAAD//////////wIAAAABAJACAAAA
+			AAAAkAIAAAAAAAAAAAAAAAAAABAnAAAEAJntgAIAADwoAAABAJnt
+			dAIAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAPSgAAAEAme0UAAAAFQAAAGQAAABxZVNN
+			AgAOAAAA5AAAAP//////////AgAAAAEALgEAAAAAAAAuAwEAAAAA
+			AAgAAAAAAAAACQDmnKrlkb3lkI0AAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAglqKWvZa8AJJpAACcAd4FAAAUToUWAAAAAOjS8AAAAAAAAAAA
+			AAAAADB1AAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAABooAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAIAAAAAAP8AAAAAAHFTdkUBAA4AAADkAAAACAAA
+			AP////8CAAAAAQAQAAAAAAAAAPEAAAD///8/AAAAAAAAAABNcm9D
+			AQAOAAAA6AAAAP//////////AgAAAAEABgAAAAAAAAAGAAAAAABN
+			cm9DAQAOAAAA7AAAAP//////////AgAAAAEABgAAAAAAAAAGAAAA
+			AABPZ25TAQAOAAAACAEAAP//////////AgAAAAEAVgoAAAAAAABW
+			CgAAAAAAAAAAAAAAAAAAoCgAAAEAme1GCgAABAAAAKAoAAADAJnt
+			TgEAAAAAAAALAAAAAAAAAKAoAAACAJntNgEAAAEAAAAiAQAAYnBs
+			aXN0MDDUAQIDBAUIHyBUJHRvcFgkb2JqZWN0c1gkdmVyc2lvblkk
+			YXJjaGl2ZXLRBgdUcm9vdIABpQkKExQYVSRudWxs0wsMDQ4QEVpO
+			Uy5vYmplY3RzViRjbGFzc1dOUy5rZXlzoQ+AA4AEoRKAAlJDYtML
+			DA0VEBeggASg0hkaGxxYJGNsYXNzZXNaJGNsYXNzbmFtZaMcHR5f
+			EBNOU011dGFibGVEaWN0aW9uYXJ5XE5TRGljdGlvbmFyeVhOU09i
+			amVjdBIAAYagXxAPTlNLZXllZEFyY2hpdmVyCBEWHygyNTo8QkhP
+			WmFpa21vcXN2fX6AgYaPmp60wcrPAAAAAAAAAQEAAAAAAAAAIQAA
+			AAAAAAAAAAAAAAAAAOGgKAAAAwCZ7YcDAABIAAAAFAAAAP////+g
+			KAAAAgCZ7W8DAAABAAAAWwMAAGJwbGlzdDAw1AECAwQFCENEVCR0
+			b3BYJG9iamVjdHNYJHZlcnNpb25ZJGFyY2hpdmVy0QYHVHJvb3SA
+			Aa8QEwkKExQkJSYnKCkqKywtMTc4Pj9VJG51bGzTCwwNDhARWk5T
+			Lm9iamVjdHNWJGNsYXNzV05TLmtleXOhD4ADgBKhEoACUkNi0wsM
+			DRUQHaYWFxgZGhuACoALgAyADYAPgBCAEqYeHyAhIiOABIAFgAaA
+			B4AIgAleaW5wdXRNZXRob2RLZXlfEBRjaGFubmVsU3RyaXBGdWxs
+			UGF0aF8QE3RyYWNrUmVjRW5hYmxlU3RhdGVebGFzdEVkaXRlZERh
+			dGVaSW5wdXRJbmRleF8QE2lucHV0TWV0aG9kU2V0dGluZ3NfEA9D
+			YkF1ZGlvUmVjb3JkZXJfEMUvdmFyL2NvbnRhaW5lcnMvQnVuZGxl
+			L0FwcGxpY2F0aW9uL0IzMjdCRjM2LTc0NzctNDM2Qy05ODcwLTVE
+			NjM0MzgyOTYwOC9Nb2JpbGVHYXJhZ2VCYW5kLmFwcC9MaWJyYXJ5
+			LmJ1bmRsZS9BcHBsaWNhdGlvbiBTdXBwb3J0L0luc3RydW1lbnQg
+			TGlicmFyeS9UcmFjayBTZXR0aW5ncy9SZWFsL0Jhc2ljIFRyYWNr
+			L0F1ZGlvIFJlY29yZGVyLmNzdAjSDC4vMFdOUy50aW1lgA4jQcDR
+			b3kmPKfSMjM0NVgkY2xhc3Nlc1okY2xhc3NuYW1lojU2Vk5TRGF0
+			ZVhOU09iamVjdBAA0wsMDTkQPKEYgAyAEqE9gBFfEBhDYklucHV0
+			TW9uaXRvcmluZ0VuYWJsZWTSMjNAQaNBQjZfEBNOU011dGFibGVE
+			aWN0aW9uYXJ5XE5TRGljdGlvbmFyeRIAAYagXxAPTlNLZXllZEFy
+			Y2hpdmVyAAgAEQAWAB8AKAAyADUAOgA8AFIAWABfAGoAcQB5AHsA
+			fQB/AIEAgwCGAI0AlACWAJgAmgCcAJ4AoACiAKkAqwCtAK8AsQCz
+			ALUAxADbAPEBAAELASEBMwH7AfwCAQIJAgsCFAIZAiICLQIwAjcC
+			QAJCAkkCSwJNAk8CUQJTAm4CcwJ3Ao0CmgKfAAAAAAAAAgEAAAAA
+			AAAARQAAAAAAAAAAAAAAAAAAArGgKAAAAwCZ7bkCAABQAAAAFAAA
+			AP////+gKAAAAgCZ7aECAAABAAAAjQIAAGJwbGlzdDAw1AECAwQF
+			CC0uVCR0b3BYJG9iamVjdHNYJHZlcnNpb25ZJGFyY2hpdmVy0QYH
+			VHJvb3SAAaoJChMUHB0eHyMpVSRudWxs0wsMDQ4QEVpOUy5vYmpl
+			Y3RzViRjbGFzc1dOUy5rZXlzoQ+AA4AJoRKAAlJDYtMLDA0VEBmi
+			FheABoAHgAmiGhuABIAFXxAUY2hhbm5lbFN0cmlwRnVsbFBhdGhe
+			bGFzdEVkaXRlZERhdGVfEM0vdmFyL2NvbnRhaW5lcnMvQnVuZGxl
+			L0FwcGxpY2F0aW9uL0IzMjdCRjM2LTc0NzctNDM2Qy05ODcwLTVE
+			NjM0MzgyOTYwOC9Nb2JpbGVHYXJhZ2VCYW5kLmFwcC9MaWJyYXJ5
+			LmJ1bmRsZS9BcHBsaWNhdGlvbiBTdXBwb3J0L0luc3RydW1lbnQg
+			TGlicmFyeS9UcmFjayBTZXR0aW5ncy9Tb2Z0d2FyZS9NZXRyb25v
+			bWVzL01ldHJvbm9tZSBXb29kYmxvY2suY3N00gwgISJXTlMudGlt
+			ZYAII0HA0W94+T8Y0iQlJidYJGNsYXNzZXNaJGNsYXNzbmFtZaIn
+			KFZOU0RhdGVYTlNPYmplY3TSJCUqK6MrLChfEBNOU011dGFibGVE
+			aWN0aW9uYXJ5XE5TRGljdGlvbmFyeRIAAYagXxAPTlNLZXllZEFy
+			Y2hpdmVyAAgAEQAWAB8AKAAyADUAOgA8AEcATQBUAF8AZgBuAHAA
+			cgB0AHYAeAB7AIIAhQCHAIkAiwCOAJAAkgCpALgBiAGNAZUBlwGg
+			AaUBrgG5AbwBwwHMAdEB1QHrAfgB/QAAAAAAAAIBAAAAAAAAAC8A
+			AAAAAAAAAAAAAAAAAAIPoCgAAAMAme2oAgAAXAAAABQAAAD/////
+			oCgAAAIAme2QAgAAAQAAAHwCAABicGxpc3QwMNQBAgMEBQgtLlQk
+			dG9wWCRvYmplY3RzWCR2ZXJzaW9uWSRhcmNoaXZlctEGB1Ryb290
+			gAGqCQoTFBwdHh8jKVUkbnVsbNMLDA0OEBFaTlMub2JqZWN0c1Yk
+			Y2xhc3NXTlMua2V5c6EPgAOACaESgAJSQ2LTCwwNFRAZohYXgAaA
+			B4AJohobgASABV8QFGNoYW5uZWxTdHJpcEZ1bGxQYXRoXmxhc3RF
+			ZGl0ZWREYXRlXxC8L3Zhci9jb250YWluZXJzL0J1bmRsZS9BcHBs
+			aWNhdGlvbi9CMzI3QkYzNi03NDc3LTQzNkMtOTg3MC01RDYzNDM4
+			Mjk2MDgvTW9iaWxlR2FyYWdlQmFuZC5hcHAvTGlicmFyeS5idW5k
+			bGUvQXBwbGljYXRpb24gU3VwcG9ydC9JbnN0cnVtZW50IExpYnJh
+			cnkvVHJhY2sgU2V0dGluZ3MvTWFzdGVyLyBCYXNpYy8gRGVmYXVs
+			dC5jc3TSDCAhIldOUy50aW1lgAgjQcDRb3j4/CbSJCUmJ1gkY2xh
+			c3Nlc1okY2xhc3NuYW1loicoVk5TRGF0ZVhOU09iamVjdNIkJSor
+			oyssKF8QE05TTXV0YWJsZURpY3Rpb25hcnlcTlNEaWN0aW9uYXJ5
+			EgABhqBfEA9OU0tleWVkQXJjaGl2ZXIACAARABYAHwAoADIANQA6
+			ADwARwBNAFQAXwBmAG4AcAByAHQAdgB4AHsAggCFAIcAiQCLAI4A
+			kACSAKkAuAF3AXwBhAGGAY8BlAGdAagBqwGyAbsBwAHEAdoB5wHs
+			AAAAAAAAAgEAAAAAAAAALwAAAAAAAAAAAAAAAAAAAf5ycHlIAQAP
+			AAAAAAAAAP//////////AgAAAAEA+gMAAAAAAACEF/r/AAAAAAAA
+			AAAAAAAAgAAGAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAA
+			AAAAAAAAAAEAIFZvbHVtZQAAAAAAAAAAALAH/wAAAAAAAAAAAAAA
+			AAAGAFZvbHVtZQAA+v8AAAAAAAAAAAAAAACAAAYAAAAAAAAAAAAA
+			AAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAgTUlESSBDb250
+			cm9scwAAsAf/AAAAAAAAAAAAAAAAAA0ATUlESSBDb250cm9scwAA
+			APr/AAAAAAAAAAAAAAAAgAAGAAAAAAAAAAAAAAAAAAAAAAAAAPAA
+			AAAAAAAAAAAAAAAAAAAAAAAAIFZvbHVtZQAAAAAAAAAAALAH/wAA
+			AAAAAAAAAAAAAAAGAFZvbHVtZQAA+v8AAAAAAAAAAAAAAACAAAYA
+			AAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAg
+			UGFuAG1lAAAAAAAAAAAAsAqAAAAAAAAAAAAAAAAAAAMAUGFuAAAA
+			+v8AAAAAAAAAAAAAAACAAAYAAAAAAAAAAAAAAAAAAAAAAAAA8AAA
+			AAAAAAAAAAAAAAAAAAAAAAAgTW9kdWxhdGlvbgAAAAAAsAGAAAAA
+			AAAAAAAAAAAAAAoATW9kdWxhdGlvbgAA/P8AAAAAAAAAAAAAAACA
+			AAMAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA
+			AAAgUGl0Y2ggQmVuZAAAAAAA4ICAAAAAAAAAAAAAAAAAAAoAUGl0
+			Y2ggQmVuZAAA+v8AAAAAAAAAAAAAAACAAAYAAAAAAAAAAAAAAAAA
+			AAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAgQ2guIFByZXNzdXJl
+			AAAA0ICAAAAAAAAAAAAAAAAAAAwAQ2guIFByZXNzdXJlAAD6/wAA
+			AAAAAAAAAAAAAIAABgAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAA
+			AAAAAAAAAAAAAAAAACBQb2x5IFByZXNzdXJlAACggIAAAAAAAAAA
+			AAAAAAAADQBQb2x5IFByZXNzdXJlAAAA+v8AAAAAAAAAAAAAAACA
+			AAYAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA
+			AAAgUHJvZ3JhbQAAAAAAAAAAwICAAAAAAAAAAAAAAAAAAAcAUHJv
+			Z3JhbQAAAPr/AAAAAAAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAAA
+			AAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAIEFsbCBWZWxvY2l0aWVz
+			AJC8gAAAAAAAAAAAAAAAAAAOAEFsbCBWZWxvY2l0aWVzcnB5SAEA
+			DwAAAAQAAAD//////////wIAAAABADIYAAAAAAAAme36/8yRAAAA
+			AAAAAAAAAIAABgAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAA
+			AAAAAAAAAAAAACBWb2x1bWUAAAAAAAAAAACwB/8AAAAAAAAAAAAA
+			AAAABgBWb2x1bWUAAPr/AAAAAAAAAAAAAAAAgAAGAAAAAAAAAAAA
+			AAATAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAIEdNIERydW0g
+			S2l0AHMAALAH/wAAAAAAAAAAAAAAAAALAEdNIERydW0gS2l0AAAA
+			+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAA
+			AAAAAAAAAAAAAAAAAAAAAAAgU0xBUABlAAAAAAAAAAAAkByAAAAA
+			AAAAAAAAAAAAAAQAU0xBUAAA+v8AAAAAAAAAAAAAAACAABAAAAAA
+			AAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAgU0NS
+			QVBVU0gAAAAAAAAAkB2AAAAAAAAAAAAAAAAAAAgAU0NSQVBVU0gA
+			APr/AAAAAAAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAA
+			AAAAAAAAAAAAAAAAAAAAAAAAIFNDUkFQVUxMAAAAAAAAAJAegAAA
+			AAAAAAAAAAAAAAAIAFNDUkFQVUxMAAD6/wAAAAAAAAAAAAAAAIAA
+			EAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAA
+			ACBTVElDS1MAAAAAAAAAAACQH4AAAAAAAAAAAAAAAAAABgBTVElD
+			S1MAAPr/AAAAAAAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAA
+			APAAAAAAAAAAAAAAAAAAAAAAAAAAIFNRIENMSUNLAAAAAAAAAJAg
+			gAAAAAAAAAAAAAAAAAAIAFNRIENMSUNLAAD6/wAAAAAAAAAAAAAA
+			AIAAEAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAA
+			AAAAACBNRVRST0NMSUNLAAAAAACQIYAAAAAAAAAAAAAAAAAACgBN
+			RVRST0NMSUNLAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAA
+			AAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBNRVRST0JFTEwA
+			AAAAAACQIoAAAAAAAAAAAAAAAAAACQBNRVRST0JFTEwAAAD6/wAA
+			AAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAA
+			AAAAAAAAAAAAAAAAACBLSUNLIDIAAAAAAAAAAACQI4AAAAAAAAAA
+			AAAAAAAABgBLSUNLIDIAAPr/AAAAAAAAAAAAAAAAgAAQAAAAAAAA
+			AAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAIEtJQ0sg
+			MQAAAAAAAAAAAJAkgAAAAAAAAAAAAAAAAAAGAEtJQ0sgMQAA+v8A
+			AAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAA
+			AAAAAAAAAAAAAAAAAAAgU0lERVNUSUNLAAAAAAAAkCWAAAAAAAAA
+			AAAAAAAAAAkAU0lERVNUSUNLAAAA+v8AAAAAAAAAAAAAAACAABAA
+			AAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAg
+			U0QgMQBlAAAAAAAAAAAAkCaAAAAAAAAAAAAAAAAAAAQAU0QgMQAA
+			+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAA
+			AAAAAAAAAAAAAAAAAAAAAAAgSEFORENMQVAAAAAAAAAAkCeAAAAA
+			AAAAAAAAAAAAAAgASEFORENMQVAAAPr/AAAAAAAAAAAAAAAAgAAQ
+			AAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAA
+			IFNEIDIAZQAAAAAAAAAAAJAogAAAAAAAAAAAAAAAAAAEAFNEIDIA
+			APr/AAAAAAAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAA
+			AAAAAAAAAAAAAAAAAAAAAAABIENsb3NlZCBISAAAAAAAAJAqgAAA
+			AAAAAAAAAAAAAAAJAENsb3NlZCBISAAAAPr/AAAAAAAAAAAAAAAA
+			gAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA
+			AAABIFBFRCBISAAAAAAAAAAAAJAsgAAAAAAAAAAAAAAAAAAGAFBF
+			RCBISAAA+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAA
+			AAAA8AAAAAAAAAAAAAAAAAAAAAAAAAEgT3BlbiBISAAAAAAAAAAA
+			kC6AAAAAAAAAAAAAAAAAAAcAT3BlbiBISAAAAPr/AAAAAAAAAAAA
+			AAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAA
+			AAAAAAAAIENSQVNIIDEAAAAAAAAAAJAxgAAAAAAAAAAAAAAAAAAH
+			AENSQVNIIDEAAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAA
+			AAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAASBMb3cgVE9NIDIA
+			AAAAAACQKYAAAAAAAAAAAAAAAAAACQBMb3cgVE9NIDIAAAD6/wAA
+			AAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAA
+			AAAAAAAAAAAAAAAAASBMb3cgVE9NIDEAAAAAAACQK4AAAAAAAAAA
+			AAAAAAAACQBMb3cgVE9NIDEAAAD6/wAAAAAAAAAAAAAAAIAAEAAA
+			AAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAASBN
+			aWQgVE9NIDIAAAAAAACQLYAAAAAAAAAAAAAAAAAACQBNaWQgVE9N
+			IDIAAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAA
+			AADwAAAAAAAAAAAAAAAAAAAAAAAAASBNaWQgVE9NIDEAAAAAAACQ
+			L4AAAAAAAAAAAAAAAAAACQBNaWQgVE9NIDEAAAD6/wAAAAAAAAAA
+			AAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAA
+			AAAAAAAAASBIaWdoIFRPTSAyAAAAAACQMIAAAAAAAAAAAAAAAAAA
+			CgBIaWdoIFRPTSAyAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAA
+			AAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAASBIaWdoIFRP
+			TSAxAAAAAACQMoAAAAAAAAAAAAAAAAAACgBIaWdoIFRPTSAxAAD6
+			/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAAAADwAAAA
+			AAAAAAAAAAAAAAAAAAAAACBSSURFIDEAAAAAAAAAAACQM4AAAAAA
+			AAAAAAAAAAAABgBSSURFIDEAAPr/AAAAAAAAAAAAAAAAgAAQAAAA
+			AAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAIENI
+			SU5BAAAAAAAAAAAAAJA0gAAAAAAAAAAAAAAAAAAFAENISU5BAAAA
+			+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAA
+			AAAAAAAAAAAAAAAAAAAAAAAgUklERSBCRUxMAAAAAAAAkDWAAAAA
+			AAAAAAAAAAAAAAkAUklERSBCRUxMAAAA+v8AAAAAAAAAAAAAAACA
+			ABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA
+			AAAgVEFNQi4AAAAAAAAAAAAAkDaAAAAAAAAAAAAAAAAAAAUAVEFN
+			Qi4AAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAA
+			AADwAAAAAAAAAAAAAAAAAAAAAAAAACBTUExBU0gAAAAAAAAAAACQ
+			N4AAAAAAAAAAAAAAAAAABgBTUExBU0gAAPr/AAAAAAAAAAAAAAAA
+			gAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA
+			AAAAIENPV0JFTEwAAAAAAAAAAJA4gAAAAAAAAAAAAAAAAAAHAENP
+			V0JFTEwAAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAA
+			AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBDUkFTSCAyAAAAAAAA
+			AACQOYAAAAAAAAAAAAAAAAAABwBDUkFTSCAyAAAA+v8AAAAAAAAA
+			AAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAA
+			AAAAAAAAAAAgVklCUkEAAAAAAAAAAAAAkDqAAAAAAAAAAAAAAAAA
+			AAUAVklCUkEAAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAA
+			AAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBSSURFIDIAAAAA
+			AAAAAACQO4AAAAAAAAAAAAAAAAAABgBSSURFIDIAAPr/AAAAAAAA
+			AAAAAAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAA
+			AAAAAAAAAAAAIEggQk9OR08AAAAAAAAAAJA8gAAAAAAAAAAAAAAA
+			AAAHAEggQk9OR08AAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAA
+			AAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBMIEJPTkdP
+			AAAAAAAAAACQPYAAAAAAAAAAAAAAAAAABwBMIEJPTkdPAAAA+v8A
+			AAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAA
+			AAAAAAAAAAAAAAAAAAAgTUggQ09OR0EAAAAAAAAAkD6AAAAAAAAA
+			AAAAAAAAAAgATUggQ09OR0EAAPr/AAAAAAAAAAAAAAAAgAAQAAAA
+			AAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAIE9I
+			IENPTkdBAAAAAAAAAJA/gAAAAAAAAAAAAAAAAAAIAE9IIENPTkdB
+			AAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAAAADw
+			AAAAAAAAAAAAAAAAAAAAAAAAACBMIENPTkdBAAAAAAAAAACQQIAA
+			AAAAAAAAAAAAAAAABwBMIENPTkdBAAAA+v8AAAAAAAAAAAAAAACA
+			ABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAA
+			AAAgSCBUSU1CAAAAAAAAAAAAkEGAAAAAAAAAAAAAAAAAAAYASCBU
+			SU1CAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAA
+			AADwAAAAAAAAAAAAAAAAAAAAAAAAACBMIFRJTUIAAAAAAAAAAACQ
+			QoAAAAAAAAAAAAAAAAAABgBMIFRJTUIAAPr/AAAAAAAAAAAAAAAA
+			gAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA
+			AAAAIEggQUdPR08AAAAAAAAAAJBDgAAAAAAAAAAAAAAAAAAHAEgg
+			QUdPR08AAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAA
+			AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBMIEFHT0dPAAAAAAAA
+			AACQRIAAAAAAAAAAAAAAAAAABwBMIEFHT0dPAAAA+v8AAAAAAAAA
+			AAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAA
+			AAAAAAAAAAAgQ0FCQVNBAAAAAAAAAAAAkEWAAAAAAAAAAAAAAAAA
+			AAYAQ0FCQVNBAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAA
+			AAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBNQVJBQ0FTAAAA
+			AAAAAACQRoAAAAAAAAAAAAAAAAAABwBNQVJBQ0FTAAAA+v8AAAAA
+			AAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAA
+			AAAAAAAAAAAAAAAgU0ggV0hJU1RMRQAAAAAAkEeAAAAAAAAAAAAA
+			AAAAAAoAU0ggV0hJU1RMRQAA+v8AAAAAAAAAAAAAAACAABAAAAAA
+			AAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAgTEwg
+			V0hJU1RMRQAAAAAAkEiAAAAAAAAAAAAAAAAAAAoATEwgV0hJU1RM
+			RQAA+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA
+			8AAAAAAAAAAAAAAAAAAAAAAAAAAgUyBHVUlSTwAAAAAAAAAAkEmA
+			AAAAAAAAAAAAAAAAAAcAUyBHVUlSTwAAAPr/AAAAAAAAAAAAAAAA
+			gAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAA
+			AAAAIEwgR1VJUk8AAAAAAAAAAJBKgAAAAAAAAAAAAAAAAAAHAEwg
+			R1VJUk8AAAD6/wAAAAAAAAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAA
+			AAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBDTEFWRVMAAAAAAAAA
+			AACQS4AAAAAAAAAAAAAAAAAABgBDTEFWRVMAAPr/AAAAAAAAAAAA
+			AAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAA
+			AAAAAAAAIEggV09PREJMTwAAAAAAAJBMgAAAAAAAAAAAAAAAAAAJ
+			AEggV09PREJMTwAAAPr/AAAAAAAAAAAAAAAAgAAQAAAAAAAAAAAA
+			AAAAAAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAIEwgV09PREJM
+			TwAAAAAAAJBNgAAAAAAAAAAAAAAAAAAJAEwgV09PREJMTwAAAPr/
+			AAAAAAAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAA
+			AAAAAAAAAAAAAAAAAAAAIE0gQ1VJQ0EAAAAAAAAAAJBOgAAAAAAA
+			AAAAAAAAAAAHAE0gQ1VJQ0EAAAD6/wAAAAAAAAAAAAAAAIAAEAAA
+			AAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBP
+			IENVSUNBAAAAAAAAAACQT4AAAAAAAAAAAAAAAAAABwBPIENVSUNB
+			AAAA+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA
+			8AAAAAAAAAAAAAAAAAAAAAAAAAAgTSBUUklBTkdMAAAAAAAAkFCA
+			AAAAAAAAAAAAAAAAAAkATSBUUklBTkdMAAAA+v8AAAAAAAAAAAAA
+			AACAABAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAA
+			AAAAAAAgTyBUUklBTkdMAAAAAAAAkFGAAAAAAAAAAAAAAAAAAAkA
+			TyBUUklBTkdMAAAA+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAA
+			AAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAgU0hBS0VSAAAA
+			AAAAAAAAkFKAAAAAAAAAAAAAAAAAAAYAU0hBS0VSAAD6/wAAAAAA
+			AAAAAAAAAIAAEAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAA
+			AAAAAAAAAAAAACBKSU5HTEVCLgAAAAAAAACQU4AAAAAAAAAAAAAA
+			AAAACABKSU5HTEVCLgAA+v8AAAAAAAAAAAAAAACAABAAAAAAAAAA
+			AAAAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAgQkVMTFRS
+			RUUAAAAAAAAAkFSAAAAAAAAAAAAAAAAAAAgAQkVMTFRSRUUAAPr/
+			AAAAAAAAAAAAAAAAgAAQAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAA
+			AAAAAAAAAAAAAAAAAAAAIENBU1RBTkVUAAAAAAAAAJBVgAAAAAAA
+			AAAAAAAAAAAIAENBU1RBTkVUAAD6/wAAAAAAAAAAAAAAAIAAEAAA
+			AAAAAAAAAAAAAAAAAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAACBN
+			IFNVUkRPAAAAAAAAAACQVoAAAAAAAAAAAAAAAAAABwBNIFNVUkRP
+			AAAA+v8AAAAAAAAAAAAAAACAABAAAAAAAAAAAAAAAAAAAAAAAAAA
+			8AAAAAAAAAAAAAAAAAAAAAAAAAAgTyBTVVJETwAAAAAAAAAAkFeA
+			AAAAAAAAAAAAAAAAAAcATyBTVVJETwBpdm5FAwAUAAAAAAAAAP//
+			////////AgAAAAEAtAAAAAAAAAC0AkBAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIADBwAKAAEAAQAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAC0AiBObyBPdXRwdXQAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAABAAAAAACAAAAAkATm8gT3V0cHV0AAAAAAAA
+			AAAAAABpdm5FAwAUAAAADAAAAP//////////AgAAAAEASgEAAAAA
+			AABIA0BAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAJggEHABkAEAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABI
+			AyBNSURJIENsaWNrACkAAAAAAAAAAAAAAAAAAAAAAAAAOBEAAAAA
+			AAAAAAoATUlESSBDbGljawkAAAAAAAAAAAAAAAAAAACZAAAAAAAA
+			AAAAAHAlAAAAAAAAAAAAAIkAAAAA4AEAAAAAAAAAAAAAAAAAAAAA
+			AACZAAAAAAAAAAAAAFglAAAAAAAAAAAAAIkAAAAA8AAAAAAAAAAA
+			AAAAAAAAAAAAAACZAAAAAAAAgAAAADQlAAAAAAAAAAAAAIkAAAAA
+			UAAAAAAAAAAAAAAAAAAAAAAAAABpdm5FAwAUAAAAEAAAAP//////
+			////AgAAAAEAsgAAAAAAAAC0AkBAAAAAAAAAAAAAAAAAEAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAIADBwAKAAEAAQD//wAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAC0AiAoRm9sZGVyKQAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAARAAAAAAACgAAAgAKEZvbGRlcikAAAAAAAAAAAAA
+			aXZuRQMAFAAAABQAAAD//////////wIAAAABALoAAAAAAAAAtAJA
+			QAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			Do4CVgAZABAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtAIgU2Vx
+			dWVuY2VyIElucHV0ACkAAAAAAAAAAAAAAAAAAEQRAAAAAAEAAAAP
+			AFNlcXVlbmNlciBJbnB1dAAAAAAAAAAAAAAAaXZuRQMAFAAAABgA
+			AAD//////////wIAAAABANAAAAAAAAAAzAJAQAAAAAAAAAAAAAAA
+			ABgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADSIADQDSAGAAAgAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAyAIgUGh5c2ljYWwgSW5wdXQA
+			KQAAAAAAAAAAAAAAAAAAAEMRAAAAAAEAAAAOAFBoeXNpY2FsIElu
+			cHV0AEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEQAAAAAAGl2
+			bkUDABQAAABAAAAA//////////8CAAAAAQDCAgAAAAAAAMAEQEAA
+			AAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABM8
+			AVYAUAA8AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALwEIElucHV0
+			IFZpZXcAAAAAAAAAAAAAAAAAAAAAAAAAAABBEQAAAAABAAAACgBJ
+			bnB1dCBWaWV3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAABp
+			dm5FAwAUAAAARAAAAP//////////AgAAAAEAPgEAAAAAAABAA0BA
+			AAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH
+			NgG8AJYBNgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AyBJbnB1
+			dCBOb3RlcwAAAAAAAAAAAAAAAAAAAAAAAAAAPBEAAAAAAAAAAAsA
+			SW5wdXQgTm90ZXMAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAA
+			AAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAA
+			AABpdm5FAwAUAAAASAAAAP//////////AgAAAAEAwgEAAAAAAABs
+			BkBAAAAAAAAAAAAAAAAASAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAARCQAZAEIAEAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsBiBB
+			dWRpbyAxACBTdHJpcCkAAAAAAAAAAAAAAAAAAAAAmhEAAAAACCgA
+			AAcAQXVkaW8gMQABAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAEwAAAAAAAAAAAAA
+			BgAAAAAGigAAAAAAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABpdm5FAwAUAAAATAAAAP//////
+			////AgAAAAEAxAEAAAAAAABsBkBAAAAAAAAAAAAAAAAATAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAARSwAZAEIAEAAEAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAABsBiBQcmVsaXN0ZW4AdHJpcCkAAAAAAAAA
+			AAAAAAAAAAAAmhEAAAAACCgAAAkAUHJlbGlzdGVuACIAAAEAAQAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAEAAAAAUAAAAAAAAAAAAAAGAAAAAAaKAAAAAAAAAAAAfwB/
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AGl2bkUDABQAAABQAAAA//////////8CAAAAAQDAAQAAAAAAAGwG
+			QEAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			ABHhABkAQgAQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwGIENs
+			aWNrAGVsIFN0cmlwKQAAAAAAAAAAAAAAAAAAAACZEQAAAQAIIQAA
+			BQBDbGljawBJAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAFQAAAAAAAAAAAAABgAA
+			AAAGigAAAAAAAAAAAH8AfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAABpdm5FAwAUAAAAVAAAAP//////////
+			AgAAAAEAwAEAAAAAAABsBkBAAAAAAAAAAAAAAAAAVAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAARiQEZAEIAEAAEAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAABsBiBCdXMgMQBlbCBTdHJpcCkAAAAAAAAAAAAA
+			AAAAAAAAnBEAAAAACB4AAAUAQnVzIDEATAAAAAABAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+			AABYAAAAAAAAAAAAAAYAAAAABooAAAAAAAAAAAB/AH8AAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAaXZuRQMA
+			FAAAAFgAAAD//////////wIAAAABAMABAAAAAAAAbAZAQAAAAAAA
+			AAAAAAAAAFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEcsBGQBC
+			ABAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbAYgQnVzIDIAZWwg
+			U3RyaXApAAAAAAAAAAAAAAAAAAAAAJwRAAAAAAgeAAAFAEJ1cyAy
+			AE0AAAEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAEAAAAAXAAAAAAAAAAAAAAGAAAAAAaKAAAA
+			AAAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAGl2bkUDABQAAABcAAAA//////////8CAAAAAQDA
+			AQAAAAAAAGwGQEAAAAAAAAAAAAAAAABcAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAQIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAREfAhkAQgAQAAQAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAGwGIE91dHB1dABsIFN0cmlwKQAAAAAAAAAAAAAAAAAAAACa
+			EQAAAAAIHgAABgBPdXRwdXRQAAAAAAEAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAGAAAAAA
+			AAAAAAAABgAAAAAGigAAAAAAAAAAAH8AfwAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABpdm5FAwAUAAAAYAAA
+			AP//////////AgAAAAEAwAEAAAAAAABsBkBAAAAAAAAAAAAAAAAA
+			YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARcwIZAEIAEAAEAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAABsBiBNYXN0ZXIAbCBTdHJpcCkA
+			AAAAAAAAAAAAAAAAAAAAmhEAAAAACDAAAAYATWFzdGVyTgAAAAAB
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAQAAAABkAAAAAAAAAAAAAAYAAAAABooAAAAAAAAAAAB/
+			AH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAaXZuRQMAFAAAAGQAAAD//////////wIAAAABAMABAAAAAAAA
+			bAZAQAAAAAAAAAAAAAAAAGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAABAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAETUBGQBCABAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbAYg
+			QXV4IDEAZWwgU3RyaXApAAAAAAAAAAAAAAAAAAAAAJwRAAAAAAge
+			AAAFAEF1eCAxACUAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAaAAAAAAAAAAAAAAG
+			AAAAAAaKAAAAAAAAAAAAfwB/AAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAGl2bkUDABQAAABoAAAA////////
+			//8CAAAAAQDAAQAAAAAAAGwGQEAAAAAAAAAAAAAAAABoAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAABGfABkAQgAQAAQAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAGwGIEluc3QgMQBsIFN0cmlwKQAAAAAAAAAA
+			AAAAAAAAAACZEQAAAAAIIQAABgBJbnN0IDEoAAD/AAEAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB
+			AAAAAP//AAAAAAAAAAAABgAAAAAGigAAAAAAAAAAAH8AfwAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABxZVNN
+			AgAWAAAAAAAAAP//////////AgAAAAEALgEAAAAAAAAuA0EAAAAA
+			AA8AAAAAAAAACQDmnKrlkb3lkI0AAAAAAAAAAABAAAAAAAAAAAAA
+			AAAglqKWvZa8AJJpAACcAd4FAAAUToUWAAAAAOjS8AAAAAAAAAAA
+			AAAAADB1AAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAABooAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAIAAAAAAP8AAAAAAHFTdkUBABYAAAAAAAAADwAA
+			AP////8CAAAAAQBQAAAAAAAAABEAAAAApQAAAAAAAAAAAAARAAAA
+			AMMAAAAAAAABAAAAEAAAAP/BAQAAAAAAAAAAgAAAAAAAAACIAAAA
+			AACWAADxAAAA////PwAAAAAAAAAAcWVTTQIAFgAAAAQAAAD/////
+			/////wIAAAABAC4BAAAAAAAALgNBAAAAAAAFAAAAAAAAAAkA5pyq
+			5ZG95ZCNAAAAAAAAAAAAQAAAAAAAAAAAAAAAIJailr2WvACSaQAA
+			nAHeBQAAFE6FFgAAAADo0vAAAAAAAAAAAAAAAAAwdQAAAAAAAAAA
+			AAAAAFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAGAAAAAAaKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAA
+			AAD/AAAAAABxU3ZFAQAWAAAABAAAAAUAAAD/////AgAAAAEAQAAA
+			AAAAAAASAAAAAJYAAAAAAAAAAAAABAAAAAAAAIgAAAAAACwBAAAA
+			AAAAAACIAAAAAAAAAADxAAAA////PwAAAAAAAAAAcWVTTQIAFwAA
+			AAAAAAD//////////wIAAAABACoBAAAAAAAAagNBAAAAAAAGAAAA
+			AAAAAAUAVFJBU0gAAAAAAAAAAABCADwAAAAAAAAAAAAgVFJBU0gA
+			0JJpAACcAd4FAAAUToUWAAAAAOjS8AAAAAAAAAAAAAAA/z3+PwAA
+			AAACAAAAAAAAVAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAYAAAAABooAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAD//wAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAIAAAAAAP8AAAAAAGthclQDABcAAAAAAAAA/////wAAAAACAAAA
+			AQAwAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAGyEliyeeRo68
+			R0eUxne8RQAAAAAAAAAAAAAAAHFTdkUBABcAAAAAAAAABgAAAP//
+			//8CAAAAAQAQAAAAAAAAAPEAAAD///8/AAAAAAAAAABxZVNNAgAX
+			AAAABAAAAP//////////AgAAAAEAMAEAAAAAAADiA0EAAAAAAAcA
+			AAAAAAAACwBSb290IEZvbGRlcgAAAAAAAAAAAEMAtAAAAAAAAAAA
+			ACBSb290IEZvbGRlcgAB3gUAABROhRYAAAAA6NLwAAAAAAAAAAAA
+			AAAALAEAAAAAAAIAAAAAAABUAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAigAAAAAAAAAAAAAA
+			AAAAAAAAACAAAAAAAAAAAAABAAAAAAAAAAAAAAAQAAAAAAAAAP//
+			AAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAgAAAAAA/wAAAAAAa2FyVAMAFwAAAAQAAAD/////
+			AAAAAAIAAAABADAAAAAAAAAAAQAVAAgAAABIAAAAAAAAAAAAAAA+
+			9+/iWWZGK6tx+bg71hmyIAAAAAAAAAcAAAAAa2FyVAMAFwAAAAQA
+			AAD/////AQAAAAIAAAABADAAAAAAAAAAAQAAAAAAAABkAAAAAAAA
+			AAAAAACGSUb4CIxAw6CEItGQzmPvIAAAAAAAAAcAAAAAa2FyVAMA
+			FwAAAAQAAAD/////AgAAAAIAAAABADAAAAAAAAAAAQAAAAAAAABc
+			AAAAAAAAAAAAAAALG3EH0AlIZadBGHP6KXRIIAAAAAAAAAcAAAAA
+			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
+			AAAAAAAAAAAAMHUAAAAAAAAAAAAAAABUAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAGigAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAA
+			AAAAAPj/AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAgAAAAAA/wAAAAAAcVN2RQEAFwAAAAwA
+			AAAMAAAA/////wIAAAABABAAAAAAAAAA8QAAAP///z8AAAAAAAAA
+			AHFlU00CABcAAAAQAAAA//////////8CAAAAAQAwAQAAAAAAAC4D
+			QQAAAAAADQAAAAAAAAALACpBdXRvbWF0aW9uAAAAAAAAAAAAQyEA
+			AAAAAAAAAAAAICpBdXRvbWF0aW9uAAHeBQAAFE6FFgAAAADo0vAA
+			AAAAAAAAAAAAAAAwdQAAAAAAAAAAAAAAAFQAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAE
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAAaKAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGgA
+			AAAAAAAA/f8AAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAACAAAAAAD/AAAAAABxU3ZFAQAXAAAA
+			EAAAAA0AAAD/////AgAAAAEAEAAAAAAAAADxAAAA////PwAAAAAA
+			AAAAcWVTTQIAFwAAABQAAAD//////////wIAAAABADABAAAAAAAA
+			LgNBAAAAAAAOAAAAAAAAAAsAKkF1dG9tYXRpb24AAAAAAAAAAABD
+			IQAAAAAAAAAAAAAgKkF1dG9tYXRpb24AAd4FAAAUToUWAAAAAOjS
+			8AAAAAAAAAAAAAAAADB1AAAAAAAAAAAAAAAAVAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAABooA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			ZAAAAAAAAAD7/wAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAP8AAAAAAHFTdkUBABcA
+			AAAUAAAADgAAAP////8CAAAAAQAQAAAAAAAAAPEAAAD///8/AAAA
+			AAAAAABxZVNNAgAXAAAAGAAAAP//////////AgAAAAEAMAEAAAAA
+			AAAuA0EAAAAAABAAAAAAAAAACwAqQXV0b21hdGlvbgAAAAAAAAAA
+			AEMhAAAAAAAAAAAAACAqQXV0b21hdGlvbgAB3gUAABROhRYAAAAA
+			6NLwAAAAAAAAAAAAAAAAMHUAAAAAAAAAAAAAAABUAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAG
+			igAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AABIAAAAAAAAAP//AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAA/wAAAAAAcVN2RQEA
+			FwAAABgAAAAQAAAA/////wIAAAABABAAAAAAAAAA8QAAAP///z8A
+			AAAAAAAAAHFlU00CABkAAAAAAAAA//////////8CAAAAAQAuAQAA
+			AAAAAC4DAQAAAAAAAQAAAAAAAAAJAOacquWRveWQjQAAAAAAAAAA
+			AAAAAAAAAAAAAAAAACCWopa9lrwAkmkAAJwB3gUAABROhRYAAAAA
+			6NLwAAAAAAAAAAAAAAAAMHUAAAAAAAAAAAAAAABUAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAG
+			igAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAA/wAAAAAAcVN2RQEA
+			GQAAAAAAAAABAAAA/////wIAAAABAEAAAAAAAAAAcAAAAACWAAAA
+			AAAAZQAAAP//////DDyyIiIiIgL/////////////siIiIiIi////
+			8QAAAP///z8AAAAAAAAAAE1kblUBABwAAAAAAAAA//////////8C
+			AAAAAQAYAAAAAAAAABgARxIAAAAAAAAAAAAAAAAAAAAAAAAAAHFT
+			eFQBACAAAAAAAAAA//////////8CAAAAAQBkAAAAAAAAAGQAAAAA
+			AAAAAAAAAAAAAABiAAAAZAAAABEAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAPVxU3hUAQAgAAAABAAAAP//////////
+			AgAAAAEAbAAAAAAAAABsAAAAAAAAAAAAAAAAAAAAYgAAAGwAAAAU
+			AP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFNlY3Rp
+			b24gQQBxU3hUAQAgAAAACAAAAP//////////AgAAAAEAcgAAAAAA
+			AAByAAAAAAAAAAAAAAAAAAAAYgAAAHIAAAARAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+			AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEF1ZGlvIFJlY29yZGVyAAA=
+			</data>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSMutableData</string>
+				<string>NSData</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSMutableData</string>
+		</dict>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>DfLogicModel</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>DfLogicModel</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>29</integer>
+			</dict>
+			<key>CBData</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>17</integer>
+			</dict>
+			<key>DfArrangeCatchStatus</key>
+			<false/>
+			<key>DfArrangeFloatZoomIndex</key>
+			<real>41.749267578125</real>
+			<key>DfArrangeSPLVisibility</key>
+			<integer>1</integer>
+			<key>DfCountIn</key>
+			<true/>
+			<key>DfLastChromatic</key>
+			<false/>
+			<key>DfLastGrid</key>
+			<integer>0</integer>
+			<key>DfMediaProperties</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>8</integer>
+			</dict>
+			<key>DfMediaTrackTypeValue</key>
+			<integer>0</integer>
+			<key>DfMetronome</key>
+			<true/>
+			<key>DfMidiEditorTypeValue</key>
+			<integer>0</integer>
+			<key>DfMoveAutomationDataEnabled</key>
+			<false/>
+			<key>DfMovieFullPath</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>0</integer>
+			</dict>
+			<key>DfQuantizeAutomaticEnabledArrange</key>
+			<true/>
+			<key>DfQuantizeAutomaticEnabledEditor</key>
+			<true/>
+			<key>DfQuantizeAutomaticEnabledScoreEditor</key>
+			<false/>
+			<key>DfQuantizeGroupArrange</key>
+			<integer>0</integer>
+			<key>DfQuantizeGroupEditor</key>
+			<integer>0</integer>
+			<key>DfQuantizeGroupScoreEditor</key>
+			<integer>0</integer>
+			<key>DfQuantizeModeArrange</key>
+			<integer>-12</integer>
+			<key>DfQuantizeModeEditor</key>
+			<integer>-6</integer>
+			<key>DfQuantizeModeScoreEditor</key>
+			<integer>-8</integer>
+			<key>DfScoreFloatZoomIndex</key>
+			<real>127</real>
+			<key>DfShowAlignmentGuidesEnabled</key>
+			<false/>
+			<key>DfSnapEnabled</key>
+			<true/>
+			<key>DfSongFirstActiveSongPartIndex</key>
+			<integer>0</integer>
+			<key>DfSongLastActiveSongPartIndex</key>
+			<integer>0</integer>
+			<key>DfTransportViewLCDMode</key>
+			<integer>1</integer>
+			<key>DfWaveFloatZoomIndex</key>
+			<real>35</real>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>16</integer>
+			</dict>
+			<key>NS.keys</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>9</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>10</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>11</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>12</integer>
+				</dict>
+			</array>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>13</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>14</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>14</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>15</integer>
+				</dict>
+			</array>
+		</dict>
+		<string>DfPodcastExplicitKey</string>
+		<string>DfPodcastEpisodeCropImageRectKey</string>
+		<string>DfPodcastEpisodeImageNameKey</string>
+		<string>DfPodcastTitleKey</string>
+		<integer>0</integer>
+		<string></string>
+		<string>我的乐曲</string>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>NSMutableDictionary</string>
+				<string>NSDictionary</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>NSMutableDictionary</string>
+		</dict>
+		<dict>
+			<key>$class</key>
+			<dict>
+				<key>CF$UID</key>
+				<integer>16</integer>
+			</dict>
+			<key>NS.keys</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>18</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>19</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>20</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>21</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>22</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>23</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>24</integer>
+				</dict>
+			</array>
+			<key>NS.objects</key>
+			<array>
+				<dict>
+					<key>CF$UID</key>
+					<integer>25</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>26</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>26</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>26</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>27</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>28</integer>
+				</dict>
+				<dict>
+					<key>CF$UID</key>
+					<integer>26</integer>
+				</dict>
+			</array>
+		</dict>
+		<string>ArrangeScrollOffset</string>
+		<string>AutomaticRecordingActiveForLastSongPart</string>
+		<string>IMVisible</string>
+		<string>CbMiniArrangeVisible</string>
+		<string>CurrentMediaImporterPage</string>
+		<string>CbArrangeButtonWasShownKey</string>
+		<string>CbArrangeTrackHeaderMixerOpenWhenTIClose</string>
+		<string>{0, 0}</string>
+		<false/>
+		<string>AudioFileImport</string>
+		<true/>
+		<dict>
+			<key>$classes</key>
+			<array>
+				<string>DfArrangeModel</string>
+				<string>NSObject</string>
+			</array>
+			<key>$classname</key>
+			<string>DfArrangeModel</string>
+		</dict>
+	</array>
+	<key>$top</key>
+	<dict>
+		<key>CbVersion</key>
+		<integer>35000</integer>
+		<key>DfDocument arrange model</key>
+		<dict>
+			<key>CF$UID</key>
+			<integer>7</integer>
+		</dict>
+		<key>DfDocument logic model</key>
+		<dict>
+			<key>CF$UID</key>
+			<integer>3</integer>
+		</dict>
+		<key>DfDocumentMachine</key>
+		<dict>
+			<key>CF$UID</key>
+			<integer>2</integer>
+		</dict>
+		<key>DfDocumentSystem</key>
+		<dict>
+			<key>CF$UID</key>
+			<integer>1</integer>
+		</dict>
+		<key>Version</key>
+		<integer>55000</integer>
+	</dict>
+	<key>$version</key>
+	<integer>100000</integer>
+</dict>
+</plist>

BIN
AIPlayRingtones/AppPage/Common/TSBandRingTool/tutorial-ring.mp4


+ 250 - 0
AIPlayRingtones/AppPage/Common/TSNetWork/TSNetWork+Business.swift

@@ -0,0 +1,250 @@
+//
+//  TSNetWork+Business.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/1/16.
+//
+
+/// 基础 URL(根据需求修改)
+private let baseURL = "http://ai.soundmove.cn"
+//private let baseChinaURL = "http://ai.100yearslater100.com"
+import Alamofire
+enum TSNeURLType:String {
+    
+    case musicCreate = "/api/music/create"         //音乐生成
+    case actionInfo = "/api/action/info"         //查询生成过程接口
+    case upload = "/api/upload"                  //上传
+   
+//    func getUrlString() -> String {
+//        if Locale.current.identifier.contains("_CN") {//中国区
+//            return baseChinaURL + self.rawValue
+//        }else{
+//            return baseURL + self.rawValue
+//        }
+//    }
+    
+    func getUrlString() -> String {
+        return baseURL + self.rawValue
+    }
+}
+
+
+func getUserInfoJsonString()->[String:Any] {
+    let uuid: String
+    let uuidUdKey = "my_UUID"
+    if let saved = UserDefaults.standard.string(forKey: uuidUdKey),
+       !saved.isEmpty {
+        uuid = saved
+    } else {
+        let newUuid = UUID().uuidString
+        UserDefaults.standard.set(newUuid, forKey: uuidUdKey)
+        UserDefaults.standard.synchronize()
+        uuid = newUuid
+    }
+    
+    let dic:[String:Any] = [
+        "device":UIDevice.current.modelName,
+        "deviceId":uuid,
+        "iosVersion":UIDevice.current.systemVersion,
+        "appVersion":appShortVersion(),
+//        "subscriptionStatus":kPurchaseDefault.isVip ? "active" : "fallow",
+    ]
+
+    return [String:Any]()
+}
+
+
+func getLanguageCode()->String{
+    if Locale.current.identifier.contains("zh-Hant"){
+        return "zh-Hant"
+    }
+    if let languageCode = Locale.current.languageCode {
+//        print("当前设备语言简写: \(languageCode)") // 输出如 "en", "ja", "zh" 等
+        return languageCode
+    }
+    return "en"
+}
+
+
+extension TSNetworkManager {
+    
+    /// 通用 get 请求
+    func get<T: TSBaseModel>(
+        urlType: TSNeURLType,
+        parameters: [String: Any]? = nil,
+        responseType: T.Type? = nil,
+        completion: @escaping (Result<Any, Error>) -> Void
+    ) -> Request  {
+        let urlString = urlType.getUrlString()
+        return request(method: .get, urlString: urlString, parameters:parameters) { result in
+            completion(result)
+        }
+    }
+
+
+    /// 通用 POST 请求
+    /// - Parameters:
+    ///   - endpoint: 接口路径
+    ///   - parameters: 请求参数
+    ///   - responseType: 响应数据模型(可选)
+    ///   - completion: 请求完成的回调
+    func post<T: TSBaseModel>(
+        urlType: TSNeURLType,
+        parameters: [String: Any]? = nil,
+        responseType: T.Type? = nil,
+        completion: @escaping (Result<Any, Error>) -> Void
+    ) -> Request {
+        let urlString = urlType.getUrlString()
+        return request(method: .post, urlString: urlString, parameters:parameters) { result in
+            completion(result)
+        }
+    }
+    
+    /// 通用 POST Stream 请求
+    /// - Parameters:
+    ///   - endpoint: 接口路径
+    ///   - parameters: 请求参数
+    ///   - responseType: 响应数据模型(可选)
+    ///   - completion: 请求完成的回调
+    func postStream<T: TSBaseModel>(
+        urlType: TSNeURLType,
+        parameters: [String: Any]? = nil,
+        responseType: T.Type? = nil,
+        streamHandler:@escaping (String) -> Void,
+        completion: @escaping (Result<Any, Error>) -> Void
+    ) -> Request?{
+        let urlString = urlType.getUrlString()
+        let streamRequest = postStreamRequest(urlString: urlString, parameters: parameters, streamHandler: streamHandler, completion: completion)
+        return streamRequest
+    }
+
+    
+    /// 上传多个 Data 数据
+    /// - Parameters:
+    ///   - urlType: TSNeURLType
+    ///   - dataArray: Data 数组,每个元素是一个字典,包含 Data 和字段名
+    ///   - parameters: 其他参数(可选)
+    ///   - headers: 自定义请求头(可选)
+    ///   - completion: 完成回调,返回结果或错误
+    func uploadData<T: TSBaseModel>(
+        urlType: TSNeURLType,
+        dataArray: [[String: Any]], // Data 数组,每个元素包含 Data 和字段名
+        parameters: [String: Any]? = nil,
+        responseType: T.Type? = nil,
+        progressHandler: @escaping (Float) -> Void, // 上传进度回调
+        completion: @escaping (Result<Any, Error>) -> Void
+    ) -> Request?{
+        let urlString = urlType.getUrlString()
+        let request = uploadData(urlString: urlString,dataArray:dataArray, parameters: parameters, progressHandler: { progress in
+            progressHandler(Float(progress.fractionCompleted))
+        },completion: completion)
+        return request
+    }
+    
+    func downloadFile(
+        urlString: String,
+        to destination: URL,
+        progressHandler: ((Double) -> Void)? = nil,
+        completion: @escaping (URL?, Error?) -> Void
+    ) -> DownloadRequest? {
+        let request = self.downloadFile(
+            urlString: urlString,
+            to: destination,
+            progressHandler: { progress in
+                print("下载进度: \(progress * 100)%")
+                progressHandler?(progress)
+            },
+            completion: { result in
+                switch result {
+                case .success(let fileURL):
+                    dePrint("下载完成,文件保存在: \(fileURL.path)")
+                    completion(fileURL,nil)
+                case .failure(let error):
+                    dePrint("下载失败: \(error.localizedDescription)")
+                    completion(nil,error)
+                }
+            }
+        )
+        return request
+    }
+
+}
+
+extension TSNetworkManager {
+    
+//    func uploadAudio(
+//        fileURL:URL,
+//        progressHandler: @escaping (Float) -> Void, // 上传进度回调
+//        completion: @escaping (Any?, Error?) -> Void)
+//    -> Request?{
+//
+//        let urlString = TSNeURLType.upload.getUrlString()
+//        
+//        let request = uploadFile(urlString: urlString, fileURL: fileURL, multipartBuilder: { multipart in
+//            multipart.append(fileURL, withName: "file", fileName: "audio.mp3", mimeType: "audio/mp3")
+//        }) { progress in
+//            progressHandler(Float(progress.fractionCompleted))
+//        } completion: { [weak self] result in
+//            guard let self = self else { return }
+//            switch result {
+//            case .success(let data):
+//                if let dataDict = kNetWorkCodeSuccess(data: data),
+//                   let picUrl = dataDict["result"] as? String{
+//                    completion(picUrl,nil)
+//                }else{
+//                    let error = NSError(domain: "Service exception", code: 0)
+//                    completion(nil,error)
+//                }
+//            case .failure(let error):
+//                completion(nil,error)
+//            }
+//        }
+//        
+//        return request
+//    }
+    
+    
+    func uploadAudio(
+        fileURL:URL,
+        progressHandler: @escaping (Float) -> Void, // 上传进度回调
+        completion: @escaping (Any?, Error?) -> Void)
+    -> Request?{
+
+        let urlString = TSNeURLType.upload.getUrlString()
+        
+        
+        dePrint("✈️✈️✈️网络请求:\(urlString)")
+        guard let url = URL(string: urlString) else {
+            completion(nil,NSError(domain: "url nil", code: 0))
+            return nil
+        }
+        return AF.upload(
+            multipartFormData: { multipart in
+                multipart.append(fileURL, withName: "file", fileName: "audio.mp3", mimeType: "audio/mp3")
+            },
+            to: url
+        )
+        .uploadProgress { progress in
+            dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
+            progressHandler(Float(progress.fractionCompleted))
+        }
+        .responseString { response in
+            self.handleResponse(response) { [weak self] result in
+                guard let self = self else { return }
+                switch result {
+                case .success(let data):
+                    if let dataDict = kNetWorkCodeSuccess(data: data),
+                       let picUrl = dataDict["result"] as? String{
+                        completion(picUrl,nil)
+                    }else{
+                        let error = NSError(domain: "Service exception", code: 0)
+                        completion(nil,error)
+                    }
+                case .failure(let error):
+                    completion(nil,error)
+                }
+            }
+        }
+    }
+}
+

+ 111 - 0
AIPlayRingtones/AppPage/Common/TSNetWork/TSNetWork+Error.swift

@@ -0,0 +1,111 @@
+//
+//  TSNetWork+Error.swift
+//  AIPlayRingtones
+//
+//  Created by 100Years on 2025/5/18.
+//
+
+
+import Alamofire
+let kGenerateFailed:String = "Sorry there was a slight problem with the image processing, please try again later.".localized
+
+enum TSNetWorkCode : Int {
+    case success = 200
+    case fail = 0   //通用错误
+    case textSensitive = -10003    //文生图敏感错误
+    case imageSensitive = -10004   //图生图敏感错误
+    case networkError = -1005   //网络错误
+    
+    
+    var errorMsg:String {
+        switch self {
+        case .textSensitive,.imageSensitive:
+            return "Your photo may contain copyright infringement, nudity, gore or violence that does not comply with the Health Policy, please replace the photo and try again.".localized
+        case .networkError:
+            return "No network, please check your network and try again.".localized
+        default:
+            return "Sorry there was a slight problem with the image processing, please try again later.".localized
+        }
+        
+    }
+    
+    //获取生成错误 code 对应的文案
+    static func errorMsg(code:Int)->String{
+        let netCode = TSNetWorkCode(rawValue: code) ?? .fail
+        return netCode.errorMsg
+    }
+    //敏感错误
+    static func sensitiveError(code:Int)->Bool{
+        let netCode = TSNetWorkCode(rawValue: code)
+        switch netCode {
+        case .textSensitive,.imageSensitive:
+            return true
+        default:
+            return false
+        }
+    }
+    
+    //网络错误错误
+    static func networkError(code:Int)->Bool{
+        let netCode = TSNetWorkCode(rawValue: code)
+        switch netCode {
+        case .networkError:
+            return true
+        default:
+            return false
+        }
+    }
+    
+    //网络错误错误
+    static func getErrorCode(_ error: Error) -> Int {
+        if let urlError = error as? URLError {
+            switch urlError.code {
+            case .notConnectedToInternet, .networkConnectionLost:
+                return TSNetWorkCode.networkError.rawValue
+            default:
+                return urlError.code.rawValue
+            }
+        }
+        return 0
+    }
+    //获取生成错误 code 对应的文案
+    static func getGeneratorStyle(code:Int)->ASGeneratorView.Style{
+        let netCode = TSNetWorkCode(rawValue: code)
+        switch netCode {
+        case .textSensitive,.imageSensitive:
+            return ASGeneratorView.Style.sensitiveError
+        case .networkError:
+            return ASGeneratorView.Style.netWorkError
+        default:
+            return ASGeneratorView.Style.generalError
+        }
+    }
+}
+
+
+extension Error {
+    
+    var tsCode:Int {
+        if let error = self as? AFError, let underlyingError = error.underlyingError as? URLError {
+            switch underlyingError.code {
+            case .notConnectedToInternet, .networkConnectionLost,.timedOut:
+                return TSNetWorkCode.networkError.rawValue
+            default:
+                return underlyingError.code.rawValue
+            }
+        }else
+        if let urlError = self as? URLError {
+            switch urlError.code {
+            case .notConnectedToInternet, .networkConnectionLost,.timedOut:
+                return TSNetWorkCode.networkError.rawValue
+            default:
+                return urlError.code.rawValue
+            }
+        }
+        return 0
+    }
+    
+    var tsDesc:String {
+        return TSNetWorkCode.errorMsg(code: tsCode)
+    }
+}

+ 86 - 0
AIPlayRingtones/AppPage/Common/TSNetWork/TSNetworkManager+Loading.swift

@@ -0,0 +1,86 @@
+//
+//  TSNetworkManager+Loading.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/1/16.
+//
+import Alamofire
+extension TSNetworkManager {
+    
+    /// 通用 get 请求
+    func get<T: TSBaseModel>(
+        urlType: TSNeURLType,
+        parameters: [String: Any]? = nil,
+        responseType: T.Type? = nil,
+        animationView:UIView? = nil,
+        completion: @escaping (Any?, Error?) -> Void
+    ) -> Request {
+        
+        var isShowAnimation = false
+        if animationView != nil {
+            isShowAnimation = true
+        }
+        
+        if isShowAnimation,let view = animationView {
+            TSToastShared.showLoading(containerView: view)
+        }
+
+        return get(urlType: urlType, parameters:parameters,responseType:responseType) { result in
+            
+            if isShowAnimation {
+                TSToastShared.hideLoading()
+            }
+    
+            switch result {
+            case .success(let data):
+//                print("Response data: \(data)")
+                completion(data,nil)
+            case .failure(let error):
+//                print("Error: \(error)")
+                completion(nil,error)
+            }
+        }
+    }
+
+
+    /// 通用 POST 请求
+    /// - Parameters:
+    ///   - endpoint: 接口路径
+    ///   - parameters: 请求参数
+    ///   - responseType: 响应数据模型(可选)
+    ///   - completion: 请求完成的回调
+    func post<T: TSBaseModel>(
+        urlType: TSNeURLType,
+        parameters: [String: Any]? = nil,
+        responseType: T.Type? = nil,
+        animationView:UIView? = nil,
+        completion: @escaping (Any?, Error?) -> Void
+    ) -> Request {
+        var isShowAnimation = false
+        if animationView != nil {
+            isShowAnimation = true
+        }
+        
+        if isShowAnimation,let view = animationView {
+            TSToastShared.showLoading(containerView: view)
+        }
+
+        return post(urlType: urlType, parameters:parameters,responseType:responseType){ result in
+            
+            if isShowAnimation {
+                TSToastShared.hideLoading()
+            }
+    
+            switch result {
+            case .success(let data):
+//                print("Response data: \(data)")
+                completion(data,nil)
+            case .failure(let error):
+//                print("Error: \(error)")
+                completion(nil,error)
+            }
+        }
+    
+    }
+    
+}

+ 438 - 0
AIPlayRingtones/AppPage/Common/TSNetWork/TSNetworkManager.swift

@@ -0,0 +1,438 @@
+//
+//  NetworkManager.swift
+//  AIEmoji
+//
+//  Created by 100Years on 2025/1/16.
+//
+
+import Alamofire
+import ObjectMapper
+
+
+let TSNetworkShared = TSNetworkManager.shared
+
+/// 网络工具类
+class TSNetworkManager {
+    
+    static let shared = TSNetworkManager()
+    private init() {}
+    
+    /// 通用 Headers
+    private var defaultHeaders: HTTPHeaders {
+        return ["Content-Type": "application/json",
+                "accept": "application/json",
+//            "Authorization": "Bearer YOUR_ACCESS_TOKEN" // 按需修改
+        ]
+    }
+    
+    lazy var afSession: Session = {
+//        let configuration = URLSessionConfiguration.af.default
+//        configuration.timeoutIntervalForRequest = 15  // 请求超时时间(秒)
+//        configuration.timeoutIntervalForResource = 30 // 资源超时时间(秒)
+//        let session = Session(configuration: configuration)
+//        return session
+        
+        return AF
+    }()
+    lazy var encoder: JSONEncoding = {
+        return JSONEncoding(options: .withoutEscapingSlashes)// 关键:禁用斜杠转义
+    }()
+
+    func postStreamRequest(
+        urlString: String,
+        parameters: [String: Any]? = nil,
+        streamHandler:@escaping (String) -> Void,
+        completion: @escaping (Result<Any, Error>) -> Void
+    )-> Request? {
+        
+        guard let url = URL(string: urlString) else {
+            completion(.failure(NSError(domain: "url nil", code: 0)))
+            return nil
+        }
+        
+        // 1. 创建 URLRequest
+        var urlRequest = URLRequest(url:URL(string: urlString)!)
+        urlRequest.httpMethod = "POST"
+        urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
+        
+        // 2. 将字典参数转换为 JSON 数据并设置为请求体
+        do {
+            let jsonData = try JSONSerialization.data(withJSONObject: parameters, options: [.withoutEscapingSlashes])//去掉转义
+            urlRequest.httpBody = jsonData
+        } catch {
+            dePrint("Failed to encode parameters: \(error)")
+            completion(.failure(error))
+            return nil
+        }
+        
+        // 3. 使用 streamRequest 发起流式请求
+        let request = afSession.streamRequest(urlRequest)
+        request.responseStreamString{ stream in
+            switch stream.event {
+            case .stream(let result):
+                switch result {
+                case .success(let string):
+                    dePrint("🚰🚰🚰Stream Received string string: \(string)")
+                    streamHandler(string)
+                case .failure(let error):
+                    dePrint("Stream error: \(error)")
+                    completion(.failure(error))
+                }
+            case .complete(let cpl):
+                if let error = cpl.error {
+                    dePrint("Stream Request failed with error: \(error)")
+                    completion(.failure(error))
+                } else {
+                    dePrint("Stream success")
+                    completion(.success("Stream success"))
+                }
+            }
+        }
+        return request
+    }
+
+    func request(
+        method:HTTPMethod,
+        urlString: String,
+        parameters: [String: any Any & Sendable]? = nil,
+        completion: @escaping (Result<Any, Error>) -> Void
+    ) -> Request{
+        dePrint("✈️✈️✈️网络请求:\(urlString)")
+        dePrint("✈️✈️✈️参数:\(String(describing: parameters))")
+        
+        var encoding: ParameterEncoding = URLEncoding.default
+        if method == .post {
+            encoding = encoder
+        }
+        let request = afSession.request(urlString, method: method, parameters: parameters, encoding: encoding, headers: defaultHeaders, interceptor: nil)
+        request.responseString { response in
+                self.handleResponse(response, completion: completion)
+            }
+        return request
+    }
+    
+    
+
+    
+}
+
+extension TSNetworkManager {
+    
+    
+    /*
+     // Data 数组
+     let dataArray: [[String: Any]] = [
+         [
+             "data": imageData,
+             "fieldName": "file1", // 字段名
+             "fileName": "App-Icon.png", // 文件名
+             "mimeType": "image/png" // MIME 类型
+         ],
+         [
+             "data": textData,
+             "fieldName": "file2", // 字段名
+             "fileName": "hello.txt", // 文件名
+             "mimeType": "text/plain" // MIME 类型
+         ]
+     ]
+     */
+    
+    /// 上传多个 Data 数据
+    /// - Parameters:
+    ///   - url: 上传地址
+    ///   - dataArray: Data 数组,每个元素是一个字典,包含 Data 和字段名
+    ///   - parameters: 其他参数(可选)
+    ///   - headers: 自定义请求头(可选)
+    ///   - completion: 完成回调,返回结果或错误
+    func uploadData(
+        urlString: String,
+        dataArray: [[String: Any]], // Data 数组,每个元素包含 Data 和字段名
+        parameters: [String: Any]? = nil, // 其他参数
+        headers: HTTPHeaders? = nil, // 自定义请求头
+        progressHandler: @escaping (Progress) -> Void, // 上传进度回调
+        completion: @escaping (Result<Any, Error>) -> Void
+    )-> Request? {
+        
+        guard let url = URL(string: urlString) else {
+            completion(.failure(NSError(domain: "url nil", code: 0)))
+            return nil
+        }
+        
+        // 1. 设置默认请求头
+        var defaultHeaders: HTTPHeaders = [
+            "accept": "application/json",
+            "Content-Type": "multipart/form-data"
+        ]
+        // 合并自定义请求头
+        if let customHeaders = headers {
+            customHeaders.forEach { defaultHeaders[$0.name] = $0.value }
+        }
+        
+        dePrint("✈️✈️✈️网络请求:\(urlString)")
+        dePrint("✈️✈️✈️dataArray:\(String(describing: dataArray))")
+        dePrint("✈️✈️✈️参数:\(String(describing: parameters))")
+        // 2. 使用 Alamofire 上传 Data
+        let request = afSession.upload(
+            multipartFormData: { multipartFormData in
+                // 添加 Data
+                for dataItem in dataArray {
+                    if let data = dataItem["data"] as? Data,
+                       let fieldName = dataItem["fieldName"] as? String,
+                       let fileName = dataItem["fileName"] as? String,
+                       let mimeType = dataItem["mimeType"] as? String {
+                        multipartFormData.append(
+                            data,
+                            withName: fieldName,
+                            fileName: fileName,
+                            mimeType: mimeType
+                        )
+                    }
+                }
+
+                // 添加其他参数
+                if let parameters = parameters {
+                    for (key, value) in parameters {
+                        if let data = "\(value)".data(using: .utf8) {
+                            multipartFormData.append(data, withName: key)
+                        }
+                    }
+                }
+            },
+            to: url, // 上传地址
+            headers: defaultHeaders // 请求头
+        )
+        
+        request
+            .uploadProgress{ progress in
+                // 3. 上传进度回调
+                // 上传进度回调
+                dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
+                progressHandler(progress)
+            }
+            .responseString{ response in
+                // 4. 处理响应
+                self.handleResponse(response, completion: completion)
+        }
+        
+        return request
+    }
+    
+    //上传文件地址到服务器
+    func uploadFile(
+        urlString: String,
+        fileURL:URL,
+        multipartBuilder: @escaping (MultipartFormData) -> Void, // 闭包参数
+        progressHandler: @escaping (Progress) -> Void, // 上传进度回调
+        completion: @escaping (Result<Any, Error>) -> Void
+    )-> Request?{
+        dePrint("✈️✈️✈️网络请求:\(urlString)")
+        guard let url = URL(string: urlString) else {
+            completion(.failure(NSError(domain: "url nil", code: 0)))
+            return nil
+        }
+        return AF.upload(
+            multipartFormData: multipartBuilder,
+            to: url
+        )
+        .uploadProgress { progress in
+            dePrint("✈️✈️✈️进度: \(progress.fractionCompleted * 100)%")
+            progressHandler(progress)
+        }
+        .responseString { response in
+            self.handleResponse(response, completion: completion)
+        }
+    }
+    
+    
+    /// 下载文件
+    /// - Parameters:
+    ///   - url: 下载URL
+    ///   - destination: 目标保存路径 (可选,不传则使用临时目录)
+    ///   - progressHandler: 进度回调 (0.0~1.0)
+    ///   - completion: 完成回调 (返回文件URL或错误)
+    func downloadFile(
+        urlString: String,
+        to destination: URL? = nil,
+        progressHandler: ((Double) -> Void)? = nil,
+        completion: @escaping (Result<URL, Error>) -> Void
+    ) -> DownloadRequest? {
+        
+        
+        guard let url = URL(string: urlString) else {
+            completion(.failure(NSError(domain: "url nil", code: 0)))
+            return nil
+        }
+        
+        // 设置下载目标路径
+        let destination: DownloadRequest.Destination = { temporaryURL, response in
+            // 如果用户指定了目标路径
+            if let destination = destination {
+                // 确保目录存在
+                let directory = destination.deletingLastPathComponent()
+                try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: nil)
+                return (destination, [.removePreviousFile, .createIntermediateDirectories])
+            }
+            
+            // 否则使用临时目录
+            let documentsURL = FileManager.default.temporaryDirectory
+            let suggestedFilename = response.suggestedFilename ?? url.lastPathComponent
+            let fileURL = documentsURL.appendingPathComponent(suggestedFilename)
+            
+            return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
+        }
+        
+        // 开始下载
+        let request = afSession.download(url, to: destination)
+            .downloadProgress { progress in
+                // 主线程回调进度
+                DispatchQueue.main.async {
+                    progressHandler?(progress.fractionCompleted)
+                }
+            }
+            .response { response in
+                // 主线程回调结果
+                DispatchQueue.main.async {
+                    switch response.result {
+                    case .success(let fileURL):
+                        if let fileURL = fileURL {
+                            completion(.success(fileURL))
+                        } else {
+                            completion(.failure(NSError(domain: "DownloadError", code: -1, userInfo: [NSLocalizedDescriptionKey: "文件路径无效"])))
+                        }
+                    case .failure(let error):
+                        completion(.failure(error))
+                    }
+                }
+            }
+        
+        return request
+    }
+
+}
+
+extension TSNetworkManager {
+    
+    func handleResponse(
+        _ response: AFDataResponse<String>,
+        completion: @escaping (Result<Any, Error>) -> Void
+    ) {
+        
+        switch response.result {
+        case .success(let value):
+            
+            if let resultDict = dataToJSONObject(data:response.data) as? [String:Any] {
+                
+//                let code = resultDict.safeInt(forKey: "code")
+//                if responseType != nil {
+//                    if let model = T(JSONString: value) {
+//                        handleSuccess(data: model, response: response, completion: completion)
+//                    } else {
+//                        let models = Mapper<T>().mapArray(JSONString: value)
+//                        handleSuccess(data: models ?? [], response: response, completion: completion)
+//                    }
+//                } else {
+                    handleSuccess(data: resultDict, response: response, completion: completion)
+//                }
+                
+            }else{
+                handleFail(error: NSError(domain: "Unable to parse data", code: 0), response: response, completion: completion)
+            }
+
+        case .failure(let error):
+            handleFail(error: error, response: response, completion: completion)
+        }
+    }
+    
+    func handleSuccess(data:Any,
+                       response: AFDataResponse<String>,
+                       completion: @escaping (Result<Any, Error>) -> Void){
+        dePrint("🚗🚗🚗网络请求成功:\(String(describing: response.request?.url?.absoluteString))")
+        dePrint("🚗🚗🚗网络请求成功:\(response)")
+        completion(.success(data))
+       }
+    
+    func handleFail(error:Error,
+                    response: AFDataResponse<String>,
+                    completion: @escaping (Result<Any, Error>) -> Void){
+        dePrint("🚗🚗🚗网络请求失败:\(String(describing: response.request?.url?.absoluteString))")
+        dePrint("🚗🚗🚗网络请求失败:\(response)")
+        completion(.failure(error))
+    }
+    
+    func dataToJSONObject(data: Data?) -> Any? {
+        guard let data = data else { return nil }
+        do {
+            let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
+            return jsonObject
+        } catch {
+            print("Failed to convert Data to JSON object: \(error.localizedDescription)")
+            return nil
+        }
+    }
+    
+}
+
+
+
+func kNetWorkCodeSuccess(data:Any?) -> [String:Any]? {
+    guard let data = data else { return nil }
+    if let dataDict = data as? [String:Any]{
+        let code = dataDict.safeInt(forKey: "code")
+        
+        switch code {
+        case 200://成功
+            return dataDict
+//        case 400://机器人提示
+//            TSAbnormalPopUpAlertVC.showRobotWarning()
+//            return nil
+        default:
+            return nil
+        }
+    }
+    return nil
+}
+
+
+
+func kNetWorkResultSuccess(data:Any?) -> [String:Any]? {
+    guard let dataDict = kNetWorkCodeSuccess(data: data) else { return nil }
+    if let result = dataDict["result"] as? [String:Any]{
+        return result
+    }
+    return nil
+}
+
+func kNetWorkMessage(data:Any?) -> String? {
+    guard let data = data else { return nil }
+    if let dataDict = data as? [String:Any] ,
+       let message = dataDict["message"] as? String{
+        return message
+    }
+    return nil
+}
+
+  
+
+class JsonStringTransform<T:Mappable>: TransformType {
+    typealias Object = T
+    typealias JSON = [String: Any]
+    
+    func transformFromJSON(_ value: Any?) -> T? {
+    
+        if let jsonString = value as? String {
+            let obj = T(JSONString: jsonString)
+            return obj
+        }
+        
+        if let dict = value as? [String: Any] {
+            let obj = T(JSON: dict)
+            return obj
+        }
+
+        return nil
+    }
+    
+    func transformToJSON(_ value: T?) -> [String : Any]? {
+        return value?.toJSON() as? [String: Any]
+    }
+}

+ 19 - 0
AIPlayRingtones/AppPage/Common/TSPurchaseTool/TSPurchaseTool.swift

@@ -0,0 +1,19 @@
+//
+//  TSPurchaseTool.swift
+//  AIPlayRingtones
+//
+//  Created by mini on 2025/5/19.
+//
+
+
+
+
+func kshareBand(needVip:Bool,
+               vc:UIViewController,
+                fileURL:URL,
+                fileName:String,
+                completion:((Bool)->Void)? = nil) -> Bool {
+
+    TSBandRingTool.creatBandRingTool().shareBandVC(vc: vc, fileURL: fileURL, fileName: fileName,completion: completion)
+    return false
+}

+ 6 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Disco.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_Disco@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_Disco@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Disco.imageset/rtr_style_Disco@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Disco.imageset/rtr_style_Disco@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Dubstep.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_Dubstep@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_Dubstep@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Dubstep.imageset/rtr_style_Dubstep@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Dubstep.imageset/rtr_style_Dubstep@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Electro.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_Electro@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_Electro@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Electro.imageset/rtr_style_Electro@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Electro.imageset/rtr_style_Electro@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Funk.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_Funk@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_Funk@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Funk.imageset/rtr_style_Funk@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Funk.imageset/rtr_style_Funk@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_HipHop.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_HipHop@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_HipHop@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_HipHop.imageset/rtr_style_HipHop@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_HipHop.imageset/rtr_style_HipHop@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Jazz.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_Jazz@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_Jazz@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Jazz.imageset/rtr_style_Jazz@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Jazz.imageset/rtr_style_Jazz@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Pop.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_Pop@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_Pop@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Pop.imageset/rtr_style_Pop@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Pop.imageset/rtr_style_Pop@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Rock.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "rtr_style_Rock@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "rtr_style_Rock@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Rock.imageset/rtr_style_Rock@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/Style/rtr_style_Rock.imageset/rtr_style_Rock@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/nav_title_audioRingtone.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "nav_titile_audioRingtone@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "nav_titile_audioRingtone@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/nav_title_audioRingtone.imageset/nav_titile_audioRingtone@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/nav_title_audioRingtone.imageset/nav_titile_audioRingtone@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_add.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "uploadFile_add@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "uploadFile_add@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_add.imageset/uploadFile_add@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_add.imageset/uploadFile_add@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_change.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "uploadFile_change@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "uploadFile_change@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_change.imageset/uploadFile_change@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_change.imageset/uploadFile_change@3x.png


+ 22 - 0
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_icon.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "uploadFile_icon@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "uploadFile_icon@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_icon.imageset/uploadFile_icon@2x.png


BIN
AIPlayRingtones/Assets.xcassets/AudioToRingtone/uploadFile_icon.imageset/uploadFile_icon@3x.png


+ 6 - 0
AIPlayRingtones/Assets.xcassets/CellPlay/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
AIPlayRingtones/Assets.xcassets/CellPlay/ai_rintone_icon.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "ai_rintone_icon@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "ai_rintone_icon@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
AIPlayRingtones/Assets.xcassets/CellPlay/ai_rintone_icon.imageset/ai_rintone_icon@2x.png


BIN
AIPlayRingtones/Assets.xcassets/CellPlay/ai_rintone_icon.imageset/ai_rintone_icon@3x.png


Vissa filer visades inte eftersom för många filer har ändrats