diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d47b27556..889dece87 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,11 +5,11 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -# Only run this workflow when a tag is pushed when the tag starts with "v". +# Only run this workflow when a tag is pushed when the tag starts with "v0.2.". on: push: tags: - - 'v*' + - 'v0.2.*' # So we can use the GitHub API to create releases with the run token. permissions: @@ -35,11 +35,11 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 10.0.x - name: Download Dalamud Library run: | - wget https://goatcorp.github.io/dalamud-distrib/latest.zip -O /tmp/dalamud.zip + wget https://goatcorp.github.io/dalamud-distrib/stg/latest.zip -O /tmp/dalamud.zip unzip /tmp/dalamud.zip -d /tmp/dalamud - name: Restore Dependencies @@ -66,7 +66,7 @@ jobs: fail_on_unmatched_files: true # If the files arent found, fail the workflow and abort the release. - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Release Artifacts path: | @@ -82,9 +82,7 @@ jobs: sed -i repo.json -E \ -e 's#"AssemblyVersion": "([0-9]*\.){2,3}[0-9]*"#"AssemblyVersion": "'"$release_version"'"#g' \ - -e 's#"TestingAssemblyVersion": "([0-9]*\.){2,3}[0-9]*"#"TestingAssemblyVersion": "'"$release_version"'"#' \ -e 's#"DownloadLinkInstall": "[^"]*"#"DownloadLinkInstall": "'"$repo_url/releases/download/${{ github.ref_name }}/latest.zip"'"#g' \ - -e 's#"DownloadLinkTesting": "[^"]*"#"DownloadLinkTesting": "'"$repo_url/releases/download/${{ github.ref_name }}/latest.zip"'"#g' \ -e 's#"DownloadLinkUpdate": "[^"]*"#"DownloadLinkUpdate": "'"$repo_url/releases/download/${{ github.ref_name }}/latest.zip"'"#g' git add repo.json diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ec26fa55..9514534b8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,9 +23,10 @@ jobs: working-directory: Ktisis/ shell: bash strategy: + fail-fast: false matrix: - dotnet-version: [7.0.x] # Can add multiple .NET versions here to test against (For example, testing a new version of .NET before it's released) - dalamud-version: ["latest"] # Can add multiple Dalamud branches here to test against (For example, testing against Dalamud staging) + dotnet-version: [10.0.x] # Can add multiple .NET versions here to test against (For example, testing a new version of .NET before it's released) + dalamud-version: [""] # Can add multiple Dalamud branches here to test against - empty string means live latest. env: DALAMUD_HOME: /tmp/dalamud IsCI: true @@ -43,7 +44,8 @@ jobs: - name: Download Dalamud Library run: | - wget https://goatcorp.github.io/dalamud-distrib/${{ matrix.dalamud-version }}.zip -O /tmp/dalamud.zip + dalamud_version="${{ matrix.dalamud-version }}" + wget https://goatcorp.github.io/dalamud-distrib/${dalamud_version}${dalamud_version:+/}latest.zip -O /tmp/dalamud.zip unzip /tmp/dalamud.zip -d /tmp/dalamud - name: Restore Dependencies @@ -56,7 +58,7 @@ jobs: run: dotnet build -c Release --no-restore --nologo - name: Upload Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Build Artifacts path: Ktisis/bin/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..134e4d647 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "GLib"] + path = GLib + url = git@github.com:ktisis-tools/GLib.git diff --git a/GLib b/GLib new file mode 160000 index 000000000..e6286c041 --- /dev/null +++ b/GLib @@ -0,0 +1 @@ +Subproject commit e6286c041e401cae9d4c60e3ebce085122a1e530 diff --git a/Ktisis.sln b/Ktisis.sln index 69d0376bb..e3ee8ca0b 100644 --- a/Ktisis.sln +++ b/Ktisis.sln @@ -9,6 +9,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLib", "GLib\GLib\GLib.csproj", "{2267C775-9220-4EF5-B146-4FBC5B7499D8}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 @@ -22,6 +24,12 @@ Global {13C812E9-0D42-4B95-8646-40EEBF30636F}.Release|x64.Build.0 = Release|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.External|x64.ActiveCfg = External|x64 {13C812E9-0D42-4B95-8646-40EEBF30636F}.External|x64.Build.0 = External|x64 + {2267C775-9220-4EF5-B146-4FBC5B7499D8}.Debug|x64.ActiveCfg = Debug|Any CPU + {2267C775-9220-4EF5-B146-4FBC5B7499D8}.Debug|x64.Build.0 = Debug|Any CPU + {2267C775-9220-4EF5-B146-4FBC5B7499D8}.Release|x64.ActiveCfg = Release|Any CPU + {2267C775-9220-4EF5-B146-4FBC5B7499D8}.Release|x64.Build.0 = Release|Any CPU + {2267C775-9220-4EF5-B146-4FBC5B7499D8}.External|x64.ActiveCfg = Debug|Any CPU + {2267C775-9220-4EF5-B146-4FBC5B7499D8}.External|x64.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Ktisis/Camera/CameraService.cs b/Ktisis/Camera/CameraService.cs index 886203e8d..668b62b47 100644 --- a/Ktisis/Camera/CameraService.cs +++ b/Ktisis/Camera/CameraService.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using Dalamud.Logging; using Dalamud.Game.ClientState.Objects.Types; using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; @@ -29,7 +28,7 @@ internal static class CameraService { var camera = GetCameraByAddress((nint)active); if (camera == null && Override != null) { - PluginLog.Warning("Lost track of active camera! Attempting to reset."); + Ktisis.Log.Warning("Lost track of active camera! Attempting to reset."); Reset(); camera = GetCameraByAddress((nint)Services.Camera->Camera); } @@ -83,7 +82,7 @@ internal unsafe static void RemoveCamera(KtisisCamera cam) { return pos; } - internal static GameObject? GetTargetLock(nint addr) { + internal static IGameObject? GetTargetLock(nint addr) { if (!Ktisis.IsInGPose || GetCameraByAddress(addr) is not KtisisCamera camera) return null; @@ -133,6 +132,7 @@ private static void CheckFreecam(KtisisCamera? other = null) { // CameraManager wrappers internal unsafe static void Reset() { + Ktisis.Log.Debug("Resetting camera"); CheckFreecam(); Override = null; SetCamera(Services.Camera->Camera); @@ -141,12 +141,14 @@ internal unsafe static void Reset() { private unsafe static void SetCamera(GameCamera* camera) { if (camera == null) return; var mgr = CameraManager.Instance(); - mgr->CameraArraySpan[0] = &camera->CameraBase.SceneCamera; + mgr->Cameras[0] = &camera->CameraBase.SceneCamera; } // Overrides internal unsafe static void SetOverride(KtisisCamera camera) { + Ktisis.Log.Debug($"Setting camera to {camera.Name}"); + CheckFreecam(camera); if (camera.IsNative || !camera.IsValid()) { @@ -164,6 +166,21 @@ internal static void Init() { CameraHooks.Init(); EventManager.OnGPoseChange += OnGPoseChange; } + + internal static void ChangeCameraIndex(int offset) { + var camera = GetActiveCamera(); + if (camera == null) + return; + + if (GetFreecam() == camera) + return; + + var newIndex = (Cameras.FindIndex(tofind => tofind == camera) + offset) % Cameras.Count; + if (newIndex < 0) // loop back to start. + newIndex = Cameras.Count - 1; + + SetOverride(Cameras[newIndex]); + } internal static void Dispose() { EventManager.OnGPoseChange -= OnGPoseChange; @@ -182,6 +199,9 @@ private unsafe static void OnGPoseChange(bool state) { var active = (GPoseCamera*)Services.Camera->GetActiveCamera(); if (active != null) { active->DistanceMax = 20; + active->DistanceMin = 1.5f; + active->YMax = -1.5f; + active->YMin = 1.5f; active->Distance = Math.Clamp(active->Distance, 0, 20); } } @@ -199,7 +219,7 @@ private unsafe static void PrepareCameraList() { } private unsafe static void DisposeCameras() { - PluginLog.Debug("Disposing cameras..."); + Ktisis.Log.Debug("Disposing cameras..."); if (Override != null) Reset(); foreach (var cam in Cameras) @@ -207,4 +227,4 @@ private unsafe static void DisposeCameras() { Cameras.Clear(); } } -} \ No newline at end of file +} diff --git a/Ktisis/Camera/KtisisCamera.cs b/Ktisis/Camera/KtisisCamera.cs index 252e88589..6d54b3b7b 100644 --- a/Ktisis/Camera/KtisisCamera.cs +++ b/Ktisis/Camera/KtisisCamera.cs @@ -72,7 +72,7 @@ public unsafe static KtisisCamera Spawn(GameCamera* clone = null) { public void SetPositionLock(Vector3? pos) => CameraEdit.Position = pos; public void SetOffset(Vector3? off) => CameraEdit.Offset = off; - internal GameObject? GetOrbitTarget() { + internal IGameObject? GetOrbitTarget() { if (!Ktisis.IsInGPose) return null; return CameraEdit.Orbit != null ? Services.ObjectTable.FirstOrDefault( actor => actor.ObjectIndex == CameraEdit.Orbit diff --git a/Ktisis/Camera/WorkCamera.cs b/Ktisis/Camera/WorkCamera.cs index d4bdb93cb..bc2d16627 100644 --- a/Ktisis/Camera/WorkCamera.cs +++ b/Ktisis/Camera/WorkCamera.cs @@ -5,6 +5,7 @@ using SceneCamera = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.Camera; using Ktisis.Helpers; +using Ktisis.Interface; using Ktisis.Structs.Input; namespace Ktisis.Camera { @@ -60,7 +61,7 @@ internal unsafe void UpdateControl(MouseState* mouseState, KeyboardState* keySta } MoveSpeed = DefaultSpeed; - if (keyState != null) { + if (keyState != null && !Input.IsChatInputActive()) { if (Ktisis.Configuration.FreecamFast.IsActive(keyState)) MoveSpeed *= Ktisis.Configuration.FreecamShiftMuli; else if (Ktisis.Configuration.FreecamSlow.IsActive(keyState)) diff --git a/Ktisis/Configuration.cs b/Ktisis/Configuration.cs index 5b59c7c35..9b71a81a5 100644 --- a/Ktisis/Configuration.cs +++ b/Ktisis/Configuration.cs @@ -2,12 +2,13 @@ using System.Linq; using System.Numerics; using System.Collections.Generic; - -using ImGuizmoNET; +using System.IO; using Dalamud; using Dalamud.Configuration; +using Dalamud.Game; using Dalamud.Game.ClientState.Keys; +using Dalamud.Bindings.ImGuizmo; using Ktisis.Interface; using Ktisis.Localization; @@ -65,6 +66,14 @@ public class Configuration : IPluginConfiguration { public float SkeletonLineOpacityWhileUsing { get; set; } = 0.15F; public float SkeletonDotRadius { get; set; } = 3.0F; + //AutoSave + public bool EnableAutoSave { get; set; } = false; + public int AutoSaveInterval { get; set; } = 60; + public int AutoSaveCount { get; set; } = 5; + public string AutoSavePath { get; set; } = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Ktisis", "PoseAutoBackup"); + public string AutoSaveFormat { get; set; } = "AutoSave - %Date% %Time%"; + public bool ClearAutoSavesOnExit { get; set; } = false; + // References // The reference Key creates a uniqueness constraint for imgui window IDs for each reference. public Dictionary References { get; set; } = new(); @@ -108,8 +117,8 @@ public bool IsBoneCategoryVisible(Category category) { // Gizmo - public MODE GizmoMode { get; set; } = MODE.LOCAL; - public OPERATION GizmoOp { get; set; } = OPERATION.ROTATE; + public ImGuizmoMode GizmoMode { get; set; } = ImGuizmoMode.Local; + public ImGuizmoOperation GizmoOp { get; set; } = ImGuizmoOperation.Rotate; public SiblingLink SiblingLink { get; set; } = SiblingLink.None; @@ -138,15 +147,15 @@ public bool IsBoneCategoryVisible(Category category) { public bool EnableParenting { get; set; } = true; public bool LinkedGaze { get; set; } = true; - + public bool ShowToolbar { get; set; } = false; public Dictionary SavedDirPaths { get; set; } = new(); - + // Camera public float FreecamMoveSpeed { get; set; } = 0.1f; - + public float FreecamShiftMuli { get; set; } = 2.5f; public float FreecamCtrlMuli { get; set; } = 0.25f; public float FreecamUpDownMuli { get; set; } = 1f; @@ -159,7 +168,7 @@ public bool IsBoneCategoryVisible(Category category) { public Keybind FreecamRight { get; set; } = new(VirtualKey.D); public Keybind FreecamUp { get; set; } = new(VirtualKey.SPACE); public Keybind FreecamDown { get; set; } = new(VirtualKey.Q); - + public Keybind FreecamFast { get; set; } = new(VirtualKey.SHIFT); public Keybind FreecamSlow { get; set; } = new(VirtualKey.CONTROL); diff --git a/Ktisis/Data/Excel/BattleNpc.cs b/Ktisis/Data/Excel/BattleNpc.cs new file mode 100644 index 000000000..04cdd8852 --- /dev/null +++ b/Ktisis/Data/Excel/BattleNpc.cs @@ -0,0 +1,67 @@ +using Lumina.Excel; +using Lumina.Excel.Sheets; + +using Ktisis.Data.Npc; +using Ktisis.Structs.Actor; +using Ktisis.Structs.Extensions; +using Lumina.Text.ReadOnly; + +namespace Ktisis.Data.Excel { + [Sheet("BNpcBase", columnHash: 0xD5D82616)] + public struct BattleNpc(ExcelPage page, uint offset, uint row) : IExcelRow, INpcBase { + // Excel + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + + public float Scale { get; set; } + public RowRef ModelChara { get; set; } + private RowRef CustomizeSheet { get; set; } + private RowRef NpcEquipment { get; set; } + + public static BattleNpc Create(ExcelPage page, uint offset, uint row) { + return new BattleNpc(page, offset, row) { + Scale = page.ReadColumn(4, offset), + ModelChara = page.ReadRowRef(5, offset), + CustomizeSheet = page.ReadRowRef(6, offset), + NpcEquipment = page.ReadRowRef(7, offset) + }; + } + + // INpcBase + + public string Name { get; set; } = string.Empty; + + public ushort GetModelId() + => (ushort)this.ModelChara.RowId; + + public Customize? GetCustomize() + => this.CustomizeSheet.RowId != 0 ? this.CustomizeSheet.Value.Customize : null; + + public Equipment? GetEquipment() + => this.NpcEquipment.Value.Equipment; + + public WeaponEquip? GetMainHand() + => this.NpcEquipment.Value.MainHand; + + public WeaponEquip? GetOffHand() + => this.NpcEquipment.Value.OffHand; + + // Customize Sheet + + [Sheet("BNpcCustomize", columnHash: 0x18f060d4)] + private struct BNpcCustomizeSheet(ExcelPage page, uint offset, uint row) : IExcelRow { + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + + public Customize Customize { get; set; } + + public static BNpcCustomizeSheet Create(ExcelPage page, uint offset, uint row) { + return new BNpcCustomizeSheet(page, offset, row) { + Customize = page.ReadCustomize(0, offset) + }; + } + } + } +} diff --git a/Ktisis/Data/Excel/CharaMakeCustomize.cs b/Ktisis/Data/Excel/CharaMakeCustomize.cs index 687e905d4..1beae9228 100644 --- a/Ktisis/Data/Excel/CharaMakeCustomize.cs +++ b/Ktisis/Data/Excel/CharaMakeCustomize.cs @@ -1,28 +1,33 @@ -using Lumina.Data; +using Ktisis.Structs.Extensions; + using Lumina.Excel; -using Lobby = Lumina.Excel.GeneratedSheets.Lobby; +using Lumina.Excel.Sheets; namespace Ktisis.Data.Excel { [Sheet("CharaMakeCustomize")] - public class CharaMakeCustomize : ExcelRow { + public struct CharaMakeCustomize(ExcelPage page, uint offset, uint row) : IExcelRow { + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + public string Name { get; set; } = ""; public byte FeatureId { get; set; } public uint Icon { get; set; } public ushort Data { get; set; } public bool IsPurchasable { get; set; } - public LazyRow Hint { get; set; } = null!; + public RowRef Hint { get; set; } public byte FaceType { get; set; } - public override void PopulateData(RowParser parser, Lumina.GameData gameData, Language language) { - base.PopulateData(parser, gameData, language); - - FeatureId = parser.ReadColumn(0); - Icon = parser.ReadColumn(1); - Data = parser.ReadColumn(2); - IsPurchasable = parser.ReadColumn(3); - Hint = new LazyRow(gameData, parser.ReadColumn(4), language); - FaceType = parser.ReadColumn(6); + static CharaMakeCustomize IExcelRow.Create(ExcelPage page, uint offset, uint row) { + return new CharaMakeCustomize(page, offset, row) { + FeatureId = page.ReadColumn(0, offset), + Icon = page.ReadColumn(1, offset), + Data = page.ReadColumn(2, offset), + IsPurchasable = page.ReadColumn(3, offset), + Hint = page.ReadRowRef(4, offset), + FaceType = page.ReadColumn(6, offset) + }; } } } diff --git a/Ktisis/Data/Excel/CharaMakeType.cs b/Ktisis/Data/Excel/CharaMakeType.cs index 7a366e029..3fdcae833 100644 --- a/Ktisis/Data/Excel/CharaMakeType.cs +++ b/Ktisis/Data/Excel/CharaMakeType.cs @@ -1,9 +1,11 @@ -using Lumina.Data; using Lumina.Excel; -using Lumina.Excel.GeneratedSheets; using Dalamud.Game.ClientState.Objects.Enums; +using Ktisis.Structs.Extensions; + +using Lumina.Excel.Sheets; + using RaceEnum = Ktisis.Structs.Actor.Race; using TribeEnum = Ktisis.Structs.Actor.Tribe; using Gender = Ktisis.Structs.Actor.Gender; @@ -29,78 +31,85 @@ public struct Menu { public uint[] Params; public byte[] Graphics; - public LazyRow[] Features; + public RowRef[] Features; public bool HasIcon => Type == MenuType.Select; public bool IsFeature => HasIcon && Graphics[0] == 0; } [Sheet("CharaMakeType")] - public class CharaMakeType : ExcelRow { + public struct CharaMakeType(ExcelPage page, uint offset, uint row) : IExcelRow { // Consts public const int MenuCt = 28; public const int VoiceCt = 12; public const int GraphicCt = 10; + public const int FacialFeaturesCt = 7 * 8; // Properties + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + + public uint RowId => row; - public LazyRow Race { get; set; } = null!; - public LazyRow Tribe { get; set; } = null!; + public RowRef Race { get; set; } + public RowRef Tribe { get; set; } public sbyte Gender { get; set; } - public Menu[] Menus { get; set; } = new Menu[MenuCt]; - public byte[] Voices { get; set; } = new byte[VoiceCt]; - public int[] FacialFeatures { get; set; } = new int[7 * 8]; + public Menu[] Menus { get; set; } + public byte[] Voices { get; set; } + public int[] FacialFeatures { get; set; } - public LazyRow FeatureMake { get; set; } = null!; + public RowRef FeatureMake { get; set; } - public RaceEnum RaceEnum => (RaceEnum)Race.Row; - public TribeEnum TribeEnum => (TribeEnum)Tribe.Row; + public RaceEnum RaceEnum => (RaceEnum)Race.RowId; + public TribeEnum TribeEnum => (TribeEnum)Tribe.RowId; public Gender GenderEnum => (Gender)Gender; + + public static CharaMakeType Create(ExcelPage page, uint offset, uint row) { + var features = new int[FacialFeaturesCt]; + for (var i = 0; i < FacialFeaturesCt; i++) + features[i] = page.ReadColumn(3459 + i, offset); - // Build sheet - - public override void PopulateData(RowParser parser, Lumina.GameData gameData, Language language) { - base.PopulateData(parser, gameData, language); - - Race = new LazyRow(gameData, parser.ReadColumn(0), language); - Tribe = new LazyRow(gameData, parser.ReadColumn(1), language); - Gender = parser.ReadColumn(2); - - FeatureMake = new LazyRow(gameData, RowId, language); - - for (var i = 0; i < 7 * 8; i++) - FacialFeatures[i] = parser.ReadColumn(3291 + i); - + var menus = new Menu[MenuCt]; for (var i = 0; i < MenuCt; i++) { - var ct = parser.ReadColumn(3 + 3 * MenuCt + i); + var ct = page.ReadColumn(3 + 3 * MenuCt + i, offset); + var lobby = page.ReadRowRef(3 + i, offset); var menu = new Menu() { - Name = new LazyRow(gameData, parser.ReadColumn(3 + i), language).Value!.Text, - Default = parser.ReadColumn(3 + 1 * MenuCt + i), - Type = (MenuType)parser.ReadColumn(3 + 2 * MenuCt + i), + Name = lobby.IsValid ? lobby.Value.Text.ExtractText() : string.Empty, + Default = page.ReadColumn(3 + 1 * MenuCt + i, offset), + Type = (MenuType)page.ReadColumn(3 + 2 * MenuCt + i, offset), Count = ct, - Index = (CustomizeIndex)parser.ReadColumn(3 + 6 * MenuCt + i), + Index = (CustomizeIndex)page.ReadColumn(3 + 6 * MenuCt + i, offset), Params = new uint[ct], Graphics = new byte[GraphicCt] }; if (menu.HasIcon || menu.Type == MenuType.List) { for (var p = 0; p < ct; p++) - menu.Params[p] = parser.ReadColumn(3 + (7 + p) * MenuCt + i); + menu.Params[p] = page.ReadColumn(3 + (7 + p) * MenuCt + i, offset); for (var g = 0; g < GraphicCt; g++) - menu.Graphics[g] = parser.ReadColumn(3 + (107 + g) * MenuCt + i); + menu.Graphics[g] = page.ReadColumn(3 + (113 + g) * MenuCt + i, offset); } - + if (menu.IsFeature) { - var feats = new LazyRow[ct]; + var feats = new RowRef[ct]; for (var x = 0; x < ct; x++) - feats[x] = new LazyRow(gameData, menu.Params[x]); + feats[x] = new RowRef(page.Module, menu.Params[x], page.Language); menu.Features = feats; } - Menus[i] = menu; + menus[i] = menu; } + + return new CharaMakeType(page, offset, row) { + Race = page.ReadRowRef(0, offset), + Tribe = page.ReadRowRef(1, offset), + Gender = page.ReadColumn(2, offset), + FeatureMake = new RowRef(page.Module, row, page.Language), + FacialFeatures = features, + Menus = menus + }; } } } diff --git a/Ktisis/Data/Excel/Dye.cs b/Ktisis/Data/Excel/Dye.cs index fa8f26746..d7d357f8a 100644 --- a/Ktisis/Data/Excel/Dye.cs +++ b/Ktisis/Data/Excel/Dye.cs @@ -1,22 +1,28 @@ using System.Numerics; -using ImGuiNET; +using Dalamud.Utility; +using Dalamud.Bindings.ImGui; + +using Ktisis.Structs.Extensions; -using Lumina.Data; using Lumina.Excel; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.Sheets; namespace Ktisis.Data.Excel { [Sheet("Stain")] - public class Dye : ExcelRow { - public string Name { get; set; } = ""; + public struct Dye(ExcelPage page, uint offset, uint row) : IExcelRow { + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + + public string Name { get; set; } public uint Color { get; set; } public byte Shade { get; set; } public byte SubOrder { get; set; } public bool IsMetallic { get; set; } public bool UnknownBool { get; set; } - public LazyRow Stain { get; set; } = null!; + public RowRef Stain { get; set; } public bool IsValid() => Shade != 0; public Vector4 ColorVector4 @@ -26,18 +32,16 @@ public Vector4 ColorVector4 return new Vector4(c.Z, c.Y, c.X, c.W); } } - - public override void PopulateData(RowParser parser, Lumina.GameData gameData, Language language) { - base.PopulateData(parser, gameData, language); - - Name = parser.ReadColumn(3)!; - Color = parser.ReadColumn(0); - Shade = parser.ReadColumn(1); - SubOrder = parser.ReadColumn(2); - IsMetallic = parser.ReadColumn(4); - - if (Name == "") - Name = "Undyed"; // TODO: translation + + public static Dye Create(ExcelPage page, uint offset, uint row) { + var name = page.ReadColumn(3, offset); + return new Dye(page, offset, row) { + Name = !name.IsNullOrEmpty() ? name : "Undyed", // TODO: translation + Color = page.ReadColumn(0, offset), + Shade = page.ReadColumn(1, offset), + SubOrder = page.ReadColumn(2, offset), + IsMetallic = page.ReadColumn(5, offset) + }; } } } diff --git a/Ktisis/Data/Excel/EventNpc.cs b/Ktisis/Data/Excel/EventNpc.cs new file mode 100644 index 000000000..284700a41 --- /dev/null +++ b/Ktisis/Data/Excel/EventNpc.cs @@ -0,0 +1,78 @@ +using Lumina.Excel; +using Lumina.Excel.Sheets; + +using Ktisis.Data.Npc; +using Ktisis.Structs.Actor; +using Ktisis.Structs.Extensions; + +namespace Ktisis.Data.Excel { + [Sheet("ENpcBase", columnHash: 0x5BA9E1A6)] + public struct EventNpc : IExcelRow, INpcBase { + // Excel + + public ExcelPage ExcelPage { get; } + public uint RowOffset { get; } + public uint RowId { get; } + + public ushort EventHandler { get; set; } + + public RowRef ModelChara { get; set; } + public Customize Customize { get; set; } + + public WeaponEquip MainHand { get; set; } + public WeaponEquip OffHand { get; set; } + public Equipment Equipment { get; set; } + + public EventNpc(ExcelPage page, uint offset, uint row) { + this.ExcelPage = page; + this.RowOffset = offset; + this.RowId = row; + + this.Name = $"E:{this.RowId:D7}"; + + this.EventHandler = page.ReadColumn(0, offset); + + this.ModelChara = page.ReadRowRef(35, offset); + this.Customize = page.ReadCustomize(36, offset); + + var equipRow = page.ReadColumn(63, offset); + + this.MainHand = page.ReadWeapon(65, offset); + this.OffHand = page.ReadWeapon(68, offset); + this.Equipment = page.ReadEquipment(71, offset); + + // what the fuck? + + if (equipRow is 0 or 175) return; + + var equip = new RowRef(page.Module, equipRow, page.Language); + this.Equipment = EquipOverride(this.Equipment, equip.Value.Equipment); + } + + public static EventNpc Create(ExcelPage page, uint offset, uint row) => new(page, offset, row); + + private unsafe Equipment EquipOverride(Equipment equip, Equipment alt) { + for (var i = 0; i < Equipment.SlotCount; i++) { + var altVal = alt.Slots[i]; + if (altVal != 0) + equip.Slots[i] = altVal; + } + + return equip; + } + + // INpcBase + + public string Name { get; set; } = null!; + + public ushort GetModelId() => (ushort)this.ModelChara.RowId; + + public Customize? GetCustomize() => this.Customize; + + public Equipment? GetEquipment() => this.Equipment; + + public WeaponEquip? GetMainHand() => this.MainHand; + + public WeaponEquip? GetOffHand() => this.OffHand; + } +} diff --git a/Ktisis/Data/Excel/Glasses.cs b/Ktisis/Data/Excel/Glasses.cs new file mode 100644 index 000000000..61a24d07b --- /dev/null +++ b/Ktisis/Data/Excel/Glasses.cs @@ -0,0 +1,23 @@ +using Dalamud.Utility; + +using Ktisis.Structs.Extensions; + +using Lumina.Excel; +using Lumina.Text.ReadOnly; + +namespace Ktisis.Data.Excel { + [Sheet("Glasses")] + public struct Glasses(ExcelPage page, uint offset, uint row) : IExcelRow { + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + + public string Name { get; set; } = string.Empty; + + static Glasses IExcelRow.Create(ExcelPage page, uint offset, uint row) { + return new Glasses(page, offset, row) { + Name = row != 0 ? page.ReadColumn(13, offset) : "None" + }; + } + } +} \ No newline at end of file diff --git a/Ktisis/Data/Excel/HairMakeType.cs b/Ktisis/Data/Excel/HairMakeType.cs index 04b779bdd..b2e4b3fab 100644 --- a/Ktisis/Data/Excel/HairMakeType.cs +++ b/Ktisis/Data/Excel/HairMakeType.cs @@ -1,11 +1,17 @@ using System.Collections.Generic; +using System.Linq; + +using Ktisis.Structs.Extensions; -using Lumina.Data; using Lumina.Excel; namespace Ktisis.Data.Excel { [Sheet("HairMakeType")] - public class HairMakeType : ExcelRow { + public struct HairMakeType(ExcelPage page, uint offset, uint row) : IExcelRow { + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + // Properties public const uint HairLength = 100; @@ -14,22 +20,25 @@ public class HairMakeType : ExcelRow { public uint HairStartIndex { get; set; } // 66 public uint FacepaintStartIndex { get; set; } // 82 - public List> HairStyles { get; set; } = new(); - public List> Facepaints { get; set; } = new(); + public List> HairStyles { get; set; } + public List> Facepaints { get; set; } // Build sheet - public override void PopulateData(RowParser parser, Lumina.GameData gameData, Language language) { - base.PopulateData(parser, gameData, language); - - HairStartIndex = parser.ReadColumn(66); - FacepaintStartIndex = parser.ReadColumn(82); - - for (var i = HairStartIndex; i < HairStartIndex + HairLength; i++) - HairStyles.Add(new LazyRow(gameData, i, language)); + static HairMakeType IExcelRow.Create(ExcelPage page, uint offset, uint row) { + var hairStartIndex = page.ReadColumn(66, offset); + var facePaintStartIndex = page.ReadColumn(82, offset); + return new HairMakeType(page, offset, row) { + HairStartIndex = hairStartIndex, + FacepaintStartIndex = facePaintStartIndex, + HairStyles = GetRange(page, hairStartIndex, HairLength).ToList(), + Facepaints = GetRange(page, facePaintStartIndex, FacepaintLength).ToList() + }; + } - for (var i = FacepaintStartIndex; i < FacepaintStartIndex + FacepaintLength; i++) - Facepaints.Add(new LazyRow(gameData, i, language)); + private static IEnumerable> GetRange(ExcelPage page, uint start, uint length) { + for (var i = start; i < start + length; i++) + yield return new RowRef(page.Module, i, page.Language); } } } diff --git a/Ktisis/Data/Excel/INpcBase.cs b/Ktisis/Data/Excel/INpcBase.cs new file mode 100644 index 000000000..81123dd1b --- /dev/null +++ b/Ktisis/Data/Excel/INpcBase.cs @@ -0,0 +1,17 @@ +using Ktisis.Structs.Actor; + +namespace Ktisis.Data.Npc { + public interface INpcBase { + public string Name { get; set; } + + public ushort GetModelId() => 0; + + public Customize? GetCustomize() => null; + + public Equipment? GetEquipment() => null; + + public WeaponEquip? GetMainHand(); + + public WeaponEquip? GetOffHand(); + } +} diff --git a/Ktisis/Data/Excel/Item.cs b/Ktisis/Data/Excel/Item.cs index 17aa815c7..521f6454a 100644 --- a/Ktisis/Data/Excel/Item.cs +++ b/Ktisis/Data/Excel/Item.cs @@ -1,8 +1,10 @@ -using Lumina.Data; -using Lumina.Text; +using System.Collections.Generic; +using System.Linq; + using Lumina.Excel; using Ktisis.Structs.Actor; +using Ktisis.Structs.Extensions; namespace Ktisis.Data.Excel { public enum EquipSlot { @@ -35,35 +37,41 @@ public ItemModel(ulong var, bool isWep = false) { } [Sheet("Item")] - public class Item : ExcelRow { + public struct Item : IExcelRow { + public ExcelPage ExcelPage { get; } + public uint RowOffset { get; } + public uint RowId { get; } + public string Name { get; set; } = ""; - public ushort Icon { get; set; } + public int Icon { get; set; } - public LazyRow EquipSlotCategory { get; set; } = null!; + public RowRef EquipSlotCategory { get; set; } public ItemModel Model { get; set; } = null!; public ItemModel SubModel { get; set; } = null!; - public bool IsEquippable() => EquipSlotCategory.Value!.RowId != 0; - public bool IsEquippable(EquipSlot slot) => IsEquippable() && EquipSlotCategory.Value!.IsEquippable(slot); + public bool IsEquippable() => EquipSlotCategory.IsValid && EquipSlotCategory.RowId != 0; + public bool IsEquippable(EquipSlot slot) => IsEquippable() && EquipSlotCategory.Value.IsEquippable(slot); public bool IsWeapon() => IsEquippable(EquipSlot.MainHand) || IsEquippable(EquipSlot.OffHand); - public override void PopulateData(RowParser parser, Lumina.GameData gameData, Language language) { - base.PopulateData(parser, gameData, language); - - Name = parser.ReadColumn(9) ?? ""; - Icon = parser.ReadColumn(10); + public Item(uint row, ExcelPage page, uint offset) { + this.ExcelPage = page; + this.RowOffset = offset; + this.RowId = row; + + this.Name = page.ReadColumn(9, offset); + this.Icon = page.ReadColumn(10, offset); - EquipSlotCategory = new LazyRow(gameData, parser.ReadColumn(17), language); + this.EquipSlotCategory = page.ReadRowRef(17, offset); - var isWep = IsWeapon(); - var model = parser.ReadColumn(47); - var subModel = parser.ReadColumn(48); - Model = new ItemModel(model, isWep); - SubModel = new ItemModel(subModel, isWep); + var isWep = this.IsWeapon(); + this.Model = new ItemModel(page.ReadColumn(47, offset), isWep); + this.SubModel = new ItemModel(page.ReadColumn(48, offset), isWep); } + public static Item Create(ExcelPage page, uint offset, uint row) => new(row, page, offset); + public bool IsEquipItem(object equip) { if (equip is WeaponEquip wep) { if (Model.Id == 0 && SubModel.Id == 0) return false; @@ -78,16 +86,24 @@ public bool IsEquipItem(object equip) { } [Sheet("EquipSlotCategory")] - public class EquipSlotCategory : ExcelRow { + public struct EquipSlotCategory(ExcelPage page, uint offset, uint row) : IExcelRow { + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + public sbyte[] Slots { get; set; } = new sbyte[14]; public bool IsEquippable(EquipSlot slot) => Slots[(int)slot] == 1 || (slot == EquipSlot.MainHand && Slots[1] == 1) || (slot == EquipSlot.OffHand && Slots[0] == 1); - public override void PopulateData(RowParser parser, Lumina.GameData gameData, Language language) { - base.PopulateData(parser, gameData, language); + public static EquipSlotCategory Create(ExcelPage page, uint offset, uint row) { + return new EquipSlotCategory(page, offset, row) { + Slots = ReadSlots(page, offset).ToArray() + }; + } + private static IEnumerable ReadSlots(ExcelPage page, uint offset) { for (var i = 0; i < 14; i++) - Slots[i] = parser.ReadColumn(i); + yield return page.ReadColumn(i, offset); } } } diff --git a/Ktisis/Data/Excel/NpcEquipment.cs b/Ktisis/Data/Excel/NpcEquipment.cs new file mode 100644 index 000000000..0ab7a32a6 --- /dev/null +++ b/Ktisis/Data/Excel/NpcEquipment.cs @@ -0,0 +1,26 @@ +using Lumina.Excel; + +using Ktisis.Structs.Actor; +using Ktisis.Structs.Extensions; + +namespace Ktisis.Data.Excel { + [Sheet("NpcEquip", columnHash: 0x7EAEB95C)] + public struct NpcEquipment(ExcelPage page, uint offset, uint row) : IExcelRow { + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + public uint RowId => row; + + public WeaponEquip MainHand { get; private set; } + public WeaponEquip OffHand { get; private set; } + + public Equipment Equipment { get; private set; } + + public static NpcEquipment Create(ExcelPage page, uint offset, uint row) { + return new NpcEquipment(page, offset, row) { + MainHand = page.ReadWeapon(0, offset), + OffHand = page.ReadWeapon(3, offset), + Equipment = page.ReadEquipment(6, offset) + }; + } + } +} diff --git a/Ktisis/Data/Excel/ResidentNpc.cs b/Ktisis/Data/Excel/ResidentNpc.cs new file mode 100644 index 000000000..e10c79468 --- /dev/null +++ b/Ktisis/Data/Excel/ResidentNpc.cs @@ -0,0 +1,46 @@ +using Lumina.Excel; + +using Ktisis.Data.Npc; +using Ktisis.Structs.Actor; +using Ktisis.Structs.Extensions; + +namespace Ktisis.Data.Excel { + [Sheet("ENpcResident", columnHash: 0xf74fa88c)] + public struct ResidentNpc(ExcelPage page, uint offset, uint row) : IExcelRow, INpcBase { + // Excel + public ExcelPage ExcelPage => page; + public uint RowOffset => offset; + + public uint RowId => row; + + public byte Map { get; set; } + + public RowRef EventNpc { get; set; } + + public static ResidentNpc Create(ExcelPage page, uint offset, uint row) { + var singular = page.ReadColumn(0, offset); + var article = page.ReadColumn(7, offset); + return new ResidentNpc(page, offset, row) { + Name = singular.FormatName(article) ?? $"E:{row:D7}", + EventNpc = new RowRef(page.Module, row, page.Language), + Map = page.ReadColumn(9, offset) + }; + } + + // INpcBase + + public string Name { get; set; } = null!; + + public uint HashId { get; set; } + + public ushort GetModelId() => this.EventNpc.Value.GetModelId(); + + public Customize? GetCustomize() => this.EventNpc.Value.GetCustomize(); + + public Equipment? GetEquipment() => this.EventNpc.Value.GetEquipment(); + + public WeaponEquip? GetMainHand() => this.EventNpc.Value.GetMainHand(); + + public WeaponEquip? GetOffHand() => this.EventNpc.Value.GetOffHand(); + } +} diff --git a/Ktisis/Data/Files/AnamCharaFile.cs b/Ktisis/Data/Files/AnamCharaFile.cs index bfc9e04c4..96759369e 100644 --- a/Ktisis/Data/Files/AnamCharaFile.cs +++ b/Ktisis/Data/Files/AnamCharaFile.cs @@ -3,6 +3,7 @@ using Dalamud.Game.ClientState.Objects.Enums; +using Ktisis.Data.Excel; using Ktisis.Structs.Actor; using Ktisis.Data.Serialization.Converters; @@ -85,6 +86,8 @@ public enum SaveModes { public ItemSave? Wrists { get; set; } public ItemSave? LeftRing { get; set; } public ItemSave? RightRing { get; set; } + + public ushort? Glasses { get; set; } // extended appearance // NOTE: extended weapon values are stored in the WeaponSave @@ -108,64 +111,67 @@ public void WriteToFile(Actor actor, SaveModes mode) { ObjectKind = (ObjectKind)actor.GameObject.ObjectKind; SaveMode = mode; + + var custom = actor.GetCustomize(); if (IncludeSection(SaveModes.EquipmentWeapons, mode)) { - MainHand = new WeaponSave(actor.DrawData.MainHand.Equip); + MainHand = new WeaponSave(actor.GetWeaponEquip(EquipSlot.MainHand)); ////MainHand.Color = actor.GetValue(Offsets.Main.MainHandColor); ////MainHand.Scale = actor.GetValue(Offsets.Main.MainHandScale); - OffHand = new WeaponSave(actor.DrawData.OffHand.Equip); + OffHand = new WeaponSave(actor.GetWeaponEquip(EquipSlot.OffHand)); ////OffHand.Color = actor.GetValue(Offsets.Main.OffhandColor); ////OffHand.Scale = actor.GetValue(Offsets.Main.OffhandScale); } if (IncludeSection(SaveModes.EquipmentGear, mode)) { - HeadGear = new ItemSave(actor.DrawData.Equipment.Head); - Body = new ItemSave(actor.DrawData.Equipment.Chest); - Hands = new ItemSave(actor.DrawData.Equipment.Hands); - Legs = new ItemSave(actor.DrawData.Equipment.Legs); - Feet = new ItemSave(actor.DrawData.Equipment.Feet); + HeadGear = GetItemSave(actor, EquipIndex.Head); + Body = GetItemSave(actor, EquipIndex.Chest); + Hands = GetItemSave(actor, EquipIndex.Hands); + Legs = GetItemSave(actor, EquipIndex.Legs); + Feet = GetItemSave(actor, EquipIndex.Feet); + Glasses = actor.DrawData.Glasses; } if (IncludeSection(SaveModes.EquipmentAccessories, mode)) { - Ears = new ItemSave(actor.DrawData.Equipment.Earring); - Neck = new ItemSave(actor.DrawData.Equipment.Necklace); - Wrists = new ItemSave(actor.DrawData.Equipment.Bracelet); - LeftRing = new ItemSave(actor.DrawData.Equipment.RingLeft); - RightRing = new ItemSave(actor.DrawData.Equipment.RingRight); + Ears = GetItemSave(actor, EquipIndex.Earring); + Neck = GetItemSave(actor, EquipIndex.Necklace); + Wrists = GetItemSave(actor, EquipIndex.Bracelet); + LeftRing = GetItemSave(actor, EquipIndex.RingLeft); + RightRing = GetItemSave(actor, EquipIndex.RingRight); } if (IncludeSection(SaveModes.AppearanceHair, mode)) { - Hair = actor.DrawData.Customize.HairStyle; - EnableHighlights = (actor.DrawData.Customize.HasHighlights & 0x80) != 0; - HairTone = actor.DrawData.Customize.HairColor; - Highlights = actor.DrawData.Customize.HairColor2; + Hair = custom.HairStyle; + EnableHighlights = (custom.HasHighlights & 0x80) != 0; + HairTone = custom.HairColor; + Highlights = custom.HairColor2; /*HairColor = actor.ModelObject?.ExtendedAppearance?.HairColor; HairGloss = actor.ModelObject?.ExtendedAppearance?.HairGloss; HairHighlight = actor.ModelObject?.ExtendedAppearance?.HairHighlight;*/ } if (IncludeSection(SaveModes.AppearanceFace, mode) || IncludeSection(SaveModes.AppearanceBody, mode)) { - Race = (AnamRace)actor.DrawData.Customize.Race; - Gender = actor.DrawData.Customize.Gender; - Tribe = (AnamTribe)actor.DrawData.Customize.Tribe; - Age = actor.DrawData.Customize.Age; + Race = (AnamRace)custom.Race; + Gender = custom.Gender; + Tribe = (AnamTribe)custom.Tribe; + Age = custom.Age; } if (IncludeSection(SaveModes.AppearanceFace, mode)) { - Head = actor.DrawData.Customize.FaceType; - REyeColor = actor.DrawData.Customize.EyeColor; - LimbalEyes = actor.DrawData.Customize.FaceFeaturesColor; - FacialFeatures = (AnamFacialFeature)actor.DrawData.Customize.FaceFeatures; - Eyebrows = actor.DrawData.Customize.Eyebrows; - LEyeColor = actor.DrawData.Customize.EyeColor2; - Eyes = actor.DrawData.Customize.EyeShape; - Nose = actor.DrawData.Customize.NoseShape; - Jaw = actor.DrawData.Customize.JawShape; - Mouth = actor.DrawData.Customize.LipStyle; - LipsToneFurPattern = actor.DrawData.Customize.LipColor; - FacePaint = (byte)actor.DrawData.Customize.Facepaint; - FacePaintColor = actor.DrawData.Customize.FacepaintColor; + Head = custom.FaceType; + REyeColor = custom.EyeColor; + LimbalEyes = custom.FaceFeaturesColor; + FacialFeatures = (AnamFacialFeature)custom.FaceFeatures; + Eyebrows = custom.Eyebrows; + LEyeColor = custom.EyeColor2; + Eyes = custom.EyeShape; + Nose = custom.NoseShape; + Jaw = custom.JawShape; + Mouth = custom.LipStyle; + LipsToneFurPattern = custom.LipColor; + FacePaint = (byte)custom.Facepaint; + FacePaintColor = custom.FacepaintColor; /*LeftEyeColor = actor.ModelObject?.ExtendedAppearance?.LeftEyeColor; RightEyeColor = actor.ModelObject?.ExtendedAppearance?.RightEyeColor; LimbalRingColor = actor.ModelObject?.ExtendedAppearance?.LimbalRingColor; @@ -173,22 +179,25 @@ public void WriteToFile(Actor actor, SaveModes mode) { } if (IncludeSection(SaveModes.AppearanceBody, mode)) { - Height = actor.DrawData.Customize.Height; - Skintone = actor.DrawData.Customize.SkinColor; - EarMuscleTailSize = actor.DrawData.Customize.RaceFeatureSize; - TailEarsType = actor.DrawData.Customize.RaceFeatureType; - Bust = actor.DrawData.Customize.BustSize; + Height = custom.Height; + Skintone = custom.SkinColor; + EarMuscleTailSize = custom.RaceFeatureSize; + TailEarsType = custom.RaceFeatureType; + Bust = custom.BustSize; - unsafe { HeightMultiplier = actor.Model->Height; } + unsafe { HeightMultiplier = actor.Model != null ? actor.Model->Height : 1; } /*SkinColor = actor.ModelObject?.ExtendedAppearance?.SkinColor; SkinGloss = actor.ModelObject?.ExtendedAppearance?.SkinGloss; MuscleTone = actor.ModelObject?.ExtendedAppearance?.MuscleTone; - BustScale = actor.ModelObject?.Bust?.Scale; - Transparency = actor.Transparency;*/ + BustScale = actor.ModelObject?.Bust?.Scale;*/ + Transparency = actor.Transparency; } } + private ItemSave GetItemSave(Actor actor, EquipIndex slot) + => new ItemSave(actor.GetEquip(slot)); + public unsafe void Apply(Actor* actor, SaveModes mode) { if (Tribe != null && !Enum.IsDefined((Tribe)Tribe)) throw new Exception($"Invalid tribe: {Tribe} in appearance file"); @@ -209,6 +218,7 @@ public unsafe void Apply(Actor* actor, SaveModes mode) { Hands?.Write(actor, EquipIndex.Hands); Legs?.Write(actor, EquipIndex.Legs); Feet?.Write(actor, EquipIndex.Feet); + if (Glasses != null) actor->SetGlasses(Glasses.Value); } if (IncludeSection(SaveModes.EquipmentAccessories, mode)) { @@ -219,7 +229,7 @@ public unsafe void Apply(Actor* actor, SaveModes mode) { LeftRing?.Write(actor, EquipIndex.RingLeft); } - var custom = actor->DrawData.Customize; + var custom = actor->GetCustomize(); if (IncludeSection(SaveModes.AppearanceHair, mode)) { if (Hair != null) @@ -305,6 +315,8 @@ public unsafe void Apply(Actor* actor, SaveModes mode) { if (Bust != null) custom.BustSize = (byte)Bust; + + actor->Transparency = Transparency ?? 1.0f; } actor->ApplyCustomize(custom); @@ -353,6 +365,7 @@ public WeaponSave(WeaponEquip from) { ModelBase = from.Base; ModelVariant = from.Variant; DyeId = from.Dye; + DyeId2 = from.Dye2; } public Vector3 Color { get; set; } @@ -361,6 +374,7 @@ public WeaponSave(WeaponEquip from) { public ushort ModelBase { get; set; } public ushort ModelVariant { get; set; } public byte DyeId { get; set; } + public byte DyeId2 { get; set; } public unsafe void Write(Actor* actor, bool isMainHand) { var wep = new WeaponEquip() { @@ -371,6 +385,7 @@ public unsafe void Write(Actor* actor, bool isMainHand) { wep.Base = ModelBase; wep.Variant = ModelVariant; wep.Dye = DyeId; + wep.Dye2 = DyeId2; } actor->Equip(isMainHand ? 0 : 1, wep); @@ -386,17 +401,20 @@ public ItemSave(ItemEquip from) { ModelBase = from.Id; ModelVariant = from.Variant; DyeId = from.Dye; + DyeId2 = from.Dye2; } public ushort ModelBase { get; set; } public byte ModelVariant { get; set; } public byte DyeId { get; set; } + public byte DyeId2 { get; set; } public unsafe void Write(Actor* actor, EquipIndex index) { var item = new ItemEquip() { Id = ModelBase, Variant = ModelVariant, - Dye = DyeId + Dye = DyeId, + Dye2 = DyeId2 }; actor->Equip(index, item); } diff --git a/Ktisis/Data/Files/FfxivCharaDat.cs b/Ktisis/Data/Files/FfxivCharaDat.cs index 77c6aef8b..9fef7e1d4 100644 --- a/Ktisis/Data/Files/FfxivCharaDat.cs +++ b/Ktisis/Data/Files/FfxivCharaDat.cs @@ -43,10 +43,5 @@ public unsafe string Note() { fixed (byte* ptr = NoteChars) return Marshal.PtrToStringAnsi((IntPtr)ptr) ?? ""; } - - public unsafe static FfxivCharaDat GetFromSlot(int slot) { - var addr = Interop.StaticOffsets.CharaDatData + 8 + 0x140*slot; - return *(FfxivCharaDat*)addr; - } } } diff --git a/Ktisis/Data/Library/bnpc-index.json b/Ktisis/Data/Library/bnpc-index.json new file mode 100644 index 000000000..946437778 --- /dev/null +++ b/Ktisis/Data/Library/bnpc-index.json @@ -0,0 +1,18632 @@ +{ + "0": 1073802067, + "1": 6373, + "2": 2012, + "3": 176, + "4": 460, + "5": 184, + "6": 2020, + "7": 1121, + "8": 481, + "9": 571, + "10": 572, + "11": 2033, + "12": 2757, + "13": 397, + "14": 202, + "15": 502, + "16": 15, + "17": 963, + "18": 2018, + "19": 2019, + "20": 110, + "21": 2169, + "22": 1085, + "23": 3341, + "24": 3343, + "25": 25, + "26": 1040, + "27": 1757, + "28": 1071, + "29": 29, + "30": 4286, + "31": 270879791, + "32": 203, + "33": 33, + "34": 506, + "35": 270855189, + "36": 1051, + "37": 1101, + "38": 1146, + "39": 962, + "40": 1145, + "41": 486, + "42": 1084, + "43": 181, + "44": 2225, + "45": 491, + "46": 1703, + "47": 199, + "48": 166, + "49": 1046, + "50": 270990461, + "51": 269815996, + "52": 464, + "53": 462, + "54": 269815996, + "55": 3110, + "56": 270839315, + "57": 201, + "58": 2032, + "59": 7134, + "60": 1073761583, + "61": 2173, + "62": 2173, + "63": 3178, + "64": 2173, + "65": 62, + "66": 1021, + "67": 108, + "68": 1073743916, + "69": 269768264, + "70": 1139, + "71": 68, + "72": 69, + "73": 1138, + "74": 270335052, + "75": 269889549, + "76": 73, + "77": 74, + "78": 3669, + "79": 2362, + "80": 2363, + "81": 675, + "82": 79, + "83": 79, + "84": 540, + "85": 81, + "86": 540, + "87": 83, + "88": 84, + "89": 270471669, + "90": 1073750170, + "91": 269017088, + "92": 270509357, + "93": 336, + "94": 1073742269, + "95": 270234663, + "96": 269017088, + "97": 269889549, + "98": 91, + "99": 91, + "100": 91, + "101": 91, + "102": 428, + "103": 513, + "104": 1067, + "105": 104, + "106": 613, + "107": 548, + "108": 349, + "109": 310, + "110": 314, + "111": 312, + "112": 101, + "113": 190, + "114": 1783, + "115": 1782, + "116": 1784, + "117": 1066, + "118": 1093, + "119": 445, + "120": 247, + "121": 447, + "122": 363, + "123": 260, + "124": 1873, + "125": 456, + "126": 110, + "127": 111, + "128": 431, + "129": 434, + "130": 3342, + "131": 113, + "132": 114, + "133": 115, + "134": 912, + "135": 117, + "136": 1042, + "137": 119, + "138": 2756, + "139": 1134, + "140": 237, + "141": 1846, + "142": 605, + "143": 1763, + "144": 121, + "145": 83, + "146": 122, + "147": 84, + "148": 84, + "149": 123, + "150": 1327, + "151": 125, + "152": 185, + "153": 186, + "154": 186, + "155": 189, + "156": 612, + "157": 2329, + "158": 139, + "159": 381, + "160": 196, + "161": 1758, + "162": 616, + "163": 191, + "164": 156, + "165": 140, + "166": 259, + "167": 253, + "168": 252, + "169": 1725, + "170": 1115, + "171": 1114, + "172": 1037, + "173": 1736, + "174": 303, + "175": 1045, + "176": 286, + "177": 1019, + "178": 1869, + "179": 1316, + "180": 1036, + "181": 1116, + "182": 467, + "183": 1759, + "184": 2197, + "185": 1362, + "186": 3059, + "187": 1041, + "188": 2008, + "189": 1671, + "190": 4285, + "191": 3699, + "192": 1344, + "193": 2049, + "194": 2050, + "195": 482, + "196": 6733, + "197": 1022, + "198": 298, + "199": 440, + "200": 269, + "201": 3179, + "202": 362, + "203": 1023, + "204": 271, + "205": 1049, + "206": 1317, + "207": 1185, + "208": 1186, + "209": 1185, + "210": 1186, + "211": 1185, + "212": 1186, + "213": 346, + "214": 213, + "215": 294, + "216": 515, + "217": 300, + "218": 319, + "219": 315, + "220": 1194, + "221": 718, + "222": 719, + "223": 720, + "224": 721, + "225": 722, + "226": 723, + "227": 724, + "228": 725, + "229": 718, + "230": 719, + "231": 720, + "232": 721, + "233": 722, + "234": 723, + "235": 724, + "236": 2752, + "237": 1649, + "238": 1647, + "239": 1644, + "240": 1649, + "241": 1647, + "242": 1644, + "243": 1649, + "244": 1647, + "245": 1644, + "246": 1801, + "247": 1801, + "248": 1801, + "249": 1375, + "250": 1376, + "251": 1428, + "252": 321, + "253": 3126, + "254": 496, + "255": 422, + "256": 424, + "257": 425, + "258": 428, + "259": 444, + "260": 443, + "261": 437, + "262": 375, + "263": 306, + "264": 514, + "265": 590, + "266": 440, + "267": 988, + "268": 736, + "269": 1208, + "270": 442, + "271": 441, + "272": 423, + "273": 426, + "274": 427, + "275": 428, + "276": 633, + "277": 518, + "278": 1760, + "279": 768, + "280": 769, + "281": 414, + "282": 1987, + "283": 1257, + "284": 1442, + "285": 344, + "286": 279, + "287": 279, + "288": 279, + "289": 279, + "290": 1266, + "291": 2265, + "292": 1268, + "293": 4146, + "294": 134, + "295": 553, + "296": 1274, + "297": 136, + "298": 142, + "299": 135, + "300": 374, + "301": 596, + "302": 1135, + "303": 1735, + "304": 505, + "305": 1785, + "306": 1027, + "307": 332, + "308": 104, + "309": 1743, + "310": 3746, + "311": 77, + "312": 1069, + "313": 1100, + "314": 1068, + "315": 1075, + "316": 344, + "317": 2732, + "318": 978, + "319": 866, + "320": 1748, + "321": 4114, + "322": 1076, + "323": 1077, + "324": 1103, + "325": 1081, + "326": 825, + "327": 1073, + "328": 1158, + "329": 1157, + "330": 1156, + "331": 1155, + "332": 502, + "333": 2165, + "334": 1163, + "335": 1162, + "336": 2166, + "337": 386, + "338": 1098, + "339": 1096, + "340": 1087, + "341": 1097, + "342": 1035, + "343": 414, + "344": 413, + "345": 676, + "346": 415, + "347": 1236, + "348": 674, + "349": 1719, + "350": 1173, + "351": 1050, + "352": 326, + "353": 329, + "354": 1310, + "355": 328, + "356": 234, + "357": 290, + "358": 243, + "359": 408, + "360": 599, + "361": 445, + "362": 1115, + "363": 3332, + "364": 3332, + "365": 332, + "366": 464, + "367": 337, + "368": 338, + "369": 339, + "370": 1141, + "371": 348, + "372": 3332, + "373": 213, + "374": 2066, + "375": 539, + "376": 1352, + "377": 1769, + "378": 1790, + "379": 360, + "380": 1785, + "381": 491, + "382": 1032, + "383": 2021, + "384": 684, + "385": 953, + "386": 1063, + "387": 685, + "388": 1141, + "389": 635, + "390": 1182, + "391": 214, + "392": 3577, + "393": 2406, + "394": 1850, + "395": 1755, + "396": 1852, + "397": 2755, + "398": 3336, + "399": 3533, + "400": 425, + "401": 1185, + "402": 500, + "403": 1789, + "404": 1753, + "405": 1021, + "406": 480, + "407": 1162, + "408": 1408, + "409": 662, + "410": 2137, + "411": 1204, + "412": 342, + "413": 1382, + "414": 1205, + "415": 1205, + "416": 1382, + "417": 1206, + "418": 1207, + "419": 1351, + "420": 1298, + "421": 1299, + "422": 1300, + "423": 1280, + "424": 1281, + "425": 1282, + "426": 1283, + "427": 1286, + "428": 1279, + "429": 1279, + "430": 500, + "431": 1038, + "432": 294, + "433": 1262, + "434": 1680, + "435": 483, + "436": 503, + "437": 1846, + "438": 296, + "439": 413, + "440": 417, + "441": 447, + "442": 375, + "443": 453, + "444": 453, + "445": 524, + "446": 1324, + "447": 1325, + "448": 527, + "449": 613, + "450": 526, + "451": 2838, + "452": 520, + "453": 5301, + "454": 533, + "455": 1429, + "456": 526, + "457": 453, + "458": 453, + "459": 948, + "460": 949, + "461": 453, + "462": 453, + "463": 453, + "464": 526, + "465": 529, + "466": 453, + "467": 453, + "468": 453, + "469": 526, + "470": 1436, + "471": 1260, + "472": 108, + "473": 624, + "474": 425, + "475": 491, + "476": 203, + "477": 834, + "478": 511, + "479": 230, + "480": 526, + "481": 51, + "482": 512, + "483": 446, + "484": 517, + "485": 518, + "486": 445, + "487": 447, + "488": 448, + "489": 513, + "490": 449, + "491": 514, + "492": 2873, + "493": 515, + "494": 450, + "495": 451, + "496": 516, + "497": 452, + "498": 498, + "499": 507, + "500": 479, + "501": 471, + "502": 472, + "503": 473, + "504": 474, + "505": 475, + "506": 476, + "507": 477, + "508": 478, + "509": 1131, + "510": 1130, + "511": 3713, + "512": 547, + "513": 1029, + "514": 509, + "515": 72, + "516": 20, + "517": 19, + "518": 14, + "519": 52, + "520": 574, + "521": 488, + "522": 1243, + "523": 587, + "524": 592, + "525": 582, + "526": 1310, + "527": 3712, + "528": 1036, + "529": 565, + "530": 464, + "531": 464, + "532": 771, + "533": 465, + "534": 466, + "535": 467, + "536": 468, + "537": 610, + "538": 470, + "539": 598, + "540": 600, + "541": 598, + "542": 599, + "543": 608, + "544": 609, + "545": 610, + "546": 611, + "547": 614, + "548": 939, + "549": 30, + "550": 621, + "551": 622, + "552": 621, + "553": 622, + "554": 193, + "555": 194, + "556": 192, + "557": 947, + "558": 628, + "559": 629, + "560": 609, + "561": 615, + "562": 108, + "563": 586, + "564": 442, + "565": 589, + "566": 613, + "567": 455, + "568": 72, + "569": 71, + "570": 655, + "571": 541, + "572": 437, + "573": 1536, + "574": 6947, + "575": 486, + "576": 544, + "577": 2964, + "578": 545, + "579": 838, + "580": 453, + "581": 453, + "582": 453, + "583": 453, + "584": 454, + "585": 454, + "586": 454, + "587": 511, + "588": 466, + "589": 668, + "590": 3792, + "591": 87, + "592": 553, + "593": 543, + "594": 169, + "595": 84, + "596": 1385, + "597": 527, + "598": 627, + "599": 439, + "600": 1390, + "601": 448, + "602": 448, + "603": 905, + "604": 522, + "605": 550, + "606": 542, + "607": 536, + "608": 1566, + "609": 1565, + "610": 1390, + "611": 523, + "612": 535, + "613": 528, + "614": 1728, + "615": 532, + "616": 4, + "617": 523, + "618": 1398, + "619": 3949, + "620": 10, + "621": 5, + "622": 881, + "623": 140, + "624": 139, + "625": 924, + "626": 923, + "627": 923, + "628": 944, + "629": 690, + "630": 925, + "631": 943, + "632": 925, + "633": 929, + "634": 1306, + "635": 1304, + "636": 928, + "637": 1307, + "638": 689, + "639": 599, + "640": 698, + "641": 25, + "642": 877, + "643": 1694, + "644": 1790, + "645": 1746, + "646": 1111, + "647": 6725, + "648": 518, + "649": 519, + "650": 1625, + "651": 1444, + "652": 582, + "653": 568, + "654": 1910, + "655": 1445, + "656": 1301, + "657": 690, + "658": 929, + "659": 928, + "660": 1305, + "661": 1306, + "662": 1307, + "663": 929, + "664": 1305, + "665": 689, + "666": 934, + "667": 934, + "668": 709, + "669": 925, + "670": 925, + "671": 781, + "672": 1306, + "673": 758, + "674": 756, + "675": 757, + "676": 765, + "677": 766, + "678": 767, + "679": 782, + "680": 783, + "681": 552, + "682": 841, + "683": 842, + "684": 843, + "685": 844, + "686": 845, + "687": 708, + "688": 1647, + "689": 601, + "690": 262, + "691": 932, + "692": 1305, + "693": 1305, + "694": 823, + "695": 751, + "696": 751, + "697": 751, + "698": 828, + "699": 823, + "700": 829, + "701": 830, + "702": 831, + "703": 823, + "704": 828, + "705": 751, + "706": 907, + "707": 756, + "708": 932, + "709": 1306, + "710": 932, + "711": 757, + "712": 1307, + "713": 824, + "714": 825, + "715": 826, + "716": 262, + "717": 937, + "718": 591, + "719": 1750, + "720": 1747, + "721": 1630, + "722": 1631, + "723": 787, + "724": 2230, + "725": 2228, + "726": 2229, + "727": 646, + "728": 647, + "729": 1771, + "730": 1772, + "731": 3473, + "732": 4054, + "733": 655, + "734": 780, + "735": 247, + "736": 254, + "737": 250, + "738": 1856, + "739": 2301, + "740": 2369, + "741": 1838, + "742": 1840, + "743": 192, + "744": 193, + "745": 194, + "746": 1843, + "747": 1842, + "748": 1843, + "749": 662, + "750": 1845, + "751": 378, + "752": 368, + "753": 621, + "754": 372, + "755": 2702, + "756": 2694, + "757": 2704, + "758": 2703, + "759": 1888, + "760": 632, + "761": 1884, + "762": 2321, + "763": 2320, + "764": 2313, + "765": 2543, + "766": 2540, + "767": 2537, + "768": 2541, + "769": 1360, + "770": 283, + "771": 350, + "772": 832, + "773": 1168, + "774": 1705, + "775": 979, + "776": 2535, + "777": 4094, + "778": 914, + "779": 914, + "780": 914, + "781": 707, + "782": 1329, + "783": 1272, + "784": 1272, + "785": 1272, + "786": 1273, + "787": 1273, + "788": 1273, + "789": 1274, + "790": 1274, + "791": 1275, + "792": 1275, + "793": 1275, + "794": 1276, + "795": 1277, + "796": 1277, + "797": 1277, + "798": 1277, + "799": 1255, + "800": 1252, + "801": 1253, + "802": 1254, + "803": 1243, + "804": 1242, + "805": 1239, + "806": 1239, + "807": 1239, + "808": 1240, + "809": 1239, + "810": 1239, + "811": 1239, + "812": 1239, + "813": 1239, + "814": 1239, + "815": 1240, + "816": 1240, + "817": 1238, + "818": 1372, + "819": 1234, + "820": 338, + "821": 1263, + "822": 3564, + "823": 405, + "824": 1261, + "825": 1260, + "826": 1259, + "827": 6, + "828": 1043, + "829": 742, + "830": 2385, + "831": 402, + "832": 1258, + "833": 639, + "834": 1257, + "835": 289, + "836": 1008, + "837": 1009, + "838": 1010, + "839": 1011, + "840": 1012, + "841": 1013, + "842": 1015, + "843": 1014, + "844": 479, + "845": 1016, + "846": 1024, + "847": 1122, + "848": 1047, + "849": 1052, + "850": 1053, + "851": 1054, + "852": 1055, + "853": 1056, + "854": 1057, + "855": 1058, + "856": 1059, + "857": 1061, + "858": 1062, + "859": 479, + "860": 1060, + "861": 1092, + "862": 1079, + "863": 1075, + "864": 117, + "865": 1175, + "866": 1174, + "867": 1099, + "868": 934, + "869": 933, + "870": 933, + "871": 933, + "872": 1304, + "873": 1301, + "874": 385, + "875": 393, + "876": 531, + "877": 539, + "878": 621, + "879": 751, + "880": 751, + "881": 751, + "882": 887, + "883": 1377, + "884": 1547, + "885": 942, + "886": 938, + "887": 936, + "888": 935, + "889": 713, + "890": 35, + "891": 949, + "892": 974, + "893": 973, + "894": 970, + "895": 970, + "896": 972, + "897": 971, + "898": 945, + "899": 980, + "900": 617, + "901": 541, + "902": 941, + "903": 940, + "904": 1374, + "905": 404, + "906": 1373, + "907": 978, + "908": 977, + "909": 836, + "910": 982, + "911": 981, + "912": 981, + "913": 729, + "914": 975, + "915": 976, + "916": 945, + "917": 980, + "918": 617, + "919": 1556, + "920": 619, + "921": 620, + "922": 948, + "923": 517, + "924": 946, + "925": 193, + "926": 194, + "927": 947, + "928": 945, + "929": 980, + "930": 617, + "931": 1550, + "932": 752, + "933": 945, + "934": 811, + "935": 812, + "936": 813, + "937": 814, + "938": 815, + "939": 816, + "940": 817, + "941": 818, + "942": 1209, + "943": 1532, + "944": 716, + "945": 983, + "946": 985, + "947": 555, + "948": 554, + "949": 554, + "950": 554, + "951": 554, + "952": 780, + "953": 1378, + "954": 1381, + "955": 1380, + "956": 1277, + "957": 827, + "958": 1414, + "959": 1306, + "960": 991, + "961": 989, + "962": 990, + "963": 993, + "964": 994, + "965": 1007, + "966": 1005, + "967": 992, + "968": 256, + "969": 251, + "970": 248, + "971": 1187, + "972": 1195, + "973": 1194, + "974": 117, + "975": 1196, + "976": 1187, + "977": 1195, + "978": 116, + "979": 1197, + "980": 1193, + "981": 346, + "982": 344, + "983": 342, + "984": 348, + "985": 346, + "986": 1420, + "987": 342, + "988": 348, + "989": 1279, + "990": 1284, + "991": 1285, + "992": 824, + "993": 826, + "994": 906, + "995": 833, + "996": 834, + "997": 824, + "998": 835, + "999": 824, + "1000": 838, + "1001": 839, + "1002": 1314, + "1003": 837, + "1004": 1221, + "1005": 1343, + "1006": 342, + "1007": 968, + "1008": 1398, + "1009": 1399, + "1010": 8141, + "1011": 585, + "1012": 1401, + "1013": 2104, + "1014": 797, + "1015": 1309, + "1016": 269, + "1017": 1001, + "1018": 1176, + "1019": 999, + "1020": 996, + "1021": 998, + "1022": 997, + "1023": 995, + "1024": 994, + "1025": 1006, + "1026": 1005, + "1027": 1267, + "1028": 1268, + "1029": 1463, + "1030": 1003, + "1031": 1002, + "1032": 1004, + "1033": 346, + "1034": 344, + "1035": 342, + "1036": 348, + "1037": 38, + "1038": 1210, + "1039": 1211, + "1040": 1212, + "1041": 1287, + "1042": 1288, + "1043": 1289, + "1044": 1290, + "1045": 1292, + "1046": 1291, + "1047": 1293, + "1048": 1294, + "1049": 1295, + "1050": 1296, + "1051": 1297, + "1052": 1548, + "1053": 1549, + "1054": 1551, + "1055": 1552, + "1056": 1553, + "1057": 1554, + "1058": 1555, + "1059": 802, + "1060": 1566, + "1061": 1557, + "1062": 1558, + "1063": 1559, + "1064": 1383, + "1065": 1205, + "1066": 1205, + "1067": 5537, + "1068": 1705, + "1069": 346, + "1070": 1560, + "1071": 1561, + "1072": 1562, + "1073": 1563, + "1074": 1570, + "1075": 1565, + "1076": 716, + "1077": 108, + "1078": 108, + "1079": 108, + "1080": 108, + "1081": 1577, + "1082": 891, + "1083": 888, + "1084": 889, + "1085": 890, + "1086": 1154, + "1087": 1169, + "1088": 1165, + "1089": 1160, + "1090": 1143, + "1091": 1133, + "1092": 1159, + "1093": 1073, + "1094": 1137, + "1095": 1127, + "1096": 1126, + "1097": 1109, + "1098": 1108, + "1099": 1110, + "1100": 1105, + "1101": 1166, + "1102": 1033, + "1103": 1167, + "1104": 1151, + "1105": 1150, + "1106": 542, + "1107": 1144, + "1108": 1136, + "1109": 497, + "1110": 1129, + "1111": 1128, + "1112": 1125, + "1113": 1124, + "1114": 1107, + "1115": 1106, + "1116": 1361, + "1117": 757, + "1118": 1755, + "1119": 1259, + "1120": 1259, + "1121": 200, + "1122": 1037, + "1123": 1264, + "1124": 1262, + "1125": 1262, + "1126": 1265, + "1127": 1266, + "1128": 1269, + "1129": 1270, + "1130": 116, + "1131": 1524, + "1132": 1522, + "1133": 1584, + "1134": 5604, + "1135": 1200, + "1136": 1584, + "1137": 1584, + "1138": 1528, + "1139": 779, + "1140": 1533, + "1141": 1281, + "1142": 5612, + "1143": 1534, + "1144": 1534, + "1145": 1584, + "1146": 1537, + "1147": 5617, + "1148": 5618, + "1149": 10402, + "1150": 621, + "1151": 1861, + "1152": 1337, + "1153": 981, + "1154": 1868, + "1155": 892, + "1156": 1277, + "1157": 1277, + "1158": 1277, + "1159": 1277, + "1160": 1454, + "1161": 1371, + "1162": 1343, + "1163": 1275, + "1164": 992, + "1165": 1584, + "1166": 531, + "1167": 529, + "1168": 527, + "1169": 533, + "1170": 531, + "1171": 1348, + "1172": 527, + "1173": 1856, + "1174": 979, + "1175": 1568, + "1176": 5646, + "1177": 1569, + "1178": 1584, + "1179": 1711, + "1180": 1293, + "1181": 1293, + "1182": 1301, + "1183": 526, + "1184": 1322, + "1185": 1322, + "1186": 1524, + "1187": 1306, + "1188": 1729, + "1189": 1352, + "1190": 904, + "1191": 527, + "1192": 1338, + "1193": 1583, + "1194": 1359, + "1195": 903, + "1196": 1635, + "1197": 1273, + "1198": 1277, + "1199": 1277, + "1200": 1277, + "1201": 1277, + "1202": 1277, + "1203": 1277, + "1204": 1701, + "1205": 1746, + "1206": 1275, + "1207": 1275, + "1208": 1371, + "1209": 1371, + "1210": 1347, + "1211": 1707, + "1212": 1659, + "1213": 519, + "1214": 1356, + "1215": 1324, + "1216": 1340, + "1217": 1321, + "1218": 1323, + "1219": 1322, + "1220": 527, + "1221": 2175, + "1222": 849, + "1223": 850, + "1224": 851, + "1225": 852, + "1226": 853, + "1227": 854, + "1228": 855, + "1229": 856, + "1230": 857, + "1231": 858, + "1232": 859, + "1233": 860, + "1234": 861, + "1235": 862, + "1236": 1355, + "1237": 864, + "1238": 1177, + "1239": 1213, + "1240": 1304, + "1241": 929, + "1242": 974, + "1243": 1305, + "1244": 1177, + "1245": 923, + "1246": 1179, + "1247": 108, + "1248": 108, + "1249": 108, + "1250": 108, + "1251": 108, + "1252": 108, + "1253": 108, + "1254": 108, + "1255": 1432, + "1256": 108, + "1257": 2971, + "1258": 895, + "1259": 1765, + "1260": 1319, + "1261": 1406, + "1262": 896, + "1263": 897, + "1264": 1377, + "1265": 898, + "1266": 899, + "1267": 865, + "1268": 866, + "1269": 867, + "1270": 868, + "1271": 869, + "1272": 870, + "1273": 871, + "1274": 872, + "1275": 873, + "1276": 874, + "1277": 875, + "1278": 876, + "1279": 877, + "1280": 878, + "1281": 879, + "1282": 880, + "1283": 881, + "1284": 882, + "1285": 883, + "1286": 884, + "1287": 885, + "1288": 886, + "1289": 1333, + "1290": 520, + "1291": 1722, + "1292": 1083, + "1293": 1730, + "1294": 1347, + "1295": 1716, + "1296": 1416, + "1297": 1440, + "1298": 1325, + "1299": 1348, + "1300": 1464, + "1301": 1377, + "1302": 935, + "1303": 1417, + "1304": 1172, + "1305": 1171, + "1306": 1445, + "1307": 1237, + "1308": 1241, + "1309": 1256, + "1310": 1244, + "1311": 1251, + "1312": 1245, + "1313": 1246, + "1314": 1250, + "1315": 1249, + "1316": 1248, + "1317": 1247, + "1318": 346, + "1319": 344, + "1320": 346, + "1321": 344, + "1322": 344, + "1323": 344, + "1324": 969, + "1325": 1232, + "1326": 1231, + "1327": 1225, + "1328": 1230, + "1329": 1229, + "1330": 1228, + "1331": 1227, + "1332": 1226, + "1333": 1225, + "1334": 1589, + "1335": 108, + "1336": 108, + "1337": 1166, + "1338": 108, + "1339": 108, + "1340": 108, + "1341": 1345, + "1342": 1278, + "1343": 1245, + "1344": 1330, + "1345": 109, + "1346": 143, + "1347": 144, + "1348": 145, + "1349": 146, + "1350": 111, + "1351": 284, + "1352": 147, + "1353": 151, + "1354": 153, + "1355": 441, + "1356": 158, + "1357": 438, + "1358": 117, + "1359": 154, + "1360": 155, + "1361": 157, + "1362": 430, + "1363": 431, + "1364": 432, + "1365": 433, + "1366": 434, + "1367": 435, + "1368": 625, + "1369": 1202, + "1370": 1203, + "1371": 1200, + "1372": 1201, + "1373": 918, + "1374": 919, + "1375": 920, + "1376": 921, + "1377": 922, + "1378": 1326, + "1379": 2093, + "1380": 1525, + "1381": 1170, + "1382": 1330, + "1383": 1536, + "1384": 1332, + "1385": 1412, + "1386": 1219, + "1387": 1255, + "1388": 1271, + "1389": 1331, + "1390": 1178, + "1391": 833, + "1392": 1570, + "1393": 497, + "1394": 967, + "1395": 629, + "1396": 631, + "1397": 117, + "1398": 97, + "1399": 984, + "1400": 1303, + "1401": 987, + "1402": 986, + "1403": 1302, + "1404": 1357, + "1405": 1362, + "1406": 1223, + "1407": 1224, + "1408": 894, + "1409": 1618, + "1410": 1188, + "1411": 1189, + "1412": 1190, + "1413": 1191, + "1414": 1192, + "1415": 1193, + "1416": 117, + "1417": 1276, + "1418": 1346, + "1419": 1312, + "1420": 1608, + "1421": 1342, + "1422": 621, + "1423": 622, + "1424": 1354, + "1425": 1704, + "1426": 193, + "1427": 194, + "1428": 602, + "1429": 602, + "1430": 601, + "1431": 139, + "1432": 140, + "1433": 212, + "1434": 2163, + "1435": 130, + "1436": 108, + "1437": 2135, + "1438": 2118, + "1439": 2160, + "1440": 1231, + "1441": 2136, + "1442": 1471, + "1443": 1803, + "1444": 1804, + "1445": 244, + "1446": 128, + "1447": 354, + "1448": 1907, + "1449": 139, + "1450": 599, + "1451": 597, + "1452": 35, + "1453": 192, + "1454": 517, + "1455": 1680, + "1456": 1680, + "1457": 1678, + "1458": 1678, + "1459": 108, + "1460": 1676, + "1461": 1677, + "1462": 1672, + "1463": 1673, + "1464": 1674, + "1465": 114, + "1466": 1675, + "1467": 1535, + "1468": 1536, + "1469": 1067, + "1470": 1533, + "1471": 1534, + "1472": 1538, + "1473": 1535, + "1474": 1539, + "1475": 1540, + "1476": 1541, + "1477": 1542, + "1478": 1543, + "1479": 1544, + "1480": 1545, + "1481": 1546, + "1482": 108, + "1483": 1120, + "1484": 1696, + "1485": 1697, + "1486": 1698, + "1487": 1316, + "1488": 1689, + "1489": 1690, + "1490": 1691, + "1491": 1692, + "1492": 1693, + "1493": 1681, + "1494": 1681, + "1495": 1681, + "1496": 1681, + "1497": 1682, + "1498": 1683, + "1499": 1684, + "1500": 1685, + "1501": 1686, + "1502": 1687, + "1503": 29, + "1504": 1803, + "1505": 1804, + "1506": 1804, + "1507": 1802, + "1508": 1802, + "1509": 1802, + "1510": 1566, + "1511": 1566, + "1512": 1566, + "1513": 1402, + "1514": 1640, + "1515": 1970, + "1516": 2104, + "1517": 1883, + "1518": 1884, + "1519": 1885, + "1520": 1531, + "1521": 1886, + "1522": 1650, + "1523": 1613, + "1524": 1887, + "1525": 1888, + "1526": 2147, + "1527": 1889, + "1528": 1650, + "1529": 1650, + "1530": 2146, + "1531": 1890, + "1532": 1890, + "1533": 108, + "1534": 1588, + "1535": 1648, + "1536": 2091, + "1537": 1648, + "1538": 220, + "1539": 108, + "1540": 1397, + "1541": 1397, + "1542": 1497, + "1543": 1498, + "1544": 1415, + "1545": 1499, + "1546": 1396, + "1547": 2154, + "1548": 2154, + "1549": 1657, + "1550": 2152, + "1551": 1654, + "1552": 1655, + "1553": 1656, + "1554": 1652, + "1555": 1449, + "1556": 1653, + "1557": 1808, + "1558": 1421, + "1559": 1892, + "1560": 1893, + "1561": 1894, + "1562": 1895, + "1563": 584, + "1564": 1897, + "1565": 1805, + "1566": 1646, + "1567": 1645, + "1568": 1646, + "1569": 1645, + "1570": 1644, + "1571": 1644, + "1572": 1644, + "1573": 1644, + "1574": 1644, + "1575": 2100, + "1576": 2098, + "1577": 2099, + "1578": 1453, + "1579": 2101, + "1580": 2102, + "1581": 2103, + "1582": 583, + "1583": 68, + "1584": 69, + "1585": 2063, + "1586": 619, + "1587": 620, + "1588": 1391, + "1589": 1392, + "1590": 1393, + "1591": 1394, + "1592": 1639, + "1593": 750, + "1594": 1395, + "1595": 436, + "1596": 103, + "1597": 104, + "1598": 1901, + "1599": 653, + "1600": 1416, + "1601": 2204, + "1602": 1903, + "1603": 1904, + "1604": 1905, + "1605": 1906, + "1606": 1585, + "1607": 1586, + "1608": 1587, + "1609": 1588, + "1610": 1589, + "1611": 1589, + "1612": 1590, + "1613": 1848, + "1614": 1159, + "1615": 1592, + "1616": 1591, + "1617": 1593, + "1618": 1799, + "1619": 1596, + "1620": 1597, + "1621": 1595, + "1622": 1594, + "1623": 1599, + "1624": 1598, + "1625": 1600, + "1626": 1601, + "1627": 1415, + "1628": 1806, + "1629": 1805, + "1630": 1805, + "1631": 1858, + "1632": 1417, + "1633": 2201, + "1634": 2201, + "1635": 598, + "1636": 1907, + "1637": 550, + "1638": 614, + "1639": 2064, + "1640": 122, + "1641": 139, + "1642": 546, + "1643": 2065, + "1644": 2066, + "1645": 57, + "1646": 80, + "1647": 2200, + "1648": 2199, + "1649": 2198, + "1650": 619, + "1651": 729, + "1652": 2087, + "1653": 2088, + "1654": 1810, + "1655": 2089, + "1656": 1418, + "1657": 269, + "1658": 67, + "1659": 115, + "1660": 1910, + "1661": 1419, + "1662": 1420, + "1663": 1421, + "1664": 1911, + "1665": 1912, + "1666": 1605, + "1667": 165, + "1668": 1581, + "1669": 1603, + "1670": 1582, + "1671": 820, + "1672": 1581, + "1673": 1603, + "1674": 11, + "1675": 1422, + "1676": 1423, + "1677": 40, + "1678": 130, + "1679": 56, + "1680": 201, + "1681": 56, + "1682": 1424, + "1683": 1919, + "1684": 1920, + "1685": 1921, + "1686": 113, + "1687": 1923, + "1688": 1419, + "1689": 1425, + "1690": 1426, + "1691": 115, + "1692": 117, + "1693": 56, + "1694": 1924, + "1695": 1925, + "1696": 1926, + "1697": 2161, + "1698": 656, + "1699": 2162, + "1700": 1848, + "1701": 1927, + "1702": 1450, + "1703": 213, + "1704": 1451, + "1705": 1929, + "1706": 1422, + "1707": 1423, + "1708": 1452, + "1709": 1930, + "1710": 1424, + "1711": 1453, + "1712": 1931, + "1713": 2096, + "1714": 1932, + "1715": 1933, + "1716": 2153, + "1717": 1907, + "1718": 1935, + "1719": 1936, + "1720": 1937, + "1721": 361, + "1722": 1939, + "1723": 824, + "1724": 1391, + "1725": 1863, + "1726": 2186, + "1727": 2186, + "1728": 1941, + "1729": 2068, + "1730": 2202, + "1731": 2076, + "1732": 2077, + "1733": 2078, + "1734": 2079, + "1735": 1454, + "1736": 2080, + "1737": 656, + "1738": 2082, + "1739": 2081, + "1740": 1688, + "1741": 1942, + "1742": 15, + "1743": 56, + "1744": 116, + "1745": 614, + "1746": 2083, + "1747": 2084, + "1748": 1293, + "1749": 656, + "1750": 2085, + "1751": 2086, + "1752": 2086, + "1753": 1567, + "1754": 1568, + "1755": 1569, + "1756": 1570, + "1757": 1798, + "1758": 1572, + "1759": 1573, + "1760": 1833, + "1761": 1571, + "1762": 1574, + "1763": 1575, + "1764": 1576, + "1765": 1577, + "1766": 1578, + "1767": 1579, + "1768": 1580, + "1769": 2073, + "1770": 2074, + "1771": 2075, + "1772": 1385, + "1773": 1581, + "1774": 1582, + "1775": 1583, + "1776": 1584, + "1777": 1584, + "1778": 1584, + "1779": 1607, + "1780": 1427, + "1781": 1428, + "1782": 1429, + "1783": 1430, + "1784": 1431, + "1785": 1432, + "1786": 1433, + "1787": 1434, + "1788": 1435, + "1789": 1436, + "1790": 1437, + "1791": 1438, + "1792": 1439, + "1793": 1440, + "1794": 1445, + "1795": 1441, + "1796": 1442, + "1797": 1443, + "1798": 1444, + "1799": 1610, + "1800": 1446, + "1801": 1614, + "1802": 1615, + "1803": 1616, + "1804": 1617, + "1805": 1618, + "1806": 1619, + "1807": 1620, + "1808": 1621, + "1809": 1622, + "1810": 1623, + "1811": 1624, + "1812": 1625, + "1813": 646, + "1814": 647, + "1815": 648, + "1816": 1629, + "1817": 1630, + "1818": 1631, + "1819": 1632, + "1820": 1633, + "1821": 1634, + "1822": 1635, + "1823": 1636, + "1824": 1637, + "1825": 1638, + "1826": 1796, + "1827": 1797, + "1828": 1734, + "1829": 1734, + "1830": 1734, + "1831": 1747, + "1832": 1750, + "1833": 1752, + "1834": 1763, + "1835": 1764, + "1836": 1765, + "1837": 1767, + "1838": 1766, + "1839": 1773, + "1840": 1776, + "1841": 1778, + "1842": 114, + "1843": 1777, + "1844": 1783, + "1845": 491, + "1846": 1789, + "1847": 1638, + "1848": 1631, + "1849": 1787, + "1850": 117, + "1851": 1762, + "1852": 1770, + "1853": 1779, + "1854": 1786, + "1855": 1793, + "1856": 1792, + "1857": 1794, + "1858": 1232, + "1859": 1795, + "1860": 1170, + "1861": 115, + "1862": 1148, + "1863": 113, + "1864": 1609, + "1865": 2105, + "1866": 2106, + "1867": 2120, + "1868": 2108, + "1869": 2109, + "1870": 2110, + "1871": 2111, + "1872": 2159, + "1873": 1810, + "1874": 1811, + "1875": 1812, + "1876": 1486, + "1877": 2092, + "1878": 2113, + "1879": 269, + "1880": 1688, + "1881": 2114, + "1882": 557, + "1883": 2116, + "1884": 2117, + "1885": 2206, + "1886": 1975, + "1887": 1976, + "1888": 34, + "1889": 1977, + "1890": 1978, + "1891": 1979, + "1892": 1980, + "1893": 2074, + "1894": 1982, + "1895": 58, + "1896": 59, + "1897": 60, + "1898": 61, + "1899": 1985, + "1900": 1986, + "1901": 1709, + "1902": 1988, + "1903": 1709, + "1904": 1991, + "1905": 331, + "1906": 333, + "1907": 332, + "1908": 1996, + "1909": 2001, + "1910": 2002, + "1911": 2003, + "1912": 2004, + "1913": 2005, + "1914": 2006, + "1915": 2007, + "1916": 236, + "1917": 2010, + "1918": 2013, + "1919": 2014, + "1920": 2015, + "1921": 2016, + "1922": 2017, + "1923": 2022, + "1924": 2023, + "1925": 2024, + "1926": 2025, + "1927": 2026, + "1928": 2029, + "1929": 2030, + "1930": 2031, + "1931": 2034, + "1932": 2035, + "1933": 2036, + "1934": 2037, + "1935": 2041, + "1936": 2042, + "1937": 2043, + "1938": 2043, + "1939": 2045, + "1940": 2046, + "1941": 2047, + "1942": 2048, + "1943": 2051, + "1944": 2051, + "1945": 2051, + "1946": 2052, + "1947": 2053, + "1948": 2054, + "1949": 2055, + "1950": 2115, + "1951": 2123, + "1952": 2106, + "1953": 2125, + "1954": 2126, + "1955": 2109, + "1956": 2128, + "1957": 2129, + "1958": 2089, + "1959": 2113, + "1960": 2205, + "1961": 1727, + "1962": 1946, + "1963": 2149, + "1964": 104, + "1965": 105, + "1966": 2089, + "1967": 2130, + "1968": 1615, + "1969": 2131, + "1970": 2132, + "1971": 2133, + "1972": 2134, + "1973": 2121, + "1974": 2137, + "1975": 2137, + "1976": 2143, + "1977": 2067, + "1978": 253, + "1979": 1785, + "1980": 245, + "1981": 1126, + "1982": 2069, + "1983": 2070, + "1984": 2071, + "1985": 2072, + "1986": 2072, + "1987": 1486, + "1988": 2092, + "1989": 2088, + "1990": 1811, + "1991": 1809, + "1992": 2090, + "1993": 1805, + "1994": 1802, + "1995": 1486, + "1996": 2209, + "1997": 1464, + "1998": 1461, + "1999": 1646, + "2000": 2174, + "2001": 1479, + "2002": 1481, + "2003": 1463, + "2004": 1480, + "2005": 1462, + "2006": 1465, + "2007": 1466, + "2008": 1467, + "2009": 1459, + "2010": 1468, + "2011": 1469, + "2012": 1470, + "2013": 1471, + "2014": 1472, + "2015": 1473, + "2016": 1474, + "2017": 1475, + "2018": 1477, + "2019": 1476, + "2020": 1478, + "2021": 1482, + "2022": 2171, + "2023": 2176, + "2024": 1483, + "2025": 1484, + "2026": 1485, + "2027": 2118, + "2028": 2119, + "2029": 2120, + "2030": 2158, + "2031": 297, + "2032": 2136, + "2033": 108, + "2034": 2170, + "2035": 2210, + "2036": 2138, + "2037": 2142, + "2038": 2139, + "2039": 2140, + "2040": 2141, + "2041": 108, + "2042": 1490, + "2043": 108, + "2044": 620, + "2045": 1492, + "2046": 1949, + "2047": 1950, + "2048": 1493, + "2049": 1400, + "2050": 1951, + "2051": 1952, + "2052": 1953, + "2053": 1494, + "2054": 1495, + "2055": 1493, + "2056": 1400, + "2057": 1954, + "2058": 1955, + "2059": 1956, + "2060": 1957, + "2061": 1496, + "2062": 1400, + "2063": 1494, + "2064": 1495, + "2065": 1958, + "2066": 1958, + "2067": 1960, + "2068": 1961, + "2069": 1962, + "2070": 1963, + "2071": 1951, + "2072": 1952, + "2073": 1954, + "2074": 1967, + "2075": 1493, + "2076": 1400, + "2077": 1501, + "2078": 1968, + "2079": 1969, + "2080": 1500, + "2082": 2170, + "2084": 2020, + "2085": 1535, + "2086": 1544, + "2087": 233, + "2088": 1546, + "2089": 1994, + "2090": 417, + "2091": 678, + "2092": 270, + "2093": 2009, + "2094": 637, + "2095": 346, + "2096": 342, + "2097": 1555, + "2098": 347, + "2099": 1566, + "2100": 1563, + "2101": 345, + "2102": 2181, + "2103": 1862, + "2104": 1714, + "2105": 1716, + "2106": 1718, + "2107": 1721, + "2108": 1722, + "2109": 1604, + "2110": 1724, + "2111": 274, + "2112": 1707, + "2113": 248, + "2114": 260, + "2115": 1710, + "2116": 343, + "2117": 1661, + "2118": 1662, + "2119": 1663, + "2120": 1664, + "2121": 1665, + "2122": 1666, + "2123": 1667, + "2124": 1668, + "2125": 1669, + "2126": 1670, + "2127": 2280, + "2128": 1503, + "2129": 1504, + "2130": 1505, + "2131": 257, + "2132": 1506, + "2133": 1699, + "2134": 1507, + "2135": 1508, + "2136": 1509, + "2137": 1632, + "2138": 1511, + "2139": 1512, + "2140": 1513, + "2141": 1514, + "2142": 1515, + "2143": 1516, + "2144": 1517, + "2145": 1700, + "2146": 1701, + "2147": 1518, + "2148": 1519, + "2149": 1520, + "2150": 1521, + "2151": 1522, + "2152": 1523, + "2153": 1524, + "2154": 1702, + "2155": 1525, + "2156": 1526, + "2157": 1527, + "2158": 1529, + "2159": 1529, + "2160": 1530, + "2161": 108, + "2162": 1717, + "2163": 1777, + "2164": 1717, + "2165": 1713, + "2166": 1715, + "2167": 1712, + "2168": 1726, + "2169": 2093, + "2170": 1811, + "2171": 1813, + "2172": 1418, + "2173": 1502, + "2174": 2095, + "2175": 2090, + "2176": 1809, + "2177": 2089, + "2178": 297, + "2179": 2094, + "2180": 2093, + "2181": 1776, + "2182": 1726, + "2183": 1459, + "2184": 1460, + "2185": 1469, + "2186": 1472, + "2187": 1992, + "2188": 1993, + "2189": 1995, + "2190": 1785, + "2192": 1736, + "2193": 2057, + "2194": 1738, + "2195": 2059, + "2196": 2060, + "2197": 2061, + "2198": 2062, + "2199": 1744, + "2200": 2197, + "2201": 108, + "2202": 2196, + "2203": 1403, + "2204": 1882, + "2205": 1971, + "2206": 2211, + "2207": 1881, + "2208": 1640, + "2209": 1404, + "2210": 2203, + "2211": 1640, + "2212": 1972, + "2213": 1973, + "2214": 1870, + "2215": 1870, + "2216": 1870, + "2217": 1870, + "2218": 1651, + "2219": 2148, + "2220": 1640, + "2221": 1732, + "2222": 1848, + "2223": 399, + "2224": 67, + "2225": 68, + "2226": 69, + "2227": 405, + "2228": 2144, + "2229": 2145, + "2230": 2168, + "2231": 1870, + "2232": 1690, + "2233": 1699, + "2234": 2183, + "2235": 1855, + "2236": 1974, + "2237": 1860, + "2238": 331, + "2239": 417, + "2240": 678, + "2241": 43, + "2242": 680, + "2243": 681, + "2244": 630, + "2245": 2097, + "2246": 2164, + "2247": 2185, + "2248": 2092, + "2249": 297, + "2250": 2121, + "2251": 2092, + "2252": 297, + "2253": 2121, + "2254": 2092, + "2255": 2089, + "2256": 2121, + "2257": 1984, + "2258": 1984, + "2259": 1998, + "2260": 1999, + "2261": 2180, + "2262": 1633, + "2263": 1728, + "2264": 2187, + "2265": 2188, + "2266": 2189, + "2267": 2190, + "2268": 2191, + "2269": 2192, + "2270": 1468, + "2271": 1470, + "2272": 1472, + "2273": 1473, + "2274": 1459, + "2275": 1459, + "2276": 2105, + "2277": 2109, + "2278": 2110, + "2279": 2106, + "2280": 2111, + "2281": 1382, + "2282": 1474, + "2283": 1482, + "2284": 1472, + "2285": 2212, + "2286": 3240, + "2287": 2265, + "2288": 2266, + "2289": 2513, + "2290": 2325, + "2291": 750, + "2292": 2261, + "2293": 2262, + "2294": 2263, + "2295": 2267, + "2296": 2267, + "2297": 2261, + "2298": 108, + "2299": 2259, + "2300": 2260, + "2301": 2256, + "2302": 2252, + "2303": 2251, + "2304": 2245, + "2305": 2249, + "2306": 2257, + "2307": 3984, + "2308": 2227, + "2309": 2220, + "2310": 2221, + "2311": 2222, + "2312": 1185, + "2313": 2246, + "2314": 2247, + "2315": 2248, + "2316": 2250, + "2317": 2255, + "2318": 2253, + "2319": 2137, + "2320": 2139, + "2321": 2140, + "2322": 2141, + "2323": 2138, + "2324": 2324, + "2325": 2142, + "2326": 1792, + "2327": 2254, + "2328": 2264, + "2329": 2258, + "2330": 2256, + "2331": 1186, + "2332": 2268, + "2333": 2269, + "2334": 2270, + "2335": 2271, + "2336": 2272, + "2337": 2273, + "2338": 2274, + "2339": 2275, + "2340": 2276, + "2341": 2277, + "2342": 2278, + "2343": 2279, + "2344": 2280, + "2345": 2281, + "2346": 1894, + "2347": 706, + "2348": 706, + "2349": 707, + "2350": 710, + "2351": 710, + "2352": 711, + "2353": 712, + "2354": 727, + "2355": 727, + "2356": 728, + "2357": 730, + "2358": 731, + "2359": 2510, + "2360": 732, + "2361": 732, + "2362": 733, + "2363": 108, + "2364": 2370, + "2365": 2371, + "2366": 2371, + "2367": 2333, + "2368": 2334, + "2369": 2335, + "2370": 428, + "2371": 2322, + "2372": 2337, + "2373": 2338, + "2374": 2339, + "2375": 2282, + "2376": 2283, + "2377": 2283, + "2378": 2283, + "2379": 983, + "2380": 2284, + "2381": 2285, + "2382": 2286, + "2383": 1303, + "2384": 2287, + "2385": 2288, + "2386": 2289, + "2387": 2290, + "2388": 2290, + "2389": 2281, + "2390": 2332, + "2391": 2332, + "2392": 736, + "2393": 737, + "2394": 738, + "2395": 739, + "2396": 740, + "2397": 741, + "2398": 820, + "2399": 821, + "2400": 822, + "2401": 1864, + "2402": 1871, + "2403": 1872, + "2404": 820, + "2405": 822, + "2406": 1864, + "2407": 1873, + "2408": 1874, + "2409": 1875, + "2410": 1876, + "2411": 2150, + "2412": 426, + "2413": 2340, + "2414": 427, + "2415": 2341, + "2416": 2342, + "2417": 2343, + "2418": 2344, + "2419": 2346, + "2420": 2917, + "2421": 633, + "2422": 428, + "2423": 2347, + "2424": 108, + "2425": 2349, + "2426": 2291, + "2427": 2292, + "2428": 2292, + "2429": 2292, + "2430": 2293, + "2431": 2293, + "2432": 2293, + "2433": 2286, + "2434": 913, + "2435": 2000, + "2436": 730, + "2437": 2375, + "2438": 2376, + "2439": 2342, + "2440": 1313, + "2441": 2343, + "2442": 2334, + "2443": 802, + "2444": 727, + "2445": 730, + "2446": 8143, + "2447": 1205, + "2448": 909, + "2449": 910, + "2450": 911, + "2451": 2360, + "2452": 1877, + "2453": 1878, + "2454": 258, + "2455": 2309, + "2456": 2302, + "2457": 2303, + "2458": 2306, + "2459": 2307, + "2460": 2379, + "2461": 2309, + "2462": 2306, + "2463": 2310, + "2464": 2315, + "2465": 2316, + "2466": 2312, + "2467": 2206, + "2468": 812, + "2469": 2508, + "2470": 2509, + "2471": 2364, + "2472": 2365, + "2473": 2366, + "2474": 2326, + "2475": 2299, + "2476": 1939, + "2477": 692, + "2478": 693, + "2479": 694, + "2480": 695, + "2481": 697, + "2482": 2359, + "2483": 700, + "2484": 701, + "2485": 702, + "2486": 703, + "2487": 704, + "2488": 705, + "2489": 2224, + "2490": 2226, + "2491": 2227, + "2492": 2233, + "2493": 2241, + "2494": 2242, + "2495": 2243, + "2496": 2244, + "2497": 1756, + "2498": 2237, + "2499": 2240, + "2500": 2231, + "2501": 2368, + "2502": 2350, + "2503": 64, + "2504": 2367, + "2505": 2353, + "2506": 2354, + "2507": 2355, + "2508": 2356, + "2509": 2357, + "2510": 2377, + "2511": 2378, + "2512": 2379, + "2513": 2380, + "2514": 2381, + "2515": 2382, + "2516": 2383, + "2517": 2384, + "2518": 2385, + "2519": 2386, + "2520": 2387, + "2521": 2388, + "2522": 2389, + "2523": 2390, + "2524": 2390, + "2525": 2391, + "2526": 2392, + "2527": 2393, + "2528": 2394, + "2529": 2395, + "2530": 2396, + "2531": 2397, + "2532": 2379, + "2533": 2398, + "2534": 2399, + "2535": 2400, + "2536": 2400, + "2537": 2401, + "2538": 2402, + "2539": 2403, + "2540": 2404, + "2541": 2405, + "2542": 2406, + "2543": 2407, + "2544": 2408, + "2545": 2409, + "2546": 2410, + "2547": 2411, + "2548": 2411, + "2549": 2412, + "2550": 2413, + "2551": 2414, + "2552": 2415, + "2553": 2416, + "2554": 2417, + "2555": 2418, + "2556": 2419, + "2557": 2420, + "2558": 2421, + "2559": 2422, + "2560": 2423, + "2561": 2424, + "2562": 2425, + "2563": 2426, + "2564": 2427, + "2565": 2428, + "2566": 2429, + "2567": 2430, + "2568": 2431, + "2569": 2432, + "2570": 2406, + "2571": 2433, + "2572": 2434, + "2573": 2435, + "2574": 2436, + "2575": 2437, + "2576": 2438, + "2577": 2439, + "2578": 2440, + "2579": 2439, + "2580": 2440, + "2581": 2441, + "2582": 2442, + "2583": 2443, + "2584": 2444, + "2585": 2445, + "2586": 2407, + "2587": 2446, + "2588": 2447, + "2589": 2448, + "2590": 2380, + "2591": 2449, + "2592": 2450, + "2593": 2451, + "2594": 2452, + "2595": 2414, + "2596": 2453, + "2597": 2454, + "2598": 2455, + "2599": 2405, + "2600": 2456, + "2601": 2457, + "2602": 2458, + "2603": 2459, + "2604": 2460, + "2605": 2461, + "2606": 2462, + "2607": 2463, + "2608": 2394, + "2609": 2464, + "2610": 2465, + "2611": 2466, + "2612": 2411, + "2613": 2429, + "2614": 2467, + "2615": 2468, + "2616": 2469, + "2617": 2470, + "2618": 2404, + "2619": 2471, + "2620": 2472, + "2621": 2473, + "2622": 2474, + "2623": 2475, + "2624": 2476, + "2625": 2477, + "2626": 2404, + "2627": 2471, + "2628": 2478, + "2629": 2479, + "2630": 2480, + "2631": 2481, + "2632": 2482, + "2633": 2482, + "2634": 2483, + "2635": 2484, + "2636": 2485, + "2637": 2486, + "2638": 2388, + "2639": 2460, + "2640": 2488, + "2641": 2489, + "2642": 2487, + "2643": 2490, + "2644": 2491, + "2645": 2492, + "2646": 2493, + "2647": 2494, + "2648": 2452, + "2649": 2495, + "2650": 2496, + "2651": 2497, + "2652": 2498, + "2653": 2499, + "2654": 2500, + "2655": 2501, + "2656": 2502, + "2657": 2503, + "2658": 2504, + "2659": 2422, + "2660": 2314, + "2661": 2374, + "2662": 1141, + "2663": 2550, + "2664": 958, + "2665": 2334, + "2666": 883, + "2667": 681, + "2668": 951, + "2669": 886, + "2670": 2235, + "2671": 965, + "2672": 2520, + "2674": 2601, + "2677": 2291, + "2678": 2292, + "2679": 2292, + "2680": 2292, + "2682": 2273, + "2683": 2295, + "2684": 2564, + "2685": 2309, + "2686": 2307, + "2687": 2313, + "2688": 2556, + "2689": 2557, + "2691": 2552, + "2692": 2553, + "2693": 2554, + "2694": 2551, + "2695": 2550, + "2696": 2550, + "2697": 2548, + "2698": 2549, + "2699": 2567, + "2700": 2580, + "2701": 2560, + "2702": 2561, + "2703": 2562, + "2704": 2572, + "2705": 2572, + "2706": 2573, + "2707": 2574, + "2708": 2575, + "2709": 2576, + "2710": 2577, + "2711": 2578, + "2712": 2579, + "2713": 2580, + "2714": 2581, + "2715": 2582, + "2716": 2583, + "2717": 2566, + "2718": 2594, + "2719": 2596, + "2720": 2595, + "2721": 2604, + "2722": 2605, + "2723": 2606, + "2724": 2602, + "2725": 2607, + "2726": 2609, + "2727": 2619, + "2728": 2620, + "2729": 2621, + "2730": 2622, + "2731": 2621, + "2732": 2610, + "2733": 2624, + "2734": 2625, + "2735": 2626, + "2736": 2627, + "2737": 2610, + "2738": 2611, + "2739": 1478, + "2740": 2660, + "2741": 2611, + "2742": 2612, + "2743": 2628, + "2744": 2629, + "2745": 2630, + "2746": 2631, + "2747": 2632, + "2748": 2634, + "2749": 2608, + "2750": 2617, + "2751": 2636, + "2752": 2637, + "2753": 2638, + "2754": 2423, + "2755": 2612, + "2756": 2623, + "2757": 2597, + "2758": 2625, + "2759": 2413, + "2760": 2590, + "2761": 2598, + "2762": 2629, + "2763": 2643, + "2764": 2603, + "2765": 2505, + "2766": 2651, + "2767": 2599, + "2768": 2636, + "2772": 2611, + "2774": 2428, + "2775": 2660, + "2776": 2659, + "2777": 1289, + "2778": 2547, + "2779": 1288, + "2780": 1287, + "2781": 1300, + "2782": 108, + "2783": 2661, + "2784": 2656, + "2785": 1297, + "2786": 2658, + "2787": 2662, + "2788": 2663, + "2789": 1300, + "2790": 2653, + "2791": 2548, + "2792": 2654, + "2793": 2549, + "2794": 2656, + "2795": 2660, + "2796": 2547, + "2797": 2654, + "2798": 1385, + "2799": 2650, + "2800": 2655, + "2801": 2660, + "2802": 2550, + "2803": 2551, + "2804": 2550, + "2805": 2550, + "2806": 2673, + "2807": 2552, + "2808": 2553, + "2809": 2554, + "2810": 2555, + "2811": 2652, + "2812": 2651, + "2813": 2591, + "2814": 2589, + "2815": 2682, + "2816": 2584, + "2817": 2585, + "2818": 2750, + "2819": 2593, + "2820": 2586, + "2821": 2587, + "2822": 2588, + "2823": 2665, + "2824": 2666, + "2825": 2667, + "2826": 2668, + "2827": 2669, + "2828": 2516, + "2829": 1528, + "2830": 374, + "2831": 1343, + "2832": 2538, + "2833": 2528, + "2834": 2529, + "2835": 2530, + "2836": 2531, + "2837": 2532, + "2838": 2522, + "2839": 2725, + "2840": 2698, + "2841": 2706, + "2842": 2722, + "2843": 3101, + "2844": 2737, + "2845": 2746, + "2846": 2709, + "2847": 2725, + "2848": 2672, + "2849": 2710, + "2850": 2723, + "2851": 2546, + "2852": 2868, + "2853": 3021, + "2854": 2684, + "2855": 2685, + "2856": 2702, + "2857": 2448, + "2858": 2680, + "2859": 2681, + "2860": 2719, + "2861": 3106, + "2862": 2677, + "2863": 3022, + "2864": 2686, + "2865": 2686, + "2866": 2686, + "2867": 2716, + "2868": 2717, + "2869": 2718, + "2870": 2715, + "2871": 2702, + "2872": 2749, + "2873": 2741, + "2874": 2723, + "2875": 2570, + "2876": 2725, + "2877": 2670, + "2878": 2738, + "2879": 2739, + "2880": 2740, + "2881": 2687, + "2882": 2708, + "2883": 2699, + "2884": 2713, + "2885": 2714, + "2886": 2735, + "2887": 2734, + "2888": 2736, + "2889": 2727, + "2890": 2678, + "2891": 2679, + "2892": 2680, + "2893": 2678, + "2894": 2679, + "2895": 2681, + "2896": 2680, + "2897": 2681, + "2898": 2682, + "2899": 2695, + "2900": 2695, + "2901": 2696, + "2902": 2719, + "2903": 2726, + "2904": 2681, + "2905": 2679, + "2906": 2680, + "2907": 2678, + "2908": 2679, + "2909": 2680, + "2910": 2741, + "2911": 539, + "2912": 2640, + "2913": 2742, + "2914": 2742, + "2915": 2641, + "2916": 2642, + "2917": 2643, + "2918": 2174, + "2919": 2644, + "2920": 2645, + "2921": 2646, + "2922": 1474, + "2923": 2647, + "2924": 2648, + "2925": 2649, + "2926": 2570, + "2927": 2569, + "2928": 2571, + "2929": 2505, + "2930": 2665, + "2931": 2793, + "2932": 108, + "2933": 2632, + "2934": 2592, + "2935": 2751, + "2936": 2754, + "2937": 2753, + "2938": 2686, + "2939": 2685, + "2940": 2787, + "2941": 2787, + "2942": 2687, + "2943": 2811, + "2944": 2689, + "2945": 2690, + "2946": 725, + "2947": 108, + "2948": 2568, + "2949": 4050, + "2950": 2827, + "2951": 2828, + "2952": 2829, + "2953": 2830, + "2954": 2831, + "2955": 2887, + "2956": 2888, + "2957": 2889, + "2958": 2890, + "2959": 2892, + "2960": 2655, + "2961": 2894, + "2962": 2895, + "2963": 2896, + "2964": 2897, + "2965": 2898, + "2966": 2899, + "2967": 2900, + "2968": 2901, + "2969": 2902, + "2970": 2904, + "2971": 2906, + "2972": 2905, + "2973": 2993, + "2974": 2790, + "2975": 2788, + "2976": 2789, + "2977": 2787, + "2978": 2786, + "2979": 2786, + "2980": 2782, + "2981": 2783, + "2982": 2784, + "2983": 2785, + "2984": 2781, + "2985": 2780, + "2986": 108, + "2987": 2832, + "2988": 2832, + "2989": 2833, + "2990": 2832, + "2991": 2832, + "2992": 2833, + "2993": 2891, + "2994": 2903, + "2995": 2916, + "2996": 2168, + "2997": 2833, + "2998": 2778, + "2999": 2779, + "3000": 2775, + "3001": 2776, + "3002": 2777, + "3003": 2086, + "3004": 2086, + "3005": 2086, + "3006": 2086, + "3007": 2774, + "3008": 2774, + "3009": 2809, + "3010": 2808, + "3011": 2801, + "3012": 2806, + "3013": 2805, + "3014": 2804, + "3015": 2800, + "3016": 2803, + "3017": 2802, + "3018": 2801, + "3019": 2800, + "3020": 2799, + "3021": 2796, + "3022": 2795, + "3023": 2798, + "3024": 2794, + "3025": 2797, + "3026": 2797, + "3027": 2792, + "3028": 2807, + "3029": 2791, + "3030": 2793, + "3031": 2815, + "3032": 2814, + "3033": 2813, + "3034": 2812, + "3035": 2824, + "3036": 2823, + "3037": 2822, + "3038": 108, + "3039": 2825, + "3040": 2821, + "3041": 2820, + "3042": 2819, + "3043": 2818, + "3044": 2817, + "3045": 2816, + "3046": 2826, + "3047": 2886, + "3048": 2970, + "3049": 2851, + "3050": 2852, + "3051": 2854, + "3052": 2853, + "3053": 2855, + "3054": 2856, + "3055": 2830, + "3056": 2857, + "3057": 2858, + "3058": 2859, + "3059": 2860, + "3060": 2861, + "3061": 2756, + "3062": 2758, + "3063": 2759, + "3064": 2760, + "3065": 2761, + "3066": 2762, + "3067": 2763, + "3068": 2764, + "3069": 2765, + "3070": 2766, + "3071": 2767, + "3072": 2768, + "3073": 2769, + "3074": 2770, + "3075": 2772, + "3076": 2771, + "3077": 2773, + "3078": 2810, + "3079": 2834, + "3080": 2836, + "3081": 2835, + "3082": 2837, + "3083": 2743, + "3084": 2839, + "3085": 2840, + "3086": 2841, + "3087": 2842, + "3088": 2843, + "3089": 2844, + "3090": 2845, + "3091": 2846, + "3092": 2847, + "3093": 2848, + "3094": 2849, + "3095": 2850, + "3096": 2884, + "3097": 2885, + "3098": 2823, + "3099": 2168, + "3100": 2994, + "3101": 2872, + "3102": 2873, + "3103": 3218, + "3104": 2995, + "3105": 2994, + "3106": 2994, + "3107": 2994, + "3108": 2189, + "3109": 2189, + "3110": 2754, + "3111": 2753, + "3112": 2892, + "3113": 3045, + "3114": 2868, + "3115": 2868, + "3116": 2869, + "3117": 2870, + "3118": 2903, + "3119": 2875, + "3120": 3021, + "3121": 2862, + "3122": 3182, + "3123": 2971, + "3124": 3022, + "3125": 3034, + "3126": 2914, + "3127": 2915, + "3128": 2704, + "3129": 2927, + "3130": 3063, + "3131": 2609, + "3132": 2619, + "3133": 2620, + "3134": 2621, + "3135": 2622, + "3136": 2623, + "3137": 2621, + "3138": 2610, + "3139": 2624, + "3140": 2625, + "3141": 2626, + "3142": 2627, + "3143": 2610, + "3144": 2611, + "3145": 1478, + "3146": 2611, + "3147": 2612, + "3148": 2628, + "3149": 2629, + "3150": 2630, + "3151": 2631, + "3152": 2632, + "3153": 2634, + "3154": 2635, + "3155": 2636, + "3156": 2637, + "3157": 2638, + "3158": 2612, + "3159": 2632, + "3160": 539, + "3161": 2640, + "3162": 2742, + "3163": 2742, + "3164": 2641, + "3165": 2642, + "3166": 2643, + "3167": 2174, + "3168": 2644, + "3169": 2645, + "3170": 2646, + "3171": 1474, + "3172": 2647, + "3173": 2648, + "3174": 2649, + "3175": 2919, + "3176": 2920, + "3177": 2921, + "3178": 2922, + "3179": 2923, + "3180": 2924, + "3181": 2925, + "3182": 2926, + "3183": 2927, + "3184": 2928, + "3185": 2929, + "3186": 2930, + "3187": 2931, + "3188": 2932, + "3189": 2933, + "3190": 2934, + "3191": 2935, + "3192": 2936, + "3193": 2937, + "3194": 2938, + "3195": 2939, + "3196": 2940, + "3197": 2941, + "3198": 2942, + "3199": 2943, + "3200": 2944, + "3201": 2945, + "3202": 2946, + "3203": 2947, + "3204": 2948, + "3205": 2949, + "3206": 2950, + "3207": 2951, + "3208": 2952, + "3209": 2953, + "3210": 2954, + "3211": 2955, + "3212": 2956, + "3213": 2957, + "3214": 2958, + "3215": 2959, + "3216": 2960, + "3217": 2961, + "3218": 2962, + "3219": 2963, + "3220": 2964, + "3221": 2965, + "3222": 2966, + "3223": 2967, + "3224": 2968, + "3225": 2969, + "3226": 3330, + "3227": 2866, + "3228": 2972, + "3229": 2973, + "3230": 2974, + "3231": 2975, + "3232": 2976, + "3233": 2977, + "3234": 2978, + "3235": 2979, + "3236": 2980, + "3237": 2981, + "3238": 3018, + "3239": 2984, + "3240": 2988, + "3241": 2992, + "3242": 3050, + "3243": 3051, + "3244": 3052, + "3245": 3053, + "3246": 3054, + "3247": 3055, + "3248": 3330, + "3249": 5763, + "3250": 3056, + "3251": 3057, + "3252": 3058, + "3253": 3059, + "3254": 3060, + "3255": 3061, + "3256": 3666, + "3257": 3030, + "3258": 3014, + "3259": 3015, + "3260": 3016, + "3261": 3017, + "3262": 3018, + "3263": 3019, + "3264": 2904, + "3265": 2906, + "3266": 2905, + "3267": 2997, + "3268": 2998, + "3269": 2999, + "3270": 3000, + "3271": 3001, + "3272": 3002, + "3273": 3003, + "3274": 3004, + "3275": 3005, + "3276": 3006, + "3277": 3007, + "3278": 3008, + "3279": 3009, + "3280": 3010, + "3281": 3011, + "3282": 3012, + "3283": 3013, + "3284": 3065, + "3285": 3192, + "3286": 3193, + "3287": 3194, + "3288": 3192, + "3289": 3197, + "3290": 3198, + "3291": 3199, + "3292": 3200, + "3293": 3201, + "3294": 3201, + "3295": 3204, + "3296": 3205, + "3297": 3206, + "3298": 3207, + "3299": 3208, + "3300": 3209, + "3301": 3209, + "3302": 3209, + "3303": 3204, + "3304": 3210, + "3305": 3211, + "3306": 3212, + "3307": 3213, + "3308": 3116, + "3309": 3214, + "3310": 3215, + "3311": 3216, + "3312": 3217, + "3313": 3210, + "3314": 261, + "3315": 267, + "3316": 3190, + "3317": 3191, + "3318": 1467, + "3319": 3196, + "3320": 3195, + "3321": 2810, + "3322": 3240, + "3323": 3242, + "3324": 3069, + "3325": 3070, + "3326": 3062, + "3327": 3063, + "3328": 3064, + "3329": 2994, + "3330": 3218, + "3331": 2995, + "3332": 2994, + "3333": 2994, + "3334": 2994, + "3335": 3038, + "3336": 3014, + "3337": 3039, + "3338": 3040, + "3339": 3041, + "3340": 3043, + "3341": 3042, + "3342": 3044, + "3343": 3044, + "3344": 3045, + "3345": 3072, + "3346": 3073, + "3347": 3074, + "3348": 3071, + "3349": 3075, + "3350": 3066, + "3351": 3067, + "3352": 3068, + "3353": 3028, + "3354": 3288, + "3355": 3030, + "3356": 3032, + "3357": 3037, + "3358": 114, + "3359": 3031, + "3360": 3027, + "3361": 3034, + "3362": 3035, + "3363": 3219, + "3364": 3029, + "3365": 4739, + "3366": 3046, + "3367": 3047, + "3368": 3046, + "3369": 3047, + "3370": 3048, + "3371": 3046, + "3372": 3046, + "3373": 3047, + "3374": 3038, + "3375": 3049, + "3376": 3033, + "3377": 3220, + "3378": 5892, + "3379": 3022, + "3380": 3021, + "3381": 887, + "3382": 1858, + "3383": 1858, + "3384": 887, + "3385": 3026, + "3386": 3076, + "3387": 3164, + "3388": 3169, + "3389": 3172, + "3390": 3168, + "3391": 3163, + "3392": 3162, + "3393": 3164, + "3394": 3129, + "3395": 3130, + "3396": 3131, + "3397": 3045, + "3398": 3133, + "3399": 3134, + "3400": 3135, + "3401": 3136, + "3402": 3137, + "3403": 3159, + "3404": 3160, + "3405": 3045, + "3406": 3047, + "3407": 4613, + "3408": 3139, + "3409": 3140, + "3410": 3141, + "3411": 3133, + "3412": 3142, + "3413": 3138, + "3414": 3129, + "3415": 3143, + "3416": 3144, + "3417": 3145, + "3418": 3146, + "3419": 3133, + "3420": 3129, + "3421": 3148, + "3422": 3147, + "3423": 3149, + "3424": 3272, + "3425": 3273, + "3426": 3274, + "3427": 3275, + "3428": 3276, + "3429": 3277, + "3430": 3236, + "3431": 3279, + "3432": 3280, + "3433": 3281, + "3434": 3282, + "3435": 3283, + "3436": 3284, + "3437": 3285, + "3438": 3286, + "3439": 1695, + "3440": 3248, + "3441": 3255, + "3442": 3256, + "3443": 3257, + "3444": 3258, + "3445": 3259, + "3446": 3260, + "3447": 3261, + "3448": 3262, + "3449": 3263, + "3450": 3264, + "3451": 3265, + "3452": 3266, + "3453": 3267, + "3454": 3268, + "3455": 3269, + "3456": 3270, + "3457": 3271, + "3458": 3150, + "3459": 3151, + "3460": 3152, + "3461": 3133, + "3462": 3153, + "3463": 3154, + "3464": 3155, + "3465": 3156, + "3466": 3159, + "3467": 3157, + "3468": 3158, + "3469": 3189, + "3470": 3160, + "3471": 3133, + "3472": 3138, + "3473": 3129, + "3474": 3165, + "3475": 3164, + "3476": 3166, + "3477": 3167, + "3478": 3170, + "3479": 3166, + "3480": 3167, + "3481": 3165, + "3482": 3164, + "3483": 3169, + "3484": 3243, + "3485": 3244, + "3486": 3246, + "3487": 3245, + "3488": 3247, + "3489": 3248, + "3490": 3249, + "3491": 3250, + "3492": 3381, + "3493": 3252, + "3494": 3119, + "3495": 3120, + "3496": 3121, + "3497": 3122, + "3498": 3123, + "3499": 3124, + "3500": 3125, + "3501": 3126, + "3502": 3110, + "3503": 2120, + "3504": 3114, + "3505": 3111, + "3506": 3112, + "3507": 3113, + "3508": 3118, + "3509": 3115, + "3510": 3116, + "3511": 3117, + "3512": 3127, + "3513": 3128, + "3514": 3132, + "3515": 3221, + "3516": 3152, + "3517": 3161, + "3518": 3165, + "3519": 3167, + "3520": 3164, + "3521": 3170, + "3522": 3172, + "3523": 3172, + "3524": 3173, + "3525": 3210, + "3526": 3213, + "3527": 3172, + "3528": 3172, + "3529": 3171, + "3530": 3091, + "3531": 3092, + "3532": 3093, + "3533": 3209, + "3534": 3095, + "3535": 3096, + "3536": 3097, + "3537": 3098, + "3538": 3077, + "3539": 3078, + "3540": 3079, + "3541": 3080, + "3542": 3081, + "3543": 108, + "3544": 3083, + "3545": 3084, + "3546": 3085, + "3547": 3086, + "3548": 3087, + "3549": 3088, + "3550": 3089, + "3551": 3090, + "3552": 3100, + "3553": 3100, + "3554": 3104, + "3555": 3104, + "3556": 3102, + "3557": 3103, + "3558": 3101, + "3559": 3107, + "3560": 3108, + "3561": 3479, + "3562": 3106, + "3563": 3105, + "3564": 2039, + "3565": 3188, + "3566": 3179, + "3567": 3183, + "3568": 3184, + "3569": 3153, + "3570": 3153, + "3571": 3154, + "3572": 3166, + "3573": 3166, + "3574": 3234, + "3575": 3235, + "3576": 3236, + "3577": 3237, + "3578": 3238, + "3579": 3239, + "3580": 3227, + "3581": 3228, + "3582": 3229, + "3583": 3230, + "3584": 3231, + "3585": 3232, + "3586": 3233, + "3587": 3241, + "3588": 3263, + "3589": 108, + "3590": 108, + "3591": 108, + "3592": 108, + "3593": 108, + "3594": 108, + "3595": 108, + "3596": 108, + "3597": 108, + "3598": 3454, + "3599": 8395, + "3600": 2993, + "3601": 8395, + "3602": 3077, + "3603": 3222, + "3604": 3223, + "3605": 3224, + "3606": 3225, + "3607": 3301, + "3608": 3345, + "3609": 3345, + "3610": 3345, + "3611": 3082, + "3612": 3302, + "3613": 3303, + "3614": 3261, + "3615": 3269, + "3616": 3522, + "3618": 127, + "3619": 3078, + "3620": 2665, + "3621": 2665, + "3622": 3304, + "3623": 3307, + "3624": 3305, + "3625": 3304, + "3626": 3305, + "3627": 3306, + "3628": 3321, + "3629": 3322, + "3630": 3323, + "3631": 3324, + "3632": 3280, + "3633": 3325, + "3634": 3326, + "3635": 3371, + "3636": 3329, + "3637": 2168, + "3638": 3331, + "3639": 3314, + "3640": 3330, + "3641": 3315, + "3642": 3316, + "3643": 3317, + "3644": 3318, + "3645": 3319, + "3646": 3320, + "3647": 3311, + "3648": 3496, + "3649": 3287, + "3650": 3386, + "3651": 3289, + "3652": 3290, + "3653": 3291, + "3654": 3292, + "3655": 3294, + "3656": 3293, + "3657": 3335, + "3658": 3337, + "3659": 3339, + "3660": 3340, + "3661": 3475, + "3662": 3300, + "3663": 3046, + "3664": 108, + "3665": 108, + "3666": 3355, + "3667": 3354, + "3668": 3353, + "3669": 3368, + "3670": 3367, + "3671": 3366, + "3672": 3365, + "3673": 3358, + "3674": 3357, + "3675": 3523, + "3676": 3363, + "3677": 3362, + "3678": 3361, + "3679": 3360, + "3680": 3359, + "3681": 3529, + "3682": 3352, + "3683": 3351, + "3684": 3350, + "3685": 3349, + "3686": 3369, + "3687": 3370, + "3688": 3373, + "3689": 3357, + "3690": 3374, + "3691": 3375, + "3692": 3375, + "3693": 3452, + "3694": 3251, + "3695": 3362, + "3696": 3361, + "3697": 3360, + "3698": 3359, + "3699": 3298, + "3700": 3298, + "3701": 3378, + "3702": 3372, + "3703": 3371, + "3704": 3095, + "3705": 73793675, + "3706": 108, + "3707": 3374, + "3708": 3370, + "3709": 2665, + "3710": 3445, + "3711": 108, + "3712": 3331, + "3713": 4685, + "3714": 3923, + "3715": 3925, + "3716": 3930, + "3717": 3931, + "3718": 3932, + "3719": 3933, + "3720": 3789, + "3721": 3405, + "3722": 3406, + "3723": 3407, + "3724": 3408, + "3725": 3409, + "3726": 3410, + "3727": 3791, + "3728": 3487, + "3729": 3793, + "3730": 3794, + "3731": 3620, + "3732": 3796, + "3733": 3797, + "3734": 3798, + "3735": 3818, + "3736": 3819, + "3737": 3820, + "3738": 3821, + "3739": 2143, + "3740": 3822, + "3741": 4383, + "3742": 4384, + "3743": 3823, + "3744": 4382, + "3745": 4383, + "3746": 4384, + "3747": 3293, + "3748": 3930, + "3749": 2343, + "3750": 3452, + "3751": 3453, + "3752": 3454, + "3753": 3455, + "3754": 3456, + "3755": 3457, + "3756": 3458, + "3757": 3459, + "3758": 3460, + "3759": 3461, + "3760": 3462, + "3761": 3463, + "3762": 3464, + "3763": 3465, + "3764": 3660, + "3765": 3660, + "3766": 3661, + "3767": 3661, + "3768": 3662, + "3769": 3662, + "3770": 3663, + "3771": 3663, + "3772": 3664, + "3773": 3664, + "3774": 3745, + "3775": 3746, + "3776": 3747, + "3777": 3748, + "3778": 3749, + "3779": 3748, + "3780": 4492, + "3781": 4420, + "3782": 1385, + "3783": 4133, + "3784": 3735, + "3785": 3921, + "3786": 3918, + "3787": 3910, + "3788": 3922, + "3789": 3913, + "3790": 3912, + "3791": 3915, + "3792": 3916, + "3793": 3911, + "3794": 3917, + "3795": 3920, + "3796": 3909, + "3797": 3914, + "3798": 3923, + "3799": 3460, + "3800": 243, + "3801": 3865, + "3802": 3388, + "3803": 3389, + "3804": 3390, + "3805": 3391, + "3806": 3392, + "3807": 3393, + "3808": 3394, + "3809": 3395, + "3810": 3396, + "3811": 3397, + "3812": 3398, + "3813": 3399, + "3814": 3400, + "3815": 3401, + "3816": 3402, + "3817": 3403, + "3818": 3404, + "3819": 3409, + "3820": 3649, + "3821": 3649, + "3822": 4606, + "3823": 108, + "3824": 3650, + "3825": 3651, + "3826": 3652, + "3827": 3653, + "3828": 3654, + "3829": 3655, + "3830": 3658, + "3831": 3568, + "3832": 3649, + "3833": 3649, + "3834": 3650, + "3835": 8144, + "3836": 3652, + "3837": 3653, + "3838": 3654, + "3839": 3658, + "3840": 3655, + "3841": 3754, + "3842": 3755, + "3843": 4142, + "3844": 4490, + "3845": 1300, + "3846": 3753, + "3847": 3757, + "3848": 8145, + "3849": 3758, + "3850": 3759, + "3851": 3760, + "3852": 3761, + "3853": 2667, + "3854": 3978, + "3855": 3758, + "3856": 3754, + "3857": 3755, + "3858": 3753, + "3859": 3757, + "3860": 8146, + "3861": 3758, + "3862": 3759, + "3863": 3760, + "3864": 3761, + "3865": 2667, + "3866": 3546, + "3867": 4049, + "3868": 3818, + "3869": 3799, + "3870": 3800, + "3871": 3801, + "3872": 3802, + "3873": 3803, + "3874": 3804, + "3875": 3577, + "3876": 3805, + "3877": 3807, + "3878": 3808, + "3879": 3815, + "3880": 3809, + "3881": 3816, + "3882": 3810, + "3883": 3811, + "3884": 3812, + "3885": 3026, + "3886": 3813, + "3887": 3814, + "3888": 3806, + "3889": 3815, + "3890": 3816, + "3891": 4101, + "3892": 3772, + "3893": 3772, + "3894": 3773, + "3895": 3778, + "3896": 3779, + "3897": 3774, + "3898": 3775, + "3899": 3759, + "3900": 3776, + "3901": 3777, + "3902": 3772, + "3903": 3772, + "3904": 3773, + "3905": 3778, + "3906": 3774, + "3907": 3759, + "3908": 6305, + "3909": 4259, + "3910": 3500, + "3911": 3824, + "3912": 3825, + "3913": 3826, + "3914": 3827, + "3915": 3828, + "3916": 3829, + "3917": 3830, + "3918": 3831, + "3919": 3832, + "3920": 3833, + "3921": 3834, + "3922": 4336, + "3923": 3835, + "3924": 3836, + "3925": 3837, + "3926": 3838, + "3927": 3839, + "3928": 3840, + "3929": 4340, + "3930": 4339, + "3931": 3818, + "3932": 3825, + "3933": 4489, + "3934": 3765, + "3935": 3999, + "3936": 3378, + "3937": 3766, + "3938": 3766, + "3939": 8958, + "3940": 3767, + "3941": 3770, + "3942": 3769, + "3943": 3771, + "3944": 3768, + "3945": 3765, + "3946": 4141, + "3947": 3726, + "3948": 3372, + "3949": 2751, + "3950": 3119, + "3951": 3120, + "3952": 4135, + "3953": 4136, + "3954": 4137, + "3955": 4138, + "3956": 3721, + "3957": 3723, + "3958": 3724, + "3959": 3722, + "3960": 3731, + "3961": 3732, + "3962": 3733, + "3963": 3736, + "3964": 3737, + "3965": 108, + "3966": 3739, + "3967": 3278, + "3968": 3727, + "3969": 3728, + "3970": 3734, + "3971": 3740, + "3972": 3741, + "3973": 3742, + "3974": 4130, + "3975": 3127, + "3976": 4139, + "3977": 4140, + "3978": 2064, + "3979": 4116, + "3980": 4125, + "3981": 4117, + "3982": 4126, + "3983": 4130, + "3984": 1394, + "3985": 4116, + "3986": 3489, + "3987": 3573, + "3988": 3479, + "3989": 3575, + "3990": 3488, + "3991": 3492, + "3992": 3483, + "3993": 3485, + "3994": 3584, + "3995": 3893, + "3996": 3484, + "3997": 3487, + "3998": 3486, + "3999": 3670, + "4000": 3900, + "4001": 4049, + "4002": 3901, + "4003": 4337, + "4004": 4338, + "4005": 4390, + "4006": 3581, + "4007": 3577, + "4008": 3688, + "4009": 3691, + "4010": 3585, + "4011": 3564, + "4012": 3696, + "4013": 3693, + "4014": 3580, + "4015": 4284, + "4016": 4070, + "4017": 3597, + "4018": 3715, + "4019": 3945, + "4020": 3712, + "4021": 3611, + "4022": 3520, + "4023": 3612, + "4024": 3714, + "4025": 3710, + "4026": 3610, + "4027": 3713, + "4028": 3711, + "4029": 3606, + "4030": 3599, + "4031": 3707, + "4032": 3708, + "4033": 3709, + "4034": 56, + "4035": 3609, + "4036": 3977, + "4037": 4045, + "4038": 3613, + "4039": 4277, + "4040": 3559, + "4041": 3700, + "4042": 3701, + "4043": 3630, + "4044": 4294, + "4045": 4291, + "4046": 3542, + "4047": 117, + "4048": 3526, + "4049": 3703, + "4050": 3512, + "4051": 3501, + "4052": 4061, + "4053": 3503, + "4054": 3705, + "4055": 4059, + "4056": 4071, + "4057": 3674, + "4058": 3672, + "4059": 3509, + "4060": 4288, + "4061": 4283, + "4062": 3611, + "4063": 3673, + "4064": 4293, + "4065": 3654, + "4066": 3702, + "4067": 3649, + "4068": 3513, + "4069": 3675, + "4070": 3525, + "4071": 3544, + "4072": 3541, + "4073": 3660, + "4074": 3727, + "4075": 3554, + "4076": 3698, + "4077": 3651, + "4078": 3623, + "4079": 3555, + "4080": 3556, + "4081": 3537, + "4082": 3625, + "4083": 3552, + "4084": 4399, + "4085": 3538, + "4086": 3539, + "4087": 3543, + "4088": 3561, + "4089": 3551, + "4090": 3534, + "4091": 3535, + "4092": 3536, + "4093": 3532, + "4094": 3669, + "4095": 3557, + "4096": 4128, + "4097": 3502, + "4098": 3503, + "4099": 4129, + "4100": 2082, + "4101": 1990, + "4102": 108, + "4103": 4346, + "4104": 4347, + "4105": 4348, + "4106": 4349, + "4107": 4346, + "4108": 4347, + "4109": 4348, + "4110": 4349, + "4111": 4130, + "4112": 3850, + "4113": 4131, + "4114": 3428, + "4115": 3429, + "4116": 3430, + "4117": 3431, + "4118": 3432, + "4119": 3433, + "4120": 3434, + "4121": 3435, + "4122": 3436, + "4123": 3411, + "4124": 3412, + "4125": 3413, + "4126": 3414, + "4127": 3415, + "4128": 3416, + "4129": 3417, + "4130": 3418, + "4131": 3419, + "4132": 3420, + "4133": 3421, + "4134": 3422, + "4135": 3423, + "4136": 3424, + "4137": 3425, + "4138": 3426, + "4139": 3427, + "4140": 4132, + "4141": 3540, + "4142": 3586, + "4143": 3599, + "4144": 3817, + "4145": 4154, + "4146": 4154, + "4147": 1391, + "4148": 4155, + "4149": 4156, + "4150": 4157, + "4151": 4145, + "4152": 4158, + "4153": 4159, + "4154": 4160, + "4155": 4161, + "4156": 4162, + "4157": 1392, + "4158": 4150, + "4159": 4151, + "4160": 4152, + "4161": 4153, + "4162": 4130, + "4163": 1394, + "4164": 4130, + "4165": 4179, + "4166": 3690, + "4167": 4130, + "4168": 2082, + "4169": 4144, + "4170": 2077, + "4171": 4143, + "4172": 2080, + "4173": 2076, + "4174": 3849, + "4175": 3841, + "4176": 3843, + "4177": 3634, + "4178": 4385, + "4179": 3850, + "4180": 3639, + "4181": 3293, + "4182": 3642, + "4183": 3851, + "4184": 3852, + "4185": 4400, + "4186": 3841, + "4187": 3841, + "4188": 3319, + "4189": 3319, + "4190": 4401, + "4191": 3841, + "4192": 3841, + "4193": 3842, + "4194": 3842, + "4195": 3843, + "4196": 3843, + "4197": 3844, + "4198": 3845, + "4199": 3846, + "4200": 3847, + "4201": 3848, + "4202": 2234, + "4203": 4148, + "4204": 4147, + "4205": 4146, + "4206": 2098, + "4207": 2099, + "4208": 1453, + "4209": 4427, + "4210": 4178, + "4211": 3632, + "4212": 3633, + "4213": 3634, + "4214": 3635, + "4215": 3636, + "4216": 3637, + "4217": 3638, + "4218": 3639, + "4219": 3640, + "4220": 3641, + "4221": 3642, + "4222": 3643, + "4223": 3644, + "4224": 3645, + "4225": 4385, + "4226": 4386, + "4227": 4387, + "4228": 3641, + "4229": 3223, + "4230": 3224, + "4231": 1848, + "4232": 4173, + "4233": 4174, + "4234": 2347, + "4235": 4180, + "4236": 4185, + "4237": 4184, + "4238": 4186, + "4239": 4187, + "4240": 3438, + "4241": 3439, + "4242": 3440, + "4243": 3441, + "4244": 3442, + "4245": 3443, + "4246": 3445, + "4247": 3446, + "4248": 3447, + "4249": 3448, + "4250": 3449, + "4251": 3450, + "4252": 3451, + "4253": 3445, + "4254": 4188, + "4255": 1422, + "4256": 1423, + "4257": 3665, + "4258": 3665, + "4259": 4381, + "4260": 4163, + "4261": 4164, + "4262": 4165, + "4263": 4166, + "4264": 4167, + "4265": 4168, + "4266": 4109, + "4267": 4169, + "4268": 4170, + "4269": 4171, + "4270": 4172, + "4271": 4426, + "4272": 4342, + "4273": 4343, + "4274": 4344, + "4275": 4345, + "4276": 4388, + "4277": 4389, + "4278": 3919, + "4279": 3915, + "4280": 3864, + "4281": 4190, + "4282": 4190, + "4283": 4191, + "4284": 3045, + "4285": 4192, + "4286": 4193, + "4287": 365, + "4288": 398, + "4289": 106, + "4290": 117, + "4291": 4194, + "4292": 3929, + "4293": 3928, + "4294": 4195, + "4295": 4196, + "4296": 407, + "4297": 171, + "4298": 45, + "4299": 170, + "4300": 24, + "4301": 3854, + "4302": 3855, + "4303": 3856, + "4304": 3857, + "4305": 4424, + "4306": 3859, + "4307": 3860, + "4308": 3861, + "4309": 3862, + "4310": 3863, + "4311": 114, + "4312": 3476, + "4313": 3475, + "4314": 3478, + "4315": 3743, + "4316": 4116, + "4317": 4423, + "4318": 4126, + "4319": 4127, + "4320": 4197, + "4321": 4200, + "4322": 4201, + "4323": 4202, + "4324": 1440, + "4325": 4203, + "4326": 3888, + "4327": 4193, + "4328": 4204, + "4329": 4000, + "4330": 2147, + "4331": 4107, + "4332": 4173, + "4333": 4174, + "4334": 2096, + "4335": 4175, + "4336": 4176, + "4337": 1391, + "4338": 1392, + "4339": 3653, + "4340": 1393, + "4341": 1990, + "4342": 4184, + "4343": 4181, + "4344": 4182, + "4345": 4183, + "4346": 445, + "4347": 4189, + "4348": 3338, + "4349": 3326, + "4350": 3339, + "4351": 4193, + "4352": 4205, + "4353": 4206, + "4354": 4207, + "4355": 4208, + "4356": 4209, + "4357": 4220, + "4358": 4221, + "4359": 4222, + "4360": 4117, + "4361": 4101, + "4362": 4102, + "4363": 4035, + "4364": 4393, + "4365": 3902, + "4366": 3901, + "4367": 3900, + "4368": 3901, + "4369": 3902, + "4370": 3901, + "4371": 4109, + "4372": 3571, + "4373": 4100, + "4374": 4112, + "4375": 3908, + "4376": 3893, + "4377": 4123, + "4378": 4123, + "4379": 3894, + "4380": 3896, + "4381": 3895, + "4382": 3897, + "4383": 3898, + "4384": 3899, + "4385": 3900, + "4386": 3901, + "4387": 3901, + "4388": 3900, + "4389": 3900, + "4390": 3902, + "4391": 4030, + "4392": 4031, + "4393": 4032, + "4394": 4030, + "4395": 4033, + "4396": 4031, + "4397": 4034, + "4398": 4035, + "4399": 4107, + "4400": 4110, + "4401": 4111, + "4402": 4103, + "4403": 4104, + "4404": 4105, + "4405": 4106, + "4406": 3729, + "4407": 3730, + "4408": 3562, + "4409": 6560, + "4410": 6544, + "4411": 6560, + "4412": 6544, + "4413": 6159, + "4414": 6654, + "4415": 6502, + "4416": 6655, + "4417": 5660, + "4418": 6653, + "4419": 4402, + "4420": 108, + "4421": 3656, + "4422": 3657, + "4423": 3656, + "4424": 3657, + "4425": 2085, + "4426": 2086, + "4427": 4269, + "4428": 4270, + "4429": 4271, + "4430": 4272, + "4431": 2086, + "4432": 3763, + "4433": 3762, + "4434": 3764, + "4435": 4193, + "4436": 4192, + "4437": 4204, + "4438": 4209, + "4439": 4212, + "4440": 4223, + "4441": 4224, + "4442": 3339, + "4443": 4225, + "4444": 4220, + "4445": 4149, + "4446": 4392, + "4447": 9374, + "4448": 3745, + "4449": 3746, + "4450": 3747, + "4451": 3748, + "4452": 3749, + "4453": 3748, + "4454": 3493, + "4455": 3761, + "4456": 2667, + "4457": 4612, + "4458": 3602, + "4459": 3599, + "4460": 3600, + "4461": 3601, + "4462": 729, + "4463": 4130, + "4464": 4408, + "4465": 3694, + "4466": 3695, + "4467": 3570, + "4468": 657, + "4469": 3630, + "4470": 4043, + "4471": 3894, + "4472": 3178, + "4473": 3177, + "4474": 3949, + "4475": 3636, + "4476": 4113, + "4477": 4113, + "4478": 4085, + "4479": 3907, + "4480": 4287, + "4481": 3906, + "4482": 4089, + "4483": 4078, + "4484": 4062, + "4485": 4280, + "4486": 4087, + "4487": 4076, + "4488": 3904, + "4489": 3617, + "4490": 3905, + "4491": 3905, + "4492": 4047, + "4493": 4073, + "4494": 3623, + "4495": 3623, + "4496": 3623, + "4497": 4302, + "4498": 4279, + "4499": 4281, + "4500": 4063, + "4501": 4304, + "4502": 4303, + "4503": 4072, + "4504": 4086, + "4505": 4295, + "4506": 4298, + "4507": 4299, + "4508": 4236, + "4509": 4237, + "4510": 4238, + "4511": 4239, + "4512": 4324, + "4513": 4325, + "4514": 4326, + "4515": 4327, + "4516": 4328, + "4517": 4329, + "4518": 4330, + "4519": 4331, + "4520": 1808, + "4521": 4233, + "4522": 4234, + "4523": 3508, + "4524": 3558, + "4525": 3751, + "4526": 3469, + "4527": 4350, + "4528": 4351, + "4529": 4352, + "4530": 4353, + "4531": 4354, + "4532": 4355, + "4533": 4356, + "4534": 4357, + "4535": 4358, + "4536": 4359, + "4537": 4360, + "4538": 4361, + "4539": 4362, + "4540": 4363, + "4541": 4364, + "4542": 4365, + "4543": 4366, + "4544": 4367, + "4545": 4368, + "4546": 4369, + "4547": 4370, + "4548": 4371, + "4549": 4372, + "4550": 4373, + "4551": 4374, + "4552": 4375, + "4553": 4376, + "4554": 4377, + "4555": 4378, + "4556": 4380, + "4557": 729, + "4558": 4231, + "4559": 1893, + "4560": 1895, + "4561": 4232, + "4562": 2145, + "4563": 4099, + "4564": 1416, + "4565": 4226, + "4566": 4227, + "4567": 2204, + "4568": 4235, + "4569": 4236, + "4570": 4237, + "4571": 108, + "4572": 4316, + "4573": 4317, + "4574": 4318, + "4575": 4319, + "4576": 6697, + "4577": 3164, + "4578": 4241, + "4579": 4243, + "4580": 3171, + "4581": 3170, + "4582": 4493, + "4583": 3860, + "4584": 3861, + "4585": 4247, + "4586": 4247, + "4587": 4248, + "4588": 3863, + "4589": 4254, + "4590": 3860, + "4591": 3861, + "4592": 4253, + "4593": 4253, + "4594": 4253, + "4595": 3858, + "4596": 4255, + "4597": 3860, + "4598": 3861, + "4599": 3870, + "4600": 4249, + "4601": 4250, + "4602": 4421, + "4603": 794, + "4604": 1849, + "4605": 108, + "4606": 4491, + "4607": 4250, + "4608": 4251, + "4609": 3660, + "4610": 3660, + "4611": 4251, + "4613": 4436, + "4614": 4029, + "4615": 4093, + "4616": 4090, + "4617": 4335, + "4618": 4041, + "4619": 4123, + "4620": 4038, + "4621": 4056, + "4622": 3741, + "4623": 4029, + "4624": 4036, + "4625": 4037, + "4626": 4039, + "4627": 4095, + "4628": 108, + "4629": 3725, + "4630": 3553, + "4631": 3669, + "4632": 4192, + "4633": 3164, + "4634": 4251, + "4635": 4242, + "4636": 4243, + "4637": 4244, + "4638": 4091, + "4639": 4245, + "4640": 4246, + "4641": 3171, + "4642": 3170, + "4643": 4256, + "4644": 4257, + "4645": 2077, + "4646": 2080, + "4647": 2076, + "4648": 4258, + "4649": 4259, + "4650": 4228, + "4651": 2204, + "4652": 4229, + "4653": 4230, + "4654": 1416, + "4655": 4226, + "4656": 4227, + "4657": 4379, + "4658": 4193, + "4659": 4204, + "4660": 4209, + "4661": 4210, + "4662": 4211, + "4663": 4212, + "4664": 4212, + "4665": 3888, + "4666": 1990, + "4667": 4203, + "4668": 3697, + "4669": 3518, + "4670": 3519, + "4671": 3520, + "4672": 3549, + "4673": 3522, + "4674": 4228, + "4675": 4312, + "4676": 4582, + "4677": 4081, + "4678": 4394, + "4679": 4395, + "4680": 4075, + "4681": 4077, + "4682": 4077, + "4683": 4080, + "4684": 4074, + "4685": 4311, + "4686": 4096, + "4687": 4098, + "4688": 4099, + "4689": 4081, + "4690": 4082, + "4691": 4083, + "4692": 4084, + "4693": 4119, + "4694": 4120, + "4695": 4121, + "4696": 787, + "4697": 2086, + "4698": 4218, + "4699": 4214, + "4700": 4213, + "4701": 4216, + "4702": 4219, + "4703": 4215, + "4704": 4217, + "4705": 3860, + "4706": 3861, + "4707": 3870, + "4708": 3871, + "4709": 3872, + "4710": 3873, + "4711": 3874, + "4712": 3875, + "4713": 3876, + "4714": 3877, + "4715": 3878, + "4716": 3879, + "4717": 3880, + "4718": 1724, + "4719": 4260, + "4720": 4261, + "4721": 4262, + "4722": 4264, + "4723": 4259, + "4724": 108, + "4725": 4265, + "4726": 4266, + "4727": 4267, + "4728": 4259, + "4729": 4322, + "4730": 3318, + "4731": 3317, + "4732": 4323, + "4733": 4321, + "4734": 108, + "4735": 4322, + "4736": 4322, + "4737": 4322, + "4738": 4322, + "4739": 4333, + "4740": 4333, + "4741": 3319, + "4742": 3319, + "4743": 3317, + "4744": 3317, + "4745": 4323, + "4746": 4332, + "4747": 4331, + "4748": 4321, + "4749": 3888, + "4750": 3773, + "4751": 3959, + "4752": 3960, + "4753": 3738, + "4754": 3751, + "4755": 3957, + "4756": 3956, + "4757": 3955, + "4758": 4412, + "4759": 3949, + "4760": 3953, + "4761": 3711, + "4762": 4417, + "4763": 3950, + "4764": 3948, + "4765": 3952, + "4766": 3861, + "4767": 3860, + "4768": 3864, + "4769": 4425, + "4770": 1400, + "4771": 3865, + "4772": 3129, + "4773": 3866, + "4774": 3867, + "4775": 3868, + "4776": 3869, + "4777": 4313, + "4778": 4313, + "4779": 4300, + "4780": 5533, + "4781": 4314, + "4782": 4055, + "4783": 4066, + "4784": 4065, + "4785": 4051, + "4786": 4315, + "4787": 4124, + "4788": 1402, + "4789": 3887, + "4790": 3892, + "4791": 3890, + "4792": 3891, + "4793": 3965, + "4794": 3964, + "4795": 3983, + "4796": 3962, + "4797": 3946, + "4798": 3783, + "4799": 4455, + "4800": 3902, + "4801": 114, + "4802": 3474, + "4803": 3684, + "4804": 3488, + "4805": 3685, + "4806": 3470, + "4807": 3476, + "4808": 3477, + "4809": 3472, + "4810": 3682, + "4811": 4406, + "4812": 4011, + "4813": 3494, + "4814": 3497, + "4815": 3496, + "4816": 3498, + "4817": 56, + "4818": 3481, + "4819": 4012, + "4820": 3944, + "4821": 3943, + "4822": 3495, + "4823": 3942, + "4824": 3941, + "4825": 3940, + "4826": 3939, + "4827": 3498, + "4828": 3938, + "4829": 3936, + "4830": 3935, + "4831": 3934, + "4832": 1640, + "4833": 3881, + "4834": 3882, + "4835": 3883, + "4836": 3884, + "4837": 3885, + "4838": 3886, + "4839": 4192, + "4840": 3477, + "4841": 3474, + "4842": 3952, + "4843": 3659, + "4844": 4377, + "4845": 3781, + "4846": 3410, + "4847": 3410, + "4848": 3945, + "4849": 4444, + "4850": 3982, + "4851": 3981, + "4852": 3980, + "4853": 3984, + "4854": 3984, + "4855": 3979, + "4856": 3978, + "4857": 3975, + "4858": 3974, + "4859": 3530, + "4860": 3973, + "4861": 3972, + "4862": 3971, + "4863": 3970, + "4864": 3969, + "4865": 3968, + "4866": 3967, + "4867": 108, + "4868": 4419, + "4869": 3968, + "4870": 538, + "4871": 4009, + "4872": 4008, + "4873": 4006, + "4874": 113, + "4875": 4002, + "4876": 4003, + "4877": 4418, + "4878": 4000, + "4879": 3999, + "4880": 3998, + "4881": 3997, + "4882": 4405, + "4883": 4404, + "4884": 4403, + "4885": 3996, + "4886": 3564, + "4887": 3993, + "4888": 3992, + "4889": 3990, + "4890": 3988, + "4891": 3988, + "4892": 3987, + "4893": 3986, + "4894": 3985, + "4895": 1640, + "4896": 3881, + "4897": 3882, + "4898": 1402, + "4899": 1403, + "4900": 1404, + "4901": 1402, + "4902": 1403, + "4903": 1404, + "4904": 3882, + "4905": 3789, + "4906": 3780, + "4907": 108, + "4908": 3780, + "4909": 3765, + "4910": 3766, + "4911": 3770, + "4912": 3769, + "4913": 3768, + "4914": 3765, + "4915": 108, + "4916": 108, + "4917": 3660, + "4918": 3660, + "4919": 3753, + "4920": 3752, + "4921": 3758, + "4922": 115, + "4923": 3605, + "4924": 163, + "4925": 3716, + "4926": 3717, + "4927": 3718, + "4928": 3719, + "4929": 3720, + "4930": 3679, + "4931": 3679, + "4932": 3686, + "4933": 3686, + "4934": 3689, + "4935": 3687, + "4936": 3692, + "4937": 3692, + "4938": 3701, + "4939": 3709, + "4940": 2838, + "4941": 3773, + "4942": 3853, + "4943": 3853, + "4944": 4341, + "4945": 4398, + "4946": 4428, + "4947": 4429, + "4948": 4430, + "4949": 4431, + "4950": 4432, + "4951": 4433, + "4952": 4434, + "4953": 4435, + "4954": 4436, + "4955": 4437, + "4956": 4438, + "4957": 4439, + "4958": 4440, + "4959": 4441, + "4960": 4442, + "4961": 4443, + "4962": 4444, + "4963": 4445, + "4964": 4446, + "4965": 4447, + "4966": 4448, + "4967": 4449, + "4968": 4450, + "4969": 4451, + "4970": 4452, + "4971": 4453, + "4972": 4454, + "4973": 4455, + "4974": 4456, + "4975": 4457, + "4976": 4458, + "4977": 4459, + "4978": 4460, + "4979": 4461, + "4980": 4462, + "4981": 4463, + "4982": 4464, + "4983": 4465, + "4984": 4466, + "4985": 4467, + "4986": 4468, + "4987": 4469, + "4988": 4470, + "4989": 4471, + "4990": 4472, + "4991": 4473, + "4992": 4474, + "4993": 4475, + "4994": 4476, + "4995": 4477, + "4996": 4478, + "4997": 4479, + "4998": 4480, + "4999": 4481, + "5000": 4482, + "5001": 4483, + "5002": 4484, + "5003": 4485, + "5004": 4486, + "5005": 4487, + "5006": 4488, + "5007": 4897, + "5008": 5046, + "5009": 5047, + "5010": 4026, + "5011": 4025, + "5012": 4024, + "5013": 4023, + "5014": 4022, + "5015": 4021, + "5016": 4020, + "5017": 4019, + "5018": 4017, + "5019": 4016, + "5020": 4015, + "5021": 4014, + "5022": 4013, + "5023": 4243, + "5024": 4243, + "5025": 4243, + "5026": 4243, + "5027": 4010, + "5028": 4397, + "5029": 114, + "5030": 795, + "5031": 3410, + "5032": 3410, + "5033": 3410, + "5034": 4239, + "5035": 108, + "5036": 3789, + "5037": 731, + "5038": 3790, + "5039": 4034, + "5040": 3181, + "5041": 4115, + "5042": 4305, + "5043": 1895, + "5044": 4123, + "5045": 4123, + "5046": 1239, + "5047": 4422, + "5048": 1240, + "5049": 4308, + "5050": 4143, + "5051": 4067, + "5052": 4282, + "5053": 4027, + "5054": 4028, + "5055": 3738, + "5056": 4415, + "5057": 3949, + "5058": 3444, + "5059": 3655, + "5060": 4414, + "5061": 4413, + "5062": 3743, + "5063": 3784, + "5064": 303, + "5065": 4411, + "5066": 4007, + "5067": 4205, + "5069": 3676, + "5070": 3677, + "5071": 3678, + "5072": 3681, + "5073": 3683, + "5074": 3660, + "5075": 3660, + "5076": 108, + "5077": 3987, + "5078": 4560, + "5079": 4561, + "5080": 4562, + "5081": 274, + "5082": 3667, + "5083": 3915, + "5084": 4347, + "5085": 3692, + "5086": 4197, + "5087": 2901, + "5088": 4570, + "5089": 4571, + "5090": 4200, + "5091": 4573, + "5093": 4084, + "5094": 287, + "5095": 3951, + "5096": 4189, + "5097": 3983, + "5098": 116, + "5099": 113, + "5100": 114, + "5101": 3961, + "5102": 4409, + "5103": 4624, + "5104": 4624, + "5105": 4623, + "5106": 4625, + "5107": 4631, + "5108": 4632, + "5109": 4633, + "5110": 4635, + "5111": 4613, + "5112": 4609, + "5113": 4610, + "5114": 4612, + "5115": 4613, + "5116": 3494, + "5117": 4607, + "5118": 4608, + "5119": 4609, + "5120": 4611, + "5121": 108, + "5122": 4551, + "5123": 4552, + "5124": 4553, + "5125": 4554, + "5126": 4568, + "5127": 4555, + "5128": 4556, + "5129": 4557, + "5130": 4558, + "5131": 4559, + "5132": 4560, + "5133": 4561, + "5134": 4562, + "5135": 4563, + "5136": 4564, + "5137": 4565, + "5138": 4566, + "5139": 4626, + "5140": 4627, + "5141": 4630, + "5142": 4628, + "5143": 4629, + "5144": 4626, + "5145": 2564, + "5146": 4622, + "5147": 4620, + "5148": 4621, + "5149": 3527, + "5150": 4636, + "5151": 4637, + "5152": 4638, + "5153": 4639, + "5154": 4640, + "5155": 4641, + "5156": 4642, + "5157": 4643, + "5158": 4644, + "5159": 4645, + "5160": 4646, + "5161": 4646, + "5162": 4647, + "5163": 4648, + "5164": 4649, + "5165": 4650, + "5166": 4651, + "5167": 4653, + "5168": 4654, + "5169": 4655, + "5170": 4656, + "5171": 4657, + "5172": 4658, + "5173": 4659, + "5174": 4660, + "5175": 4665, + "5176": 4666, + "5177": 4667, + "5178": 4568, + "5179": 4568, + "5180": 4567, + "5181": 4568, + "5182": 4568, + "5183": 4569, + "5184": 4570, + "5185": 4571, + "5186": 4451, + "5187": 4572, + "5188": 4573, + "5189": 4574, + "5190": 4570, + "5191": 4575, + "5192": 4576, + "5193": 4577, + "5194": 4578, + "5195": 4579, + "5196": 4580, + "5197": 108, + "5198": 4614, + "5199": 4616, + "5200": 4619, + "5201": 4617, + "5202": 4618, + "5203": 3632, + "5204": 3633, + "5205": 3634, + "5206": 3635, + "5207": 3636, + "5208": 3637, + "5209": 3638, + "5210": 3639, + "5211": 3640, + "5212": 3641, + "5213": 3642, + "5214": 3643, + "5215": 3644, + "5216": 3645, + "5217": 4386, + "5218": 4387, + "5219": 3645, + "5220": 4634, + "5221": 4601, + "5222": 4217, + "5223": 4610, + "5224": 4084, + "5225": 4611, + "5226": 4612, + "5227": 4611, + "5228": 139, + "5229": 4614, + "5230": 4652, + "5231": 10808, + "5232": 4583, + "5233": 4584, + "5234": 4585, + "5235": 4587, + "5236": 4586, + "5237": 4603, + "5238": 4588, + "5239": 4589, + "5240": 4590, + "5241": 4591, + "5242": 4682, + "5243": 4593, + "5244": 4594, + "5245": 4562, + "5246": 4581, + "5247": 4563, + "5248": 10826, + "5249": 4556, + "5250": 4739, + "5251": 265, + "5252": 4666, + "5253": 4671, + "5254": 4672, + "5255": 4673, + "5256": 4597, + "5257": 3841, + "5258": 3841, + "5259": 4401, + "5260": 3843, + "5261": 4401, + "5262": 3842, + "5263": 3842, + "5264": 3843, + "5265": 3843, + "5266": 4598, + "5267": 4599, + "5268": 4130, + "5269": 729, + "5270": 713, + "5271": 4595, + "5272": 4596, + "5273": 4670, + "5274": 3852, + "5275": 4607, + "5276": 4593, + "5277": 4139, + "5278": 4594, + "5279": 6595, + "5280": 4587, + "5281": 4799, + "5282": 4801, + "5283": 4807, + "5284": 4808, + "5285": 3698, + "5286": 300, + "5287": 4604, + "5288": 4785, + "5289": 4605, + "5290": 4788, + "5291": 4307, + "5292": 4646, + "5293": 4682, + "5294": 4646, + "5295": 4682, + "5296": 4682, + "5297": 4683, + "5298": 4684, + "5299": 4685, + "5300": 4686, + "5301": 4686, + "5302": 4687, + "5303": 4688, + "5304": 4684, + "5305": 4612, + "5306": 4690, + "5307": 4691, + "5308": 4660, + "5309": 4693, + "5310": 4600, + "5311": 4602, + "5312": 4602, + "5313": 4600, + "5314": 4601, + "5315": 4600, + "5316": 4485, + "5317": 4653, + "5318": 4654, + "5319": 3842, + "5320": 108, + "5321": 4578, + "5322": 108, + "5323": 4610, + "5324": 4631, + "5325": 4812, + "5326": 4813, + "5327": 4744, + "5328": 4839, + "5329": 4745, + "5330": 4746, + "5331": 4747, + "5332": 4748, + "5333": 4749, + "5334": 4750, + "5335": 4751, + "5336": 4752, + "5337": 4753, + "5338": 4754, + "5339": 4755, + "5340": 4756, + "5341": 4757, + "5342": 4758, + "5343": 4759, + "5344": 4760, + "5345": 4761, + "5346": 4776, + "5347": 4776, + "5348": 4777, + "5349": 4778, + "5350": 4779, + "5351": 4780, + "5352": 4776, + "5353": 4687, + "5354": 3646, + "5355": 4791, + "5356": 4791, + "5357": 4688, + "5358": 4774, + "5359": 4690, + "5360": 4762, + "5361": 4794, + "5362": 4798, + "5363": 4799, + "5364": 4800, + "5365": 4795, + "5366": 4801, + "5367": 736, + "5368": 4802, + "5369": 4803, + "5370": 4804, + "5371": 4796, + "5372": 4805, + "5373": 4806, + "5374": 4807, + "5375": 4808, + "5376": 4810, + "5377": 4809, + "5378": 4813, + "5379": 4811, + "5380": 4812, + "5381": 3376, + "5382": 4692, + "5383": 4775, + "5384": 4694, + "5385": 3749, + "5386": 3774, + "5387": 3746, + "5388": 4698, + "5389": 4695, + "5390": 3745, + "5391": 4709, + "5392": 4838, + "5393": 4699, + "5394": 4700, + "5395": 4700, + "5396": 4700, + "5397": 4773, + "5398": 4703, + "5399": 4704, + "5400": 4818, + "5401": 4817, + "5402": 4816, + "5403": 4705, + "5404": 4769, + "5405": 4770, + "5406": 4772, + "5407": 4691, + "5408": 4771, + "5409": 4706, + "5410": 4768, + "5411": 4820, + "5412": 4704, + "5413": 4707, + "5414": 3778, + "5415": 3776, + "5416": 3777, + "5417": 4699, + "5418": 4700, + "5419": 4706, + "5420": 4705, + "5421": 4703, + "5422": 4704, + "5423": 4817, + "5424": 4816, + "5425": 4708, + "5426": 4855, + "5427": 4820, + "5428": 4773, + "5429": 4819, + "5430": 4764, + "5431": 4813, + "5432": 4730, + "5433": 4729, + "5434": 4733, + "5435": 4734, + "5436": 4732, + "5437": 4732, + "5438": 4729, + "5439": 4733, + "5440": 4731, + "5441": 4728, + "5442": 4727, + "5443": 4726, + "5444": 4725, + "5445": 4728, + "5446": 4725, + "5447": 108, + "5448": 108, + "5449": 4735, + "5450": 4736, + "5451": 4737, + "5452": 4738, + "5453": 4739, + "5454": 4739, + "5455": 4740, + "5456": 4741, + "5457": 4742, + "5458": 4743, + "5459": 541, + "5460": 4765, + "5461": 4766, + "5462": 4767, + "5463": 4784, + "5464": 4785, + "5465": 4957, + "5466": 4956, + "5467": 4955, + "5468": 4952, + "5469": 4953, + "5470": 5043, + "5471": 4815, + "5472": 4896, + "5473": 4954, + "5474": 2667, + "5475": 4782, + "5476": 541, + "5477": 4784, + "5478": 4782, + "5479": 4814, + "5480": 4784, + "5481": 4785, + "5482": 4786, + "5483": 4784, + "5484": 4786, + "5485": 4782, + "5486": 4784, + "5487": 4781, + "5488": 4782, + "5489": 4784, + "5490": 4785, + "5491": 4786, + "5492": 4781, + "5493": 4782, + "5494": 4784, + "5495": 4785, + "5496": 4781, + "5497": 4782, + "5498": 4784, + "5499": 4833, + "5500": 4786, + "5501": 4781, + "5502": 4782, + "5503": 4784, + "5505": 4814, + "5506": 4781, + "5507": 4782, + "5508": 4784, + "5509": 4781, + "5510": 4784, + "5511": 4786, + "5512": 4781, + "5513": 4783, + "5514": 4784, + "5515": 4785, + "5516": 4781, + "5517": 4783, + "5518": 4781, + "5519": 4783, + "5520": 4782, + "5521": 4787, + "5522": 4788, + "5523": 4789, + "5525": 2667, + "5526": 4687, + "5527": 3646, + "5528": 4688, + "5529": 4689, + "5530": 4690, + "5531": 4797, + "5532": 4701, + "5533": 4702, + "5534": 4697, + "5535": 4853, + "5536": 4710, + "5537": 4711, + "5538": 4712, + "5539": 4712, + "5540": 4713, + "5541": 4714, + "5542": 4715, + "5543": 4716, + "5544": 4717, + "5545": 4718, + "5546": 4719, + "5547": 4721, + "5548": 4720, + "5549": 4724, + "5550": 4713, + "5551": 4723, + "5552": 4722, + "5553": 3745, + "5554": 4709, + "5555": 4776, + "5556": 4776, + "5557": 4777, + "5558": 4778, + "5559": 4779, + "5560": 4780, + "5561": 4776, + "5562": 4782, + "5563": 4897, + "5564": 3376, + "5565": 4692, + "5566": 4775, + "5567": 4694, + "5568": 3749, + "5569": 3774, + "5570": 3746, + "5571": 4698, + "5572": 4695, + "5573": 2667, + "5574": 4691, + "5575": 4693, + "5576": 3758, + "5577": 4772, + "5578": 4774, + "5579": 4699, + "5580": 4700, + "5581": 4773, + "5582": 4703, + "5583": 4705, + "5584": 4706, + "5585": 4768, + "5586": 4820, + "5587": 4706, + "5588": 4707, + "5589": 3778, + "5590": 3776, + "5591": 3777, + "5592": 4699, + "5593": 4700, + "5594": 4706, + "5595": 4705, + "5596": 1835010, + "5597": 4708, + "5598": 4773, + "5599": 4764, + "5600": 4811, + "5601": 4812, + "5602": 4811, + "5603": 4812, + "5604": 4787, + "5605": 4788, + "5606": 4821, + "5607": 4822, + "5608": 4840, + "5609": 5041, + "5610": 5042, + "5611": 4731, + "5612": 4804, + "5613": 4734, + "5614": 4736, + "5615": 4843, + "5616": 3458, + "5617": 3458, + "5618": 4737, + "5619": 4963, + "5620": 4962, + "5621": 3460, + "5622": 3459, + "5623": 4960, + "5624": 4961, + "5625": 4959, + "5626": 4963, + "5627": 4943, + "5628": 4944, + "5629": 4945, + "5630": 4946, + "5631": 4947, + "5632": 4948, + "5633": 4949, + "5634": 4950, + "5635": 4951, + "5636": 4928, + "5637": 4929, + "5638": 4932, + "5639": 4933, + "5640": 4931, + "5641": 4930, + "5642": 4936, + "5643": 4935, + "5644": 4937, + "5645": 4934, + "5646": 4939, + "5647": 4938, + "5648": 4940, + "5649": 4942, + "5650": 4954, + "5651": 4941, + "5652": 4855, + "5653": 4856, + "5654": 4857, + "5655": 4858, + "5656": 4859, + "5657": 4860, + "5658": 4861, + "5659": 4854, + "5660": 4853, + "5661": 4852, + "5662": 3818, + "5663": 3819, + "5664": 3820, + "5665": 4489, + "5666": 5045, + "5667": 1492, + "5668": 729, + "5669": 4846, + "5670": 4847, + "5671": 4878, + "5672": 4879, + "5673": 4880, + "5674": 4881, + "5675": 4882, + "5676": 4868, + "5677": 4884, + "5678": 4885, + "5679": 4886, + "5680": 4887, + "5681": 4878, + "5682": 108, + "5683": 108, + "5684": 108, + "5685": 108, + "5686": 4942, + "5687": 4871, + "5688": 4848, + "5689": 4907, + "5690": 5589, + "5691": 4908, + "5692": 4852, + "5693": 4913, + "5694": 4909, + "5695": 5048, + "5696": 5049, + "5697": 4910, + "5698": 4849, + "5699": 4911, + "5700": 4911, + "5701": 4912, + "5702": 4913, + "5703": 4914, + "5704": 4915, + "5705": 4916, + "5706": 4888, + "5707": 4889, + "5708": 4890, + "5709": 4891, + "5710": 4892, + "5711": 4893, + "5712": 4894, + "5713": 4958, + "5714": 2095, + "5715": 4895, + "5716": 5050, + "5717": 5051, + "5718": 4965, + "5719": 5052, + "5720": 5053, + "5721": 4966, + "5722": 4967, + "5723": 4968, + "5724": 4969, + "5725": 4970, + "5726": 4971, + "5727": 4972, + "5728": 5044, + "5729": 4897, + "5730": 4898, + "5731": 4899, + "5732": 4900, + "5733": 4901, + "5734": 4902, + "5735": 4903, + "5736": 4904, + "5737": 4862, + "5738": 4863, + "5739": 4864, + "5740": 4865, + "5741": 4866, + "5742": 4867, + "5743": 4868, + "5744": 4869, + "5745": 4870, + "5746": 4872, + "5747": 4873, + "5748": 4874, + "5749": 4875, + "5750": 4877, + "5751": 4871, + "5752": 5056, + "5753": 4911, + "5754": 5057, + "5755": 4876, + "5756": 4973, + "5757": 4974, + "5758": 4905, + "5759": 4905, + "5760": 4905, + "5761": 4906, + "5762": 4901, + "5763": 108, + "5764": 5054, + "5765": 4910, + "5766": 5479, + "5767": 4975, + "5768": 4976, + "5769": 4977, + "5770": 4978, + "5771": 4979, + "5772": 4980, + "5773": 4981, + "5774": 4982, + "5775": 4983, + "5776": 4984, + "5777": 4985, + "5778": 4986, + "5779": 4987, + "5780": 4988, + "5781": 4989, + "5782": 4990, + "5783": 4991, + "5784": 4992, + "5785": 4993, + "5786": 4994, + "5787": 4995, + "5788": 4996, + "5789": 4997, + "5790": 4998, + "5791": 4999, + "5792": 5000, + "5793": 5001, + "5794": 5002, + "5795": 5003, + "5796": 5004, + "5797": 5005, + "5798": 5006, + "5799": 5007, + "5800": 5008, + "5801": 5009, + "5802": 5010, + "5803": 5011, + "5804": 5012, + "5805": 5013, + "5806": 5014, + "5807": 5015, + "5808": 5016, + "5809": 5017, + "5810": 5018, + "5811": 5019, + "5812": 5020, + "5813": 5021, + "5814": 5022, + "5815": 5023, + "5816": 5024, + "5817": 5025, + "5818": 5026, + "5819": 5027, + "5820": 5028, + "5821": 5029, + "5822": 5030, + "5823": 5031, + "5824": 5032, + "5825": 5033, + "5826": 5034, + "5827": 5035, + "5828": 5036, + "5829": 5037, + "5830": 5038, + "5831": 2566, + "5832": 2566, + "5833": 2566, + "5834": 2566, + "5835": 2566, + "5836": 4961, + "5837": 5041, + "5838": 5041, + "5839": 5041, + "5840": 5041, + "5841": 5009, + "5842": 5010, + "5843": 5011, + "5844": 5012, + "5845": 5013, + "5846": 5049, + "5847": 5050, + "5848": 5051, + "5849": 5052, + "5850": 5053, + "5851": 5054, + "5852": 5055, + "5853": 5048, + "5854": 5047, + "5855": 3458, + "5856": 3458, + "5857": 4013, + "5858": 4014, + "5859": 3459, + "5860": 4960, + "5861": 4961, + "5862": 4959, + "5863": 3459, + "5864": 5039, + "5865": 5040, + "5866": 5058, + "5867": 5059, + "5868": 5060, + "5869": 5060, + "5870": 5060, + "5871": 5060, + "5872": 5061, + "5873": 5061, + "5874": 5061, + "5875": 5061, + "5876": 5061, + "5877": 5061, + "5878": 5062, + "5879": 5063, + "5880": 5064, + "5881": 5065, + "5882": 5066, + "5883": 5066, + "5884": 5066, + "5885": 5066, + "5886": 5067, + "5887": 5068, + "5888": 5069, + "5889": 5070, + "5890": 4987, + "5891": 5072, + "5892": 5073, + "5893": 5074, + "5894": 5075, + "5895": 5076, + "5896": 5077, + "5897": 5078, + "5898": 5079, + "5899": 5080, + "5900": 5081, + "5901": 5082, + "5902": 5083, + "5903": 5084, + "5904": 5085, + "5905": 5086, + "5906": 5087, + "5907": 5088, + "5908": 5089, + "5909": 5090, + "5910": 5091, + "5911": 5092, + "5912": 5093, + "5913": 5094, + "5914": 5095, + "5915": 5096, + "5916": 5097, + "5917": 5098, + "5918": 5099, + "5919": 5100, + "5920": 5101, + "5921": 5102, + "5922": 5103, + "5923": 5104, + "5924": 5105, + "5925": 5106, + "5926": 5107, + "5927": 5108, + "5928": 5109, + "5929": 5110, + "5930": 5111, + "5931": 5112, + "5932": 5113, + "5933": 5114, + "5934": 5115, + "5935": 5116, + "5936": 5117, + "5937": 5118, + "5938": 5119, + "5939": 5120, + "5940": 5121, + "5941": 5122, + "5942": 5123, + "5943": 5124, + "5944": 5125, + "5945": 5126, + "5946": 5127, + "5947": 5128, + "5948": 5129, + "5949": 5130, + "5950": 5131, + "5951": 5132, + "5952": 5133, + "5953": 5134, + "5954": 5135, + "5955": 5136, + "5956": 5137, + "5957": 5138, + "5958": 5139, + "5959": 5140, + "5960": 5141, + "5961": 5142, + "5962": 5143, + "5963": 5144, + "5964": 5145, + "5965": 5146, + "5966": 5147, + "5967": 5148, + "5968": 5149, + "5969": 5150, + "5970": 5151, + "5971": 5152, + "5972": 5153, + "5973": 5154, + "5974": 5155, + "5975": 5156, + "5976": 5157, + "5977": 5158, + "5978": 5159, + "5979": 5160, + "5980": 5161, + "5981": 5162, + "5982": 5163, + "5983": 5164, + "5984": 5165, + "5985": 5166, + "5986": 5167, + "5987": 4981, + "5988": 5030, + "5989": 5147, + "5990": 108, + "5991": 5216, + "5992": 5278, + "5993": 5279, + "5994": 5280, + "5995": 5218, + "5996": 5141, + "5997": 5142, + "5998": 5219, + "5999": 5220, + "6000": 4895, + "6001": 5221, + "6002": 5222, + "6003": 5223, + "6004": 5224, + "6005": 5225, + "6006": 5226, + "6007": 5227, + "6008": 5228, + "6009": 5229, + "6010": 5230, + "6011": 5231, + "6012": 5232, + "6013": 5233, + "6014": 5234, + "6015": 5235, + "6016": 5236, + "6017": 5237, + "6018": 5238, + "6019": 5061, + "6020": 5061, + "6021": 5061, + "6022": 5168, + "6023": 5085, + "6024": 5085, + "6025": 5085, + "6026": 5199, + "6027": 5201, + "6028": 5200, + "6029": 5202, + "6030": 5203, + "6031": 5204, + "6032": 4914, + "6033": 5199, + "6034": 5201, + "6035": 5202, + "6036": 5203, + "6037": 5204, + "6038": 5219, + "6039": 5220, + "6040": 5221, + "6041": 5222, + "6043": 5265, + "6044": 5266, + "6045": 5267, + "6046": 5268, + "6047": 5269, + "6048": 5270, + "6049": 5230, + "6050": 5272, + "6051": 5259, + "6052": 1644, + "6053": 5186, + "6054": 5186, + "6055": 5187, + "6056": 5188, + "6057": 5189, + "6058": 5190, + "6059": 5246, + "6060": 5247, + "6061": 5251, + "6062": 5252, + "6063": 5253, + "6065": 5257, + "6066": 5255, + "6067": 5256, + "6068": 5258, + "6069": 5254, + "6070": 5260, + "6071": 5259, + "6072": 5264, + "6073": 5262, + "6074": 5261, + "6075": 5263, + "6076": 5193, + "6077": 5194, + "6078": 5195, + "6079": 5196, + "6080": 5197, + "6081": 5193, + "6082": 108, + "6083": 5195, + "6084": 5196, + "6085": 5197, + "6086": 5198, + "6087": 5174, + "6088": 4130, + "6089": 4392, + "6090": 5239, + "6091": 713, + "6092": 1492, + "6093": 5240, + "6094": 5241, + "6095": 5244, + "6096": 5242, + "6097": 5243, + "6098": 5279, + "6099": 3306, + "6100": 5274, + "6101": 3647, + "6102": 3648, + "6103": 5269, + "6104": 5169, + "6105": 5170, + "6106": 5171, + "6107": 5172, + "6108": 5173, + "6109": 1385, + "6110": 3749, + "6111": 5176, + "6112": 5277, + "6113": 5178, + "6114": 5170, + "6115": 5180, + "6116": 5181, + "6117": 5182, + "6118": 5183, + "6119": 5184, + "6120": 5185, + "6121": 5182, + "6122": 5186, + "6123": 5186, + "6124": 5187, + "6125": 5188, + "6126": 5189, + "6127": 5347, + "6128": 5192, + "6129": 5295, + "6130": 5297, + "6131": 5179, + "6132": 5191, + "6133": 541, + "6134": 108, + "6135": 108, + "6136": 108, + "6137": 5181, + "6138": 5358, + "6139": 5207, + "6140": 5208, + "6141": 4691, + "6142": 5206, + "6143": 5175, + "6144": 3468, + "6145": 5205, + "6146": 5180, + "6147": 5182, + "6148": 5185, + "6150": 5184, + "6151": 5182, + "6152": 5356, + "6153": 5357, + "6154": 5358, + "6155": 5359, + "6156": 564, + "6157": 565, + "6158": 5193, + "6159": 5194, + "6160": 5195, + "6161": 5197, + "6162": 5194, + "6163": 5174, + "6164": 5309, + "6165": 5321, + "6166": 5333, + "6167": 5345, + "6168": 5371, + "6169": 5384, + "6170": 5397, + "6171": 5410, + "6172": 5424, + "6173": 5438, + "6174": 5449, + "6175": 5461, + "6176": 5471, + "6177": 4996, + "6178": 5299, + "6179": 5300, + "6180": 5301, + "6181": 5302, + "6182": 5303, + "6183": 5304, + "6184": 5305, + "6185": 5306, + "6186": 5307, + "6187": 5308, + "6188": 5311, + "6189": 5312, + "6190": 5313, + "6191": 5004, + "6192": 5314, + "6193": 5315, + "6194": 5316, + "6195": 5317, + "6196": 5318, + "6197": 5319, + "6198": 5320, + "6199": 5322, + "6200": 5323, + "6201": 5324, + "6202": 5325, + "6203": 5326, + "6204": 5327, + "6205": 5328, + "6206": 5329, + "6207": 5330, + "6208": 5331, + "6209": 5332, + "6210": 5334, + "6211": 5335, + "6212": 5336, + "6213": 5337, + "6214": 5338, + "6215": 5339, + "6216": 5340, + "6217": 5341, + "6218": 5342, + "6219": 5343, + "6220": 5344, + "6221": 5346, + "6222": 5347, + "6223": 5348, + "6224": 5349, + "6225": 5350, + "6226": 5351, + "6227": 4979, + "6228": 5352, + "6229": 5353, + "6230": 5354, + "6231": 5355, + "6232": 5480, + "6233": 5360, + "6234": 5361, + "6235": 5362, + "6236": 5363, + "6237": 5364, + "6238": 5365, + "6239": 5366, + "6240": 5367, + "6241": 5368, + "6242": 5369, + "6243": 5370, + "6244": 5372, + "6245": 5373, + "6246": 5374, + "6247": 5375, + "6248": 5376, + "6249": 5377, + "6250": 5378, + "6251": 5379, + "6252": 5380, + "6253": 5381, + "6254": 5382, + "6255": 5383, + "6256": 5385, + "6257": 5386, + "6258": 5387, + "6259": 5388, + "6260": 5389, + "6261": 5390, + "6262": 5391, + "6263": 5392, + "6264": 5393, + "6265": 5394, + "6266": 5395, + "6267": 5396, + "6268": 5398, + "6269": 5399, + "6270": 5400, + "6271": 5401, + "6272": 5402, + "6273": 5403, + "6274": 5404, + "6275": 5405, + "6276": 5406, + "6277": 5407, + "6278": 5408, + "6279": 5409, + "6280": 5412, + "6281": 5413, + "6282": 5414, + "6283": 5415, + "6284": 5416, + "6285": 5417, + "6286": 5418, + "6287": 5419, + "6288": 5420, + "6289": 5421, + "6290": 5422, + "6291": 5423, + "6292": 5381, + "6293": 5429, + "6294": 5430, + "6295": 5431, + "6296": 5432, + "6297": 5433, + "6298": 5406, + "6299": 5434, + "6300": 5435, + "6301": 5436, + "6302": 5437, + "6303": 5439, + "6304": 5440, + "6305": 5441, + "6306": 5389, + "6307": 5442, + "6308": 5443, + "6309": 5444, + "6310": 5445, + "6311": 5446, + "6312": 5447, + "6313": 5448, + "6314": 5450, + "6315": 5451, + "6316": 5452, + "6317": 5453, + "6318": 5454, + "6319": 5455, + "6320": 5456, + "6321": 5457, + "6322": 5458, + "6323": 5459, + "6324": 5460, + "6325": 5462, + "6326": 5463, + "6327": 5440, + "6328": 5464, + "6329": 5465, + "6330": 5466, + "6331": 5467, + "6332": 5480, + "6333": 5468, + "6334": 5469, + "6335": 5470, + "6336": 5401, + "6337": 5474, + "6338": 5420, + "6339": 5415, + "6340": 5472, + "6341": 5473, + "6342": 5364, + "6343": 5409, + "6344": 5475, + "6345": 5422, + "6346": 5423, + "6347": 3467, + "6348": 5169, + "6349": 5170, + "6350": 5171, + "6351": 5172, + "6352": 5173, + "6353": 5176, + "6354": 5277, + "6355": 5179, + "6357": 5217, + "6358": 9958, + "6359": 2566, + "6360": 2566, + "6361": 2566, + "6362": 2566, + "6363": 2566, + "6364": 2566, + "6365": 2566, + "6366": 2566, + "6367": 2566, + "6368": 2566, + "6369": 2566, + "6370": 2566, + "6371": 2566, + "6372": 2566, + "6373": 2566, + "6374": 5310, + "6375": 783, + "6376": 4578, + "6377": 4580, + "6378": 5477, + "6379": 5425, + "6380": 5426, + "6381": 5427, + "6382": 5428, + "6383": 4170, + "6384": 5461, + "6385": 4579, + "6386": 4580, + "6387": 5477, + "6388": 5625, + "6389": 5292, + "6390": 5293, + "6391": 5294, + "6392": 5297, + "6393": 5290, + "6394": 5291, + "6395": 5295, + "6396": 5283, + "6397": 5296, + "6398": 5298, + "6399": 5289, + "6400": 5288, + "6401": 5286, + "6402": 5285, + "6403": 5287, + "6404": 5284, + "6405": 5366, + "6406": 5411, + "6407": 2564, + "6408": 5526, + "6409": 2564, + "6410": 5523, + "6411": 2568, + "6412": 5522, + "6413": 5524, + "6414": 5525, + "6415": 5507, + "6416": 5508, + "6417": 5507, + "6418": 3725, + "6419": 5529, + "6420": 5585, + "6421": 5586, + "6422": 5530, + "6423": 5587, + "6424": 5531, + "6425": 5532, + "6426": 5534, + "6427": 5535, + "6428": 5536, + "6429": 5537, + "6430": 5538, + "6431": 5539, + "6432": 3805, + "6433": 5540, + "6434": 5541, + "6435": 5542, + "6436": 5543, + "6437": 3797, + "6438": 5544, + "6439": 5545, + "6440": 5509, + "6441": 5510, + "6442": 5511, + "6443": 5512, + "6444": 5513, + "6445": 5514, + "6446": 5509, + "6447": 2096, + "6448": 5567, + "6449": 5567, + "6450": 5568, + "6451": 5569, + "6452": 5570, + "6453": 5571, + "6454": 5572, + "6455": 5567, + "6456": 5560, + "6457": 5561, + "6458": 5562, + "6459": 5563, + "6460": 5554, + "6461": 5564, + "6462": 5565, + "6463": 5566, + "6464": 5547, + "6465": 5548, + "6466": 13439, + "6467": 5550, + "6468": 5551, + "6469": 5552, + "6470": 5546, + "6471": 5553, + "6472": 5557, + "6473": 5554, + "6474": 5555, + "6475": 5556, + "6476": 5558, + "6477": 5559, + "6478": 3281, + "6479": 5515, + "6480": 5516, + "6481": 633, + "6482": 5517, + "6483": 5519, + "6484": 5518, + "6485": 5521, + "6486": 12792, + "6487": 237, + "6488": 238, + "6489": 4686, + "6490": 5476, + "6491": 5573, + "6492": 5574, + "6493": 5575, + "6494": 5576, + "6495": 5576, + "6496": 5577, + "6497": 5578, + "6498": 5579, + "6499": 5580, + "6500": 5581, + "6501": 5582, + "6502": 5583, + "6503": 3997698, + "6504": 3782, + "6505": 3781, + "6506": 3780, + "6507": 5276, + "6508": 3780, + "6509": 5515, + "6510": 5591, + "6511": 5165, + "6512": 5594, + "6513": 13494, + "6514": 264, + "6515": 5169, + "6516": 11230, + "6517": 7365, + "6518": 5172, + "6519": 269, + "6520": 6547, + "6522": 6203, + "6523": 5798, + "6524": 12830, + "6525": 6256, + "6526": 5595, + "6527": 13500, + "6528": 5597, + "6529": 5800, + "6530": 5184, + "6531": 5640, + "6532": 5549, + "6533": 5550, + "6534": 5603, + "6535": 5604, + "6536": 3656, + "6537": 5645, + "6538": 7175, + "6539": 5657, + "6540": 2695, + "6541": 5654, + "6542": 2746, + "6543": 8143, + "6544": 5502, + "6545": 5503, + "6546": 5504, + "6547": 5505, + "6548": 8148, + "6549": 3856, + "6550": 5567, + "6551": 5567, + "6552": 5568, + "6553": 5569, + "6554": 5570, + "6555": 2712, + "6556": 5572, + "6557": 5567, + "6558": 5657, + "6559": 5651, + "6560": 5652, + "6561": 5651, + "6562": 3869, + "6563": 2768, + "6564": 9856, + "6565": 2096, + "6566": 3873, + "6567": 11352, + "6568": 628, + "6569": 6014, + "6570": 6015, + "6571": 6017, + "6572": 6018, + "6573": 6019, + "6574": 108, + "6575": 5520, + "6576": 108, + "6577": 6353, + "6578": 5690, + "6579": 5691, + "6580": 6145, + "6581": 5767, + "6582": 5696, + "6583": 5698, + "6584": 6429, + "6585": 5704, + "6586": 5535, + "6587": 5735, + "6588": 5716, + "6589": 5717, + "6590": 5681, + "6591": 5705, + "6592": 5740, + "6593": 5700, + "6594": 5780, + "6595": 5692, + "6596": 5693, + "6597": 5684, + "6598": 6485, + "6599": 6797, + "6600": 5683, + "6601": 5674, + "6602": 5711, + "6603": 5705, + "6604": 5701, + "6605": 5712, + "6606": 5721, + "6607": 5720, + "6608": 5688, + "6609": 5707, + "6610": 5722, + "6611": 113, + "6612": 115, + "6613": 56, + "6614": 117, + "6615": 116, + "6616": 5733, + "6617": 108, + "6618": 6483, + "6619": 6483, + "6620": 6489, + "6621": 5849, + "6622": 5897, + "6623": 125, + "6624": 6528, + "6625": 6518, + "6626": 5776, + "6627": 6509, + "6628": 5662, + "6629": 5782, + "6630": 5588, + "6631": 6529, + "6632": 5773, + "6633": 6141, + "6634": 6519, + "6635": 6519, + "6636": 6519, + "6637": 5734, + "6638": 5899, + "6639": 5775, + "6640": 5646, + "6641": 6288, + "6642": 5761, + "6643": 6521, + "6644": 5777, + "6645": 5736, + "6646": 5900, + "6647": 6798, + "6648": 6729, + "6649": 6550, + "6650": 5778, + "6651": 5728, + "6652": 5714, + "6653": 5715, + "6654": 5685, + "6655": 6796, + "6656": 5764, + "6657": 5805, + "6658": 5686, + "6659": 6775, + "6660": 5768, + "6661": 5726, + "6662": 6741, + "6663": 5680, + "6664": 6280, + "6665": 5687, + "6666": 5713, + "6667": 5708, + "6668": 5702, + "6669": 5723, + "6670": 5724, + "6671": 5725, + "6672": 5729, + "6673": 5730, + "6674": 6730, + "6675": 5750, + "6676": 6722, + "6677": 5887, + "6678": 5772, + "6679": 5748, + "6680": 5760, + "6681": 6728, + "6682": 5762, + "6683": 5748, + "6684": 5764, + "6685": 5836, + "6686": 5765, + "6687": 5941, + "6688": 5764, + "6689": 190, + "6690": 5737, + "6691": 5785, + "6692": 5780, + "6693": 5781, + "6694": 5839, + "6695": 5884, + "6696": 5836, + "6697": 5738, + "6698": 5763, + "6699": 6586, + "6700": 6426, + "6701": 144, + "6702": 5830, + "6703": 5822, + "6704": 5832, + "6705": 239, + "6706": 5727, + "6707": 6776, + "6708": 5810, + "6709": 5792, + "6710": 5954, + "6711": 6378, + "6712": 6381, + "6713": 6382, + "6714": 6383, + "6715": 5839, + "6716": 5846, + "6717": 6773, + "6718": 252, + "6719": 5687, + "6720": 5850, + "6721": 5846, + "6722": 6544, + "6723": 5873, + "6724": 5818, + "6725": 5808, + "6726": 6624, + "6727": 5825, + "6728": 5696, + "6729": 231, + "6730": 5837, + "6731": 5785, + "6732": 5797, + "6733": 5877, + "6734": 5702, + "6735": 5590, + "6736": 5591, + "6737": 5592, + "6738": 5650, + "6739": 5576, + "6740": 5651, + "6741": 5652, + "6742": 5670, + "6743": 108, + "6744": 6154, + "6745": 4133, + "6746": 5239, + "6747": 5656, + "6748": 5657, + "6749": 5658, + "6750": 5659, + "6751": 5660, + "6752": 5661, + "6753": 5662, + "6754": 5239, + "6755": 4130, + "6756": 6146, + "6757": 6143, + "6758": 6144, + "6759": 5871, + "6760": 6816, + "6761": 5729, + "6762": 5540, + "6763": 6144, + "6764": 6147, + "6765": 6916, + "6766": 5643, + "6767": 5629, + "6768": 5629, + "6769": 5630, + "6770": 108, + "6771": 6142, + "6772": 6085, + "6773": 6086, + "6774": 6087, + "6775": 6088, + "6776": 6089, + "6777": 6090, + "6778": 6675, + "6779": 6676, + "6780": 6787, + "6781": 6787, + "6782": 6786, + "6783": 108, + "6784": 3237, + "6785": 6677, + "6786": 5970, + "6787": 5659, + "6788": 5964, + "6789": 5965, + "6790": 5966, + "6791": 5967, + "6792": 5953, + "6793": 5968, + "6794": 5969, + "6795": 5950, + "6796": 5951, + "6797": 1768, + "6798": 6342, + "6799": 6091, + "6800": 3305, + "6801": 6093, + "6802": 6075, + "6803": 6075, + "6804": 6076, + "6805": 6077, + "6806": 6078, + "6807": 6079, + "6808": 6080, + "6809": 6081, + "6810": 6082, + "6811": 6083, + "6812": 6084, + "6813": 5630, + "6814": 6173, + "6815": 6174, + "6816": 6175, + "6817": 6175, + "6818": 6176, + "6819": 6177, + "6820": 6178, + "6821": 6180, + "6822": 6155, + "6823": 6181, + "6824": 6182, + "6825": 6263, + "6826": 6264, + "6827": 6265, + "6828": 6266, + "6829": 6267, + "6830": 6268, + "6831": 6269, + "6832": 6270, + "6833": 5984, + "6834": 5985, + "6835": 5986, + "6836": 5987, + "6837": 5988, + "6838": 5989, + "6839": 5990, + "6840": 5991, + "6841": 5992, + "6842": 5993, + "6843": 5994, + "6844": 5995, + "6845": 5996, + "6846": 5997, + "6847": 5998, + "6848": 5999, + "6849": 6000, + "6850": 6001, + "6851": 6002, + "6852": 6003, + "6853": 6004, + "6854": 6005, + "6855": 6006, + "6856": 6007, + "6857": 6008, + "6858": 6009, + "6859": 6010, + "6860": 6011, + "6861": 6012, + "6862": 6013, + "6863": 6674, + "6864": 9096, + "6865": 9114, + "6866": 9106, + "6867": 9079, + "6868": 9088, + "6869": 9093, + "6870": 9084, + "6871": 9076, + "6872": 9113, + "6873": 6352, + "6874": 6049, + "6875": 6050, + "6876": 6051, + "6877": 5645, + "6878": 6045, + "6879": 6342, + "6880": 6341, + "6881": 6672, + "6882": 6673, + "6883": 1854, + "6884": 6691, + "6885": 108, + "6886": 6346, + "6887": 6341, + "6888": 5648, + "6889": 6662, + "6890": 6658, + "6891": 6659, + "6892": 6660, + "6893": 1501, + "6894": 108, + "6895": 4865, + "6896": 4866, + "6897": 4869, + "6898": 6391, + "6899": 6341, + "6900": 6669, + "6901": 6670, + "6902": 5972, + "6903": 6221, + "6904": 6221, + "6905": 108, + "6906": 6671, + "6907": 6071, + "6908": 6072, + "6909": 6073, + "6910": 6074, + "6911": 6058, + "6912": 6059, + "6913": 6060, + "6914": 6061, + "6915": 6062, + "6916": 6063, + "6917": 6064, + "6918": 6065, + "6919": 6066, + "6920": 6067, + "6921": 6068, + "6922": 6058, + "6923": 6069, + "6924": 6237, + "6925": 6238, + "6926": 6241, + "6927": 6243, + "6928": 6244, + "6929": 6246, + "6930": 5789, + "6931": 6275, + "6932": 6272, + "6933": 6279, + "6934": 6278, + "6935": 6277, + "6936": 6030, + "6937": 5641, + "6938": 5642, + "6939": 6226, + "6940": 6227, + "6941": 6228, + "6942": 6229, + "6943": 6384, + "6944": 6230, + "6945": 6231, + "6946": 6231, + "6947": 6232, + "6948": 6231, + "6949": 6233, + "6950": 6234, + "6951": 6235, + "6952": 6236, + "6953": 6335, + "6954": 6239, + "6955": 6146, + "6956": 5575, + "6957": 6148, + "6958": 6149, + "6959": 6158, + "6960": 6156, + "6961": 6158, + "6962": 6157, + "6963": 6161, + "6964": 6165, + "6965": 6165, + "6966": 6164, + "6967": 6163, + "6968": 6153, + "6969": 6152, + "6970": 5576, + "6971": 5562, + "6972": 6170, + "6973": 6208, + "6974": 6172, + "6975": 6336, + "6976": 6336, + "6977": 6153, + "6978": 6152, + "6979": 6337, + "6980": 9219, + "6981": 6314, + "6982": 6566, + "6983": 6341, + "6984": 6166, + "6985": 6151, + "6986": 5973, + "6987": 6302, + "6988": 6307, + "6989": 6308, + "6990": 6309, + "6991": 4385, + "6992": 6310, + "6993": 6311, + "6994": 1420, + "6995": 6119, + "6996": 6120, + "6997": 6118, + "6998": 6117, + "6999": 6116, + "7000": 6115, + "7001": 6665, + "7002": 6242, + "7003": 6185, + "7004": 6186, + "7005": 6187, + "7006": 6188, + "7007": 6189, + "7008": 6293, + "7009": 6190, + "7010": 6191, + "7011": 6192, + "7012": 6193, + "7013": 6297, + "7014": 6194, + "7015": 6195, + "7016": 6196, + "7017": 713, + "7018": 4392, + "7019": 6146, + "7020": 4130, + "7021": 6102, + "7022": 6103, + "7023": 6097, + "7024": 6101, + "7025": 6098, + "7026": 6099, + "7027": 6100, + "7028": 6175, + "7029": 6176, + "7030": 6177, + "7031": 6094, + "7032": 6094, + "7033": 6094, + "7034": 6097, + "7035": 6101, + "7036": 6098, + "7037": 6104, + "7038": 6108, + "7039": 6175, + "7040": 6140, + "7041": 6138, + "7042": 6139, + "7043": 6136, + "7044": 6137, + "7045": 6134, + "7046": 6135, + "7047": 6132, + "7048": 6131, + "7049": 6130, + "7050": 6129, + "7051": 6127, + "7052": 6128, + "7053": 6125, + "7054": 6124, + "7055": 6123, + "7056": 6122, + "7057": 6121, + "7058": 3920, + "7059": 3921, + "7060": 3922, + "7061": 3913, + "7062": 3912, + "7063": 6342, + "7064": 6668, + "7065": 3930, + "7066": 6650, + "7067": 6222, + "7068": 6221, + "7069": 6221, + "7070": 6221, + "7071": 6222, + "7072": 6223, + "7073": 6221, + "7074": 108, + "7075": 4420, + "7076": 6037, + "7077": 108, + "7078": 6038, + "7079": 6389, + "7080": 6389, + "7081": 6390, + "7082": 6039, + "7083": 6039, + "7084": 6041, + "7085": 6042, + "7086": 6040, + "7087": 6666, + "7088": 6114, + "7089": 331, + "7090": 6021, + "7091": 332, + "7092": 5666, + "7093": 6677, + "7094": 6342, + "7095": 6343, + "7096": 6248, + "7097": 6249, + "7098": 6250, + "7099": 6251, + "7100": 6252, + "7101": 6386, + "7102": 6254, + "7103": 6255, + "7104": 6256, + "7105": 6258, + "7106": 6259, + "7107": 6260, + "7108": 6261, + "7109": 6262, + "7110": 6257, + "7111": 5980, + "7112": 6088, + "7113": 3165, + "7114": 108, + "7115": 5667, + "7116": 6200, + "7117": 6200, + "7118": 6202, + "7119": 6201, + "7120": 6203, + "7121": 6203, + "7122": 6204, + "7123": 6204, + "7124": 6205, + "7125": 6205, + "7126": 6206, + "7127": 6206, + "7128": 6207, + "7129": 6171, + "7130": 6208, + "7131": 6209, + "7132": 6210, + "7133": 6211, + "7134": 6212, + "7135": 6213, + "7136": 6214, + "7137": 6215, + "7138": 6216, + "7139": 6170, + "7140": 6217, + "7141": 6218, + "7142": 6219, + "7143": 6220, + "7144": 6112, + "7145": 5764, + "7146": 6113, + "7147": 6113, + "7148": 6111, + "7149": 6289, + "7150": 6111, + "7151": 6111, + "7152": 6111, + "7153": 6710, + "7154": 6095, + "7155": 6095, + "7156": 6110, + "7157": 6105, + "7158": 6106, + "7159": 6107, + "7160": 6096, + "7161": 6096, + "7162": 6110, + "7163": 6105, + "7164": 6107, + "7165": 6114, + "7166": 331, + "7167": 6021, + "7168": 332, + "7169": 5666, + "7170": 6022, + "7171": 1416, + "7172": 4226, + "7173": 4227, + "7174": 823, + "7175": 828, + "7176": 751, + "7177": 8395, + "7178": 6183, + "7179": 6184, + "7180": 331, + "7181": 6021, + "7182": 6328, + "7183": 6329, + "7184": 6330, + "7185": 6331, + "7186": 6324, + "7187": 6332, + "7188": 6333, + "7189": 6334, + "7190": 6332, + "7191": 6321, + "7192": 6322, + "7193": 6323, + "7194": 6324, + "7195": 6325, + "7196": 6326, + "7197": 108, + "7198": 108, + "7199": 6667, + "7200": 6224, + "7201": 6224, + "7202": 5798, + "7203": 6794, + "7204": 6792, + "7205": 6732, + "7206": 5799, + "7207": 5800, + "7208": 5801, + "7209": 5802, + "7210": 5806, + "7211": 5807, + "7212": 5808, + "7213": 5809, + "7214": 5810, + "7215": 5811, + "7216": 5812, + "7217": 5813, + "7218": 5814, + "7219": 5814, + "7220": 251, + "7221": 2234, + "7222": 5815, + "7223": 5814, + "7224": 5872, + "7225": 5816, + "7226": 5819, + "7227": 5216, + "7228": 1402, + "7229": 1402, + "7230": 1403, + "7231": 3825, + "7232": 5822, + "7233": 5823, + "7234": 5824, + "7235": 5825, + "7236": 5826, + "7237": 5872, + "7238": 5828, + "7239": 6360, + "7240": 5975, + "7241": 5976, + "7242": 5977, + "7243": 4130, + "7244": 4392, + "7245": 6565, + "7246": 6288, + "7247": 108, + "7248": 6700, + "7249": 6701, + "7250": 1640, + "7251": 3881, + "7252": 6694, + "7253": 6702, + "7254": 6703, + "7255": 6704, + "7256": 6705, + "7257": 108, + "7258": 5979, + "7259": 5979, + "7260": 4331, + "7261": 4321, + "7262": 6300, + "7263": 5240, + "7264": 6301, + "7265": 6302, + "7266": 6303, + "7267": 6306, + "7268": 4332, + "7269": 6304, + "7270": 6304, + "7271": 6304, + "7272": 6304, + "7273": 5241, + "7274": 5243, + "7275": 5242, + "7276": 5244, + "7277": 6313, + "7278": 3849, + "7279": 4142, + "7280": 6314, + "7281": 6315, + "7282": 6316, + "7283": 4131, + "7284": 6317, + "7285": 3850, + "7286": 6318, + "7287": 6319, + "7288": 6320, + "7289": 5240, + "7290": 4130, + "7291": 4392, + "7292": 5239, + "7293": 6146, + "7294": 3204, + "7295": 5649, + "7296": 6306, + "7297": 6661, + "7298": 6656, + "7299": 6273, + "7300": 6225, + "7301": 6225, + "7302": 6276, + "7303": 6245, + "7304": 6706, + "7305": 5631, + "7306": 5632, + "7307": 6711, + "7308": 6712, + "7309": 6897, + "7310": 6385, + "7311": 6690, + "7312": 6386, + "7313": 5904, + "7314": 6388, + "7315": 6387, + "7316": 5904, + "7317": 6705, + "7318": 6705, + "7319": 6707, + "7320": 4130, + "7321": 4392, + "7322": 5239, + "7323": 4846, + "7324": 4740, + "7325": 5947, + "7326": 5948, + "7327": 5949, + "7328": 5950, + "7329": 5951, + "7330": 5952, + "7331": 5953, + "7332": 5954, + "7333": 5955, + "7334": 5956, + "7335": 5957, + "7336": 5958, + "7337": 5959, + "7338": 5960, + "7339": 5961, + "7340": 108, + "7341": 2147, + "7342": 6344, + "7343": 6345, + "7344": 4759, + "7345": 4760, + "7346": 4761, + "7347": 4762, + "7348": 6346, + "7349": 6408, + "7350": 6709, + "7351": 1640, + "7352": 3881, + "7353": 6694, + "7354": 6695, + "7355": 5682, + "7356": 5944, + "7357": 4236, + "7358": 4237, + "7359": 6686, + "7360": 6687, + "7361": 6688, + "7362": 6407, + "7363": 6683, + "7364": 6413, + "7365": 6414, + "7366": 6415, + "7367": 6416, + "7368": 6418, + "7369": 6422, + "7370": 6424, + "7371": 4427, + "7372": 5648, + "7373": 6420, + "7374": 5969, + "7375": 6695, + "7376": 6425, + "7377": 6696, + "7378": 5919, + "7379": 5742, + "7380": 5757, + "7381": 6697, + "7382": 6698, + "7383": 108, + "7384": 6699, + "7385": 6693, + "7386": 5962, + "7387": 5963, + "7388": 6347, + "7389": 6347, + "7390": 6351, + "7391": 6348, + "7392": 108, + "7393": 541, + "7394": 541, + "7395": 108, + "7396": 5633, + "7397": 5634, + "7398": 5635, + "7399": 5626, + "7400": 6724, + "7401": 6056, + "7402": 5636, + "7403": 5637, + "7404": 5633, + "7405": 6379, + "7406": 5954, + "7407": 5664, + "7408": 2096, + "7409": 628, + "7410": 5663, + "7411": 5665, + "7412": 5663, + "7413": 6385, + "7414": 6261, + "7415": 6392, + "7416": 6393, + "7417": 2096, + "7418": 6020, + "7419": 6016, + "7420": 6394, + "7421": 6395, + "7422": 6290, + "7423": 6290, + "7424": 6298, + "7425": 6294, + "7426": 2343, + "7427": 8395, + "7428": 6453, + "7429": 6349, + "7430": 6350, + "7431": 6231, + "7432": 6231, + "7433": 6231, + "7434": 6231, + "7435": 5671, + "7436": 5678, + "7437": 5672, + "7438": 5673, + "7439": 5674, + "7440": 5675, + "7441": 5676, + "7442": 5677, + "7443": 5679, + "7444": 5680, + "7445": 5698, + "7446": 5699, + "7447": 5700, + "7448": 5701, + "7449": 5702, + "7450": 5703, + "7451": 113, + "7452": 115, + "7453": 56, + "7454": 5781, + "7455": 6052, + "7456": 6052, + "7457": 6053, + "7458": 6054, + "7459": 6055, + "7460": 6055, + "7461": 4815, + "7462": 6055, + "7463": 6385, + "7464": 5791, + "7465": 6686, + "7466": 6687, + "7467": 6688, + "7468": 6685, + "7469": 108, + "7470": 6689, + "7471": 5655, + "7472": 5653, + "7473": 5654, + "7474": 6337, + "7475": 6338, + "7476": 6339, + "7477": 6340, + "7478": 6340, + "7479": 6340, + "7480": 4237, + "7481": 108, + "7482": 108, + "7483": 108, + "7484": 108, + "7485": 108, + "7486": 5850, + "7487": 5851, + "7488": 5853, + "7489": 5854, + "7490": 5855, + "7491": 5856, + "7492": 3102, + "7493": 104, + "7494": 5880, + "7495": 5860, + "7496": 6354, + "7497": 5913, + "7498": 5915, + "7499": 6714, + "7500": 3107, + "7501": 5865, + "7502": 3107, + "7503": 5865, + "7504": 5866, + "7505": 5866, + "7506": 5867, + "7507": 5868, + "7508": 5869, + "7509": 5838, + "7510": 5871, + "7511": 5777, + "7512": 5946, + "7513": 5873, + "7514": 5934, + "7515": 5874, + "7516": 5875, + "7517": 5800, + "7518": 5876, + "7519": 5805, + "7520": 5878, + "7521": 5806, + "7522": 6575, + "7523": 5882, + "7524": 5883, + "7525": 5883, + "7526": 5884, + "7527": 5885, + "7528": 3930, + "7529": 5886, + "7530": 5888, + "7531": 5889, + "7532": 5890, + "7533": 5891, + "7534": 5892, + "7535": 5916, + "7536": 5893, + "7537": 5896, + "7538": 6597, + "7539": 5901, + "7540": 5902, + "7541": 5903, + "7542": 5904, + "7543": 5905, + "7544": 5906, + "7545": 5907, + "7546": 5909, + "7547": 5841, + "7548": 5783, + "7549": 5910, + "7550": 5911, + "7551": 5912, + "7552": 5877, + "7553": 2234, + "7554": 6736, + "7555": 5830, + "7556": 159, + "7557": 5833, + "7558": 5832, + "7559": 5834, + "7560": 5835, + "7561": 5837, + "7562": 5838, + "7563": 5804, + "7564": 6923, + "7565": 5946, + "7566": 5982, + "7567": 5983, + "7568": 5847, + "7569": 5848, + "7570": 108, + "7571": 6023, + "7572": 6024, + "7573": 6026, + "7574": 6025, + "7575": 6027, + "7576": 6028, + "7577": 6029, + "7578": 6030, + "7579": 6031, + "7580": 6032, + "7581": 6033, + "7582": 6034, + "7583": 6035, + "7584": 6035, + "7585": 6036, + "7586": 6737, + "7587": 6738, + "7588": 5660, + "7589": 6735, + "7590": 6471, + "7591": 6472, + "7592": 6474, + "7593": 6475, + "7594": 6480, + "7595": 6482, + "7596": 6492, + "7597": 6497, + "7598": 6455, + "7599": 6454, + "7600": 5644, + "7601": 6050, + "7602": 6051, + "7603": 5645, + "7604": 6045, + "7605": 5643, + "7606": 3860, + "7607": 5646, + "7608": 5647, + "7609": 5971, + "7610": 6043, + "7611": 6044, + "7612": 6146, + "7613": 5575, + "7614": 6148, + "7615": 6149, + "7616": 6162, + "7617": 6156, + "7618": 6046, + "7619": 5981, + "7620": 6673, + "7621": 6031, + "7622": 5857, + "7623": 108, + "7624": 108, + "7625": 108, + "7626": 108, + "7627": 108, + "7628": 108, + "7629": 108, + "7630": 108, + "7631": 108, + "7632": 108, + "7633": 108, + "7634": 108, + "7635": 108, + "7636": 108, + "7637": 6493, + "7638": 6655, + "7639": 108, + "7640": 108, + "7641": 6157, + "7642": 6163, + "7643": 6743, + "7644": 6744, + "7645": 6745, + "7646": 6746, + "7647": 6747, + "7648": 6748, + "7649": 6749, + "7650": 6750, + "7651": 6751, + "7652": 6752, + "7653": 6753, + "7654": 6754, + "7655": 6755, + "7656": 6756, + "7657": 6757, + "7658": 6758, + "7659": 6759, + "7660": 6760, + "7661": 6761, + "7662": 6762, + "7663": 6763, + "7664": 6764, + "7665": 6765, + "7666": 6766, + "7667": 6767, + "7668": 6768, + "7669": 6769, + "7670": 6770, + "7671": 6771, + "7672": 6772, + "7673": 6773, + "7674": 6774, + "7675": 6433, + "7676": 6434, + "7677": 6435, + "7678": 6829, + "7679": 6438, + "7680": 6440, + "7681": 6441, + "7682": 6443, + "7683": 6445, + "7684": 6446, + "7685": 6447, + "7686": 6449, + "7687": 6450, + "7688": 6503, + "7689": 6506, + "7690": 5926, + "7691": 6513, + "7692": 6514, + "7693": 6515, + "7694": 6516, + "7695": 6517, + "7696": 6522, + "7697": 6523, + "7698": 6524, + "7699": 6047, + "7700": 5633, + "7701": 5634, + "7702": 6724, + "7703": 3293, + "7704": 6048, + "7705": 5644, + "7706": 6377, + "7707": 6364, + "7708": 6365, + "7709": 6366, + "7710": 108, + "7711": 108, + "7712": 6385, + "7713": 6690, + "7714": 6386, + "7715": 6385, + "7716": 108, + "7717": 6473, + "7718": 4144, + "7719": 4192, + "7720": 6367, + "7721": 6368, + "7722": 6369, + "7723": 6156, + "7724": 6159, + "7725": 6791, + "7726": 6715, + "7727": 2147, + "7728": 4760, + "7729": 5978, + "7730": 6716, + "7731": 3257, + "7732": 3258, + "7733": 3259, + "7734": 3262, + "7735": 3264, + "7736": 1486, + "7737": 1418, + "7738": 1502, + "7739": 6057, + "7740": 3374, + "7741": 5625, + "7742": 5625, + "7743": 5626, + "7744": 5627, + "7745": 6197, + "7746": 108, + "7747": 6718, + "7748": 108, + "7749": 6719, + "7750": 6530, + "7751": 6531, + "7752": 6536, + "7753": 6538, + "7754": 6539, + "7755": 6542, + "7756": 6545, + "7757": 6546, + "7758": 6548, + "7759": 6551, + "7760": 6552, + "7761": 6553, + "7762": 6555, + "7763": 6549, + "7764": 5777, + "7765": 6916, + "7766": 6499, + "7767": 5753, + "7768": 6500, + "7769": 6495, + "7770": 5748, + "7771": 6593, + "7772": 251, + "7773": 5631, + "7774": 6711, + "7775": 6712, + "7776": 3164, + "7777": 3133, + "7778": 6678, + "7779": 3138, + "7780": 3129, + "7781": 6679, + "7782": 6680, + "7783": 6680, + "7784": 6680, + "7785": 3165, + "7786": 4144, + "7787": 4192, + "7788": 4204, + "7789": 6375, + "7790": 6370, + "7791": 6371, + "7792": 6372, + "7793": 6372, + "7794": 6373, + "7795": 6374, + "7796": 6681, + "7797": 1501, + "7798": 108, + "7799": 6052, + "7800": 6052, + "7801": 6053, + "7802": 6054, + "7803": 6566, + "7804": 5970, + "7805": 4130, + "7806": 713, + "7807": 6357, + "7808": 6358, + "7809": 6470, + "7810": 6356, + "7811": 5721, + "7812": 6359, + "7813": 6281, + "7814": 5841, + "7815": 6283, + "7816": 6284, + "7817": 6285, + "7818": 6286, + "7819": 6287, + "7820": 5792, + "7821": 5914, + "7822": 5818, + "7823": 5916, + "7824": 5918, + "7825": 5920, + "7826": 5921, + "7827": 5922, + "7828": 5923, + "7829": 5924, + "7830": 5925, + "7831": 5926, + "7832": 5927, + "7833": 5798, + "7834": 5929, + "7835": 5930, + "7836": 5931, + "7837": 5932, + "7838": 5933, + "7839": 5934, + "7840": 5935, + "7841": 6604, + "7842": 5937, + "7843": 5939, + "7844": 5940, + "7845": 5942, + "7846": 5943, + "7847": 6747, + "7848": 5944, + "7849": 5945, + "7850": 6950, + "7851": 6111, + "7852": 6683, + "7853": 6684, + "7854": 6684, + "7855": 108, + "7856": 6360, + "7857": 6361, + "7858": 6362, + "7859": 6363, + "7860": 6657, + "7861": 6102, + "7862": 6097, + "7863": 6098, + "7864": 6101, + "7865": 5719, + "7866": 5723, + "7867": 4392, + "7868": 5954, + "7869": 108, + "7870": 6567, + "7871": 6568, + "7872": 6569, + "7873": 6570, + "7874": 6571, + "7875": 6572, + "7876": 6573, + "7877": 6574, + "7878": 6575, + "7879": 6576, + "7880": 6577, + "7881": 6578, + "7882": 6579, + "7883": 6580, + "7884": 6581, + "7885": 6582, + "7886": 6583, + "7887": 6584, + "7888": 6585, + "7889": 6586, + "7890": 6587, + "7891": 6588, + "7892": 6589, + "7893": 6590, + "7894": 6591, + "7895": 6592, + "7896": 6593, + "7897": 6594, + "7898": 6595, + "7899": 6596, + "7900": 6597, + "7901": 6598, + "7902": 6599, + "7903": 6600, + "7904": 6601, + "7905": 6602, + "7906": 6582, + "7907": 6603, + "7908": 6604, + "7909": 6605, + "7910": 6606, + "7911": 6607, + "7912": 6608, + "7913": 6609, + "7914": 6610, + "7915": 6611, + "7916": 6612, + "7917": 6585, + "7918": 6613, + "7919": 6614, + "7920": 6615, + "7921": 6616, + "7922": 6617, + "7923": 6618, + "7924": 6619, + "7925": 6620, + "7926": 6621, + "7927": 6622, + "7928": 6623, + "7929": 6624, + "7930": 6625, + "7931": 6626, + "7932": 6627, + "7933": 6628, + "7934": 6629, + "7935": 6630, + "7936": 6631, + "7937": 6632, + "7938": 6633, + "7939": 6634, + "7940": 6635, + "7941": 6636, + "7942": 6637, + "7943": 6638, + "7944": 6639, + "7945": 6640, + "7946": 6641, + "7947": 6642, + "7948": 6585, + "7949": 6643, + "7950": 6644, + "7951": 6645, + "7952": 6586, + "7953": 6646, + "7954": 6647, + "7955": 6648, + "7956": 6649, + "7957": 6650, + "7958": 6651, + "7959": 6652, + "7960": 6562, + "7961": 6563, + "7962": 6554, + "7963": 6540, + "7964": 6532, + "7965": 6456, + "7966": 6457, + "7967": 6458, + "7968": 6459, + "7969": 6460, + "7970": 6461, + "7971": 6462, + "7972": 6463, + "7973": 6464, + "7974": 6465, + "7975": 6466, + "7976": 6468, + "7977": 6469, + "7978": 6734, + "7979": 6467, + "7980": 6727, + "7981": 6427, + "7982": 6430, + "7983": 6428, + "7984": 6511, + "7985": 6487, + "7986": 6749, + "7987": 6495, + "7988": 6491, + "7989": 6493, + "7990": 6493, + "7991": 6402, + "7992": 6396, + "7993": 6397, + "7994": 6400, + "7995": 6401, + "7996": 6564, + "7997": 6564, + "7998": 6501, + "7999": 6501, + "8000": 6501, + "8001": 108, + "8002": 6111, + "8003": 108, + "8004": 6680, + "8005": 6680, + "8006": 6682, + "8007": 6770, + "8008": 6095, + "8009": 6664, + "8010": 6663, + "8011": 6774, + "8012": 5632, + "8013": 6692, + "8014": 6437, + "8015": 6498, + "8016": 541, + "8017": 3306, + "8018": 6296, + "8019": 4953, + "8020": 6395, + "8021": 108, + "8022": 6708, + "8023": 5628, + "8024": 108, + "8025": 108, + "8026": 5640, + "8027": 6518, + "8028": 6529, + "8029": 6723, + "8030": 5923, + "8031": 5846, + "8032": 5845, + "8033": 5844, + "8034": 5898, + "8035": 5936, + "8036": 2234, + "8037": 5801, + "8038": 6285, + "8039": 5817, + "8040": 2234, + "8041": 5832, + "8042": 5833, + "8043": 5834, + "8044": 2236, + "8045": 5578, + "8046": 5852, + "8047": 5829, + "8048": 2236, + "8049": 5578, + "8050": 5578, + "8051": 6284, + "8052": 5970, + "8053": 5659, + "8054": 5964, + "8055": 5660, + "8056": 5660, + "8057": 5967, + "8058": 583, + "8059": 6726, + "8060": 6742, + "8061": 6465, + "8062": 12317, + "8063": 6858, + "8064": 6862, + "8065": 541, + "8067": 6922, + "8068": 3069, + "8069": 6923, + "8070": 6950, + "8071": 5789, + "8072": 6275, + "8073": 6272, + "8075": 6278, + "8076": 6277, + "8077": 6271, + "8078": 5641, + "8079": 5642, + "8080": 6273, + "8081": 6276, + "8082": 6856, + "8083": 6869, + "8084": 6870, + "8085": 6871, + "8086": 6872, + "8087": 6925, + "8088": 6926, + "8089": 6927, + "8090": 6928, + "8091": 6929, + "8092": 6930, + "8093": 6931, + "8094": 6932, + "8095": 6933, + "8096": 6934, + "8097": 6935, + "8098": 6936, + "8099": 6937, + "8100": 6938, + "8101": 6939, + "8102": 6940, + "8103": 5640, + "8104": 5642, + "8105": 5641, + "8106": 5642, + "8107": 6907, + "8108": 6908, + "8109": 6909, + "8110": 6910, + "8111": 6941, + "8112": 637, + "8113": 6391, + "8114": 639, + "8116": 6916, + "8117": 6917, + "8118": 6522, + "8119": 6646, + "8120": 6897, + "8121": 6896, + "8122": 6898, + "8123": 6899, + "8124": 6900, + "8125": 6901, + "8126": 6902, + "8127": 6903, + "8128": 6905, + "8129": 6904, + "8130": 6906, + "8131": 6945, + "8132": 6953, + "8133": 6952, + "8134": 6951, + "8135": 6942, + "8136": 6943, + "8137": 6944, + "8138": 6945, + "8139": 6946, + "8140": 6853, + "8141": 6847, + "8142": 6848, + "8143": 6849, + "8144": 6850, + "8145": 6851, + "8146": 6385, + "8147": 6911, + "8148": 4130, + "8149": 5978, + "8150": 4133, + "8151": 6912, + "8152": 6971, + "8153": 5970, + "8154": 6721, + "8155": 6913, + "8156": 5964, + "8157": 6386, + "8158": 6914, + "8159": 1482, + "8160": 2210, + "8161": 2612, + "8162": 2628, + "8163": 2630, + "8164": 2631, + "8165": 2632, + "8166": 6958, + "8167": 6957, + "8168": 3210, + "8169": 3204, + "8171": 6854, + "8172": 6855, + "8174": 6817, + "8175": 6808, + "8176": 6811, + "8177": 6810, + "8178": 6807, + "8179": 6812, + "8180": 6813, + "8181": 6814, + "8182": 6815, + "8183": 6809, + "8184": 6816, + "8185": 6818, + "8186": 6819, + "8187": 6820, + "8188": 6821, + "8189": 6822, + "8190": 6823, + "8191": 6824, + "8192": 6825, + "8193": 6826, + "8194": 6827, + "8195": 6828, + "8196": 6829, + "8197": 6830, + "8198": 6831, + "8199": 6832, + "8200": 6835, + "8201": 6834, + "8202": 6833, + "8203": 6836, + "8204": 6837, + "8205": 6838, + "8206": 6839, + "8207": 6840, + "8208": 6841, + "8209": 6842, + "8210": 6843, + "8211": 6844, + "8212": 6845, + "8213": 6846, + "8214": 6863, + "8215": 6864, + "8217": 6915, + "8218": 6916, + "8219": 6917, + "8220": 6918, + "8221": 6919, + "8222": 6920, + "8223": 6921, + "8224": 7147, + "8225": 7167, + "8226": 7168, + "8227": 7034, + "8228": 6865, + "8229": 6866, + "8230": 6941, + "8231": 7038, + "8232": 6873, + "8233": 6874, + "8234": 6875, + "8235": 6876, + "8236": 6876, + "8237": 6877, + "8238": 6878, + "8239": 6878, + "8240": 6879, + "8241": 6880, + "8242": 6881, + "8243": 6881, + "8244": 6882, + "8245": 6884, + "8246": 6890, + "8247": 6886, + "8248": 6888, + "8249": 6887, + "8250": 6885, + "8251": 6889, + "8252": 6890, + "8253": 6891, + "8254": 6961, + "8255": 6962, + "8256": 6963, + "8257": 6964, + "8258": 6965, + "8259": 6966, + "8260": 7184, + "8261": 7147, + "8262": 5746, + "8263": 5743, + "8264": 5744, + "8265": 5745, + "8266": 6967, + "8267": 5746, + "8268": 5743, + "8269": 5744, + "8270": 7036, + "8271": 108, + "8272": 108, + "8273": 6949, + "8274": 6954, + "8275": 6955, + "8276": 6956, + "8277": 6961, + "8280": 117, + "8282": 6958, + "8285": 6969, + "8286": 6967, + "8287": 7143, + "8288": 7160, + "8289": 7144, + "8290": 6959, + "8291": 6567, + "8292": 6568, + "8293": 6569, + "8294": 6570, + "8295": 6571, + "8296": 6572, + "8297": 6573, + "8298": 6574, + "8299": 6575, + "8300": 6576, + "8301": 6577, + "8302": 6578, + "8303": 6579, + "8304": 6580, + "8305": 6581, + "8306": 6582, + "8307": 6583, + "8308": 6584, + "8309": 6585, + "8310": 6586, + "8311": 6587, + "8312": 6588, + "8313": 6589, + "8314": 6590, + "8315": 6591, + "8316": 6592, + "8317": 6593, + "8318": 6594, + "8319": 6595, + "8320": 6596, + "8321": 6597, + "8322": 6598, + "8323": 6599, + "8324": 6600, + "8325": 6601, + "8326": 6602, + "8327": 6582, + "8328": 6603, + "8329": 6604, + "8330": 6605, + "8331": 6606, + "8332": 6607, + "8333": 6608, + "8334": 6609, + "8335": 6610, + "8336": 6611, + "8337": 6612, + "8338": 6585, + "8339": 6613, + "8340": 6614, + "8341": 6615, + "8342": 6616, + "8343": 6617, + "8344": 6618, + "8345": 6619, + "8346": 6620, + "8347": 6621, + "8348": 6622, + "8349": 6623, + "8350": 6624, + "8351": 6625, + "8352": 6626, + "8353": 6627, + "8354": 6628, + "8355": 6629, + "8356": 6630, + "8357": 6631, + "8358": 6632, + "8359": 6633, + "8360": 6634, + "8361": 6635, + "8362": 6636, + "8363": 6637, + "8364": 6638, + "8365": 6639, + "8366": 6640, + "8367": 6641, + "8368": 6642, + "8369": 7012, + "8370": 7003, + "8371": 7006, + "8372": 7005, + "8373": 210, + "8374": 7007, + "8375": 6960, + "8376": 6968, + "8377": 6969, + "8378": 7114, + "8379": 7115, + "8380": 6994, + "8381": 6995, + "8382": 7016, + "8383": 6996, + "8384": 7001, + "8385": 6999, + "8386": 7015, + "8387": 7074, + "8388": 7055, + "8389": 108, + "8390": 7056, + "8391": 7057, + "8392": 7058, + "8393": 7058, + "8394": 7144, + "8395": 7107, + "8396": 7108, + "8397": 7109, + "8398": 7110, + "8399": 7111, + "8400": 7112, + "8401": 7107, + "8402": 7108, + "8403": 7109, + "8404": 7110, + "8405": 7111, + "8406": 7112, + "8407": 7116, + "8408": 7059, + "8409": 7060, + "8410": 7061, + "8411": 7062, + "8412": 7063, + "8413": 7064, + "8414": 7065, + "8415": 7066, + "8416": 7067, + "8417": 7068, + "8418": 7069, + "8419": 2642, + "8420": 7071, + "8421": 6972, + "8422": 6973, + "8423": 6974, + "8424": 6975, + "8425": 6976, + "8426": 6977, + "8427": 6978, + "8428": 6979, + "8429": 6980, + "8430": 6981, + "8431": 7113, + "8432": 7113, + "8433": 7182, + "8434": 7181, + "8435": 7092, + "8436": 7093, + "8437": 7094, + "8438": 7095, + "8439": 7092, + "8440": 7093, + "8441": 7094, + "8442": 7095, + "8443": 7000, + "8444": 6998, + "8445": 7002, + "8446": 7007, + "8447": 7005, + "8448": 7004, + "8449": 7003, + "8450": 7006, + "8451": 7009, + "8452": 7008, + "8453": 7010, + "8454": 7011, + "8455": 7012, + "8456": 7013, + "8457": 7014, + "8458": 7096, + "8459": 7097, + "8460": 7098, + "8461": 7183, + "8462": 7105, + "8463": 7099, + "8465": 7106, + "8466": 108, + "8467": 108, + "8468": 6200, + "8469": 6203, + "8470": 6997, + "8471": 6982, + "8472": 6982, + "8473": 6982, + "8474": 6983, + "8475": 6983, + "8476": 6983, + "8477": 6986, + "8478": 6984, + "8479": 6985, + "8480": 6987, + "8481": 6988, + "8482": 6989, + "8483": 7148, + "8484": 7149, + "8485": 7150, + "8486": 7166, + "8487": 7151, + "8488": 6990, + "8489": 7221, + "8490": 6173, + "8491": 6174, + "8492": 6175, + "8493": 6175, + "8494": 6176, + "8495": 7221, + "8496": 6173, + "8497": 6174, + "8498": 6175, + "8499": 6175, + "8500": 6176, + "8501": 6991, + "8502": 5574, + "8503": 5239, + "8504": 6992, + "8505": 108, + "8506": 6891, + "8507": 5834, + "8508": 5834, + "8509": 5834, + "8510": 7127, + "8511": 7126, + "8512": 7125, + "8513": 7127, + "8514": 7126, + "8515": 7125, + "8516": 7124, + "8517": 7122, + "8518": 7123, + "8519": 7075, + "8520": 7126, + "8521": 7126, + "8522": 7124, + "8523": 7122, + "8524": 7123, + "8525": 7120, + "8526": 7073, + "8527": 7127, + "8528": 7131, + "8529": 7131, + "8530": 7130, + "8531": 7131, + "8532": 7080, + "8533": 7081, + "8534": 7082, + "8535": 7083, + "8536": 7084, + "8537": 7085, + "8538": 7086, + "8539": 7087, + "8540": 7088, + "8541": 7089, + "8542": 7090, + "8543": 6993, + "8544": 7119, + "8545": 7093, + "8546": 7093, + "8547": 7169, + "8548": 7170, + "8549": 7171, + "8550": 7172, + "8551": 7149, + "8552": 7149, + "8553": 7149, + "8554": 7177, + "8555": 7178, + "8556": 7149, + "8557": 7149, + "8558": 7149, + "8559": 7145, + "8560": 7146, + "8561": 7212, + "8562": 7196, + "8563": 7214, + "8564": 7129, + "8565": 7129, + "8566": 7091, + "8567": 7152, + "8568": 7153, + "8569": 7154, + "8570": 7155, + "8571": 7224, + "8572": 7156, + "8573": 7158, + "8574": 7160, + "8575": 7161, + "8576": 7157, + "8577": 7017, + "8578": 7018, + "8579": 7019, + "8580": 7020, + "8581": 7021, + "8582": 7022, + "8583": 7023, + "8584": 7024, + "8585": 7025, + "8586": 7026, + "8587": 7027, + "8588": 7028, + "8589": 7029, + "8590": 7030, + "8591": 7031, + "8592": 7032, + "8593": 7033, + "8594": 7034, + "8595": 7035, + "8596": 7152, + "8597": 7173, + "8598": 7174, + "8599": 7175, + "8600": 108, + "8601": 108, + "8602": 108, + "8603": 108, + "8604": 7176, + "8605": 7150, + "8606": 7142, + "8607": 7141, + "8608": 6057, + "8609": 1486, + "8610": 3374, + "8611": 5625, + "8612": 5625, + "8613": 7110, + "8614": 7140, + "8615": 7139, + "8616": 7230, + "8617": 7087, + "8618": 108, + "8619": 7128, + "8620": 4130, + "8621": 5978, + "8622": 6381, + "8623": 7036, + "8624": 7054, + "8625": 4148, + "8626": 5579, + "8627": 5577, + "8628": 5581, + "8629": 7137, + "8630": 7138, + "8631": 6203, + "8632": 7036, + "8633": 7136, + "8634": 7126, + "8635": 7144, + "8636": 6984, + "8637": 7037, + "8638": 7038, + "8639": 7039, + "8640": 7040, + "8641": 6993, + "8642": 7041, + "8643": 7042, + "8644": 6993, + "8645": 7043, + "8646": 6985, + "8647": 7044, + "8648": 7045, + "8649": 7046, + "8650": 7047, + "8651": 108, + "8652": 108, + "8653": 7052, + "8654": 7048, + "8655": 17, + "8656": 7096, + "8657": 7097, + "8658": 7098, + "8659": 7310, + "8660": 7100, + "8661": 7101, + "8662": 7200, + "8663": 7201, + "8664": 7202, + "8665": 7203, + "8666": 7204, + "8667": 7050, + "8668": 7049, + "8669": 6993, + "8670": 7222, + "8671": 7051, + "8672": 7222, + "8673": 6982, + "8674": 7053, + "8675": 6983, + "8676": 7186, + "8677": 6982, + "8678": 6983, + "8679": 7126, + "8680": 7126, + "8681": 7053, + "8682": 7187, + "8683": 6982, + "8684": 7162, + "8685": 7161, + "8686": 7161, + "8687": 6983, + "8688": 7188, + "8689": 7163, + "8690": 7164, + "8691": 7165, + "8692": 7189, + "8693": 6982, + "8694": 7185, + "8695": 7159, + "8696": 7190, + "8697": 6982, + "8698": 7185, + "8699": 7191, + "8700": 7185, + "8701": 7192, + "8702": 6988, + "8703": 6983, + "8704": 6988, + "8705": 7193, + "8706": 7194, + "8707": 7195, + "8708": 6993, + "8709": 7196, + "8710": 7197, + "8711": 6983, + "8712": 7198, + "8713": 7199, + "8714": 6982, + "8715": 6983, + "8716": 108, + "8717": 108, + "8718": 108, + "8719": 108, + "8720": 7225, + "8721": 7225, + "8722": 1644, + "8723": 1645, + "8724": 1647, + "8725": 1648, + "8726": 2091, + "8727": 1801, + "8728": 1803, + "8729": 1804, + "8730": 1185, + "8731": 1186, + "8732": 2143, + "8733": 5563, + "8734": 2137, + "8735": 2138, + "8736": 2324, + "8737": 7206, + "8738": 7207, + "8739": 7208, + "8740": 7209, + "8741": 7210, + "8742": 7211, + "8743": 108, + "8744": 7212, + "8745": 7213, + "8746": 7214, + "8747": 7215, + "8748": 7216, + "8749": 7217, + "8750": 7218, + "8751": 7219, + "8752": 7220, + "8754": 7205, + "8755": 7229, + "8756": 7202, + "8757": 7231, + "8758": 7232, + "8759": 7227, + "8760": 7228, + "8761": 7476, + "8762": 7537, + "8763": 7477, + "8764": 7226, + "8765": 7233, + "8766": 7233, + "8767": 7234, + "8768": 7234, + "8769": 7229, + "8770": 7230, + "8771": 1694, + "8772": 7227, + "8773": 7228, + "8774": 7476, + "8775": 7537, + "8776": 7477, + "8777": 7226, + "8778": 7233, + "8779": 7234, + "8780": 7206, + "8781": 1185, + "8782": 1801, + "8783": 1644, + "8784": 887, + "8785": 7478, + "8786": 7479, + "8787": 7070, + "8788": 7100, + "8789": 7235, + "8790": 108, + "8791": 6945, + "8792": 7494, + "8793": 7236, + "8794": 7245, + "8795": 7246, + "8796": 7247, + "8797": 7237, + "8798": 7238, + "8799": 7239, + "8800": 7244, + "8801": 6943, + "8802": 7403, + "8803": 7404, + "8804": 7405, + "8805": 7406, + "8806": 7407, + "8807": 7408, + "8808": 7409, + "8809": 7410, + "8810": 7411, + "8811": 7412, + "8812": 7413, + "8813": 7414, + "8814": 7415, + "8815": 7413, + "8816": 7416, + "8817": 7417, + "8818": 7418, + "8819": 7419, + "8820": 7420, + "8821": 7421, + "8822": 7422, + "8823": 7423, + "8824": 7231, + "8825": 7424, + "8826": 7425, + "8827": 7426, + "8828": 7427, + "8829": 7428, + "8830": 7429, + "8831": 7430, + "8832": 7431, + "8833": 7432, + "8834": 7433, + "8835": 7434, + "8836": 7435, + "8837": 7436, + "8838": 7437, + "8839": 7438, + "8840": 7439, + "8841": 7440, + "8842": 7441, + "8843": 7442, + "8844": 7443, + "8845": 7444, + "8846": 7445, + "8847": 7446, + "8848": 7447, + "8849": 7448, + "8850": 7449, + "8851": 7450, + "8852": 7451, + "8853": 7452, + "8854": 7453, + "8855": 7454, + "8856": 7455, + "8857": 7456, + "8858": 7457, + "8859": 7458, + "8860": 7459, + "8861": 7460, + "8862": 7461, + "8863": 7462, + "8864": 7463, + "8865": 7582, + "8866": 7244, + "8867": 7244, + "8868": 7223, + "8869": 7224, + "8870": 108, + "8871": 7381, + "8873": 7262, + "8874": 7263, + "8875": 7264, + "8876": 7265, + "8877": 7266, + "8878": 7267, + "8879": 7268, + "8880": 7269, + "8881": 7270, + "8882": 7271, + "8883": 7272, + "8884": 7273, + "8885": 7274, + "8886": 7275, + "8887": 7276, + "8888": 7277, + "8889": 7278, + "8890": 7279, + "8891": 7280, + "8892": 7281, + "8893": 7282, + "8894": 7283, + "8895": 7284, + "8896": 7285, + "8897": 7286, + "8898": 7287, + "8899": 7288, + "8900": 7289, + "8901": 7290, + "8902": 7291, + "8903": 7292, + "8904": 7293, + "8905": 7294, + "8906": 7295, + "8907": 7296, + "8908": 7297, + "8909": 7298, + "8910": 7299, + "8911": 7300, + "8912": 7301, + "8913": 7302, + "8914": 7303, + "8915": 7304, + "8916": 7305, + "8917": 7306, + "8918": 7307, + "8919": 7308, + "8920": 7309, + "8921": 7310, + "8922": 7305, + "8923": 7312, + "8924": 7313, + "8925": 7314, + "8926": 7315, + "8927": 7316, + "8928": 7317, + "8929": 7318, + "8930": 7319, + "8931": 7320, + "8932": 7321, + "8933": 7322, + "8934": 7323, + "8935": 7324, + "8936": 7325, + "8937": 7326, + "8938": 7327, + "8939": 7328, + "8940": 7329, + "8941": 7330, + "8942": 7331, + "8943": 7332, + "8944": 7333, + "8945": 7334, + "8946": 7335, + "8947": 7336, + "8948": 7337, + "8949": 7338, + "8950": 7339, + "8951": 7340, + "8952": 7341, + "8953": 7265, + "8954": 7342, + "8955": 7343, + "8956": 7344, + "8957": 7345, + "8958": 7346, + "8959": 7347, + "8960": 7348, + "8961": 7349, + "8962": 7350, + "8963": 7351, + "8964": 7352, + "8965": 7353, + "8966": 7354, + "8967": 7355, + "8968": 7356, + "8969": 7357, + "8970": 7358, + "8971": 7359, + "8972": 7360, + "8973": 7361, + "8974": 7362, + "8975": 7363, + "8976": 7364, + "8977": 7365, + "8978": 7366, + "8979": 7367, + "8980": 7368, + "8981": 7369, + "8982": 7370, + "8983": 7371, + "8984": 7372, + "8985": 7373, + "8986": 7374, + "8987": 7375, + "8988": 7376, + "8989": 7377, + "8990": 7378, + "8991": 7379, + "8992": 7380, + "8993": 7381, + "8994": 7382, + "8995": 7584, + "8996": 7384, + "8997": 7385, + "8998": 7386, + "8999": 7387, + "9000": 7388, + "9001": 7389, + "9002": 7390, + "9005": 7412, + "9007": 7385, + "9008": 7385, + "9009": 7364, + "9011": 7258, + "9012": 7259, + "9013": 7260, + "9014": 7260, + "9015": 7261, + "9017": 7240, + "9018": 6996, + "9019": 7241, + "9020": 11419, + "9021": 7396, + "9022": 7397, + "9023": 7398, + "9024": 7250, + "9025": 7251, + "9026": 7252, + "9027": 5978, + "9028": 7253, + "9029": 7254, + "9030": 7254, + "9031": 7255, + "9032": 7256, + "9033": 7402, + "9034": 7402, + "9035": 7257, + "9036": 7401, + "9037": 7248, + "9038": 7250, + "9039": 7242, + "9040": 7243, + "9041": 7240, + "9042": 7392, + "9043": 7392, + "9044": 7392, + "9045": 7393, + "9046": 7393, + "9047": 7393, + "9048": 7394, + "9049": 7394, + "9050": 7394, + "9051": 7394, + "9052": 7610, + "9053": 7610, + "9054": 7610, + "9055": 7610, + "9056": 7610, + "9057": 7610, + "9058": 7610, + "9059": 7610, + "9060": 7610, + "9061": 7610, + "9062": 13885, + "9063": 7526, + "9064": 7527, + "9065": 7528, + "9066": 7512, + "9067": 7513, + "9068": 7512, + "9069": 7464, + "9070": 7464, + "9071": 7464, + "9072": 7464, + "9073": 7465, + "9074": 7465, + "9075": 7465, + "9076": 7465, + "9077": 7466, + "9078": 7466, + "9079": 7466, + "9080": 7466, + "9081": 7467, + "9082": 7467, + "9083": 7467, + "9084": 7467, + "9085": 7468, + "9086": 7468, + "9087": 7468, + "9088": 7468, + "9089": 7468, + "9090": 7469, + "9091": 7470, + "9092": 7471, + "9093": 7472, + "9094": 7469, + "9095": 7470, + "9096": 7471, + "9097": 7472, + "9098": 7469, + "9099": 7470, + "9100": 7471, + "9101": 7472, + "9102": 7469, + "9103": 7470, + "9104": 7471, + "9105": 7472, + "9106": 7469, + "9107": 7470, + "9108": 7471, + "9109": 7472, + "9110": 7469, + "9111": 7520, + "9112": 7521, + "9113": 7391, + "9114": 7516, + "9115": 7517, + "9116": 7517, + "9117": 7399, + "9118": 7497, + "9119": 7498, + "9120": 7514, + "9121": 7515, + "9122": 7473, + "9123": 7508, + "9124": 7509, + "9125": 7510, + "9126": 7511, + "9127": 7508, + "9128": 7508, + "9129": 7495, + "9130": 7669, + "9131": 7670, + "9132": 7671, + "9133": 7701, + "9134": 7496, + "9135": 7495, + "9136": 7524, + "9137": 7525, + "9138": 7524, + "9139": 7518, + "9140": 7519, + "9141": 7518, + "9142": 7518, + "9143": 7518, + "9144": 7503, + "9145": 7504, + "9146": 7503, + "9147": 7523, + "9148": 7523, + "9149": 7523, + "9150": 7523, + "9151": 7524, + "9152": 7475, + "9153": 7522, + "9154": 7249, + "9155": 7499, + "9156": 7501, + "9157": 7502, + "9158": 7499, + "9159": 7505, + "9160": 7505, + "9161": 7505, + "9162": 7505, + "9163": 7533, + "9164": 7647, + "9165": 7648, + "9166": 7649, + "9167": 7650, + "9168": 7651, + "9169": 7652, + "9170": 7653, + "9171": 7654, + "9172": 7655, + "9173": 7656, + "9174": 7658, + "9175": 7506, + "9176": 7507, + "9177": 7475, + "9178": 7567, + "9179": 7248, + "9180": 7534, + "9181": 7248, + "9182": 7532, + "9183": 7531, + "9184": 7536, + "9185": 7480, + "9186": 7483, + "9187": 7484, + "9188": 7487, + "9189": 7488, + "9190": 7474, + "9191": 7481, + "9192": 7482, + "9193": 7485, + "9194": 7486, + "9195": 7489, + "9196": 7490, + "9197": 7491, + "9198": 7492, + "9199": 7493, + "9200": 7535, + "9201": 7529, + "9202": 7530, + "9203": 7568, + "9204": 7569, + "9205": 3045, + "9206": 7529, + "9207": 7529, + "9208": 12904, + "9209": 1386, + "9210": 13438, + "9211": 10933, + "9212": 9255, + "9213": 8339, + "9214": 9490, + "9215": 12898, + "9216": 2332, + "9217": 9486, + "9218": 8543, + "9219": 12951, + "9220": 10153, + "9221": 9442, + "9222": 7445, + "9223": 7201, + "9224": 12267, + "9225": 9912, + "9226": 9854, + "9227": 5020, + "9228": 10661, + "9229": 12902, + "9230": 10044, + "9231": 2329, + "9232": 13835, + "9233": 7328, + "9234": 108, + "9235": 7583, + "9236": 10169, + "9237": 9506, + "9238": 5780, + "9239": 2356, + "9240": 13084, + "9241": 7667, + "9242": 7668, + "9243": 7675, + "9244": 7676, + "9245": 7677, + "9246": 7678, + "9247": 7679, + "9248": 7680, + "9249": 7681, + "9250": 7682, + "9251": 7683, + "9252": 7684, + "9253": 7685, + "9254": 7686, + "9255": 7687, + "9256": 7688, + "9257": 7660, + "9258": 7661, + "9259": 7662, + "9260": 7665, + "9261": 8099, + "9262": 7663, + "9263": 7659, + "9264": 7650, + "9265": 7672, + "9266": 7673, + "9267": 7674, + "9268": 7672, + "9269": 7691, + "9270": 7694, + "9271": 7692, + "9272": 7693, + "9273": 7691, + "9274": 7694, + "9275": 7692, + "9276": 7693, + "9285": 7889, + "9286": 7890, + "9288": 7641, + "9289": 7641, + "9290": 7643, + "9292": 7645, + "9293": 7646, + "9294": 7641, + "9295": 7641, + "9296": 7643, + "9298": 7645, + "9299": 7646, + "9300": 7582, + "9303": 7585, + "9305": 7702, + "9306": 7725, + "9307": 7703, + "9308": 7705, + "9311": 7702, + "9312": 7707, + "9313": 7708, + "9314": 7709, + "9315": 7710, + "9316": 7702, + "9317": 7725, + "9318": 7703, + "9319": 7704, + "9320": 7705, + "9323": 7702, + "9324": 7711, + "9325": 7714, + "9326": 7713, + "9327": 7712, + "9329": 7695, + "9330": 7696, + "9331": 7697, + "9332": 7698, + "9334": 7700, + "9335": 7695, + "9337": 7699, + "9339": 7633, + "9340": 7635, + "9341": 7633, + "9342": 7635, + "9343": 7636, + "9344": 7637, + "9345": 7638, + "9346": 7639, + "9347": 7726, + "9348": 7727, + "9349": 7729, + "9350": 7731, + "9351": 7736, + "9352": 7739, + "9353": 7740, + "9354": 7742, + "9355": 7746, + "9356": 7748, + "9357": 7750, + "9358": 7753, + "9359": 7754, + "9360": 7756, + "9361": 7759, + "9362": 7760, + "9363": 7763, + "9364": 7847, + "9365": 8345, + "9366": 8344, + "9367": 8343, + "9368": 8342, + "9369": 8345, + "9370": 8344, + "9371": 8343, + "9372": 8341, + "9373": 8341, + "9374": 8272, + "9375": 7718, + "9376": 6152, + "9377": 6153, + "9378": 7716, + "9379": 6148, + "9380": 7771, + "9381": 7772, + "9382": 7772, + "9383": 7773, + "9384": 7773, + "9385": 7771, + "9386": 7772, + "9387": 7771, + "9388": 7773, + "9389": 7773, + "9390": 7771, + "9391": 7772, + "9392": 7774, + "9393": 7771, + "9394": 7771, + "9395": 7774, + "9396": 7772, + "9397": 7774, + "9398": 7773, + "9399": 7772, + "9400": 7771, + "9401": 7775, + "9402": 7775, + "9403": 7775, + "9404": 7776, + "9405": 7776, + "9406": 7776, + "9407": 7777, + "9408": 7778, + "9409": 7777, + "9410": 7779, + "9411": 7779, + "9412": 7779, + "9413": 7780, + "9414": 7780, + "9415": 7781, + "9416": 7783, + "9417": 7782, + "9418": 7782, + "9419": 7785, + "9420": 7784, + "9421": 7784, + "9422": 7786, + "9423": 7787, + "9424": 7788, + "9425": 7789, + "9426": 7790, + "9427": 7791, + "9428": 7792, + "9429": 7793, + "9430": 7794, + "9431": 7795, + "9432": 7796, + "9433": 7797, + "9434": 7798, + "9435": 7799, + "9436": 7800, + "9437": 7801, + "9438": 7802, + "9439": 7803, + "9440": 7804, + "9441": 7805, + "9442": 7806, + "9443": 7807, + "9444": 7808, + "9445": 7809, + "9446": 7810, + "9447": 7811, + "9448": 7812, + "9449": 7813, + "9450": 7814, + "9451": 7815, + "9452": 7816, + "9453": 7817, + "9454": 7818, + "9455": 7819, + "9456": 7820, + "9457": 7821, + "9458": 7822, + "9459": 7823, + "9460": 7824, + "9461": 7825, + "9462": 7826, + "9463": 7827, + "9464": 7828, + "9465": 7829, + "9466": 7830, + "9467": 7831, + "9468": 7832, + "9469": 7833, + "9470": 7834, + "9471": 7835, + "9472": 7836, + "9473": 7837, + "9474": 7838, + "9475": 7839, + "9476": 7840, + "9477": 7841, + "9478": 7842, + "9479": 7843, + "9480": 7844, + "9481": 7845, + "9482": 7846, + "9483": 7847, + "9484": 7848, + "9485": 7849, + "9486": 7658, + "9487": 7578, + "9488": 7579, + "9489": 7580, + "9490": 7581, + "9491": 7939, + "9492": 7784, + "9493": 7856, + "9494": 108, + "9495": 7871, + "9496": 7872, + "9497": 7873, + "9498": 7874, + "9499": 8264, + "9500": 7876, + "9501": 7877, + "9502": 7878, + "9503": 7879, + "9504": 7880, + "9505": 7881, + "9506": 7882, + "9507": 7895, + "9508": 7884, + "9509": 7885, + "9510": 7886, + "9511": 7887, + "9512": 7888, + "9513": 7896, + "9514": 7897, + "9515": 7898, + "9516": 7895, + "9517": 6154, + "9518": 7715, + "9519": 6196, + "9520": 6336, + "9521": 2823, + "9522": 7718, + "9523": 7585, + "9524": 7586, + "9525": 7587, + "9526": 7588, + "9527": 7589, + "9528": 7590, + "9529": 7591, + "9530": 7627, + "9531": 7593, + "9532": 7622, + "9533": 7595, + "9534": 7596, + "9535": 7597, + "9536": 7598, + "9537": 7599, + "9538": 7600, + "9539": 7601, + "9540": 7602, + "9541": 7603, + "9542": 7604, + "9543": 7605, + "9544": 7606, + "9545": 7607, + "9546": 7608, + "9547": 7609, + "9548": 7934, + "9549": 163, + "9550": 7935, + "9551": 7759, + "9552": 8265, + "9553": 7732, + "9554": 7733, + "9555": 7934, + "9557": 7731, + "9558": 7731, + "9559": 9147, + "9560": 7628, + "9561": 7727, + "9562": 7728, + "9563": 7620, + "9564": 7592, + "9565": 7594, + "9566": 7621, + "9567": 7743, + "9568": 7744, + "9569": 7629, + "9570": 7742, + "9571": 7630, + "9572": 7747, + "9573": 7623, + "9574": 7631, + "9575": 7719, + "9576": 7745, + "9577": 7720, + "9578": 7721, + "9579": 7730, + "9580": 7756, + "9581": 7757, + "9582": 7758, + "9583": 7722, + "9584": 7702, + "9585": 7723, + "9586": 7598, + "9587": 7598, + "9588": 7598, + "9589": 7764, + "9590": 7724, + "9591": 7248, + "9592": 7765, + "9593": 7766, + "9594": 7893, + "9595": 7751, + "9596": 7752, + "9597": 7248, + "9598": 7768, + "9599": 7769, + "9600": 7770, + "9601": 7767, + "9603": 7750, + "9604": 7750, + "9605": 7750, + "9606": 7748, + "9607": 7749, + "9610": 7248, + "9611": 7702, + "9612": 7737, + "9613": 7738, + "9614": 8590, + "9615": 7761, + "9616": 7762, + "9617": 8589, + "9618": 8586, + "9619": 8587, + "9620": 108, + "9621": 7741, + "9622": 7696, + "9623": 7696, + "9627": 7689, + "9628": 7755, + "9629": 7718, + "9630": 7642, + "9631": 7642, + "9632": 7726, + "9634": 7850, + "9635": 7851, + "9636": 7739, + "9637": 7739, + "9638": 7852, + "9639": 7739, + "9640": 7769, + "9641": 7909, + "9642": 7853, + "9643": 9066, + "9644": 108, + "9645": 108, + "9646": 7664, + "9647": 7857, + "9648": 7858, + "9649": 7861, + "9650": 7862, + "9651": 108, + "9652": 7895, + "9653": 7861, + "9654": 7664, + "9655": 7919, + "9656": 7920, + "9657": 7921, + "9658": 7801, + "9659": 8336, + "9660": 7919, + "9661": 8076, + "9662": 8077, + "9663": 7725, + "9664": 8078, + "9665": 8079, + "9666": 8080, + "9667": 8081, + "9668": 8082, + "9669": 8083, + "9672": 8086, + "9673": 7845, + "9674": 137, + "9676": 8089, + "9677": 8090, + "9678": 8092, + "9680": 8044, + "9681": 8045, + "9682": 8085, + "9683": 9106, + "9684": 8084, + "9685": 8087, + "9686": 8088, + "9687": 7899, + "9688": 7900, + "9689": 7901, + "9690": 7855, + "9691": 7946, + "9692": 7976, + "9693": 7977, + "9694": 7978, + "9695": 7979, + "9696": 7980, + "9697": 7947, + "9698": 7948, + "9699": 7950, + "9700": 7949, + "9701": 7951, + "9702": 7952, + "9703": 7953, + "9704": 7981, + "9705": 7982, + "9706": 7983, + "9707": 7984, + "9708": 7922, + "9709": 7930, + "9710": 7923, + "9711": 7924, + "9712": 7925, + "9713": 7927, + "9714": 7928, + "9715": 7929, + "9716": 7922, + "9717": 7930, + "9718": 7927, + "9719": 7928, + "9720": 7926, + "9721": 7929, + "9722": 7906, + "9723": 7891, + "9724": 7892, + "9725": 7570, + "9726": 7571, + "9727": 7572, + "9728": 7573, + "9729": 7574, + "9730": 7575, + "9731": 7576, + "9732": 7657, + "9733": 7973, + "9734": 7974, + "9735": 7975, + "9736": 108, + "9737": 108, + "9738": 108, + "9739": 108, + "9740": 108, + "9741": 7879, + "9742": 108, + "9743": 8002, + "9744": 108, + "9745": 7875, + "9746": 8922, + "9747": 7871, + "9748": 7872, + "9749": 7955, + "9750": 7874, + "9751": 7875, + "9752": 7879, + "9753": 7880, + "9754": 108, + "9755": 7973, + "9756": 10216, + "9757": 8922, + "9758": 750, + "9759": 7931, + "9760": 7932, + "9761": 7933, + "9762": 7934, + "9763": 7935, + "9764": 7936, + "9765": 7937, + "9766": 8133, + "9768": 7976, + "9769": 7981, + "9770": 7915, + "9771": 7916, + "9772": 7917, + "9773": 7865, + "9774": 7866, + "9775": 7867, + "9776": 7868, + "9777": 7869, + "9778": 7870, + "9779": 8922, + "9780": 7912, + "9781": 7913, + "9782": 7914, + "9783": 7911, + "9784": 7918, + "9785": 7910, + "9786": 7908, + "9787": 7985, + "9788": 7986, + "9789": 7987, + "9790": 7988, + "9791": 7989, + "9792": 7990, + "9793": 7991, + "9794": 8922, + "9795": 7992, + "9796": 7993, + "9797": 7994, + "9798": 7995, + "9799": 7996, + "9800": 7997, + "9801": 7998, + "9802": 7999, + "9803": 8000, + "9804": 8001, + "9805": 8002, + "9806": 8003, + "9807": 8004, + "9808": 7896, + "9809": 7896, + "9810": 7896, + "9811": 7894, + "9812": 1649, + "9813": 8922, + "9814": 7930, + "9815": 7930, + "9816": 7930, + "9817": 7930, + "9818": 7968, + "9819": 7969, + "9820": 7968, + "9821": 7970, + "9822": 7971, + "9823": 7970, + "9824": 7970, + "9825": 7968, + "9826": 7970, + "9827": 7871, + "9828": 7872, + "9829": 7873, + "9830": 7874, + "9831": 7875, + "9832": 7879, + "9833": 8922, + "9834": 8922, + "9835": 7972, + "9836": 7902, + "9837": 7903, + "9838": 5915, + "9839": 5915, + "9840": 7904, + "9841": 7970, + "9842": 7930, + "9843": 8107, + "9844": 8108, + "9845": 7985, + "9846": 7986, + "9847": 7991, + "9848": 8129, + "9849": 8252, + "9850": 8250, + "9851": 8249, + "9852": 8248, + "9853": 7916, + "9854": 8251, + "9855": 8129, + "9856": 8129, + "9857": 8132, + "9858": 8130, + "9859": 9040, + "9860": 8032, + "9861": 8060, + "9862": 8061, + "9863": 8061, + "9864": 8063, + "9865": 7664, + "9866": 6039, + "9867": 7537, + "9868": 6039, + "9869": 7537, + "9870": 9293, + "9871": 6042, + "9872": 6040, + "9873": 7986, + "9874": 6040, + "9875": 3293, + "9876": 3211, + "9877": 5574, + "9878": 7036, + "9879": 7867, + "9880": 6094, + "9881": 6094, + "9882": 7941, + "9883": 8015, + "9884": 8011, + "9885": 8014, + "9886": 8008, + "9887": 8012, + "9888": 8013, + "9889": 8009, + "9890": 8010, + "9891": 8016, + "9892": 8017, + "9893": 8018, + "9894": 8019, + "9895": 8020, + "9896": 8021, + "9897": 8022, + "9898": 8023, + "9899": 8024, + "9900": 8025, + "9901": 8026, + "9902": 8027, + "9903": 8028, + "9904": 8029, + "9905": 8030, + "9906": 8031, + "9907": 8032, + "9908": 8033, + "9909": 8034, + "9910": 8035, + "9911": 8036, + "9912": 8037, + "9913": 8038, + "9914": 8039, + "9915": 8040, + "9916": 8041, + "9917": 8042, + "9918": 8043, + "9919": 8044, + "9920": 8045, + "9921": 8046, + "9922": 8047, + "9923": 8048, + "9924": 8049, + "9925": 8050, + "9926": 8051, + "9927": 5945, + "9928": 8052, + "9929": 8053, + "9930": 8054, + "9931": 7176, + "9932": 7471, + "9933": 7469, + "9934": 7470, + "9935": 7176, + "9936": 7471, + "9937": 7469, + "9938": 7470, + "9939": 7176, + "9940": 7471, + "9941": 7469, + "9942": 7470, + "9943": 7176, + "9944": 7471, + "9945": 7469, + "9946": 7470, + "9947": 8055, + "9948": 8055, + "9949": 8055, + "9950": 8056, + "9951": 8056, + "9952": 8056, + "9953": 8057, + "9954": 8057, + "9955": 8057, + "9956": 8058, + "9957": 8058, + "9958": 8058, + "9959": 8059, + "9960": 8059, + "9961": 8059, + "9962": 8059, + "9963": 7871, + "9964": 7872, + "9965": 7873, + "9966": 7874, + "9967": 8487, + "9968": 8064, + "9969": 8065, + "9970": 8112, + "9971": 8112, + "9972": 8113, + "9973": 8104, + "9974": 8105, + "9975": 8106, + "9976": 8107, + "9977": 8109, + "9978": 8110, + "9979": 8111, + "9980": 8122, + "9981": 8101, + "9982": 8123, + "9983": 8090, + "9984": 8091, + "9985": 8091, + "9986": 8093, + "9987": 8094, + "9988": 8093, + "9989": 8094, + "9990": 8095, + "9991": 8094, + "9992": 8140, + "9993": 8096, + "9994": 8097, + "9995": 8098, + "9996": 8140, + "9997": 8097, + "9998": 8096, + "9999": 8096, + "10001": 8078, + "10002": 8079, + "10003": 8080, + "10004": 8081, + "10005": 8082, + "10006": 8083, + "10007": 8100, + "10008": 8101, + "10009": 8101, + "10010": 8103, + "10011": 8102, + "10012": 8103, + "10013": 8108, + "10014": 8108, + "10015": 8114, + "10016": 8115, + "10017": 8087, + "10018": 8114, + "10019": 8115, + "10020": 8116, + "10021": 8116, + "10022": 4916, + "10023": 8117, + "10024": 8117, + "10025": 8118, + "10026": 3046, + "10027": 3047, + "10028": 3046, + "10029": 3047, + "10030": 8119, + "10031": 8120, + "10032": 8121, + "10033": 8120, + "10034": 8124, + "10035": 8132, + "10036": 8126, + "10037": 8127, + "10038": 8128, + "10039": 8126, + "10040": 8127, + "10041": 8125, + "10042": 8127, + "10043": 7155, + "10044": 8068, + "10045": 108, + "10046": 7954, + "10047": 108, + "10048": 8066, + "10049": 8067, + "10050": 8069, + "10051": 8069, + "10052": 7967, + "10053": 7966, + "10054": 7965, + "10055": 7248, + "10056": 8005, + "10057": 8005, + "10058": 8006, + "10059": 8007, + "10060": 7248, + "10063": 8778, + "10064": 7248, + "10065": 7248, + "10066": 11264, + "10067": 11265, + "10068": 713, + "10069": 8917, + "10070": 1492, + "10071": 8378, + "10072": 8889, + "10073": 8919, + "10074": 8650, + "10075": 8650, + "10076": 8650, + "10077": 8070, + "10078": 8071, + "10079": 6041, + "10080": 6042, + "10081": 8072, + "10082": 8073, + "10083": 8074, + "10084": 8075, + "10085": 7955, + "10086": 7956, + "10087": 7957, + "10088": 8061, + "10089": 8062, + "10090": 7967, + "10091": 7967, + "10092": 7964, + "10093": 7964, + "10094": 7964, + "10095": 7966, + "10096": 7961, + "10097": 7962, + "10098": 7963, + "10099": 7965, + "10100": 7960, + "10101": 7959, + "10102": 7965, + "10103": 7926, + "10104": 108, + "10105": 8925, + "10107": 8061, + "10108": 8131, + "10109": 8234, + "10110": 8061, + "10111": 108, + "10112": 108, + "10113": 108, + "10114": 108, + "10115": 108, + "10116": 7956, + "10117": 7956, + "10118": 7923, + "10119": 7924, + "10120": 7925, + "10121": 7965, + "10122": 8299, + "10123": 8300, + "10124": 8301, + "10125": 7176, + "10126": 7471, + "10127": 7469, + "10128": 8135, + "10129": 8134, + "10130": 8136, + "10131": 8137, + "10132": 8139, + "10133": 8138, + "10134": 8183, + "10135": 8184, + "10136": 8185, + "10137": 8186, + "10138": 8187, + "10139": 8188, + "10140": 8189, + "10141": 8190, + "10142": 8191, + "10143": 8192, + "10144": 8193, + "10145": 8194, + "10146": 8195, + "10147": 8196, + "10148": 8197, + "10149": 8198, + "10150": 8199, + "10151": 8200, + "10152": 108, + "10153": 108, + "10154": 8210, + "10155": 8235, + "10156": 8236, + "10157": 8234, + "10158": 8826, + "10159": 8231, + "10160": 8232, + "10161": 8233, + "10162": 8935, + "10163": 8981, + "10164": 8455, + "10166": 8201, + "10167": 8826, + "10168": 8202, + "10169": 8203, + "10170": 8204, + "10171": 8205, + "10172": 8206, + "10173": 8207, + "10174": 8208, + "10175": 8209, + "10176": 8456, + "10177": 8210, + "10178": 8483, + "10179": 8211, + "10180": 8484, + "10181": 8325, + "10182": 8469, + "10183": 541, + "10184": 5978, + "10185": 8141, + "10186": 8260, + "10187": 108, + "10188": 8261, + "10189": 7864, + "10190": 8262, + "10191": 8262, + "10192": 108, + "10193": 8162, + "10194": 8163, + "10195": 8164, + "10196": 8147, + "10197": 8148, + "10198": 8149, + "10199": 8150, + "10200": 8151, + "10201": 8152, + "10202": 8153, + "10203": 8154, + "10204": 8856, + "10205": 8156, + "10206": 8157, + "10207": 8158, + "10208": 8159, + "10209": 8160, + "10210": 8161, + "10211": 8361, + "10212": 8357, + "10213": 8356, + "10214": 8355, + "10215": 8359, + "10216": 8358, + "10217": 8357, + "10218": 8356, + "10219": 8360, + "10220": 8354, + "10221": 8361, + "10222": 8357, + "10223": 8356, + "10224": 8360, + "10225": 8359, + "10226": 8357, + "10227": 8356, + "10228": 8360, + "10229": 8169, + "10230": 8170, + "10231": 7062, + "10232": 8172, + "10233": 8173, + "10234": 8174, + "10235": 8175, + "10236": 8176, + "10237": 8177, + "10238": 8178, + "10239": 8179, + "10240": 8180, + "10241": 8181, + "10242": 8182, + "10243": 8165, + "10244": 8166, + "10245": 8167, + "10246": 8569, + "10247": 8155, + "10248": 8571, + "10249": 8572, + "10250": 8573, + "10251": 8574, + "10252": 8575, + "10253": 8576, + "10254": 8577, + "10255": 8578, + "10256": 8579, + "10257": 8788, + "10258": 8581, + "10259": 8582, + "10260": 8583, + "10261": 8584, + "10262": 8585, + "10263": 8586, + "10264": 8587, + "10265": 8588, + "10266": 8589, + "10267": 8590, + "10268": 8459, + "10269": 8592, + "10270": 8653, + "10271": 8654, + "10272": 8655, + "10273": 8656, + "10274": 8596, + "10275": 8597, + "10276": 8598, + "10277": 8599, + "10278": 8600, + "10279": 8601, + "10280": 8789, + "10281": 8603, + "10282": 8604, + "10283": 8605, + "10284": 8606, + "10285": 8607, + "10286": 8608, + "10287": 8609, + "10288": 8610, + "10289": 8611, + "10290": 8612, + "10291": 8613, + "10292": 8614, + "10293": 8615, + "10294": 8616, + "10295": 8591, + "10296": 8890, + "10297": 8891, + "10298": 8892, + "10299": 8893, + "10300": 8894, + "10301": 8618, + "10302": 8619, + "10303": 8620, + "10304": 8621, + "10305": 8622, + "10306": 8638, + "10307": 8623, + "10308": 8624, + "10309": 8625, + "10310": 8626, + "10311": 8627, + "10312": 8628, + "10313": 8629, + "10314": 8621, + "10315": 8630, + "10316": 8631, + "10317": 8632, + "10318": 8633, + "10319": 8634, + "10320": 8635, + "10321": 8638, + "10322": 8895, + "10323": 8896, + "10324": 8897, + "10325": 8898, + "10326": 8899, + "10327": 8657, + "10328": 8543, + "10329": 8544, + "10330": 8982, + "10331": 8545, + "10332": 8546, + "10333": 8547, + "10334": 8548, + "10335": 8549, + "10336": 8550, + "10337": 8551, + "10338": 8552, + "10339": 8553, + "10340": 8554, + "10341": 8555, + "10342": 8556, + "10343": 8557, + "10344": 8558, + "10345": 8559, + "10346": 8560, + "10347": 8561, + "10348": 8562, + "10349": 8563, + "10350": 8564, + "10351": 8565, + "10352": 8566, + "10353": 8567, + "10354": 8568, + "10355": 8900, + "10356": 8901, + "10357": 8902, + "10358": 8903, + "10359": 8904, + "10360": 8358, + "10361": 8213, + "10362": 8498, + "10363": 8499, + "10364": 8500, + "10365": 8501, + "10366": 8696, + "10367": 8502, + "10368": 8503, + "10369": 8504, + "10370": 8505, + "10371": 8506, + "10372": 8507, + "10373": 8508, + "10374": 8509, + "10375": 8786, + "10376": 8511, + "10377": 8512, + "10378": 8513, + "10379": 8514, + "10380": 8515, + "10381": 8516, + "10382": 8905, + "10383": 8906, + "10384": 8907, + "10385": 8908, + "10386": 8909, + "10387": 8770, + "10388": 8710, + "10389": 8570, + "10390": 8299, + "10391": 8517, + "10392": 8518, + "10393": 8519, + "10394": 8520, + "10395": 8521, + "10396": 8522, + "10397": 8523, + "10398": 8524, + "10399": 8525, + "10400": 8791, + "10401": 8526, + "10402": 8527, + "10403": 8528, + "10404": 8529, + "10405": 8787, + "10406": 8531, + "10407": 8532, + "10408": 8533, + "10409": 8534, + "10410": 8535, + "10411": 8536, + "10412": 8537, + "10413": 8538, + "10414": 8539, + "10415": 8540, + "10416": 8541, + "10417": 8542, + "10418": 8913, + "10419": 8914, + "10420": 8911, + "10421": 8912, + "10422": 8915, + "10423": 8310, + "10424": 8264, + "10425": 8388, + "10426": 8308, + "10427": 8303, + "10428": 8302, + "10429": 8306, + "10430": 4130, + "10431": 5978, + "10432": 5239, + "10433": 729, + "10434": 1492, + "10435": 713, + "10436": 8917, + "10437": 8918, + "10438": 8279, + "10439": 8275, + "10440": 8278, + "10441": 8274, + "10442": 8276, + "10443": 8277, + "10444": 8288, + "10445": 8280, + "10446": 8281, + "10447": 8287, + "10448": 8285, + "10449": 8283, + "10450": 8284, + "10451": 8282, + "10452": 8286, + "10453": 8292, + "10454": 8291, + "10455": 8289, + "10456": 8293, + "10457": 8290, + "10458": 8273, + "10459": 108, + "10460": 8214, + "10461": 8215, + "10462": 8216, + "10463": 8217, + "10464": 8218, + "10465": 8219, + "10466": 8647, + "10467": 8221, + "10468": 8222, + "10469": 8223, + "10470": 8224, + "10471": 8225, + "10472": 8226, + "10473": 8154, + "10474": 8263, + "10475": 8264, + "10476": 8265, + "10477": 8262, + "10478": 8271, + "10479": 8266, + "10480": 8267, + "10481": 8268, + "10482": 8269, + "10483": 8270, + "10484": 8806, + "10485": 8394, + "10486": 8700, + "10487": 8227, + "10488": 8228, + "10489": 8229, + "10490": 8230, + "10491": 8353, + "10492": 8394, + "10493": 8268, + "10494": 8353, + "10495": 8630, + "10496": 8391, + "10497": 8390, + "10498": 8389, + "10499": 8353, + "10500": 8822, + "10501": 8391, + "10502": 8389, + "10503": 8389, + "10504": 8394, + "10505": 8268, + "10506": 8353, + "10507": 8379, + "10508": 8382, + "10509": 8381, + "10510": 8380, + "10511": 8382, + "10512": 8381, + "10513": 8380, + "10514": 8382, + "10515": 8382, + "10516": 8258, + "10517": 8256, + "10518": 8255, + "10519": 8254, + "10520": 8253, + "10521": 8339, + "10522": 8338, + "10523": 8338, + "10524": 8338, + "10525": 8338, + "10526": 8338, + "10527": 8338, + "10528": 8338, + "10529": 8338, + "10530": 8338, + "10531": 8338, + "10532": 8338, + "10533": 8338, + "10534": 8337, + "10535": 8922, + "10536": 8923, + "10537": 8924, + "10538": 8673, + "10539": 8238, + "10540": 8239, + "10541": 8857, + "10542": 8241, + "10543": 8669, + "10544": 8243, + "10545": 8244, + "10546": 8245, + "10547": 8246, + "10548": 8247, + "10549": 8918, + "10550": 8918, + "10551": 8918, + "10552": 8918, + "10553": 108, + "10554": 108, + "10555": 108, + "10556": 8302, + "10557": 8303, + "10558": 8304, + "10559": 8694, + "10560": 8306, + "10561": 8307, + "10562": 8308, + "10563": 8309, + "10564": 8310, + "10565": 8311, + "10566": 108, + "10567": 7864, + "10568": 8304, + "10569": 8352, + "10570": 8352, + "10571": 8351, + "10572": 8352, + "10573": 8822, + "10574": 8378, + "10575": 8377, + "10576": 8376, + "10577": 8375, + "10578": 8374, + "10579": 8373, + "10580": 8372, + "10581": 8371, + "10582": 8645, + "10583": 8154, + "10584": 8649, + "10585": 8648, + "10586": 8374, + "10587": 8647, + "10588": 8374, + "10589": 8374, + "10590": 8399, + "10591": 8398, + "10592": 729, + "10593": 713, + "10594": 8889, + "10595": 1492, + "10596": 4130, + "10597": 5239, + "10598": 8645, + "10599": 8645, + "10600": 8925, + "10601": 8778, + "10602": 8778, + "10603": 8486, + "10604": 8486, + "10605": 8264, + "10606": 8258, + "10607": 8312, + "10608": 8254, + "10609": 8369, + "10610": 8368, + "10611": 8404, + "10612": 8399, + "10613": 8365, + "10614": 8364, + "10615": 8363, + "10616": 8362, + "10617": 8643, + "10618": 8644, + "10619": 8643, + "10620": 8644, + "10621": 8643, + "10622": 8644, + "10623": 8318, + "10624": 8314, + "10625": 8330, + "10626": 8316, + "10627": 8329, + "10628": 8315, + "10629": 8328, + "10630": 8317, + "10631": 8331, + "10632": 8332, + "10633": 8333, + "10634": 8910, + "10635": 8370, + "10636": 8350, + "10637": 8348, + "10638": 8347, + "10639": 8350, + "10640": 8349, + "10641": 8348, + "10642": 8347, + "10643": 8346, + "10644": 8379, + "10645": 8234, + "10646": 8778, + "10647": 8374, + "10648": 108, + "10649": 8919, + "10650": 4130, + "10651": 5239, + "10652": 8917, + "10653": 8374, + "10654": 8399, + "10655": 5978, + "10656": 5978, + "10657": 8651, + "10658": 8650, + "10659": 8308, + "10660": 8264, + "10661": 8310, + "10662": 8219, + "10663": 8269, + "10664": 8311, + "10665": 8396, + "10666": 8395, + "10667": 8394, + "10668": 8307, + "10669": 8258, + "10670": 8255, + "10671": 8312, + "10672": 8393, + "10673": 8214, + "10674": 8959, + "10675": 8960, + "10676": 8961, + "10677": 8918, + "10678": 8918, + "10679": 8918, + "10680": 8918, + "10681": 8918, + "10682": 8422, + "10683": 8645, + "10684": 8921, + "10685": 8645, + "10686": 8645, + "10687": 8920, + "10688": 8921, + "10689": 8920, + "10690": 8646, + "10691": 8929, + "10692": 8930, + "10693": 8931, + "10694": 8932, + "10695": 8435, + "10696": 8933, + "10697": 8486, + "10698": 8486, + "10699": 8486, + "10700": 8486, + "10701": 8776, + "10702": 8777, + "10703": 8778, + "10704": 8777, + "10705": 8488, + "10706": 8489, + "10707": 8490, + "10708": 8491, + "10709": 8492, + "10710": 8489, + "10711": 8776, + "10712": 8352, + "10713": 8352, + "10714": 8352, + "10715": 8352, + "10716": 8748, + "10717": 8781, + "10718": 8780, + "10719": 8780, + "10720": 8781, + "10721": 8782, + "10722": 8783, + "10723": 8784, + "10724": 8785, + "10725": 108, + "10726": 8374, + "10727": 8931, + "10728": 8652, + "10729": 8258, + "10730": 8257, + "10731": 8256, + "10732": 8254, + "10733": 8312, + "10734": 8397, + "10735": 8636, + "10736": 8637, + "10737": 8858, + "10738": 8859, + "10739": 8860, + "10740": 8861, + "10741": 8862, + "10742": 8863, + "10743": 8864, + "10744": 8865, + "10745": 8866, + "10746": 8867, + "10747": 8374, + "10748": 8374, + "10749": 8374, + "10750": 8374, + "10751": 8374, + "10752": 8374, + "10753": 8374, + "10754": 8374, + "10755": 8916, + "10756": 8682, + "10757": 8683, + "10758": 8684, + "10759": 8685, + "10760": 8686, + "10761": 8687, + "10762": 8688, + "10763": 8489, + "10764": 8395, + "10765": 8787, + "10766": 108, + "10767": 8803, + "10768": 8868, + "10769": 108, + "10770": 108, + "10771": 8310, + "10772": 8308, + "10773": 8306, + "10774": 8869, + "10775": 8870, + "10776": 8871, + "10777": 108, + "10778": 108, + "10779": 108, + "10780": 108, + "10781": 108, + "10782": 108, + "10783": 108, + "10784": 8640, + "10785": 8641, + "10786": 8642, + "10787": 8689, + "10788": 8690, + "10789": 8691, + "10790": 8692, + "10791": 8693, + "10792": 8694, + "10793": 8695, + "10794": 8696, + "10795": 8697, + "10796": 8698, + "10797": 8699, + "10798": 8700, + "10799": 8701, + "10800": 8702, + "10801": 8703, + "10802": 8704, + "10803": 8705, + "10804": 8706, + "10805": 8707, + "10806": 8708, + "10807": 8709, + "10808": 8710, + "10809": 8711, + "10810": 8712, + "10811": 8557, + "10812": 8713, + "10813": 8714, + "10814": 8715, + "10815": 8785, + "10816": 8639, + "10817": 108, + "10818": 108, + "10819": 108, + "10820": 108, + "10821": 8872, + "10822": 8872, + "10823": 8874, + "10824": 8875, + "10825": 8864, + "10826": 8876, + "10827": 108, + "10828": 108, + "10829": 108, + "10830": 8858, + "10831": 8346, + "10832": 8400, + "10833": 8401, + "10834": 8402, + "10835": 8403, + "10836": 8404, + "10837": 8405, + "10838": 8406, + "10839": 8407, + "10840": 8408, + "10841": 8409, + "10842": 8410, + "10843": 8411, + "10844": 8412, + "10845": 8413, + "10846": 8414, + "10847": 8414, + "10848": 8414, + "10849": 8417, + "10850": 8418, + "10851": 8419, + "10852": 8420, + "10853": 8421, + "10854": 8422, + "10855": 8423, + "10856": 8424, + "10857": 8425, + "10858": 8426, + "10859": 8427, + "10860": 8428, + "10861": 8429, + "10862": 8430, + "10863": 8431, + "10864": 8432, + "10865": 8433, + "10866": 8434, + "10867": 8435, + "10868": 8823, + "10869": 8436, + "10870": 8437, + "10871": 8438, + "10872": 8439, + "10873": 8440, + "10874": 8441, + "10875": 8442, + "10876": 8443, + "10877": 8444, + "10878": 8445, + "10879": 8446, + "10880": 8447, + "10881": 8448, + "10882": 8449, + "10883": 8450, + "10884": 8451, + "10885": 8452, + "10886": 8323, + "10887": 8324, + "10888": 8485, + "10889": 8319, + "10890": 8817, + "10891": 8818, + "10892": 8816, + "10893": 8320, + "10894": 8934, + "10895": 8322, + "10896": 108, + "10897": 8313, + "10898": 8815, + "10899": 8814, + "10900": 8813, + "10901": 8918, + "10902": 8918, + "10903": 8918, + "10904": 8918, + "10905": 8918, + "10906": 8302, + "10907": 8821, + "10908": 8819, + "10909": 108, + "10910": 8478, + "10911": 108, + "10912": 8234, + "10913": 8480, + "10914": 8352, + "10915": 8453, + "10916": 8454, + "10917": 8457, + "10918": 8458, + "10919": 8463, + "10920": 8467, + "10921": 8664, + "10922": 8662, + "10923": 8663, + "10924": 9029, + "10925": 9029, + "10926": 8670, + "10927": 8673, + "10928": 8680, + "10929": 8234, + "10930": 8922, + "10931": 8922, + "10932": 8327, + "10933": 8334, + "10934": 8335, + "10935": 8845, + "10936": 8845, + "10937": 8845, + "10938": 8845, + "10939": 8845, + "10940": 8845, + "10941": 8848, + "10942": 8849, + "10943": 8850, + "10944": 8851, + "10945": 8854, + "10946": 8852, + "10947": 8853, + "10948": 8855, + "10949": 108, + "10950": 8434, + "10951": 8493, + "10952": 8494, + "10953": 8495, + "10954": 8496, + "10955": 8497, + "10956": 8488, + "10957": 8489, + "10958": 8493, + "10959": 8493, + "10960": 8795, + "10961": 8782, + "10962": 8866, + "10963": 8872, + "10964": 8872, + "10965": 8872, + "10966": 8872, + "10967": 8872, + "10968": 8872, + "10969": 8385, + "10970": 108, + "10971": 108, + "10972": 8795, + "10973": 108, + "10974": 8796, + "10975": 108, + "10976": 8825, + "10977": 8824, + "10978": 2186, + "10979": 8488, + "10980": 8846, + "10981": 8838, + "10982": 8839, + "10983": 8840, + "10984": 8841, + "10985": 8305, + "10986": 8847, + "10987": 8493, + "10988": 8485, + "10989": 8799, + "10990": 8798, + "10991": 108, + "10992": 8374, + "10993": 8779, + "10994": 8796, + "10995": 8797, + "10996": 8951, + "10997": 8952, + "10998": 8964, + "10999": 8830, + "11000": 8834, + "11001": 8835, + "11002": 108, + "11003": 8323, + "11004": 8812, + "11005": 8810, + "11006": 8809, + "11007": 8808, + "11008": 8807, + "11009": 8806, + "11010": 8800, + "11011": 8805, + "11012": 8395, + "11013": 8927, + "11014": 8926, + "11015": 8716, + "11016": 8717, + "11017": 8718, + "11018": 8719, + "11019": 8720, + "11020": 8721, + "11021": 8722, + "11022": 8723, + "11023": 8724, + "11024": 8725, + "11025": 8726, + "11026": 8727, + "11027": 8728, + "11028": 8729, + "11029": 8730, + "11030": 8731, + "11031": 8732, + "11032": 8733, + "11033": 8734, + "11034": 8735, + "11035": 8736, + "11036": 8737, + "11037": 8738, + "11038": 8739, + "11039": 8740, + "11040": 8741, + "11041": 8742, + "11042": 8743, + "11043": 8744, + "11044": 8745, + "11045": 8746, + "11046": 8747, + "11047": 8965, + "11048": 8749, + "11049": 8750, + "11050": 8751, + "11051": 8752, + "11052": 8753, + "11053": 8754, + "11054": 8755, + "11055": 8756, + "11056": 8757, + "11057": 8758, + "11058": 8759, + "11059": 8760, + "11060": 8761, + "11061": 8762, + "11062": 8763, + "11063": 8764, + "11064": 8765, + "11065": 8766, + "11066": 8767, + "11067": 8768, + "11068": 8769, + "11069": 8770, + "11070": 8771, + "11071": 8772, + "11072": 8773, + "11073": 8774, + "11074": 8775, + "11075": 8228, + "11076": 8227, + "11077": 8827, + "11078": 8828, + "11079": 8829, + "11080": 8831, + "11081": 8832, + "11082": 8833, + "11083": 8836, + "11084": 8837, + "11085": 8826, + "11086": 8224, + "11087": 8966, + "11088": 8967, + "11089": 8968, + "11090": 9034, + "11091": 9033, + "11092": 9035, + "11093": 8969, + "11094": 8970, + "11095": 8971, + "11096": 8972, + "11097": 8973, + "11098": 8974, + "11099": 8975, + "11100": 8976, + "11101": 9026, + "11102": 8978, + "11103": 8979, + "11104": 8980, + "11105": 8460, + "11106": 8982, + "11107": 8983, + "11108": 8984, + "11109": 8985, + "11110": 8986, + "11111": 9025, + "11112": 8988, + "11113": 9039, + "11114": 8990, + "11115": 8991, + "11116": 8992, + "11117": 8993, + "11118": 8994, + "11119": 8995, + "11120": 8996, + "11121": 8997, + "11122": 9036, + "11123": 8998, + "11124": 8999, + "11125": 8877, + "11126": 8878, + "11127": 8879, + "11128": 8880, + "11129": 8881, + "11130": 8882, + "11131": 8883, + "11132": 8884, + "11133": 8885, + "11134": 8886, + "11135": 8887, + "11136": 8888, + "11137": 8947, + "11138": 8948, + "11139": 9000, + "11140": 9001, + "11141": 9002, + "11142": 9003, + "11143": 9004, + "11144": 9005, + "11145": 9006, + "11146": 9007, + "11147": 9008, + "11148": 8427, + "11149": 9027, + "11150": 9010, + "11151": 9011, + "11152": 9013, + "11153": 9037, + "11154": 9014, + "11155": 9015, + "11156": 8943, + "11157": 8944, + "11158": 8945, + "11159": 9016, + "11160": 9017, + "11161": 9018, + "11162": 9019, + "11163": 9020, + "11164": 9021, + "11165": 9022, + "11166": 9023, + "11167": 9024, + "11168": 9027, + "11169": 9027, + "11170": 9027, + "11171": 9038, + "11172": 9028, + "11173": 8953, + "11174": 8954, + "11175": 8955, + "11176": 8956, + "11177": 8957, + "11178": 2201, + "11179": 108, + "11180": 108, + "11181": 8822, + "11182": 8822, + "11183": 8154, + "11184": 8992, + "11185": 8474, + "11186": 8461, + "11187": 8462, + "11188": 8464, + "11189": 8465, + "11190": 8466, + "11191": 8468, + "11192": 8666, + "11193": 8669, + "11194": 8671, + "11195": 8672, + "11196": 8674, + "11197": 8677, + "11198": 8678, + "11199": 8679, + "11200": 8987, + "11201": 8661, + "11202": 8662, + "11203": 8663, + "11204": 8665, + "11205": 8667, + "11206": 8668, + "11207": 8668, + "11208": 108, + "11209": 8848, + "11210": 8645, + "11211": 8918, + "11212": 8921, + "11213": 8313, + "11214": 8872, + "11215": 8918, + "11216": 8918, + "11217": 8918, + "11218": 8921, + "11219": 8645, + "11220": 8645, + "11221": 8820, + "11222": 108, + "11223": 8323, + "11224": 108, + "11225": 108, + "11226": 108, + "11227": 108, + "11228": 8819, + "11229": 8485, + "11230": 8294, + "11231": 8295, + "11232": 8294, + "11233": 8295, + "11234": 8296, + "11235": 8296, + "11236": 8949, + "11237": 8950, + "11238": 8646, + "11239": 8962, + "11240": 8962, + "11241": 8962, + "11242": 8962, + "11243": 8962, + "11244": 8963, + "11245": 8353, + "11246": 8394, + "11247": 8268, + "11248": 8952, + "11249": 8838, + "11250": 8918, + "11251": 8790, + "11252": 8234, + "11253": 8485, + "11254": 8485, + "11255": 8485, + "11256": 8324, + "11257": 8811, + "11258": 8804, + "11259": 8798, + "11260": 8722, + "11261": 8723, + "11262": 8723, + "11263": 9050, + "11264": 8810, + "11265": 8373, + "11266": 8414, + "11267": 9057, + "11268": 9044, + "11269": 9045, + "11270": 9064, + "11271": 9148, + "11272": 9149, + "11273": 9150, + "11274": 9151, + "11275": 9152, + "11276": 9152, + "11277": 9041, + "11278": 9049, + "11279": 9047, + "11280": 9048, + "11281": 9050, + "11282": 9065, + "11283": 9046, + "11284": 108, + "11285": 108, + "11286": 108, + "11287": 108, + "11288": 108, + "11289": 108, + "11290": 9041, + "11291": 9063, + "11292": 8352, + "11293": 8352, + "11294": 8352, + "11295": 8352, + "11296": 8352, + "11297": 8352, + "11298": 8352, + "11299": 8826, + "11300": 9180, + "11301": 9181, + "11302": 9182, + "11303": 9183, + "11304": 8351, + "11305": 9184, + "11306": 9185, + "11307": 9143, + "11308": 9143, + "11309": 9143, + "11310": 8788, + "11311": 9092, + "11312": 8789, + "11313": 9051, + "11314": 9051, + "11315": 9051, + "11316": 9052, + "11317": 9063, + "11318": 9053, + "11319": 9053, + "11320": 9053, + "11321": 9054, + "11322": 9055, + "11323": 9056, + "11324": 9062, + "11325": 9057, + "11326": 9179, + "11327": 9058, + "11328": 9059, + "11329": 9127, + "11330": 9128, + "11331": 9129, + "11332": 9060, + "11333": 9130, + "11334": 9061, + "11335": 9211, + "11336": 9212, + "11337": 9213, + "11338": 9214, + "11339": 9215, + "11340": 9216, + "11341": 9217, + "11342": 9218, + "11343": 8658, + "11344": 9221, + "11345": 9222, + "11346": 9223, + "11347": 9220, + "11348": 9224, + "11349": 9042, + "11350": 108, + "11351": 9186, + "11352": 9231, + "11353": 9232, + "11354": 9134, + "11355": 9239, + "11356": 9240, + "11357": 9241, + "11358": 9242, + "11359": 9243, + "11360": 9244, + "11361": 9141, + "11362": 9146, + "11363": 9142, + "11364": 8640, + "11365": 9142, + "11366": 9131, + "11367": 9245, + "11368": 2667, + "11369": 9149, + "11370": 9245, + "11371": 8851, + "11372": 9245, + "11373": 9245, + "11374": 9245, + "11375": 9245, + "11376": 8347, + "11377": 8853, + "11378": 9155, + "11379": 9143, + "11380": 9153, + "11381": 9154, + "11382": 9155, + "11383": 9156, + "11384": 9157, + "11385": 9136, + "11386": 9134, + "11387": 9135, + "11388": 9136, + "11389": 9137, + "11390": 9138, + "11391": 9139, + "11392": 9140, + "11393": 9219, + "11394": 9132, + "11395": 9133, + "11396": 9230, + "11397": 9189, + "11398": 108, + "11399": 108, + "11400": 108, + "11401": 9190, + "11402": 9190, + "11403": 9191, + "11404": 9192, + "11405": 9193, + "11406": 9194, + "11407": 9195, + "11408": 9196, + "11409": 9197, + "11410": 9143, + "11411": 9199, + "11412": 9200, + "11413": 9201, + "11414": 7857, + "11415": 7860, + "11416": 9189, + "11417": 9202, + "11418": 9203, + "11419": 9204, + "11420": 9205, + "11421": 9218, + "11422": 9220, + "11423": 9042, + "11424": 9178, + "11425": 9177, + "11426": 9176, + "11427": 9160, + "11428": 9159, + "11429": 9162, + "11430": 9161, + "11431": 9207, + "11432": 9208, + "11433": 9209, + "11434": 9210, + "11435": 9158, + "11436": 9158, + "11437": 9159, + "11438": 9160, + "11439": 9161, + "11440": 9162, + "11441": 8126, + "11442": 8105, + "11443": 9163, + "11444": 9164, + "11445": 9165, + "11446": 9166, + "11447": 9167, + "11448": 9168, + "11449": 9169, + "11450": 9170, + "11451": 9171, + "11452": 9172, + "11453": 9172, + "11454": 9172, + "11455": 9173, + "11456": 9173, + "11457": 9174, + "11458": 9175, + "11459": 9177, + "11460": 9131, + "11461": 9229, + "11462": 9247, + "11463": 108, + "11464": 108, + "11465": 108, + "11466": 9186, + "11467": 8845, + "11468": 8845, + "11469": 8845, + "11470": 9131, + "11471": 108, + "11472": 9208, + "11473": 9219, + "11474": 9233, + "11475": 9234, + "11476": 9235, + "11477": 9236, + "11478": 9237, + "11479": 9238, + "11480": 117, + "11481": 9260, + "11482": 9261, + "11483": 9262, + "11484": 9250, + "11485": 9233, + "11486": 731, + "11487": 9250, + "11488": 9254, + "11489": 9254, + "11490": 9250, + "11491": 9259, + "11492": 9253, + "11493": 731, + "11494": 9250, + "11495": 9254, + "11496": 9254, + "11497": 9255, + "11498": 9256, + "11500": 9246, + "11501": 108, + "11502": 9378, + "11503": 9254, + "11504": 9829, + "11505": 9381, + "11506": 9243, + "11507": 9383, + "11508": 9384, + "11509": 9255, + "11510": 9245, + "11511": 9245, + "11512": 3046, + "11513": 2667, + "11514": 9387, + "11515": 9248, + "11516": 9249, + "11517": 9401, + "11518": 9263, + "11519": 9264, + "11520": 9265, + "11521": 9266, + "11522": 9281, + "11523": 9282, + "11524": 9283, + "11525": 9284, + "11526": 9285, + "11527": 9404, + "11528": 9281, + "11529": 9282, + "11530": 9283, + "11531": 9284, + "11532": 9285, + "11533": 9286, + "11534": 9287, + "11535": 9288, + "11536": 9289, + "11537": 9290, + "11538": 9291, + "11539": 9287, + "11540": 9288, + "11541": 9289, + "11542": 9290, + "11543": 9291, + "11544": 9292, + "11545": 9267, + "11546": 9268, + "11547": 9269, + "11548": 9271, + "11549": 108, + "11550": 9272, + "11551": 9273, + "11552": 9274, + "11553": 9275, + "11554": 9276, + "11555": 9277, + "11556": 9278, + "11557": 9316, + "11558": 9830, + "11559": 9288, + "11560": 9289, + "11561": 108, + "11562": 108, + "11563": 9279, + "11564": 9280, + "11565": 9298, + "11566": 9299, + "11568": 9301, + "11569": 9301, + "11570": 9298, + "11571": 9299, + "11572": 9300, + "11573": 9301, + "11574": 9301, + "11576": 9302, + "11577": 9303, + "11578": 108, + "11579": 108, + "11580": 9296, + "11581": 8378, + "11582": 8377, + "11583": 8376, + "11584": 8375, + "11585": 9293, + "11586": 9294, + "11587": 9295, + "11588": 9297, + "11589": 9341, + "11590": 9365, + "11592": 9360, + "11593": 9361, + "11594": 9362, + "11595": 9355, + "11596": 3819, + "11597": 3820, + "11598": 9342, + "11599": 9356, + "11600": 9331, + "11601": 9331, + "11602": 149, + "11603": 9329, + "11604": 9328, + "11605": 9332, + "11606": 9332, + "11607": 9332, + "11608": 9332, + "11609": 9332, + "11610": 9333, + "11611": 9333, + "11612": 9333, + "11613": 9334, + "11614": 9335, + "11615": 9336, + "11616": 9337, + "11617": 9338, + "11618": 9339, + "11619": 9340, + "11620": 9341, + "11621": 9365, + "11622": 9360, + "11623": 9361, + "11624": 9362, + "11625": 9355, + "11626": 9342, + "11627": 9353, + "11628": 9407, + "11629": 9318, + "11630": 9319, + "11631": 9320, + "11632": 9321, + "11633": 9322, + "11634": 9323, + "11635": 9353, + "11636": 9409, + "11637": 9410, + "11638": 9319, + "11639": 9320, + "11640": 9321, + "11641": 9324, + "11642": 9346, + "11643": 5239, + "11644": 9348, + "11645": 9347, + "11646": 9349, + "11647": 8378, + "11648": 9386, + "11649": 9333, + "11650": 9388, + "11651": 9358, + "11652": 9357, + "11653": 9278, + "11654": 9325, + "11655": 9491, + "11656": 9490, + "11657": 9502, + "11658": 9503, + "11659": 9392, + "11660": 267, + "11661": 9379, + "11662": 9394, + "11664": 9397, + "11665": 9410, + "11666": 9411, + "11667": 9412, + "11668": 9413, + "11669": 9994, + "11670": 9326, + "11671": 9299, + "11672": 9299, + "11673": 9405, + "11674": 731, + "11675": 9408, + "11676": 733, + "11677": 10119, + "11678": 9394, + "11679": 9317, + "11680": 9317, + "11681": 9288, + "11682": 9289, + "11683": 9388, + "11684": 9443, + "11685": 9393, + "11686": 9391, + "11687": 9400, + "11688": 9513, + "11689": 9390, + "11690": 9402, + "11691": 9350, + "11692": 9359, + "11693": 9254, + "11694": 9254, + "11695": 9329, + "11696": 9327, + "11697": 9278, + "11698": 9333, + "11699": 9334, + "11700": 9339, + "11701": 9424, + "11702": 9425, + "11703": 9398, + "11704": 9399, + "11705": 9403, + "11706": 9404, + "11707": 9405, + "11708": 9406, + "11709": 9396, + "11710": 9475, + "11711": 9475, + "11712": 9476, + "11713": 9477, + "11714": 9477, + "11715": 9478, + "11716": 9641, + "11717": 9479, + "11718": 9480, + "11719": 9481, + "11720": 9482, + "11721": 9482, + "11722": 108, + "11723": 9427, + "11724": 9428, + "11725": 9462, + "11726": 9829, + "11727": 9830, + "11728": 9702, + "11729": 9702, + "11730": 9693, + "11731": 9484, + "11732": 9465, + "11733": 9466, + "11734": 9467, + "11735": 9468, + "11736": 9469, + "11737": 9470, + "11738": 9471, + "11739": 9472, + "11740": 9473, + "11741": 9462, + "11742": 9462, + "11743": 9823, + "11744": 541, + "11747": 9465, + "11748": 9466, + "11749": 9467, + "11750": 9468, + "11751": 9469, + "11752": 9470, + "11753": 9471, + "11754": 9472, + "11755": 9473, + "11756": 9505, + "11757": 9506, + "11758": 108, + "11759": 108, + "11760": 9493, + "11761": 9508, + "11762": 9510, + "11763": 9510, + "11764": 9510, + "11765": 9510, + "11766": 9509, + "11767": 9509, + "11768": 9509, + "11769": 9509, + "11770": 9458, + "11771": 9459, + "11772": 9460, + "11773": 5045, + "11774": 9461, + "11775": 9461, + "11776": 9461, + "11777": 9442, + "11778": 9443, + "11779": 9444, + "11780": 9445, + "11781": 9446, + "11782": 9447, + "11783": 9448, + "11784": 9449, + "11785": 9450, + "11786": 9299, + "11787": 9299, + "11788": 9891, + "11789": 9494, + "11790": 9451, + "11791": 108, + "11792": 9364, + "11793": 9617, + "11794": 9618, + "11795": 9322, + "11796": 9417, + "11797": 9515, + "11798": 9516, + "11799": 9517, + "11800": 9518, + "11801": 9519, + "11802": 9520, + "11803": 9521, + "11804": 9522, + "11805": 9523, + "11806": 108, + "11807": 108, + "11808": 108, + "11809": 108, + "11810": 11320, + "11812": 9530, + "11813": 9531, + "11814": 9532, + "11815": 9533, + "11816": 9534, + "11817": 9535, + "11818": 9483, + "11819": 9643, + "11820": 9485, + "11822": 10015, + "11823": 9391, + "11824": 9392, + "11825": 9393, + "11826": 9536, + "11827": 9537, + "11828": 9538, + "11829": 9931, + "11830": 9539, + "11831": 9540, + "11832": 9541, + "11833": 9542, + "11834": 9408, + "11835": 9544, + "11836": 9533, + "11837": 9545, + "11838": 9546, + "11839": 9547, + "11840": 9536, + "11841": 9548, + "11842": 9549, + "11843": 9550, + "11844": 9551, + "11845": 9537, + "11846": 10107, + "11847": 10116, + "11848": 108, + "11849": 9538, + "11850": 9555, + "11851": 9556, + "11852": 9557, + "11853": 9558, + "11854": 9559, + "11855": 9560, + "11856": 9561, + "11857": 9562, + "11858": 9563, + "11859": 9564, + "11860": 9536, + "11861": 9565, + "11862": 9430, + "11863": 9567, + "11864": 9533, + "11865": 9568, + "11866": 9569, + "11867": 9570, + "11868": 9571, + "11869": 9538, + "11870": 9572, + "11871": 9573, + "11872": 9679, + "11873": 9537, + "11874": 9575, + "11875": 9576, + "11876": 9577, + "11877": 9578, + "11878": 9394, + "11879": 9395, + "11880": 9407, + "11881": 9408, + "11882": 9650, + "11884": 9664, + "11885": 9651, + "11886": 9384, + "11887": 9422, + "11888": 9423, + "11889": 9507, + "11890": 9411, + "11891": 9411, + "11892": 9412, + "11893": 9413, + "11894": 9414, + "11895": 9415, + "11896": 9416, + "11897": 108, + "11898": 9492, + "11899": 9493, + "11900": 9494, + "11901": 9495, + "11902": 9496, + "11903": 9497, + "11904": 9498, + "11905": 9499, + "11906": 9500, + "11907": 9656, + "11908": 9664, + "11909": 9657, + "11910": 9366, + "11911": 9367, + "11912": 9369, + "11913": 9371, + "11914": 9372, + "11915": 9373, + "11916": 9426, + "11917": 9409, + "11918": 9390, + "11919": 9410, + "11920": 9375, + "11921": 9374, + "11922": 9374, + "11923": 9374, + "11924": 9374, + "11925": 9374, + "11926": 9374, + "11927": 9374, + "11928": 9389, + "11929": 9386, + "11930": 9386, + "11931": 9386, + "11932": 9387, + "11933": 9387, + "11934": 9388, + "11935": 9388, + "11936": 9384, + "11937": 108, + "11938": 9642, + "11939": 9381, + "11940": 9588, + "11941": 9382, + "11942": 9383, + "11943": 9390, + "11944": 9390, + "11945": 9663, + "11946": 9390, + "11947": 9390, + "11948": 108, + "11949": 108, + "11950": 108, + "11951": 108, + "11952": 108, + "11953": 9411, + "11954": 9403, + "11955": 9404, + "11956": 9674, + "11957": 9675, + "11958": 9676, + "11959": 9677, + "11960": 9678, + "11961": 9412, + "11962": 9412, + "11963": 9409, + "11964": 9412, + "11965": 9452, + "11966": 9453, + "11967": 9454, + "11968": 9455, + "11969": 9456, + "11970": 9457, + "11971": 9513, + "11972": 9646, + "11973": 9647, + "11974": 9644, + "11975": 9645, + "11976": 9648, + "11977": 9368, + "11978": 9370, + "11979": 9140, + "11980": 9436, + "11981": 9437, + "11982": 9438, + "11983": 9419, + "11984": 9420, + "11985": 9421, + "11986": 108, + "11987": 9439, + "11988": 9439, + "11989": 9439, + "11990": 9436, + "11991": 9440, + "11992": 9710, + "11993": 9441, + "11994": 9366, + "11995": 9367, + "11996": 9374, + "11997": 9543, + "11998": 9429, + "11999": 9430, + "12000": 300, + "12001": 9431, + "12002": 9543, + "12003": 9432, + "12004": 9652, + "12005": 9655, + "12006": 9653, + "12007": 9654, + "12008": 9967, + "12009": 9132, + "12010": 9133, + "12011": 9649, + "12012": 9140, + "12013": 9374, + "12014": 9374, + "12015": 9608, + "12016": 9607, + "12017": 9368, + "12018": 9369, + "12019": 9370, + "12020": 9371, + "12021": 9372, + "12022": 9373, + "12023": 9384, + "12024": 9659, + "12025": 9662, + "12026": 9660, + "12027": 9661, + "12028": 9663, + "12029": 9511, + "12030": 9512, + "12031": 9363, + "12032": 9363, + "12033": 11271, + "12034": 9418, + "12035": 9487, + "12036": 9484, + "12037": 9477, + "12038": 9433, + "12039": 9680, + "12040": 9433, + "12041": 9681, + "12042": 9434, + "12043": 9486, + "12044": 9595, + "12045": 9668, + "12046": 9348, + "12047": 8378, + "12048": 5573, + "12049": 9666, + "12050": 2118, + "12051": 2160, + "12052": 2135, + "12053": 2136, + "12054": 9667, + "12055": 9671, + "12056": 9672, + "12057": 9674, + "12058": 3639, + "12059": 3642, + "12060": 3633, + "12061": 3632, + "12062": 4739, + "12063": 7869, + "12064": 9675, + "12065": 3458, + "12066": 3458, + "12067": 5576, + "12068": 9676, + "12069": 9677, + "12070": 9678, + "12071": 6148, + "12072": 6039, + "12073": 7537, + "12074": 6041, + "12075": 6042, + "12076": 6040, + "12077": 9673, + "12078": 8258, + "12079": 9533, + "12080": 108, + "12081": 108, + "12082": 108, + "12083": 108, + "12084": 108, + "12085": 108, + "12086": 108, + "12087": 108, + "12088": 108, + "12089": 108, + "12090": 108, + "12091": 108, + "12092": 9669, + "12093": 8826, + "12094": 9476, + "12095": 9479, + "12096": 9479, + "12097": 9479, + "12098": 9475, + "12099": 9479, + "12100": 9480, + "12101": 8826, + "12102": 9670, + "12103": 9586, + "12104": 9587, + "12105": 108, + "12106": 108, + "12107": 108, + "12108": 108, + "12109": 108, + "12110": 9514, + "12111": 9432, + "12112": 9596, + "12113": 9787, + "12114": 9597, + "12115": 9863, + "12116": 9377, + "12117": 9378, + "12118": 108, + "12119": 9385, + "12120": 9425, + "12121": 9378, + "12122": 9589, + "12123": 9589, + "12124": 9589, + "12125": 9589, + "12126": 9590, + "12127": 9591, + "12128": 9592, + "12129": 9593, + "12130": 9594, + "12131": 9587, + "12133": 9388, + "12134": 9606, + "12135": 9604, + "12136": 9375, + "12137": 9374, + "12138": 9374, + "12139": 9374, + "12140": 9374, + "12141": 9374, + "12142": 9374, + "12143": 9374, + "12144": 9605, + "12145": 9598, + "12146": 9599, + "12147": 9600, + "12148": 9386, + "12149": 9386, + "12150": 9386, + "12151": 9387, + "12152": 9388, + "12153": 9376, + "12154": 9390, + "12155": 9603, + "12156": 9602, + "12157": 9579, + "12158": 9580, + "12159": 9581, + "12160": 9579, + "12161": 9580, + "12162": 9582, + "12163": 9582, + "12164": 9582, + "12165": 9802, + "12166": 9582, + "12167": 9582, + "12168": 9582, + "12169": 9520, + "12170": 9543, + "12171": 9609, + "12172": 9559, + "12173": 9375, + "12174": 9639, + "12175": 9543, + "12176": 9566, + "12177": 9626, + "12179": 9612, + "12180": 9850, + "12181": 9589, + "12182": 9589, + "12183": 9408, + "12184": 9407, + "12185": 9632, + "12186": 9601, + "12187": 9629, + "12188": 9630, + "12189": 9631, + "12190": 9374, + "12191": 9386, + "12192": 9636, + "12193": 9602, + "12194": 9635, + "12195": 9377, + "12196": 9647, + "12197": 9647, + "12198": 9385, + "12199": 9377, + "12200": 9637, + "12201": 9604, + "12202": 9385, + "12203": 9390, + "12204": 9633, + "12205": 9384, + "12206": 9634, + "12207": 9621, + "12208": 7974, + "12209": 9388, + "12210": 9386, + "12211": 9543, + "12212": 9638, + "12213": 9376, + "12214": 9457, + "12215": 9636, + "12216": 9602, + "12217": 9390, + "12218": 9366, + "12219": 9685, + "12220": 9685, + "12221": 9685, + "12222": 9673, + "12223": 9673, + "12224": 9615, + "12225": 9617, + "12226": 9690, + "12227": 9588, + "12228": 9588, + "12229": 9822, + "12230": 9640, + "12231": 9599, + "12232": 9636, + "12233": 9602, + "12234": 9564, + "12235": 9366, + "12236": 9367, + "12237": 6945, + "12238": 9425, + "12239": 9378, + "12240": 9607, + "12241": 9608, + "12242": 9368, + "12243": 108, + "12244": 9390, + "12245": 9636, + "12246": 9602, + "12247": 9585, + "12248": 9714, + "12249": 9715, + "12250": 9716, + "12251": 9717, + "12252": 9718, + "12253": 9719, + "12254": 9720, + "12255": 9721, + "12256": 9722, + "12257": 9723, + "12258": 9724, + "12259": 9725, + "12260": 9726, + "12261": 9727, + "12262": 9728, + "12263": 9729, + "12264": 9730, + "12265": 9731, + "12266": 9732, + "12267": 9733, + "12268": 9734, + "12269": 9665, + "12270": 9734, + "12271": 9735, + "12272": 9371, + "12273": 9372, + "12274": 9373, + "12275": 9389, + "12276": 9386, + "12277": 9386, + "12278": 9387, + "12279": 9388, + "12280": 10096, + "12281": 10099, + "12282": 9682, + "12283": 9683, + "12284": 9684, + "12285": 9603, + "12286": 9685, + "12287": 9686, + "12288": 9390, + "12289": 9390, + "12290": 9411, + "12291": 9503, + "12292": 9916, + "12293": 9439, + "12294": 8826, + "12295": 8826, + "12296": 541, + "12297": 9737, + "12298": 9688, + "12299": 9741, + "12300": 9735, + "12301": 9736, + "12302": 9737, + "12303": 9788, + "12304": 9789, + "12305": 9790, + "12306": 9791, + "12307": 9792, + "12308": 9795, + "12309": 9796, + "12310": 9793, + "12311": 9794, + "12312": 9797, + "12313": 9799, + "12314": 9808, + "12315": 9810, + "12316": 9800, + "12317": 9801, + "12318": 9802, + "12319": 9803, + "12320": 9804, + "12321": 9805, + "12322": 9806, + "12323": 9807, + "12324": 9809, + "12325": 9776, + "12326": 9777, + "12327": 9778, + "12328": 9779, + "12329": 9780, + "12330": 9781, + "12331": 9782, + "12332": 9783, + "12333": 9784, + "12334": 9785, + "12335": 9786, + "12336": 9808, + "12337": 9787, + "12338": 9808, + "12339": 9774, + "12340": 9773, + "12341": 9811, + "12342": 9775, + "12343": 9681, + "12346": 9696, + "12347": 9697, + "12348": 9698, + "12349": 9699, + "12350": 9697, + "12351": 9701, + "12352": 9702, + "12353": 9696, + "12354": 9697, + "12355": 9783, + "12356": 9699, + "12357": 9697, + "12358": 9701, + "12359": 9702, + "12360": 9703, + "12361": 9704, + "12362": 9705, + "12363": 9706, + "12364": 9798, + "12365": 9798, + "12367": 9812, + "12368": 9808, + "12369": 9808, + "12370": 9742, + "12371": 9743, + "12372": 9744, + "12373": 9745, + "12374": 9764, + "12375": 9765, + "12376": 9766, + "12377": 9767, + "12378": 9768, + "12379": 9764, + "12380": 9766, + "12381": 9767, + "12382": 9765, + "12383": 9768, + "12384": 9515, + "12385": 9769, + "12386": 9769, + "12387": 9769, + "12388": 9769, + "12389": 9769, + "12390": 9856, + "12391": 9857, + "12392": 9769, + "12393": 9769, + "12394": 9769, + "12395": 9769, + "12396": 9769, + "12397": 9772, + "12398": 9770, + "12399": 9771, + "12400": 9707, + "12401": 9708, + "12402": 9853, + "12403": 9709, + "12404": 9710, + "12405": 9711, + "12406": 9708, + "12407": 9707, + "12408": 9708, + "12410": 9709, + "12411": 9710, + "12412": 9711, + "12413": 9712, + "12414": 9713, + "12415": 9738, + "12416": 9739, + "12417": 9740, + "12418": 9808, + "12419": 9619, + "12420": 9886, + "12421": 9887, + "12422": 9888, + "12423": 9889, + "12424": 9890, + "12425": 9891, + "12426": 9892, + "12427": 9893, + "12428": 9894, + "12429": 9813, + "12430": 9813, + "12431": 9815, + "12432": 9816, + "12433": 9817, + "12434": 9818, + "12435": 9819, + "12436": 9829, + "12437": 9830, + "12438": 9826, + "12439": 9827, + "12440": 9828, + "12441": 9813, + "12442": 9814, + "12443": 9815, + "12444": 9821, + "12445": 9818, + "12446": 9819, + "12447": 9820, + "12448": 9830, + "12449": 9831, + "12450": 9832, + "12451": 9747, + "12452": 9748, + "12453": 9746, + "12454": 9751, + "12455": 9752, + "12456": 9751, + "12457": 9752, + "12458": 9753, + "12459": 9754, + "12460": 9755, + "12461": 9756, + "12462": 9755, + "12463": 9756, + "12464": 9757, + "12465": 9758, + "12466": 9759, + "12467": 9760, + "12468": 9761, + "12469": 9935, + "12470": 9763, + "12471": 9328, + "12472": 717, + "12473": 9750, + "12474": 9838, + "12475": 9839, + "12476": 9840, + "12477": 9841, + "12478": 9842, + "12479": 9843, + "12480": 9844, + "12481": 9849, + "12482": 9847, + "12483": 9838, + "12484": 9839, + "12485": 9851, + "12486": 9852, + "12487": 9840, + "12488": 9841, + "12489": 9842, + "12490": 9850, + "12491": 9843, + "12492": 9844, + "12493": 9845, + "12494": 9846, + "12495": 9849, + "12496": 9847, + "12497": 9848, + "12498": 108, + "12499": 108, + "12500": 9888, + "12501": 9889, + "12502": 9890, + "12505": 9877, + "12506": 9939, + "12507": 752, + "12508": 9853, + "12509": 9855, + "12510": 9856, + "12511": 9857, + "12512": 9858, + "12513": 9859, + "12514": 9860, + "12515": 9861, + "12516": 9862, + "12517": 9854, + "12518": 9853, + "12519": 9855, + "12520": 9856, + "12521": 9857, + "12522": 9858, + "12523": 9859, + "12524": 9860, + "12525": 9861, + "12526": 9862, + "12527": 9854, + "12528": 9796, + "12529": 9796, + "12530": 9796, + "12531": 9796, + "12532": 9796, + "12533": 9908, + "12534": 9909, + "12535": 9908, + "12536": 10002, + "12537": 9910, + "12538": 9869, + "12539": 9870, + "12540": 9871, + "12541": 9872, + "12542": 9346, + "12543": 9873, + "12544": 9875, + "12545": 9876, + "12546": 9874, + "12547": 9877, + "12548": 9878, + "12549": 316, + "12550": 9879, + "12551": 9881, + "12552": 9880, + "12553": 108, + "12554": 108, + "12555": 9863, + "12556": 9838, + "12557": 9840, + "12558": 9841, + "12559": 9842, + "12560": 9843, + "12561": 9844, + "12562": 9849, + "12563": 9847, + "12564": 9863, + "12565": 9838, + "12566": 9938, + "12567": 9851, + "12568": 9840, + "12569": 9841, + "12570": 9842, + "12571": 10037, + "12572": 9843, + "12573": 9844, + "12574": 9849, + "12575": 9847, + "12576": 10042, + "12577": 9908, + "12578": 10044, + "12579": 9895, + "12580": 9896, + "12581": 9897, + "12582": 9898, + "12583": 9898, + "12584": 9898, + "12585": 9332, + "12586": 9398, + "12587": 9902, + "12588": 9903, + "12589": 9904, + "12590": 9905, + "12591": 11321, + "12592": 3633, + "12593": 9834, + "12594": 9836, + "12595": 9978, + "12596": 9980, + "12597": 9834, + "12598": 9835, + "12599": 9836, + "12600": 9984, + "12601": 3634, + "12602": 3639, + "12603": 3642, + "12604": 3632, + "12605": 3458, + "12606": 3458, + "12607": 11315, + "12608": 11316, + "12609": 108, + "12610": 11318, + "12611": 3632, + "12612": 3458, + "12613": 4954, + "12614": 223, + "12615": 3458, + "12616": 11319, + "12621": 9821, + "12627": 9696, + "12628": 9696, + "12629": 9868, + "12630": 3983, + "12631": 11314, + "12632": 3635, + "12633": 3636, + "12634": 3637, + "12635": 3638, + "12636": 3640, + "12637": 3641, + "12638": 3643, + "12639": 3644, + "12640": 9696, + "12641": 9696, + "12642": 9700, + "12643": 9700, + "12644": 9700, + "12645": 9700, + "12646": 3984, + "12647": 3983, + "12648": 11314, + "12649": 10075, + "12650": 10077, + "12651": 10074, + "12652": 11270, + "12653": 9696, + "12654": 9696, + "12656": 9513, + "12657": 9696, + "12658": 10124, + "12659": 9696, + "12660": 9696, + "12661": 4093, + "12662": 9864, + "12663": 9865, + "12664": 9866, + "12665": 9867, + "12666": 9871, + "12667": 9911, + "12668": 9912, + "12672": 9965, + "12673": 9917, + "12674": 9967, + "12675": 9968, + "12676": 9969, + "12677": 9970, + "12678": 9971, + "12679": 9879, + "12680": 9917, + "12681": 10103, + "12682": 108, + "12683": 9902, + "12684": 9879, + "12685": 9948, + "12686": 108, + "12687": 108, + "12688": 9949, + "12689": 9950, + "12690": 9951, + "12691": 9918, + "12692": 9919, + "12693": 9921, + "12694": 9922, + "12695": 9664, + "12696": 9136, + "12697": 9923, + "12698": 10064, + "12699": 10063, + "12700": 9941, + "12701": 9942, + "12702": 9943, + "12703": 9944, + "12704": 9945, + "12705": 9946, + "12706": 10065, + "12707": 10066, + "12708": 9989, + "12709": 9988, + "12710": 9992, + "12711": 9993, + "12712": 9649, + "12713": 10059, + "12714": 9133, + "12715": 10004, + "12716": 10076, + "12717": 10068, + "12718": 10069, + "12719": 10070, + "12720": 10071, + "12721": 10072, + "12722": 10073, + "12723": 10007, + "12724": 10008, + "12725": 10009, + "12726": 108, + "12727": 10064, + "12728": 9955, + "12729": 9938, + "12730": 9947, + "12731": 9514, + "12732": 9429, + "12733": 9939, + "12734": 9940, + "12735": 10095, + "12737": 9409, + "12738": 9390, + "12739": 9694, + "12740": 9695, + "12741": 9924, + "12742": 9928, + "12743": 9929, + "12744": 9930, + "12745": 9925, + "12746": 9926, + "12747": 9927, + "12748": 9969, + "12749": 9970, + "12750": 9971, + "12751": 9972, + "12752": 9973, + "12753": 9974, + "12754": 10057, + "12755": 10100, + "12756": 108, + "12757": 10097, + "12758": 10098, + "12759": 10109, + "12760": 10113, + "12761": 10108, + "12762": 10101, + "12763": 10107, + "12764": 108, + "12765": 10192, + "12766": 10006, + "12767": 9409, + "12768": 9694, + "12769": 9453, + "12770": 10005, + "12771": 9346, + "12772": 10010, + "12773": 9869, + "12774": 9870, + "12775": 10011, + "12776": 10013, + "12777": 10014, + "12778": 9349, + "12779": 9348, + "12780": 8378, + "12781": 10016, + "12782": 10017, + "12783": 10018, + "12784": 10019, + "12785": 10020, + "12786": 10021, + "12787": 10022, + "12788": 10024, + "12789": 10026, + "12790": 10025, + "12791": 10026, + "12792": 10053, + "12793": 10028, + "12794": 10029, + "12795": 10030, + "12796": 3573, + "12797": 10031, + "12798": 10032, + "12799": 10033, + "12800": 10034, + "12801": 10037, + "12802": 10041, + "12803": 10041, + "12804": 10042, + "12805": 10043, + "12806": 10044, + "12807": 10046, + "12808": 10024, + "12809": 10026, + "12810": 10030, + "12811": 3573, + "12812": 10047, + "12813": 10048, + "12814": 10049, + "12815": 10050, + "12816": 10053, + "12817": 10054, + "12818": 10055, + "12819": 10056, + "12820": 10021, + "12821": 10016, + "12822": 10017, + "12823": 10018, + "12824": 10036, + "12825": 10038, + "12826": 10039, + "12827": 10040, + "12828": 10035, + "12829": 10012, + "12830": 10377, + "12831": 10378, + "12832": 10379, + "12833": 10380, + "12834": 10381, + "12835": 10382, + "12836": 10383, + "12837": 10384, + "12838": 10939, + "12839": 10386, + "12840": 10387, + "12841": 10388, + "12842": 10389, + "12843": 10390, + "12844": 10058, + "12845": 9956, + "12846": 9664, + "12847": 10082, + "12848": 10191, + "12849": 10084, + "12850": 9932, + "12851": 9933, + "12852": 9934, + "12853": 9935, + "12854": 9936, + "12855": 9937, + "12856": 108, + "12857": 10057, + "12858": 10057, + "12859": 9961, + "12860": 9962, + "12861": 9963, + "12862": 9963, + "12863": 9961, + "12864": 9963, + "12865": 9962, + "12866": 9964, + "12867": 9965, + "12868": 9966, + "12869": 9967, + "12870": 10079, + "12871": 10080, + "12872": 10081, + "12873": 10082, + "12874": 10086, + "12875": 11214, + "12876": 10456, + "12877": 10456, + "12878": 10073, + "12879": 10074, + "12880": 9384, + "12881": 9423, + "12882": 9384, + "12883": 9361, + "12884": 9388, + "12885": 9682, + "12886": 9388, + "12887": 10160, + "12888": 9429, + "12889": 9432, + "12890": 10001, + "12891": 9559, + "12892": 2142, + "12893": 10002, + "12894": 10000, + "12895": 10003, + "12896": 278, + "12897": 9958, + "12898": 9959, + "12899": 9960, + "12900": 9366, + "12901": 9367, + "12902": 7954, + "12903": 3164, + "12904": 3169, + "12905": 108, + "12906": 108, + "12907": 10214, + "12908": 9682, + "12909": 9564, + "12910": 9366, + "12911": 9367, + "12912": 7954, + "12913": 10177, + "12914": 10120, + "12915": 10121, + "12916": 10122, + "12917": 10123, + "12918": 10124, + "12919": 10125, + "12920": 10126, + "12921": 10130, + "12922": 10131, + "12923": 10132, + "12924": 10127, + "12925": 10133, + "12926": 10128, + "12927": 10129, + "12928": 10134, + "12929": 10135, + "12930": 10136, + "12931": 10137, + "12932": 10138, + "12933": 10139, + "12934": 10140, + "12935": 10141, + "12936": 10142, + "12937": 10143, + "12938": 10129, + "12939": 10144, + "12940": 10145, + "12941": 10146, + "12942": 10128, + "12943": 10147, + "12944": 10148, + "12945": 10149, + "12946": 10150, + "12947": 10126, + "12948": 10127, + "12949": 10151, + "12950": 10152, + "12951": 10153, + "12952": 10154, + "12953": 10155, + "12954": 10156, + "12955": 10157, + "12956": 10158, + "12957": 10159, + "12958": 10160, + "12959": 10127, + "12960": 10161, + "12961": 10162, + "12962": 10163, + "12963": 10126, + "12964": 10164, + "12965": 10165, + "12966": 10166, + "12967": 10167, + "12968": 10129, + "12969": 10168, + "12970": 10169, + "12971": 10170, + "12972": 10128, + "12973": 10171, + "12974": 10172, + "12975": 10173, + "12976": 10174, + "12978": 10558, + "12987": 9950, + "12988": 9920, + "12989": 9950, + "12990": 9950, + "12991": 10212, + "12992": 10211, + "12993": 9947, + "12995": 10574, + "12996": 9380, + "12997": 10210, + "12998": 10209, + "12999": 10208, + "13000": 10207, + "13002": 10205, + "13003": 10204, + "13004": 10057, + "13005": 10057, + "13006": 10213, + "13007": 10203, + "13009": 10588, + "13011": 108, + "13012": 108, + "13013": 9975, + "13014": 9976, + "13015": 9977, + "13016": 9978, + "13017": 9979, + "13018": 9980, + "13019": 9957, + "13020": 9953, + "13021": 9954, + "13022": 9954, + "13023": 9953, + "13024": 9954, + "13025": 9954, + "13026": 9432, + "13027": 9981, + "13028": 9982, + "13029": 9983, + "13030": 108, + "13031": 9984, + "13032": 9983, + "13033": 9985, + "13034": 9985, + "13035": 9986, + "13036": 9987, + "13037": 9896, + "13038": 9897, + "13039": 3164, + "13040": 3169, + "13041": 10175, + "13042": 10176, + "13043": 10177, + "13044": 9404, + "13045": 10178, + "13046": 9898, + "13047": 9374, + "13048": 9374, + "13049": 9901, + "13050": 9900, + "13051": 9901, + "13052": 9901, + "13053": 9946, + "13054": 10067, + "13055": 10182, + "13056": 10215, + "13057": 6529, + "13058": 10087, + "13059": 10268, + "13060": 10089, + "13061": 10090, + "13062": 10271, + "13063": 10092, + "13064": 10093, + "13065": 10612, + "13066": 108, + "13067": 10614, + "13068": 10615, + "13069": 10616, + "13070": 4385, + "13071": 3293, + "13072": 9975, + "13073": 9976, + "13074": 9978, + "13075": 108, + "13076": 108, + "13077": 108, + "13078": 108, + "13079": 10288, + "13080": 10292, + "13081": 10295, + "13082": 10193, + "13083": 108, + "13084": 9380, + "13085": 9397, + "13086": 10252, + "13087": 9425, + "13088": 10892, + "13089": 10062, + "13090": 10299, + "13091": 10396, + "13092": 10397, + "13093": 108, + "13094": 108, + "13095": 108, + "13096": 108, + "13098": 108, + "13099": 108, + "13100": 108, + "13101": 108, + "13102": 108, + "13103": 10083, + "13104": 10084, + "13105": 10085, + "13106": 10219, + "13107": 10224, + "13108": 10242, + "13109": 9503, + "13110": 9503, + "13111": 117, + "13112": 9378, + "13113": 10251, + "13114": 9344, + "13115": 9344, + "13116": 9344, + "13117": 1455, + "13118": 11313, + "13119": 11312, + "13120": 10099, + "13121": 10099, + "13122": 10099, + "13123": 108, + "13124": 108, + "13125": 108, + "13126": 108, + "13127": 10104, + "13128": 10105, + "13129": 10106, + "13130": 10240, + "13131": 10177, + "13132": 10184, + "13133": 10222, + "13134": 10223, + "13135": 10110, + "13136": 10111, + "13137": 10112, + "13138": 10116, + "13139": 108, + "13140": 10114, + "13141": 108, + "13142": 108, + "13143": 10115, + "13144": 10102, + "13145": 10117, + "13146": 10118, + "13147": 10240, + "13148": 10179, + "13149": 10180, + "13150": 10183, + "13151": 10186, + "13152": 10183, + "13153": 10239, + "13154": 10229, + "13155": 10220, + "13156": 10393, + "13157": 10393, + "13158": 10394, + "13160": 9425, + "13161": 9665, + "13162": 10024, + "13163": 10026, + "13164": 10030, + "13165": 3573, + "13166": 10049, + "13167": 10050, + "13168": 10055, + "13169": 10056, + "13170": 10019, + "13171": 10020, + "13172": 10186, + "13173": 10221, + "13174": 10189, + "13175": 253, + "13176": 10356, + "13177": 10357, + "13178": 108, + "13179": 10130, + "13180": 10184, + "13181": 10222, + "13182": 10223, + "13183": 10234, + "13184": 10235, + "13185": 10236, + "13186": 10237, + "13187": 10243, + "13188": 10244, + "13189": 10185, + "13190": 9386, + "13191": 9967, + "13192": 10225, + "13193": 10226, + "13194": 10227, + "13195": 10228, + "13196": 9595, + "13197": 10245, + "13198": 10241, + "13199": 9936, + "13201": 10131, + "13202": 10132, + "13203": 10132, + "13204": 10063, + "13205": 10159, + "13206": 10184, + "13207": 10182, + "13208": 9386, + "13209": 10182, + "13210": 9377, + "13211": 10187, + "13212": 10187, + "13213": 10185, + "13214": 10217, + "13215": 10181, + "13216": 10181, + "13217": 10181, + "13218": 10177, + "13219": 3164, + "13220": 3169, + "13221": 9939, + "13222": 10124, + "13223": 10216, + "13224": 10218, + "13225": 10183, + "13226": 10239, + "13227": 9519, + "13228": 9902, + "13229": 10186, + "13230": 6945, + "13231": 108, + "13232": 108, + "13233": 9633, + "13234": 5851, + "13235": 10230, + "13236": 10231, + "13237": 10232, + "13238": 3459, + "13239": 9388, + "13240": 9386, + "13241": 108, + "13242": 108, + "13243": 108, + "13244": 108, + "13245": 108, + "13246": 108, + "13247": 108, + "13248": 108, + "13249": 108, + "13250": 108, + "13251": 9388, + "13252": 9387, + "13253": 9595, + "13254": 10216, + "13255": 10252, + "13256": 9425, + "13257": 9939, + "13258": 10238, + "13259": 108, + "13260": 11264, + "13261": 5239, + "13262": 713, + "13263": 1492, + "13264": 8378, + "13265": 9363, + "13266": 9363, + "13267": 11271, + "13268": 10586, + "13269": 10586, + "13270": 10586, + "13271": 10898, + "13272": 10898, + "13273": 10899, + "13274": 10243, + "13275": 10244, + "13276": 9695, + "13277": 9408, + "13278": 9695, + "13279": 108, + "13280": 10231, + "13281": 108, + "13282": 10207, + "13283": 10250, + "13284": 10249, + "13285": 9344, + "13286": 9344, + "13287": 9344, + "13288": 10717, + "13289": 10718, + "13290": 10269, + "13291": 10719, + "13292": 10272, + "13293": 9425, + "13294": 10256, + "13295": 10257, + "13296": 10258, + "13297": 10259, + "13298": 10257, + "13299": 10256, + "13300": 108, + "13301": 10249, + "13302": 9543, + "13303": 10279, + "13304": 10280, + "13305": 10281, + "13306": 10282, + "13307": 10283, + "13308": 10284, + "13309": 10285, + "13310": 10286, + "13311": 10287, + "13312": 10288, + "13313": 10289, + "13314": 10419, + "13315": 10420, + "13316": 10421, + "13317": 10422, + "13318": 10423, + "13319": 10424, + "13320": 10425, + "13321": 10426, + "13322": 10427, + "13323": 10428, + "13324": 10429, + "13325": 10430, + "13326": 10431, + "13327": 10432, + "13328": 10433, + "13329": 10434, + "13330": 10435, + "13331": 108, + "13332": 108, + "13333": 108, + "13334": 10403, + "13335": 10401, + "13336": 10402, + "13337": 10364, + "13338": 10365, + "13339": 10366, + "13340": 10367, + "13341": 10446, + "13342": 10369, + "13343": 11166, + "13344": 10371, + "13345": 10372, + "13346": 10373, + "13347": 10374, + "13348": 10375, + "13349": 10398, + "13350": 10395, + "13351": 10327, + "13352": 10404, + "13353": 10405, + "13354": 10406, + "13355": 10407, + "13356": 10586, + "13357": 10587, + "13358": 10588, + "13359": 10589, + "13360": 1492, + "13361": 10457, + "13362": 10458, + "13363": 10459, + "13364": 10460, + "13365": 10461, + "13366": 10462, + "13367": 10463, + "13368": 10473, + "13369": 10464, + "13370": 10465, + "13371": 10476, + "13372": 10467, + "13373": 10468, + "13374": 10469, + "13375": 10470, + "13376": 10471, + "13377": 10482, + "13378": 10473, + "13379": 10474, + "13380": 10475, + "13381": 108, + "13382": 108, + "13383": 108, + "13384": 108, + "13385": 108, + "13386": 10491, + "13387": 10492, + "13388": 10668, + "13389": 10669, + "13390": 10670, + "13391": 10671, + "13392": 10672, + "13393": 10673, + "13394": 10674, + "13395": 10675, + "13396": 10676, + "13397": 10677, + "13398": 10678, + "13399": 10679, + "13400": 108, + "13401": 10680, + "13402": 10681, + "13403": 10682, + "13404": 108, + "13405": 10683, + "13406": 108, + "13407": 108, + "13408": 108, + "13409": 108, + "13410": 10684, + "13411": 10685, + "13412": 10686, + "13413": 10687, + "13414": 10688, + "13415": 10689, + "13416": 10690, + "13417": 10290, + "13418": 10291, + "13419": 10292, + "13420": 108, + "13421": 108, + "13422": 10293, + "13423": 10762, + "13424": 108, + "13425": 10590, + "13426": 10591, + "13427": 10592, + "13428": 10707, + "13429": 10594, + "13430": 10595, + "13431": 10596, + "13432": 10597, + "13433": 10598, + "13434": 10599, + "13435": 10600, + "13436": 10601, + "13437": 10602, + "13438": 10603, + "13439": 10604, + "13440": 10605, + "13441": 10606, + "13442": 10607, + "13443": 10608, + "13444": 10609, + "13445": 10610, + "13446": 10611, + "13447": 10612, + "13448": 10613, + "13449": 10614, + "13450": 10399, + "13451": 10494, + "13452": 10495, + "13453": 108, + "13454": 10408, + "13455": 10409, + "13456": 10410, + "13457": 10411, + "13458": 10412, + "13459": 10413, + "13460": 10414, + "13461": 10415, + "13462": 10407, + "13463": 10406, + "13464": 10648, + "13465": 10649, + "13466": 10650, + "13467": 10651, + "13468": 10652, + "13469": 10653, + "13470": 10654, + "13471": 10655, + "13472": 10656, + "13473": 10657, + "13474": 10658, + "13475": 10659, + "13476": 10942, + "13477": 10660, + "13478": 10661, + "13479": 10662, + "13480": 10663, + "13481": 10664, + "13482": 10665, + "13483": 10666, + "13484": 9349, + "13485": 10012, + "13486": 8378, + "13487": 4846, + "13488": 10259, + "13489": 10257, + "13490": 10256, + "13491": 10409, + "13492": 10412, + "13493": 10411, + "13494": 10413, + "13495": 10416, + "13496": 10417, + "13497": 10376, + "13498": 1401, + "13499": 4149, + "13500": 1400, + "13501": 1401, + "13502": 1400, + "13503": 10261, + "13504": 10261, + "13505": 10262, + "13506": 10263, + "13507": 10264, + "13508": 10313, + "13509": 10314, + "13510": 10315, + "13511": 10316, + "13512": 10317, + "13513": 10450, + "13514": 10450, + "13515": 10400, + "13516": 10400, + "13517": 10400, + "13518": 1415, + "13519": 10331, + "13520": 10332, + "13521": 10333, + "13522": 10335, + "13523": 10336, + "13524": 10697, + "13525": 11217, + "13526": 10698, + "13527": 10699, + "13528": 10700, + "13529": 10701, + "13530": 10702, + "13531": 10703, + "13532": 10704, + "13533": 10705, + "13534": 10706, + "13535": 10707, + "13536": 10708, + "13537": 10709, + "13538": 10710, + "13539": 10711, + "13540": 10712, + "13541": 10713, + "13542": 10714, + "13543": 10715, + "13544": 10716, + "13545": 10334, + "13546": 10453, + "13547": 10454, + "13548": 10452, + "13549": 10453, + "13550": 10454, + "13551": 5531, + "13552": 10452, + "13553": 10451, + "13554": 10451, + "13555": 10448, + "13556": 5640, + "13557": 10448, + "13558": 10448, + "13559": 10447, + "13560": 11195, + "13561": 10561, + "13562": 10443, + "13563": 108, + "13564": 108, + "13565": 108, + "13566": 108, + "13567": 108, + "13568": 108, + "13569": 108, + "13570": 108, + "13571": 10449, + "13572": 10449, + "13573": 10400, + "13574": 10905, + "13575": 10905, + "13576": 10905, + "13577": 10905, + "13578": 10905, + "13579": 10906, + "13580": 10907, + "13581": 10908, + "13582": 10909, + "13583": 10456, + "13584": 10911, + "13585": 10912, + "13586": 274, + "13587": 274, + "13588": 10459, + "13589": 10905, + "13590": 10905, + "13591": 10905, + "13592": 10267, + "13593": 10267, + "13594": 10913, + "13595": 10914, + "13596": 10915, + "13597": 10916, + "13598": 10268, + "13599": 10918, + "13600": 11070, + "13601": 10345, + "13602": 10345, + "13603": 108, + "13604": 108, + "13605": 108, + "13606": 10920, + "13607": 10910, + "13608": 10497, + "13609": 10921, + "13610": 10922, + "13611": 10500, + "13612": 10501, + "13613": 10502, + "13614": 10503, + "13615": 10504, + "13616": 10505, + "13617": 10506, + "13618": 10507, + "13619": 10508, + "13620": 10509, + "13621": 10510, + "13622": 10511, + "13623": 10518, + "13624": 10497, + "13625": 10920, + "13626": 10496, + "13627": 10720, + "13628": 10721, + "13629": 10794, + "13630": 10722, + "13631": 10720, + "13632": 10721, + "13633": 10724, + "13634": 10799, + "13635": 10722, + "13636": 10725, + "13637": 10726, + "13638": 10727, + "13639": 10728, + "13640": 10318, + "13641": 10319, + "13642": 10320, + "13643": 10321, + "13644": 10322, + "13645": 10323, + "13646": 10324, + "13647": 10325, + "13648": 10326, + "13649": 10327, + "13650": 10328, + "13651": 10329, + "13652": 10330, + "13653": 10347, + "13654": 10347, + "13655": 10347, + "13656": 10347, + "13657": 10871, + "13658": 10869, + "13659": 10870, + "13660": 10873, + "13661": 10874, + "13662": 10875, + "13663": 10876, + "13664": 10877, + "13665": 10872, + "13666": 108, + "13667": 10878, + "13668": 10879, + "13669": 10881, + "13670": 10880, + "13671": 10882, + "13672": 10883, + "13673": 10884, + "13674": 10885, + "13675": 108, + "13676": 108, + "13677": 10269, + "13678": 10926, + "13679": 10271, + "13680": 10271, + "13681": 10272, + "13682": 10272, + "13683": 10269, + "13684": 10269, + "13685": 10269, + "13686": 10479, + "13687": 10480, + "13688": 10481, + "13689": 10482, + "13690": 10483, + "13691": 10484, + "13692": 10485, + "13693": 10486, + "13694": 10919, + "13695": 10488, + "13696": 10490, + "13697": 10489, + "13698": 10492, + "13699": 10491, + "13700": 10479, + "13701": 11215, + "13702": 10731, + "13703": 10732, + "13704": 10730, + "13705": 10729, + "13706": 4636, + "13707": 4637, + "13708": 3799, + "13709": 10734, + "13710": 10735, + "13711": 10455, + "13712": 10455, + "13713": 10455, + "13714": 10455, + "13715": 10455, + "13716": 10455, + "13717": 10800, + "13718": 10341, + "13719": 10343, + "13720": 10344, + "13721": 10348, + "13722": 10348, + "13723": 10348, + "13724": 10348, + "13725": 10342, + "13726": 10266, + "13727": 10295, + "13728": 541, + "13729": 10438, + "13730": 10650, + "13731": 10441, + "13732": 10439, + "13733": 10436, + "13734": 10437, + "13735": 10294, + "13736": 10295, + "13737": 10296, + "13738": 10297, + "13739": 10908, + "13740": 10299, + "13741": 10911, + "13742": 10301, + "13743": 10302, + "13744": 10303, + "13745": 10304, + "13746": 10305, + "13747": 10306, + "13748": 10307, + "13749": 11196, + "13750": 11197, + "13751": 10525, + "13752": 11198, + "13753": 10312, + "13754": 10354, + "13755": 108, + "13756": 10278, + "13757": 10620, + "13758": 10619, + "13759": 10625, + "13760": 10634, + "13761": 10633, + "13762": 10729, + "13763": 10730, + "13764": 10731, + "13765": 10732, + "13766": 10733, + "13767": 10734, + "13768": 10735, + "13769": 4130, + "13770": 10337, + "13771": 10337, + "13772": 10338, + "13773": 10339, + "13774": 10340, + "13775": 10615, + "13776": 10273, + "13777": 10274, + "13778": 10270, + "13779": 10274, + "13780": 10270, + "13781": 10270, + "13782": 10274, + "13783": 596, + "13784": 10277, + "13785": 10275, + "13786": 108, + "13787": 10622, + "13788": 10621, + "13789": 10624, + "13790": 10623, + "13791": 10629, + "13792": 10923, + "13793": 10924, + "13794": 10925, + "13795": 10926, + "13796": 10927, + "13797": 10928, + "13798": 10929, + "13799": 10930, + "13800": 10931, + "13801": 10932, + "13802": 10931, + "13803": 10928, + "13804": 10933, + "13805": 10934, + "13806": 10933, + "13807": 10935, + "13808": 10936, + "13809": 10904, + "13810": 10937, + "13811": 10937, + "13812": 10938, + "13813": 10939, + "13814": 10940, + "13815": 10940, + "13816": 10940, + "13817": 10941, + "13818": 10942, + "13819": 10632, + "13820": 10626, + "13821": 10742, + "13822": 108, + "13823": 10743, + "13824": 10744, + "13825": 10745, + "13826": 10742, + "13827": 10743, + "13828": 10943, + "13829": 10944, + "13830": 10418, + "13831": 10414, + "13832": 10415, + "13833": 10627, + "13834": 10617, + "13835": 10630, + "13836": 10647, + "13837": 6148, + "13838": 9678, + "13839": 10772, + "13840": 10259, + "13841": 2667, + "13842": 2667, + "13843": 108, + "13844": 10886, + "13845": 10887, + "13846": 10888, + "13847": 10889, + "13848": 10890, + "13849": 10891, + "13850": 10945, + "13851": 10631, + "13852": 10731, + "13853": 10732, + "13854": 10400, + "13855": 10513, + "13856": 10519, + "13857": 10523, + "13858": 10529, + "13859": 10532, + "13860": 11208, + "13861": 10539, + "13862": 10548, + "13863": 11211, + "13864": 11212, + "13865": 10551, + "13866": 10552, + "13867": 10553, + "13868": 10549, + "13869": 10550, + "13870": 11213, + "13871": 10552, + "13872": 5239, + "13873": 4130, + "13874": 9363, + "13875": 10557, + "13876": 10558, + "13877": 10559, + "13878": 10549, + "13879": 11212, + "13880": 11213, + "13881": 10552, + "13882": 10560, + "13883": 10561, + "13884": 10562, + "13885": 6146, + "13886": 4740, + "13887": 6153, + "13888": 6152, + "13889": 6149, + "13890": 11210, + "13891": 10013, + "13892": 8378, + "13893": 1492, + "13894": 10572, + "13895": 10937, + "13896": 108, + "13897": 10939, + "13898": 10575, + "13899": 108, + "13900": 10400, + "13901": 10400, + "13902": 10498, + "13903": 4736, + "13904": 10555, + "13905": 10554, + "13906": 10011, + "13907": 10013, + "13908": 10571, + "13909": 9348, + "13910": 10570, + "13911": 10278, + "13912": 10278, + "13913": 655, + "13914": 11165, + "13915": 10526, + "13916": 11206, + "13917": 11207, + "13918": 10444, + "13919": 10512, + "13920": 4386, + "13921": 10578, + "13922": 10579, + "13923": 10580, + "13924": 10581, + "13925": 10582, + "13926": 10584, + "13927": 10585, + "13928": 10893, + "13929": 10894, + "13930": 10895, + "13931": 10896, + "13932": 10897, + "13933": 108, + "13934": 108, + "13935": 108, + "13936": 10618, + "13937": 10628, + "13938": 10616, + "13939": 10476, + "13940": 10477, + "13941": 10478, + "13942": 10937, + "13943": 10277, + "13944": 10273, + "13945": 10350, + "13946": 759, + "13947": 10350, + "13948": 10667, + "13949": 10691, + "13950": 10692, + "13951": 10693, + "13952": 10694, + "13953": 10695, + "13954": 10696, + "13955": 10351, + "13956": 10352, + "13957": 10353, + "13958": 10347, + "13959": 10347, + "13960": 10347, + "13961": 10349, + "13962": 10355, + "13963": 108, + "13964": 10359, + "13965": 10360, + "13966": 10361, + "13967": 10358, + "13968": 10635, + "13969": 10636, + "13970": 10637, + "13971": 10638, + "13972": 10639, + "13973": 10640, + "13974": 10939, + "13975": 10642, + "13976": 10643, + "13977": 10644, + "13978": 10645, + "13979": 10646, + "13980": 11056, + "13981": 11057, + "13982": 11056, + "13983": 11055, + "13984": 11049, + "13985": 11050, + "13986": 11052, + "13987": 11053, + "13988": 11051, + "13989": 11054, + "13990": 11053, + "13991": 11052, + "13992": 11051, + "13993": 11050, + "13994": 11049, + "13995": 11048, + "13996": 11048, + "13997": 11048, + "13998": 11047, + "13999": 11046, + "14000": 11045, + "14001": 11044, + "14002": 11043, + "14003": 11042, + "14004": 11042, + "14005": 11042, + "14006": 11041, + "14007": 11041, + "14008": 11041, + "14009": 11040, + "14010": 11039, + "14011": 11038, + "14012": 11037, + "14013": 11036, + "14014": 11036, + "14015": 11036, + "14016": 11035, + "14017": 11238, + "14018": 11033, + "14019": 11033, + "14020": 11032, + "14021": 11032, + "14022": 11031, + "14023": 11030, + "14024": 11030, + "14025": 11029, + "14026": 11028, + "14027": 11027, + "14028": 11026, + "14029": 11025, + "14030": 11024, + "14031": 11023, + "14032": 10408, + "14033": 10409, + "14034": 10408, + "14035": 10409, + "14036": 10412, + "14037": 10409, + "14038": 541, + "14039": 11022, + "14040": 11021, + "14041": 11020, + "14042": 11019, + "14043": 11018, + "14044": 11017, + "14045": 11016, + "14046": 11015, + "14047": 11014, + "14048": 11013, + "14049": 11012, + "14050": 11011, + "14051": 11010, + "14052": 11009, + "14053": 11008, + "14054": 11007, + "14055": 11006, + "14056": 11005, + "14057": 11004, + "14058": 11003, + "14059": 11002, + "14060": 11001, + "14061": 11000, + "14062": 10999, + "14063": 10998, + "14064": 10997, + "14065": 10996, + "14066": 10995, + "14067": 10994, + "14068": 10947, + "14069": 10993, + "14070": 10992, + "14071": 10990, + "14072": 10991, + "14073": 10990, + "14074": 10989, + "14075": 10989, + "14076": 10988, + "14077": 10988, + "14078": 10987, + "14079": 10986, + "14080": 10986, + "14081": 10985, + "14082": 10984, + "14083": 10984, + "14084": 10984, + "14085": 10983, + "14086": 10983, + "14087": 10982, + "14088": 10981, + "14089": 10980, + "14090": 10979, + "14091": 10978, + "14092": 10977, + "14093": 11047, + "14094": 10976, + "14095": 10975, + "14096": 10974, + "14097": 10973, + "14098": 10972, + "14099": 10971, + "14100": 10970, + "14101": 10969, + "14102": 10968, + "14103": 10967, + "14104": 10966, + "14105": 10965, + "14106": 10964, + "14107": 10963, + "14108": 10962, + "14109": 10961, + "14110": 10960, + "14111": 10959, + "14112": 10958, + "14113": 10957, + "14114": 10956, + "14115": 10955, + "14116": 10954, + "14117": 10953, + "14118": 10952, + "14119": 10951, + "14120": 10950, + "14121": 10949, + "14122": 10948, + "14123": 10947, + "14124": 10946, + "14125": 108, + "14126": 108, + "14127": 11165, + "14128": 2095, + "14129": 1383, + "14130": 11095, + "14131": 10276, + "14132": 10276, + "14133": 10273, + "14134": 11193, + "14135": 10274, + "14136": 10276, + "14137": 10385, + "14138": 10900, + "14139": 10391, + "14140": 10370, + "14141": 10368, + "14142": 10793, + "14143": 10794, + "14144": 10804, + "14145": 11216, + "14146": 10749, + "14147": 10750, + "14148": 10756, + "14149": 10757, + "14150": 10760, + "14151": 10758, + "14152": 10754, + "14153": 10759, + "14154": 10755, + "14155": 10761, + "14156": 10796, + "14157": 10795, + "14158": 10798, + "14159": 10547, + "14160": 10805, + "14161": 10807, + "14162": 10801, + "14163": 10802, + "14164": 10830, + "14165": 10803, + "14166": 10797, + "14167": 10806, + "14168": 10641, + "14169": 10923, + "14170": 10924, + "14171": 10927, + "14172": 10926, + "14173": 10490, + "14174": 10746, + "14175": 10747, + "14176": 10748, + "14177": 10751, + "14178": 10752, + "14179": 10274, + "14180": 10274, + "14181": 11144, + "14182": 11188, + "14183": 11145, + "14184": 11189, + "14185": 11189, + "14186": 11146, + "14187": 11147, + "14188": 11148, + "14189": 10819, + "14190": 10818, + "14191": 10811, + "14192": 10816, + "14193": 10812, + "14194": 10817, + "14195": 10814, + "14196": 10815, + "14197": 10810, + "14198": 10823, + "14199": 10820, + "14200": 10821, + "14201": 10822, + "14202": 11149, + "14203": 10824, + "14204": 11168, + "14205": 11169, + "14206": 10753, + "14207": 10831, + "14208": 10832, + "14209": 10773, + "14210": 10774, + "14211": 10775, + "14212": 10776, + "14213": 10777, + "14214": 10778, + "14215": 10779, + "14216": 10780, + "14217": 10781, + "14218": 10782, + "14219": 10783, + "14220": 10784, + "14221": 10736, + "14222": 10737, + "14223": 10738, + "14224": 10739, + "14225": 10740, + "14226": 10741, + "14227": 11153, + "14228": 11181, + "14229": 11180, + "14230": 11179, + "14231": 11154, + "14232": 11182, + "14233": 11183, + "14234": 11155, + "14235": 11156, + "14236": 11157, + "14237": 11158, + "14238": 11159, + "14239": 108, + "14240": 11163, + "14241": 108, + "14242": 108, + "14243": 10785, + "14244": 11093, + "14245": 11094, + "14246": 11095, + "14247": 11096, + "14248": 11097, + "14249": 11098, + "14250": 11099, + "14251": 11100, + "14252": 11101, + "14253": 11102, + "14254": 11103, + "14255": 11104, + "14256": 11105, + "14257": 11106, + "14258": 11107, + "14259": 11108, + "14260": 11109, + "14261": 11110, + "14262": 11111, + "14263": 11112, + "14264": 11113, + "14265": 11114, + "14266": 11115, + "14267": 11116, + "14268": 11117, + "14269": 11118, + "14270": 11119, + "14271": 11120, + "14272": 11121, + "14273": 11122, + "14274": 11123, + "14275": 11124, + "14276": 11125, + "14277": 11126, + "14278": 11127, + "14279": 11128, + "14280": 11129, + "14281": 11130, + "14282": 11131, + "14283": 11132, + "14284": 11133, + "14285": 11134, + "14286": 11135, + "14287": 11136, + "14288": 11137, + "14289": 11138, + "14290": 11139, + "14291": 11140, + "14292": 11141, + "14293": 11142, + "14294": 11189, + "14295": 108, + "14296": 10860, + "14297": 11192, + "14298": 11150, + "14299": 11151, + "14300": 11152, + "14301": 10925, + "14302": 11195, + "14303": 10813, + "14304": 10771, + "14305": 10790, + "14306": 10791, + "14307": 10786, + "14308": 10787, + "14309": 10788, + "14310": 10789, + "14311": 10813, + "14312": 10376, + "14313": 11077, + "14314": 11184, + "14315": 11078, + "14316": 11185, + "14317": 11186, + "14318": 11079, + "14319": 11080, + "14320": 11081, + "14321": 11082, + "14322": 11083, + "14323": 11084, + "14324": 11085, + "14325": 11187, + "14326": 11086, + "14327": 11087, + "14328": 11088, + "14329": 11089, + "14330": 11090, + "14331": 11091, + "14332": 11092, + "14333": 10825, + "14334": 10826, + "14335": 10721, + "14336": 10721, + "14337": 10827, + "14338": 108, + "14339": 108, + "14340": 108, + "14341": 108, + "14342": 10833, + "14343": 10834, + "14344": 10835, + "14345": 10836, + "14346": 10837, + "14347": 10838, + "14348": 10839, + "14349": 10840, + "14350": 10841, + "14351": 10842, + "14352": 10843, + "14353": 10844, + "14354": 10845, + "14355": 10846, + "14356": 10847, + "14357": 10848, + "14358": 10849, + "14359": 10850, + "14360": 10851, + "14361": 10852, + "14362": 10853, + "14363": 10854, + "14364": 10855, + "14365": 10856, + "14366": 10857, + "14367": 10858, + "14368": 10859, + "14369": 10860, + "14370": 10861, + "14371": 10862, + "14372": 10863, + "14373": 10864, + "14374": 10865, + "14375": 10866, + "14376": 10867, + "14377": 10868, + "14378": 10347, + "14379": 10347, + "14380": 10347, + "14381": 11176, + "14382": 11177, + "14383": 11178, + "14384": 11174, + "14385": 11175, + "14386": 655, + "14387": 11165, + "14388": 8273, + "14389": 258, + "14390": 10577, + "14391": 11073, + "14392": 11074, + "14393": 11075, + "14394": 11076, + "14395": 11072, + "14396": 11167, + "14397": 10365, + "14398": 11143, + "14399": 11160, + "14400": 11143, + "14401": 11161, + "14402": 108, + "14403": 108, + "14404": 11172, + "14405": 11173, + "14406": 10542, + "14407": 11191, + "14408": 5964, + "14409": 108, + "14410": 108, + "14411": 10310, + "14412": 10536, + "14413": 11195, + "14414": 108, + "14415": 10315, + "14416": 10908, + "14417": 108, + "14418": 108, + "14419": 11192, + "14420": 11192, + "14421": 11192, + "14422": 108, + "14423": 8308, + "14424": 10726, + "14425": 11194, + "14426": 10908, + "14427": 2137, + "14428": 2139, + "14429": 2140, + "14430": 2141, + "14431": 2138, + "14432": 2324, + "14433": 2142, + "14434": 11384, + "14435": 10270, + "14436": 10499, + "14437": 11199, + "14438": 10559, + "14439": 510, + "14440": 108, + "14441": 10348, + "14442": 10348, + "14443": 10904, + "14444": 11239, + "14445": 11240, + "14446": 11171, + "14447": 11170, + "14448": 554, + "14449": 11307, + "14450": 2134, + "14451": 2135, + "14452": 2121, + "14453": 2136, + "14454": 11285, + "14455": 11285, + "14456": 9947, + "14457": 11241, + "14458": 11242, + "14459": 11243, + "14460": 548, + "14461": 108, + "14462": 10893, + "14463": 10894, + "14464": 10895, + "14465": 10896, + "14466": 10893, + "14467": 10894, + "14468": 10895, + "14469": 10896, + "14470": 11350, + "14471": 11351, + "14472": 11353, + "14473": 11244, + "14474": 11245, + "14475": 11246, + "14476": 11247, + "14477": 11248, + "14478": 11245, + "14479": 11246, + "14480": 11249, + "14481": 11248, + "14482": 11250, + "14483": 11251, + "14484": 11252, + "14485": 11253, + "14486": 11254, + "14487": 11255, + "14488": 11256, + "14489": 11257, + "14490": 11258, + "14491": 11259, + "14492": 11260, + "14493": 11261, + "14494": 11262, + "14495": 11272, + "14496": 11286, + "14497": 11290, + "14498": 11244, + "14499": 11245, + "14500": 11246, + "14501": 11247, + "14502": 11248, + "14503": 11308, + "14504": 422, + "14505": 428, + "14506": 424, + "14507": 11218, + "14508": 11219, + "14509": 11220, + "14510": 11221, + "14511": 11222, + "14512": 11223, + "14513": 11224, + "14514": 11225, + "14515": 11226, + "14516": 11227, + "14517": 11228, + "14518": 11229, + "14519": 11230, + "14520": 11231, + "14521": 11232, + "14522": 11233, + "14523": 11234, + "14524": 11235, + "14525": 11236, + "14526": 11237, + "14527": 10448, + "14528": 5640, + "14529": 10448, + "14530": 10446, + "14531": 10445, + "14532": 10444, + "14533": 1279, + "14534": 11352, + "14535": 1678, + "14536": 9910, + "14537": 101, + "14538": 557, + "14539": 2106, + "14540": 2109, + "14541": 2116, + "14542": 2118, + "14543": 11216, + "14544": 9910, + "14545": 11277, + "14546": 11278, + "14547": 11322, + "14548": 11279, + "14549": 11280, + "14550": 11302, + "14551": 11303, + "14552": 11304, + "14553": 11305, + "14554": 11292, + "14555": 11293, + "14556": 11294, + "14557": 2124, + "14558": 2125, + "14559": 2126, + "14560": 2128, + "14561": 2130, + "14562": 2092, + "14563": 2121, + "14564": 2089, + "14565": 297, + "14566": 2133, + "14567": 1486, + "14568": 2105, + "14569": 2106, + "14570": 2107, + "14571": 2108, + "14572": 2109, + "14573": 2110, + "14574": 2111, + "14575": 2112, + "14576": 2113, + "14577": 2121, + "14578": 269, + "14579": 270, + "14580": 1486, + "14581": 2160, + "14582": 11275, + "14583": 11276, + "14584": 11273, + "14585": 11274, + "14586": 11274, + "14587": 2137, + "14588": 2141, + "14589": 2140, + "14590": 1804, + "14591": 2139, + "14592": 2137, + "14593": 2142, + "14594": 2138, + "14595": 11286, + "14596": 11374, + "14597": 8482, + "14598": 11089, + "14599": 11290, + "14600": 299, + "14601": 108, + "14602": 108, + "14603": 11281, + "14604": 11282, + "14605": 2172, + "14606": 108, + "14607": 11310, + "14608": 11309, + "14609": 9344, + "14610": 9344, + "14611": 9344, + "14612": 9344, + "14613": 11284, + "14614": 108, + "14615": 11419, + "14616": 2132, + "14617": 108, + "14618": 108, + "14619": 11446, + "14620": 718, + "14621": 719, + "14622": 720, + "14623": 721, + "14624": 722, + "14625": 723, + "14626": 724, + "14627": 725, + "14628": 11258, + "14629": 11288, + "14630": 11289, + "14631": 3369, + "14632": 3370, + "14633": 3371, + "14634": 3374, + "14635": 3375, + "14636": 3375, + "14637": 3375, + "14638": 3375, + "14639": 108, + "14640": 108, + "14641": 108, + "14642": 108, + "14643": 2143, + "14644": 4384, + "14645": 2183, + "14646": 11326, + "14647": 11327, + "14648": 11328, + "14649": 11329, + "14650": 11330, + "14651": 11331, + "14652": 11332, + "14653": 11333, + "14654": 11330, + "14655": 11331, + "14656": 11332, + "14657": 11333, + "14658": 11334, + "14659": 11335, + "14660": 11332, + "14661": 11333, + "14662": 11093, + "14663": 269, + "14664": 297, + "14665": 11420, + "14666": 11421, + "14667": 11233, + "14668": 297, + "14669": 7636, + "14670": 689, + "14671": 108, + "14672": 108, + "14673": 3667, + "14674": 11338, + "14675": 11339, + "14676": 11340, + "14677": 11341, + "14678": 10961, + "14679": 11342, + "14680": 11343, + "14681": 11344, + "14682": 11345, + "14683": 11346, + "14684": 11346, + "14685": 11346, + "14686": 11347, + "14687": 11348, + "14688": 11349, + "14689": 11323, + "14690": 11324, + "14691": 11325, + "14692": 11277, + "14693": 11302, + "14694": 11382, + "14695": 11382, + "14696": 11382, + "14697": 11354, + "14698": 428, + "14699": 11355, + "14700": 11355, + "14701": 11384, + "14702": 1385, + "14703": 11355, + "14704": 3455, + "14705": 10308, + "14706": 11386, + "14707": 108, + "14708": 11388, + "14709": 108, + "14710": 2259, + "14711": 3040, + "14712": 3042, + "14713": 3044, + "14714": 3045, + "14715": 11426, + "14716": 11357, + "14717": 11358, + "14718": 11359, + "14719": 11360, + "14720": 11361, + "14721": 11362, + "14722": 11363, + "14723": 11364, + "14724": 11365, + "14725": 11366, + "14726": 11367, + "14727": 11368, + "14728": 11382, + "14729": 11422, + "14730": 363, + "14731": 11442, + "14732": 11443, + "14733": 11330, + "14734": 11313, + "14735": 11313, + "14736": 10013, + "14737": 4130, + "14738": 4130, + "14739": 11431, + "14740": 11433, + "14741": 2077, + "14742": 1455, + "14743": 1455, + "14744": 10261, + "14745": 10261, + "14746": 4130, + "14747": 4130, + "14748": 4149, + "14749": 4149, + "14750": 11447, + "14751": 11387, + "14752": 11389, + "14753": 11390, + "14754": 11391, + "14755": 11392, + "14756": 2324, + "14757": 11387, + "14758": 11388, + "14759": 11389, + "14760": 11390, + "14761": 11393, + "14762": 11393, + "14763": 11394, + "14764": 11394, + "14765": 11395, + "14766": 11395, + "14767": 11396, + "14768": 11396, + "14769": 11397, + "14770": 11397, + "14771": 11407, + "14772": 11408, + "14773": 11409, + "14774": 11410, + "14775": 11407, + "14776": 11411, + "14777": 213, + "14778": 11413, + "14779": 11414, + "14780": 11415, + "14781": 11415, + "14782": 11416, + "14783": 11417, + "14784": 11418, + "14785": 11418, + "14786": 2354, + "14787": 108, + "14788": 13551, + "14789": 11372, + "14790": 11373, + "14791": 11373, + "14792": 108, + "14793": 11443, + "14794": 3458, + "14795": 3460, + "14796": 3462, + "14797": 3464, + "14798": 10298, + "14799": 11398, + "14800": 10300, + "14801": 10298, + "14802": 11398, + "14803": 10300, + "14804": 108, + "14805": 8378, + "14806": 11416, + "14807": 11416, + "14808": 13174, + "14809": 2376, + "14810": 4776, + "14811": 4776, + "14812": 4777, + "14813": 4778, + "14814": 4779, + "14815": 4780, + "14816": 4776, + "14817": 11393, + "14818": 11394, + "14819": 11395, + "14820": 11396, + "14821": 11397, + "14822": 11440, + "14823": 108, + "14824": 108, + "14825": 11441, + "14826": 11440, + "14827": 108, + "14828": 108, + "14829": 11441, + "14830": 13174, + "14831": 11369, + "14832": 11370, + "14833": 11371, + "14834": 11369, + "14835": 11370, + "14836": 11371, + "14837": 11369, + "14838": 11370, + "14839": 11371, + "14840": 11469, + "14841": 11470, + "14842": 11471, + "14843": 11472, + "14844": 11473, + "14845": 313, + "14846": 11474, + "14847": 11476, + "14848": 11476, + "14849": 11477, + "14850": 11478, + "14851": 11479, + "14852": 11480, + "14853": 11481, + "14854": 322, + "14855": 11483, + "14856": 11484, + "14857": 11485, + "14858": 11486, + "14859": 11487, + "14860": 11488, + "14861": 11490, + "14862": 11491, + "14863": 11492, + "14864": 11387, + "14865": 11388, + "14866": 11389, + "14867": 11390, + "14868": 11493, + "14869": 11494, + "14870": 11495, + "14871": 187, + "14872": 11496, + "14873": 11497, + "14874": 11498, + "14875": 11499, + "14876": 11500, + "14877": 11501, + "14878": 11502, + "14879": 11503, + "14880": 11504, + "14881": 11506, + "14882": 11507, + "14883": 11508, + "14884": 11509, + "14885": 11489, + "14886": 11505, + "14887": 108, + "14888": 11374, + "14889": 11375, + "14890": 11376, + "14891": 11378, + "14892": 11379, + "14893": 11374, + "14894": 11375, + "14895": 11376, + "14896": 11377, + "14897": 11378, + "14898": 11379, + "14899": 11380, + "14900": 108, + "14901": 11381, + "14902": 11462, + "14903": 11381, + "14904": 11462, + "14905": 11462, + "14906": 392, + "14907": 795, + "14908": 5, + "14909": 6, + "14910": 341, + "14911": 11448, + "14912": 37, + "14913": 262, + "14914": 11449, + "14915": 11450, + "14916": 393, + "14917": 11451, + "14918": 11452, + "14919": 11453, + "14920": 780, + "14921": 6942, + "14922": 11454, + "14923": 10173, + "14924": 357, + "14925": 11455, + "14926": 11456, + "14927": 11457, + "14928": 1281, + "14929": 2769, + "14930": 11458, + "14931": 11459, + "14932": 3499, + "14933": 11460, + "14934": 353, + "14935": 12313, + "14936": 12456, + "14937": 12457, + "14938": 12458, + "14939": 12459, + "14940": 12460, + "14941": 1294, + "14942": 13170, + "14943": 3330, + "14944": 11423, + "14945": 11424, + "14946": 11425, + "14947": 11426, + "14948": 11427, + "14949": 11428, + "14950": 11429, + "14951": 11430, + "14952": 11987, + "14953": 11988, + "14954": 11989, + "14955": 11990, + "14956": 11991, + "14957": 11439, + "14958": 11439, + "14959": 11433, + "14960": 11433, + "14961": 11438, + "14962": 11436, + "14963": 11431, + "14964": 11432, + "14965": 314, + "14966": 397, + "14967": 11435, + "14968": 11436, + "14969": 857, + "14970": 3634, + "14971": 2168, + "14972": 2168, + "14973": 2168, + "14974": 2168, + "14975": 2168, + "14976": 2168, + "14977": 2168, + "14978": 2168, + "14979": 2168, + "14980": 2168, + "14981": 2168, + "14982": 2168, + "14983": 11431, + "14984": 11431, + "14985": 11438, + "14986": 11436, + "14987": 108, + "14988": 108, + "14989": 108, + "14990": 108, + "14991": 108, + "14992": 108, + "14993": 108, + "14994": 108, + "14995": 3323, + "14996": 3323, + "14997": 3323, + "14998": 3323, + "14999": 3323, + "15000": 3321, + "15001": 3323, + "15002": 3326, + "15003": 3326, + "15004": 3326, + "15005": 3326, + "15006": 3326, + "15007": 3326, + "15008": 3326, + "15009": 3326, + "15010": 3321, + "15011": 3321, + "15012": 3321, + "15013": 3321, + "15014": 3321, + "15015": 3321, + "15016": 3321, + "15017": 3321, + "15018": 3326, + "15019": 3329, + "15020": 3321, + "15021": 3329, + "15022": 3323, + "15023": 3321, + "15024": 3323, + "15025": 3326, + "15026": 3329, + "15027": 3329, + "15028": 3329, + "15029": 3329, + "15030": 3329, + "15031": 3329, + "15032": 3329, + "15033": 3329, + "15034": 3324, + "15035": 3323, + "15036": 3323, + "15037": 3327, + "15038": 3326, + "15039": 3321, + "15040": 3326, + "15041": 3322, + "15042": 3329, + "15043": 11431, + "15044": 11436, + "15045": 11399, + "15046": 108, + "15047": 108, + "15048": 11517, + "15049": 11399, + "15050": 108, + "15051": 108, + "15052": 11517, + "15053": 11405, + "15054": 11405, + "15055": 11404, + "15056": 11404, + "15057": 11513, + "15058": 11481, + "15059": 11586, + "15060": 11512, + "15061": 11514, + "15062": 11510, + "15063": 11506, + "15064": 11515, + "15065": 108, + "15066": 11513, + "15067": 11481, + "15068": 11511, + "15069": 11512, + "15070": 11514, + "15071": 11510, + "15072": 11506, + "15073": 11515, + "15074": 11995, + "15075": 11996, + "15076": 108, + "15077": 11402, + "15078": 11406, + "15079": 11406, + "15080": 177, + "15081": 1434, + "15082": 11462, + "15083": 11462, + "15084": 11391, + "15085": 11468, + "15086": 12054, + "15087": 11405, + "15088": 565, + "15089": 575, + "15090": 11521, + "15091": 11522, + "15092": 11523, + "15093": 11524, + "15094": 11525, + "15095": 11526, + "15096": 11527, + "15097": 11528, + "15098": 11529, + "15099": 11530, + "15100": 11531, + "15101": 11532, + "15102": 11533, + "15103": 11534, + "15104": 11535, + "15105": 11536, + "15106": 11537, + "15107": 11538, + "15108": 11539, + "15109": 11540, + "15110": 11541, + "15111": 11542, + "15112": 11543, + "15113": 11544, + "15114": 11545, + "15115": 11546, + "15116": 11547, + "15117": 11548, + "15118": 11549, + "15119": 11550, + "15120": 11551, + "15121": 11552, + "15122": 11553, + "15123": 11554, + "15124": 11555, + "15125": 11556, + "15126": 11557, + "15127": 11558, + "15128": 11559, + "15129": 11560, + "15130": 11561, + "15131": 11562, + "15132": 11563, + "15133": 11564, + "15134": 11565, + "15135": 11566, + "15136": 11567, + "15137": 11568, + "15138": 11569, + "15139": 11570, + "15140": 11571, + "15141": 11572, + "15142": 11573, + "15143": 11574, + "15144": 11575, + "15145": 11576, + "15146": 11577, + "15147": 11578, + "15148": 11579, + "15149": 11580, + "15150": 11581, + "15151": 11582, + "15152": 11583, + "15153": 11584, + "15154": 11585, + "15155": 11586, + "15156": 7177, + "15157": 11588, + "15158": 11589, + "15159": 11590, + "15160": 593, + "15161": 11592, + "15162": 11593, + "15163": 11594, + "15164": 11595, + "15165": 11596, + "15166": 11597, + "15167": 11598, + "15168": 11599, + "15169": 11600, + "15170": 11601, + "15171": 11602, + "15172": 11603, + "15173": 11604, + "15174": 11605, + "15175": 11606, + "15176": 11607, + "15177": 11608, + "15178": 11609, + "15179": 11610, + "15180": 11611, + "15181": 11612, + "15182": 11613, + "15183": 11614, + "15184": 11615, + "15185": 11616, + "15186": 11617, + "15187": 11618, + "15188": 11619, + "15189": 11620, + "15190": 11621, + "15191": 11622, + "15192": 11623, + "15193": 11624, + "15194": 11625, + "15195": 11626, + "15196": 11627, + "15197": 11628, + "15198": 11629, + "15199": 11630, + "15200": 11631, + "15201": 11632, + "15202": 11633, + "15203": 11634, + "15204": 11635, + "15205": 11636, + "15206": 11637, + "15207": 11638, + "15208": 11639, + "15209": 11640, + "15210": 11641, + "15211": 11642, + "15212": 11643, + "15213": 11644, + "15214": 11645, + "15215": 11646, + "15216": 11647, + "15217": 11648, + "15218": 11649, + "15219": 11650, + "15220": 11651, + "15221": 11652, + "15222": 11653, + "15223": 11654, + "15224": 11655, + "15225": 11656, + "15226": 11657, + "15227": 11658, + "15228": 11659, + "15229": 11660, + "15230": 11661, + "15231": 11662, + "15232": 11663, + "15233": 11664, + "15234": 11665, + "15235": 11666, + "15236": 11667, + "15237": 11668, + "15238": 11669, + "15239": 11670, + "15240": 11671, + "15241": 11672, + "15242": 11673, + "15243": 11674, + "15244": 11675, + "15245": 11676, + "15246": 11677, + "15247": 11678, + "15248": 11679, + "15249": 11680, + "15250": 11681, + "15251": 11682, + "15252": 11683, + "15253": 11684, + "15254": 11685, + "15255": 11686, + "15256": 11687, + "15257": 11688, + "15258": 11689, + "15259": 11690, + "15260": 11691, + "15261": 11692, + "15262": 11693, + "15263": 11694, + "15264": 11695, + "15265": 11696, + "15266": 11697, + "15267": 11698, + "15268": 11699, + "15269": 11700, + "15270": 11701, + "15271": 11702, + "15272": 11703, + "15273": 11704, + "15274": 11705, + "15275": 11706, + "15276": 11707, + "15277": 11708, + "15278": 11709, + "15279": 11710, + "15280": 11711, + "15281": 11712, + "15282": 11713, + "15283": 11714, + "15284": 11715, + "15285": 11716, + "15286": 11717, + "15287": 11718, + "15288": 11719, + "15289": 11720, + "15290": 11721, + "15291": 11722, + "15292": 11723, + "15293": 11724, + "15294": 11725, + "15295": 11726, + "15296": 11727, + "15297": 11728, + "15298": 11729, + "15299": 11730, + "15300": 11731, + "15301": 11732, + "15302": 11733, + "15303": 11734, + "15304": 11735, + "15305": 11736, + "15306": 11737, + "15307": 11738, + "15308": 11739, + "15309": 11740, + "15310": 11741, + "15311": 11742, + "15312": 11743, + "15313": 11744, + "15314": 11745, + "15315": 11746, + "15316": 11747, + "15317": 11748, + "15318": 11749, + "15319": 11750, + "15320": 11751, + "15321": 11752, + "15322": 11753, + "15323": 11754, + "15324": 11755, + "15325": 11756, + "15326": 11757, + "15327": 11758, + "15328": 11759, + "15329": 11760, + "15330": 11761, + "15331": 11762, + "15332": 11763, + "15333": 11764, + "15334": 11765, + "15335": 11766, + "15336": 11767, + "15337": 11768, + "15338": 11769, + "15339": 11770, + "15340": 11771, + "15341": 11772, + "15342": 11773, + "15343": 11774, + "15344": 11775, + "15345": 11776, + "15346": 11777, + "15347": 11778, + "15348": 11779, + "15349": 11780, + "15350": 11781, + "15351": 11782, + "15352": 11783, + "15353": 11784, + "15354": 11785, + "15355": 11786, + "15356": 11787, + "15357": 11788, + "15358": 11789, + "15359": 11790, + "15360": 11791, + "15361": 11792, + "15362": 11793, + "15363": 11794, + "15364": 11795, + "15365": 11796, + "15366": 11797, + "15367": 11798, + "15368": 11799, + "15369": 11800, + "15370": 11801, + "15371": 11802, + "15372": 11803, + "15373": 11804, + "15374": 11805, + "15375": 11806, + "15376": 11807, + "15377": 11808, + "15378": 11809, + "15379": 11810, + "15380": 11811, + "15381": 11812, + "15382": 11813, + "15383": 11814, + "15384": 11815, + "15385": 11816, + "15386": 11817, + "15387": 11818, + "15388": 11819, + "15389": 11820, + "15390": 11821, + "15391": 11822, + "15392": 11823, + "15393": 11824, + "15394": 11825, + "15395": 11826, + "15396": 11827, + "15397": 11828, + "15398": 11829, + "15399": 11830, + "15400": 11831, + "15401": 11832, + "15402": 11833, + "15403": 11834, + "15404": 11835, + "15405": 11836, + "15406": 11837, + "15407": 11838, + "15408": 11839, + "15409": 11840, + "15410": 11841, + "15411": 11842, + "15412": 11843, + "15413": 11844, + "15414": 11845, + "15415": 11846, + "15416": 11847, + "15417": 11848, + "15418": 11849, + "15419": 11850, + "15420": 11851, + "15421": 11852, + "15422": 11853, + "15423": 11854, + "15424": 11855, + "15425": 11856, + "15426": 11857, + "15427": 11858, + "15428": 11859, + "15429": 11860, + "15430": 11861, + "15431": 11862, + "15432": 11863, + "15433": 11864, + "15434": 11865, + "15435": 11866, + "15436": 11867, + "15437": 11868, + "15438": 11869, + "15439": 11870, + "15440": 11871, + "15441": 11872, + "15442": 11873, + "15443": 11874, + "15444": 11875, + "15445": 11876, + "15446": 11877, + "15447": 11878, + "15448": 11879, + "15449": 11880, + "15450": 11881, + "15451": 11882, + "15452": 11883, + "15453": 11884, + "15454": 11885, + "15455": 11886, + "15456": 11887, + "15457": 11888, + "15458": 11889, + "15459": 11890, + "15460": 11891, + "15461": 11892, + "15462": 11893, + "15463": 11894, + "15464": 11895, + "15465": 11896, + "15466": 11897, + "15467": 11898, + "15468": 11899, + "15469": 11900, + "15470": 11901, + "15471": 11902, + "15472": 11903, + "15473": 11904, + "15474": 11905, + "15475": 11906, + "15476": 11907, + "15477": 11908, + "15478": 11909, + "15479": 11910, + "15480": 11911, + "15481": 11912, + "15482": 11913, + "15483": 11914, + "15484": 11915, + "15485": 11916, + "15486": 11917, + "15487": 11918, + "15488": 11919, + "15489": 11920, + "15490": 11921, + "15491": 11922, + "15492": 11923, + "15493": 11924, + "15494": 11925, + "15495": 11926, + "15496": 11927, + "15497": 11928, + "15498": 11929, + "15499": 11930, + "15500": 11931, + "15501": 11932, + "15502": 11933, + "15503": 11934, + "15504": 11935, + "15505": 11936, + "15506": 11937, + "15507": 11938, + "15508": 11939, + "15509": 11940, + "15510": 11941, + "15511": 11942, + "15512": 11943, + "15513": 11944, + "15514": 11945, + "15515": 11946, + "15516": 11947, + "15517": 11948, + "15518": 11949, + "15519": 11950, + "15520": 11951, + "15521": 11952, + "15522": 11953, + "15523": 11954, + "15524": 11955, + "15525": 11956, + "15526": 11957, + "15527": 11958, + "15528": 11959, + "15529": 11960, + "15530": 11961, + "15531": 11962, + "15532": 11963, + "15533": 11964, + "15534": 11965, + "15535": 11966, + "15536": 11967, + "15537": 11968, + "15538": 11969, + "15539": 11970, + "15540": 11971, + "15541": 11972, + "15542": 11973, + "15543": 11974, + "15544": 11975, + "15545": 11976, + "15546": 11977, + "15547": 11978, + "15548": 11979, + "15549": 11980, + "15550": 11981, + "15551": 11982, + "15552": 11983, + "15553": 11984, + "15554": 11985, + "15555": 11986, + "15556": 11987, + "15557": 11988, + "15558": 11989, + "15559": 11990, + "15560": 11991, + "15561": 11992, + "15562": 108, + "15563": 11994, + "15564": 11433, + "15565": 11433, + "15566": 11433, + "15567": 11433, + "15568": 11433, + "15569": 11433, + "15570": 11433, + "15571": 11433, + "15572": 3321, + "15573": 3321, + "15574": 3326, + "15575": 3326, + "15576": 11463, + "15577": 11464, + "15578": 11465, + "15579": 11466, + "15580": 11467, + "15581": 11519, + "15582": 11520, + "15583": 12062, + "15584": 12061, + "15585": 12094, + "15586": 12081, + "15587": 11525, + "15588": 12095, + "15589": 12020, + "15590": 12021, + "15591": 12022, + "15593": 12082, + "15594": 12088, + "15595": 12087, + "15596": 12086, + "15597": 12084, + "15598": 12085, + "15599": 12083, + "15600": 3329, + "15601": 3329, + "15602": 11431, + "15603": 11431, + "15604": 11431, + "15605": 11431, + "15606": 11431, + "15607": 11431, + "15608": 11431, + "15609": 11431, + "15610": 11431, + "15611": 11431, + "15612": 12100, + "15613": 12101, + "15614": 11992, + "15615": 108, + "15616": 108, + "15617": 108, + "15618": 108, + "15619": 12060, + "15620": 108, + "15621": 9363, + "15622": 108, + "15623": 12045, + "15624": 12043, + "15625": 12046, + "15626": 12047, + "15627": 12048, + "15628": 108, + "15629": 108, + "15630": 108, + "15631": 12269, + "15632": 12052, + "15633": 12250, + "15634": 12251, + "15635": 12252, + "15636": 12253, + "15637": 12254, + "15638": 12255, + "15639": 4954, + "15640": 12247, + "15641": 12248, + "15642": 12073, + "15643": 12246, + "15644": 12316, + "15645": 12263, + "15646": 12264, + "15647": 12079, + "15648": 12080, + "15649": 108, + "15650": 108, + "15651": 12102, + "15652": 12103, + "15653": 12104, + "15654": 12105, + "15655": 11997, + "15656": 11998, + "15657": 11999, + "15658": 12000, + "15659": 12001, + "15660": 12002, + "15661": 12003, + "15662": 12004, + "15663": 12005, + "15664": 12006, + "15665": 12007, + "15666": 12008, + "15667": 12009, + "15668": 12285, + "15669": 12010, + "15670": 12011, + "15671": 12012, + "15672": 12013, + "15673": 12014, + "15674": 12015, + "15675": 12016, + "15676": 12017, + "15677": 12018, + "15678": 12019, + "15679": 12020, + "15680": 12021, + "15681": 12022, + "15682": 12023, + "15683": 12024, + "15684": 12025, + "15685": 12026, + "15686": 12027, + "15687": 12028, + "15688": 12029, + "15689": 12030, + "15690": 12031, + "15691": 12032, + "15692": 12033, + "15693": 12034, + "15694": 12035, + "15695": 12036, + "15696": 12037, + "15697": 12038, + "15698": 12039, + "15699": 12040, + "15700": 12240, + "15701": 12241, + "15702": 12078, + "15703": 12097, + "15704": 12098, + "15705": 12099, + "15706": 12097, + "15707": 108, + "15708": 7695, + "15709": 7696, + "15710": 7697, + "15711": 12142, + "15712": 7635, + "15713": 7635, + "15714": 7633, + "15715": 7634, + "15716": 7640, + "15717": 7636, + "15718": 7637, + "15719": 7638, + "15720": 12257, + "15721": 12257, + "15722": 12258, + "15723": 7639, + "15724": 7695, + "15725": 12256, + "15726": 12259, + "15727": 12260, + "15728": 12063, + "15729": 12066, + "15730": 12067, + "15731": 12349, + "15732": 12069, + "15733": 12070, + "15734": 12071, + "15735": 12067, + "15736": 12067, + "15737": 12072, + "15739": 12170, + "15740": 12073, + "15741": 12074, + "15742": 12075, + "15743": 12076, + "15744": 12077, + "15745": 12065, + "15746": 4808, + "15747": 4810, + "15749": 12057, + "15750": 12059, + "15752": 12280, + "15753": 12056, + "15754": 12056, + "15755": 12056, + "15756": 12054, + "15757": 12099, + "15758": 12057, + "15759": 12059, + "15760": 12059, + "15761": 12280, + "15762": 12056, + "15763": 12056, + "15764": 12056, + "15765": 12058, + "15766": 12058, + "15767": 12058, + "15768": 108, + "15769": 12200, + "15770": 12242, + "15771": 12243, + "15772": 12265, + "15773": 12266, + "15774": 6091, + "15775": 12278, + "15776": 12279, + "15777": 12267, + "15778": 12268, + "15779": 3822, + "15780": 2143, + "15781": 12292, + "15782": 12293, + "15783": 3823, + "15784": 12292, + "15785": 12293, + "15786": 12296, + "15787": 12295, + "15788": 12294, + "15789": 12064, + "15790": 12297, + "15791": 12297, + "15792": 12312, + "15793": 12312, + "15794": 8378, + "15795": 4392, + "15796": 4392, + "15797": 4130, + "15798": 4130, + "15799": 11330, + "15800": 11331, + "15801": 11332, + "15802": 11333, + "15803": 713, + "15804": 713, + "15805": 11262, + "15806": 11262, + "15807": 12236, + "15808": 12237, + "15809": 12238, + "15810": 11418, + "15811": 12086, + "15812": 12319, + "15813": 12319, + "15814": 12106, + "15815": 12107, + "15816": 12108, + "15817": 12109, + "15818": 12110, + "15819": 12111, + "15820": 12112, + "15821": 12113, + "15822": 12114, + "15823": 12115, + "15824": 12116, + "15825": 12117, + "15826": 12118, + "15827": 12122, + "15828": 12121, + "15829": 12120, + "15830": 12119, + "15831": 12123, + "15832": 12124, + "15833": 12125, + "15834": 12126, + "15835": 12127, + "15836": 12128, + "15837": 12129, + "15838": 12130, + "15839": 12131, + "15840": 12132, + "15841": 12133, + "15842": 12134, + "15843": 12135, + "15844": 12136, + "15845": 12137, + "15846": 12138, + "15847": 12139, + "15848": 12140, + "15849": 12141, + "15850": 12142, + "15851": 12143, + "15852": 12144, + "15853": 12145, + "15854": 12146, + "15855": 12147, + "15856": 12148, + "15857": 12149, + "15858": 12150, + "15859": 12151, + "15860": 12152, + "15861": 12153, + "15862": 12154, + "15863": 12155, + "15864": 12156, + "15865": 12157, + "15866": 12158, + "15867": 12159, + "15868": 12160, + "15869": 12161, + "15870": 12162, + "15871": 12163, + "15872": 12164, + "15873": 12165, + "15874": 12166, + "15875": 12167, + "15876": 12168, + "15877": 12169, + "15878": 12170, + "15879": 12171, + "15880": 12172, + "15881": 12173, + "15882": 12174, + "15883": 12175, + "15884": 12176, + "15885": 12177, + "15886": 12178, + "15887": 12179, + "15888": 12180, + "15889": 12181, + "15890": 12182, + "15891": 12183, + "15892": 5199, + "15893": 5200, + "15894": 5201, + "15895": 5202, + "15896": 5203, + "15897": 5204, + "15898": 12321, + "15899": 12320, + "15900": 12319, + "15901": 12244, + "15902": 12324, + "15903": 12324, + "15904": 12324, + "15905": 12324, + "15906": 12324, + "15907": 12324, + "15908": 12324, + "15909": 12324, + "15910": 12324, + "15911": 12324, + "15912": 12323, + "15913": 12323, + "15914": 12323, + "15915": 12323, + "15916": 12323, + "15917": 12323, + "15918": 12323, + "15919": 12323, + "15920": 12323, + "15921": 12323, + "15922": 12322, + "15923": 12322, + "15924": 12322, + "15925": 12322, + "15926": 12322, + "15927": 12322, + "15928": 12322, + "15929": 12322, + "15930": 12322, + "15931": 12322, + "15932": 12184, + "15933": 12185, + "15934": 12186, + "15935": 12187, + "15936": 12188, + "15937": 12189, + "15938": 12190, + "15939": 12191, + "15940": 12192, + "15941": 12193, + "15942": 12194, + "15943": 12195, + "15944": 12196, + "15945": 12197, + "15946": 12198, + "15947": 12209, + "15948": 12199, + "15949": 12200, + "15950": 12208, + "15951": 12201, + "15952": 12202, + "15953": 12207, + "15954": 12203, + "15955": 12206, + "15956": 12204, + "15957": 12205, + "15958": 12212, + "15959": 12213, + "15960": 12210, + "15961": 12211, + "15962": 12214, + "15963": 12215, + "15964": 12216, + "15965": 12217, + "15966": 12218, + "15967": 12219, + "15968": 12220, + "15969": 12221, + "15970": 12222, + "15971": 12223, + "15972": 12224, + "15973": 12225, + "15974": 12229, + "15975": 12230, + "15976": 12226, + "15977": 12227, + "15978": 12232, + "15979": 12231, + "15980": 12233, + "15981": 12228, + "15982": 12234, + "15983": 12235, + "15984": 108, + "15985": 12406, + "15987": 108, + "15988": 11296, + "15989": 7142, + "15990": 12258, + "15991": 12261, + "15992": 12262, + "15993": 12268, + "15994": 5199, + "15995": 5204, + "15996": 2566, + "15997": 2566, + "15998": 2566, + "15999": 2566, + "16000": 2566, + "16001": 2566, + "16002": 2566, + "16003": 2566, + "16004": 2566, + "16005": 2566, + "16006": 10309, + "16007": 10309, + "16008": 10309, + "16009": 10309, + "16010": 10309, + "16011": 10309, + "16012": 10309, + "16013": 10309, + "16014": 10309, + "16015": 10309, + "16016": 12031, + "16017": 12270, + "16018": 12271, + "16019": 12272, + "16020": 12273, + "16021": 12274, + "16022": 12275, + "16023": 108, + "16024": 750, + "16025": 750, + "16026": 750, + "16027": 750, + "16028": 12276, + "16029": 12276, + "16030": 12277, + "16031": 12245, + "16033": 943, + "16034": 12308, + "16035": 12309, + "16037": 12308, + "16038": 12072, + "16039": 12311, + "16040": 12521, + "16042": 12334, + "16043": 12335, + "16044": 108, + "16045": 12393, + "16046": 12393, + "16047": 12281, + "16048": 12282, + "16049": 12283, + "16050": 12284, + "16051": 12285, + "16052": 12286, + "16053": 12287, + "16054": 12288, + "16055": 12289, + "16056": 12290, + "16057": 12291, + "16058": 12298, + "16059": 12540, + "16060": 12300, + "16062": 12302, + "16063": 12303, + "16064": 12304, + "16065": 12305, + "16066": 12306, + "16067": 12307, + "16068": 12314, + "16069": 12315, + "16070": 12338, + "16071": 12339, + "16072": 12340, + "16073": 12341, + "16074": 12342, + "16075": 12343, + "16076": 12344, + "16077": 12345, + "16078": 12346, + "16079": 12347, + "16080": 12348, + "16081": 12349, + "16082": 12350, + "16083": 12318, + "16084": 11297, + "16085": 12369, + "16086": 12372, + "16087": 12369, + "16088": 12370, + "16089": 12371, + "16090": 12372, + "16091": 12325, + "16092": 12326, + "16093": 12333, + "16094": 12328, + "16095": 12329, + "16096": 12330, + "16097": 12331, + "16098": 12332, + "16099": 12327, + "16100": 12311, + "16101": 12308, + "16102": 108, + "16103": 108, + "16104": 108, + "16105": 108, + "16106": 12337, + "16107": 12336, + "16108": 12388, + "16109": 12389, + "16110": 12390, + "16111": 12390, + "16113": 12391, + "16114": 12388, + "16115": 12389, + "16116": 12389, + "16117": 12390, + "16118": 12390, + "16119": 12390, + "16120": 12390, + "16121": 12391, + "16122": 12394, + "16123": 12395, + "16124": 12396, + "16125": 12397, + "16126": 12398, + "16127": 12399, + "16128": 12400, + "16129": 12401, + "16130": 12402, + "16131": 12403, + "16132": 12404, + "16133": 12405, + "16134": 12406, + "16135": 12407, + "16136": 12408, + "16137": 12409, + "16138": 12410, + "16139": 12411, + "16140": 12412, + "16141": 12413, + "16142": 12414, + "16143": 12415, + "16144": 12416, + "16145": 12417, + "16146": 12418, + "16147": 12419, + "16148": 12420, + "16149": 12421, + "16150": 12422, + "16151": 12423, + "16152": 108, + "16153": 12354, + "16154": 12355, + "16155": 12426, + "16156": 108, + "16157": 12354, + "16158": 12355, + "16159": 12426, + "16160": 12427, + "16161": 108, + "16162": 12356, + "16163": 12377, + "16164": 12378, + "16165": 12379, + "16166": 12380, + "16167": 12378, + "16168": 12377, + "16169": 12377, + "16170": 12377, + "16171": 12377, + "16172": 12378, + "16173": 12379, + "16174": 12380, + "16175": 12381, + "16176": 12377, + "16177": 12377, + "16178": 12377, + "16179": 12377, + "16180": 12377, + "16181": 12382, + "16182": 12383, + "16183": 12384, + "16184": 12385, + "16185": 12386, + "16186": 12387, + "16187": 12392, + "16188": 312, + "16189": 12457, + "16190": 12458, + "16191": 312, + "16192": 12428, + "16193": 12429, + "16194": 12430, + "16195": 12431, + "16196": 12432, + "16197": 12433, + "16198": 12434, + "16199": 12435, + "16200": 12428, + "16201": 12429, + "16202": 12430, + "16203": 12434, + "16204": 12435, + "16205": 12428, + "16206": 12429, + "16207": 12430, + "16208": 12434, + "16209": 12435, + "16210": 12456, + "16211": 108, + "16212": 12365, + "16213": 12367, + "16214": 12368, + "16215": 12365, + "16216": 12367, + "16217": 12368, + "16218": 12366, + "16219": 108, + "16220": 12373, + "16221": 12374, + "16222": 12339, + "16223": 12339, + "16224": 12375, + "16225": 12373, + "16226": 12375, + "16227": 12373, + "16228": 12375, + "16229": 108, + "16230": 954, + "16231": 954, + "16232": 12466, + "16233": 5569, + "16234": 5570, + "16235": 5571, + "16236": 5572, + "16238": 12463, + "16239": 5970, + "16240": 5239, + "16241": 4130, + "16242": 4392, + "16243": 4130, + "16244": 4392, + "16245": 4130, + "16246": 9350, + "16247": 12464, + "16248": 6148, + "16249": 12465, + "16250": 12466, + "16251": 12467, + "16252": 12468, + "16253": 12469, + "16254": 12470, + "16255": 5964, + "16256": 4133, + "16257": 12357, + "16258": 12359, + "16259": 12359, + "16260": 12360, + "16261": 12361, + "16262": 12362, + "16263": 12363, + "16264": 12364, + "16265": 12357, + "16266": 12358, + "16267": 12360, + "16268": 12361, + "16269": 12364, + "16270": 12357, + "16271": 12358, + "16272": 12360, + "16273": 12361, + "16274": 12364, + "16275": 12515, + "16276": 12422, + "16277": 12417, + "16278": 12399, + "16279": 12418, + "16280": 12410, + "16281": 12424, + "16282": 12422, + "16283": 12417, + "16284": 12399, + "16285": 12418, + "16286": 12410, + "16287": 12424, + "16288": 12425, + "16289": 12400, + "16290": 12425, + "16291": 12400, + "16292": 108, + "16293": 12471, + "16294": 12473, + "16295": 12471, + "16296": 12474, + "16297": 12475, + "16298": 12476, + "16299": 12477, + "16300": 12472, + "16301": 12382, + "16302": 12570, + "16303": 12549, + "16304": 12550, + "16305": 12551, + "16306": 12573, + "16307": 12357, + "16308": 12574, + "16309": 12575, + "16310": 12578, + "16311": 12577, + "16312": 12578, + "16313": 12579, + "16314": 12580, + "16315": 12583, + "16316": 12581, + "16317": 12662, + "16318": 12582, + "16319": 12436, + "16320": 12437, + "16321": 12438, + "16322": 12439, + "16323": 12440, + "16324": 12441, + "16325": 12442, + "16326": 12443, + "16327": 12444, + "16328": 12445, + "16329": 12446, + "16330": 12447, + "16331": 12448, + "16332": 12455, + "16333": 12449, + "16334": 12450, + "16335": 12435, + "16336": 108, + "16337": 12485, + "16338": 108, + "16339": 108, + "16340": 12461, + "16341": 12462, + "16342": 12636, + "16343": 12637, + "16344": 12638, + "16345": 108, + "16346": 108, + "16347": 108, + "16348": 10902, + "16349": 10903, + "16350": 108, + "16351": 108, + "16352": 108, + "16353": 108, + "16354": 12500, + "16355": 12501, + "16356": 12564, + "16357": 12565, + "16358": 12565, + "16359": 12530, + "16360": 12531, + "16361": 12532, + "16362": 12533, + "16363": 12534, + "16364": 12535, + "16365": 12536, + "16366": 12594, + "16367": 12598, + "16368": 12537, + "16369": 12604, + "16370": 12538, + "16371": 12539, + "16372": 12540, + "16373": 12541, + "16374": 12542, + "16375": 12543, + "16376": 12544, + "16377": 12545, + "16378": 12546, + "16379": 12547, + "16380": 12548, + "16381": 12549, + "16382": 12550, + "16383": 12551, + "16384": 12552, + "16385": 12553, + "16386": 12554, + "16387": 12555, + "16388": 12556, + "16389": 12557, + "16390": 12558, + "16391": 12559, + "16392": 12560, + "16393": 12671, + "16394": 12672, + "16395": 12561, + "16396": 12562, + "16397": 12563, + "16398": 750, + "16400": 12478, + "16401": 12479, + "16402": 11263, + "16403": 12481, + "16404": 12482, + "16405": 9363, + "16406": 4846, + "16407": 12483, + "16408": 108, + "16409": 12590, + "16410": 12591, + "16411": 12592, + "16412": 12593, + "16413": 12594, + "16414": 12595, + "16415": 12596, + "16416": 4856, + "16417": 12598, + "16418": 12484, + "16419": 12485, + "16420": 11299, + "16421": 12504, + "16422": 12502, + "16423": 12503, + "16424": 108, + "16425": 12505, + "16426": 12487, + "16427": 12488, + "16428": 12489, + "16429": 12487, + "16430": 12488, + "16431": 12490, + "16432": 12491, + "16433": 12492, + "16434": 12493, + "16435": 12494, + "16436": 12495, + "16437": 12496, + "16438": 12497, + "16439": 12499, + "16440": 12498, + "16441": 12639, + "16442": 12563, + "16443": 12640, + "16444": 12641, + "16445": 12642, + "16446": 12639, + "16447": 12643, + "16448": 12644, + "16449": 12642, + "16450": 12584, + "16451": 12585, + "16452": 12599, + "16453": 12600, + "16454": 12601, + "16455": 12602, + "16456": 12603, + "16457": 11011, + "16458": 12568, + "16459": 12598, + "16460": 11298, + "16461": 11298, + "16462": 12586, + "16463": 12566, + "16464": 12506, + "16465": 12507, + "16466": 12508, + "16467": 12509, + "16468": 12510, + "16469": 12511, + "16470": 12512, + "16471": 12513, + "16472": 12514, + "16473": 12594, + "16474": 12516, + "16475": 12517, + "16476": 12518, + "16477": 12506, + "16478": 12507, + "16479": 12508, + "16480": 12511, + "16481": 12520, + "16482": 12517, + "16483": 12518, + "16484": 12519, + "16485": 12506, + "16486": 12507, + "16487": 12508, + "16488": 12511, + "16489": 12520, + "16490": 12517, + "16491": 12518, + "16492": 12519, + "16493": 11300, + "16494": 12486, + "16495": 11300, + "16496": 12506, + "16497": 3632, + "16498": 3633, + "16499": 3634, + "16500": 3635, + "16501": 3636, + "16502": 3637, + "16503": 3638, + "16504": 3639, + "16505": 3640, + "16506": 3641, + "16507": 3642, + "16508": 3643, + "16509": 3644, + "16510": 3645, + "16511": 4386, + "16512": 4387, + "16513": 3645, + "16514": 12670, + "16516": 108, + "16517": 12480, + "16518": 11301, + "16519": 12633, + "16520": 12637, + "16522": 108, + "16523": 11322, + "16524": 12658, + "16525": 0, + "16526": 0, + "16527": 108, + "16528": 108, + "16529": 12605, + "16530": 11084, + "16531": 12607, + "16532": 12608, + "16533": 12609, + "16534": 12531, + "16535": 12610, + "16536": 12540, + "16537": 12583, + "16538": 12539, + "16539": 12351, + "16540": 12605, + "16541": 12606, + "16542": 12607, + "16543": 12608, + "16544": 12609, + "16545": 12539, + "16546": 12352, + "16547": 12605, + "16548": 12606, + "16549": 12607, + "16550": 12608, + "16551": 12609, + "16552": 12539, + "16553": 108, + "16554": 108, + "16555": 12587, + "16556": 12588, + "16557": 12586, + "16558": 12587, + "16559": 12588, + "16561": 12487, + "16562": 108, + "16563": 12522, + "16564": 12523, + "16565": 108, + "16567": 12524, + "16568": 12525, + "16569": 12526, + "16570": 12527, + "16571": 12673, + "16572": 12673, + "16573": 108, + "16574": 12528, + "16575": 12529, + "16576": 12635, + "16577": 5964, + "16578": 6148, + "16579": 8378, + "16580": 4130, + "16581": 9350, + "16582": 108, + "16583": 12837, + "16584": 12632, + "16585": 12537, + "16586": 12536, + "16587": 12631, + "16588": 12541, + "16589": 12534, + "16590": 6116, + "16591": 12712, + "16592": 12560, + "16593": 12561, + "16594": 12632, + "16595": 12537, + "16596": 12536, + "16597": 12631, + "16598": 12541, + "16599": 12534, + "16602": 12560, + "16603": 12561, + "16604": 12639, + "16605": 12643, + "16606": 12644, + "16607": 12642, + "16608": 108, + "16609": 12481, + "16610": 12645, + "16611": 12632, + "16612": 12611, + "16613": 12612, + "16614": 12613, + "16615": 12614, + "16616": 12615, + "16617": 12616, + "16618": 12617, + "16619": 12618, + "16620": 12619, + "16621": 12620, + "16622": 12621, + "16623": 12622, + "16624": 12623, + "16625": 12624, + "16626": 12625, + "16627": 12626, + "16628": 12627, + "16629": 12628, + "16630": 12629, + "16631": 12630, + "16632": 12353, + "16633": 2566, + "16634": 12646, + "16635": 12647, + "16636": 12648, + "16637": 12649, + "16638": 12650, + "16639": 12651, + "16640": 12652, + "16641": 12653, + "16642": 2, + "16643": 12655, + "16644": 12656, + "16645": 12657, + "16646": 12658, + "16647": 12659, + "16648": 12660, + "16649": 12661, + "16650": 12580, + "16652": 12651, + "16654": 12668, + "16655": 12667, + "16656": 108, + "16657": 108, + "16658": 12666, + "16659": 12665, + "16660": 12590, + "16661": 12854, + "16662": 12855, + "16663": 12856, + "16664": 12854, + "16665": 12855, + "16666": 12856, + "16667": 12857, + "16669": 12750, + "16670": 12752, + "16671": 12670, + "16672": 12671, + "16673": 12820, + "16674": 12810, + "16675": 12811, + "16676": 12812, + "16677": 12813, + "16678": 12814, + "16679": 12815, + "16680": 12817, + "16681": 12816, + "16682": 12818, + "16683": 12839, + "16684": 12836, + "16685": 12739, + "16686": 108, + "16687": 12821, + "16688": 12822, + "16689": 12824, + "16690": 12823, + "16691": 12819, + "16692": 12528, + "16693": 12529, + "16694": 12574, + "16695": 108, + "16696": 13289, + "16697": 13290, + "16698": 13291, + "16699": 13292, + "16700": 13293, + "16701": 13294, + "16702": 13295, + "16703": 13296, + "16704": 13297, + "16705": 13532, + "16706": 13405, + "16707": 13298, + "16708": 12487, + "16709": 13299, + "16710": 12487, + "16711": 13300, + "16712": 13301, + "16713": 13301, + "16714": 12866, + "16715": 12867, + "16716": 12868, + "16717": 12869, + "16718": 12870, + "16719": 12871, + "16720": 12872, + "16721": 12873, + "16722": 12874, + "16723": 12875, + "16724": 12876, + "16725": 12877, + "16726": 108, + "16727": 108, + "16728": 12880, + "16729": 12699, + "16730": 12700, + "16731": 12701, + "16732": 12702, + "16733": 12703, + "16734": 12704, + "16735": 12705, + "16736": 12706, + "16737": 11536, + "16738": 12708, + "16739": 11518, + "16740": 12709, + "16741": 12711, + "16742": 12713, + "16743": 12712, + "16744": 12714, + "16745": 12714, + "16746": 12864, + "16747": 12865, + "16748": 12715, + "16749": 13156, + "16750": 13157, + "16751": 13158, + "16752": 12693, + "16753": 12694, + "16754": 12694, + "16755": 12844, + "16756": 12842, + "16757": 12843, + "16758": 12675, + "16759": 12676, + "16760": 108, + "16761": 12854, + "16762": 12854, + "16763": 12854, + "16764": 12854, + "16765": 12695, + "16766": 12840, + "16767": 12697, + "16768": 12698, + "16769": 12857, + "16770": 12857, + "16771": 13073, + "16772": 12888, + "16773": 12741, + "16774": 12834, + "16775": 12835, + "16776": 108, + "16777": 12837, + "16778": 108, + "16779": 108, + "16780": 108, + "16781": 12839, + "16782": 12840, + "16783": 12841, + "16784": 12723, + "16785": 12724, + "16786": 12725, + "16787": 12726, + "16788": 12727, + "16789": 12716, + "16790": 12717, + "16791": 12718, + "16792": 12719, + "16793": 12720, + "16794": 12720, + "16795": 12720, + "16796": 12721, + "16797": 13390, + "16798": 108, + "16799": 12720, + "16800": 12720, + "16801": 12720, + "16802": 12766, + "16803": 12767, + "16804": 12768, + "16805": 12726, + "16806": 12769, + "16807": 12770, + "16808": 12772, + "16809": 12771, + "16810": 12773, + "16811": 12774, + "16812": 12775, + "16813": 12717, + "16814": 12718, + "16815": 12719, + "16816": 12720, + "16817": 12720, + "16818": 12720, + "16819": 12803, + "16820": 12804, + "16821": 12805, + "16822": 12806, + "16823": 12807, + "16824": 12808, + "16825": 12711, + "16826": 12752, + "16827": 13075, + "16828": 12751, + "16829": 13076, + "16830": 12853, + "16831": 12717, + "16832": 13029, + "16833": 13029, + "16834": 13029, + "16835": 12834, + "16836": 13029, + "16837": 12487, + "16838": 108, + "16839": 12728, + "16840": 108, + "16841": 541, + "16842": 12760, + "16843": 12761, + "16844": 108, + "16845": 13667, + "16846": 12729, + "16847": 12730, + "16848": 12731, + "16849": 12732, + "16850": 12762, + "16851": 12755, + "16852": 12756, + "16853": 108, + "16854": 12776, + "16855": 13048, + "16856": 12778, + "16857": 12779, + "16858": 12780, + "16859": 12781, + "16860": 12782, + "16861": 12830, + "16862": 12887, + "16863": 12733, + "16864": 12710, + "16865": 12864, + "16866": 12895, + "16867": 12837, + "16868": 13015, + "16869": 13021, + "16870": 13022, + "16871": 13023, + "16872": 13024, + "16873": 13025, + "16874": 10013, + "16875": 4130, + "16876": 4130, + "16877": 5239, + "16878": 5239, + "16879": 713, + "16880": 1492, + "16881": 8378, + "16882": 8378, + "16883": 9363, + "16884": 9363, + "16885": 9363, + "16886": 12487, + "16887": 12487, + "16888": 4846, + "16889": 12740, + "16890": 12739, + "16891": 11287, + "16892": 12692, + "16893": 12845, + "16894": 12846, + "16895": 12847, + "16896": 12848, + "16897": 12849, + "16898": 12850, + "16899": 12851, + "16900": 12852, + "16901": 13074, + "16902": 12734, + "16903": 13552, + "16904": 13553, + "16905": 12487, + "16906": 12487, + "16907": 12861, + "16908": 713, + "16909": 1492, + "16910": 4130, + "16911": 5239, + "16912": 4846, + "16913": 12677, + "16914": 12679, + "16915": 12679, + "16916": 12680, + "16917": 12677, + "16918": 12681, + "16919": 12682, + "16920": 12683, + "16921": 12684, + "16922": 12684, + "16923": 12684, + "16924": 108, + "16925": 108, + "16926": 13159, + "16927": 12763, + "16928": 12764, + "16929": 12765, + "16930": 12816, + "16931": 12858, + "16932": 108, + "16933": 12733, + "16934": 13181, + "16935": 13182, + "16936": 12737, + "16937": 12738, + "16938": 267, + "16939": 267, + "16940": 12998, + "16941": 12999, + "16942": 13000, + "16943": 4198, + "16944": 13065, + "16945": 13065, + "16946": 12753, + "16947": 12754, + "16948": 12889, + "16949": 13182, + "16950": 12913, + "16951": 12757, + "16952": 12758, + "16953": 12759, + "16954": 13106, + "16955": 11351, + "16956": 12877, + "16957": 12877, + "16958": 12877, + "16959": 12923, + "16960": 13112, + "16961": 12784, + "16962": 12785, + "16963": 12786, + "16964": 12787, + "16965": 12788, + "16966": 12789, + "16967": 12790, + "16968": 13084, + "16969": 12791, + "16970": 12793, + "16971": 12794, + "16972": 12911, + "16973": 12796, + "16974": 12797, + "16975": 12798, + "16976": 12799, + "16977": 12800, + "16978": 13173, + "16979": 12801, + "16980": 12802, + "16981": 13563, + "16982": 12742, + "16983": 12743, + "16984": 12744, + "16985": 12745, + "16986": 12746, + "16987": 12747, + "16988": 12748, + "16989": 12749, + "16990": 13062, + "16991": 12955, + "16992": 12862, + "16993": 11379, + "16994": 108, + "16995": 13057, + "16996": 12803, + "16997": 12959, + "16998": 10792, + "16999": 13325, + "17000": 12963, + "17001": 12905, + "17002": 12906, + "17003": 12890, + "17004": 12891, + "17005": 12892, + "17006": 12893, + "17007": 12896, + "17008": 12897, + "17009": 12898, + "17010": 12899, + "17011": 12900, + "17012": 12901, + "17013": 12902, + "17014": 12903, + "17015": 12904, + "17016": 12905, + "17017": 12906, + "17018": 12907, + "17019": 12908, + "17020": 12909, + "17021": 12910, + "17022": 12911, + "17023": 12912, + "17024": 12913, + "17025": 12914, + "17026": 12915, + "17027": 12916, + "17028": 12917, + "17029": 12918, + "17030": 12919, + "17031": 12920, + "17032": 12921, + "17033": 12922, + "17034": 13176, + "17035": 13177, + "17036": 13178, + "17037": 4292, + "17038": 13179, + "17039": 13078, + "17040": 13030, + "17041": 13031, + "17042": 13032, + "17043": 13033, + "17044": 13034, + "17045": 13034, + "17046": 13035, + "17047": 13036, + "17048": 13037, + "17049": 13038, + "17050": 13039, + "17051": 13040, + "17052": 13285, + "17053": 13071, + "17054": 13287, + "17055": 12831, + "17056": 12825, + "17057": 12826, + "17058": 12827, + "17059": 12828, + "17060": 12831, + "17061": 12833, + "17062": 12832, + "17063": 12829, + "17064": 12830, + "17065": 12881, + "17066": 12883, + "17067": 12883, + "17068": 12886, + "17069": 12886, + "17070": 11458, + "17071": 12960, + "17072": 108, + "17073": 108, + "17074": 108, + "17075": 108, + "17076": 12882, + "17077": 12882, + "17078": 12884, + "17079": 12884, + "17080": 12884, + "17081": 108, + "17082": 12895, + "17083": 12987, + "17084": 12988, + "17085": 108, + "17086": 12885, + "17087": 13077, + "17088": 13077, + "17089": 13303, + "17090": 13356, + "17091": 13357, + "17092": 13359, + "17093": 108, + "17094": 13676, + "17095": 12984, + "17096": 13359, + "17097": 108, + "17098": 13446, + "17099": 13358, + "17100": 13190, + "17101": 13191, + "17102": 13192, + "17103": 13193, + "17104": 13194, + "17105": 13195, + "17106": 13196, + "17107": 13197, + "17108": 13198, + "17109": 13199, + "17110": 13200, + "17111": 13201, + "17112": 13001, + "17113": 13203, + "17114": 13204, + "17115": 13205, + "17116": 13206, + "17117": 13207, + "17118": 13208, + "17119": 13209, + "17120": 13210, + "17121": 13211, + "17122": 13212, + "17123": 13213, + "17124": 13214, + "17125": 13215, + "17126": 13216, + "17127": 13217, + "17128": 13218, + "17129": 13219, + "17130": 13220, + "17131": 13221, + "17132": 13222, + "17133": 13223, + "17134": 13224, + "17135": 13225, + "17136": 13226, + "17137": 13227, + "17138": 13228, + "17139": 13229, + "17140": 13029, + "17141": 13231, + "17142": 13232, + "17143": 13233, + "17144": 13234, + "17145": 13235, + "17146": 13236, + "17147": 13237, + "17148": 13238, + "17149": 13239, + "17150": 13039, + "17151": 13040, + "17152": 13041, + "17153": 267, + "17154": 13043, + "17155": 13245, + "17156": 13246, + "17157": 12989, + "17158": 13248, + "17159": 13048, + "17160": 12742, + "17161": 12742, + "17162": 13116, + "17163": 968, + "17164": 1747, + "17165": 4385, + "17166": 5494, + "17167": 5101, + "17168": 13258, + "17169": 13058, + "17170": 13260, + "17171": 13261, + "17172": 13262, + "17173": 13406, + "17174": 13264, + "17175": 13265, + "17176": 13266, + "17177": 13267, + "17178": 13268, + "17179": 13269, + "17180": 13270, + "17181": 13271, + "17182": 13272, + "17183": 13273, + "17184": 13274, + "17185": 13247, + "17186": 13752, + "17187": 363, + "17188": 13278, + "17189": 13279, + "17190": 13280, + "17191": 12992, + "17192": 12993, + "17193": 12686, + "17194": 13520, + "17195": 108, + "17196": 13072, + "17197": 13397, + "17198": 13398, + "17199": 13363, + "17200": 13364, + "17201": 13365, + "17202": 13366, + "17203": 13367, + "17204": 13368, + "17205": 13326, + "17206": 13327, + "17207": 13160, + "17208": 12487, + "17209": 9869, + "17210": 9873, + "17211": 4846, + "17212": 13161, + "17213": 13162, + "17214": 13165, + "17215": 13166, + "17216": 13167, + "17217": 13164, + "17218": 13168, + "17219": 13161, + "17220": 13162, + "17221": 13162, + "17222": 13163, + "17223": 13164, + "17224": 13169, + "17225": 13170, + "17226": 13171, + "17227": 12943, + "17228": 12930, + "17229": 12944, + "17230": 12931, + "17231": 12939, + "17232": 12932, + "17233": 12933, + "17234": 12934, + "17235": 12935, + "17236": 12936, + "17237": 12937, + "17238": 12940, + "17239": 12941, + "17240": 12942, + "17241": 12945, + "17242": 12946, + "17243": 12947, + "17244": 12948, + "17245": 12949, + "17246": 12950, + "17247": 12951, + "17248": 12952, + "17249": 12938, + "17250": 12953, + "17251": 12964, + "17252": 12954, + "17253": 12965, + "17254": 12966, + "17255": 12956, + "17256": 12957, + "17257": 12958, + "17258": 12959, + "17259": 12960, + "17260": 12961, + "17261": 12962, + "17262": 12963, + "17263": 12967, + "17264": 12968, + "17265": 12969, + "17266": 12970, + "17267": 12971, + "17268": 12955, + "17269": 12972, + "17270": 12973, + "17271": 12974, + "17272": 12989, + "17273": 12975, + "17274": 12990, + "17275": 12991, + "17276": 12992, + "17277": 12976, + "17278": 12993, + "17279": 12994, + "17280": 12995, + "17281": 12996, + "17282": 12977, + "17283": 12978, + "17284": 12997, + "17285": 12979, + "17286": 12985, + "17287": 12986, + "17288": 12987, + "17289": 12988, + "17290": 12860, + "17291": 12858, + "17292": 12859, + "17293": 12860, + "17294": 12858, + "17295": 12859, + "17296": 13369, + "17297": 13370, + "17298": 13371, + "17299": 13372, + "17300": 13373, + "17301": 13435, + "17302": 13436, + "17303": 13004, + "17304": 13374, + "17305": 13375, + "17306": 13376, + "17307": 13377, + "17308": 13378, + "17309": 13379, + "17310": 13380, + "17311": 13381, + "17312": 13382, + "17313": 13383, + "17314": 12700, + "17315": 108, + "17316": 13172, + "17317": 13174, + "17318": 13384, + "17319": 13385, + "17320": 12886, + "17321": 12836, + "17322": 13025, + "17323": 13026, + "17324": 13027, + "17325": 13027, + "17326": 13042, + "17327": 13043, + "17328": 108, + "17329": 13161, + "17330": 13162, + "17331": 13165, + "17332": 13166, + "17333": 13035, + "17334": 12766, + "17335": 12768, + "17336": 12769, + "17337": 12774, + "17338": 12775, + "17339": 13386, + "17340": 13387, + "17341": 108, + "17342": 108, + "17343": 108, + "17344": 13388, + "17345": 13389, + "17346": 13390, + "17347": 13391, + "17348": 13392, + "17349": 13393, + "17350": 13394, + "17351": 12923, + "17352": 12924, + "17353": 13057, + "17354": 13043, + "17355": 12925, + "17356": 12925, + "17357": 13061, + "17358": 12925, + "17359": 12925, + "17360": 12925, + "17361": 12928, + "17362": 12929, + "17363": 13065, + "17364": 12780, + "17365": 12834, + "17366": 12837, + "17367": 12894, + "17368": 108, + "17369": 12840, + "17370": 13074, + "17371": 13400, + "17372": 13401, + "17373": 13399, + "17374": 12838, + "17375": 12838, + "17376": 12926, + "17377": 12927, + "17378": 12926, + "17379": 13083, + "17380": 12927, + "17381": 12834, + "17382": 12980, + "17383": 12981, + "17384": 12982, + "17385": 12983, + "17386": 12984, + "17387": 13087, + "17388": 13088, + "17389": 13091, + "17390": 13094, + "17391": 13095, + "17392": 108, + "17393": 13093, + "17394": 13094, + "17395": 13095, + "17396": 13056, + "17397": 13097, + "17398": 13130, + "17399": 13288, + "17400": 13286, + "17401": 13285, + "17402": 13287, + "17403": 13288, + "17404": 108, + "17405": 13183, + "17406": 13184, + "17407": 13185, + "17408": 13186, + "17409": 13187, + "17410": 13188, + "17411": 12689, + "17412": 12689, + "17413": 12689, + "17414": 12689, + "17415": 12999, + "17416": 13000, + "17417": 13001, + "17418": 13002, + "17419": 13003, + "17420": 13004, + "17421": 13005, + "17422": 13006, + "17423": 13007, + "17424": 13008, + "17425": 13009, + "17426": 13010, + "17427": 13011, + "17428": 13012, + "17429": 13013, + "17430": 13014, + "17431": 13015, + "17432": 13016, + "17433": 13017, + "17434": 13018, + "17435": 13019, + "17436": 13020, + "17437": 13021, + "17438": 13022, + "17439": 13023, + "17440": 13024, + "17441": 13025, + "17442": 13026, + "17443": 13142, + "17444": 13143, + "17445": 13328, + "17446": 13329, + "17447": 13330, + "17448": 13148, + "17449": 13333, + "17450": 13332, + "17451": 13151, + "17452": 13152, + "17453": 13336, + "17454": 13337, + "17455": 13339, + "17456": 13338, + "17457": 13340, + "17458": 13341, + "17459": 13347, + "17460": 13342, + "17461": 13165, + "17462": 13162, + "17463": 13345, + "17464": 13346, + "17465": 13079, + "17466": 13080, + "17467": 13081, + "17468": 13082, + "17469": 13083, + "17470": 13084, + "17471": 13085, + "17472": 13086, + "17473": 13087, + "17474": 13088, + "17475": 13089, + "17476": 13090, + "17477": 13091, + "17478": 13092, + "17479": 13093, + "17480": 13094, + "17481": 13095, + "17482": 13096, + "17483": 13097, + "17484": 13098, + "17485": 13101, + "17486": 13102, + "17487": 13103, + "17488": 13104, + "17489": 13105, + "17490": 13106, + "17491": 13107, + "17492": 12925, + "17493": 13109, + "17494": 13110, + "17495": 13111, + "17496": 13112, + "17497": 13113, + "17498": 13114, + "17499": 13115, + "17500": 13116, + "17501": 13117, + "17502": 13118, + "17503": 13119, + "17504": 13120, + "17505": 13121, + "17506": 13122, + "17507": 13123, + "17508": 13124, + "17509": 13125, + "17510": 13126, + "17511": 13127, + "17512": 13128, + "17513": 13129, + "17514": 13130, + "17515": 13131, + "17516": 13132, + "17517": 13133, + "17518": 13134, + "17519": 13135, + "17520": 13136, + "17521": 13137, + "17522": 13138, + "17523": 13139, + "17524": 13140, + "17525": 13099, + "17526": 13100, + "17527": 13029, + "17528": 12777, + "17529": 12778, + "17530": 12779, + "17531": 12780, + "17532": 12782, + "17533": 12997, + "17534": 12997, + "17535": 13043, + "17536": 13045, + "17537": 13046, + "17538": 13047, + "17539": 13047, + "17540": 12993, + "17541": 13048, + "17542": 13027, + "17543": 13028, + "17544": 13591, + "17545": 13067, + "17546": 13287, + "17547": 13179, + "17548": 12795, + "17549": 12800, + "17550": 12867, + "17551": 12875, + "17552": 12876, + "17553": 12877, + "17554": 12856, + "17555": 12857, + "17556": 13172, + "17557": 13144, + "17558": 13145, + "17559": 13146, + "17560": 13147, + "17561": 13148, + "17562": 13149, + "17563": 13150, + "17564": 13151, + "17565": 13152, + "17566": 13153, + "17567": 13154, + "17568": 13155, + "17569": 13153, + "17570": 13409, + "17571": 13410, + "17572": 13411, + "17573": 13412, + "17574": 13413, + "17575": 13438, + "17576": 13415, + "17577": 13416, + "17578": 13417, + "17579": 13419, + "17580": 13421, + "17581": 13422, + "17582": 13423, + "17583": 13425, + "17584": 13427, + "17585": 13428, + "17586": 13429, + "17587": 13430, + "17588": 13432, + "17589": 13433, + "17590": 12850, + "17591": 13189, + "17592": 12928, + "17593": 13409, + "17594": 13414, + "17595": 13439, + "17596": 13440, + "17597": 13418, + "17598": 13420, + "17599": 13420, + "17600": 13424, + "17601": 13441, + "17602": 12851, + "17603": 13431, + "17604": 108, + "17605": 13460, + "17606": 13461, + "17607": 13462, + "17608": 13048, + "17609": 13461, + "17610": 13463, + "17611": 13464, + "17612": 12745, + "17613": 12746, + "17614": 12745, + "17615": 12746, + "17616": 12745, + "17617": 5832, + "17618": 5832, + "17619": 5833, + "17620": 13465, + "17621": 12925, + "17622": 12925, + "17623": 12925, + "17624": 13466, + "17625": 13467, + "17626": 13468, + "17627": 13469, + "17628": 13470, + "17629": 13471, + "17630": 13471, + "17631": 13471, + "17632": 13472, + "17633": 13472, + "17634": 13472, + "17635": 13219, + "17636": 13121, + "17637": 13472, + "17638": 13472, + "17639": 13472, + "17640": 13473, + "17641": 13474, + "17642": 13475, + "17643": 13476, + "17644": 13476, + "17645": 13477, + "17646": 13478, + "17647": 13479, + "17648": 13480, + "17649": 13481, + "17650": 13482, + "17651": 13483, + "17652": 13484, + "17653": 13564, + "17654": 13486, + "17655": 13487, + "17656": 13488, + "17657": 13489, + "17658": 13489, + "17659": 13490, + "17660": 13491, + "17661": 13492, + "17662": 13447, + "17663": 13493, + "17664": 13494, + "17665": 13494, + "17666": 13495, + "17667": 13363, + "17668": 13496, + "17669": 13496, + "17670": 13496, + "17671": 13497, + "17672": 13498, + "17673": 13499, + "17674": 13499, + "17675": 13500, + "17676": 13501, + "17677": 13502, + "17678": 13503, + "17679": 13504, + "17680": 117, + "17681": 13111, + "17682": 117, + "17683": 13111, + "17684": 13505, + "17685": 13506, + "17686": 13507, + "17687": 13508, + "17688": 13509, + "17689": 13510, + "17690": 13511, + "17691": 13512, + "17692": 13012, + "17693": 13513, + "17694": 13514, + "17695": 13134, + "17696": 13095, + "17697": 13515, + "17698": 13516, + "17699": 13517, + "17700": 13517, + "17701": 13111, + "17702": 13518, + "17703": 13519, + "17704": 13520, + "17705": 13521, + "17706": 13588, + "17707": 13361, + "17708": 13362, + "17709": 13325, + "17710": 13326, + "17711": 13325, + "17712": 13537, + "17713": 13329, + "17714": 13309, + "17715": 13331, + "17716": 13311, + "17717": 13312, + "17718": 13332, + "17719": 13314, + "17720": 13315, + "17721": 13337, + "17722": 13540, + "17723": 13339, + "17724": 13340, + "17725": 13320, + "17726": 13321, + "17727": 13343, + "17728": 12978, + "17729": 12978, + "17730": 13395, + "17731": 13396, + "17732": 13406, + "17733": 13448, + "17734": 13449, + "17735": 13449, + "17736": 13450, + "17737": 13451, + "17738": 13452, + "17739": 13453, + "17740": 13454, + "17741": 13455, + "17742": 13456, + "17743": 13457, + "17744": 13458, + "17745": 13459, + "17746": 13523, + "17747": 13524, + "17748": 13525, + "17749": 13526, + "17750": 13528, + "17751": 13529, + "17752": 13531, + "17753": 13533, + "17754": 13535, + "17755": 13536, + "17756": 13537, + "17757": 13601, + "17758": 13539, + "17759": 13540, + "17760": 108, + "17761": 13541, + "17762": 13542, + "17763": 13543, + "17764": 13545, + "17765": 13546, + "17766": 13548, + "17767": 13549, + "17768": 13384, + "17769": 13057, + "17770": 13255, + "17771": 13387, + "17772": 13047, + "17773": 13047, + "17774": 13048, + "17775": 13048, + "17776": 13043, + "17777": 13407, + "17778": 13558, + "17779": 13426, + "17780": 13643, + "17781": 13455, + "17782": 13106, + "17783": 12837, + "17784": 108, + "17785": 13109, + "17786": 12766, + "17787": 13301, + "17788": 13301, + "17789": 13408, + "17790": 13434, + "17791": 13442, + "17792": 13443, + "17793": 13611, + "17794": 13444, + "17795": 13043, + "17796": 13043, + "17797": 13048, + "17798": 13048, + "17799": 13048, + "17800": 13445, + "17801": 13633, + "17802": 7095, + "17803": 7093, + "17804": 12689, + "17805": 12689, + "17806": 12689, + "17807": 12689, + "17808": 12689, + "17809": 12689, + "17810": 13663, + "17811": 13210, + "17812": 13592, + "17813": 13184, + "17814": 13185, + "17815": 13187, + "17816": 13183, + "17817": 13189, + "17818": 13181, + "17819": 13659, + "17820": 9708, + "17821": 9710, + "17822": 13600, + "17823": 13662, + "17824": 13554, + "17825": 13646, + "17826": 13480, + "17827": 13481, + "17828": 13671, + "17829": 13670, + "17830": 13484, + "17831": 13545, + "17832": 13451, + "17833": 13487, + "17834": 9324, + "17835": 13678, + "17836": 13657, + "17837": 13658, + "17838": 13457, + "17839": 13561, + "17840": 13484, + "17841": 13492, + "17842": 13172, + "17843": 13161, + "17844": 13674, + "17845": 13105, + "17846": 13186, + "17847": 13186, + "17848": 13189, + "17849": 13181, + "17850": 13182, + "17851": 13498, + "17852": 13678, + "17853": 13679, + "17854": 13634, + "17855": 13680, + "17856": 13876, + "17857": 13877, + "17858": 12834, + "17859": 9349, + "17860": 13685, + "17861": 13641, + "17862": 13643, + "17863": 13695, + "17864": 13529, + "17865": 13495, + "17866": 13584, + "17867": 9756, + "17868": 13686, + "17869": 13700, + "17870": 13890, + "17871": 9363, + "17872": 13243, + "17873": 13654, + "17874": 9403, + "17875": 13696, + "17876": 13702, + "17877": 9870, + "17878": 13696, + "17879": 13697, + "17880": 13711, + "17881": 13500, + "17882": 13532, + "17883": 13714, + "17884": 13904, + "17885": 9753, + "17886": 13906, + "17887": 13708, + "17888": 13251, + "17889": 13666, + "17890": 13668, + "17891": 12871, + "17892": 12775, + "17893": 13913, + "17894": 12775, + "17895": 12780, + "17896": 12780, + "17897": 12780, + "17898": 12780, + "17899": 12780, + "17900": 12780, + "17901": 13545, + "17902": 13727, + "17903": 13921, + "17904": 13924, + "17905": 13683, + "17906": 13926, + "17907": 13274, + "17908": 13685, + "17909": 13272, + "17910": 13930, + "17911": 13688, + "17912": 13932, + "17913": 13693, + "17914": 13924, + "17915": 13935, + "17916": 13936, + "17917": 13937, + "17918": 13938, + "17919": 13939, + "17920": 13940, + "17921": 13941, + "17922": 13942, + "17923": 13943, + "17924": 12904, + "17925": 12979, + "17926": 250, + "17927": 13744, + "17928": 12812, + "17929": 13711, + "17930": 13950, + "17931": 13712, + "17932": 13952, + "17933": 13272, + "17934": 13714, + "17935": 13716, + "17936": 13716, + "17937": 13718, + "17938": 13756, + "17939": 13757, + "17940": 13960, + "17941": 13575, + "17942": 12996, + "17943": 267, + "17944": 13578, + "17945": 13579, + "17946": 13580, + "17947": 13581, + "17948": 13583, + "17949": 13584, + "17950": 13601, + "17951": 13586, + "17952": 13586, + "17953": 13587, + "17954": 13588, + "17955": 13589, + "17956": 13590, + "17957": 13591, + "17958": 13593, + "17959": 13737, + "17960": 13611, + "17961": 13612, + "17962": 13597, + "17963": 13598, + "17964": 13599, + "17965": 13600, + "17966": 13601, + "17967": 13592, + "17968": 113, + "17969": 113, + "17970": 113, + "17971": 113, + "17972": 113, + "17973": 13590, + "17974": 13591, + "17975": 13995, + "17976": 13594, + "17977": 13642, + "17978": 13643, + "17979": 13758, + "17980": 13493, + "17981": 13353, + "17982": 13763, + "17983": 12963, + "17984": 14004, + "17985": 14005, + "17986": 14006, + "17987": 14007, + "17988": 14008, + "17989": 14009, + "17990": 13624, + "17991": 13625, + "17992": 13046, + "17993": 13772, + "17994": 13774, + "17995": 13776, + "17996": 13631, + "17997": 13632, + "17998": 13633, + "17999": 13634, + "18000": 14020, + "18001": 14021, + "18002": 13640, + "18003": 13639, + "18004": 13639, + "18005": 13640, + "18006": 14026, + "18007": 13641, + "18008": 1215, + "18009": 13581, + "18010": 13656, + "18011": 13651, + "18012": 13626, + "18013": 13648, + "18014": 13585, + "18015": 13650, + "18016": 13651, + "18017": 13651, + "18018": 13652, + "18019": 13591, + "18020": 13591, + "18021": 13593, + "18022": 13385, + "18023": 13663, + "18024": 13595, + "18025": 13660, + "18026": 13661, + "18027": 13662, + "18028": 13601, + "18029": 13601, + "18030": 13601, + "18031": 13603, + "18032": 13604, + "18033": 13604, + "18034": 13606, + "18035": 13670, + "18036": 13671, + "18037": 13688, + "18038": 13673, + "18039": 13677, + "18040": 13676, + "18041": 13029, + "18042": 13680, + "18043": 13679, + "18044": 13678, + "18045": 13679, + "18046": 13680, + "18047": 13692, + "18048": 13682, + "18049": 13683, + "18050": 13685, + "18051": 13685, + "18052": 13686, + "18053": 13687, + "18054": 13689, + "18055": 13689, + "18056": 13691, + "18057": 13691, + "18058": 13692, + "18059": 13693, + "18060": 13695, + "18061": 13696, + "18062": 13697, + "18063": 13698, + "18064": 13699, + "18065": 13701, + "18066": 13701, + "18067": 13702, + "18068": 108, + "18069": 13709, + "18070": 13710, + "18071": 13685, + "18072": 13643, + "18073": 13713, + "18074": 13714, + "18075": 218, + "18076": 218, + "18077": 218, + "18078": 13695, + "18079": 13696, + "18080": 13070, + "18081": 14101, + "18082": 13070, + "18083": 13654, + "18084": 13656, + "18085": 13725, + "18086": 13074, + "18087": 13656, + "18088": 13074, + "18089": 13656, + "18090": 13724, + "18091": 13725, + "18092": 13660, + "18093": 13660, + "18094": 13732, + "18095": 13729, + "18096": 13730, + "18097": 13735, + "18098": 13723, + "18099": 244, + "18100": 244, + "18101": 244, + "18102": 13705, + "18103": 13093, + "18104": 13718, + "18105": 13093, + "18106": 13675, + "18107": 13093, + "18108": 13676, + "18109": 13677, + "18110": 13678, + "18111": 13679, + "18112": 13679, + "18113": 13685, + "18114": 14126, + "18115": 14135, + "18116": 14136, + "18117": 14137, + "18118": 14138, + "18119": 14139, + "18120": 14140, + "18121": 14141, + "18122": 13768, + "18123": 14143, + "18124": 13770, + "18125": 14145, + "18126": 13771, + "18127": 14147, + "18128": 13670, + "18129": 13659, + "18130": 111, + "18131": 13661, + "18132": 14152, + "18133": 1340, + "18134": 14154, + "18135": 1343, + "18136": 1333, + "18137": 1341, + "18138": 13771, + "18139": 13775, + "18140": 14160, + "18141": 13630, + "18142": 13738, + "18143": 14163, + "18144": 13689, + "18145": 14165, + "18146": 13691, + "18147": 13636, + "18148": 13788, + "18149": 13763, + "18150": 13466, + "18151": 13467, + "18152": 13468, + "18153": 13469, + "18154": 13788, + "18155": 13789, + "18156": 13728, + "18157": 13644, + "18158": 13730, + "18159": 13648, + "18160": 14171, + "18161": 14171, + "18162": 13796, + "18163": 13652, + "18164": 13798, + "18165": 13759, + "18166": 13758, + "18167": 13761, + "18168": 13803, + "18169": 13755, + "18170": 13758, + "18171": 13757, + "18172": 13806, + "18173": 13807, + "18174": 13808, + "18175": 13809, + "18176": 13663, + "18177": 13811, + "18178": 13813, + "18179": 1376, + "18180": 1384, + "18181": 13723, + "18182": 13724, + "18183": 223, + "18184": 13635, + "18185": 225, + "18186": 13812, + "18187": 13811, + "18188": 13813, + "18189": 334, + "18190": 13824, + "18191": 13825, + "18192": 13826, + "18193": 13827, + "18194": 13828, + "18195": 13682, + "18196": 13607, + "18197": 13610, + "18198": 13612, + "18199": 13837, + "18200": 13836, + "18201": 13836, + "18202": 13828, + "18203": 13822, + "18204": 334, + "18205": 350, + "18206": 350, + "18207": 350, + "18208": 350, + "18209": 350, + "18210": 13827, + "18211": 13828, + "18212": 13830, + "18213": 13831, + "18214": 13832, + "18215": 13833, + "18216": 13834, + "18217": 13835, + "18218": 13821, + "18219": 13791, + "18220": 13210, + "18221": 1428, + "18222": 13210, + "18223": 13848, + "18224": 13850, + "18225": 1429, + "18226": 149, + "18227": 13844, + "18228": 13796, + "18229": 13796, + "18230": 153, + "18231": 13704, + "18232": 13704, + "18233": 13814, + "18234": 13855, + "18235": 13870, + "18236": 13723, + "18237": 13726, + "18238": 13947, + "18239": 13811, + "18240": 13682, + "18241": 13813, + "18242": 223, + "18243": 13730, + "18244": 13695, + "18245": 13653, + "18246": 13795, + "18247": 13796, + "18248": 13797, + "18249": 172, + "18250": 13799, + "18251": 13822, + "18252": 13801, + "18253": 13885, + "18254": 13792, + "18255": 13828, + "18256": 13828, + "18257": 13794, + "18258": 13795, + "18259": 185, + "18260": 13719, + "18261": 13703, + "18262": 13852, + "18263": 13722, + "18264": 13854, + "18265": 13763, + "18266": 13717, + "18267": 13765, + "18268": 13755, + "18269": 13897, + "18270": 13897, + "18271": 246, + "18272": 13900, + "18273": 13878, + "18274": 14007, + "18275": 13878, + "18276": 13911, + "18277": 13902, + "18278": 13947, + "18279": 13951, + "18280": 13950, + "18281": 13948, + "18282": 13949, + "18283": 13780, + "18284": 13694, + "18285": 13727, + "18286": 13697, + "18287": 13700, + "18288": 13702, + "18289": 13834, + "18290": 13815, + "18291": 13778, + "18292": 13781, + "18293": 13791, + "18294": 13792, + "18295": 13794, + "18296": 13793, + "18297": 13784, + "18298": 13787, + "18299": 274, + "18300": 13797, + "18301": 13906, + "18302": 13800, + "18303": 13745, + "18304": 13802, + "18305": 13792, + "18306": 13716, + "18307": 13715, + "18308": 13718, + "18309": 13722, + "18310": 13724, + "18311": 13798, + "18312": 13726, + "18313": 13946, + "18314": 13949, + "18315": 13905, + "18316": 13937, + "18317": 13897, + "18318": 13749, + "18319": 108, + "18320": 13809, + "18321": 13753, + "18322": 3069, + "18323": 13751, + "18324": 13755, + "18325": 114, + "18326": 13947, + "18327": 13759, + "18328": 3075, + "18329": 13757, + "18330": 13982, + "18331": 13763, + "18332": 3079, + "18333": 13884, + "18334": 13885, + "18335": 13885, + "18336": 13885, + "18337": 564, + "18338": 13770, + "18339": 3086, + "18340": 13782, + "18341": 13829, + "18342": 13830, + "18343": 13831, + "18344": 13832, + "18345": 13833, + "18346": 13788, + "18347": 13835, + "18348": 13846, + "18349": 13757, + "18350": 13837, + "18351": 14066, + "18352": 13845, + "18353": 13812, + "18354": 13796, + "18355": 13843, + "18356": 13844, + "18357": 13845, + "18358": 585, + "18359": 14063, + "18360": 13780, + "18361": 588, + "18362": 13850, + "18363": 114, + "18364": 13718, + "18365": 13816, + "18366": 289, + "18367": 118, + "18368": 13810, + "18369": 168, + "18370": 13860, + "18371": 13858, + "18372": 13859, + "18373": 13790, + "18374": 13791, + "18375": 13792, + "18376": 13864, + "18377": 13836, + "18378": 13866, + "18379": 13867, + "18380": 13868, + "18381": 7707, + "18382": 13870, + "18383": 13800, + "18384": 13801, + "18385": 13802, + "18386": 7725, + "18387": 7703, + "18388": 7704, + "18389": 7705, + "18390": 7702, + "18391": 618, + "18392": 7714, + "18393": 7713, + "18394": 7712, + "18395": 13933, + "18396": 13869, + "18397": 7714, + "18398": 13942, + "18399": 13897, + "18400": 13898, + "18401": 355, + "18402": 13765, + "18403": 7723, + "18404": 7726, + "18405": 13898, + "18406": 13903, + "18407": 13904, + "18408": 13819, + "18409": 13820, + "18410": 13924, + "18411": 13908, + "18412": 144, + "18413": 13906, + "18414": 13911, + "18415": 13912, + "18416": 13906, + "18417": 14105, + "18418": 13880, + "18419": 13880, + "18420": 13907, + "18421": 13908, + "18422": 154, + "18423": 13843, + "18424": 13875, + "18425": 13874, + "18426": 13789, + "18427": 13844, + "18428": 13845, + "18429": 13846, + "18430": 13793, + "18431": 7757, + "18432": 13919, + "18433": 184, + "18434": 13921, + "18435": 13925, + "18436": 13843, + "18437": 7753, + "18438": 13926, + "18439": 13989, + "18440": 13927, + "18441": 13795, + "18442": 14094, + "18443": 13929, + "18444": 7762, + "18445": 7752, + "18446": 13944, + "18447": 13878, + "18448": 13865, + "18449": 13866, + "18450": 13867, + "18451": 13980, + "18452": 13880, + "18453": 13947, + "18454": 13975, + "18455": 14088, + "18456": 13819, + "18457": 14090, + "18458": 14091, + "18459": 14091, + "18460": 13953, + "18461": 13954, + "18462": 13955, + "18463": 13956, + "18464": 13976, + "18465": 13870, + "18466": 13870, + "18467": 13965, + "18468": 13966, + "18469": 13763, + "18470": 13764, + "18471": 14092, + "18472": 13773, + "18473": 13774, + "18474": 273, + "18475": 13973, + "18476": 13950, + "18477": 13950, + "18478": 13886, + "18479": 706, + "18480": 13897, + "18481": 13898, + "18482": 13899, + "18483": 14012, + "18484": 1753, + "18485": 1674, + "18486": 237, + "18487": 13894, + "18488": 13895, + "18489": 221, + "18490": 14142, + "18491": 13977, + "18492": 13786, + "18493": 13961, + "18494": 13962, + "18495": 13926, + "18496": 285, + "18497": 248, + "18498": 14186, + "18499": 3246, + "18500": 13928, + "18501": 290, + "18502": 13909, + "18503": 13935, + "18504": 3251, + "18505": 13922, + "18506": 13923, + "18507": 13924, + "18508": 13967, + "18509": 13920, + "18510": 14018, + "18511": 1780, + "18512": 1781, + "18513": 1702, + "18514": 1782, + "18515": 2010, + "18516": 2010, + "18517": 13928, + "18518": 13949, + "18519": 13816, + "18520": 14013, + "18521": 14020, + "18522": 3269, + "18523": 14021, + "18524": 14017, + "18525": 14018, + "18526": 13946, + "18527": 13947, + "18528": 13948, + "18529": 13637, + "18530": 13728, + "18531": 13659, + "18532": 13939, + "18533": 760, + "18534": 285, + "18535": 13963, + "18536": 3283, + "18537": 13988, + "18538": 327, + "18539": 290, + "18540": 14069, + "18541": 14070, + "18542": 13846, + "18543": 13847, + "18544": 14073, + "18545": 14039, + "18546": 14040, + "18547": 13888, + "18548": 347, + "18549": 14062, + "18550": 14062, + "18551": 340, + "18552": 7878, + "18553": 14041, + "18554": 3301, + "18555": 13983, + "18556": 3303, + "18557": 13985, + "18558": 7874, + "18559": 14049, + "18560": 14050, + "18561": 14050, + "18562": 789, + "18563": 14053, + "18564": 14054, + "18565": 14053, + "18566": 13997, + "18567": 356, + "18568": 14045, + "18569": 13906, + "18570": 3317, + "18571": 14100, + "18572": 14101, + "18573": 324, + "18574": 13868, + "18575": 13871, + "18576": 308, + "18577": 13878, + "18578": 13875, + "18579": 14066, + "18580": 13688, + "18581": 13900, + "18582": 13989, + "18583": 14069, + "18584": 13991, + "18585": 14002, + "18586": 14073, + "18587": 14074, + "18588": 14075, + "18589": 14079, + "18590": 14007, + "18591": 14008, + "18592": 14009, + "18593": 14081, + "18594": 14082, + "18595": 14083, + "18596": 14084, + "18597": 14085, + "18598": 14086, + "18599": 13893, + "18600": 13896, + "18601": 13902, + "18602": 13903, + "18603": 14010, + "18604": 14015, + "18605": 14016, + "18606": 13947, + "18607": 359, + "18608": 7934, + "18609": 13910, + "18610": 13911, + "18611": 13907, + "18612": 13913, + "18613": 13914, + "18614": 346, + "18615": 7935, + "18616": 7938, + "18617": 7937, + "18618": 7936, + "18619": 7926, + "18620": 13914, + "18621": 353, + "18622": 13918, + "18623": 14109, + "18624": 13925, + "18625": 14154, + "18626": 13989, + "18627": 14036, + "18628": 14036, + "18629": 14036, + "18630": 14036, + "18631": 14036, + "18632": 14036, + "18633": 14101, + "18634": 13935, + "18635": 13936, + "18636": 7958, + "18637": 7957, + "18638": 7956, + "18639": 7946, + "18640": 7957, + "18641": 13938, + "18642": 13939, + "18643": 14100, + "18644": 14101, + "18645": 13946, + "18646": 14102, + "18647": 14176, + "18648": 13944, + "18649": 14178, + "18650": 14179, + "18651": 14180, + "18652": 14181, + "18653": 14182, + "18654": 13955, + "18655": 13956, + "18656": 13952, + "18657": 13958, + "18658": 14161, + "18659": 14161, + "18660": 14161, + "18661": 14161, + "18662": 14161, + "18663": 13964, + "18664": 13958, + "18665": 13959, + "18666": 14186, + "18667": 13775, + "18668": 14186, + "18669": 13963, + "18670": 13964, + "18671": 13967, + "18672": 13973, + "18673": 14187, + "18674": 14187, + "18675": 14016, + "18676": 14017, + "18677": 13978, + "18678": 13979, + "18679": 13973, + "18680": 13974, + "18681": 13975, + "18682": 14023, + "18683": 13897, + "18684": 14187, + "18685": 13981, + "18686": 13987, + "18687": 13983, + "18688": 13982, + "18689": 13983, + "18690": 13986, + "18691": 14028, + "18692": 13993, + "18693": 13987, + "18694": 13995, + "18695": 14163, + "18696": 13992, + "18697": 13998, + "18698": 13995, + "18699": 14040, + "18700": 13994, + "18701": 13995, + "18702": 13996, + "18703": 14101, + "18704": 14005, + "18705": 14006, + "18706": 14007, + "18707": 14008, + "18708": 14009, + "18709": 14177, + "18710": 14006, + "18711": 14048, + "18712": 14053, + "18713": 14007, + "18714": 14008, + "18715": 14052, + "18716": 14017, + "18717": 14018, + "18718": 14186, + "18719": 14015, + "18720": 14016, + "18721": 14189, + "18722": 14023, + "18723": 14060, + "18724": 14061, + "18725": 14026, + "18726": 14027, + "18727": 14068, + "18728": 14069, + "18729": 14197, + "18730": 14198, + "18731": 14068, + "18732": 14200, + "18733": 14070, + "18735": 14072, + "18736": 14073, + "18737": 14074, + "18738": 14075, + "18739": 14076, + "18740": 14193, + "18741": 14078, + "18745": 14082, + "18747": 14084, + "18748": 14085, + "18750": 14091, + "18751": 14092, + "18752": 14089, + "18755": 14092, + "18757": 14094, + "18758": 14095, + "18760": 14097, + "18761": 14098, + "18762": 14099, + "18766": 14103, + "18768": 14105, + "18770": 14107, + "18772": 14109, + "18773": 14110, + "18775": 14112, + "18777": 13885, + "18778": 14115, + "18779": 13885, + "18780": 13942, + "33024": 196640, + "34048": 32, + "34056": 524320, + "50944": 65568, + "52992": 65568, + "54528": 196704, + "55040": 196640, + "65288": 420151328, + "71021": 71021, + "1009679": 1009679, + "1011021": 1011021, + "1011832": 1011832, + "1024554": 1024554, + "1024570": 1024570, + "1024579": 1024579, + "1025038": 1025038, + "1026228": 1026228, + "1031796": 1031796 +} \ No newline at end of file diff --git a/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs b/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs index 1d69f2c0f..ce8040427 100644 --- a/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs +++ b/Ktisis/Data/Serialization/Converters/JsonFileConverter.cs @@ -3,8 +3,6 @@ using System.Text.Json; using System.Text.Json.Serialization; -using Dalamud.Logging; - using Ktisis.Data.Files; namespace Ktisis.Data.Serialization.Converters { @@ -27,7 +25,7 @@ public class JsonFileConverter : JsonConverter { var value = jsonValue.Deserialize(prop.PropertyType, options); if (value != null) prop.SetValue(result, value); } catch { - PluginLog.Warning($"Failed to parse {prop.PropertyType.Name} value '{prop.Name}' (received {jsonValue.ValueKind} instead)"); + Ktisis.Log.Warning($"Failed to parse {prop.PropertyType.Name} value '{prop.Name}' (received {jsonValue.ValueKind} instead)"); } } diff --git a/Ktisis/Data/Sheets.cs b/Ktisis/Data/Sheets.cs index 21dbc1754..e417a41b6 100644 --- a/Ktisis/Data/Sheets.cs +++ b/Ktisis/Data/Sheets.cs @@ -7,19 +7,19 @@ namespace Ktisis.Data { internal class Sheets { // Sheets - internal static Dictionary Cache = new(); + internal static Dictionary Cache = new(); - public static ExcelSheet GetSheet() where T : ExcelRow { + public static ExcelSheet GetSheet() where T : struct, IExcelRow { var type = typeof(T); - if (Cache.ContainsKey(type)) - return (ExcelSheet)Cache[type]; + if (Cache.TryGetValue(type, out var value)) + return (ExcelSheet)value; - var sheet = Services.DataManager.GetExcelSheet()!; + var sheet = Services.DataManager.GetExcelSheet(); Cache.Add(type, sheet); return sheet; } - public static void ClearSheet() where T : ExcelRow { + public static void ClearSheet() where T : struct, IExcelRow { var type = typeof(T); if (Cache.ContainsKey(type)) Cache.Remove(type); diff --git a/Ktisis/Env/EnvService.cs b/Ktisis/Env/EnvService.cs new file mode 100644 index 000000000..1125824f4 --- /dev/null +++ b/Ktisis/Env/EnvService.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +using Dalamud.Interface.Textures; + +using FFXIVClientStructs.FFXIV.Client.Graphics.Environment; + +using Ktisis.Events; +using Ktisis.Interop.Hooks; +using Ktisis.Structs.Env; + +using Lumina.Excel.Sheets; + +namespace Ktisis.Env { + public static class EnvService { + public static float? TimeOverride; + public static uint? SkyOverride; + public static bool? FreezeWater; + + // Init & Dispose + + public static void Init() { + EventManager.OnGPoseChange += OnGPoseChange; + EnvHooks.Init(); + } + + public static void Dispose() { + EventManager.OnGPoseChange -= OnGPoseChange; + EnvHooks.Dispose(); + } + + // Events + + private static void OnGPoseChange(bool state) { + Ktisis.Log.Info($"Setting env hooks: {state}"); + EnvHooks.SetEnabled(state); + if (!state) { + TimeOverride = null; + SkyOverride = null; + FreezeWater = null; + } + } + + // Data + + private static uint CurSky = uint.MaxValue; + + public static readonly object SkyLock = new(); + public static ISharedImmediateTexture? SkyTex; + + public static void GetSkyImage(uint sky) { + if (sky == CurSky) return; + + CurSky = sky; + GetSkyboxTex(CurSky).ContinueWith(result => { + if (result.Exception != null) { + Ktisis.Log.Error(result.Exception.ToString()); + return; + } + + lock (SkyLock) { + SkyTex = result.Result; + } + }); + } + + private static async Task GetSkyboxTex(uint skyId) { + await Task.Yield(); + Ktisis.Log.Verbose($"Retrieving skybox texture: {skyId:000}"); + return Services.Textures.GetFromGame($"bgcommon/nature/sky/texture/sky_{skyId:000}.tex"); + } + + public unsafe static byte[] GetEnvWeatherIds() { + var env = (EnvManagerEx*)EnvManager.Instance(); + var scene = env != null ? env->EnvScene : null; + if (scene == null) return Array.Empty(); + return scene->GetWeatherSpan() + .TrimEnd((byte)0) + .ToArray(); + } + + public static async Task> GetWeatherIcons(IEnumerable weathers, CancellationToken token) { + await Task.Yield(); + + var result = new List(); + + var weatherSheet = Services.DataManager.GetExcelSheet(); + if (weatherSheet == null) return result; + + foreach (var id in weathers) { + if (token.IsCancellationRequested) break; + + if (id == 0) continue; + + var weather = weatherSheet.GetRow(id); + + var icon = Services.Textures.GetFromGameIcon((uint)weather.Icon); + var info = new WeatherInfo(weather, icon); + result.Add(info); + } + + token.ThrowIfCancellationRequested(); + + return result; + } + } +} diff --git a/Ktisis/Env/WeatherInfo.cs b/Ktisis/Env/WeatherInfo.cs new file mode 100644 index 000000000..392cccd9b --- /dev/null +++ b/Ktisis/Env/WeatherInfo.cs @@ -0,0 +1,28 @@ +using Dalamud.Interface.Textures; +using Dalamud.Utility; + +using Lumina.Excel.Sheets; + +namespace Ktisis.Env { + public class WeatherInfo { + public readonly string Name; + public readonly uint RowId; + public readonly ISharedImmediateTexture? Icon; + + public WeatherInfo(string name) { + this.Name = name; + } + + public WeatherInfo(Weather weather, ISharedImmediateTexture? icon) { + var name = weather.Name.ExtractText(); + if (name.IsNullOrEmpty()) + name = $"Weather #{weather.RowId}"; + + this.Name = name; + this.RowId = weather.RowId; + this.Icon = icon; + } + + public static WeatherInfo Default => new("None"); + } +} diff --git a/Ktisis/Events/EventManager.cs b/Ktisis/Events/EventManager.cs index 4109a4787..40991aab2 100644 --- a/Ktisis/Events/EventManager.cs +++ b/Ktisis/Events/EventManager.cs @@ -1,11 +1,10 @@ using Dalamud.Game.ClientState.Keys; -using FFXIVClientStructs.Havok; -using static FFXIVClientStructs.Havok.hkaPose; +using FFXIVClientStructs.Havok.Animation.Rig; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; using Ktisis.Overlay; using Ktisis.Structs.Actor; -using Ktisis.Structs.Actor.State; using Ktisis.Structs.Input; namespace Ktisis.Events { @@ -34,7 +33,7 @@ public static unsafe void FireOnTransformationMatrixChangeEvent(bool state) { if (OnTransformationMatrixChange == null) return; var bone = Skeleton.GetSelectedBone(); var actor = (Actor*)Ktisis.GPoseTarget!.Address; - hkQsTransformf* boneTransform = bone is null ? &actor->Model->Transform : bone.AccessModelSpace(PropagateOrNot.DontPropagate); + hkQsTransformf* boneTransform = bone is null ? &actor->Model->Transform : bone.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); OnTransformationMatrixChange(state); } diff --git a/Ktisis/Helpers/Common.cs b/Ktisis/Helpers/Common.cs index 31b5131bf..ecc242b0b 100644 --- a/Ktisis/Helpers/Common.cs +++ b/Ktisis/Helpers/Common.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Diagnostics; using System.Security.AccessControl; @@ -13,25 +14,31 @@ internal static bool IsPathValid(string path) { if (!di.Exists) return false; var canRead = false; - - var acl = di.GetAccessControl(); - var rules = acl.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); - foreach (FileSystemAccessRule rule in rules) { - if ((rule.FileSystemRights & FileSystemRights.Read) == 0) - continue; - switch (rule.AccessControlType) { - case AccessControlType.Allow: - canRead = true; - break; - case AccessControlType.Deny: - return false; - default: + try { + var acl = di.GetAccessControl(); + var rules = acl.GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); + foreach (FileSystemAccessRule rule in rules) { + if ((rule.FileSystemRights & FileSystemRights.Read) == 0) continue; + + switch (rule.AccessControlType) { + case AccessControlType.Allow: + canRead = true; + break; + case AccessControlType.Deny: + return false; + default: + continue; + } } - } - return canRead; + return canRead; + } catch (UnauthorizedAccessException e) { + Logger.Error(e, "Unable to check access to path: {Path}", path); + + return false; + } } } } diff --git a/Ktisis/Helpers/LegacyPoseHelpers.cs b/Ktisis/Helpers/LegacyPoseHelpers.cs new file mode 100644 index 000000000..6837f6a72 --- /dev/null +++ b/Ktisis/Helpers/LegacyPoseHelpers.cs @@ -0,0 +1,50 @@ +using System; +using System.Linq; + +using Ktisis.Data.Files; + +namespace Ktisis.Helpers { + public static class LegacyPoseHelpers { + public static string ConvertLegacyPose(string file) { + var result = "{\n"; + result += "\t\"FileExtension\": \".pose\",\n"; + result += "\t\"TypeName\": \"Anamnesis Pose\",\n"; + result += "\t\"Position\": \"0, 0, 0\",\n"; + result += "\t\"Rotation\": \"0, 0, 0, 1\",\n"; + result += "\t\"Scale\": \"1, 1, 1\",\n"; + result += "\t\"Bones\": {\n"; + + var lines = file.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.TrimEntries); + + for (var i = 7; i < lines.Length - 1; i++) { + result += ConvertLegacyBone(lines[i]); + } + + // Length - 2 removes the trailing comma and, incorrectly, an extra curly bracket. Length - 1 doesn't remove the comma at all. Beats me. + result = result.Substring(0, result.Length - 2); + result += "}\n\t}"; + return result; + } + + private static string? ConvertLegacyBone(string bone) { + var boneString = ""; + var boneName = bone.Split(new char[] {':'}, 2)[0].Replace("\"", ""); + var boneRotation = bone.Split(new char[] {':'}, 2)[1].Replace("\"", "").Replace(",", "").Replace(" ", ""); + + if (!PoseFile.LegacyConversions.ContainsKey(boneName) || boneRotation.Contains("null")) return null; + + var boneRotationValues = new float[4]; + for (var i = 0; i < 4; i++) { + var axisValue = Convert.ToInt32(boneRotation.Substring(i * 8, 8), 16); + boneRotationValues[i] = BitConverter.ToSingle(BitConverter.GetBytes(axisValue).Reverse().ToArray(), 0); + } + + boneString += "\t\t\"" + boneName + "\": {\n"; + boneString += "\t\t\t\"Position\": \"0, 0, 0\",\n"; + boneString += "\t\t\t\"Rotation\": \"" + boneRotationValues[0] + ", " + boneRotationValues[1] + ", " + boneRotationValues[2] + ", " + boneRotationValues[3] + "\",\n"; + boneString += "\t\t\t\"Scale\": \"1, 1, 1\"\n"; + boneString += "\t\t},\n"; + return boneString; + } + } +} \ No newline at end of file diff --git a/Ktisis/Helpers/PathHelper.cs b/Ktisis/Helpers/PathHelper.cs new file mode 100644 index 000000000..b9e538bac --- /dev/null +++ b/Ktisis/Helpers/PathHelper.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using Lumina.Excel.Sheets; + +namespace Ktisis.Helpers { + public static class PathHelper { + + internal static readonly Dictionary> Replacers = new() { + {"%Date%", () => DateTime.Now.ToString("yyyy-MM-dd")}, + {"%Year%", () => DateTime.Now.ToString("yyyy")}, + {"%Month%", () => DateTime.Now.ToString("MM")}, + {"%Day%", () => DateTime.Now.ToString("dd")}, + {"%Time%", () => DateTime.Now.ToString("hh-mm-ss")}, + {"%PlayerName%", () => { + if (Ktisis.Configuration.DisplayCharName) + return Services.ClientState.LocalPlayer?.Name.ToString() ?? "Unknown"; + + return "Player"; + }}, + {"%CurrentWorld%", () => Services.ClientState.LocalPlayer?.CurrentWorld.Value.Name.ToString() ?? "Unknown"}, + {"%HomeWorld%", () => Services.ClientState.LocalPlayer?.HomeWorld.Value.Name.ToString() ?? "Unknown" }, + {"%Zone%", () => Services.DataManager.GetExcelSheet()?.GetRow(Services.ClientState.TerritoryType).PlaceName.Value.Name.ToString() ?? "Unknown"}, + }; + + internal static string Replace(ReadOnlySpan path) { + StringBuilder output = new StringBuilder(path.Length); + + for (var i = 0; i < path.Length; i++) { + if (path[i] == '%') { + for (var j = i + 1; j < path.Length; j++) { + if (path[j] != '%') + continue; + + var key = path[i..(j + 1)].ToString(); + + if (Replacers.TryGetValue(key, out var replacer)) { + output.Append(replacer()); + i = j; + } else if (key == "%%") { + output.Append('%'); + i = j; + } else { + output.Append(key); + i = j - 1; // -1 so that if there is an invalid replacement key, we might be able to show the rest without any issues. + } + + break; + } + } else { + + output.Append(path[i]); + } + } + + return output.ToString(); + } + } +} diff --git a/Ktisis/Helpers/PoseHelpers.cs b/Ktisis/Helpers/PoseHelpers.cs new file mode 100644 index 000000000..74e3e62e3 --- /dev/null +++ b/Ktisis/Helpers/PoseHelpers.cs @@ -0,0 +1,108 @@ +using System.IO; +using System.Collections.Generic; + +using Ktisis.Data.Files; +using Ktisis.Data.Serialization; +using Ktisis.Structs.Actor; +using Ktisis.Structs.Poses; +using Ktisis.Interop.Hooks; + +namespace Ktisis.Helpers { + internal class PoseHelpers { + public unsafe static void ExportPose(Actor* actor, string path, PoseMode modes) { + var model = actor->Model; + if (model == null) return; + + var skeleton = model->Skeleton; + if (skeleton == null) return; + + var pose = new PoseFile { + Position = model->Position, + Rotation = model->Rotation, + Scale = model->Scale, + Bones = new () + }; + + pose.Bones.Store(skeleton); + + if (modes.HasFlag(PoseMode.Weapons)) { + var main = actor->GetWeaponSkeleton(WeaponSlot.MainHand); + if (main != null) { + pose.MainHand = new (); + pose.MainHand.Store(main); + } + + var off = actor->GetWeaponSkeleton(WeaponSlot.OffHand); + if (off != null) { + pose.OffHand = new (); + pose.OffHand.Store(off); + } + + var prop = actor->GetWeaponSkeleton(WeaponSlot.Prop); + if (prop != null) { + pose.Prop = new (); + pose.Prop.Store(prop); + } + } + + var json = JsonParser.Serialize(pose); + + using var file = new StreamWriter(path); + file.Write(json); + } + + public unsafe static void ImportPose(Actor* actor, List path, PoseMode modes) { + var content = File.ReadAllText(path[0]); + if (Path.GetExtension(path[0]).Equals(".cmp")) content = LegacyPoseHelpers.ConvertLegacyPose(content); + var pose = JsonParser.Deserialize(content); + if (pose == null) return; + + if (actor->Model == null) return; + + var skeleton = actor->Model->Skeleton; + if (skeleton == null) return; + + pose.ConvertLegacyBones(); + + // Ensure posing is enabled. + if (!PoseHooks.PosingEnabled && !PoseHooks.AnamPosingEnabled) + PoseHooks.EnablePosing(); + + if (pose.Bones != null) { + for (var p = 0; p < skeleton->PartialSkeletonCount; p++) { + switch (p) { + case 0: + if (!modes.HasFlag(PoseMode.Body)) continue; + break; + case 1: + if (!modes.HasFlag(PoseMode.Face)) continue; + break; + } + + pose.Bones.ApplyToPartial(skeleton, p, Ktisis.Configuration.PoseTransforms); + } + } + + if (modes.HasFlag(PoseMode.Weapons)) { + var wepTrans = Ktisis.Configuration.PoseTransforms; + if (Ktisis.Configuration.PositionWeapons) + wepTrans |= PoseTransforms.Position; + + if (pose.MainHand != null) { + var skele = actor->GetWeaponSkeleton(WeaponSlot.MainHand); + if (skele != null) pose.MainHand.Apply(skele, wepTrans); + } + + if (pose.OffHand != null) { + var skele = actor->GetWeaponSkeleton(WeaponSlot.OffHand); + if (skele != null) pose.OffHand.Apply(skele, wepTrans); + } + + if (pose.Prop != null) { + var skele = actor->GetWeaponSkeleton(WeaponSlot.Prop); + if (skele != null) pose.Prop.Apply(skele, wepTrans); + } + } + } + } +} diff --git a/Ktisis/History/ActorBone.cs b/Ktisis/History/ActorBone.cs index 7bf36b4d1..6de7ae18e 100644 --- a/Ktisis/History/ActorBone.cs +++ b/Ktisis/History/ActorBone.cs @@ -1,11 +1,11 @@ using System.Numerics; +using FFXIVClientStructs.Havok.Animation.Rig; + using Ktisis.Structs; using Ktisis.Structs.Actor; using Ktisis.Structs.Bones; -using static FFXIVClientStructs.Havok.hkaPose; - namespace Ktisis.History { public class ActorBone : HistoryItem { private Bone? Bone { get; set; } // This should never have been introduced here. @@ -58,7 +58,7 @@ public unsafe override void Update(bool undo) { var bone = model->Skeleton->GetBone(historyBone.Partial, historyBone.Index); var boneName = bone.HkaBone.Name.String ?? ""; - var boneTransform = bone.AccessModelSpace(PropagateOrNot.DontPropagate); + var boneTransform = bone.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); // Write our updated matrix to memory. var initialRot = boneTransform->Rotation.ToQuat(); @@ -78,7 +78,7 @@ public unsafe bool SetMatrix(bool start = true) { var bone = GetBone(); if (bone == null) return false; - var boneTransform = bone.AccessModelSpace(PropagateOrNot.DontPropagate); + var boneTransform = bone.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); var matrix = Interop.Alloc.GetMatrix(boneTransform); if (start) diff --git a/Ktisis/Interface/Components/ActorsList.cs b/Ktisis/Interface/Components/ActorsList.cs index 72bdc675b..e46c06087 100644 --- a/Ktisis/Interface/Components/ActorsList.cs +++ b/Ktisis/Interface/Components/ActorsList.cs @@ -3,10 +3,10 @@ using System.Linq; using System.Numerics; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using FFXIVClientStructs.FFXIV.Client.Game.Object; using Dalamud.Interface; -using DalamudGameObject = Dalamud.Game.ClientState.Objects.Types.GameObject; +using DalamudGameObject = Dalamud.Game.ClientState.Objects.Types.IGameObject; using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind; using Ktisis.Structs.Actor; @@ -14,8 +14,7 @@ namespace Ktisis.Interface.Components { internal static class ActorsList { - - private static List SavedObjects = new(); + internal static List SavedObjects = new(); private static List? SelectorList = null; private static string Search = ""; private static readonly HashSet WhitelistObjectKinds = new(){ @@ -29,7 +28,6 @@ internal static class ActorsList { // TODO to clear the list on gpose leave public static void Clear() => SavedObjects.Clear(); - // Draw public unsafe static void Draw() { @@ -165,7 +163,7 @@ private unsafe static bool IsValidActor(long target) { private static bool IsValidActor(DalamudGameObject gameObject) => IsValidActor((long)gameObject.Address); private static bool IsNonNetworkObject(DalamudGameObject gameObject) => - gameObject.ObjectId == DalamudGameObject.InvalidGameObjectId; + gameObject.EntityId == 0xE0000000; private static string ExtraInfo(DalamudGameObject gameObject) { List info = new(); if (IsGposeActor(gameObject)) @@ -191,7 +189,7 @@ private static bool IsPlayer(DalamudGameObject gameObject) => gameObject.ObjectKind == ObjectKind.Player; private static bool IsPlayerNotGpose(DalamudGameObject gameObject) => gameObject.ObjectKind == ObjectKind.Player && GetGposeId(gameObject) < 200; - private unsafe static byte GetGposeId(DalamudGameObject gameObject) => + private unsafe static ushort GetGposeId(DalamudGameObject gameObject) => ((Actor*)gameObject.Address)->ObjectID; } diff --git a/Ktisis/Interface/Components/AnimationControls.cs b/Ktisis/Interface/Components/AnimationControls.cs index 558d83643..f0db2946b 100644 --- a/Ktisis/Interface/Components/AnimationControls.cs +++ b/Ktisis/Interface/Components/AnimationControls.cs @@ -1,7 +1,6 @@ -using ImGuiNET; - +using Dalamud.Bindings.ImGui; using Dalamud.Game.ClientState.Objects.Types; -using FFXIVClientStructs.Havok; +using FFXIVClientStructs.Havok.Animation.Playback.Control.Default; using Ktisis.Interop.Hooks; using Ktisis.Util; @@ -10,7 +9,7 @@ namespace Ktisis.Interface.Components { public static class AnimationControls { - public static unsafe void Draw(GameObject? target) { + public static unsafe void Draw(IGameObject? target) { // Animation control if (ImGui.CollapsingHeader("Animation Control")) { var control = PoseHooks.GetAnimationControl(target); diff --git a/Ktisis/Interface/Components/BoneTree.cs b/Ktisis/Interface/Components/BoneTree.cs index e3d421a72..e8dd06a5d 100644 --- a/Ktisis/Interface/Components/BoneTree.cs +++ b/Ktisis/Interface/Components/BoneTree.cs @@ -1,7 +1,7 @@ using System.Linq; using System.Numerics; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Overlay; using Ktisis.Structs; diff --git a/Ktisis/Interface/Components/Categories.cs b/Ktisis/Interface/Components/Categories.cs index 5aa8dc2f1..ee00f8d16 100644 --- a/Ktisis/Interface/Components/Categories.cs +++ b/Ktisis/Interface/Components/Categories.cs @@ -3,7 +3,7 @@ using System.Numerics; using Dalamud.Interface; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Interface.Windows.Workspace; using Ktisis.Localization; diff --git a/Ktisis/Interface/Components/ControlButtons.cs b/Ktisis/Interface/Components/ControlButtons.cs index d8e8ca715..1da363a28 100644 --- a/Ktisis/Interface/Components/ControlButtons.cs +++ b/Ktisis/Interface/Components/ControlButtons.cs @@ -2,8 +2,8 @@ using System.Linq; using System.Numerics; -using ImGuiNET; -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; using Dalamud.Interface; using Dalamud.Interface.Components; @@ -27,8 +27,8 @@ public static class ControlButtons { public static void DrawExtra() { var gizmode = Ktisis.Configuration.GizmoMode; - if (GuiHelpers.IconButtonTooltip(gizmode == MODE.WORLD ? FontAwesomeIcon.Globe : FontAwesomeIcon.Home, "Local / World orientation mode switch.", ButtonSize)) - Ktisis.Configuration.GizmoMode = gizmode == MODE.WORLD ? MODE.LOCAL : MODE.WORLD; + if (GuiHelpers.IconButtonTooltip(gizmode == ImGuizmoMode.World ? FontAwesomeIcon.Globe : FontAwesomeIcon.Home, "Local / World orientation mode switch.", ButtonSize)) + Ktisis.Configuration.GizmoMode = gizmode == ImGuizmoMode.World ? ImGuizmoMode.Local : ImGuizmoMode.World; ImGui.SameLine(); var showSkeleton = Ktisis.Configuration.ShowSkeleton; @@ -121,15 +121,15 @@ public static void PlaceAndRenderSettings() { } - public static void ButtonChangeOperation(OPERATION operation, FontAwesomeIcon icon) { - var isCurrentOperation = Ktisis.Configuration.GizmoOp.HasFlag(OPERATION.ROTATE_X) ? (Ktisis.Configuration.GizmoOp | OPERATION.ROTATE).HasFlag(operation) : Ktisis.Configuration.GizmoOp.HasFlag(operation); + public static void ButtonChangeOperation(ImGuizmoOperation operation, FontAwesomeIcon icon) { + var isCurrentOperation = Ktisis.Configuration.GizmoOp.HasFlag(ImGuizmoOperation.RotateX) ? (Ktisis.Configuration.GizmoOp | ImGuizmoOperation.Rotate).HasFlag(operation) : Ktisis.Configuration.GizmoOp.HasFlag(operation); if (isCurrentOperation) ImGui.PushStyleColor(ImGuiCol.Text, GuiHelpers.VisibleCheckmarkColor()); if (GuiHelpers.IconButton(icon, ButtonSize)) if (!isCurrentOperation) Ktisis.Configuration.GizmoOp = ImGui.GetIO().KeyShift ? Ktisis.Configuration.GizmoOp.AddFlag(operation) : operation; else if (ImGui.GetIO().KeyCtrl) - Ktisis.Configuration.GizmoOp = Ktisis.Configuration.GizmoOp.ToggleFlag(OPERATION.ROTATE, OPERATION.ROTATE_X, OPERATION.ROTATE_Y, OPERATION.ROTATE_Z); + Ktisis.Configuration.GizmoOp = Ktisis.Configuration.GizmoOp.ToggleFlag(ImGuizmoOperation.Rotate, ImGuizmoOperation.RotateX, ImGuizmoOperation.RotateY, ImGuizmoOperation.RotateZ); else if (ImGui.GetIO().KeyShift) Ktisis.Configuration.GizmoOp = Ktisis.Configuration.GizmoOp.RemoveFlag(operation); else @@ -144,10 +144,10 @@ public static void ButtonChangeOperation(OPERATION operation, FontAwesomeIcon ic help += "Change gizmo operation to "; help += operation switch { - OPERATION.TRANSLATE => "Position", - OPERATION.ROTATE => "Rotation", - OPERATION.SCALE => "Scale", - OPERATION.UNIVERSAL => "Universal", + ImGuizmoOperation.Translate => "Position", + ImGuizmoOperation.Rotate => "Rotation", + ImGuizmoOperation.Scale => "Scale", + ImGuizmoOperation.Universal => "Universal", var _ => throw new ArgumentOutOfRangeException(nameof(operation), operation, null) }; diff --git a/Ktisis/Interface/Components/Equipment.cs b/Ktisis/Interface/Components/Equipment.cs index b3767bfe0..7eb44949f 100644 --- a/Ktisis/Interface/Components/Equipment.cs +++ b/Ktisis/Interface/Components/Equipment.cs @@ -1,4 +1,4 @@ -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Util; using Dalamud.Interface; diff --git a/Ktisis/Interface/Components/KeybindEdit.cs b/Ktisis/Interface/Components/KeybindEdit.cs index d22c32e3d..feda2d3d8 100644 --- a/Ktisis/Interface/Components/KeybindEdit.cs +++ b/Ktisis/Interface/Components/KeybindEdit.cs @@ -3,8 +3,7 @@ using System.Collections.Generic; using Dalamud.Game.ClientState.Keys; - -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Interop.Hooks; using Ktisis.Structs.Input; diff --git a/Ktisis/Interface/Components/NpcImport.cs b/Ktisis/Interface/Components/NpcImport.cs new file mode 100644 index 000000000..43a23b8c8 --- /dev/null +++ b/Ktisis/Interface/Components/NpcImport.cs @@ -0,0 +1,198 @@ +using System; +using System.Linq; +using System.Collections.Generic; + +using Dalamud.Utility.Numerics; +using Dalamud.Game.ClientState.Objects.Enums; +using Dalamud.Bindings.ImGui; + +using GLib.Popups; + +using Ktisis.Util; +using Ktisis.Data.Files; +using Ktisis.Data.Npc; +using Ktisis.Localization; +using Ktisis.Structs.Actor; + +namespace Ktisis.Interface.Components { + public class NpcImport { + private readonly PopupList _popup; + + private bool _npcListRaii; + private readonly List NpcList = new(); + + public NpcImport() { + this._popup = new PopupList("##NpcImportPopup", DrawItem) + .WithSearch(MatchQuery); + } + + // Draw handlers + + private bool DrawItem(INpcBase npc, bool isFocus) { + var style = ImGui.GetStyle(); + var fontSize = ImGui.GetFontSize(); + var result = ImGui.Selectable("##", isFocus, 0, ImGui.GetContentRegionAvail().WithY(fontSize * 2)); + + ImGui.SameLine(style.ItemInnerSpacing.X, 0); + ImGui.Text(npc.Name); + + var model = npc.GetModelId(); + ImGui.SameLine(style.ItemInnerSpacing.X, 0); + ImGui.SetCursorPosY(ImGui.GetCursorPosY() + fontSize); + if (model == 0) { + var custom = npc.GetCustomize(); + if (custom != null && custom.Value.Tribe != 0) { + var value = custom.Value; + var sex = value.Gender == Gender.Masculine ? "♂" : "♀"; + ImGui.TextDisabled($"{sex} {Locale.GetString(value.Tribe.ToString())}"); + } else { + ImGui.TextDisabled("Unknown"); + } + } else { + ImGui.TextDisabled($"Model #{model}"); + } + + return result; + } + + private bool MatchQuery(INpcBase npc, string query) + => npc.Name.Contains(query, StringComparison.OrdinalIgnoreCase); + + // Open handler + + public void Open() { + if (!this._npcListRaii) { + this._npcListRaii = true; + FetchNpcList(); + } + + this._popup.Open(); + } + + // Fetch NPC list on open + + private void FetchNpcList() { + NpcImportService.GetNpcList().ContinueWith(task => { + if (task.Exception != null) { + Logger.Error($"Failed to retrieve NPC list:\n{task.Exception}"); + return; + } + + foreach (var chunk in task.Result.Chunk(6000)) { + lock (this.NpcList) { + this.NpcList.AddRange(chunk); + } + } + }); + } + + // Draw UI + + public void Draw(AnamCharaFile.SaveModes mode) { + if (!this._popup.IsOpen) + return; + + var height = ImGui.GetFontSize() * 2; + lock (this.NpcList) { + if (this._popup.Draw(this.NpcList, out var selected, height) && selected != null) { + Services.Framework.RunOnFrameworkThread(() => { + ApplyNpc(selected, mode); + }); + } + } + } + + // Handle NPC select + + private unsafe void ApplyNpc(INpcBase npc, AnamCharaFile.SaveModes mode) { + var target = Ktisis.Target; + if (target == null) return; + + var body = mode.HasFlag(AnamCharaFile.SaveModes.AppearanceBody); + var face = mode.HasFlag(AnamCharaFile.SaveModes.AppearanceFace); + var hair = mode.HasFlag(AnamCharaFile.SaveModes.AppearanceHair); + + if (body) { + var modelId = npc.GetModelId(); + if (modelId != ushort.MaxValue) + target->ModelId = modelId; + } + + if (body || face || hair) { + var custom = npc.GetCustomize(); + if (custom != null && IsCustomizeValid(custom.Value, target->DrawData.Customize)) { + var value = custom.Value; + for (var i = 0; i < Customize.Length; i++) { + var valid = (CustomizeIndex)i switch { + CustomizeIndex.FaceType + or (>= CustomizeIndex.FaceFeatures and <= CustomizeIndex.LipColor) + or CustomizeIndex.Facepaint + or CustomizeIndex.FacepaintColor => face, + CustomizeIndex.HairStyle + or CustomizeIndex.HairColor + or CustomizeIndex.HairColor2 + or CustomizeIndex.HasHighlights => hair, + (>= CustomizeIndex.Race and <= CustomizeIndex.Tribe) + or (>= CustomizeIndex.RaceFeatureSize and <= CustomizeIndex.BustSize) => face || body, + _ => body + }; + if (!valid) continue; + target->DrawData.Customize.Bytes[i] = value.Bytes[i]; + } + } + } + + var gear = mode.HasFlag(AnamCharaFile.SaveModes.EquipmentGear); + var accs = mode.HasFlag(AnamCharaFile.SaveModes.EquipmentAccessories); + if (gear || accs) { + var equip = npc.GetEquipment(); + if (equip != null && IsEquipValid(equip.Value, target->DrawData.Equipment)) { + var value = equip.Value; + for (var i = 0; i < Structs.Actor.Equipment.SlotCount; i++) { + var valid = (EquipIndex)i switch { + <= EquipIndex.Feet => gear, + <= EquipIndex.RingLeft => accs, + _ => true + }; + if (!valid) continue; + target->DrawData.Equipment.Slots[i] = value.Slots[i]; + } + } + } + + if (mode.HasFlag(AnamCharaFile.SaveModes.EquipmentWeapons)) { + var main = npc.GetMainHand(); + if (main != null) + target->DrawData.MainHand.Equip = main.Value; + + var off = npc.GetOffHand(); + if (off != null) + target->DrawData.OffHand.Equip = off.Value; + } + + target->Redraw(); + } + + private unsafe bool IsCustomizeValid(Customize custom, Customize current) { + for (var i = 0; i < Customize.Length; i++) + if (custom.Bytes[i] != 0 && custom.Bytes[i] != current.Bytes[i]) + return true; + return false; + } + + private unsafe bool IsEquipValid(Structs.Actor.Equipment equip, Structs.Actor.Equipment current) { + var isValid = false; + var isUnique = false; + + for (var i = 0; i < Structs.Actor.Equipment.SlotCount; i++) { + var item = equip.Slots[i]; + isValid |= item != 0; + isUnique |= item != current.Slots[i]; + if (isValid && isUnique) + return true; + } + + return false; + } + } +} diff --git a/Ktisis/Interface/Components/PopupSelect.cs b/Ktisis/Interface/Components/PopupSelect.cs index 4951421fe..ac9684669 100644 --- a/Ktisis/Interface/Components/PopupSelect.cs +++ b/Ktisis/Interface/Components/PopupSelect.cs @@ -3,7 +3,7 @@ using System.Numerics; using System.Collections.Generic; -using ImGuiNET; +using Dalamud.Bindings.ImGui; namespace Ktisis.Interface.Components { public static class PopupSelect { @@ -26,7 +26,7 @@ public static class PopupSelect { public static int HoverPopupWindowColumns = 1; private static Action? PreviousOnClose; public static int HoverPopupWindowIndexKey = 0; - public static dynamic? HoverPopupWindowItemForHeader = null; + public static object? HoverPopupWindowItemForHeader = null; [Flags] public enum HoverPopupWindowFlags { @@ -63,7 +63,7 @@ public static void HoverPopupWindow( HoverPopupWindowFlags flags, IEnumerable enumerable, Func, string, IEnumerable> filter, - Action header, + Action header, Func drawBeforeLine, // Parameters: T item, bool isActive. Returns bool isSelected, bool Focus. Action onSelect, Action onClose, diff --git a/Ktisis/Interface/Components/TransformTable.cs b/Ktisis/Interface/Components/TransformTable.cs index fa3a713f0..bb9249f84 100644 --- a/Ktisis/Interface/Components/TransformTable.cs +++ b/Ktisis/Interface/Components/TransformTable.cs @@ -2,12 +2,13 @@ using System.Numerics; using System.Collections.Generic; -using ImGuiNET; -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; using Dalamud.Interface; -using FFXIVClientStructs.Havok; +using FFXIVClientStructs.Havok.Common.Base.Math.Quaternion; +using FFXIVClientStructs.Havok.Common.Base.Math.Vector; using Ktisis.Util; using Ktisis.Events; @@ -100,19 +101,19 @@ public bool DrawTable() { result |= ColoredDragFloat3("##Position", ref Position, BaseSpeedPos * multiplier, AxisColors, out active); anyActive |= active; ImGui.SameLine(); - ControlButtons.ButtonChangeOperation(OPERATION.TRANSLATE, iconPosition); + ControlButtons.ButtonChangeOperation(ImGuizmoOperation.Translate, iconPosition); // Rotation result |= ColoredDragFloat3("##Rotation", ref Rotation, BaseSpeedRot * multiplier, AxisColors, out active); anyActive |= active; ImGui.SameLine(); - ControlButtons.ButtonChangeOperation(OPERATION.ROTATE, iconRotation); + ControlButtons.ButtonChangeOperation(ImGuizmoOperation.Rotate, iconRotation); // Scale result |= ColoredDragFloat3("##Scale", ref Scale, BaseSpeedSca * multiplier, AxisColors, out active); anyActive |= active; ImGui.SameLine(); - ControlButtons.ButtonChangeOperation(OPERATION.SCALE, iconScale); + ControlButtons.ButtonChangeOperation(ImGuizmoOperation.Scale, iconScale); IsActive = anyActive; /* FIXME: Checking `ImGui.IsAnyItemActive` seems overzealous? Should probably replace with new `anyActive`. */ @@ -132,7 +133,7 @@ public bool DrawTable() { Vector2 mults = new(ModifierMultShift, ModifierMultCtrl); ImGui.PushItemWidth(CalcItemWidth(2)); - if (ImGui.DragFloat2("##SpeedMult##shiftCtrl", ref mults, 1f, 0.00001f, 10000f, null, ImGuiSliderFlags.Logarithmic)) { + if (ImGui.DragFloat2("##SpeedMult##shiftCtrl", ref mults, 1f, 0.00001f, 10000f, flags: ImGuiSliderFlags.Logarithmic)) { Ktisis.Configuration.TransformTableModifierMultShift = mults.X; Ktisis.Configuration.TransformTableModifierMultCtrl = mults.Y; } diff --git a/Ktisis/Interface/Input.cs b/Ktisis/Interface/Input.cs index 6fce59495..47e74ddbe 100644 --- a/Ktisis/Interface/Input.cs +++ b/Ktisis/Interface/Input.cs @@ -3,12 +3,13 @@ using System.Collections.Immutable; using System.Linq; -using ImGuizmoNET; +using Dalamud.Bindings.ImGuizmo; using Dalamud.Game.ClientState.Keys; using FFXIVClientStructs.FFXIV.Client.UI; +using Ktisis.Camera; using Ktisis.Events; using Ktisis.Overlay; using Ktisis.Interop.Hooks; @@ -41,6 +42,19 @@ internal static bool HandleHeldPurposes(VirtualKey key) { case Purpose.HoldToHideSkeleton: Skeleton.Toggle(); return true; + case Purpose.NextCamera: + CameraService.ChangeCameraIndex(1); + break; + case Purpose.PreviousCamera: + CameraService.ChangeCameraIndex(-1); + break; + case Purpose.ToggleFreeCam: + CameraService.ToggleFreecam(); + break; + case Purpose.NewCamera: + var camera = CameraService.SpawnCamera(); + CameraService.SetOverride(camera); + break; } return false; @@ -66,19 +80,19 @@ internal static bool OnKeyPressed(QueueItem input) { var isUsing = ImGuizmo.IsUsing(); switch (purpose) { case Purpose.SwitchToTranslate: - if (!isUsing) Ktisis.Configuration.GizmoOp = OPERATION.TRANSLATE; + if (!isUsing) Ktisis.Configuration.GizmoOp = ImGuizmoOperation.Translate; break; case Purpose.SwitchToRotate: - if (!isUsing) Ktisis.Configuration.GizmoOp = OPERATION.ROTATE; + if (!isUsing) Ktisis.Configuration.GizmoOp = ImGuizmoOperation.Rotate; break; case Purpose.SwitchToScale: - if (!isUsing) Ktisis.Configuration.GizmoOp = OPERATION.SCALE; + if (!isUsing) Ktisis.Configuration.GizmoOp = ImGuizmoOperation.Scale; break; case Purpose.SwitchToUniversal: - if (!isUsing) Ktisis.Configuration.GizmoOp = OPERATION.UNIVERSAL; + if (!isUsing) Ktisis.Configuration.GizmoOp = ImGuizmoOperation.Universal; break; case Purpose.ToggleLocalWorld: - if (!isUsing) Ktisis.Configuration.GizmoMode = Ktisis.Configuration.GizmoMode == MODE.WORLD ? MODE.LOCAL : MODE.WORLD; + if (!isUsing) Ktisis.Configuration.GizmoMode = Ktisis.Configuration.GizmoMode == ImGuizmoMode.World ? ImGuizmoMode.Local : ImGuizmoMode.World; break; case Purpose.ClearCategoryVisibilityOverload: Category.VisibilityOverload.Clear(); @@ -156,6 +170,10 @@ public enum Purpose { DeselectGizmo, BoneSelectionUp, BoneSelectionDown, + NextCamera, + PreviousCamera, + ToggleFreeCam, + NewCamera, } public static readonly Dictionary> DefaultKeys = new(){ @@ -172,6 +190,8 @@ public enum Purpose { {Purpose.DeselectGizmo, new(){VirtualKey.ESCAPE}}, {Purpose.BoneSelectionUp, new(){VirtualKey.UP}}, {Purpose.BoneSelectionDown, new(){VirtualKey.DOWN}}, + {Purpose.NextCamera, new(){VirtualKey.OEM_6}}, + {Purpose.PreviousCamera, new(){VirtualKey.OEM_4}}, }; // Init & dispose @@ -257,6 +277,6 @@ private static void ReadPurposesStates() { return (purpose: p, state); }).ToDictionary(kp => kp.purpose, kp => kp.state); } - private unsafe static bool IsChatInputActive() => ((UIModule*)Services.GameGui.GetUIModule())->GetRaptureAtkModule()->AtkModule.IsTextInputActive(); + internal unsafe static bool IsChatInputActive() => ((UIModule*)Services.GameGui.GetUIModule().Address)->GetRaptureAtkModule()->AtkModule.IsTextInputActive(); } } diff --git a/Ktisis/Interface/KtisisGui.cs b/Ktisis/Interface/KtisisGui.cs index 1293cb6fc..a47dc8b42 100644 --- a/Ktisis/Interface/KtisisGui.cs +++ b/Ktisis/Interface/KtisisGui.cs @@ -19,6 +19,15 @@ static KtisisGui() { FontAwesomeIcon.None, 0 )); + + if (Ktisis.Configuration.EnableAutoSave) { + FileDialogManager.CustomSideBarItems.Add(( + "AutoSave", + Ktisis.Configuration.AutoSavePath, + FontAwesomeIcon.Bookmark, + -1 + )); + } } public static void Draw() { diff --git a/Ktisis/Interface/Windows/ActorEdit/EditActor.cs b/Ktisis/Interface/Windows/ActorEdit/EditActor.cs index d2748b6bf..52a0b721e 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditActor.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditActor.cs @@ -1,8 +1,10 @@ +using System; using System.Numerics; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Structs.Actor; +using Ktisis.Structs.Actor.State; namespace Ktisis.Interface.Windows.ActorEdit { public static class EditActor { @@ -55,11 +57,32 @@ public unsafe static void Draw() { } public unsafe static void AdvancedEdit() { + ImGui.Spacing(); var modelId = (int)Target->ModelId; if (ImGui.InputInt("Model ID", ref modelId)) { Target->ModelId = (uint)modelId; Target->Redraw(); } + + ImGui.Spacing(); + ImGui.SliderFloat("Opacity", ref Target->Transparency, 0.0f, 1.0f); + + if (Target->Model != null) { + if (!ActorWetnessOverride.Instance.WetnessOverrides.TryGetValue((IntPtr)Target, out var wetness)) + wetness = (Target->Model->WeatherWetness, Target->Model->SwimmingWetness, Target->Model->WetnessDepth); + + if (!ActorWetnessOverride.Instance.WetnessOverridesEnabled.TryGetValue((IntPtr)Target, out var enabled)) + enabled = false; + + ImGui.Checkbox("Wetness Override Enabled", ref enabled); + + ImGui.SliderFloat("WeatherWetness", ref wetness.WeatherWetness, 0.0f, 1.0f); + ImGui.SliderFloat("SwimmingWetness", ref wetness.SwimmingWetness, 0.0f, 1.0f); + ImGui.SliderFloat("WetnessDepth", ref wetness.WetnessDepth, 0.0f, 3.0f); + + ActorWetnessOverride.Instance.WetnessOverrides[(IntPtr)Target] = wetness; + ActorWetnessOverride.Instance.WetnessOverridesEnabled[(IntPtr)Target] = enabled; + } ImGui.EndTabItem(); } diff --git a/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs b/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs index a014ab8a2..8acdf7b06 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditCustomize.cs @@ -3,14 +3,11 @@ using System.Numerics; using System.Collections.Generic; -using ImGuiNET; -using ImGuiScene; - -using Lumina.Excel; - +using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Game.ClientState.Objects.Enums; +using Dalamud.Interface.Textures; using Ktisis.Util; using Ktisis.Data; @@ -21,13 +18,15 @@ using Ktisis.Structs.Actor; using Ktisis.Interface.Windows.ActorEdit; +using Lumina.Excel; + namespace Ktisis.Interface.Windows { public struct MenuOption { public Menu Option; public CustomizeIndex ColorIndex = 0; public uint[] Colors = Array.Empty(); - public Dictionary? Select = null; + public Dictionary? Select = null; public MenuOption(Menu option) => Option = option; } @@ -70,9 +69,9 @@ public static class EditCustomize { public static int FaceType = -1; public static string FacialFeatureName = ""; - public static List? FacialFeatureIcons = null; + public static List? FacialFeatureIcons = null; - public static CharaMakeType? CharaMakeType; + public static CharaMakeType? CharaMakeData; public static HumanCmp HumanCmp = new(); @@ -102,28 +101,26 @@ private static void InvokeMakeData(object[] args) { CustomIndex = index; FacialFeatureIcons = null; } + + private static void GetFeatureIcons(Customize custom) { + if (CharaMakeData == null) return; - private readonly static AsyncTask GetFeatureIcons = new(InvokeFeatureIcons); - private static void InvokeFeatureIcons(object[] args) { - if (args[0] is not Customize custom) - return; - - if (CharaMakeType == null) return; + var data = CharaMakeData.Value; - var features = new List(); + var features = new List(); for (var i = 0; i < 7; i++) { var index = custom.FaceType - 1 + (8 * i); if (custom.Race == Race.Hrothgar) index -= 4; // ??? - if (index < 0 || index >= CharaMakeType.FacialFeatures.Length) + if (index < 0 || index >= data.FacialFeatures.Length) index = 8 * i; - var iconId = (uint)CharaMakeType.FacialFeatures[index]; + var iconId = (uint)data.FacialFeatures[index]; if (iconId == 0) - iconId = (uint)CharaMakeType.FacialFeatures[8 * i]; + iconId = (uint)data.FacialFeatures[8 * i]; - var icon = Services.DataManager.GetImGuiTextureIcon(iconId); + var icon = Services.Textures.GetFromGameIcon(iconId); if (icon != null) features.Add(icon); } FacialFeatureIcons = features; @@ -135,12 +132,22 @@ private static void InvokeFeatureIcons(object[] args) { public unsafe static void Draw() { // Customize - var custom = Target->DrawData.Customize; + if (Target->ModelId != 0) { + ImGui.Text("Target actor must be a human to edit customization data."); + ImGui.Spacing(); + if (ImGui.Button("Turn Human")) { + Target->ModelId = 0; + Target->Redraw(); + } + ImGui.EndTabItem(); + return; + } + + var custom = Target->GetCustomize(); if (custom.Race == 0 || custom.Tribe == 0) { custom.Race = Race.Hyur; custom.Tribe = Tribe.Highlander; - Target->DrawData.Customize = custom; } var index = custom.GetMakeIndex(); @@ -166,8 +173,7 @@ public static void DrawFundamental(Customize custom) { // Gender var isM = custom.Gender == Gender.Masculine; - - if (ImGuiComponents.IconButton(isM ? FontAwesomeIcon.Mars : FontAwesomeIcon.Venus)) { + if (ImGuiComponents.IconButton("##KtisisCustomizeGender", isM ? FontAwesomeIcon.Mars : FontAwesomeIcon.Venus)) { custom.Gender = isM ? Gender.Feminine : Gender.Masculine; Apply(custom); } @@ -329,7 +335,7 @@ public static void DrawIconSelector(Customize custom, MenuOption option, int _va bool click; if (sel!.ContainsKey(val)) - click = ImGui.ImageButton(sel[val].ImGuiHandle, IconSize); + click = ImGui.ImageButton(sel[val].GetWrapOrEmpty().Handle, IconSize); else click = ImGui.Button($"{val}", ButtonIconSize); @@ -492,8 +498,8 @@ public static bool DrawColorList(uint[] colors, ref byte value) { // Facial feature selector public static void DrawFacialFeatures(Customize custom) { - if ((FacialFeatureIcons == null || custom.FaceType != FaceType) && !GetFeatureIcons.IsRunning) - GetFeatureIcons.Run(custom); + if ((FacialFeatureIcons == null || custom.FaceType != FaceType)) + GetFeatureIcons(custom); if (FacialFeatureIcons == null) return; @@ -514,7 +520,7 @@ public static void DrawFacialFeatures(Customize custom) { if (i == 7) // Legacy tattoo button |= ImGui.Button("Legacy\nTattoo", ButtonIconSize); else - button |= ImGui.ImageButton(FacialFeatureIcons[i].ImGuiHandle, IconSize); + button |= ImGui.ImageButton(FacialFeatureIcons[i].GetWrapOrEmpty().Handle, IconSize); ImGui.PopStyleColor(); if (button) { @@ -569,7 +575,7 @@ public unsafe static void DrawIconList(Customize custom, MenuOption option) { foreach (var (val, icon) in option.Select!) { if (icon == null) continue; - if (ImGui.ImageButton(icon.ImGuiHandle, ListIconSize)) { + if (ImGui.ImageButton(icon.GetWrapOrEmpty().Handle, ListIconSize)) { custom.Bytes[(uint)opt.Index] = (byte)val; Apply(custom); } @@ -601,100 +607,102 @@ public unsafe static void DrawIconList(Customize custom, MenuOption option) { public static Dictionary> GetMenuOptions(uint index, Customize custom) { var options = new Dictionary>(); - - var data = CharaMakeType; - if (data == null || data.RowId != index) { - CharaMakeType = Sheets.GetSheet().GetRow(index)!; + + if (CharaMakeData == null || CharaMakeData.Value.RowId != index) { + CharaMakeData = Sheets.GetSheet().GetRow(index); MenuColors.Clear(); - data = CharaMakeType; } + + var data = CharaMakeData!.Value; + + for (int i = 0; i < CharaMakeType.MenuCt; i++) { + var val = data.Menus[i]; - if (data != null) { - for (int i = 0; i < CharaMakeType.MenuCt; i++) { - var val = data.Menus[i]; - - if (val.Index == 0) - break; + if (val.Index == 0) + break; - var type = val.Type; - if (type == MenuType.Unknown1) - type = MenuType.Color; - - if (type == MenuType.Color) { // I gave up on making this work procedurally - var menuCol = new MenuColor(val.Name, val.Index); - switch (val.Index) { - case CustomizeIndex.EyeColor: - menuCol.Colors = HumanCmp.GetEyeColors(); - menuCol.AltIndex = CustomizeIndex.EyeColor2; - break; - case CustomizeIndex.FaceFeaturesColor: - menuCol.Colors = HumanCmp.GetEyeColors(); - menuCol.Iterable = false; - break; - case CustomizeIndex.FacepaintColor: - menuCol.Colors = HumanCmp.GetFacepaintColors(); - break; - case CustomizeIndex.HairColor: - menuCol.Colors = HumanCmp.GetHairColors(data.TribeEnum, data.GenderEnum); - menuCol.AltIndex = CustomizeIndex.HairColor2; - menuCol.AltColors = HumanCmp.GetHairHighlights(); - break; - case CustomizeIndex.LipColor: - menuCol.Colors = HumanCmp.GetLipColors(); - break; - case CustomizeIndex.SkinColor: - menuCol.Colors = HumanCmp.GetSkinColors(data.TribeEnum, data.GenderEnum); - break; - default: - Logger.Warning($"Color not implemented: {val.Index}"); - break; - } - MenuColors.Add(menuCol); - continue; + var type = val.Type; + if (type == MenuType.Unknown1) + type = MenuType.Color; + + if (type == MenuType.Color) { // I gave up on making this work procedurally + var menuCol = new MenuColor(val.Name, val.Index); + switch (val.Index) { + case CustomizeIndex.EyeColor: + menuCol.Colors = HumanCmp.GetEyeColors(); + menuCol.AltIndex = CustomizeIndex.EyeColor2; + break; + case CustomizeIndex.FaceFeaturesColor: + menuCol.Colors = HumanCmp.GetEyeColors(); + menuCol.Iterable = false; + break; + case CustomizeIndex.FacepaintColor: + menuCol.Colors = HumanCmp.GetFacepaintColors(); + break; + case CustomizeIndex.HairColor: + menuCol.Colors = HumanCmp.GetHairColors(data.TribeEnum, data.GenderEnum); + menuCol.AltIndex = CustomizeIndex.HairColor2; + menuCol.AltColors = HumanCmp.GetHairHighlights(); + break; + case CustomizeIndex.LipColor: + menuCol.Colors = HumanCmp.GetLipColors(); + break; + case CustomizeIndex.SkinColor: + menuCol.Colors = HumanCmp.GetSkinColors(data.TribeEnum, data.GenderEnum); + break; + default: + Logger.Warning($"Color not implemented: {val.Index}"); + break; } + MenuColors.Add(menuCol); + continue; + } - if (type == MenuType.SelectMulti) { - if (val.Index == CustomizeIndex.FaceFeatures) - FacialFeatureName = val.Name; - continue; - } + if (type == MenuType.SelectMulti) { + if (val.Index == CustomizeIndex.FaceFeatures) + FacialFeatureName = val.Name; + continue; + } + + if (!options.ContainsKey(type)) + options[type] = new(); - if (!options.ContainsKey(type)) - options[type] = new(); - - var opt = new MenuOption(val); - - if (val.HasIcon) { - var icons = new Dictionary(); - if (val.IsFeature) { - var featMake = CharaMakeType?.FeatureMake.Value; - if (featMake == null) continue; - - List> features; - if (val.Index == CustomizeIndex.HairStyle) - features = featMake.HairStyles; - else if (val.Index == CustomizeIndex.Facepaint) - features = featMake.Facepaints; - else continue; - - foreach (var feature in features) { - var feat = feature.Value; - if (feat == null || feat.FeatureId == 0) break; - - var icon = Services.DataManager.GetImGuiTextureIcon(feat.Icon); - if (icon != null) icons.Add(feat.FeatureId, icon); - } - } else { - for (var x = 0; x < val.Count; x++) { - var icon = Services.DataManager.GetImGuiTextureIcon(val.Params[x]); - if (icon != null) icons.Add(val.Graphics[x], icon); - } + var opt = new MenuOption(val); + + if (val.HasIcon) { + var icons = new Dictionary(); + if (val.IsFeature) { + var featMake = CharaMakeData?.FeatureMake.Value; + if (featMake == null) continue; + + List> features; + if (val.Index == CustomizeIndex.HairStyle) + features = featMake.Value.HairStyles; + else if (val.Index == CustomizeIndex.Facepaint) + features = featMake.Value.Facepaints; + else continue; + + foreach (var feature in features) { + var feat = feature.Value; + if (feat.FeatureId == 0) break; + + if (!Services.Textures.TryGetFromGameIcon(feat.Icon, out var icon)) + continue; + + icons.Add(feat.FeatureId, icon); + } + } else { + for (var x = 0; x < val.Count; x++) { + if (!Services.Textures.TryGetFromGameIcon(val.Params[x], out var icon)) + continue; + + icons.Add(val.Graphics[x], icon); } - opt.Select = icons; } - - options[type].Add(opt); + opt.Select = icons; } + + options[type].Add(opt); } return options; diff --git a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs index e4b8b298f..bdaefa9a6 100644 --- a/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs +++ b/Ktisis/Interface/Windows/ActorEdit/EditEquip.cs @@ -5,11 +5,10 @@ using System.Threading; using System.Threading.Tasks; -using ImGuiNET; -using ImGuiScene; - +using Dalamud.Bindings.ImGui; using Dalamud.Interface; -using Dalamud.Logging; +using Dalamud.Interface.Textures; +using Dalamud.Utility; using Ktisis.Util; using Ktisis.Data; @@ -18,6 +17,9 @@ using Ktisis.Structs.Actor; using Ktisis.Structs.Actor.Equip; using Ktisis.Interface.Components; +using Ktisis.Structs.Actor.Types; + +using Lumina.Excel; namespace Ktisis.Interface.Windows.ActorEdit { public static class EditEquip { @@ -31,22 +33,27 @@ public static class EditEquip { public static IEnumerable? Items => ItemData.Get(); + public static ExcelSheet? Glasses; + public static Dictionary Equipped = new(); public static EquipSlot? SlotSelect; public static IEnumerable? SlotItems; + private static string GlassesSearch = ""; private static string ItemSearch = ""; private static string SetSearch = ""; private static string DyeSearch = ""; private static bool DrawSetSelection = false; private static bool DrawSetDyeSelection = false; + private static bool DrawGlassesSelection = false; private static EquipSlot? SlotSelectDye; + private static int SelectDyeIndex; public static IEnumerable? Dyes => DyeData.Get(); public static Item? FindItem(object item, EquipSlot slot) - => Items?.FirstOrDefault(i => (item is WeaponEquip ? i.IsWeapon() : i.IsEquippable(slot)) && i.IsEquipItem(item), null!); + => Items?.FirstOrDefault(i => (item is WeaponEquip ? i.IsWeapon() : i.IsEquippable(slot)) && i.IsEquipItem(item)); public static EquipIndex SlotToIndex(EquipSlot slot) => (EquipIndex)(slot - ((int)slot >= 5 ? 3 : 2)); @@ -54,13 +61,14 @@ public static class EditEquip { private readonly static AsyncData> ItemData = new(GetItemData); private static IEnumerable GetItemData(object[] args) - => Sheets.GetSheet().Where(i => i.IsEquippable()); + => Sheets.GetSheet().Where(i => i.IsEquippable()).ToList(); private readonly static AsyncData> DyeData = new(GetDyeData); private static IEnumerable GetDyeData(object[] args) => Sheets.GetSheet() .Where(i => i.IsValid()) - .OrderBy(i => i.Shade).ThenBy(i => i.SubOrder); + .OrderBy(i => i.Shade).ThenBy(i => i.SubOrder) + .ToList(); // UI Code @@ -68,6 +76,11 @@ public static void Draw() { if (Items == null || Dyes == null) return; DrawControls(); + + ImGui.Spacing(); + DrawFaceWear(); + ImGui.Spacing(); + ImGui.Spacing(); ImGui.BeginGroup(); for (var i = 2; i < 13; i++) { @@ -83,19 +96,35 @@ public static void Draw() { DrawSelector(slot); } ImGui.EndGroup(); - + ImGui.EndTabItem(); } + public unsafe static void DrawFaceWear() { + Glasses ??= Services.DataManager.GetExcelSheet(); + + var glassesId = EditActor.Target->DrawData.Glasses; + var glasses = Glasses.GetRow(glassesId); + var name = glasses.Name; + if (ImGui.BeginCombo("Glasses", name)) { + DrawGlassesSelection = true; + ImGui.CloseCurrentPopup(); + ImGui.EndCombo(); + } + + if (DrawGlassesSelection) + DrawGlassesSelector(); + } + public unsafe static void DrawSelector(EquipSlot slot) { var tar = EditActor.Target; var isWeapon = slot == EquipSlot.MainHand || slot == EquipSlot.OffHand; - + object equipObj; if (isWeapon) - equipObj = slot == EquipSlot.MainHand ? tar->DrawData.MainHand.Equip : tar->DrawData.OffHand.Equip; + equipObj = tar->GetWeaponEquip(slot); else - equipObj = (ItemEquip)tar->DrawData.Equipment.Slots[(int)SlotToIndex(slot)]; + equipObj = tar->GetEquip(SlotToIndex(slot)); var isEmpty = true; { @@ -111,7 +140,7 @@ public unsafe static void DrawSelector(EquipSlot slot) { Equipped[slot].SetEquip(equipObj, slot); var item = Equipped[slot]; - var icon = item.Icon?.ImGuiHandle ?? 0; + var icon = item.Icon?.GetWrapOrEmpty().Handle ?? 0; ImGui.PushID((int)slot); if (ImGui.ImageButton(icon, IconSize) && SlotSelect == null) OpenSelector(slot); @@ -133,8 +162,9 @@ public unsafe static void DrawSelector(EquipSlot slot) { ImGui.PushItemWidth(120); if (isWeapon) { var equip = (WeaponEquip)equipObj; + //PluginLog.Information($"{equip.Set} {equip.Base} {equip.Variant}"); var val = new int[] { equip.Set, equip.Base, equip.Variant }; - if (ImGui.InputInt3($"##{slot}", ref val[0])) { + if (ImGui.InputInt($"##KtisisWep_{slot}", val)) { equip.Set = (ushort)val[0]; equip.Base = (ushort)val[1]; equip.Variant = (ushort)val[2]; @@ -143,7 +173,7 @@ public unsafe static void DrawSelector(EquipSlot slot) { } else { var equip = (ItemEquip)equipObj; var val = new int[] { equip.Id, equip.Variant }; - if (ImGui.InputInt2($"##{slot}", ref val[0])) { + if (ImGui.InputInt($"##{slot}", val)) { equip.Id = (ushort)val[0]; equip.Variant = (byte)val[1]; tar->Equip(SlotToIndex(slot), equip); @@ -152,9 +182,9 @@ public unsafe static void DrawSelector(EquipSlot slot) { ImGui.PopItemWidth(); ImGui.SameLine(); - var dye = Dyes!.FirstOrDefault(i => i.RowId == (isWeapon ? ((WeaponEquip)equipObj).Dye : ((ItemEquip)equipObj).Dye))!; - if (ImGui.ColorButton($"{dye.Name} [{dye.RowId}]##{slot}", dye.ColorVector4, ImGuiColorEditFlags.NoBorder)) - OpenDyePicker(slot); + DrawDyeButton((IEquipItem)equipObj, slot, 0); + ImGui.SameLine(); + DrawDyeButton((IEquipItem)equipObj, slot, 1); if (equipObj is WeaponEquip) { ImGui.SameLine(); @@ -179,7 +209,7 @@ public unsafe static void DrawSelector(EquipSlot slot) { if (SlotSelect == slot) DrawSelectorList(slot, equipObj); if (SlotSelectDye == slot) - DrawDyePicker(slot, equipObj); + DrawDyePicker(slot, equipObj, SelectDyeIndex); } public static void OpenSelector(EquipSlot slot) { @@ -191,7 +221,26 @@ public static void CloseSelector() { SlotItems = null; } - public static void OpenDyePicker(EquipSlot slot) => SlotSelectDye = slot; + private static void DrawDyeButton(IEquipItem item, EquipSlot slot, int index) { + var dye = Dyes!.FirstOrDefault(i => i.RowId == item.GetDye(index)); + if (ImGui.ColorButton($"{dye.Name} [{dye.RowId}]##{slot}_{index}", dye.ColorVector4, ImGuiColorEditFlags.NoBorder)) + OpenDyePicker(slot, index); + if (ImGui.IsItemClicked(ImGuiMouseButton.Right)) + SetDye(item, slot, index, 0); + } + + private unsafe static void SetDye(IEquipItem item, EquipSlot slot, int index, byte value) { + item.SetDye(index, value); + if (item is WeaponEquip wepEquip) + Target->Equip((int)slot, wepEquip); + else if (item is ItemEquip itemEquip) + Target->Equip(SlotToIndex(slot), itemEquip); + } + + public static void OpenDyePicker(EquipSlot slot, int index) { + SlotSelectDye = slot; + SelectDyeIndex = index; + } public static void CloseDyePicker() => SlotSelectDye = null; public static void OpenSetSelector() => DrawSetSelection = true; @@ -274,6 +323,28 @@ public unsafe static void DrawSelectorList(EquipSlot slot, object equipObj) ); } + private unsafe static void DrawGlassesSelector() { + if (Glasses == null) return; + + PopupSelect.HoverPopupWindow( + PopupSelect.HoverPopupWindowFlags.SelectorList | PopupSelect.HoverPopupWindowFlags.SearchBar, + Glasses.Where(x => x.RowId == 0 || !x.Name.IsNullOrEmpty()), + (e, input) => e.Where(i => i.Name.Contains(input, StringComparison.OrdinalIgnoreCase)), + (i, a) => ( // draw Line + ImGui.Selectable(i.Name, a), + ImGui.IsItemFocused() + ), + (i) => { // on Select + Target->SetGlasses((ushort)i.RowId); + }, + () => DrawGlassesSelection = false, + ref GlassesSearch, + "Glasses Select", + "##glasses_list", + "##glasses_search" + ); + } + public unsafe static void DrawSetSelectorList() { IEnumerable sets = Sets.FindSets(); @@ -307,7 +378,7 @@ public unsafe static void DrawSetSelectorList() private static int DyeLastSubOrder = -1; private const int DyePickerWidth = 485; - public static unsafe void DrawDyePicker(EquipSlot slot, object equipObj) + public static unsafe void DrawDyePicker(EquipSlot slot, object equipObj, int index) { PopupSelect.HoverPopupWindow( PopupSelect.HoverPopupWindowFlags.SearchBar @@ -318,13 +389,7 @@ public static unsafe void DrawDyePicker(EquipSlot slot, object equipObj) DrawDyePickerHeader, DrawDyePickerItem, (i) => { // on Select - if (equipObj is WeaponEquip wep) { - wep.Dye = (byte)i.RowId; - Target->Equip((int)slot, wep); - } else if (equipObj is ItemEquip item) { - item.Dye = (byte)i.RowId; - Target->Equip(SlotToIndex(slot), item); - } + SetDye((IEquipItem)equipObj, slot, index, (byte)i.RowId); }, CloseDyePicker, // on close ref DyeSearch, @@ -369,7 +434,7 @@ public static unsafe void DrawSetDyePicker() 12 // number of columns ); } - private static (bool, bool) DrawDyePickerItem(dynamic i, bool isActive) + private static (bool, bool) DrawDyePickerItem(Dye i, bool isActive) { bool isThisRealNewLine = PopupSelect.HoverPopupWindowIndexKey % PopupSelect.HoverPopupWindowColumns == 0; bool isThisANewShade = i.SubOrder == 1; @@ -400,8 +465,9 @@ private static (bool, bool) DrawDyePickerItem(dynamic i, bool isActive) return (selecting, ImGui.IsItemFocused()); } - private static void DrawDyePickerHeader(dynamic i) + private static void DrawDyePickerHeader(object obj) { + var i = (Dye)obj; // TODO: configuration to not show this var textSize = ImGui.CalcTextSize(i.Name); float dyeShowcaseWidth = (DyePickerWidth - textSize.X - (ImGui.GetStyle().ItemSpacing.X * 2)) / 2; @@ -416,11 +482,11 @@ private static void DrawDyePickerHeader(dynamic i) public class ItemCache : IDisposable { private CancellationTokenSource? _tokenSrc; - private ushort? IconId; + private int? IconId; public object? Equip; public Item? Item; - public TextureWrap? Icon; + public ISharedImmediateTexture? Icon; public ItemCache(object? equip, EquipSlot slot) => SetEquip(equip, slot); @@ -432,7 +498,7 @@ public void SetEquip(object? equip, EquipSlot slot) { _tokenSrc = new CancellationTokenSource(); Resolve(equip, slot, _tokenSrc.Token).ContinueWith(task => { if (task.Exception != null) - PluginLog.Error($"Error occurred while resolving item:\n{task.Exception}"); + Ktisis.Log.Error($"Error occurred while resolving item:\n{task.Exception}"); }, TaskContinuationOptions.OnlyOnFaulted); } @@ -445,22 +511,18 @@ private async Task Resolve(object? equip, EquipSlot slot, CancellationToken toke var newIconId = item?.Icon; if (newIconId != IconId) { - var newIcon = newIconId is ushort id ? Services.DataManager.GetImGuiTextureIcon(id, true) : null; - if (token.IsCancellationRequested) { - newIcon?.Dispose(); + var newIcon = newIconId is int id ? Services.Textures.GetFromGameIcon(id) : null; + if (token.IsCancellationRequested) return; - } IconId = newIconId; - Icon?.Dispose(); Icon = newIcon; } } public void Dispose() { - Icon?.Dispose(); Icon = null; } ~ItemCache() => Dispose(); } -} \ No newline at end of file +} diff --git a/Ktisis/Interface/Windows/ConfigGui.cs b/Ktisis/Interface/Windows/ConfigGui.cs index 1ee68ea59..1f797c411 100644 --- a/Ktisis/Interface/Windows/ConfigGui.cs +++ b/Ktisis/Interface/Windows/ConfigGui.cs @@ -1,10 +1,8 @@ using System; -using System.Collections.Generic; using System.Linq; -using System.Numerics; using System.Text; - -using ImGuiNET; +using System.Numerics; +using System.Collections.Generic; using Newtonsoft.Json; @@ -12,7 +10,9 @@ using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Game.ClientState.Keys; +using Dalamud.Bindings.ImGui; +using Ktisis.Helpers; using Ktisis.Util; using Ktisis.Overlay; using Ktisis.Localization; @@ -20,6 +20,7 @@ using Ktisis.Structs.Actor.Equip; using Ktisis.Structs.Actor.Equip.SetSources; using Ktisis.Interface.Components; +using Ktisis.Interop.Hooks; namespace Ktisis.Interface.Windows { internal static class ConfigGui { @@ -46,7 +47,7 @@ public static void Hide() { public static void Draw() { if (!Visible) { if (!_isSaved) { - PluginLog.Verbose("Saving config..."); + Ktisis.Log.Verbose("Saving config..."); Services.PluginInterface.SavePluginConfig(Ktisis.Configuration); _isSaved = true; } @@ -75,6 +76,8 @@ public static void Draw() { DrawInputTab(cfg); if (ImGui.BeginTabItem(Locale.GetString("Camera"))) DrawCameraTab(cfg); + if (ImGui.BeginTabItem(Locale.GetString("AutoSave"))) + DrawAutoSaveTab(cfg); if (ImGui.BeginTabItem(Locale.GetString("References"))) DrawReferencesTab(cfg); if (ImGui.BeginTabItem(Locale.GetString("Language"))) @@ -150,7 +153,7 @@ public static void DrawInterfaceTab(Configuration cfg) { var displayMultiplierInputs = cfg.TransformTableDisplayMultiplierInputs; if (ImGui.Checkbox(Locale.GetString("Show_speed_multipler_inputs"), ref displayMultiplierInputs)) cfg.TransformTableDisplayMultiplierInputs = displayMultiplierInputs; - + var showToolbar = cfg.ShowToolbar; if (ImGui.Checkbox("Show Experimental Toolbar", ref showToolbar)) cfg.ShowToolbar = showToolbar; @@ -174,13 +177,13 @@ public static void DrawInterfaceTab(Configuration cfg) { public static void DrawOverlayTab(Configuration cfg) { ImGui.Spacing(); - + var order = cfg.OrderBoneListByDistance; if (ImGui.Checkbox("Order bone list by distance from camera", ref order)) cfg.OrderBoneListByDistance = order; ImGui.Spacing(); - + if (ImGui.CollapsingHeader(Locale.GetString("Skeleton_lines_and_dots"), ImGuiTreeNodeFlags.DefaultOpen)) { ImGui.Separator(); var drawLines = cfg.DrawLinesOnSkeleton; @@ -202,11 +205,11 @@ public static void DrawOverlayTab(Configuration cfg) { var lineThickness = cfg.SkeletonLineThickness; if (ImGui.SliderFloat(Locale.GetString("Lines_thickness"), ref lineThickness, 0.01F, 15F, "%.1f")) cfg.SkeletonLineThickness = lineThickness; - + var lineOpacity = cfg.SkeletonLineOpacity; if (ImGui.SliderFloat(Locale.GetString("Lines_opacity"), ref lineOpacity, 0.01F, 1F, "%.2f")) cfg.SkeletonLineOpacity = lineOpacity; - + var lineOpacityWhileUsing = cfg.SkeletonLineOpacityWhileUsing; if (ImGui.SliderFloat(Locale.GetString("Lines_opacity_while_using"), ref lineOpacityWhileUsing, 0.01F, 1F, "%.2f")) cfg.SkeletonLineOpacityWhileUsing = lineOpacityWhileUsing; @@ -270,6 +273,62 @@ public static void DrawGizmoTab(Configuration cfg) { ImGui.EndTabItem(); } + // AutoSave + public static void DrawAutoSaveTab(Configuration cfg) { + var enableAutoSave = cfg.EnableAutoSave; + if (ImGui.Checkbox(Locale.GetString("Enable_auto_save"), ref enableAutoSave)) { + cfg.EnableAutoSave = enableAutoSave; + PoseHooks.AutoSave.UpdateSettings(); + } + + var clearOnExit = cfg.ClearAutoSavesOnExit; + if (ImGui.Checkbox(Locale.GetString("Clear_auto_saves_on_exit"), ref clearOnExit)) + cfg.ClearAutoSavesOnExit = clearOnExit; + + ImGui.Spacing(); + + var autoSaveInterval = cfg.AutoSaveInterval; + if (ImGui.SliderInt(Locale.GetString("Auto_save_interval"), ref autoSaveInterval, 10, 600, "%d s")) { + cfg.AutoSaveInterval = autoSaveInterval; + PoseHooks.AutoSave.UpdateSettings(); + } + + var autoSaveCount = cfg.AutoSaveCount; + if (ImGui.SliderInt(Locale.GetString("Auto_save_count"), ref autoSaveCount, 1, 20)) + cfg.AutoSaveCount = autoSaveCount; + + var autoSavePath = cfg.AutoSavePath; + if (ImGui.InputText(Locale.GetString("Auto_save_path"), ref autoSavePath, 256)) + cfg.AutoSavePath = autoSavePath; + + var autoSaveFormat = cfg.AutoSaveFormat; + if (ImGui.InputText(Locale.GetString("Auto_save_Folder_Name"), ref autoSaveFormat, 256)) + cfg.AutoSaveFormat = autoSaveFormat; + + ImGui.Text(Locale.GetString("Example_Folder_Name")); + ImGui.TextUnformatted(PathHelper.Replace(autoSaveFormat)); + + ImGui.Spacing(); + ImGui.BeginTable("AutoSaveFormatters", 2, ImGuiTableFlags.SizingFixedFit | ImGuiTableFlags.Borders| ImGuiTableFlags.PadOuterX); + + ImGui.TableSetupScrollFreeze(0, 1); + ImGui.TableSetupColumn(Locale.GetString("Formatter")); + ImGui.TableSetupColumn(Locale.GetString("Example_Value")); + ImGui.TableHeadersRow(); + + foreach ((var replaceKey, var replaceFunc) in PathHelper.Replacers) { + ImGui.TableNextRow(); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(replaceKey); + ImGui.TableNextColumn(); + ImGui.TextUnformatted(replaceFunc()); + } + + ImGui.EndTable(); + + ImGui.EndTabItem(); + } + // Language public static void DrawLanguageTab(Configuration cfg) { @@ -421,11 +480,11 @@ private static void DrawCameraTab(Configuration cfg) { var shiftMuli = cfg.FreecamShiftMuli; if (ImGui.DragFloat("Fast speed multiplier", ref shiftMuli, 0.001f, 0, 10)) cfg.FreecamShiftMuli = shiftMuli; - + var ctrlMuli = cfg.FreecamCtrlMuli; if (ImGui.DragFloat("Slow speed multiplier", ref ctrlMuli, 0.001f, 0, 10)) cfg.FreecamCtrlMuli = ctrlMuli; - + var upDownMuli = cfg.FreecamUpDownMuli; if (ImGui.DragFloat("Up/down speed multiplier", ref upDownMuli, 0.001f, 0, 10)) cfg.FreecamUpDownMuli = upDownMuli; @@ -437,7 +496,7 @@ private static void DrawCameraTab(Configuration cfg) { cfg.FreecamSensitivity = camSens; ImGui.Spacing(); - + ImGui.PushItemWidth(ImGui.GetFontSize() * 8); ImGui.Text("Work camera keybinds"); @@ -450,17 +509,17 @@ private static void DrawCameraTab(Configuration cfg) { KeybindEdit.Draw("Down##WCDown", cfg.FreecamDown); ImGui.Spacing(); - + KeybindEdit.Draw("Fast speed modifier##WCUp", cfg.FreecamFast); KeybindEdit.Draw("Slow speed modifier##WCUp", cfg.FreecamSlow); ImGui.PopItemWidth(); - + ImGui.EndTabItem(); } // Data - + public static void DrawDataTab(Configuration cfg) { ImGui.Spacing(); var validGlamPlatesFound = GlamourDresser.CountValid(); @@ -619,7 +678,7 @@ public static void DrawReferencesTab(Configuration cfg) { public static bool TryChangeReference(Configuration cfg, int key, string newPath) { try { - var texture = Ktisis.UiBuilder.LoadImage(newPath); + var texture = Services.Textures.GetFromFile(newPath); cfg.References[key] = new ReferenceInfo { Path = newPath, Showing = true, diff --git a/Ktisis/Interface/Windows/Information.cs b/Ktisis/Interface/Windows/Information.cs index e4d9380a4..4288c97ae 100644 --- a/Ktisis/Interface/Windows/Information.cs +++ b/Ktisis/Interface/Windows/Information.cs @@ -1,7 +1,7 @@ using System; using System.Numerics; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Helpers; @@ -44,7 +44,7 @@ public static void Draw() { ImGui.PushStyleColor(ImGuiCol.Button, DiscordColor); if (ImGui.Button("Join us on Discord", ButtonSize)) - Common.OpenBrowser("https://discord.gg/ktisis"); + Common.OpenBrowser("https://discord.gg/kUG3W8B8Ny"); ImGui.PopStyleColor(); ImGui.PushStyleColor(ImGuiCol.Button, KofiColor); diff --git a/Ktisis/Interface/Windows/References.cs b/Ktisis/Interface/Windows/References.cs index 93d44425b..a21e710a5 100644 --- a/Ktisis/Interface/Windows/References.cs +++ b/Ktisis/Interface/Windows/References.cs @@ -3,13 +3,14 @@ using System.Linq; using System.Numerics; -using ImGuiNET; -using ImGuiScene; +using Dalamud.Interface.Textures; +using Dalamud.Interface.Textures.TextureWraps; +using Dalamud.Bindings.ImGui; namespace Ktisis.Interface.Windows { internal static class References { /** Maps file paths to loaded textures. */ - public static Dictionary Textures = new(); + public static Dictionary Textures = new(); // Draw @@ -23,9 +24,11 @@ public static void Draw() { public static void DrawReferenceWindow(Configuration cfg, int key, ReferenceInfo reference) { if (!reference.Showing) return; if (reference.Path is not string path) return; - if (!Textures.TryGetValue(path, out var texture)) + if (!Textures.TryGetValue(path, out var sharedTex)) return; + var texture = sharedTex.GetWrapOrEmpty(); + var size = new Vector2(texture.Width, texture.Height); ImGui.SetNextWindowSize(size, ImGuiCond.FirstUseEver); ImGui.SetNextWindowSizeConstraints(new Vector2(50, 50), size); @@ -39,7 +42,7 @@ public static void DrawReferenceWindow(Configuration cfg, int key, ReferenceInfo if (ImGui.Begin($"{reference.Path}##reference{key}", flags)) { var scaled = new Vector2(ImGui.GetWindowWidth(), texture.Height * ImGui.GetWindowWidth() / texture.Width ); var tintColor = new Vector4(1f, 1f, 1f, cfg.ReferenceAlpha); - ImGui.Image(texture.ImGuiHandle, scaled, Vector2.Zero, Vector2.One, tintColor); + ImGui.Image(texture.Handle, scaled, Vector2.Zero, Vector2.One, tintColor); } ImGui.PopStyleVar(2); ImGui.End(); @@ -53,7 +56,7 @@ public static bool LoadReference(KeyValuePair reference) { var path = reference.Value.Path; try { if (path == null) return false; - Textures[path] = Ktisis.UiBuilder.LoadImage(path); + Textures[path] = Services.Textures.GetFromFile(path); return true; } catch (Exception e) { Logger.Error(e, "Failed to load reference image {0}", path ?? "null"); @@ -66,7 +69,6 @@ public static void DisposeUnreferencedTextures(Configuration cfg) { var paths = cfg.References.Values.Select(x => x.Path ?? ""); var unloadPaths = loadedPaths.Except(paths); foreach (var path in unloadPaths) { - Textures[path].Dispose(); Textures.Remove(path); } } diff --git a/Ktisis/Interface/Windows/Toolbar/AdvancedWindow.cs b/Ktisis/Interface/Windows/Toolbar/AdvancedWindow.cs index 0c46e8178..f74ee2a87 100644 --- a/Ktisis/Interface/Windows/Toolbar/AdvancedWindow.cs +++ b/Ktisis/Interface/Windows/Toolbar/AdvancedWindow.cs @@ -1,6 +1,6 @@ using System.Numerics; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Structs.Actor; using Ktisis.Interop.Hooks; diff --git a/Ktisis/Interface/Windows/Toolbar/BonesWindow.cs b/Ktisis/Interface/Windows/Toolbar/BonesWindow.cs index 1078fccb9..805e7bd9e 100644 --- a/Ktisis/Interface/Windows/Toolbar/BonesWindow.cs +++ b/Ktisis/Interface/Windows/Toolbar/BonesWindow.cs @@ -1,8 +1,7 @@ using System.Numerics; using Dalamud.Interface; - -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Interface.Components; using Ktisis.Structs.Actor; diff --git a/Ktisis/Interface/Windows/Toolbar/ImportExportWindow.cs b/Ktisis/Interface/Windows/Toolbar/ImportExportWindow.cs index 2a725c66a..5433f7ac4 100644 --- a/Ktisis/Interface/Windows/Toolbar/ImportExportWindow.cs +++ b/Ktisis/Interface/Windows/Toolbar/ImportExportWindow.cs @@ -1,6 +1,6 @@ using System.Numerics; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Structs.Actor; diff --git a/Ktisis/Interface/Windows/Toolbar/ToolbarWindow.cs b/Ktisis/Interface/Windows/Toolbar/ToolbarWindow.cs index 5c3a46ba3..efcc25177 100644 --- a/Ktisis/Interface/Windows/Toolbar/ToolbarWindow.cs +++ b/Ktisis/Interface/Windows/Toolbar/ToolbarWindow.cs @@ -2,9 +2,8 @@ using Dalamud.Interface; -using ImGuiNET; - -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; using Ktisis.History; using Ktisis.Interface.Components; @@ -133,11 +132,11 @@ public static void Draw() { public static void DrawMainButtons() { // Operations - ControlButtons.ButtonChangeOperation(OPERATION.TRANSLATE, IconsPool.Position); + ControlButtons.ButtonChangeOperation(ImGuizmoOperation.Translate, IconsPool.Position); ImGui.SameLine(); - ControlButtons.ButtonChangeOperation(OPERATION.ROTATE, IconsPool.Rotation); + ControlButtons.ButtonChangeOperation(ImGuizmoOperation.Rotate, IconsPool.Rotation); ImGui.SameLine(); - ControlButtons.ButtonChangeOperation(OPERATION.SCALE, IconsPool.Scale); + ControlButtons.ButtonChangeOperation(ImGuizmoOperation.Scale, IconsPool.Scale); ImGui.SameLine(); ControlButtons.VerticalAlignTextOnButtonSize(0.9f); if (GuiHelpers.IconButtonTooltip(IconsPool.DownMore, "Show transform table ")) { @@ -156,8 +155,8 @@ public static void DrawMainButtons() { ImGui.SameLine(0, ImGui.GetFontSize()); // Extra Options var gizmoMode = Ktisis.Configuration.GizmoMode; - if (GuiHelpers.IconButtonTooltip(gizmoMode == MODE.WORLD ? FontAwesomeIcon.Globe : FontAwesomeIcon.Home, "Local / World orientation mode switch.", ControlButtons.ButtonSize)) - Ktisis.Configuration.GizmoMode = gizmoMode == MODE.WORLD ? MODE.LOCAL : MODE.WORLD; + if (GuiHelpers.IconButtonTooltip(gizmoMode == ImGuizmoMode.World ? FontAwesomeIcon.Globe : FontAwesomeIcon.Home, "Local / World orientation mode switch.", ControlButtons.ButtonSize)) + Ktisis.Configuration.GizmoMode = gizmoMode == ImGuizmoMode.World ? ImGuizmoMode.Local : ImGuizmoMode.World; ImGui.SameLine(); diff --git a/Ktisis/Interface/Windows/Toolbar/TransformWindow.cs b/Ktisis/Interface/Windows/Toolbar/TransformWindow.cs index 6ef4093e0..613fa32ae 100644 --- a/Ktisis/Interface/Windows/Toolbar/TransformWindow.cs +++ b/Ktisis/Interface/Windows/Toolbar/TransformWindow.cs @@ -1,6 +1,6 @@ using System.Numerics; -using ImGuiNET; +using Dalamud.Bindings.ImGui; using Ktisis.Interface.Components; using Ktisis.Overlay; diff --git a/Ktisis/Interface/Windows/Workspace/EditGaze.cs b/Ktisis/Interface/Windows/Workspace/EditGaze.cs index 3a3f115a5..9c1b819a6 100644 --- a/Ktisis/Interface/Windows/Workspace/EditGaze.cs +++ b/Ktisis/Interface/Windows/Workspace/EditGaze.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; -using ImGuiNET; -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; using Dalamud.Interface; using Dalamud.Interface.Components; @@ -13,7 +13,7 @@ namespace Ktisis.Interface.Windows.Workspace { public static class EditGaze { - public static Dictionary? ActorControl = null; // ObjectID : ActorGaze + public static Dictionary? ActorControl = null; // ObjectID : ActorGaze public static bool IsLinked { get => Ktisis.Configuration.LinkedGaze; @@ -115,7 +115,7 @@ public unsafe static bool DrawGaze(Actor* target, ref Gaze gaze, GazeControl typ if (gizmo != null) { if (enabled) { - gizmo.ForceOp = OPERATION.TRANSLATE; + gizmo.ForceOp = ImGuizmoOperation.Translate; result |= gizmo.Draw(ref gaze.Pos); } else { OverlayWindow.DeselectGizmo(); diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs index 2335f4234..7e1b8e7da 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/ActorTab.cs @@ -3,8 +3,10 @@ using Dalamud.Interface; using Dalamud.Interface.Components; using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Interface.Utility.Raii; +using Dalamud.Bindings.ImGui; -using ImGuiNET; +using GLib.Widgets; using Ktisis.Data.Files; using Ktisis.Data.Serialization; @@ -12,14 +14,16 @@ using Ktisis.Structs.Actor; using Ktisis.Interface.Components; using Ktisis.Interface.Windows.ActorEdit; +using Ktisis.Interop; +using Ktisis.Structs.Actor.State; namespace Ktisis.Interface.Windows.Workspace.Tabs { public static class ActorTab { - public unsafe static void Draw(GameObject target) { - var cfg = Ktisis.Configuration; - + private static readonly NpcImport _npcImport = new(); + + public unsafe static void Draw(IGameObject target) { var actor = (Actor*)target.Address; - if (actor->Model == null) return; + if (actor == null) return; // Actor details @@ -149,10 +153,30 @@ public unsafe static void ImportExportChara(Actor* actor) { } ); } + + ImGui.Spacing(); + if (ImGui.Button("Import NPC")) + _npcImport.Open(); + + if (IpcChecker.IsGlamourerActive()) { + using var _ = ImRaii.PushColor(ImGuiCol.Button, 0); + + ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X); + + Buttons.IconButtonTooltip( + FontAwesomeIcon.ExclamationCircle, + "Glamourer heavily interferes with edits made by other tools.\n" + + "You may need to disable it for this to function correctly!" + ); + } if (isUseless) ImGui.EndDisabled(); ImGui.Spacing(); + if (ImGui.Button("Revert Changes")) + ActorStateWatcher.RevertToOriginal(actor); + + _npcImport.Draw(mode); } } -} \ No newline at end of file +} diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs index 8d58a95cf..5646b7727 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/CameraTab.cs @@ -1,10 +1,9 @@ using System; using System.Numerics; -using ImGuiNET; - using Dalamud.Interface; using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Bindings.ImGui; using Ktisis.Util; using Ktisis.Camera; @@ -167,7 +166,7 @@ private unsafe static void DrawTargetLock() { var isFreecam = camera.WorkCamera != null; - var tarLock = camera.GetOrbitTarget() is GameObject actor ? (Actor*)actor.Address : null; + var tarLock = camera.GetOrbitTarget() is IGameObject actor ? (Actor*)actor.Address : null; var isTarLocked = tarLock != null || isFreecam; var target = tarLock != null ? tarLock : Ktisis.Target; @@ -318,7 +317,10 @@ private unsafe static void DrawControls() { if (ImGui.Checkbox("Delimit camera", ref delimit)) { var max = delimit ? 350 : 20; gposeCam->DistanceMax = max; + gposeCam->DistanceMin = delimit ? 0 : 1.5f; gposeCam->Distance = Math.Clamp(gposeCam->Distance, 0, max); + gposeCam->YMin = delimit ? 1.5f : 1.25f; + gposeCam->YMax = delimit ? -1.5f : -1.4f; } ImGui.SameLine(); @@ -336,4 +338,4 @@ private static void PrepareIconTooltip(FontAwesomeIcon icon, string tooltip, flo ImGui.SetCursorPosX(posCursor); } } -} \ No newline at end of file +} diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs index 75e37a0f4..a3d8e9f14 100644 --- a/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs +++ b/Ktisis/Interface/Windows/Workspace/Tabs/PoseTab.cs @@ -1,18 +1,13 @@ -using System.IO; - -using ImGuiNET; - using Dalamud.Interface; using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Bindings.ImGui; using Ktisis.Util; using Ktisis.Overlay; +using Ktisis.Helpers; using Ktisis.Structs.Actor; using Ktisis.Structs.Poses; -using Ktisis.Data.Files; -using Ktisis.Data.Serialization; using Ktisis.Interface.Components; -using Ktisis.Interop.Hooks; namespace Ktisis.Interface.Windows.Workspace.Tabs { public static class PoseTab { @@ -20,13 +15,10 @@ public static class PoseTab { public static PoseContainer _TempPose = new(); - public unsafe static void Draw(GameObject target) { + public unsafe static void Draw(IGameObject target) { var cfg = Ktisis.Configuration; - if (target == null) return; - var actor = (Actor*)target.Address; - if (actor->Model == null) return; // Extra Controls ControlButtons.DrawExtra(); @@ -37,26 +29,30 @@ public unsafe static void Draw(GameObject target) { if (ImGui.Checkbox("Parenting", ref parent)) cfg.EnableParenting = parent; - // Transform table - TransformTable(actor); - - ImGui.Spacing(); + if (actor->Model != null) { + // Transform table + TransformTable(actor); - // Bone categories - if (ImGui.CollapsingHeader("Bone Categories")) { + ImGui.Spacing(); - if (!Categories.DrawToggleList(cfg)) { - ImGui.Text("No bone found."); - ImGui.Text("Show Skeleton ("); - ImGui.SameLine(); - GuiHelpers.Icon(FontAwesomeIcon.EyeSlash); - ImGui.SameLine(); - ImGui.Text(") to fill this."); + // Bone categories + if (ImGui.CollapsingHeader("Bone Categories")) { + if (!Categories.DrawToggleList(cfg)) { + ImGui.Text("No bone found."); + ImGui.Text("Show Skeleton ("); + ImGui.SameLine(); + GuiHelpers.Icon(FontAwesomeIcon.EyeSlash); + ImGui.SameLine(); + ImGui.Text(") to fill this."); + } } - } - // Bone tree - BoneTree.Draw(actor); + // Bone tree + BoneTree.Draw(actor); + } else { + ImGui.Text("Target actor has no valid skeleton!"); + ImGui.Spacing(); + } // Import & Export if (ImGui.CollapsingHeader("Import & Export")) @@ -71,17 +67,17 @@ public unsafe static void Draw(GameObject target) { } public static unsafe void DrawAdvancedDebugOptions(Actor* actor) { - if(ImGui.Button("Reset Current Pose") && actor->Model != null) - actor->Model->SyncModelSpace(); - - if(ImGui.Button("Set to Reference Pose") && actor->Model != null) - actor->Model->SyncModelSpace(true); - - if(ImGui.Button("Store Pose") && actor->Model != null) - _TempPose.Store(actor->Model->Skeleton); - ImGui.SameLine(); - if(ImGui.Button("Apply Pose") && actor->Model != null) - _TempPose.Apply(actor->Model->Skeleton); + if (actor->Model != null) { + if (ImGui.Button("Reset Current Pose")) + actor->Model->SyncModelSpace(); + if (ImGui.Button("Set to Reference Pose")) + actor->Model->SyncModelSpace(true); + if (ImGui.Button("Store Pose")) + _TempPose.Store(actor->Model->Skeleton); + ImGui.SameLine(); + if (ImGui.Button("Apply Pose")) + _TempPose.Apply(actor->Model->Skeleton); + } if(ImGui.Button("Force Redraw")) actor->Redraw(); @@ -176,60 +172,11 @@ public unsafe static void ImportExportPose(Actor* actor) { if (ImGui.Button("Import##ImportExportPose")) { KtisisGui.FileDialogManager.OpenFileDialog( "Importing Pose", - "Pose Files (.pose){.pose}", + "Pose Files{.pose,.cmp}", (success, path) => { if (!success) return; - var content = File.ReadAllText(path[0]); - var pose = JsonParser.Deserialize(content); - if (pose == null) return; - - if (actor->Model == null) return; - - var skeleton = actor->Model->Skeleton; - if (skeleton == null) return; - - pose.ConvertLegacyBones(); - - // Ensure posing is enabled. - if (!PoseHooks.PosingEnabled && !PoseHooks.AnamPosingEnabled) - PoseHooks.EnablePosing(); - - if (pose.Bones != null) { - for (var p = 0; p < skeleton->PartialSkeletonCount; p++) { - switch (p) { - case 0: - if (!body) continue; - break; - case 1: - if (!face) continue; - break; - } - - pose.Bones.ApplyToPartial(skeleton, p, trans); - } - } - - if (modes.HasFlag(PoseMode.Weapons)) { - var wepTrans = trans; - if (Ktisis.Configuration.PositionWeapons) - wepTrans |= PoseTransforms.Position; - - if (pose.MainHand != null) { - var skele = actor->GetWeaponSkeleton(WeaponSlot.MainHand); - if (skele != null) pose.MainHand.Apply(skele, wepTrans); - } - - if (pose.OffHand != null) { - var skele = actor->GetWeaponSkeleton(WeaponSlot.OffHand); - if (skele != null) pose.OffHand.Apply(skele, wepTrans); - } - - if (pose.Prop != null) { - var skele = actor->GetWeaponSkeleton(WeaponSlot.Prop); - if (skele != null) pose.Prop.Apply(skele, wepTrans); - } - } + PoseHelpers.ImportPose(actor, path, Ktisis.Configuration.PoseMode); }, 1, null @@ -246,44 +193,7 @@ public unsafe static void ImportExportPose(Actor* actor) { (success, path) => { if (!success) return; - var model = actor->Model; - if (model == null) return; - - var skeleton = model->Skeleton; - if (skeleton == null) return; - - var pose = new PoseFile(); - - pose.Position = model->Position; - pose.Rotation = model->Rotation; - pose.Scale = model->Scale; - - pose.Bones = new PoseContainer(); - pose.Bones.Store(skeleton); - - if (modes.HasFlag(PoseMode.Weapons)) { - var main = actor->GetWeaponSkeleton(WeaponSlot.MainHand); - if (main != null) { - pose.MainHand = new PoseContainer(); - pose.MainHand.Store(main); - } - - var off = actor->GetWeaponSkeleton(WeaponSlot.OffHand); - if (off != null) { - pose.OffHand = new PoseContainer(); - pose.OffHand.Store(off); - } - - var prop = actor->GetWeaponSkeleton(WeaponSlot.Prop); - if (prop != null) { - pose.Prop = new PoseContainer(); - pose.Prop.Store(prop); - } - } - - var json = JsonParser.Serialize(pose); - using (var file = new StreamWriter(path)) - file.Write(json); + PoseHelpers.ExportPose(actor, path, Ktisis.Configuration.PoseMode); } ); } @@ -291,4 +201,4 @@ public unsafe static void ImportExportPose(Actor* actor) { ImGui.Spacing(); } } -} \ No newline at end of file +} diff --git a/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs new file mode 100644 index 000000000..78bce2790 --- /dev/null +++ b/Ktisis/Interface/Windows/Workspace/Tabs/WorldTab.cs @@ -0,0 +1,204 @@ +using System; +using System.Numerics; +using System.Threading; +using System.Collections.Generic; +using System.Linq; + +using FFXIVClientStructs.FFXIV.Client.Graphics.Environment; + +using Dalamud.Bindings.ImGui; + +using Ktisis.Env; +using Ktisis.Structs.Env; + +namespace Ktisis.Interface.Windows.Workspace.Tabs { + public static class WorldTab { + // Data + + private static object AsyncLock = new(); + + private static CancellationTokenSource? TokenSource; + + private static ushort TerritoryType = ushort.MaxValue; + private static List Weather = new(); + + // UI Draw + + private static float LabelMargin = 0.0f; + + private const string TimeLabel = "Time"; + private const string WeatherLabel = "Weather"; + + private static void CheckData() { + var territory = Services.ClientState.TerritoryType; + if (territory == TerritoryType) return; + TerritoryType = territory; + + var source = new CancellationTokenSource(); + var token = source.Token; + TokenSource?.Cancel(); + TokenSource = source; + + var weather = EnvService.GetEnvWeatherIds(); + EnvService.GetWeatherIcons(weather, token).ContinueWith(result => { + if (result.Exception != null) { + Ktisis.Log.Error($"Failed to load weather data:\n{result.Exception}"); + return; + } else if (result.IsCanceled) return; + + lock (AsyncLock) { + Weather = result.Result.Prepend(WeatherInfo.Default).ToList(); + TokenSource = null; + } + }, token); + + Logger.Information($"Weathers: {string.Join(", ", weather)}"); + } + + public static void Draw() { + CheckData(); + + LabelMargin = Math.Max( + ImGui.CalcTextSize(TimeLabel).X, + ImGui.CalcTextSize(WeatherLabel).X + ); + + ImGui.Spacing(); + + DrawControls(); + + ImGui.EndTabItem(); + } + + private unsafe static void DrawControls() { + var env = (EnvManagerEx*)EnvManager.Instance(); + if (env == null) return; + + var time = EnvService.TimeOverride ?? env->Time; + var sky = EnvService.SkyOverride ?? env->SkyId; + + var width = ImGui.GetContentRegionAvail().X - LabelMargin; + var spacing = ImGui.GetStyle().ItemInnerSpacing.X; + + const float MaxTime = 86400; + + var dateTime = new DateTime().AddSeconds(time); + ImGui.SetNextItemWidth(width * (3f/4f) - spacing * 2); + if (ImGui.SliderFloat($"##{TimeLabel}_Slider", ref time, 0, 86400, dateTime.ToShortTimeString(), ImGuiSliderFlags.NoInput)) + EnvService.TimeOverride = time % MaxTime; + + var timeMins = time / 60f; + ImGui.SameLine(0, spacing); + ImGui.SetNextItemWidth(width * (1f/4f)); + if (ImGui.InputFloat(TimeLabel, ref timeMins, 0, 0, "%.0f")) + EnvService.TimeOverride = (timeMins * 60f) % MaxTime; + + ImGui.Spacing(); + + lock (AsyncLock) { + var disable = Weather.Count <= 1; + ImGui.BeginDisabled(disable); + if (DrawWeatherSelect(env->ActiveWeather, out var clickedId)) + env->ActiveWeather = (byte)clickedId; + if (disable) + ImGui.Text("Weather unavailable in this area."); + ImGui.EndDisabled(); + } + + ImGui.Spacing(); + + var skyId = EnvService.SkyOverride ?? env->SkyId; + if (DrawSkySelect(ref skyId)) + EnvService.SkyOverride = skyId; + + ImGui.Spacing(); + + var waterFrozen = EnvService.FreezeWater ?? false; + if (ImGui.Checkbox("Freeze Water", ref waterFrozen)) { + EnvService.FreezeWater = waterFrozen; + } + } + + // Weather + + private static readonly Vector2 WeatherIconSize = new(28, 28); + + private static bool DrawWeatherSelect(int current, out int clickedId) { + var currentInfo = Weather.Find(w => w.RowId == current); + + var click = false; + clickedId = 0; + + var style = ImGui.GetStyle(); + var padding = style.FramePadding.Y + WeatherIconSize.Y - ImGui.GetFrameHeight(); + + ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X - style.ItemInnerSpacing.X - LabelMargin); + ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, style.FramePadding with { Y = padding }); + if (ImGui.BeginCombo(WeatherLabel, currentInfo != null ? "##" : "Unknown")) { + foreach (var weatherInfo in Weather) { + if (ImGui.Selectable($"##EnvWeather{weatherInfo.RowId}", weatherInfo.RowId == current, ImGuiSelectableFlags.DontClosePopups)) { + click = true; + clickedId = (int)weatherInfo.RowId; + } + DrawWeatherLabel(weatherInfo, true); + } + + ImGui.EndCombo(); + } + + if (currentInfo != null) + DrawWeatherLabel(currentInfo); + + ImGui.PopStyleVar(); + + return click; + } + + private static void DrawWeatherLabel(WeatherInfo weather, bool adjustPad = false) { + var style = ImGui.GetStyle(); + var height = ImGui.GetFrameHeight(); + + ImGui.SameLine(0, 0); + ImGui.SetCursorPosX(ImGui.GetCursorStartPos().X + style.ItemInnerSpacing.X); + + var posY = ImGui.GetCursorPos().Y + height / 2 - WeatherIconSize.Y / 2; + if (adjustPad) posY -= style.FramePadding.Y; + ImGui.SetCursorPosY(posY); + + ImGui.Image(weather.Icon?.GetWrapOrEmpty().Handle ?? 0, WeatherIconSize); + ImGui.SameLine(); + + ImGui.Text(weather.Name); + } + + // Sky + + private static bool DrawSkySelect(ref uint skyId) { + EnvService.GetSkyImage(skyId); + + var innerSpace = ImGui.GetStyle().ItemInnerSpacing.Y; + + var height = ImGui.GetFrameHeight() * 2 + innerSpace; + var buttonSize = new Vector2(height, height); + + lock (EnvService.SkyLock) { + if (EnvService.SkyTex != null) + ImGui.Image(EnvService.SkyTex.GetWrapOrEmpty().Handle, buttonSize); + } + + ImGui.SameLine(); + + ImGui.SetCursorPosY(ImGui.GetCursorPosY() + innerSpace); + + ImGui.BeginGroup(); + ImGui.Text("Sky Texture"); + var sky = (int)skyId; + ImGui.SetNextItemWidth(ImGui.CalcItemWidth() - (ImGui.GetCursorPosX() - ImGui.GetCursorStartPos().X) - LabelMargin); + var changed = ImGui.InputInt("##SkyId", ref sky); + if (changed) skyId = (uint)sky; + ImGui.EndGroup(); + + return changed; + } + } +} diff --git a/Ktisis/Interface/Windows/Workspace/Workspace.cs b/Ktisis/Interface/Windows/Workspace/Workspace.cs index afe74eb85..0a73f965b 100644 --- a/Ktisis/Interface/Windows/Workspace/Workspace.cs +++ b/Ktisis/Interface/Windows/Workspace/Workspace.cs @@ -1,9 +1,8 @@ using System.Numerics; -using ImGuiNET; - using Dalamud.Interface; using Dalamud.Game.ClientState.Objects.Types; +using Dalamud.Bindings.ImGui; using Ktisis.Util; using Ktisis.Overlay; @@ -90,12 +89,12 @@ public static void Draw() { if (ImGui.BeginTabBar(Locale.GetString("Workspace"))) { if (ImGui.BeginTabItem(Locale.GetString("Actor"))) ActorTab.Draw(target); - /*if (ImGui.BeginTabItem(Locale.GetString("Scene"))) - SceneTab();*/ if (ImGui.BeginTabItem(Locale.GetString("Pose"))) PoseTab.Draw(target); if (ImGui.BeginTabItem(Locale.GetString("Camera"))) CameraTab.Draw(); + if (ImGui.BeginTabItem("World")) + WorldTab.Draw(); } } @@ -105,7 +104,7 @@ public static void Draw() { // Selection details - private unsafe static void SelectInfo(GameObject target) { + private unsafe static void SelectInfo(IGameObject target) { var actor = (Actor*)target.Address; var select = Skeleton.BoneSelect; diff --git a/Ktisis/Interop/Alloc.cs b/Ktisis/Interop/Alloc.cs index ab4a8e3ce..3efd6579c 100644 --- a/Ktisis/Interop/Alloc.cs +++ b/Ktisis/Interop/Alloc.cs @@ -2,10 +2,9 @@ using System.Numerics; using System.Runtime.InteropServices; -using Dalamud.Logging; - -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.System.Memory; +using FFXIVClientStructs.Havok.Common.Base.Math.Matrix; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; namespace Ktisis.Interop { internal static class Alloc { @@ -46,7 +45,6 @@ internal unsafe GameAlloc(ulong align = 16) => Address = (nint)IMemorySpace.GetDefaultSpace()->Malloc(align); public unsafe void Dispose() { - PluginLog.Debug($"Disposing GameAlloc<{typeof(T)}>"); if (Disposed) return; IMemorySpace.Free(Data); // Free our allocated memory. Disposed = true; diff --git a/Ktisis/Interop/Hooks/ActorHooks.cs b/Ktisis/Interop/Hooks/ActorHooks.cs index 4a6b84f88..f126a733c 100644 --- a/Ktisis/Interop/Hooks/ActorHooks.cs +++ b/Ktisis/Interop/Hooks/ActorHooks.cs @@ -18,13 +18,13 @@ internal unsafe static IntPtr ControlGaze(nint a1) { EditGaze.Apply(actor); return ControlGazeHook.Original(a1); } - + // Init & Dispose - internal unsafe static void Init() { - var controlGaze = Services.SigScanner.ScanText("40 53 41 54 41 55 48 81 EC ?? ?? ?? ?? 48 8B D9"); - ControlGazeHook = Hook.FromAddress(controlGaze, ControlGaze); - ControlGazeHook.Enable(); + internal static void Init() { + var controlGaze = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 83 C3 08 48 83 EF 01 75 CF"); + ControlGazeHook = Services.Hooking.HookFromAddress(controlGaze, ControlGaze); + ControlGazeHook.Enable(); } internal static void Dispose() { diff --git a/Ktisis/Interop/Hooks/CameraHooks.cs b/Ktisis/Interop/Hooks/CameraHooks.cs index bc5323e82..2079e3138 100644 --- a/Ktisis/Interop/Hooks/CameraHooks.cs +++ b/Ktisis/Interop/Hooks/CameraHooks.cs @@ -2,11 +2,11 @@ using System.Runtime.InteropServices; using Dalamud.Hooking; -using Dalamud.Logging; using FFXIVClientStructs.FFXIV.Common.Math; using GameCamera = FFXIVClientStructs.FFXIV.Client.Game.Camera; using SceneCamera = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.Camera; +using RenderCamera = FFXIVClientStructs.FFXIV.Client.Graphics.Render.Camera; using Ktisis.Camera; using Ktisis.Structs.FFXIV; @@ -39,9 +39,9 @@ private unsafe static void EndOverride() { // Camera control - private delegate nint ControlDelegate(nint a1); + private delegate bool ControlDelegate(nint a1); private static Hook ControlHook = null!; - private unsafe static nint ControlDetour(nint a1) { + private unsafe static bool ControlDetour(nint a1) { StartOverride(); var exec = ControlHook.Original(a1); EndOverride(); @@ -58,20 +58,37 @@ private unsafe static nint ControlDetour(nint a1) { camera->LookAtVector += newPos - curPos; } } catch (Exception e) { - PluginLog.Error(e.ToString()); + Ktisis.Log.Error(e.ToString()); DisableHooks(); } return exec; } + // Pre-update + + private delegate nint PreUpdateDelegate(nint a1); + private static Hook PreUpdateHook = null!; + private unsafe static nint PreUpdateDetour(nint a1) { + StartOverride(); + var exec = PreUpdateHook.Original(a1); + EndOverride(); + return exec; + } + // Freecam + private unsafe delegate Matrix4x4* LoadMatrixDelegate(RenderCamera* camera, Matrix4x4* matrix, int a3, int a4); + private static LoadMatrixDelegate LoadMatrix = null!; + private unsafe delegate Matrix4x4* CalcViewMatrixDelegate(SceneCamera* camera); private static Hook CalcViewMatrixHook = null!; private unsafe static Matrix4x4* CalcViewMatrixDetour(SceneCamera* camera) { + var exec = CalcViewMatrixHook.Original(camera); + var freecam = CameraService.GetFreecam(); - if (freecam == null || freecam.WorkCamera == null) goto retn; + if (freecam == null || freecam.WorkCamera == null) + return exec; try { var active = Services.Camera->GetActiveCamera(); @@ -82,14 +99,14 @@ private unsafe static nint ControlDetour(nint a1) { var matrix = freecam.WorkCamera.Update(active->FoV * Math.Abs(1 + zoom)); *tarMatrix = matrix; - return tarMatrix; + LoadMatrix(camera->RenderCamera, tarMatrix, 0, 0); } } catch (Exception e) { - PluginLog.Error(e.ToString()); + Ktisis.Log.Error(e.ToString()); DisableHooks(); } - retn: return CalcViewMatrixHook.Original(camera); + return exec; } // GetActiveCamera @@ -163,6 +180,7 @@ internal static void SetEnabled(bool enabled) { private static void EnableHooks() { TargetHook.Enable(); ControlHook.Enable(); + PreUpdateHook.Enable(); ActiveCamHook.Enable(); CameraEventHook.Enable(); CameraUiHook.Enable(); @@ -174,6 +192,7 @@ private static void EnableHooks() { private static void DisableHooks() { TargetHook.Disable(); ControlHook.Disable(); + PreUpdateHook.Disable(); ActiveCamHook.Disable(); CameraEventHook.Disable(); CameraUiHook.Disable(); @@ -187,36 +206,43 @@ private static void DisableHooks() { internal unsafe static void Init() { // Native methods - var ctorAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? EB 03 48 8B C7 45 33 C0 48 89 03"); + var ctorAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? EB 03 48 8B C6 45 33 C0 48 89 07"); GameCamera_Ctor = Marshal.GetDelegateForFunctionPointer(ctorAddr); // Hooks var camCtrlAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 83 3D ?? ?? ?? ?? ?? 74 0C"); - ControlHook = Hook.FromAddress(camCtrlAddr, ControlDetour); - - var actCamAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? F7 80"); - ActiveCamHook = Hook.FromAddress(actCamAddr, GetActiveCamDetour); - - var camEventAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F0 EB 34"); - CameraEventHook = Hook.FromAddress(camEventAddr, CameraEventDetour); - + ControlHook = Services.Hooking.HookFromAddress(camCtrlAddr, ControlDetour); + + var preUpdateAddr = Services.SigScanner.ScanText("48 83 EC 28 8B 41 48"); + PreUpdateHook = Services.Hooking.HookFromAddress(preUpdateAddr, PreUpdateDetour); + + var actCamAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 45 32 FF 40 32 F6"); + ActiveCamHook = Services.Hooking.HookFromAddress(actCamAddr, GetActiveCamDetour); + + var camEventAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F8 EB 34"); + CameraEventHook = Services.Hooking.HookFromAddress(camEventAddr, CameraEventDetour); + var camUiAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 80 BB ?? ?? ?? ?? ?? 74 0D 8B 53 28"); - CameraUiHook = Hook.FromAddress(camUiAddr, CameraUiDetour); - - var camVf17 = ((nint*)Services.SigScanner.GetStaticAddressFromSig("88 83 ?? ?? ?? ?? 48 8D 05 ?? ?? ?? ?? 48 89 03 C6 83", 6))[17]; - TargetHook = Hook.FromAddress(camVf17, TargetDetour); - - var viewMxAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 33 C0 48 89 83 ?? ?? ?? ?? 48 8B 9C 24"); - CalcViewMatrixHook = Hook.FromAddress(viewMxAddr, CalcViewMatrixDetour); - - var collideAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 4C 8D 45 C7 89 83"); - CameraCollisionHook = Hook.FromAddress(collideAddr, CameraCollisionDetour); - } + CameraUiHook = Services.Hooking.HookFromAddress(camUiAddr, CameraUiDetour); + + var camVf17 = ((nint*)Services.SigScanner.GetStaticAddressFromSig("48 8D 05 ?? ?? ?? ?? C7 83 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 03 0F 57 C0 33 C0 48 C7 83 ?? ?? ?? ?? ?? ?? ?? ??"))[17]; + TargetHook = Services.Hooking.HookFromAddress(camVf17, TargetDetour); + + var viewMxAddr = Services.SigScanner.ScanText("48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? F6 81 ?? ?? ?? ?? ?? 48 8B D9 48 89 B4 24 ?? ?? ?? ??"); + CalcViewMatrixHook = Services.Hooking.HookFromAddress(viewMxAddr, CalcViewMatrixDetour); + + var loadMxAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B 17 48 8D 4D E0"); + LoadMatrix = Marshal.GetDelegateForFunctionPointer(loadMxAddr); + + var collideAddr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 4C 8D 45 97 89 83 ?? ?? ?? ??"); + CameraCollisionHook = Services.Hooking.HookFromAddress(collideAddr, CameraCollisionDetour); + } internal static void Dispose() { DisableHooks(); ControlHook.Dispose(); + PreUpdateHook.Dispose(); ActiveCamHook.Dispose(); CameraEventHook.Dispose(); CameraUiHook.Dispose(); @@ -225,4 +251,4 @@ internal static void Dispose() { CameraCollisionHook.Dispose(); } } -} \ No newline at end of file +} diff --git a/Ktisis/Interop/Hooks/ControlHooks.cs b/Ktisis/Interop/Hooks/ControlHooks.cs index 8cbeac100..318dc9255 100644 --- a/Ktisis/Interop/Hooks/ControlHooks.cs +++ b/Ktisis/Interop/Hooks/ControlHooks.cs @@ -92,12 +92,12 @@ internal static IntPtr InputDetour2(ulong a1, uint a2, ulong a3, uint a4) { internal static void Init() { unsafe { var addr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 83 7B 58 00"); - InputHook = Hook.FromAddress(addr, InputDetour); - InputHook.Enable(); + InputHook = Services.Hooking.HookFromAddress(addr, InputDetour); + InputHook.Enable(); var addr2 = Services.SigScanner.ScanText("48 89 5C 24 ?? 55 56 57 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 40 4D 8B F9"); - InputHook2 = Hook.FromAddress(addr2, InputDetour2); - InputHook2.Enable(); + InputHook2 = Services.Hooking.HookFromAddress(addr2, InputDetour2); + InputHook2.Enable(); } } diff --git a/Ktisis/Interop/Hooks/EnvHooks.cs b/Ktisis/Interop/Hooks/EnvHooks.cs new file mode 100644 index 000000000..d2dbc4503 --- /dev/null +++ b/Ktisis/Interop/Hooks/EnvHooks.cs @@ -0,0 +1,94 @@ +using Dalamud.Hooking; + +using Ktisis.Env; +using Ktisis.Structs.Env; + +namespace Ktisis.Interop.Hooks { + public static class EnvHooks { + // Hooks + + private unsafe delegate nint EnvUpdateDelegate(EnvManagerEx* env, nint a2); + private delegate nint SkyTexDelegate(nint a1, nint a2); + + private static Hook EnvUpdateHook = null!; + private unsafe static nint EnvUpdateDetour(EnvManagerEx* env, nint a2) { + if (Ktisis.IsInGPose && EnvService.TimeOverride != null) { + env->Time = EnvService.TimeOverride.Value; + } + + return EnvUpdateHook.Original(env, a2); + } + + private static Hook SkyTexHook = null!; + private unsafe static nint SkyTexDetour(nint a1, nint a2) { + var res = SkyTexHook.Original(a1, a2); + + if (Ktisis.IsInGPose && EnvService.SkyOverride != null) + *(uint*)(a1 + 8) = EnvService.SkyOverride.Value; + + return res; + } + + private delegate nint WaterRendererUpdateDelegate(nint a1); + private static Hook WaterRendererUpdateHook = null!; + private static nint WaterRendererUpdateDetour(nint a1) { + if (Ktisis.IsInGPose && EnvService.FreezeWater == true) { + return 0; + } + return WaterRendererUpdateHook.Original(a1); + } + + + // State + + private static bool Enabled; + + internal static void SetEnabled(bool enable) { + if (Enabled == enable) return; + if (enable) + EnableHooks(); + else + DisableHooks(); + } + + private static void EnableHooks() { + Enabled = true; + EnvUpdateHook.Enable(); + SkyTexHook.Enable(); + WaterRendererUpdateHook.Enable(); + } + + private static void DisableHooks() { + Enabled = false; + EnvUpdateHook.Disable(); + SkyTexHook.Disable(); + WaterRendererUpdateHook.Disable(); + } + + // Init & Dispose + + public unsafe static void Init() { + var addr1 = Services.SigScanner.ScanText("40 53 48 83 EC 30 48 8B 05 ?? ?? ?? ?? 48 8B D9 0F 29 74 24 ??"); + EnvUpdateHook = Services.Hooking.HookFromAddress(addr1, EnvUpdateDetour); + + var addr2 = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 49 3B F5 75 0D"); + SkyTexHook = Services.Hooking.HookFromAddress(addr2, SkyTexDetour); + + var addr3 = Services.SigScanner.ScanText("48 8B C4 48 89 58 18 57 48 81 EC ?? ?? ?? ?? 0F B6 B9 ?? ?? ?? ??"); + WaterRendererUpdateHook = Services.Hooking.HookFromAddress(addr3, WaterRendererUpdateDetour); + } + + public static void Dispose() { + DisableHooks(); + + EnvUpdateHook.Dispose(); + EnvUpdateHook.Dispose(); + + SkyTexHook.Disable(); + SkyTexHook.Dispose(); + + WaterRendererUpdateHook.Disable(); + WaterRendererUpdateHook.Dispose(); + } + } +} diff --git a/Ktisis/Interop/Hooks/EventsHooks.cs b/Ktisis/Interop/Hooks/EventsHooks.cs index d1996d86f..b747d3a3e 100644 --- a/Ktisis/Interop/Hooks/EventsHooks.cs +++ b/Ktisis/Interop/Hooks/EventsHooks.cs @@ -4,10 +4,12 @@ using Dalamud.Hooking; +using FFXIVClientStructs.FFXIV.Client.Game.Control; using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Component.GUI; +using Ktisis.Events; using Ktisis.Structs.Actor.Equip; using Ktisis.Structs.Actor.Equip.SetSources; @@ -20,9 +22,10 @@ public static void Init() { var MiragePrismMiragePlate = Services.AddonManager.Get(); MiragePrismMiragePlate.ReceiveEvent += OnGlamourPlatesReceiveEvent; - - OnGposeEnter(); // TODO: move this call on "enter gpose" event - OnLogin(null!, null!); + + EventManager.OnGPoseChange += OnGposeChange; + + OnLogin(); } public static void Dispose() { @@ -33,24 +36,32 @@ public static void Dispose() { var MiragePrismMiragePlate = Services.AddonManager.Get(); MiragePrismMiragePlate.ReceiveEvent -= OnGlamourPlatesReceiveEvent; - OnGposeLeave(); - OnLogout(null!, null!); - } + EventManager.OnGPoseChange -= OnGposeChange; + + OnLogout(0, 0); + } // Various event methods - private static void OnLogin(object? sender, EventArgs e) { + private static void OnLogin() { Sets.Init(); } - private static void OnLogout(object? sender, EventArgs e) { + private static void OnLogout(int type, int code) { Sets.Dispose(); } + + private static void OnGposeChange(bool state) { + if (state) + OnGposeEnter(); + else + OnGposeLeave(); + } private static void OnGposeEnter() { var ClickTargetAddon = Services.AddonManager.Get(); ClickTargetAddon.Enable(); } private static void OnGposeLeave() { var ClickTargetAddon = Services.AddonManager.Get(); - ClickTargetAddon.Dispose(); + ClickTargetAddon.Disable(); } private static unsafe void OnGlamourPlatesReceiveEvent(object? sender, ReceiveEventArgs e) { @@ -98,8 +109,8 @@ internal unsafe class MiragePrismMiragePlateAddon : IDisposable { public MiragePrismMiragePlateAddon() { var MiragePrismMiragePlateAgentInterface = Framework.Instance()->UIModule->GetAgentModule()->GetAgentByInternalId(AgentId.MiragePrismMiragePlate); - receiveEventHook ??= Hook.FromAddress(new IntPtr(MiragePrismMiragePlateAgentInterface->VTable->ReceiveEvent), OnReceiveEvent); - + receiveEventHook ??= Services.Hooking.HookFromAddress(new IntPtr(MiragePrismMiragePlateAgentInterface->VirtualTable->ReceiveEvent), OnReceiveEvent); + receiveEventHook?.Enable(); } @@ -118,65 +129,42 @@ public void Dispose() { } } internal unsafe class ClickTargetAddon : IDisposable { - - - private delegate IntPtr ClickTarget(IntPtr a1, byte* a2, byte a3); - private readonly Hook? rightClickTargetHook; - private readonly Hook? leftClickTargetHook; + private delegate nint ProcessMouseStateDelegate(TargetSystem* targets, nint a2, nint a3); + private readonly Hook? ProcessMouseStateHook; public ClickTargetAddon() { - rightClickTargetHook ??= Hook.FromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8B CE E8 ?? ?? ?? ?? 48 85 C0 74 1B"), RightClickTargetDetour); - leftClickTargetHook ??= Hook.FromAddress(Services.SigScanner.ScanText("E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 84 C0 74 16"), LeftClickTargetDetour); + var addr = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 4C 8B BC 24 ?? ?? ?? ?? 4C 8B B4 24 ?? ?? ?? ?? 48 8B B4 24 ?? ?? ?? ?? 48 8B 9C 24 ?? ?? ?? ??"); + ProcessMouseStateHook = Services.Hooking.HookFromAddress(addr, ProcessMouseStateDetour); } - public void Enable() { - rightClickTargetHook?.Enable(); - leftClickTargetHook?.Enable(); - } + private nint ProcessMouseStateDetour(TargetSystem* targets, nint a2, nint a3) { + var prev = targets->GPoseTarget; + var exec = ProcessMouseStateHook!.Original(targets, a2, a3); - public void Dispose() { - // Verify presence of hooks, in case of calls when it's already been disposed - if (!(bool)rightClickTargetHook?.IsDisposed!) { - if ((bool)rightClickTargetHook?.IsEnabled!) - rightClickTargetHook?.Disable(); - rightClickTargetHook?.Dispose(); - } - if (!(bool)leftClickTargetHook?.IsDisposed!) { - if ((bool)leftClickTargetHook?.IsEnabled!) - leftClickTargetHook?.Disable(); - leftClickTargetHook?.Dispose(); + if (Ktisis.IsInGPose && targets->GPoseTarget != prev) { + var left = Ktisis.Configuration.DisableChangeTargetOnLeftClick && exec == 0; + var right = !left && Ktisis.Configuration.DisableChangeTargetOnRightClick && exec == 0x10; + if (left || right) targets->GPoseTarget = prev; } + + return exec; } + public void Enable() { + ProcessMouseStateHook?.Enable(); + } - private IntPtr RightClickTargetDetour(IntPtr a1, byte* a2, byte a3) => - ClickEvent(a1, a2, a3, ClickType.Right); - private IntPtr LeftClickTargetDetour(IntPtr a1, byte* a2, byte a3) => - ClickEvent(a1, a2, a3, ClickType.Left); - - - private IntPtr ClickEvent(IntPtr a1, byte* actor, byte a3, ClickType clickType) { - if (Ktisis.IsInGPose) { - // 1. Prevents target self when clicking somewhere else with left click - // 2. Prevent target change with left and right clicks - // returning null wasn't enough for 1. so we pass the current target instead - - var left = Ktisis.Configuration.DisableChangeTargetOnLeftClick && clickType == ClickType.Left; - var right = Ktisis.Configuration.DisableChangeTargetOnRightClick && clickType == ClickType.Right; + public void Disable() { + ProcessMouseStateHook?.Disable(); + } - if (left || right) - return IntPtr.Zero; + public void Dispose() { + if (ProcessMouseStateHook?.IsDisposed == false) { + ProcessMouseStateHook?.Disable(); + ProcessMouseStateHook?.Dispose(); } - - if (clickType == ClickType.Left) return leftClickTargetHook!.Original(a1, actor, a3); - if (clickType == ClickType.Right) return rightClickTargetHook!.Original(a1, actor, a3); - - return IntPtr.Zero; - } - internal enum ClickType { - Left, - Right } + } internal unsafe class ReceiveEventArgs : EventArgs { public ReceiveEventArgs(AgentInterface* agentInterface, void* rawData, AtkValue* eventArgs, uint eventArgsCount, ulong senderID) { diff --git a/Ktisis/Interop/Hooks/GuiHooks.cs b/Ktisis/Interop/Hooks/GuiHooks.cs index f3582170e..7be8a6fbd 100644 --- a/Ktisis/Interop/Hooks/GuiHooks.cs +++ b/Ktisis/Interop/Hooks/GuiHooks.cs @@ -40,9 +40,9 @@ internal unsafe static void UpdateTarName(IntPtr a1) { // Init & dispose internal static void Init() { - var tarName = Services.SigScanner.ScanText("40 56 48 83 EC 50 48 8B 05 ?? ?? ?? ?? 48 8B F1 48 85 C0"); - TarNameHook = Hook.FromAddress(tarName, UpdateTarName); - TarNameHook.Enable(); + var tarName = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 8D 8D ?? ?? ?? ?? 48 83 C4 28"); + TarNameHook = Services.Hooking.HookFromAddress(tarName, UpdateTarName); + TarNameHook.Enable(); } internal static void Dispose() { diff --git a/Ktisis/Interop/Hooks/PoseHooks.cs b/Ktisis/Interop/Hooks/PoseHooks.cs index 3635c96da..41269fa9a 100644 --- a/Ktisis/Interop/Hooks/PoseHooks.cs +++ b/Ktisis/Interop/Hooks/PoseHooks.cs @@ -4,12 +4,14 @@ using Dalamud.Hooking; using Dalamud.Game.ClientState.Objects.Types; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.Havok.Animation.Playback.Control.Default; +using FFXIVClientStructs.Havok.Animation.Rig; using Ktisis.Structs; using Ktisis.Structs.Actor; using Ktisis.Structs.Poses; +using Ktisis.Util; namespace Ktisis.Interop.Hooks { public static class PoseHooks { @@ -24,6 +26,9 @@ public static class PoseHooks { internal unsafe delegate byte* LookAtIKDelegate(byte* a1, long* a2, long* a3, float a4, long* a5, long* a6); internal static Hook LookAtIKHook = null!; + + internal delegate nint KineDriverDelegate(nint a1, nint a2); + internal static Hook KineDriverHook = null!; internal unsafe delegate byte AnimFrozenDelegate(uint* a1, int a2); internal static Hook AnimFrozenHook = null!; @@ -33,7 +38,7 @@ public static class PoseHooks { internal unsafe delegate char SetSkeletonDelegate(Skeleton* a1, ushort a2, nint a3); internal static Hook SetSkeletonHook = null!; - + internal unsafe delegate nint BustDelegate(ActorModel* a1, Breasts* a2); internal static Hook BustHook = null!; @@ -42,31 +47,36 @@ public static class PoseHooks { internal static Dictionary PreservedPoses = new(); + internal static PoseAutoSave AutoSave = new(); + internal static unsafe void Init() { var setBoneModelSpaceFfxiv = Services.SigScanner.ScanText("48 8B C4 48 89 58 18 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 0F 29 70 B8 0F 29 78 A8 44 0F 29 40 ?? 44 0F 29 48 ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B B1"); - SetBoneModelSpaceFfxivHook = Hook.FromAddress(setBoneModelSpaceFfxiv, SetBoneModelSpaceFfxivDetour); + SetBoneModelSpaceFfxivHook = Services.Hooking.HookFromAddress(setBoneModelSpaceFfxiv, SetBoneModelSpaceFfxivDetour); var calculateBoneModelSpace = Services.SigScanner.ScanText("40 53 48 83 EC 10 4C 8B 49 28"); - CalculateBoneModelSpaceHook = Hook.FromAddress(calculateBoneModelSpace, CalculateBoneModelSpaceDetour); + CalculateBoneModelSpaceHook = Services.Hooking.HookFromAddress(calculateBoneModelSpace, CalculateBoneModelSpaceDetour); var syncModelSpace = Services.SigScanner.ScanText("48 83 EC 18 80 79 38 00"); - SyncModelSpaceHook = Hook.FromAddress(syncModelSpace, SyncModelSpaceDetour); - - var lookAtIK = Services.SigScanner.ScanText("48 8B C4 48 89 58 08 48 89 70 10 F3 0F 11 58 ??"); - LookAtIKHook = Hook.FromAddress(lookAtIK, LookAtIKDetour); + SyncModelSpaceHook = Services.Hooking.HookFromAddress(syncModelSpace, SyncModelSpaceDetour); - var animFrozen = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F0 84 C0 74 0E"); - AnimFrozenHook = Hook.FromAddress(animFrozen, AnimFrozenDetour); + var lookAtIK = Services.SigScanner.ScanText("48 8B C4 48 89 58 08 48 89 70 10 F3 0F 11 58"); + LookAtIKHook = Services.Hooking.HookFromAddress(lookAtIK, LookAtIKDetour); - var updatePos = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? EB 29 48 8B 5F 08"); - UpdatePosHook = Hook.FromAddress(updatePos, UpdatePosDetour); + var kineDrive = Services.SigScanner.ScanText("48 8B C4 55 57 48 83 EC 58"); + KineDriverHook = Services.Hooking.HookFromAddress(kineDrive, KineDriverDetour); + + var animFrozen = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F B6 F8 84 C0 74 12"); + AnimFrozenHook = Services.Hooking.HookFromAddress(animFrozen, AnimFrozenDetour); + + var updatePos = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 84 DB 74 3A"); + UpdatePosHook = Services.Hooking.HookFromAddress(updatePos, UpdatePosDetour); var loadSkele = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 48 C1 E5 08"); - SetSkeletonHook = Hook.FromAddress(loadSkele, SetSkeletonDetour); + SetSkeletonHook = Services.Hooking.HookFromAddress(loadSkele, SetSkeletonDetour); SetSkeletonHook.Enable(); - var loadBust = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? F6 84 24 ?? ?? ?? ?? ?? 0F 28 74 24 ??"); - BustHook = Hook.FromAddress(loadBust, BustDetour); + var loadBust = Services.SigScanner.ScanText("E8 ?? ?? ?? ?? 0F 28 7C 24 ?? 0F 28 74 24 ?? 4C 8B 74 24 ??"); + BustHook = Services.Hooking.HookFromAddress(loadBust, BustDetour); } internal static void DisablePosing() { @@ -75,9 +85,11 @@ internal static void DisablePosing() { SetBoneModelSpaceFfxivHook?.Disable(); SyncModelSpaceHook?.Disable(); LookAtIKHook?.Disable(); + KineDriverHook.Disable(); UpdatePosHook?.Disable(); AnimFrozenHook?.Disable(); BustHook?.Disable(); + AutoSave?.Disable(); PosingEnabled = false; } @@ -86,9 +98,11 @@ internal static void EnablePosing() { SetBoneModelSpaceFfxivHook?.Enable(); SyncModelSpaceHook?.Enable(); LookAtIKHook?.Enable(); + KineDriverHook.Enable(); UpdatePosHook?.Enable(); AnimFrozenHook?.Enable(); BustHook?.Enable(); + AutoSave?.Enable(); PosingEnabled = true; } @@ -153,7 +167,7 @@ private static unsafe char SetSkeletonDetour(Skeleton* a1, ushort a2, nint a3) { if (actor->Model == null || actor->Model->Skeleton != a1) continue; PoseContainer container = new(); - container.Store(actor->Model->Skeleton); + container.Store((FFXIVClientStructs.FFXIV.Client.Graphics.Render.Skeleton*)actor->Model->Skeleton); PreservedPoses[actor->ObjectID] = container; } } @@ -205,6 +219,10 @@ private unsafe static nint BustDetour(ActorModel* a1, Breasts* a2) { return (byte*)nint.Zero; } + private static nint KineDriverDetour(nint a1, nint a2) { + return nint.Zero; + } + private unsafe static byte AnimFrozenDetour(uint* a1, int a2) { return 1; } @@ -213,13 +231,13 @@ private static unsafe void SyncBone(hkaPose* bonesPose, int index) { CalculateBoneModelSpaceHook.Original(ref *bonesPose, index); } - public static unsafe bool IsGamePlaybackRunning(GameObject? gPoseTarget) { + public static unsafe bool IsGamePlaybackRunning(IGameObject? gPoseTarget) { var animationControl = GetAnimationControl(gPoseTarget); if (animationControl == null) return true; return animationControl->PlaybackSpeed == 1; } - public static unsafe hkaDefaultAnimationControl* GetAnimationControl(GameObject? go) { + public static unsafe hkaDefaultAnimationControl* GetAnimationControl(IGameObject? go) { if (go == null) return null; var actor = (Actor*)go.Address; @@ -243,6 +261,8 @@ internal static void Dispose() { SyncModelSpaceHook.Dispose(); LookAtIKHook.Disable(); LookAtIKHook.Dispose(); + KineDriverHook.Disable(); + KineDriverHook.Dispose(); AnimFrozenHook.Disable(); AnimFrozenHook.Dispose(); UpdatePosHook.Disable(); diff --git a/Ktisis/Interop/IpcChecker.cs b/Ktisis/Interop/IpcChecker.cs new file mode 100644 index 000000000..fef802437 --- /dev/null +++ b/Ktisis/Interop/IpcChecker.cs @@ -0,0 +1,19 @@ +using System; +using System.Linq; + +namespace Ktisis.Interop { + public class IpcChecker { + private static bool? _isActive; + private static DateTime? _lastCheck; + + public static bool IsGlamourerActive() { + var now = DateTime.Now; + if (_isActive == null || (now - _lastCheck)!.Value.TotalSeconds > 60) { + _lastCheck = now; + _isActive = Services.PluginInterface.InstalledPlugins + .FirstOrDefault(p => p is { InternalName: "Glamourer", IsLoaded: true }) != null; + } + return _isActive.Value; + } + } +} diff --git a/Ktisis/Interop/Methods.cs b/Ktisis/Interop/Methods.cs index 2c598e39c..c68060b02 100644 --- a/Ktisis/Interop/Methods.cs +++ b/Ktisis/Interop/Methods.cs @@ -15,12 +15,15 @@ internal class Methods { // Change actor equipment // a1 = Actor + 0x6D0, a2 = EquipIndex, a3 = EquipItem - internal unsafe delegate void ChangeEquipDelegate(ActorDrawData* writeTo, EquipIndex index, ItemEquip item); + internal unsafe delegate void ChangeEquipDelegate(ActorDrawData* writeTo, EquipIndex index, ItemEquip* item, bool force); internal static ChangeEquipDelegate? ActorChangeEquip; internal unsafe delegate void ChangeWeaponDelegate(ActorDrawData* writeTo, int slot, WeaponEquip weapon, byte a4, byte a5, byte a6, byte a7); // a4-a7 is always 0,1,0,0. internal static ChangeWeaponDelegate? ActorChangeWeapon; + internal unsafe delegate void ChangeGlassesDelegate(ActorDrawData* writeTo, int slot, ushort id); + internal static ChangeGlassesDelegate? ChangeGlasses; + // Get world matrix [UnmanagedFunctionPointer(CallingConvention.Cdecl)] @@ -33,9 +36,10 @@ private static TDelegate Retrieve(string sig) => Marshal.GetDelegateForFunctionPointer(Services.SigScanner.ScanText(sig)); internal static void Init() { - ActorLookAt = Retrieve("40 53 55 57 41 56 41 57 48 83 EC 70"); - ActorChangeEquip = Retrieve("E8 ?? ?? ?? ?? 41 B5 01 FF C6"); - ActorChangeWeapon = Retrieve("E8 ?? ?? ?? ?? 80 7F 25 00"); + ActorLookAt = Retrieve("E8 ?? ?? ?? ?? 8B D6 48 8B CF E8 ?? ?? ?? ?? EB 2A"); + ActorChangeEquip = Retrieve("E8 ?? ?? ?? ?? B1 ?? 41 FF C6"); + ActorChangeWeapon = Retrieve("E8 ?? ?? ?? ?? 4C 8B 45 7F"); + ChangeGlasses = Retrieve("E8 ?? ?? ?? ?? EB 50 44 8B 03"); GetMatrix = Retrieve("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); } } diff --git a/Ktisis/Interop/StaticOffsets.cs b/Ktisis/Interop/StaticOffsets.cs index af1f53a94..6f3e1e9ba 100644 --- a/Ktisis/Interop/StaticOffsets.cs +++ b/Ktisis/Interop/StaticOffsets.cs @@ -1,8 +1,5 @@ namespace Ktisis.Interop { internal static class StaticOffsets { - // Address of loaded FFXIV_CHARA files in memory. - internal static nint CharaDatData; - // If this is NOP'd, Anam posing is enabled. internal unsafe static byte* FreezePosition; internal unsafe static byte* FreezeRotation; @@ -16,9 +13,6 @@ internal static class StaticOffsets { // Init internal unsafe static void Init() { - var datAddr = *(nint*)Services.SigScanner.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 C7 44 24 24 05 00 00 00 C6 84 24"); - CharaDatData = *(nint*)(datAddr + 1392); - FreezePosition = (byte*)Services.SigScanner.ScanText("41 0F 29 24 12"); FreezeRotation = (byte*)Services.SigScanner.ScanText("41 0F 29 5C 12 10"); FreezeScale = (byte*)Services.SigScanner.ScanText("41 0F 29 44 12 20"); diff --git a/Ktisis/Ktisis.cs b/Ktisis/Ktisis.cs index 68cfa010e..83fa8a216 100644 --- a/Ktisis/Ktisis.cs +++ b/Ktisis/Ktisis.cs @@ -4,8 +4,10 @@ using Dalamud.Game.Command; using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Interface; +using Dalamud.Plugin.Services; using Ktisis.Camera; +using Ktisis.Env; using Ktisis.Interface; using Ktisis.Interface.Windows; using Ktisis.Interface.Windows.Workspace; @@ -23,12 +25,13 @@ public sealed class Ktisis : IDalamudPlugin { public static string Version = $"Alpha {GetVersion()}"; public static Configuration Configuration { get; private set; } = null!; - public static UiBuilder UiBuilder { get; private set; } = null!; + public static IUiBuilder UiBuilder { get; private set; } = null!; + public static IPluginLog Log { get; private set; } = null!; - public static bool IsInGPose => Services.PluginInterface.UiBuilder.GposeActive && IsGposeTargetPresent(); + public static bool IsInGPose => Services.ClientState.IsGPosing && IsGposeTargetPresent(); public unsafe static bool IsGposeTargetPresent() => (IntPtr)Services.Targets->GPoseTarget != IntPtr.Zero; - public unsafe static GameObject? GPoseTarget + public unsafe static IGameObject? GPoseTarget => IsInGPose ? Services.ObjectTable.CreateObjectReference((IntPtr)Services.Targets->GPoseTarget) : null; public unsafe static Actor* Target => GPoseTarget != null ? (Actor*)GPoseTarget.Address : null; @@ -36,10 +39,14 @@ public static string GetVersion() { return typeof(Ktisis).Assembly.GetName().Version!.ToString(fieldCount: 3); } - public Ktisis(DalamudPluginInterface pluginInterface) { + public Ktisis( + IDalamudPluginInterface pluginInterface, + IPluginLog log + ) { Services.Init(pluginInterface); Configuration = pluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); UiBuilder = pluginInterface.UiBuilder; + Log = log; if (Configuration.IsFirstTimeInstall) { Configuration.IsFirstTimeInstall = false; @@ -64,11 +71,13 @@ public Ktisis(DalamudPluginInterface pluginInterface) { Interop.Hooks.PoseHooks.Init(); CameraService.Init(); + EnvService.Init(); EventManager.OnGPoseChange += Workspace.OnEnterGposeToggle; // must be placed before ActorStateWatcher.Init() Input.Init(); ActorStateWatcher.Init(); + ActorWetnessOverride.Instance.Init(); // Register command @@ -81,6 +90,7 @@ public Ktisis(DalamudPluginInterface pluginInterface) { if (Configuration.OpenKtisisMethod == OpenKtisisMethod.OnPluginLoad) Workspace.Show(); + pluginInterface.UiBuilder.OpenMainUi += Workspace.Toggle; pluginInterface.UiBuilder.OpenConfigUi += ConfigGui.Toggle; pluginInterface.UiBuilder.DisableGposeUiHide = true; pluginInterface.UiBuilder.Draw += KtisisGui.Draw; @@ -92,6 +102,7 @@ public Ktisis(DalamudPluginInterface pluginInterface) { public void Dispose() { Services.CommandManager.RemoveHandler(CommandName); Services.PluginInterface.SavePluginConfig(Configuration); + Services.PluginInterface.UiBuilder.OpenMainUi -= Workspace.Toggle; Services.PluginInterface.UiBuilder.OpenConfigUi -= ConfigGui.Toggle; OverlayWindow.DeselectGizmo(); @@ -103,19 +114,17 @@ public void Dispose() { Interop.Hooks.PoseHooks.Dispose(); CameraService.Dispose(); + EnvService.Dispose(); Interop.Alloc.Dispose(); ActorStateWatcher.Dispose(); + ActorWetnessOverride.Instance.Dispose(); EventManager.OnGPoseChange -= Workspace.OnEnterGposeToggle; Data.Sheets.Cache.Clear(); Input.Dispose(); HistoryManager.Dispose(); - - foreach (var (_, texture) in References.Textures) { - texture.Dispose(); - } } private void OnCommand(string command, string arguments) { diff --git a/Ktisis/Ktisis.csproj b/Ktisis/Ktisis.csproj index dd7256f93..ae076ded5 100644 --- a/Ktisis/Ktisis.csproj +++ b/Ktisis/Ktisis.csproj @@ -3,22 +3,22 @@ Chirp Ktisis Tools - 0.2.15 + 0.2.30 An internal posing tool. - https://github.com/ktisis-tools/Ktisis Debug;Release;External - net7.0-windows + net10.0-windows x64 - enable + enable latest true false false true + true @@ -30,7 +30,7 @@ - net7.0 + net10.0 EXTERNAL_BUILD ..\..\DalamudLibs\ @@ -51,11 +51,16 @@ - + + $(DalamudLibPath)FFXIVClientStructs.dll false + + $(DalamudLibPath)InteropGenerator.Runtime.dll + false + $(DalamudLibPath)Newtonsoft.Json.dll false @@ -64,8 +69,16 @@ $(DalamudLibPath)Dalamud.dll false - - $(DalamudLibPath)ImGui.NET.dll + + $(DalamudLibPath)Dalamud.Bindings.ImGui.dll + false + + + $(DalamudLibPath)Dalamud.Bindings.ImGuizmo.dll + false + + + $(DalamudLibPath)Dalamud.Bindings.ImPlot.dll false @@ -90,4 +103,13 @@ + + + + + + + + + diff --git a/Ktisis/Ktisis.json b/Ktisis/Ktisis.json index 2c9d295f9..6f2c7f025 100644 --- a/Ktisis/Ktisis.json +++ b/Ktisis/Ktisis.json @@ -6,9 +6,9 @@ "InternalName": "Ktisis", "RepoUrl": "https://github.com/ktisis-tools/Ktisis", "IconUrl": "https://github.com/ktisis-tools/Ktisis/raw/main/icon.png", - "AssemblyVersion": "0.2.15", + "AssemblyVersion": "0.2.30", "ApplicableVersion": "any", - "DalamudApiLevel": 8, + "DalamudApiLevel": 14, "Tags": [ "gpose", "posing" diff --git a/Ktisis/Locale/i18n/English.json b/Ktisis/Locale/i18n/English.json index a3e7af750..ad6b733db 100644 --- a/Ktisis/Locale/i18n/English.json +++ b/Ktisis/Locale/i18n/English.json @@ -62,6 +62,15 @@ "Keyboard_shortcuts": "Keyboard Shortcuts", "Pressing_keys": "Pressing Keys", "Edit_bone_positions": "Edit bone positions", + "Enable_auto_save": "Enable auto save", + "Auto_save_interval": "Auto Save Interval", + "Auto_save_count": "Auto Save Count", + "Auto_save_path": "Auto Save Path", + "Clear_auto_saves_on_exit": "Clear auto saves on exit", + "Formatter": "Formatter", + "Example_Value": "Example Value", + "Example_Folder_Name": "Example Folder Name:", + "Auto_save_Folder_Name": "Auto Save Folder Name", // Display keyboard configs from enum defined in Input.cs "Input_Generic_Toggle": "Toggle", "Input_Generic_Hold": "Hold", @@ -77,6 +86,10 @@ "Keyboard_Action_ClearCategoryVisibilityOverload": "Clear category visibility overload", "Keyboard_Action_HoldAllCategoryVisibilityOverload": "Hold all category visibility overload", "Keyboard_Action_CircleThroughSiblingLinkModes": "Circle through sibling link modes", + "Keyboard_Action_NextCamera": "Next camera", + "Keyboard_Action_PreviousCamera": "Previous camera", + "Keyboard_Action_ToggleFreeCam": "Toggle free cam", + "Keyboard_Action_NewCamera": "New camera", //// Game Jargon //// @@ -201,12 +214,8 @@ "j_f_eye_l": "Left Eye", "j_f_eye_r": "Right Eye", "j_f_hana": "Nose", - "j_f_hoho_l": "Left Cheek", - "j_f_hoho_r": "Right Cheek", "j_f_lip_l": "Left Lips", "j_f_lip_r": "Right Lips", - "j_f_mayu_l": "Left Eyebrow", - "j_f_mayu_r": "Right Eyebrow", "j_f_memoto": "Bridge", "j_f_miken_l": "Left Brow", "j_f_miken_r": "Right Brow", @@ -246,12 +255,86 @@ "oh_n_hara": "Off Hand", "j_half_l": "Left Half", "j_half_r": "Right Half", + + "j_f_ago": "Jaw", + "j_f_dago": "Lower Jaw", + "j_f_bero_01": "Tongue A", + "j_f_bero_02": "Tongue B", + "j_f_bero_03": "Tongue C", + "j_f_hagukiup": "Upper Teeth", + "j_f_hagukidn": "Lower Teeth", + "j_f_dlip_01_l": "Lip Lower Left Center A", + "j_f_dlip_02_l": "Lip Lower Left Center B", + "j_f_dlip_01_r": "Lip Lower Right Center A", + "j_f_dlip_02_r": "Lip Lower Right Center B", + "j_f_ulip_01_l": "Lip Upper Left Center A", + "j_f_ulip_02_l": "Lip Upper Left Center B", + "j_f_ulip_01_r": "Lip Upper Right Center A", + "j_f_ulip_02_r": "Lip Upper Right Center B", + "j_f_dmlip_01_l": "Lip Lower Left A", + "j_f_dmlip_02_l": "Lip Lower Left B", + "j_f_dmlip_01_r": "Lip Lower Right A", + "j_f_dmlip_02_r": "Lip Lower Right B", + "j_f_umlip_01_l": "Lip Upper Left A", + "j_f_umlip_02_l": "Lip Upper Left B", + "j_f_umlip_01_r": "Lip Upper Right A", + "j_f_umlip_02_r": "Lip Upper Right B", + "j_f_uslip_l": "Lip Upper Left Corner A", + "j_f_dslip_l": "Lip Lower Left Corner A", + "j_f_uslip_r": "Lip Upper Right Corner A", + "j_f_dslip_r": "Lip Lower Right Corner A", + + "j_f_mab_l": "Left Eye Socket", + "j_f_mab_r": "Right Eye Socket", + "j_f_eyepuru_l": "Left Iris", + "j_f_eyepuru_r": "Right Iris", + "j_f_mabup_01_l": "Left Upper Eyelid", + "j_f_mabdn_01_l": "Left Lower Eyelid", + "j_f_mabup_01_r": "Right Upper Eyelid", + "j_f_mabdn_01_r": "Right Lower Eyelid", + "j_f_mabup_02out_l": "Left Upper Eyelid Outer", + "j_f_mabdn_02out_l": "Left Lower Eyelid Outer", + "j_f_mabup_03in_l": "Left Upper Eyelid Inner", + "j_f_mabdn_03in_l": "Left Lower Eyelid Inner", + "j_f_mabup_02out_r": "Right Upper Eyelid Outer", + "j_f_mabdn_02out_r": "Right Lower Eyelid Outer", + "j_f_mabup_03in_r": "Right Upper Eyelid Inner", + "j_f_mabdn_03in_r": "Right Lower Eyelid Inner", + + "j_f_mayu_l": "Left Eyebrow A", + "j_f_mayu_r": "Right Eyebrow A", + "j_f_mmayu_l": "Left Eyebrow B", + "j_f_mmayu_r": "Right Eyebrow B", + "j_f_miken_01_l": "Left Brow Ridge A", + "j_f_miken_02_l": "Left Brow Ridge B", + "j_f_miken_01_r": "Right Brow Ridge A", + "j_f_miken_02_r": "Right Brow Ridge B", + + "j_f_face": "Face", + "j_f_hoho_l": "Left Cheek", + "j_f_hoho_r": "Right Cheek", + "j_f_dhoho_l": "Left Outer Cheek", + "j_f_dhoho_r": "Right Outer Cheek", + "j_f_shoho_l": "Left Middle Cheek", + "j_f_shoho_r": "Right Middle Cheek", + "j_f_dmemoto_l": "Left Inner Cheek", + "j_f_dmemoto_r": "Right Inner Cheek", + "j_f_uhana": "Bridge", + "j_f_hana_l": "Left Nostril", + "j_f_hana_r": "Right Nostril", + "j_f_dmiken_l": "Left Glabella", + "j_f_dmiken_r": "Right Glabella", + + "j_ex_met_vb": "Visor", // Bone Category names "other": "Other", "body": "Body", "head": "Head", "hair": "Hair", + "eyes": "Eyes", + "face": "Face", + "mouth": "Mouth", "clothes": "Clothes", "weapons": "Weapons", "right hand": "Right hand", diff --git a/Ktisis/Logger.cs b/Ktisis/Logger.cs index f3905c0a9..f1668b5f4 100644 --- a/Ktisis/Logger.cs +++ b/Ktisis/Logger.cs @@ -20,7 +20,7 @@ internal static void Fatal(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.DarkRed, format, values); else - PluginLog.Fatal(format, values); + Ktisis.Log.Fatal(format, values); } [StringFormatMethod("format")] @@ -28,14 +28,14 @@ internal static void Error(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Red, format, values); else - PluginLog.Error(format, values); + Ktisis.Log.Error(format, values); } internal static void Error(Exception ex, string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Red, ex, format, values); else - PluginLog.Error(ex, format, values); + Ktisis.Log.Error(ex, format, values); } [StringFormatMethod("format")] @@ -43,7 +43,7 @@ internal static void Warning(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Yellow, format, values); else - PluginLog.Warning(format, values); + Ktisis.Log.Warning(format, values); } [StringFormatMethod("format")] @@ -51,7 +51,7 @@ public static void Information(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Cyan, format, values); else - PluginLog.Information(format, values); + Ktisis.Log.Information(format, values); } [StringFormatMethod("format")] @@ -59,7 +59,7 @@ internal static void Verbose(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Gray, format, values); else - PluginLog.Verbose(format, values); + Ktisis.Log.Verbose(format, values); } [StringFormatMethod("format")] @@ -67,7 +67,7 @@ internal static void Debug(string format, params object[] values) { if (IsExternal) WriteToConsole(ConsoleColor.Magenta, format, values); else - PluginLog.Debug(format, values); + Ktisis.Log.Debug(format, values); } [StringFormatMethod("format")] diff --git a/Ktisis/Overlay/Gizmo.cs b/Ktisis/Overlay/Gizmo.cs index 57b1f8283..7a393e8bb 100644 --- a/Ktisis/Overlay/Gizmo.cs +++ b/Ktisis/Overlay/Gizmo.cs @@ -1,7 +1,7 @@ using System.Numerics; -using ImGuiNET; -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; using Ktisis.Structs.Extensions; @@ -9,14 +9,14 @@ namespace Ktisis.Overlay { public class Gizmo { // Instanced properties - public MODE Mode => Ktisis.Configuration.GizmoMode; - public OPERATION Operation => Ktisis.Configuration.GizmoOp; + public ImGuizmoMode Mode => Ktisis.Configuration.GizmoMode; + public ImGuizmoOperation Operation => Ktisis.Configuration.GizmoOp; public Matrix4x4 Matrix = new(); public Matrix4x4 Delta = new(); public SharpDX.Matrix3x3 EulerDeltaMatrix = new(); // for non gizmo manipulation, euler based, which must have an effect on the gizmo - public OPERATION? ForceOp = null; + public ImGuizmoOperation? ForceOp = null; // Compose & Decompose // Compose updates the matrix using given values. diff --git a/Ktisis/Overlay/OverlayWindow.cs b/Ktisis/Overlay/OverlayWindow.cs index 2cc815c37..41e806eb5 100644 --- a/Ktisis/Overlay/OverlayWindow.cs +++ b/Ktisis/Overlay/OverlayWindow.cs @@ -1,9 +1,10 @@ using System.Numerics; -using ImGuiNET; -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; using Dalamud.Interface; +using Dalamud.Interface.Utility; using Ktisis.Interop; using Ktisis.Structs.FFXIV; diff --git a/Ktisis/Overlay/Selection.cs b/Ktisis/Overlay/Selection.cs index d54a1838e..64a1e901b 100644 --- a/Ktisis/Overlay/Selection.cs +++ b/Ktisis/Overlay/Selection.cs @@ -2,8 +2,8 @@ using System.Numerics; using System.Collections.Generic; -using ImGuiNET; -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; namespace Ktisis.Overlay { public static class Selection { diff --git a/Ktisis/Overlay/Skeleton.cs b/Ktisis/Overlay/Skeleton.cs index 26af16997..9cd6c1b2c 100644 --- a/Ktisis/Overlay/Skeleton.cs +++ b/Ktisis/Overlay/Skeleton.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Numerics; -using ImGuiNET; -using ImGuizmoNET; +using Dalamud.Bindings.ImGui; +using Dalamud.Bindings.ImGuizmo; using Ktisis.Structs; using Ktisis.Structs.Actor; @@ -44,16 +44,14 @@ public unsafe static void Draw() { var actor = Ktisis.Target; if (actor == null) return; - - // Draw actor root - - DrawActorRoot(actor); - - // Draw model skeleton var model = actor->Model; if (model == null || model->Skeleton == null) return; + + // Draw actor root + DrawActorRoot(actor); + // Draw model skeleton DrawModelSkeleton(model); // Draw children (weapons, props) @@ -99,6 +97,8 @@ public unsafe static void DrawModelSkeleton(ActorModel* model, ActorModel* paren var camera = Services.Camera->GetActiveCamera(); var skeleton = pose->Skeleton; + if (skeleton == null) continue; + for (var i = 1; i < skeleton->Bones.Length; i++) { var bone = model->Skeleton->GetBone(p, i, parentModel != null); if (_setCategory != null) bone._setCategory = _setCategory; diff --git a/Ktisis/Services.cs b/Ktisis/Services.cs index 0f5917dc9..711ad4b0a 100644 --- a/Ktisis/Services.cs +++ b/Ktisis/Services.cs @@ -1,32 +1,29 @@ using Dalamud.IoC; -using Dalamud.Data; using Dalamud.Game; using Dalamud.Plugin; -using Dalamud.Game.Gui; -using Dalamud.Game.Command; -using Dalamud.Game.ClientState; -using Dalamud.Game.ClientState.Keys; -using Dalamud.Game.ClientState.Objects; +using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game.Control; namespace Ktisis { internal class Services { - [PluginService] internal static DalamudPluginInterface PluginInterface { get; private set; } = null!; - [PluginService] internal static CommandManager CommandManager { get; private set; } = null!; - [PluginService] internal static DataManager DataManager { get; private set; } = null!; - [PluginService] internal static ClientState ClientState { get; private set; } = null!; - [PluginService] internal static ObjectTable ObjectTable { get; private set; } = null!; - [PluginService] internal static SigScanner SigScanner { get; private set; } = null!; - [PluginService] internal static Framework Framework { get; private set; } = null!; - [PluginService] internal static KeyState KeyState { get; private set; } = null!; - [PluginService] internal static GameGui GameGui { get; private set; } = null!; + [PluginService] internal static IDalamudPluginInterface PluginInterface { get; private set; } = null!; + [PluginService] internal static ICommandManager CommandManager { get; private set; } = null!; + [PluginService] internal static ITextureProvider Textures { get; private set; } = null!; + [PluginService] internal static IDataManager DataManager { get; private set; } = null!; + [PluginService] internal static IClientState ClientState { get; private set; } = null!; + [PluginService] internal static IObjectTable ObjectTable { get; private set; } = null!; + [PluginService] internal static ISigScanner SigScanner { get; private set; } = null!; + [PluginService] internal static IFramework Framework { get; private set; } = null!; + [PluginService] internal static IKeyState KeyState { get; private set; } = null!; + [PluginService] internal static IGameGui GameGui { get; private set; } = null!; + [PluginService] internal static IGameInteropProvider Hooking { get; private set; } = null!; internal static Interop.Hooks.AddonManager AddonManager = null!; internal unsafe static TargetSystem* Targets = TargetSystem.Instance(); - internal unsafe static CameraManager* Camera = CameraManager.Instance; + internal unsafe static CameraManager* Camera = CameraManager.Instance(); - public static void Init(DalamudPluginInterface dalamud) { + public static void Init(IDalamudPluginInterface dalamud) { dalamud.Create(); } } diff --git a/Ktisis/Structs/Actor/Actor.cs b/Ktisis/Structs/Actor/Actor.cs index bfa1448c6..1001a8b48 100644 --- a/Ktisis/Structs/Actor/Actor.cs +++ b/Ktisis/Structs/Actor/Actor.cs @@ -10,22 +10,28 @@ using Ktisis.Data.Excel; namespace Ktisis.Structs.Actor { - [StructLayout(LayoutKind.Explicit, Size = 0x84A)] + [StructLayout(LayoutKind.Explicit, Size = 0x22E0)] public struct Actor { [FieldOffset(0)] public GameObject GameObject; - [FieldOffset(0x88)] public byte ObjectID; + [FieldOffset(0x8C)] public ushort ObjectID; [FieldOffset(0x100)] public unsafe ActorModel* Model; - [FieldOffset(0x114)] public RenderMode RenderMode; - [FieldOffset(0x1B4)] public uint ModelId; - - [FieldOffset(0x6E8)] public ActorDrawData DrawData; + [FieldOffset(0x118)] public RenderMode RenderMode; + + [FieldOffset(0x6F8)] public ActorDrawData DrawData; - [FieldOffset(0x876)] public bool IsHatHidden; + [FieldOffset(0x936)] public bool IsHatHidden; - public const int GazeOffset = 0xC60; + public const int GazeOffset = 0xD80; [FieldOffset(GazeOffset + 0x10)] public ActorGaze Gaze; + + // FFXIVClientStructs.FFXIV.Client.Game.Character + // ModelContainer is at 0x1B28 + // ModelCharaId is at 0x10 within ModelContainer + [FieldOffset(0x1B28 + 0x10)] public uint ModelId; + + [FieldOffset(0x22E8)] public float Transparency; public unsafe string? GetName() { fixed (byte* ptr = GameObject.Name) @@ -56,11 +62,27 @@ public unsafe void LookAt(Gaze* tar, GazeControl bodyPart) { // Change equipment - no redraw method + public unsafe ItemEquip GetEquip(EquipIndex index) { + if (index == EquipIndex.Head && this.IsHatHidden) + return this.DrawData.Equipment.Head; + return this.Model != null ? this.Model->GetEquipSlot((int)index) : default; + } + + public unsafe Customize GetCustomize() + => this.Model != null ? this.Model->GetCustomize() ?? default : default; + + public WeaponEquip GetWeaponEquip(EquipSlot slot) + => slot == EquipSlot.MainHand ? this.DrawData.MainHand.GetEquip() : this.DrawData.OffHand.GetEquip(); + public unsafe void Equip(EquipIndex index, ItemEquip item) { if (Methods.ActorChangeEquip == null) return; - fixed (ActorDrawData* ptr = &DrawData) - Methods.ActorChangeEquip(ptr, index, item); + + fixed (ActorDrawData* ptr = &DrawData) { + //Methods.ActorChangeEquip(ptr, index, (ItemEquip)0xFFFFFFFF); + Methods.ActorChangeEquip(ptr, index, &item, true); + } } + public void Equip(List<(EquipSlot, object)> items) { foreach ((EquipSlot slot, object item) in items) if (item is ItemEquip equip) @@ -71,63 +93,84 @@ public void Equip(List<(EquipSlot, object)> items) { public unsafe void Equip(int slot, WeaponEquip item) { if (Methods.ActorChangeWeapon == null) return; - fixed (ActorDrawData* ptr = &DrawData) + + fixed (ActorDrawData* ptr = &DrawData) { + Logger.Information($"Setting to {item.Set} {item.Base} {item.Variant} {item.Dye}"); + + Methods.ActorChangeWeapon(ptr, slot, default, 0, 1, 0, 0); Methods.ActorChangeWeapon(ptr, slot, item, 0, 1, 0, 0); + if (slot == 0) + this.DrawData.MainHand.SetEquip(item); + else if (slot == 1) + this.DrawData.OffHand.SetEquip(item); + } + } + + public unsafe void SetGlasses(ushort id) { + if (Methods.ChangeGlasses == null) return; + + fixed (ActorDrawData* ptr = &DrawData) + Methods.ChangeGlasses(ptr, 0, id); } // Change customize - no redraw method public unsafe bool UpdateCustomize() { - fixed (Customize* custom = &DrawData.Customize) - return ((Human*)Model)->UpdateDrawData((byte*)custom, true); + if (this.Model == null) return false; + + var result = false; + + var human = (Human*)this.Model; + if (this.Model->IsHuman()) + result = human->UpdateDrawData((byte*)&this.Model->Customize, true); + + fixed (Customize* ptr = &DrawData.Customize) + return result | ((Human*)Model)->UpdateDrawData((byte*)ptr, true); } // Apply new customize public unsafe void ApplyCustomize(Customize custom) { - var cur = DrawData.Customize; - DrawData.Customize = custom; + if (this.ModelId != 0) return; + + var cur = GetCustomize(); // Fix UpdateCustomize on Carbuncles & Minions - if (DrawData.Customize.ModelType == 0) - DrawData.Customize.ModelType = 1; + if (custom.ModelType == 0) + custom.ModelType = 1; + + if (custom.Race == Race.Viera) { + // avoid crash when loading invalid ears + var ears = custom.RaceFeatureType; + custom.RaceFeatureType = ears switch { + > 4 => 1, + 0 => 4, + _ => ears + }; + } var faceHack = cur.FaceType != custom.FaceType; - if (cur.Race != custom.Race - || cur.Tribe != custom.Tribe // Eye glitch. - || cur.Gender != custom.Gender - || cur.FaceType != custom.FaceType // Eye glitch. - ) { - Redraw(faceHack); - } else { - if (DrawData.Customize.Race == Race.Viera) { - // avoid crash when loading invalid ears - var ears = DrawData.Customize.RaceFeatureType; - DrawData.Customize.RaceFeatureType = ears switch { - > 4 => 1, - 0 => 4, - _ => ears - }; - } - - var res = UpdateCustomize(); - if (!res) { - Logger.Warning("Failed to update character. Forcing redraw."); - Redraw(faceHack); - } else if (cur.BustSize != custom.BustSize && Model != null) { - Model->ScaleBust(); - } + DrawData.Customize = custom; + var redraw = !UpdateCustomize() + || faceHack + || cur.Tribe != custom.Tribe + || cur.Gender != custom.Gender; + + if (redraw) { + Redraw(); + } else if (cur.BustSize != custom.BustSize && Model != null) { + Model->ScaleBust(); } } // Actor redraw - public void Redraw(bool faceHack = false) { - faceHack &= GameObject.ObjectKind == (byte)ObjectKind.Pc; + public void Redraw() { + var faceHack = GameObject.ObjectKind == ObjectKind.Pc; GameObject.DisableDraw(); - if (faceHack) GameObject.ObjectKind = (byte)ObjectKind.BattleNpc; + if (faceHack) GameObject.ObjectKind = ObjectKind.BattleNpc; GameObject.EnableDraw(); - if (faceHack) GameObject.ObjectKind = (byte)ObjectKind.Pc; + if (faceHack) GameObject.ObjectKind = ObjectKind.Pc; } // weapons diff --git a/Ktisis/Structs/Actor/ActorDrawData.cs b/Ktisis/Structs/Actor/ActorDrawData.cs index b752bc614..1341eee9d 100644 --- a/Ktisis/Structs/Actor/ActorDrawData.cs +++ b/Ktisis/Structs/Actor/ActorDrawData.cs @@ -4,10 +4,12 @@ namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] public struct ActorDrawData { [FieldOffset(0x010)] public Weapon MainHand; - [FieldOffset(0x078)] public Weapon OffHand; - [FieldOffset(0x0E0)] public Weapon Prop; + [FieldOffset(0x080)] public Weapon OffHand; + [FieldOffset(0x0F0)] public Weapon Prop; - [FieldOffset(0x148)] public Equipment Equipment; - [FieldOffset(0x170)] public Customize Customize; + [FieldOffset(0x1D0)] public Equipment Equipment; + [FieldOffset(0x220)] public Customize Customize; + + [FieldOffset(0x240)] public ushort Glasses; } -} \ No newline at end of file +} diff --git a/Ktisis/Structs/Actor/ActorModel.cs b/Ktisis/Structs/Actor/ActorModel.cs index 353578622..9318ff161 100644 --- a/Ktisis/Structs/Actor/ActorModel.cs +++ b/Ktisis/Structs/Actor/ActorModel.cs @@ -2,9 +2,11 @@ using System.Runtime.InteropServices; using System.Collections.Generic; -using FFXIVClientStructs.Havok; -using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; + +using ModelType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.CharacterBase.ModelType; namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] @@ -24,10 +26,36 @@ public struct ActorModel { [FieldOffset(0x148)] public unsafe Breasts* Bust; - [FieldOffset(0x274)] public float Height; + [FieldOffset(0x2A4)] public float Height; + + [FieldOffset(0x2E0)] public float WeatherWetness; // Set to 1.0f when raining and not covered or umbrella'd + [FieldOffset(0x2E4)] public float SwimmingWetness; // Set to 1.0f when in water + [FieldOffset(0x2E8)] public float WetnessDepth; // Set to ~character height in GPose and higher values when swimming or diving. [FieldOffset(0x370)] public nint Sklb; + [FieldOffset(0xA20)] public Customize Customize; + + [FieldOffset(0xA28)] public unsafe fixed ulong DemiEquip[5]; + [FieldOffset(0xA40)] public unsafe fixed ulong HumanEquip[11]; + + private unsafe CharacterBase* AsCharacter() { + fixed (ActorModel* self = &this) + return (CharacterBase*)self; + } + + public unsafe bool IsHuman() + => AsCharacter()->GetModelType() == ModelType.Human; + + public unsafe Customize? GetCustomize() + => IsHuman() ? this.Customize : null; + + public unsafe ItemEquip GetEquipSlot(int slot) => AsCharacter()->GetModelType() switch { + ModelType.Human => (ItemEquip)this.HumanEquip[slot], + ModelType.DemiHuman => slot < 5 ? (ItemEquip)this.DemiEquip[slot] : default, + _ => default + }; + public unsafe void SyncModelSpace(bool refPose = false) { if (Skeleton == null) return; diff --git a/Ktisis/Structs/Actor/Customize.cs b/Ktisis/Structs/Actor/Customize.cs index f7e7b6449..25a019dc9 100644 --- a/Ktisis/Structs/Actor/Customize.cs +++ b/Ktisis/Structs/Actor/Customize.cs @@ -6,7 +6,9 @@ namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit, Size = 0x1A)] public unsafe struct Customize { - [FieldOffset(0)] public fixed byte Bytes[0x1A]; + public const int Length = 0x1A; + + [FieldOffset(0)] public fixed byte Bytes[Customize.Length]; // this is auto-generated [FieldOffset((int)CustomizeIndex.BustSize)] public byte BustSize; @@ -42,6 +44,16 @@ public byte GetRaceTribeIndex() => (byte)((byte)Race * 2 - 1); public uint GetMakeIndex() => (((uint)Race - 1) * 4) + (((uint)Tribe - GetRaceTribeIndex()) * 2) + (uint)Gender; // Thanks cait + + public static Customize FromBytes(byte[] bytes) { + if (bytes.Length != Customize.Length) + throw new Exception($"Unexpected length for customize array: {bytes.Length} != {Customize.Length}"); + + var custom = new Customize(); + for (var i = 0; i < Customize.Length; i++) + custom.Bytes[i] = bytes[i]; + return custom; + } } [Flags] diff --git a/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs b/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs index 19278f020..e12f7de02 100644 --- a/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs +++ b/Ktisis/Structs/Actor/Equip/SetSources/GearSet.cs @@ -1,5 +1,4 @@ using System.Linq; -using System.Text; using System.Collections.Generic; using FFXIVClientStructs.FFXIV.Client.Game; @@ -17,10 +16,10 @@ public static unsafe Dictionary List() { var raptureGearsetModule = RaptureGearsetModule.Instance(); for (var i = 0; i < _gearSetNumber; i++) { - var gearset = raptureGearsetModule->Gearset[i]; - if (gearset->ID != i) break; + var gearset = raptureGearsetModule->GetGearset(i); + if (gearset->Id != i) break; if (!gearset->Flags.HasFlag(RaptureGearsetModule.GearsetFlag.Exists)) continue; - nameList.Add(i, Encoding.UTF8.GetString(gearset->Name, 0x2F)); + nameList.Add(i, gearset->NameString); } return nameList; @@ -28,7 +27,7 @@ public static unsafe Dictionary List() { public static unsafe List<(EquipSlot, object)> GetEquipForSet(Set set) { List<(EquipSlot, object)> itemsToEquip = new(); - var gearset = RaptureGearsetModule.Instance()->Gearset[set.ID]; + var gearset = RaptureGearsetModule.Instance()->GetGearset(set.ID); // find inventory containers InventoryType[] inventoryTypes = { @@ -58,18 +57,18 @@ public static unsafe Dictionary List() { // get item IDs from gearset List<(uint, EquipSlot)> itemsToRemodel = new() { - (gearset->MainHand.ItemID, EquipSlot.MainHand), - (gearset->OffHand.ItemID, EquipSlot.OffHand), - (gearset->Head.ItemID, EquipSlot.Head), - (gearset->Body.ItemID, EquipSlot.Chest), - (gearset->Hands.ItemID, EquipSlot.Hands), - (gearset->Legs.ItemID, EquipSlot.Legs), - (gearset->Feet.ItemID, EquipSlot.Feet), - (gearset->Ears.ItemID, EquipSlot.Earring), - (gearset->Neck.ItemID, EquipSlot.Necklace), - (gearset->Wrists.ItemID, EquipSlot.Bracelet), - (gearset->RightLeft.ItemID, EquipSlot.RingLeft), - (gearset->RingRight.ItemID, EquipSlot.RingRight), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.MainHand).ItemId, EquipSlot.MainHand), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.OffHand).ItemId, EquipSlot.OffHand), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Head).ItemId, EquipSlot.Head), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Body).ItemId, EquipSlot.Chest), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Hands).ItemId, EquipSlot.Hands), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Legs).ItemId, EquipSlot.Legs), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Feet).ItemId, EquipSlot.Feet), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Ears).ItemId, EquipSlot.Earring), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Neck).ItemId, EquipSlot.Necklace), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.Wrists).ItemId, EquipSlot.Bracelet), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.RingLeft).ItemId, EquipSlot.RingLeft), + (gearset->GetItem(RaptureGearsetModule.GearsetItemIndex.RingRight).ItemId, EquipSlot.RingRight), }; @@ -84,12 +83,12 @@ public static unsafe Dictionary List() { InventoryItem? invItem = null; // get the inventory item by the gearset item id - var invItems = inventoryItems.Where(i => i.ItemID == id); - if (!invItems.Any()) invItems = inventoryItems.Where(i => i.ItemID == uint.Parse(id.ToString()[2..])); // not sure why, sometimes item IDs have numbers prepended to them (mostly "10") + var invItems = inventoryItems.Where(i => i.ItemId == id); + if (!invItems.Any()) invItems = inventoryItems.Where(i => i.ItemId == uint.Parse(id.ToString()[2..])); // not sure why, sometimes item IDs have numbers prepended to them (mostly "10") if (invItems.Any()) invItem = invItems.First(); // get the Item that contains the model Id - var items = Sets.ItemsSheet.Where(i => i.RowId == (invItem?.GlamourID == 0 ? invItem?.ItemID : invItem?.GlamourID)); + var items = Sets.ItemsSheet.Where(i => i.RowId == (invItem?.GlamourId == 0 ? invItem?.ItemId : invItem?.GlamourId)); if (items.Any()) item = items.First(); if (item == null) { @@ -98,7 +97,7 @@ public static unsafe Dictionary List() { continue; } - byte dye = (invItem?.Stain) ?? default; + byte dye = (invItem?.GetStain(0)) ?? default; itemsToEquip.Add((slot, Sets.ItemToEquipObject(item, dye, slot))); } diff --git a/Ktisis/Structs/Actor/Equip/SetSources/GlamourDresser.cs b/Ktisis/Structs/Actor/Equip/SetSources/GlamourDresser.cs index a72c9ad68..8d814e8cb 100644 --- a/Ktisis/Structs/Actor/Equip/SetSources/GlamourDresser.cs +++ b/Ktisis/Structs/Actor/Equip/SetSources/GlamourDresser.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json; using FFXIVClientStructs.FFXIV.Client.Game; +using FFXIVClientStructs.FFXIV.Client.UI; using Ktisis.Data.Excel; using Ktisis.Structs.FFXIV; @@ -117,7 +118,7 @@ public static void LoadGlamourPlatesIntoMemory() { internal static void PopupOfferOpenGlamourPlates_open() { // This is a way to actively get the data, with the user's authorization - if (GameMain.IsInSanctuary()) + if (UIGlobals.CanApplyGlamourPlates()) Interface.Components.Equipment.OpenGlamourQuestionPopup(); } public static EquipSlot GlamourPlateSlotToEquipSlot(GlamourPlateSlot slot) => (EquipSlot)((int)slot + ((int)slot > 4 ? 1 : 0)); diff --git a/Ktisis/Structs/Actor/Equipment.cs b/Ktisis/Structs/Actor/Equipment.cs index ba970f2cc..dc7d2dc50 100644 --- a/Ktisis/Structs/Actor/Equipment.cs +++ b/Ktisis/Structs/Actor/Equipment.cs @@ -1,35 +1,62 @@ using System.Runtime.InteropServices; +using Ktisis.Structs.Actor.Types; + namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] public struct Equipment { - [FieldOffset(0)] public unsafe fixed uint Slots[0x4 * 10]; + public const int SlotCount = 10; + + [FieldOffset(0)] public unsafe fixed ulong Slots[0x4 * SlotCount]; [FieldOffset(0x00)] public ItemEquip Head; - [FieldOffset(0x04)] public ItemEquip Chest; - [FieldOffset(0x08)] public ItemEquip Hands; - [FieldOffset(0x0C)] public ItemEquip Legs; - [FieldOffset(0x10)] public ItemEquip Feet; - [FieldOffset(0x14)] public ItemEquip Earring; - [FieldOffset(0x18)] public ItemEquip Necklace; - [FieldOffset(0x1C)] public ItemEquip Bracelet; - [FieldOffset(0x20)] public ItemEquip RingRight; - [FieldOffset(0x24)] public ItemEquip RingLeft; + [FieldOffset(0x08)] public ItemEquip Chest; + [FieldOffset(0x10)] public ItemEquip Hands; + [FieldOffset(0x18)] public ItemEquip Legs; + [FieldOffset(0x20)] public ItemEquip Feet; + [FieldOffset(0x28)] public ItemEquip Earring; + [FieldOffset(0x30)] public ItemEquip Necklace; + [FieldOffset(0x38)] public ItemEquip Bracelet; + [FieldOffset(0x40)] public ItemEquip RingRight; + [FieldOffset(0x48)] public ItemEquip RingLeft; } - [StructLayout(LayoutKind.Explicit, Size = 0x4)] - public struct ItemEquip { + [StructLayout(LayoutKind.Explicit, Size = 0x8)] + public struct ItemEquip : IEquipItem { [FieldOffset(0)] public ushort Id; [FieldOffset(2)] public byte Variant; [FieldOffset(3)] public byte Dye; + [FieldOffset(4)] public byte Dye2; - public static explicit operator ItemEquip(uint num) => new() { + public static explicit operator ItemEquip(ulong num) => new() { Id = (ushort)(num & 0xFFFF), Variant = (byte)(num >> 16 & 0xFF), - Dye = (byte)(num >> 24) + Dye = (byte)(num >> 24), + Dye2 = (byte)(num >> 32) }; + + public static explicit operator ulong(ItemEquip equip) + => (uint)(equip.Id | (equip.Variant << 16) | (equip.Dye << 24)) | ((ulong)equip.Dye2 << 32); public bool Equals(ItemEquip other) => Id == other.Id && Variant == other.Variant; + + public byte GetDye(int index) { + return index switch { + 1 => this.Dye2, + _ => this.Dye + }; + } + + public void SetDye(int index, byte value) { + switch (index) { + case 0: + this.Dye = value; + break; + case 1: + this.Dye2 = value; + break; + } + } } public enum EquipIndex : uint { diff --git a/Ktisis/Structs/Actor/State/ActorStateWatcher.cs b/Ktisis/Structs/Actor/State/ActorStateWatcher.cs index 44dc1f9e5..39c38db35 100644 --- a/Ktisis/Structs/Actor/State/ActorStateWatcher.cs +++ b/Ktisis/Structs/Actor/State/ActorStateWatcher.cs @@ -1,12 +1,18 @@ -using Dalamud.Game; +using System.Collections.Generic; +using System.Linq; + using Ktisis.Events; -using System; + +using Dalamud.Plugin.Services; + +using Ktisis.Data.Files; namespace Ktisis.Structs.Actor.State { public static class ActorStateWatcher { - private static bool _wasInGPose = false; + private static readonly Dictionary _originalActorData = new(); + public static void Dispose() { Services.Framework.Update -= Monitor; if(Ktisis.IsInGPose) @@ -17,11 +23,38 @@ public static void Init() { Services.Framework.Update += Monitor; } - public static void Monitor(Framework framework) { - if (_wasInGPose != Ktisis.IsInGPose) { - _wasInGPose = Ktisis.IsInGPose; - EventManager.FireOnGposeChangeEvent(Ktisis.IsInGPose); + private static void Monitor(IFramework framework) { + if (_wasInGPose != Ktisis.IsInGPose) + HandleStateChanged(Ktisis.IsInGPose); + } + + private unsafe static void HandleStateChanged(bool state) { + _wasInGPose = state; + EventManager.FireOnGposeChangeEvent(state); + + if (state) { // Enter + foreach (var gameObj in Services.ObjectTable.Where(go => go.ObjectIndex <= 248)) { + var actor = (Actor*)gameObj.Address; + if (actor == null) continue; + + Logger.Debug($"Saving actor data for {actor->GameObject.ObjectIndex} {actor->GetName()}"); + + var save = new AnamCharaFile(); + save.WriteToFile(*actor, AnamCharaFile.SaveModes.All); + _originalActorData.Add(gameObj.ObjectIndex, save); + } + } else { // Exit + _originalActorData.Clear(); } } + + public unsafe static void RevertToOriginal(Actor* actor) { + if (actor == null) return; + + if (!_originalActorData.TryGetValue(actor->GameObject.ObjectIndex, out var save)) + return; + + save.Apply(actor, AnamCharaFile.SaveModes.All); + } } } diff --git a/Ktisis/Structs/Actor/State/ActorWetnessOverride.cs b/Ktisis/Structs/Actor/State/ActorWetnessOverride.cs new file mode 100644 index 000000000..28eb3a2e1 --- /dev/null +++ b/Ktisis/Structs/Actor/State/ActorWetnessOverride.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Threading; + +using Dalamud.Logging; +using Dalamud.Plugin.Services; + +using FFXIVClientStructs.FFXIV.Client.Graphics.Scene; + +using Ktisis.Events; + +namespace Ktisis.Structs.Actor.State +{ + public class ActorWetnessOverride + { + public static ActorWetnessOverride Instance { get; set; } = new(); + + public Dictionary WetnessOverrides = new(); + public Dictionary WetnessOverridesEnabled = new(); + + public void Dispose() { + Services.Framework.Update -= Monitor; + } + + public void Init() { + Services.Framework.Update += Monitor; + EventManager.OnGPoseChange += OnGPoseChange; + } + private void OnGPoseChange(bool isingpose) + { + if (!isingpose) return; + + WetnessOverrides = new(); + WetnessOverridesEnabled = new(); + } + + private unsafe void Monitor(IFramework framework) + { + if (!Ktisis.IsInGPose) return; + + + foreach ((var charAddress, var (weatherWetness, swimmingWetness, wetnessDepth)) in WetnessOverrides) + { + if (WetnessOverridesEnabled.TryGetValue(charAddress, out var enabled) && !enabled) + continue; + + var actor = (Actor*) charAddress; + actor->Model->WeatherWetness = weatherWetness; + actor->Model->SwimmingWetness = swimmingWetness; + actor->Model->WetnessDepth = wetnessDepth; + } + } + } +} diff --git a/Ktisis/Structs/Actor/Types/IEquipItem.cs b/Ktisis/Structs/Actor/Types/IEquipItem.cs new file mode 100644 index 000000000..7ca611705 --- /dev/null +++ b/Ktisis/Structs/Actor/Types/IEquipItem.cs @@ -0,0 +1,7 @@ +namespace Ktisis.Structs.Actor.Types { + public interface IEquipItem { + public byte GetDye(int index); + + public void SetDye(int index, byte value); + } +} \ No newline at end of file diff --git a/Ktisis/Structs/Actor/Weapon.cs b/Ktisis/Structs/Actor/Weapon.cs index 20333b05c..af03b849f 100644 --- a/Ktisis/Structs/Actor/Weapon.cs +++ b/Ktisis/Structs/Actor/Weapon.cs @@ -2,24 +2,55 @@ using System.Numerics; using System.Runtime.InteropServices; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; + +using Ktisis.Structs.Actor.Types; namespace Ktisis.Structs.Actor { [StructLayout(LayoutKind.Explicit)] public struct Weapon { [FieldOffset(0x00)] public WeaponEquip Equip; - [FieldOffset(0x08)] public unsafe WeaponModel* Model; + [FieldOffset(0x18)] public unsafe WeaponModel* Model; [FieldOffset(0x40)] public bool IsSheathed; - [FieldOffset(0x5C)] public WeaponFlags Flags; + [FieldOffset(0x60)] public WeaponFlags Flags; + + public unsafe WeaponEquip GetEquip() + => this.Model != null ? this.Model->Equip : this.Equip; + + public unsafe void SetEquip(WeaponEquip item) { + if (this.Model != null) + this.Model->Equip = item; + } } - [StructLayout(LayoutKind.Explicit)] - public struct WeaponEquip { + [StructLayout(LayoutKind.Explicit, Size = 0x8)] + public struct WeaponEquip : IEquipItem { [FieldOffset(0x00)] public ushort Set; [FieldOffset(0x02)] public ushort Base; [FieldOffset(0x04)] public ushort Variant; [FieldOffset(0x06)] public byte Dye; + [FieldOffset(0x07)] public byte Dye2; + + [FieldOffset(0x00)] public ulong Value; + + public byte GetDye(int index) { + return index switch { + 1 => this.Dye2, + _ => this.Dye + }; + } + + public void SetDye(int index, byte value) { + switch (index) { + case 0: + this.Dye = value; + break; + case 1: + this.Dye2 = value; + break; + } + } } [StructLayout(LayoutKind.Explicit)] @@ -32,6 +63,8 @@ public struct WeaponModel { [FieldOffset(0x88)] public byte Flags; [FieldOffset(0xA0)] public unsafe Skeleton* Skeleton; + + [FieldOffset(0xA20)] public WeaponEquip Equip; } public enum WeaponSlot { diff --git a/Ktisis/Structs/Bones/Bone.cs b/Ktisis/Structs/Bones/Bone.cs index 1a101e30f..3f34a1bd9 100644 --- a/Ktisis/Structs/Bones/Bone.cs +++ b/Ktisis/Structs/Bones/Bone.cs @@ -1,9 +1,9 @@ using System.Numerics; using System.Collections.Generic; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; -using static FFXIVClientStructs.Havok.hkaPose; +using FFXIVClientStructs.Havok.Animation.Rig; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; using Ktisis.Localization; using Ktisis.Structs.Actor; @@ -46,7 +46,7 @@ public unsafe hkQsTransformf Transform { internal List? _setCategory = null; public List Categories => _setCategory ?? Category.GetForBone(HkaBone.Name.String); - public unsafe hkQsTransformf* AccessModelSpace(PropagateOrNot propagate = PropagateOrNot.DontPropagate) => Pose->AccessBoneModelSpace(Index, propagate); + public unsafe hkQsTransformf* AccessModelSpace(hkaPose.PropagateOrNot propagate = hkaPose.PropagateOrNot.DontPropagate) => Pose->AccessBoneModelSpace(Index, propagate); public unsafe hkQsTransformf* AccessLocalSpace() => Pose->AccessBoneLocalSpace(Index); public unsafe Vector3 GetWorldPos(ActorModel* model, ActorModel* parent = null) { @@ -142,7 +142,7 @@ public unsafe void PropagateChildren(hkQsTransformf* transform, Vector3 initialP var descendants = GetDescendants(includePartials, true); foreach (var child in descendants) { - var access = child.AccessModelSpace(PropagateOrNot.DontPropagate); + var access = child.AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); var offset = access->Translation.ToVector3() - sourcePos; offset = Vector3.Transform(offset, deltaRot); @@ -157,7 +157,7 @@ public unsafe void PropagateChildren(hkQsTransformf* transform, Vector3 initialP public unsafe void PropagateSibling(Quaternion deltaRot, SiblingLink mode = SiblingLink.Rotation) { if (mode == SiblingLink.None) return; - var access = AccessModelSpace(PropagateOrNot.DontPropagate); + var access = AccessModelSpace(hkaPose.PropagateOrNot.DontPropagate); var offset = access->Translation.ToVector3(); if (mode == SiblingLink.RotationMirrorX) diff --git a/Ktisis/Structs/Bones/Category.cs b/Ktisis/Structs/Bones/Category.cs index b457dac7b..99af8a16d 100644 --- a/Ktisis/Structs/Bones/Category.cs +++ b/Ktisis/Structs/Bones/Category.cs @@ -126,49 +126,90 @@ static Category() "n_hkata_l", // ShoulderLeft "n_hkata_r", // ShoulderRight "n_hhiji_l", // ElbowLeft - "n_hhiji_r" // ElbowRight - }); - CreateCategory("head", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List { + "n_hhiji_r", // ElbowRight "j_kao", // RootHead - "j_ago", // Jaw - "j_f_dmab_l", // EyelidLowerLeft - "j_f_dmab_r", // EyelidLowerRight + "j_ago" // Jaw + }); + + CreateCategory("eyes", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List() { "j_f_eye_l", // EyeLeft "j_f_eye_r", // EyeRight + "j_f_mab_l", + "j_f_eyepuru_l", + "j_f_mabdn_01_l", + "j_f_mabup_01_l", + "j_f_mabdn_02out_l", + "j_f_mabdn_03in_l", + "j_f_mabup_02out_l", + "j_f_mabup_03in_l", + "j_f_mab_r", + "j_f_eyepuru_r", + "j_f_mabdn_01_r", + "j_f_mabup_01_r", + "j_f_mabdn_02out_r", + "j_f_mabdn_03in_r", + "j_f_mabup_02out_r", + "j_f_mabup_03in_r", + "j_f_mmayu_l", + "j_f_miken_01_l", + "j_f_miken_02_l", + "j_f_mmayu_r", + "j_f_miken_01_r", + "j_f_miken_02_r", + "j_f_mayu_l", // EyebrowLeft + "j_f_mayu_r", // EyebrowRight + }); + + CreateCategory("mouth", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List() { + "j_f_ago", + "j_f_dago", + "j_f_hagukiup", + "j_f_hagukidn", + "j_f_bero_01", + "j_f_bero_02", + "j_f_bero_03", + "j_f_lip_l", // LipsLeft + "j_f_lip_r", // LipsRight + "j_f_dmlip_01_l", + "j_f_dmlip_02_l", + "j_f_umlip_01_l", + "j_f_umlip_02_l", + "j_f_dmlip_01_r", + "j_f_dmlip_02_r", + "j_f_umlip_01_r", + "j_f_umlip_02_r", + "j_f_dlip_01_l", + "j_f_dlip_02_l", + "j_f_ulip_01_l", + "j_f_ulip_02_l", + "j_f_dlip_01_r", + "j_f_dlip_02_r", + "j_f_ulip_01_r", + "j_f_ulip_02_r", + "j_f_uslip_l", + "j_f_dslip_l", + "j_f_uslip_r", + "j_f_dslip_r" + }); + + CreateCategory("face", new Vector4(0.0F, 1.0F, 0.0F, 0.5647059F), new List() { + "j_f_face", "j_f_hana", // Nose + "j_f_hana_l", + "j_f_hana_r", + "j_f_uhana", "j_f_hoho_l", // CheekLeft "j_f_hoho_r", // CheekRight - "j_f_lip_l", // LipsLeft - "j_f_lip_r", // LipsRight - "j_f_mayu_l", // EyebrowLeft - "j_f_mayu_r", // EyebrowRight - "j_f_memoto", // Bridge - "j_f_miken_l", // BrowLeft - "j_f_miken_r", // BrowRight - "j_f_ulip_a", // LipUpperA - "j_f_umab_l", // EyelidUpperLeft - "j_f_umab_r", // EyelidUpperRight - "j_f_dlip_a", // LipLowerA - "j_f_ulip_b", // LipUpperB - "j_f_dlip_b", // LipLowerB - // Hrothgar Faces - "j_f_hige_l", // HrothWhiskersLeft - "j_f_hige_r", // HrothWhiskersRight - //"j_f_mayu_l", // HrothEyebrowLeft - //"j_f_mayu_r", // HrothEyebrowRight - //"j_f_memoto", // HrothBridge - //"j_f_miken_l", // HrothBrowLeft - //"j_f_miken_r", // HrothBrowRight - "j_f_uago", // HrothJawUpper - "j_f_ulip", // HrothLipUpper - //"j_f_umab_l", // HrothEyelidUpperLeft - //"j_f_umab_r", // HrothEyelidUpperRight - "n_f_lip_l", // HrothLipsLeft - "n_f_lip_r", // HrothLipsRight - "n_f_ulip_l", // HrothLipUpperLeft - "n_f_ulip_r", // HrothLipUpperRight - "j_f_dlip", // HrothLipLower + "j_f_dhoho_l", + "j_f_dhoho_r", + "j_f_shoho_l", + "j_f_shoho_r", + "j_f_dmemoto_l", + "j_f_dmemoto_r", + "j_f_dmiken_l", + "j_f_dmiken_r" }); + CreateCategory("hair", new Vector4(0.0F, 0.0F, 1.0F, 0.5647059F), new List { "j_kami_a", // HairA "j_kami_f_l", // HairFrontLeft diff --git a/Ktisis/Structs/Env/EnvManagerEx.cs b/Ktisis/Structs/Env/EnvManagerEx.cs new file mode 100644 index 000000000..00a422c7c --- /dev/null +++ b/Ktisis/Structs/Env/EnvManagerEx.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace Ktisis.Structs.Env { + [StructLayout(LayoutKind.Explicit, Size = 0x900)] + public struct EnvManagerEx { + [FieldOffset(0x08)] public unsafe EnvSceneEx* EnvScene; + + [FieldOffset(0x10)] public float Time; + + [FieldOffset(0x27)] public byte ActiveWeather; + + [FieldOffset(0x58)] public uint SkyId; + } +} diff --git a/Ktisis/Structs/Env/EnvSceneEx.cs b/Ktisis/Structs/Env/EnvSceneEx.cs new file mode 100644 index 000000000..5147edf26 --- /dev/null +++ b/Ktisis/Structs/Env/EnvSceneEx.cs @@ -0,0 +1,17 @@ +using System; +using System.Runtime.InteropServices; + +namespace Ktisis.Structs.Env { + [StructLayout(LayoutKind.Explicit, Size = 0x790)] + public struct EnvSceneEx { + private const int WeatherIdsLength = 32; + + [FieldOffset(0x2C)] public unsafe fixed byte WeatherIds[WeatherIdsLength]; + + public unsafe Span GetWeatherSpan() { + fixed (byte* ptr = this.WeatherIds) { + return new Span(ptr, WeatherIdsLength); + } + } + } +} diff --git a/Ktisis/Structs/Extensions/Camera.cs b/Ktisis/Structs/Extensions/Camera.cs index e746724ab..6b40917f5 100644 --- a/Ktisis/Structs/Extensions/Camera.cs +++ b/Ktisis/Structs/Extensions/Camera.cs @@ -6,12 +6,19 @@ namespace Ktisis.Structs.Extensions { public static class Camera { public unsafe static Matrix4x4 GetProjectionMatrix(this GameCamera camera) { - var ptr = (byte*)&camera; - return *(Matrix4x4*)((IntPtr)camera.CameraBase.SceneCamera.RenderCamera + 80); + var cam = camera.CameraBase.SceneCamera.RenderCamera; + var proj = cam->ProjectionMatrix; + + var far = cam->FarPlane; + var near = cam->NearPlane; + var clip = far / (far - near); + proj.M43 = -(clip * near); + proj.M33 = -((far + near) / (far - near)); + + return proj; } public unsafe static Matrix4x4 GetViewMatrix(this GameCamera camera) { - var ptr = (byte*)&camera; - var view = *(Matrix4x4*)(ptr + 0xB0); + var view = camera.CameraBase.SceneCamera.ViewMatrix; view.M44 = 1; return view; } diff --git a/Ktisis/Structs/Extensions/ExcelPage.cs b/Ktisis/Structs/Extensions/ExcelPage.cs new file mode 100644 index 000000000..91f0ccbcf --- /dev/null +++ b/Ktisis/Structs/Extensions/ExcelPage.cs @@ -0,0 +1,45 @@ +using System; + +using Dalamud.Utility; + +using Lumina.Data.Structs.Excel; +using Lumina.Excel; + +namespace Ktisis.Structs.Extensions { + public static class ExcelPageExtensions { + public static RowRef ReadRowRef(this ExcelPage page, int columnIndex, uint offset) where T : struct, IExcelRow { + var rowId = GetAndReadColumn(page, columnIndex, offset); + return new RowRef(page.Module, Convert.ToUInt32(rowId), page.Language); + } + + public static T ReadColumn(this ExcelPage page, int columnIndex, uint offset) { + return (T)GetAndReadColumn(page, columnIndex, offset); + } + + private static object GetAndReadColumn(ExcelPage page, int columnIndex, uint offset) { + var column = page.Sheet.Columns[columnIndex]; + return column.Type switch { + ExcelColumnDataType.String => page.ReadString(column.Offset + offset, offset).ExtractText(), + ExcelColumnDataType.Bool => page.ReadBool(column.Offset + offset), + ExcelColumnDataType.Int8 => page.ReadInt8(column.Offset + offset), + ExcelColumnDataType.UInt8 => page.ReadUInt8(column.Offset + offset), + ExcelColumnDataType.Int16 => page.ReadInt16(column.Offset + offset), + ExcelColumnDataType.UInt16 => page.ReadUInt16(column.Offset + offset), + ExcelColumnDataType.Int32 => page.ReadInt32(column.Offset + offset), + ExcelColumnDataType.UInt32 => page.ReadUInt32(column.Offset + offset), + ExcelColumnDataType.Float32 => page.ReadFloat32(column.Offset + offset), + ExcelColumnDataType.Int64 => page.ReadInt64(column.Offset + offset), + ExcelColumnDataType.UInt64 => page.ReadUInt64(column.Offset + offset), + ExcelColumnDataType.PackedBool0 => page.ReadPackedBool(column.Offset + offset, 0), + ExcelColumnDataType.PackedBool1 => page.ReadPackedBool(column.Offset + offset, 1), + ExcelColumnDataType.PackedBool2 => page.ReadPackedBool(column.Offset + offset, 2), + ExcelColumnDataType.PackedBool3 => page.ReadPackedBool(column.Offset + offset, 3), + ExcelColumnDataType.PackedBool4 => page.ReadPackedBool(column.Offset + offset, 4), + ExcelColumnDataType.PackedBool5 => page.ReadPackedBool(column.Offset + offset, 5), + ExcelColumnDataType.PackedBool6 => page.ReadPackedBool(column.Offset + offset, 6), + ExcelColumnDataType.PackedBool7 => page.ReadPackedBool(column.Offset + offset, 7), + _ => throw new Exception($"Unknown type: {column.Type}") + }; + } + } +} \ No newline at end of file diff --git a/Ktisis/Structs/Extensions/Havok.cs b/Ktisis/Structs/Extensions/Havok.cs index 50ae7d909..8fe9d9acb 100644 --- a/Ktisis/Structs/Extensions/Havok.cs +++ b/Ktisis/Structs/Extensions/Havok.cs @@ -1,7 +1,11 @@ using System.Numerics; -using FFXIVClientStructs.Havok; using FFXIVClientStructs.FFXIV.Client.Graphics.Render; +using FFXIVClientStructs.Havok.Animation.Rig; +using FFXIVClientStructs.Havok.Common.Base.Container.Array; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; +using FFXIVClientStructs.Havok.Common.Base.Math.Quaternion; +using FFXIVClientStructs.Havok.Common.Base.Math.Vector; using Ktisis.Structs.Bones; diff --git a/Ktisis/Structs/Extensions/RowParser.cs b/Ktisis/Structs/Extensions/RowParser.cs new file mode 100644 index 000000000..88f6f025c --- /dev/null +++ b/Ktisis/Structs/Extensions/RowParser.cs @@ -0,0 +1,50 @@ +using Lumina.Excel; +using Lumina.Data.Parsing; + +using Ktisis.Structs.Actor; + +namespace Ktisis.Structs.Extensions { + public static class RowParserExtensions { + public static Customize ReadCustomize(this ExcelPage parser, int index, uint offset) { + var result = new byte[Customize.Length]; + for (var i = 0; i < Customize.Length; i++) + result[i] = parser.ReadColumn(index + i, offset); + return Customize.FromBytes(result); + } + + public static WeaponEquip ReadWeapon(this ExcelPage parser, int index, uint offset) { + var data = parser.ReadColumn(index, offset); + var dye = parser.ReadColumn(index + 1, offset); + var dye2 = parser.ReadColumn(index + 2, offset); + + var quad = (Quad)data; + return new WeaponEquip { + Set = quad.A, + Base = quad.B, + Variant = quad.C, + Dye = dye, + Dye2 = dye2 + }; + } + + public static ItemEquip ReadItem(this ExcelPage parser, int index, uint offset) { + var model = parser.ReadColumn(index, offset); + var dye = parser.ReadColumn(index + 1, offset); + var dye2 = parser.ReadColumn(index + 2, offset); + + return new ItemEquip { + Id = (ushort)model, + Variant = (byte)(model >> 16), + Dye = dye, + Dye2 = dye2 + }; + } + + public unsafe static Equipment ReadEquipment(this ExcelPage parser, int index, uint offset) { + var result = new Equipment(); + for (var i = 0; i < Equipment.SlotCount; i++) + result.Slots[i] = (ulong)parser.ReadItem(index + i * 3 + (i > 0 ? 2 : 0), offset); + return result; + } + } +} diff --git a/Ktisis/Structs/Extensions/SeString.cs b/Ktisis/Structs/Extensions/SeString.cs new file mode 100644 index 000000000..b80f3c20f --- /dev/null +++ b/Ktisis/Structs/Extensions/SeString.cs @@ -0,0 +1,19 @@ +using System.Linq; + +using Dalamud.Utility; + +using Lumina.Text; + +namespace Ktisis.Structs.Extensions { + public static class SeStringExtensions { + public static string? FormatName(this string name, sbyte article) { + if (name.IsNullOrEmpty()) return null; + + return article == 1 ? name : string.Join(' ', name.Split(' ').Select((word, index) => { + if (word.Length <= 1 || index > 0 && word is "of" or "the" or "and") + return word; + return word[0].ToString().ToUpper() + word[1..]; + })); + } + } +} diff --git a/Ktisis/Structs/FFXIV/GPoseCamera.cs b/Ktisis/Structs/FFXIV/GPoseCamera.cs index 60ba24657..a12d4f3d5 100644 --- a/Ktisis/Structs/FFXIV/GPoseCamera.cs +++ b/Ktisis/Structs/FFXIV/GPoseCamera.cs @@ -8,13 +8,16 @@ namespace Ktisis.Structs.FFXIV { public struct GPoseCamera { [FieldOffset(0x60)] public Vector3 Position; - [FieldOffset(0x114)] public float Distance; - [FieldOffset(0x11C)] public float DistanceMax; - [FieldOffset(0x12C)] public float FoV; - [FieldOffset(0x130)] public Vector2 Angle; - [FieldOffset(0x150)] public Vector2 Pan; - [FieldOffset(0x160)] public float Rotation; - [FieldOffset(0x208)] public Vector2 DistanceCollide; + [FieldOffset(0x124)] public float Distance; + [FieldOffset(0x128)] public float DistanceMin; + [FieldOffset(0x12C)] public float DistanceMax; + [FieldOffset(0x13C)] public float FoV; + [FieldOffset(0x140)] public Vector2 Angle; + [FieldOffset(0x15C)] public float YMin; + [FieldOffset(0x158)] public float YMax; + [FieldOffset(0x160)] public Vector2 Pan; + [FieldOffset(0x170)] public float Rotation; + [FieldOffset(0x218)] public Vector2 DistanceCollide; public Vector3 CalcRotation() => new(Angle.X - Pan.X, -Angle.Y - Pan.Y, Rotation); } diff --git a/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs b/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs index 83ae85280..e19a908e2 100644 --- a/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs +++ b/Ktisis/Structs/FFXIV/MiragePrismMiragePlate.cs @@ -4,7 +4,6 @@ using FFXIVClientStructs.Attributes; using FFXIVClientStructs.FFXIV.Client.System.Framework; using FFXIVClientStructs.FFXIV.Client.UI.Agent; -using FFXIVClientStructs.FFXIV.Component.GUI; using Ktisis.Structs.Actor.Equip.SetSources; @@ -20,7 +19,7 @@ public unsafe partial struct MiragePrismMiragePlate { //[FieldOffset(40 + 36)] public IntPtr* PlatesPointer; //[FieldOffset(40 + 36)] public fixed MiragePage Plates[20]; // This would be ideal, TODO: try to find a way to achieve this - internal static AgentInterface* MiragePlateAgent() => Framework.Instance()->GetUiModule()->GetAgentModule()->GetAgentByInternalId(AgentId.MiragePrismMiragePlate); + internal static AgentInterface* MiragePlateAgent() => Framework.Instance()->GetUIModule()->GetAgentModule()->GetAgentByInternalId(AgentId.MiragePrismMiragePlate); // this getter exists because we cannot specify a sized array in the variable public MiragePage[] Pages { diff --git a/Ktisis/Structs/FFXIV/WorldMatrix.cs b/Ktisis/Structs/FFXIV/WorldMatrix.cs index 7bd4bd4c5..81828393d 100644 --- a/Ktisis/Structs/FFXIV/WorldMatrix.cs +++ b/Ktisis/Structs/FFXIV/WorldMatrix.cs @@ -3,6 +3,8 @@ using System.Numerics; using System.Runtime.InteropServices; +using Dalamud.Interface.Utility; + namespace Ktisis.Structs.FFXIV { [StructLayout(LayoutKind.Explicit, Size = 0x1FC)] public partial struct WorldMatrix { @@ -20,18 +22,16 @@ public bool WorldToScreen(Vector3 v, out Vector2 pos2d) { public bool WorldToScreenDepth(Vector3 v, out Vector3 pos2d) { var m = Matrix; - var windowPos = ImGuiHelpers.MainViewport.Pos; - - float x = (m.M11 * v.X) + (m.M21 * v.Y) + (m.M31 * v.Z) + m.M41; - float y = (m.M12 * v.X) + (m.M22 * v.Y) + (m.M32 * v.Z) + m.M42; - float w = (m.M14 * v.X) + (m.M24 * v.Y) + (m.M34 * v.Z) + m.M44; - - float camX = (Width / 2f); - float camY = (Height / 2f); + var x = (m.M11 * v.X) + (m.M21 * v.Y) + (m.M31 * v.Z) + m.M41; + var y = (m.M12 * v.X) + (m.M22 * v.Y) + (m.M32 * v.Z) + m.M42; + var w = (m.M14 * v.X) + (m.M24 * v.Y) + (m.M34 * v.Z) + m.M44; + var view = ImGuiHelpers.MainViewport; + var camX = (view.Size.X / 2f); + var camY = (view.Size.Y / 2f); pos2d = new Vector3( - camX + (camX * x / w) + windowPos.X, - camY - (camY * y / w) + windowPos.Y, + camX + (camX * x / w) + view.Pos.X, + camY - (camY * y / w) + view.Pos.Y, w ); diff --git a/Ktisis/Structs/Poses/PoseContainer.cs b/Ktisis/Structs/Poses/PoseContainer.cs index 30e071267..99b4c7e8c 100644 --- a/Ktisis/Structs/Poses/PoseContainer.cs +++ b/Ktisis/Structs/Poses/PoseContainer.cs @@ -52,7 +52,7 @@ public unsafe void ApplyToPartial(Skeleton* modelSkeleton, int p, PoseTransforms var owner = modelSkeleton->Owner; if (owner != null && owner->GetModelType() == CharacterBase.ModelType.Human) { var human = (Human*)owner; - isElezen = human->Race == (byte)Race.Elezen; + isElezen = human->Customize.Race == (byte)Race.Elezen; } var partial = modelSkeleton->PartialSkeletons[p]; diff --git a/Ktisis/Structs/Poses/Transform.cs b/Ktisis/Structs/Poses/Transform.cs index 2088d4bb9..5d7e66d6e 100644 --- a/Ktisis/Structs/Poses/Transform.cs +++ b/Ktisis/Structs/Poses/Transform.cs @@ -1,6 +1,6 @@ using System.Numerics; -using FFXIVClientStructs.Havok; +using FFXIVClientStructs.Havok.Common.Base.Math.QsTransform; namespace Ktisis.Structs.Poses { public class Transform { diff --git a/Ktisis/Util/GuiHelpers.cs b/Ktisis/Util/GuiHelpers.cs index a72998191..28465b12f 100644 --- a/Ktisis/Util/GuiHelpers.cs +++ b/Ktisis/Util/GuiHelpers.cs @@ -1,8 +1,7 @@ using System; using System.Numerics; -using ImGuiNET; - +using Dalamud.Bindings.ImGui; using Dalamud.Interface; using Ktisis.Interface.Components; @@ -134,16 +133,19 @@ public static void PopupConfirm(string label, Action contents, Action? onAccept, public static Vector4 VisibleCheckmarkColor() { var currentCol = ImGui.GetStyle().Colors[(int)ImGuiCol.CheckMark]; - ImGui.ColorConvertRGBtoHSV(currentCol.X, currentCol.Y, currentCol.Z, out var h, out var s, out var v); + var h = 0.0f; + var s = 0.0f; + var v = 0.0f; + ImGui.ColorConvertRGBtoHSV(currentCol.X, currentCol.Y, currentCol.Z, ref h, ref s, ref v); s = 0.55f; v = Math.Clamp(v * 1.25f, 0.0f, 1.0f); - ImGui.ColorConvertHSVtoRGB(h, s, v, out currentCol.X, out currentCol.Y, out currentCol.Z); + ImGui.ColorConvertHSVtoRGB(h, s, v, ref currentCol.X, ref currentCol.Y, ref currentCol.Z); return currentCol; } // Copy from Dalamud's ToggleButton but with colorizable circle public static bool ToggleButton(string id, ref bool v, Vector4 circleColor) { - RangeAccessor colors = ImGui.GetStyle().Colors; + var colors = ImGui.GetStyle().Colors; Vector2 cursorScreenPos = ImGui.GetCursorScreenPos(); ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList(); float frameHeight = ImGui.GetFrameHeight(); diff --git a/Ktisis/Util/NpcImportService.cs b/Ktisis/Util/NpcImportService.cs new file mode 100644 index 000000000..64be7ed4b --- /dev/null +++ b/Ktisis/Util/NpcImportService.cs @@ -0,0 +1,109 @@ +using System.IO; +using System.Linq; +using System.Reflection; +using System.Diagnostics; +using System.Threading.Tasks; +using System.Collections.Generic; + +using Newtonsoft.Json; + +using BNpcName = Lumina.Excel.Sheets.BNpcName; + +using Ktisis.Data.Npc; +using Ktisis.Data.Excel; +using Ktisis.Structs.Extensions; + +namespace Ktisis.Util { + public static class NpcImportService { + // Name index + + private static Stream GetNameIndexStream() { + var assembly = Assembly.GetExecutingAssembly(); + var assemblyName = assembly.GetName().Name!; + + var path = $"{assemblyName}.Data.Library.bnpc-index.json"; + + var stream = assembly.GetManifestResourceStream(path); + if (stream == null) + throw new FileNotFoundException(path); + + return stream; + } + + private static async Task> GetNameIndex() { + var stream = GetNameIndexStream(); + + using var reader = new StreamReader(stream); + + var content = await reader.ReadToEndAsync(); + var dict = JsonConvert.DeserializeObject>(content); + + return dict ?? new Dictionary(); + } + + // NPC List + + public static async Task> GetNpcList() { + await Task.Yield(); + + var timer = new Stopwatch(); + timer.Start(); + + var result = Enumerable.Empty(); + + var battleTask = GetBattleNpcs(); + var residentTask = GetResidentNpcs(); + await Task.WhenAll(battleTask, residentTask); + + if (battleTask.Result != null) + result = result.Concat(battleTask.Result); + + if (residentTask.Result != null) + result = result.Concat(residentTask.Result); + + var list = result.DistinctBy(npc => ( + npc.Name, + npc.GetModelId(), + npc.GetCustomize(), + npc.GetEquipment() + )); + + timer.Stop(); + Logger.Information($"NPC list retrieved in {timer.Elapsed.TotalMilliseconds:0.00}ms"); + + return list; + } + + // BattleNpcs + + private static async Task?> GetBattleNpcs() { + await Task.Yield(); + + var nameIndexTask = GetNameIndex(); + + var npcSheet = Services.DataManager.GetExcelSheet(); + var namesSheet = Services.DataManager.GetExcelSheet(); + + var nameIndexDict = await nameIndexTask; + return npcSheet.Skip(1).Select(row => { + string? name = null; + if (nameIndexDict.TryGetValue(row.RowId.ToString(), out var nameIndex) && namesSheet.HasRow(nameIndex)) { + var nameRow = namesSheet.GetRow(nameIndex); + name = nameRow.Singular.ExtractText().FormatName(nameRow.Article); + } + + row.Name = name ?? $"B:{row.RowId:D7}"; + return row as INpcBase; + }); + } + + // ResidentNpcs + + private static async Task> GetResidentNpcs() { + await Task.Yield(); + + var npcSheet = Services.DataManager.GetExcelSheet(); + return npcSheet.Where(npc => npc.Map != 0).Cast(); + } + } +} diff --git a/Ktisis/Util/PoseAutoSave.cs b/Ktisis/Util/PoseAutoSave.cs new file mode 100644 index 000000000..9203b4b22 --- /dev/null +++ b/Ktisis/Util/PoseAutoSave.cs @@ -0,0 +1,143 @@ +using System; +using System.IO; +using System.Timers; +using System.Collections.Generic; +using System.Linq; + +using Ktisis.Helpers; +using Ktisis.Structs.Actor; +using Ktisis.Structs.Poses; +using Ktisis.Interface.Components; +using Ktisis.Interop.Hooks; + +namespace Ktisis.Util { + internal class PoseAutoSave { + private Queue prefixes = new(); + private Timer? _timer = null; + private string SaveFolder => Ktisis.Configuration.AutoSavePath; + + public void Enable() { + if (!Ktisis.Configuration.EnableAutoSave) + return; + + if (!Directory.Exists(SaveFolder)) + Directory.CreateDirectory(SaveFolder); + + _timer = new Timer(TimeSpan.FromSeconds(Ktisis.Configuration.AutoSaveInterval)); + _timer.Elapsed += OnElapsed; + _timer.AutoReset = true; + + _timer.Start(); + prefixes.Clear(); + } + + public void Disable() { + lock (this) { + _timer?.Stop(); + + if (!Ktisis.Configuration.ClearAutoSavesOnExit || Ktisis.Configuration.AutoSaveCount <= 0) + return; + + while (prefixes.Count > 0) { + DeleteOldest(); + } + } + } + + private void OnElapsed(object? sender, ElapsedEventArgs e) { + Services.Framework.RunOnFrameworkThread(Save); + } + + internal void UpdateSettings() { + var timerEnabled = _timer?.Enabled ?? false; + var cfg = Ktisis.Configuration; + + if (!timerEnabled && cfg.EnableAutoSave && PoseHooks.PosingEnabled) + Enable(); + else if (timerEnabled && !cfg.EnableAutoSave && PoseHooks.PosingEnabled) + Disable(); + + if (_timer is not null && Math.Abs(_timer.Interval - TimeSpan.FromSeconds(cfg.AutoSaveInterval).TotalMilliseconds) > 0.01) + _timer.Interval = TimeSpan.FromSeconds(cfg.AutoSaveInterval).TotalMilliseconds; + } + + private void Save() { + if (!Ktisis.IsInGPose) { + Disable(); + return; + } + + var actors = ActorsList.SavedObjects; + + Logger.Information($"Saving {actors.Count} actors"); + + // var prefix = $"AutoSave - {DateTime.Now:yyyy-MM-dd HH-mm-ss}"; + var prefix = PathHelper.Replace(Ktisis.Configuration.AutoSaveFormat); + var folder = Path.Combine(SaveFolder, prefix); + prefixes.Enqueue(prefix); + + if (!Directory.Exists(folder)) + Directory.CreateDirectory(folder); + + unsafe { + foreach (var actorPtr in actors) { + var actor = (Actor*)actorPtr; + var filename = $"{actor->GetNameOrId()}.pose"; + Logger.Information($"Saving {filename}"); + + var path = Path.Combine(folder, filename); + Logger.Verbose($"Saving to {path}"); + + PoseHelpers.ExportPose(actor, path, PoseMode.All); + } + } + + Logger.Verbose($"Prefix count: {prefixes.Count} max: {Ktisis.Configuration.AutoSaveCount}"); + + //Clear old saves + while (prefixes.Count > Ktisis.Configuration.AutoSaveCount) { + DeleteOldest(); + } + } + + private void DeleteOldest() { + var oldest = prefixes.Dequeue(); + var folder = Path.Combine(SaveFolder, oldest); + if (Directory.Exists(folder)) { + Logger.Verbose($"Deleting {folder}"); + Directory.Delete(folder, true); + } + + DeleteEmptyDirs(SaveFolder); + } + + static void DeleteEmptyDirs(string dir) + { + if (string.IsNullOrEmpty(dir)) + throw new ArgumentException( + "Starting directory is a null reference or an empty string", + nameof(dir)); + + try + { + foreach (var d in Directory.EnumerateDirectories(dir)) + { + DeleteEmptyDirs(d); + } + + var entries = Directory.EnumerateFileSystemEntries(dir); + + if (entries.Any()) + return; + + try + { + Directory.Delete(dir); + } + catch (UnauthorizedAccessException) { } + catch (DirectoryNotFoundException) { } + } + catch (UnauthorizedAccessException) { } + } + } +} diff --git a/Ktisis/packages.lock.json b/Ktisis/packages.lock.json index a5d13fa4e..fff6485c7 100644 --- a/Ktisis/packages.lock.json +++ b/Ktisis/packages.lock.json @@ -1,18 +1,52 @@ { "version": 1, "dependencies": { - "net7.0-windows7.0": { + "net10.0-windows7.0": { "DalamudPackager": { "type": "Direct", - "requested": "[2.1.6, )", - "resolved": "2.1.6", - "contentHash": "JGgpGP2FMM5Vt4utyDD+xV2+XXfo3Rb3VgJ4FnvzkWlvn4JG/bBILo6mDubWCPjDGqT0n6dF1JRG0r5ygLv/ng==" + "requested": "[2.1.12, )", + "resolved": "2.1.12", + "contentHash": "Sc0PVxvgg4NQjcI8n10/VfUQBAS4O+Fw2pZrAqBdRMbthYGeogzu5+xmIGCGmsEZ/ukMOBuAqiNiB5qA3MRalg==" }, "JetBrains.Annotations": { "type": "Direct", "requested": "[2022.3.1, )", "resolved": "2022.3.1", "contentHash": "11nsS3+lFICGkztVs9PP2NRItxf9fF+qD6xEW/T0YGto52zj07wseUeBdMAU1ah9HNVTDZyRC1u4NWdtJScwhw==" + }, + "SharpDX.Mathematics": { + "type": "Direct", + "requested": "[4.2.0, )", + "resolved": "4.2.0", + "contentHash": "R2pcKLgdsP9p5WyTjHmGOZ0ka0zASAZYc6P4L6rSvjYhf6klGYbent7MiVwbkwkt9dD44p5brjy5IwAnVONWGw==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "SharpDX": "4.2.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + } + }, + "SharpDX": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "3pv0LFMvfK/dv1qISJnn8xBeeT6R/FRvr0EV4KI2DGsL84Qlv6P7isWqxGyU0LCwlSVCJN3jgHJ4Bl0KI2PJww==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "glib": { + "type": "Project" } } } diff --git a/README.md b/README.md index 53e9d6ad8..ebd7c60a9 100644 --- a/README.md +++ b/README.md @@ -3,23 +3,15 @@ Ktisis is a robust posing tool for creating screenshots within FFXIV's GPose mode which allows you to pose characters by clicking on bones and moving them in any way you want, bringing additional features such as animation control and character editing. Our primary aim is to make posing more accessible for all. -Please feel free to join us on [Discord](https://discord.gg/kUG3W8B8Ny) to get in touch with developers and receive regular progress updates. +Please feel free to join us on [Discord](https://discord.gg/kUG3W8B8Ny) to get in touch with developers and receive patch notes. -To see a list of target features as well as their current progress on implementation, see our [Trello](https://trello.com/b/w64GYAWJ/ktisis-plugin) board. - -## Disclaimers - -Ktisis is still in early development, and any releases that go out will be primarily for alpha testing. This means that some functionality may be buggy or broken, so it's recommended that you save your poses regularly and report any bugs or errors you come across. - -Moreover, there will be many rough edges that may affect user experience, which we will work to improve. We hope to put together some comprehensive usage guides and other resources to help ease the barrier to entry and learning curve involved - if you're interested in helping with this, please reach out! +## Installation -Additionally, this tool is not made to be a replacement for Anamnesis. Instead, it's intended to be a new addition to the standard toolkits of posers, and will best be used in conjunction. +Ktisis is available from the [Sea of Stars](https://github.com/Ottermandias/SeaOfStars/) repo alongside other commonly installed plugins. -## Installation +Additionally, you will need to enable plugin testing builds in your Dalamud settings in order to opt into v0.3 releases. -Ktisis is written as a Dalamud plugin and as such, requires that you use [FFXIVQuickLauncher](https://github.com/goatcorp/FFXIVQuickLauncher) to start your game. -
-This will enable you to install community-created plugins. +If you wish to install the plugin from a standalone repo: 1. Type the `/xlsettings` command into your chatbox. This will open your Dalamud Settings. 2. In the window that opens, navigate to the "Experimental" tab. Scroll down to "Custom Plugin Repositories". @@ -32,25 +24,19 @@ This will enable you to install community-created plugins. ## Contributing -Contributions are generally welcome, as long as they adhere to the following principles: -- Manipulation of any ingame object must be confined within GPose. -- It must not automate any tasks that result in network packets being sent to the server. -- Any changes to the client state must not be: - - a) Permanent or irreversible by the user. - - b) Detectable by the server, directly or indirectly. - -Ktisis makes heavy use of unsafe code. If you are inexperienced or unfamiliar with the risks of this, then refrain from making code contributions that depend on it. Pull requests that show a reckless disregard for memory safety may be closed without further review. +All contributions are welcome. Feel free to reach out in the discord's #ktisis-dev channel if you want to work on something! -Pull requests containing new features must be reviewed by an organization member or repo maintainer before being merged - PRs heavily containing unsafe code must be reviewed by both core developers ([@chirpxiv](https://github.com/chirpxiv), [@Fayti1703](https://github.com/Fayti1703)). +Be aware that changes to unsafe code may be subject to extra scrutiny due to the possibility of causing client crashes or unintended behaviour. -As Ktisis is currently in a 'soft' feature lock with v0.3's codebase overhaul underway, PRs can take some time before they get merged or put in an official release; most will likely be put into individual branches to be merged with v0.3. +Most work is currently focused on the [v0.3/main](https://github.com/ktisis-tools/Ktisis/tree/v0.3/main) branch, which will supersede the current main branch when ready. ## Acknowledgements -Huge thanks go out to: -- [Goat Corp](https://github.com/goatcorp) and [XIV Tools](https://github.com/XIV-Tools), whose existing work in this area provided excellent insight into internal memory and data structures. +Huge thanks to: +- [@CedricGuillemet](https://github.com/CedricGuillemet) for developing [ImGuizmo](https://github.com/CedricGuillemet/ImGuizmo). +- [Goat Corp](https://github.com/goatcorp) and [XIV Tools](https://github.com/XIV-Tools) for developing Dalamud and Anamnesis, respectively. - [@BobTheBob9](https://github.com/BobTheBob9), [@Fayti1703](https://github.com/Fayti1703) and [@hackmud-dtr](https://github.com/hackmud-dtr) for their help with reverse engineering and low-level code. -- The other developers from [Bnuuy Central](https://github.com/Bnuuy-Central) who have supported and helped me through this project's development. -- perchird ([@lmcintyre](https://github.com/lmcintyre/)) for their amazing work on Havok structs which helped to make this possible. +- [@perchbirdd](https://github.com/perchbirdd) for their amazing work on Havok structs which helped to make this possible. +- [@sudojunior](https://github.com/sudojunior) for their help with operating the Discord. - [@Emyka](https://github.com/Emyka) for their continued efforts to help with accessibility and customisation. - Everyone who has contributed code and features through pull requests! diff --git a/fetch_bnpcs.bat b/fetch_bnpcs.bat new file mode 100644 index 000000000..d5262a7cb --- /dev/null +++ b/fetch_bnpcs.bat @@ -0,0 +1,4 @@ +@echo off +set source="https://raw.githubusercontent.com/ffxiv-teamcraft/ffxiv-teamcraft/staging/libs/data/src/lib/json/gubal-bnpcs-index.json" +set dest="./Ktisis/Data/Library/bnpc-index.json" +curl %source% -o %dest% \ No newline at end of file diff --git a/repo.json b/repo.json index 0fe6c205b..ec49ef8f6 100644 --- a/repo.json +++ b/repo.json @@ -1,22 +1,23 @@ [ { - "Author": "Chirp", + "Author": "Chirp, Cazzar, Bwuny and contributors", "Name": "Ktisis", "InternalName": "Ktisis", "Description": "A robust posing tool for creating screenshots in GPose.", - "AssemblyVersion": "0.2.15", - "TestingAssemblyVersion": "0.2.15", + "AssemblyVersion": "0.2.30", + "TestingAssemblyVersion": "0.3.16.4", "RepoUrl": "https://github.com/ktisis-tools/Ktisis", "ApplicableVersion": "any", - "DalamudApiLevel": 8, + "DalamudApiLevel": 14, + "TestingDalamudApiLevel": 14, "Tags": [ "gpose", "posing", "ktisis" ], "IconUrl": "https://github.com/ktisis-tools/Ktisis/raw/main/icon.png", - "DownloadLinkInstall": "https://github.com/ktisis-tools/Ktisis/releases/download/v0.2.15/latest.zip", - "DownloadLinkTesting": "https://github.com/ktisis-tools/Ktisis/releases/download/v0.2.15/latest.zip", - "DownloadLinkUpdate": "https://github.com/ktisis-tools/Ktisis/releases/download/v0.2.15/latest.zip" + "DownloadLinkInstall": "https://github.com/ktisis-tools/Ktisis/releases/download/v0.2.30/latest.zip", + "DownloadLinkTesting": "https://github.com/ktisis-tools/Ktisis/releases/download/v0.3.16.4/latest.zip", + "DownloadLinkUpdate": "https://github.com/ktisis-tools/Ktisis/releases/download/v0.2.30/latest.zip" } ]