├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── DodocoTales.StarRail ├── App.config ├── App.xaml ├── App.xaml.cs ├── Common │ ├── Enums │ │ ├── DDCCPoolType.cs │ │ └── DDCCUnitType.cs │ ├── Models │ │ └── DDCCPredictTargetItem.cs │ ├── Services │ │ ├── DDCCChanceProvider.cs │ │ └── DDCCGachaPredictor.cs │ └── Signals │ │ ├── DDCS_Core.cs │ │ ├── DDCS_Lib.cs │ │ └── DDCS_Loader.cs ├── DodocoTales.StarRail.csproj ├── Gui │ ├── Converters │ │ ├── DDCVClientTypeConverter.cs │ │ ├── DDCVItemNameColorConverter.cs │ │ ├── DDCVPercentageConverter.cs │ │ ├── DDCVPoolTypeConverter.cs │ │ ├── DDCVProgressConverter.cs │ │ ├── DDCVSegmentPercentageConverter.cs │ │ ├── DDCVTimeProgressConverter.cs │ │ ├── DDCVTimeZoneConverter.cs │ │ ├── DDCVUidAnonymousConverter.cs │ │ ├── DDCVUidNormalConverter.cs │ │ ├── DDCVVisibleByAvailableUIDConverter.cs │ │ ├── DDCVVisibleByBooleanConverter.cs │ │ └── DDCVVisibleByNotNullConverter.cs │ ├── DDCV.cs │ ├── Enums │ │ ├── DDCVGreaterRoundType.cs │ │ ├── DDCVHintBannerStatus.cs │ │ ├── DDCVSupportedGachaLogFormat.cs │ │ └── DDCVUnitIndicatorType.cs │ ├── Models │ │ ├── DDCVBannerItemModel.cs │ │ ├── DDCVMainPanelItemModel.cs │ │ ├── DDCVRoundItemModel.cs │ │ ├── DDCVUnitIndicatorModel.cs │ │ ├── DDCVUserlogItem.cs │ │ └── DDCVVersionItemModel.cs │ ├── Resources │ │ ├── DDCVConverters.xaml │ │ ├── DDCVResources.xaml │ │ ├── Digiface_Regular.ttf │ │ ├── Segment7Standard.otf │ │ └── Styles │ │ │ └── DDCVListViewItemStyle.xaml │ ├── ViewModels │ │ ├── Cards │ │ │ ├── DDCVHomeSceneCardVMBase.cs │ │ │ ├── DDCVHomeSceneCharEventCardVM.cs │ │ │ ├── DDCVHomeSceneLCEventCardVM.cs │ │ │ └── DDCVHomeScenePermanentCardVM.cs │ │ ├── DDCVMainWindowVM.cs │ │ ├── Dialogs │ │ │ ├── DDCVExportDialogVM.cs │ │ │ ├── DDCVGameClientManagerWindowEditDialogVM.cs │ │ │ └── DDCVImportDialogVM.cs │ │ ├── Screens │ │ │ ├── DDCVBannerViewScreenVM.cs │ │ │ ├── DDCVDependenciesDownloadScreenVM.cs │ │ │ ├── DDCVSettingsWindowAboutScreenVM.cs │ │ │ ├── DDCVSettingsWindowChangeLogScreenVM.cs │ │ │ ├── DDCVSettingsWindowUsersScreenVM.cs │ │ │ └── DDCVVersionViewScreenVM.cs │ │ └── Windows │ │ │ ├── DDCVGameClientManagerWindowVM.cs │ │ │ └── DDCVSettingsWindowVM.cs │ └── Views │ │ ├── Cards │ │ ├── DDCVHomeSceneCharEventCard.xaml │ │ ├── DDCVHomeSceneCharEventCard.xaml.cs │ │ ├── DDCVHomeSceneLCEventCard.xaml │ │ ├── DDCVHomeSceneLCEventCard.xaml.cs │ │ ├── DDCVHomeScenePermanentCard.xaml │ │ └── DDCVHomeScenePermanentCard.xaml.cs │ │ ├── Dialogs │ │ ├── DDCVExportDialog.xaml │ │ ├── DDCVExportDialog.xaml.cs │ │ ├── DDCVGameClientManagerWindowEditDialog.xaml │ │ ├── DDCVGameClientManagerWindowEditDialog.xaml.cs │ │ ├── DDCVImportDialog.xaml │ │ └── DDCVImportDialog.xaml.cs │ │ ├── Screens │ │ ├── DDCVBannerViewScreen.xaml │ │ ├── DDCVBannerViewScreen.xaml.cs │ │ ├── DDCVDependenciesDownloadScreen.xaml │ │ ├── DDCVDependenciesDownloadScreen.xaml.cs │ │ ├── DDCVGachaPredictionScreen.xaml │ │ ├── DDCVGachaPredictionScreen.xaml.cs │ │ ├── DDCVHomeScreen.xaml │ │ ├── DDCVHomeScreen.xaml.cs │ │ ├── DDCVSettingsWindowAboutScreen.xaml │ │ ├── DDCVSettingsWindowAboutScreen.xaml.cs │ │ ├── DDCVSettingsWindowChangeLogScreen.xaml │ │ ├── DDCVSettingsWindowChangeLogScreen.xaml.cs │ │ ├── DDCVSettingsWindowUsersScreen.xaml │ │ ├── DDCVSettingsWindowUsersScreen.xaml.cs │ │ ├── DDCVSwapableScreen.cs │ │ ├── DDCVVersionViewScreen.xaml │ │ └── DDCVVersionViewScreen.xaml.cs │ │ └── Windows │ │ ├── DDCVGameClientManagerWindow.xaml │ │ ├── DDCVGameClientManagerWindow.xaml.cs │ │ ├── DDCVSettingsWindow.xaml │ │ └── DDCVSettingsWindow.xaml.cs ├── Library │ ├── BannerLibrary │ │ ├── DDCLBannerLibrary.cs │ │ └── Models │ │ │ ├── DDCLBannerInfo.cs │ │ │ ├── DDCLBannerLibModel.cs │ │ │ └── DDCLVersionInfo.cs │ ├── CurrentUser │ │ ├── DDCLCurrentUserLibrary.cs │ │ └── Models │ │ │ ├── DDCLBannerLogItem.cs │ │ │ └── DDCLRoundLogItem.cs │ ├── DDCL.cs │ ├── Enums │ │ ├── DDCLActivateStatus.cs │ │ ├── DDCLGameClientType.cs │ │ └── DDCLUnitMetadataSource.cs │ ├── GameClient │ │ ├── DDCLGameClientLibrary.cs │ │ └── Models │ │ │ └── DDCLGameClientItem.cs │ ├── MetadataLibrary │ │ ├── DDCLMetadataVersionLibrary.cs │ │ └── Models │ │ │ └── DDCLMetadataVersion.cs │ ├── Settings │ │ ├── DDCLSettingsLibrary.cs │ │ └── Models │ │ │ └── DDCLSettingsInfo.cs │ ├── TrustedExporters │ │ ├── DDCLTrustedExportersLibrary.cs │ │ └── Models │ │ │ └── DDCLTrustedExporters.cs │ ├── UnitLibrary │ │ ├── DDCLUnitLibrary.cs │ │ └── Models │ │ │ └── DDCLUnitItem.cs │ └── UserDataLibrary │ │ ├── DDCLUserDataLibrary.cs │ │ └── Models │ │ ├── DDCLGachaLogItem.cs │ │ └── DDCLUserGachaLog.cs ├── Loader │ ├── DDCG.cs │ ├── DDCGGachaLogMerger.cs │ ├── DDCGGameClientLoader.cs │ ├── DDCGItemMetadataLoader.cs │ ├── DDCGProxyLoader.cs │ ├── DDCGUniversalFormatExporter.cs │ ├── DDCGUniversalFormatImporter.cs │ ├── DDCGUpdateLoader.cs │ ├── DDCGWebGachaLogLoader.cs │ ├── ItemMetadataLoaders │ │ └── HakushLoader │ │ │ ├── DDCGItemMetadataLoader.cs │ │ │ ├── Enums │ │ │ └── DDCGHakushMetadataItemTypeRarity.cs │ │ │ └── Models │ │ │ └── DDCGHakushMetadataItem.cs │ └── Models │ │ ├── DDCGDownloadTask.cs │ │ ├── DDCGGachaLogResponse.cs │ │ ├── DDCGGachaLogResponseItem.cs │ │ ├── DDCGUniversalFormatLog.cs │ │ ├── DDCGUniversalFormatLogInfo.cs │ │ ├── DDCGUniversalFormatLogItem.cs │ │ └── DDCGUniversalFormatLogSRSection.cs ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── icon.ico └── packages.config ├── LICENSE ├── README.md ├── StarRailWarpObserve.sln └── Updater ├── App.config ├── Program.cs ├── Properties └── AssemblyInfo.cs └── Updater.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | [Ll]ogs/ 25 | 26 | # Visual Studio 2015 cache/options directory 27 | .vs/ 28 | # Uncomment if you have tasks that create the project's static files in wwwroot 29 | #wwwroot/ 30 | 31 | # MSTest test Results 32 | [Tt]est[Rr]esult*/ 33 | [Bb]uild[Ll]og.* 34 | 35 | # NUNIT 36 | *.VisualState.xml 37 | TestResult.xml 38 | 39 | # Build Results of an ATL Project 40 | [Dd]ebugPS/ 41 | [Rr]eleasePS/ 42 | dlldata.c 43 | 44 | # DNX 45 | project.lock.json 46 | project.fragment.lock.json 47 | artifacts/ 48 | 49 | *_i.c 50 | *_p.c 51 | *_i.h 52 | *.ilk 53 | *.meta 54 | *.obj 55 | *.pch 56 | *.pdb 57 | *.pgc 58 | *.pgd 59 | *.rsp 60 | *.sbr 61 | *.tlb 62 | *.tli 63 | *.tlh 64 | *.tmp 65 | *.tmp_proj 66 | *.log 67 | *.vspscc 68 | *.vssscc 69 | .builds 70 | *.pidb 71 | *.svclog 72 | *.scc 73 | 74 | # Chutzpah Test files 75 | _Chutzpah* 76 | 77 | # Visual C++ cache files 78 | ipch/ 79 | *.aps 80 | *.ncb 81 | *.opendb 82 | *.opensdf 83 | *.sdf 84 | *.cachefile 85 | *.VC.db 86 | *.VC.VC.opendb 87 | 88 | # Visual Studio profiler 89 | *.psess 90 | *.vsp 91 | *.vspx 92 | *.sap 93 | 94 | # TFS 2012 Local Workspace 95 | $tf/ 96 | 97 | # Guidance Automation Toolkit 98 | *.gpState 99 | 100 | # ReSharper is a .NET coding add-in 101 | _ReSharper*/ 102 | *.[Rr]e[Ss]harper 103 | *.DotSettings.user 104 | 105 | # JustCode is a .NET coding add-in 106 | .JustCode 107 | 108 | # TeamCity is a build add-in 109 | _TeamCity* 110 | 111 | # DotCover is a Code Coverage Tool 112 | *.dotCover 113 | 114 | # NCrunch 115 | _NCrunch_* 116 | .*crunch*.local.xml 117 | nCrunchTemp_* 118 | 119 | # MightyMoose 120 | *.mm.* 121 | AutoTest.Net/ 122 | 123 | # Web workbench (sass) 124 | .sass-cache/ 125 | 126 | # Installshield output folder 127 | [Ee]xpress/ 128 | 129 | # DocProject is a documentation generator add-in 130 | DocProject/buildhelp/ 131 | DocProject/Help/*.HxT 132 | DocProject/Help/*.HxC 133 | DocProject/Help/*.hhc 134 | DocProject/Help/*.hhk 135 | DocProject/Help/*.hhp 136 | DocProject/Help/Html2 137 | DocProject/Help/html 138 | 139 | # Click-Once directory 140 | publish/ 141 | 142 | # Publish Web Output 143 | *.[Pp]ublish.xml 144 | *.azurePubxml 145 | # TODO: Comment the next line if you want to checkin your web deploy settings 146 | # but database connection strings (with potential passwords) will be unencrypted 147 | #*.pubxml 148 | *.publishproj 149 | 150 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 151 | # checkin your Azure Web App publish settings, but sensitive information contained 152 | # in these scripts will be unencrypted 153 | PublishScripts/ 154 | 155 | # NuGet Packages 156 | *.nupkg 157 | # The packages folder can be ignored because of Package Restore 158 | **/packages/* 159 | # except build/, which is used as an MSBuild target. 160 | !**/packages/build/ 161 | # Uncomment if necessary however generally it will be regenerated when needed 162 | #!**/packages/repositories.config 163 | # NuGet v3's project.json files produces more ignoreable files 164 | *.nuget.props 165 | *.nuget.targets 166 | 167 | # Microsoft Azure Build Output 168 | csx/ 169 | *.build.csdef 170 | 171 | # Microsoft Azure Emulator 172 | ecf/ 173 | rcf/ 174 | 175 | # Windows Store app package directories and files 176 | AppPackages/ 177 | BundleArtifacts/ 178 | Package.StoreAssociation.xml 179 | _pkginfo.txt 180 | 181 | # Visual Studio cache files 182 | # files ending in .cache can be ignored 183 | *.[Cc]ache 184 | # but keep track of directories ending in .cache 185 | !*.[Cc]ache/ 186 | 187 | # Others 188 | ClientBin/ 189 | ~$* 190 | *~ 191 | *.dbmdl 192 | *.dbproj.schemaview 193 | *.jfm 194 | *.pfx 195 | *.publishsettings 196 | node_modules/ 197 | orleans.codegen.cs 198 | 199 | # Since there are multiple workflows, uncomment next line to ignore bower_components 200 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 201 | #bower_components/ 202 | 203 | # RIA/Silverlight projects 204 | Generated_Code/ 205 | 206 | # Backup & report files from converting an old project file 207 | # to a newer Visual Studio version. Backup files are not needed, 208 | # because we have git ;-) 209 | _UpgradeReport_Files/ 210 | Backup*/ 211 | UpgradeLog*.XML 212 | UpgradeLog*.htm 213 | 214 | # SQL Server files 215 | *.mdf 216 | *.ldf 217 | 218 | # Business Intelligence projects 219 | *.rdl.data 220 | *.bim.layout 221 | *.bim_*.settings 222 | 223 | # Microsoft Fakes 224 | FakesAssemblies/ 225 | 226 | # GhostDoc plugin setting file 227 | *.GhostDoc.xml 228 | 229 | # Node.js Tools for Visual Studio 230 | .ntvs_analysis.dat 231 | 232 | # Visual Studio 6 build log 233 | *.plg 234 | 235 | # Visual Studio 6 workspace options file 236 | *.opt 237 | 238 | # Visual Studio LightSwitch build output 239 | **/*.HTMLClient/GeneratedArtifacts 240 | **/*.DesktopClient/GeneratedArtifacts 241 | **/*.DesktopClient/ModelManifest.xml 242 | **/*.Server/GeneratedArtifacts 243 | **/*.Server/ModelManifest.xml 244 | _Pvt_Extensions 245 | 246 | # Paket dependency manager 247 | .paket/paket.exe 248 | paket-files/ 249 | 250 | # FAKE - F# Make 251 | .fake/ 252 | 253 | # JetBrains Rider 254 | .idea/ 255 | *.sln.iml 256 | 257 | # CodeRush 258 | .cr/ 259 | 260 | # Python Tools for Visual Studio (PTVS) 261 | __pycache__/ 262 | *.pyc -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | ## V1.5.2 4 | 5 | - 支持新版统一可交换抽卡记录格式,版本4.0(UIGF v4.0)所要求的多语言、跨时区导入能力。 6 | - 添加单位元数据,以实现对UIGF v4.0的完全支持。当前仅包括Hakush数据源。 7 | 8 | ## V1.5.1 9 | 10 | - 支持V4.0版本的新版统一可交换抽卡记录格式(UIGF v4.0)文件的导入与导出 11 | - 更新五星概率经验公式 12 | - 修复主界面部分提升显示错误 13 | 14 | ## V1.5.0 15 | 16 | - 重构“首页”界面 17 | - 修复卡池间隔期内轮次进度指示器显示异常的错误 18 | 19 | ## V1.3.0 20 | 21 | - 添加进行中任务提示栏 22 | - 修复了光锥活动跃迁卡池页中抽取状态指示器尺寸异常的错误 23 | - 优化更新逻辑 24 | 25 | ## V1.2.2 26 | 27 | - 优化SRGF导入提示 28 | 29 | ## V1.2.1 30 | 31 | - 修复无法获取1.2以上版本《崩坏:星穹铁道》缓存信息的错误 32 | 33 | ## V1.2.0 34 | 35 | - 添加“设置->用户”页;允许切换用户以及移除用户 36 | - 修复显示尚未开始的卡池的错误 37 | - 为四星、五星单位名称添加自动计算的颜色 38 | - 添加“软保底”机制激活指示器 39 | - 修复左下角刷新按钮于更新跃迁记录功能被锁定时仍可被点击的错误 40 | - 通过左下角刷新按钮进行跃迁记录增量更新时,保持更新选项菜单显示 41 | 42 | ## V1.1.1 43 | 44 | - 添加应用图标 45 | - 添加“设置->更新日志”页;在完成更新后的初次运行时自动弹出“设置->更新日志”页 46 | - 在获取用户跃迁记录过程中保持更新选项菜单显示 47 | - 修正了初次获取跃迁记录的用户在更新选项菜单中被显示错误的客户端与时区的问题 48 | - 调整了SRGF导出文件中`export_timestamp`与`region_time_zone`字段的格式 49 | 50 | ## V1.1.0 51 | 52 | - 添加对国际服客户端的实验性支持(未进行测试) 53 | - 添加对“星穹铁道抽卡记录格式”(SRGF)的导出支持 54 | - 添加对“星穹铁道抽卡记录格式”(SRGF)的导入支持 55 | - 保存并默认选择用户上一次所选的游戏客户端作为缓存模式更新源 56 | - 添加“设置-关于”页 57 | 58 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace DodocoTales 10 | { 11 | /// 12 | /// App.xaml 的交互逻辑 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Enums/DDCCPoolType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Common.Enums 8 | { 9 | public enum DDCCPoolType 10 | { 11 | Null = 0, 12 | Permanent = 1, 13 | Beginner = 2, 14 | CharacterEvent = 11, 15 | LCEvent = 12, 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Enums/DDCCUnitType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Common.Enums 8 | { 9 | public enum DDCCUnitType 10 | { 11 | Unknown, 12 | Character, 13 | LightCone 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Models/DDCCPredictTargetItem.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Common.Models 9 | { 10 | public class DDCCPredictTargetItem 11 | { 12 | public DDCCPoolType PoolType { get; set; } 13 | public int PreviousCount { get; set; } 14 | public bool IsPreviousPermanant { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Services/DDCCChanceProvider.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Navigation; 8 | 9 | namespace DodocoTales.SR.Common.Services 10 | { 11 | public static class DDCCChanceProvider 12 | { 13 | public static readonly double CharEventUpRatio = 0.5625; 14 | public static readonly double LCEventUpRatio = 0.78125; 15 | 16 | public static readonly double PermanentBasicRatio = 0.006; 17 | public static readonly int PermanentSoftPityThreshold = 72; 18 | public static readonly double PermanentSoftPityRatio = 0.06; 19 | 20 | public static readonly double LCEventBasicRatio = 0.008; 21 | public static readonly int LCEventSoftPityThreshold = 64; 22 | public static readonly double LCEventSoftPityRatio = 0.07; 23 | 24 | public static double GetNextPullRank5Chance(DDCCPoolType type, int count) 25 | { 26 | double bRatio = PermanentBasicRatio; 27 | double spRatio = PermanentSoftPityRatio; 28 | int spThreshold = PermanentSoftPityThreshold; 29 | 30 | if (type == DDCCPoolType.LCEvent) 31 | { 32 | bRatio = LCEventBasicRatio; 33 | spRatio = LCEventSoftPityRatio; 34 | spThreshold = LCEventSoftPityThreshold; 35 | } 36 | return Math.Min(bRatio + Math.Max(count - spThreshold, 0) * spRatio, 1); 37 | } 38 | 39 | public static double GetNextPullTargetChance(DDCCPoolType type, int count, bool previous_permanent) 40 | { 41 | double upRatio = 1; 42 | 43 | switch (type) 44 | { 45 | case DDCCPoolType.CharacterEvent: 46 | if (!previous_permanent) { upRatio = CharEventUpRatio; }; 47 | break; 48 | case DDCCPoolType.LCEvent: 49 | if (!previous_permanent) { upRatio = LCEventUpRatio; }; 50 | break; 51 | } 52 | return GetNextPullRank5Chance(type, count) * upRatio; 53 | } 54 | 55 | public static double GetNextPullPermanantChance(DDCCPoolType type, int count, bool previous_permanent = false) 56 | { 57 | double upRatio = 1; 58 | 59 | switch (type) 60 | { 61 | case DDCCPoolType.CharacterEvent: 62 | if (!previous_permanent) { upRatio = CharEventUpRatio; }; 63 | break; 64 | case DDCCPoolType.LCEvent: 65 | if (!previous_permanent) { upRatio = LCEventUpRatio; }; 66 | break; 67 | } 68 | return GetNextPullRank5Chance(type, count) * (1 - upRatio); 69 | } 70 | 71 | 72 | public static double GetNextPullNoR5Chance(DDCCPoolType type, int count) 73 | { 74 | return 1 - GetNextPullRank5Chance(type, count); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Services/DDCCGachaPredictor.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Common.Models; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Common.Services 11 | { 12 | public class DDCCGachaPredictor 13 | { 14 | public List targets = new List(); 15 | 16 | public decimal[,,,] ChanceMatrix { get; set; } 17 | 18 | public decimal[] ChancesByTargetCount { get; set; } 19 | public int Total { get; set; } 20 | int ResultIndex; 21 | 22 | public DDCCGachaPredictor AddTarget(DDCCPoolType type, int previous_count=0, bool previous_permanant=false) 23 | { 24 | targets.Add(new DDCCPredictTargetItem 25 | { 26 | PoolType = type, 27 | PreviousCount = previous_count, 28 | IsPreviousPermanant = previous_permanant, 29 | }); 30 | return this; 31 | } 32 | 33 | public DDCCGachaPredictor Generate(int total) 34 | { 35 | int targetCnt = targets.Count; 36 | Total = total; 37 | ResultIndex = Total % 2; 38 | int tmax = Math.Max(Total + 1, 91); 39 | 40 | if (targetCnt == 0) 41 | { 42 | ChanceMatrix = null; 43 | ChancesByTargetCount = null; 44 | return this; 45 | } 46 | ChanceMatrix = new decimal[2, targetCnt + 1, 2, tmax]; 47 | 48 | ChanceMatrix[0, 0, (targets[0].IsPreviousPermanant ? 1 : 0), targets[0].PreviousCount] = 1M; 49 | 50 | for (int pull = 0; pull < total; pull++) 51 | { 52 | // For target r5 cnt not matched 53 | for (int upc = 0; upc < targetCnt; upc++) 54 | { 55 | for (int current = 0; current < 90; current++) 56 | { 57 | int thisregion = pull % 2, nextregion = (pull + 1) % 2; 58 | 59 | // For [x,x,0,x] 60 | decimal thisvalue = ChanceMatrix[thisregion, upc, 0, current]; 61 | ChanceMatrix[nextregion, upc + 1, 0, (upc + 1 < targetCnt ? (targets[upc + 1].PreviousCount) : 0)] 62 | += (decimal)DDCCChanceProvider.GetNextPullTargetChance(targets[upc].PoolType, current, false) * thisvalue; 63 | ChanceMatrix[nextregion, upc, 1, 0] 64 | += (decimal)DDCCChanceProvider.GetNextPullPermanantChance(targets[upc].PoolType, current) * thisvalue; 65 | ChanceMatrix[nextregion, upc, 0, current + 1] 66 | += (decimal)DDCCChanceProvider.GetNextPullNoR5Chance(targets[upc].PoolType, current) * thisvalue; 67 | 68 | // For [x,x,1,x] 69 | thisvalue = ChanceMatrix[thisregion, upc, 1, current]; 70 | ChanceMatrix[nextregion, upc + 1, 0, (upc + 1 < targetCnt ? (targets[upc + 1].PreviousCount) : 0)] 71 | += (decimal)DDCCChanceProvider.GetNextPullTargetChance(targets[upc].PoolType, current, true) * thisvalue; 72 | ChanceMatrix[nextregion, upc, 1, current + 1] 73 | += (decimal)DDCCChanceProvider.GetNextPullNoR5Chance(targets[upc].PoolType, current) * thisvalue; 74 | ChanceMatrix[thisregion, upc, 0, current] = 0; 75 | ChanceMatrix[thisregion, upc, 1, current] = 0; 76 | } 77 | } 78 | // For target r5 cnt matched 79 | for (int current = 0; current < Total; current++) 80 | { 81 | int thisregion = pull % 2, nextregion = (pull + 1) % 2; 82 | ChanceMatrix[nextregion, targetCnt, 0, current + 1] += ChanceMatrix[thisregion, targetCnt, 0, current]; 83 | ChanceMatrix[thisregion, targetCnt, 0, current] = 0; 84 | } 85 | } 86 | 87 | ChancesByTargetCount = new decimal[targetCnt + 1]; 88 | 89 | for (int i = 0; i <= targetCnt; i++) 90 | { 91 | for (int j = 0; j < 2; j++) 92 | { 93 | for (int k = 0; k < tmax; k++) 94 | { 95 | ChancesByTargetCount[i] += ChanceMatrix[ResultIndex, i, j, k]; 96 | } 97 | } 98 | } 99 | return this; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Signals/DDCS_Core.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using DodocoTales.SR.Common.Signals; 7 | 8 | namespace DodocoTales.SR.Common.Signals 9 | { 10 | public delegate void DDCSCommonDelegate(); 11 | public delegate void DDCSUidParamDelegate(long uid); 12 | } 13 | 14 | namespace DodocoTales.SR.Common 15 | { 16 | public static partial class DDCS 17 | { 18 | public static void ExecCommonDelegate(DDCSCommonDelegate dele) 19 | { 20 | if (dele != null) 21 | { 22 | foreach (DDCSCommonDelegate method in dele.GetInvocationList()) 23 | { 24 | method.BeginInvoke(null, null); 25 | } 26 | } 27 | } 28 | public static void ExecUidParamDelegate(DDCSUidParamDelegate dele, long uid) 29 | { 30 | if (dele != null) 31 | { 32 | foreach (DDCSUidParamDelegate method in dele.GetInvocationList()) 33 | { 34 | method.BeginInvoke(uid, null, null); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Signals/DDCS_Lib.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using DodocoTales.SR.Common.Signals; 7 | 8 | namespace DodocoTales.SR.Common 9 | { 10 | public static partial class DDCS 11 | { 12 | public static DDCSCommonDelegate BannerLibReloadFailed; 13 | public static void Emit_BannerLibReloadFailed() 14 | => ExecCommonDelegate(BannerLibReloadFailed); 15 | 16 | public static DDCSCommonDelegate BannerLibDeserialized; 17 | public static void Emit_BannerLibDeserialized() 18 | => ExecCommonDelegate(BannerLibDeserialized); 19 | 20 | public static DDCSCommonDelegate BannerLibReloadCompleted; 21 | public static void Emit_BannerLibReloadCompleted() 22 | => ExecCommonDelegate(BannerLibReloadCompleted); 23 | 24 | 25 | public static DDCSCommonDelegate UnitLibReloadFailed; 26 | public static void Emit_UnitLibReloadFailed() 27 | => ExecCommonDelegate(UnitLibReloadFailed); 28 | 29 | public static DDCSCommonDelegate UnitLibReloadCompleted; 30 | public static void Emit_UnitLibReloadCompleted() 31 | => ExecCommonDelegate(UnitLibReloadCompleted); 32 | 33 | public static DDCSUidParamDelegate CurUserSwapping; 34 | public static void Emit_CurUserSwapping(long uid) 35 | => ExecUidParamDelegate(CurUserSwapping, uid); 36 | 37 | public static DDCSCommonDelegate CurUserSwapReverted; 38 | public static void Emit_CurUserSwapReverted() 39 | => ExecCommonDelegate(CurUserSwapReverted); 40 | 41 | public static DDCSUidParamDelegate CurUserSwapCompleted; 42 | public static void Emit_CurUserSwapCompleted(long uid) 43 | => ExecUidParamDelegate(CurUserSwapCompleted, uid); 44 | 45 | public static DDCSCommonDelegate CurUserUpdateCompleted; 46 | public static void Emit_CurUserUpdateCompleted() 47 | => ExecCommonDelegate(CurUserUpdateCompleted); 48 | 49 | public static DDCSUidParamDelegate UserLibUidDeplicated; 50 | public static void Emit_UserLibUidDeplicated(long uid) 51 | => ExecUidParamDelegate(UserLibUidDeplicated, uid); 52 | 53 | public static DDCSCommonDelegate UserLibReloadCompleted; 54 | public static void Emit_UserLibReloadCompleted() 55 | => ExecCommonDelegate(UserLibReloadCompleted); 56 | 57 | public static DDCSCommonDelegate UserlogSaveCompleted; 58 | public static void Emit_UserlogSaveCompleted() 59 | => ExecCommonDelegate(UserlogSaveCompleted); 60 | 61 | public static DDCSCommonDelegate UserlogSaveFailed; 62 | public static void Emit_UserlogSaveFailed() 63 | => ExecCommonDelegate(UserlogSaveFailed); 64 | 65 | public static DDCSCommonDelegate UserlogBackupCompleted; 66 | public static void Emit_UserlogBackupCompleted() 67 | => ExecCommonDelegate(UserlogBackupCompleted); 68 | 69 | public static DDCSCommonDelegate UserlogBackupFailed; 70 | public static void Emit_UserlogBackupFailed() 71 | => ExecCommonDelegate(UserlogBackupFailed); 72 | 73 | public static DDCSCommonDelegate UserlogRemoveCompleted; 74 | public static void Emit_UserlogRemoveCompleted() 75 | => ExecCommonDelegate(UserlogRemoveCompleted); 76 | 77 | public static DDCSCommonDelegate UserlogRemoveFailed; 78 | public static void Emit_UserlogRemoveFailed() 79 | => ExecCommonDelegate(UserlogRemoveFailed); 80 | 81 | public static DDCSCommonDelegate GameClientLibReloadCompleted; 82 | public static void Emit_GameClientLibReloadCompleted() 83 | => ExecCommonDelegate(GameClientLibReloadCompleted); 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Common/Signals/DDCS_Loader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using DodocoTales.SR.Common.Enums; 7 | using DodocoTales.SR.Common.Signals; 8 | 9 | namespace DodocoTales.SR.Common.Signals 10 | { 11 | public delegate void DDCSImportStatusDelegate(DDCCPoolType type, int idx); 12 | public delegate void DDCSDownloadStatusDelegate(dynamic var); 13 | } 14 | 15 | namespace DodocoTales.SR.Common 16 | { 17 | public static partial class DDCS 18 | { 19 | public static void ExecImportStatusDelegate(DDCSImportStatusDelegate dele, DDCCPoolType type, int idx) 20 | { 21 | if (dele != null) 22 | { 23 | foreach (DDCSImportStatusDelegate method in dele.GetInvocationList().Cast()) 24 | { 25 | method.BeginInvoke(type, idx, null, null); 26 | } 27 | } 28 | } 29 | 30 | public static void ExecDownloadStatusDelegate(DDCSDownloadStatusDelegate dele, dynamic var) 31 | { 32 | if (dele != null) 33 | { 34 | foreach (DDCSDownloadStatusDelegate method in dele.GetInvocationList().Cast()) 35 | { 36 | method.BeginInvoke(var, null, null); 37 | } 38 | } 39 | } 40 | 41 | public static DDCSImportStatusDelegate ImportStatusFromWebRefreshed; 42 | public static void Emit_ImportStatusFromWebRefreshed(DDCCPoolType type, int current_page) 43 | => ExecImportStatusDelegate(ImportStatusFromWebRefreshed, type, current_page); 44 | 45 | public static DDCSCommonDelegate ImportConnectionTimeout; 46 | public static void Emit_ImportConnectionTimeout() 47 | => ExecCommonDelegate(ImportConnectionTimeout); 48 | public static DDCSCommonDelegate ImportConnectionRetry; 49 | public static void Emit_ImportConnectionRetry() 50 | => ExecCommonDelegate(ImportConnectionRetry); 51 | public static DDCSCommonDelegate ImportConnectionThrottled; 52 | public static void Emit_ImportConnectionThrottled() 53 | => ExecCommonDelegate(ImportConnectionThrottled); 54 | 55 | public static DDCSCommonDelegate ProxyCaptured; 56 | public static void Emit_ProxyCaptured() 57 | => ExecCommonDelegate(ProxyCaptured); 58 | 59 | public static DDCSCommonDelegate ClientNeedsUpdate; 60 | public static void Emit_ClientNeedsUpdate() 61 | => ExecCommonDelegate(ClientNeedsUpdate); 62 | public static DDCSCommonDelegate ClientUpdateDownloadCompleted; 63 | public static void Emit_ClientUpdateDownloadCompleted() 64 | => ExecCommonDelegate(ClientUpdateDownloadCompleted); 65 | public static DDCSCommonDelegate ClientUpdateDownloadFailed; 66 | public static void Emit_ClientUpdateDownloadFailed() 67 | => ExecCommonDelegate(ClientUpdateDownloadFailed); 68 | 69 | public static DDCSDownloadStatusDelegate ClientUpdateDownloadStatusReport; 70 | public static void Emit_ClientUpdateDownloadStatusReport(dynamic var) 71 | => ExecDownloadStatusDelegate(ClientUpdateDownloadStatusReport, var); 72 | 73 | public static DDCSCommonDelegate DependencyUpdateDownloadCompleted; 74 | public static void Emit_DependencyUpdateDownloadCompleted() 75 | => ExecCommonDelegate(DependencyUpdateDownloadCompleted); 76 | public static DDCSCommonDelegate DependencyUpdateDownloadFailed; 77 | public static void Emit_DependencyUpdateDownloadFailed() 78 | => ExecCommonDelegate(DependencyUpdateDownloadFailed); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVClientTypeConverter.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library; 2 | using DodocoTales.SR.Library.Enums; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Data; 10 | 11 | namespace DodocoTales.SR.Gui.Converters 12 | { 13 | public class DDCVClientTypeConverter : IValueConverter 14 | { 15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 16 | { 17 | DDCLGameClientType type = (DDCLGameClientType)value; 18 | return DDCL.GetGameClientTypeName(type); 19 | 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVItemNameColorConverter.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Globalization; 5 | using System.Linq; 6 | using System.Security.Cryptography; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Data; 10 | using System.Windows.Media; 11 | 12 | namespace DodocoTales.SR.Gui.Converters 13 | { 14 | public class DDCVItemNameColorConverter : IValueConverter 15 | { 16 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | byte[] bytes = Encoding.UTF8.GetBytes(value.ToString()); 19 | var hash = MD5.Create().ComputeHash(bytes); 20 | var h = (float)(hash.Take(2).Average(x => x) / 256 * 360); 21 | var s = (float)(hash.Skip(5).Take(5).Average(x => x) / 256 * 50 + 20); 22 | var l = (float)(hash.Skip(10).Average(x => x) / 256 * 50 + 20); 23 | var c = SKColor.FromHsl(h, s, l); 24 | return new SolidColorBrush(Color.FromRgb(c.Red, c.Green, c.Blue)); 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVPercentageConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace DodocoTales.SR.Gui.Converters 11 | { 12 | public class DDCVPercentageConverter : IMultiValueConverter 13 | { 14 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | if (values[0] == DependencyProperty.UnsetValue) return DependencyProperty.UnsetValue; 17 | var divident = System.Convert.ToInt32(values[0]); 18 | var divisor = System.Convert.ToInt32(values[1]); 19 | return divisor == 0 ? " — % " : string.Format("{0:P2}", divident * 1.0 / divisor); 20 | } 21 | 22 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVPoolTypeConverter.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Library; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Globalization; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows; 10 | using System.Windows.Data; 11 | 12 | namespace DodocoTales.SR.Gui.Converters 13 | { 14 | public class DDCVPoolTypeConverter : IValueConverter 15 | { 16 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 17 | { 18 | DDCCPoolType type = (DDCCPoolType)value; 19 | return DDCL.GetPoolTypeName(type); 20 | 21 | } 22 | 23 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVProgressConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace DodocoTales.SR.Gui.Converters 10 | { 11 | public class DDCVProgressConverter : IMultiValueConverter 12 | { 13 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | var now = System.Convert.ToDouble(values[0]); 16 | var max = System.Convert.ToDouble(values[1]); 17 | return max <= 0 ? 0: now * 100.0 / max; 18 | 19 | } 20 | 21 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVSegmentPercentageConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows; 9 | 10 | namespace DodocoTales.SR.Gui.Converters 11 | { 12 | public class DDCVSegmentPercentageConverter : IMultiValueConverter 13 | { 14 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | if (values[0] == DependencyProperty.UnsetValue) return DependencyProperty.UnsetValue; 17 | var divident = System.Convert.ToInt32(values[0]); 18 | var divisor = System.Convert.ToInt32(values[1]); 19 | if (divisor == 0) return "---"; 20 | var res = divident * 100.0 / divisor; 21 | if (res >= 100.0) return "100"; 22 | else if (res >= 10.0) return string.Format("{0:F1}", res); 23 | else return string.Format("{0:F2}", res); 24 | } 25 | 26 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVTimeProgressConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows; 9 | 10 | namespace DodocoTales.SR.Gui.Converters 11 | { 12 | public class DDCVTimeProgressConverter : IMultiValueConverter 13 | { 14 | public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | var begin = ((DateTimeOffset)values[0]).UtcTicks; 17 | var end = ((DateTimeOffset)values[1]).UtcTicks; 18 | var now = (DateTimeOffset.Now).UtcTicks; 19 | if (now > end || now < begin) return 0.0; 20 | return (now - begin) * 100.0 / (end - begin); 21 | 22 | } 23 | 24 | public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 25 | { 26 | throw new NotImplementedException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVTimeZoneConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace DodocoTales.SR.Gui.Converters 11 | { 12 | public class DDCVTimeZoneConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | var timezone = (int)value; 17 | if (timezone == 0) return "UTC"; 18 | else if (timezone > 0) return "UTC+" + timezone.ToString(); 19 | else return "UTC" + timezone.ToString(); 20 | } 21 | 22 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 23 | { 24 | var str = (string)value; 25 | if (str == "UTC") return 0; 26 | else if(str.StartsWith("UTC")) str = str.Substring(3); 27 | if (Int32.TryParse(str, out int res)) return res; 28 | return DependencyProperty.UnsetValue; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVUidAnonymousConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace DodocoTales.SR.Gui.Converters 10 | { 11 | public class DDCVUidAnonymousConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | string res = "--- 未登录 ---"; 16 | try 17 | { 18 | long val = System.Convert.ToInt64(value); 19 | if (val > 1000000) res = String.Format("UID:{0}****{1:D2}", val / 1000000, val % 100); 20 | else if (val >= 10000) res = String.Format("UID:{0} (匿名)", val); 21 | else if (val >= 0) res = String.Format("UID:{0} (临时)", val); 22 | } 23 | catch { } 24 | return res; 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVUidNormalConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | 9 | namespace DodocoTales.SR.Gui.Converters 10 | { 11 | public class DDCVUidNormalConverter : IValueConverter 12 | { 13 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 14 | { 15 | string res = "未登录"; 16 | try 17 | { 18 | long val = System.Convert.ToInt64(value); 19 | if (val > 1000000) res = String.Format("{0}", val); 20 | else if (val >= 10000) res = String.Format("{0} (匿名)", val); 21 | else if (val >= 0) res = String.Format("{0} (临时)", val); 22 | } 23 | catch { } 24 | return res; 25 | } 26 | 27 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 28 | { 29 | throw new NotImplementedException(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVVisibleByAvailableUIDConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace DodocoTales.SR.Gui.Converters 11 | { 12 | public class DDCVVisibleByAvailableUIDConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | var res = Visibility.Collapsed; 17 | try 18 | { 19 | var uid = System.Convert.ToInt64(value); 20 | if (uid >= 0) res = Visibility.Visible; 21 | } 22 | catch { } 23 | return res; 24 | } 25 | 26 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVVisibleByBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Data; 9 | 10 | namespace DodocoTales.SR.Gui.Converters 11 | { 12 | public class DDCVVisibleByBooleanConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return System.Convert.ToBoolean(value) ? Visibility.Visible : Visibility.Collapsed; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Converters/DDCVVisibleByNotNullConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Data; 8 | using System.Windows; 9 | 10 | namespace DodocoTales.SR.Gui.Converters 11 | { 12 | public class DDCVVisibleByNotNullConverter : IValueConverter 13 | { 14 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | return (value != null) ? Visibility.Visible : Visibility.Collapsed; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | throw new NotImplementedException(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/DDCV.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Gui.Views.Screens; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | 10 | namespace DodocoTales.SR.Gui 11 | { 12 | public static class DDCV 13 | { 14 | public static readonly Dictionary MainScreens = new Dictionary(); 15 | public static readonly Stack StackedScreens = new Stack(); 16 | 17 | public static MainWindow MainWindow; 18 | public static Grid MainNavigater; 19 | 20 | 21 | public static void RegisterMainScreens() 22 | { 23 | RegisterMainScreen("Home", new DDCVHomeScreen()); 24 | RegisterMainScreen("Version", new DDCVVersionViewScreen()); 25 | RegisterMainScreen("Prediction", new DDCVGachaPredictionScreen()); 26 | } 27 | 28 | 29 | 30 | public static void RegisterMainScreen(string tag, DDCVSwapableScreen screen) 31 | { 32 | MainScreens.Add(tag, screen); 33 | screen.Visibility = Visibility.Collapsed; 34 | MainNavigater.Children.Add(screen); 35 | if (StackedScreens.Count == 0) 36 | { 37 | StackedScreens.Push(screen); 38 | screen.Visibility = Visibility.Visible; 39 | } 40 | } 41 | 42 | 43 | public static void PushScreen(DDCVSwapableScreen screen) 44 | { 45 | //DDCLog.Info(DCLN.Gui, String.Format("Push screen: {0}", screen.GetType().Name)); 46 | if (screen.GetType() == StackedScreens.Peek().GetType()) 47 | return; 48 | 49 | StackedScreens.Peek().Visibility = Visibility.Collapsed; 50 | MainNavigater.Children.Add(screen); 51 | screen.Visibility = Visibility.Visible; 52 | StackedScreens.Push(screen); 53 | } 54 | 55 | public static bool PopScreen() 56 | { 57 | if (StackedScreens.Count == 1) return false; 58 | MainNavigater.Children.Remove(StackedScreens.Pop()); 59 | StackedScreens.Peek().Visibility = Visibility.Visible; 60 | return true; 61 | } 62 | 63 | public static void SwapMainScreen(string tag) 64 | { 65 | //DDCLog.Info(DCLN.Gui, "Swap main page: " + tag); 66 | if (!MainScreens.TryGetValue(tag, out DDCVSwapableScreen ns)) 67 | { 68 | return; 69 | } 70 | while (PopScreen()) ; 71 | var os = StackedScreens.Pop(); 72 | if (ns != os) 73 | { 74 | os.Visibility = Visibility.Collapsed; 75 | ns.Visibility = Visibility.Visible; 76 | } 77 | StackedScreens.Push(ns); 78 | } 79 | 80 | public static void RefreshAll() 81 | { 82 | foreach (var scn in StackedScreens.Union(MainScreens.Values)) 83 | { 84 | scn.Refresh(); 85 | } 86 | } 87 | 88 | public static void CreateBannerViewScreen(ulong versionid, ulong bannerinternalid) 89 | { 90 | 91 | var scn = new DDCVBannerViewScreen(); 92 | scn.SetBanner(versionid, bannerinternalid); 93 | PushScreen(scn); 94 | scn.Refresh(); 95 | 96 | } 97 | 98 | public static bool ShowWindowDialog(Window window) 99 | { 100 | window.Owner = MainWindow; 101 | return window.ShowDialog() ?? false; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Enums/DDCVGreaterRoundType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Gui.Enums 8 | { 9 | public enum DDCVGreaterRoundType 10 | { 11 | Permanent = 90, 12 | CharacterEvent = 180, 13 | LCEvent = 160, 14 | Beginner = 50, 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Enums/DDCVHintBannerStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Gui.Enums 8 | { 9 | public enum DDCVHintBannerStatus 10 | { 11 | NoHint, 12 | Updating, 13 | FetchingGachaLog, 14 | Error 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Enums/DDCVSupportedGachaLogFormat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Gui.Enums 8 | { 9 | public enum DDCVSupportedGachaLogFormat 10 | { 11 | StarwoInternalFormat = 0, 12 | StarRailGachaLogFormat = 100, 13 | //StarRailGachaLogFormatAnonymous = 101, 14 | //StarwoWorkbookExportFormat = 200, 15 | NewUniversalGachaLogFormat = 300, 16 | DualFormat_NewUIGF_SRGF = 301, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Enums/DDCVUnitIndicatorType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Gui.Enums 8 | { 9 | public enum DDCVUnitIndicatorType 10 | { 11 | Default, 12 | Rank3, 13 | Rank4Up, 14 | Rank4PermanentChar, 15 | Rank4PermanentLC, 16 | Rank5Up, 17 | Rank5PermanentChar, 18 | Rank5PermanentLC 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Models/DDCVBannerItemModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Common.Enums; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Gui.Models 11 | { 12 | public class DDCVBannerItemModel : ObservableObject 13 | { 14 | private ulong versionId; 15 | public ulong VersionID 16 | { 17 | get => versionId; 18 | set => SetProperty(ref versionId, value); 19 | } 20 | private ulong bannerInternalId; 21 | public ulong BannerInternalID 22 | { 23 | get => bannerInternalId; 24 | set => SetProperty(ref bannerInternalId, value); 25 | } 26 | private string version; 27 | public string Version 28 | { 29 | get => version; 30 | set => SetProperty(ref version, value); 31 | } 32 | private string bannerName; 33 | public string BannerName 34 | { 35 | get => bannerName; 36 | set => SetProperty(ref bannerName, value); 37 | } 38 | private string bannerHint; 39 | public string BannerHint 40 | { 41 | get => bannerHint; 42 | set => SetProperty(ref bannerHint, value); 43 | } 44 | private DDCCPoolType poolType; 45 | public DDCCPoolType PoolType 46 | { 47 | get => poolType; 48 | set => SetProperty(ref poolType, value); 49 | } 50 | private DateTimeOffset beginTime; 51 | public DateTimeOffset BeginTime 52 | { 53 | get => beginTime; 54 | set => SetProperty(ref beginTime, value); 55 | } 56 | private DateTimeOffset endTime; 57 | public DateTimeOffset EndTime 58 | { 59 | get => endTime; 60 | set => SetProperty(ref endTime, value); 61 | } 62 | 63 | private int total; 64 | public int Total 65 | { 66 | get => total; 67 | set => SetProperty(ref total, value); 68 | } 69 | private int rank5; 70 | public int Rank5 71 | { 72 | get => rank5; 73 | set => SetProperty(ref rank5, value); 74 | } 75 | private int rank4; 76 | public int Rank4 77 | { 78 | get => rank4; 79 | set => SetProperty(ref rank4, value); 80 | } 81 | private ObservableCollection rank5Ups; 82 | public ObservableCollection Rank5Ups 83 | { 84 | get => rank5Ups; 85 | set => SetProperty(ref rank5Ups, value); 86 | } 87 | public bool Rank5UpsAvailAble 88 | { 89 | get => Rank5Ups != null && Rank5Ups.Count > 0; 90 | } 91 | private ObservableCollection rank4Ups; 92 | public ObservableCollection Rank4Ups 93 | { 94 | get => rank4Ups; 95 | set => SetProperty(ref rank4Ups, value); 96 | } 97 | public bool Rank4UpsAvailAble 98 | { 99 | get => Rank4Ups != null && Rank4Ups.Count > 0; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Models/DDCVMainPanelItemModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | 10 | namespace DodocoTales.SR.Gui.Models 11 | { 12 | public class DDCVMainPanelItemModel : ObservableObject 13 | { 14 | private string title; 15 | public string Title 16 | { 17 | get => title; 18 | set => SetProperty(ref title, value); 19 | } 20 | 21 | private string tag; 22 | public string Tag 23 | { 24 | get => tag; 25 | set => SetProperty(ref tag, value); 26 | } 27 | 28 | // TODO: Screen's pointer 29 | 30 | private ObservableCollection menuItems; 31 | public ObservableCollection MenuItems 32 | { 33 | get => menuItems; 34 | set => SetProperty(ref menuItems, value); 35 | } 36 | 37 | 38 | private Thickness padding; 39 | public Thickness Padding 40 | { 41 | get => padding; 42 | set => SetProperty(ref padding, value); 43 | } 44 | 45 | private bool isSelected; 46 | public bool IsSelected 47 | { 48 | get => isSelected; 49 | set => SetProperty(ref isSelected, value); 50 | } 51 | 52 | 53 | public DDCVMainPanelItemModel(string title, string tag, int level) 54 | { 55 | Title = title; 56 | Tag = tag; 57 | Padding = new Thickness(10 * level, 0, 0, 0); 58 | MenuItems = new ObservableCollection(); 59 | IsSelected = false; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Models/DDCVRoundItemModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Library.CurrentUser.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Gui.Models 10 | { 11 | public class DDCVRoundItemModel : ObservableObject 12 | { 13 | private bool isSelected; 14 | public bool IsSelected 15 | { 16 | get => isSelected; 17 | set => SetProperty(ref isSelected, value); 18 | } 19 | 20 | private ulong versionId; 21 | public ulong VersionID 22 | { 23 | get => versionId; 24 | set => SetProperty(ref versionId, value); 25 | } 26 | private ulong bannerInternalId; 27 | public ulong BannerInternalID 28 | { 29 | get => bannerInternalId; 30 | set => SetProperty(ref bannerInternalId, value); 31 | } 32 | 33 | private int index; 34 | public int Index 35 | { 36 | get => index; 37 | set => SetProperty(ref index, value); 38 | } 39 | 40 | private DDCLRoundLogItem logItem; 41 | public DDCLRoundLogItem LogItem 42 | { 43 | get => logItem; 44 | set => SetProperty(ref logItem, value); 45 | } 46 | 47 | public int Count 48 | { 49 | get => LogItem?.Logs.Count ?? 0; 50 | } 51 | 52 | public int CountCurrent 53 | { 54 | get => LogItem?.Logs.Count(x => x.BannerInternalID == BannerInternalID) ?? 0; 55 | } 56 | 57 | public int CountInherited 58 | { 59 | get => Count - CountCurrent; 60 | } 61 | 62 | public int Rank5 63 | { 64 | get => LogItem?.Logs.Count(x => x.Rank == 5) ?? 0; 65 | } 66 | 67 | public int Rank4 68 | { 69 | get => LogItem?.Logs.Count(x => x.Rank == 4) ?? 0; 70 | } 71 | 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Models/DDCVUnitIndicatorModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Gui.Enums; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Gui.Models 10 | { 11 | public class DDCVUnitIndicatorModel : ObservableObject 12 | { 13 | private string name; 14 | public string Name 15 | { 16 | get => name; 17 | set => SetProperty(ref name, value); 18 | } 19 | 20 | private int count; 21 | public int Count 22 | { 23 | get => count; 24 | set => SetProperty(ref count, value); 25 | } 26 | 27 | private DateTimeOffset time; 28 | public DateTimeOffset Time 29 | { 30 | get => time; 31 | set => SetProperty(ref time, value); 32 | } 33 | 34 | private string version; 35 | public string Version 36 | { 37 | get => version; 38 | set => SetProperty(ref version, value); 39 | } 40 | private string banner; 41 | public string Banner 42 | { 43 | get => banner; 44 | set => SetProperty(ref banner, value); 45 | } 46 | private int index; 47 | public int Index 48 | { 49 | get => index; 50 | set => SetProperty(ref index, value); 51 | } 52 | private DDCVUnitIndicatorType indicatorType; 53 | public DDCVUnitIndicatorType IndicatorType 54 | { 55 | get => indicatorType; 56 | set => SetProperty(ref indicatorType, value); 57 | } 58 | private bool inherited; 59 | public bool Inherited 60 | { 61 | get => inherited; 62 | set => SetProperty(ref inherited, value); 63 | } 64 | private ulong id; 65 | public ulong ID 66 | { 67 | get => id; 68 | set => SetProperty(ref id, value); 69 | } 70 | private bool imported; 71 | public bool Imported 72 | { 73 | get => imported; 74 | set => SetProperty(ref imported, value); 75 | } 76 | private bool untrusted; 77 | public bool Untrusted 78 | { 79 | get => untrusted; 80 | set => SetProperty(ref untrusted, value); 81 | } 82 | private string application; 83 | public string ImportApplication 84 | { 85 | get => application; 86 | set => SetProperty(ref application, value); 87 | } 88 | 89 | private int brMax; 90 | public int BrMax 91 | { 92 | get => brMax; 93 | set => SetProperty(ref brMax, value); 94 | } 95 | private int rndMax; 96 | public int RndMax 97 | { 98 | get => rndMax; 99 | set => SetProperty(ref rndMax, value); 100 | } 101 | private bool brlucky; 102 | public bool BrLucky 103 | { 104 | get => brlucky; 105 | set => SetProperty(ref brlucky, value); 106 | } 107 | 108 | private bool brunlucky; 109 | public bool BrUnlucky 110 | { 111 | get => brunlucky; 112 | set => SetProperty(ref brunlucky, value); 113 | } 114 | 115 | private bool rndlucky; 116 | public bool RndLucky 117 | { 118 | get => rndlucky; 119 | set => SetProperty(ref rndlucky, value); 120 | } 121 | 122 | private bool rndunlucky; 123 | public bool RndUnlucky 124 | { 125 | get => rndunlucky; 126 | set => SetProperty(ref rndunlucky, value); 127 | } 128 | 129 | private int rndcount; 130 | public int RndCount 131 | { 132 | get => rndcount; 133 | set => SetProperty(ref rndcount, value); 134 | } 135 | 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Models/DDCVUserlogItem.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Library.Enums; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Gui.Models 10 | { 11 | public class DDCVUserlogItem : ObservableObject 12 | { 13 | private long uid; 14 | public long UID 15 | { 16 | get => uid; 17 | set => SetProperty(ref uid, value); 18 | } 19 | 20 | private int timezone; 21 | public int TimeZone 22 | { 23 | get => timezone; 24 | set => SetProperty(ref timezone, value); 25 | } 26 | 27 | private DDCLGameClientType clientType; 28 | public DDCLGameClientType ClientType 29 | { 30 | get => clientType; 31 | set => SetProperty(ref clientType, value); 32 | } 33 | 34 | private bool isSelected; 35 | public bool IsSelected 36 | { 37 | get => isSelected; 38 | set => SetProperty(ref isSelected, value); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Models/DDCVVersionItemModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Common.Enums; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Gui.Models 11 | { 12 | public class DDCVVersionItemModel : ObservableObject 13 | { 14 | private ulong versionId; 15 | public ulong VersionID 16 | { 17 | get => versionId; 18 | set => SetProperty(ref versionId, value); 19 | } 20 | 21 | private string versionName; 22 | public string VersionName 23 | { 24 | get => versionName; 25 | set => SetProperty(ref versionName, value); 26 | } 27 | private string version; 28 | public string Version 29 | { 30 | get => version; 31 | set => SetProperty(ref version, value); 32 | } 33 | private DateTimeOffset beginTime; 34 | public DateTimeOffset BeginTime 35 | { 36 | get => beginTime; 37 | set => SetProperty(ref beginTime, value); 38 | } 39 | private DateTimeOffset endTime; 40 | public DateTimeOffset EndTime 41 | { 42 | get => endTime; 43 | set => SetProperty(ref endTime, value); 44 | } 45 | 46 | private ObservableCollection banners; 47 | public ObservableCollection Banners 48 | { 49 | get => banners; 50 | set => SetProperty(ref banners, value); 51 | } 52 | 53 | public int BannersCnt 54 | { 55 | get => Banners.Count; 56 | } 57 | public int CharacterEventCnt 58 | { 59 | get => Banners.Where(x => x.PoolType == DDCCPoolType.CharacterEvent).Sum(x => x.Total); 60 | } 61 | public int LCEventCnt 62 | { 63 | get => Banners.Where(x => x.PoolType == DDCCPoolType.LCEvent).Sum(x => x.Total); 64 | } 65 | public int PermanentCnt 66 | { 67 | get => Banners.Where(x => x.PoolType == DDCCPoolType.Permanent).Sum(x => x.Total); 68 | } 69 | public int Total 70 | { 71 | get => Banners.Sum(x => x.Total); 72 | } 73 | public int Rank5 74 | { 75 | get => Banners.Sum(x => x.Rank5); 76 | } 77 | public int Rank4 78 | { 79 | get => Banners.Sum(x => x.Rank4); 80 | } 81 | private ObservableCollection rank5s; 82 | public ObservableCollection Rank5s 83 | { 84 | get => rank5s; 85 | set => SetProperty(ref rank5s, value); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Resources/DDCVConverters.xaml: -------------------------------------------------------------------------------- 1 |  5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Resources/DDCVResources.xaml: -------------------------------------------------------------------------------- 1 |  3 | ./Digiface_Regular.ttf #Digiface 4 | ./Segment7Standard.otf #Segment7 Standard 5 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Resources/Digiface_Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TremblingMoeNew/StarRailWarpObserve/d930b7603720da2252cf3b8d2ef7b4da899ccc56/DodocoTales.StarRail/Gui/Resources/Digiface_Regular.ttf -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Resources/Segment7Standard.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TremblingMoeNew/StarRailWarpObserve/d930b7603720da2252cf3b8d2ef7b4da899ccc56/DodocoTales.StarRail/Gui/Resources/Segment7Standard.otf -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Resources/Styles/DDCVListViewItemStyle.xaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 34 | 35 | 65 | 66 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Cards/DDCVHomeSceneCharEventCardVM.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Gui.ViewModels.Cards 9 | { 10 | public class DDCVHomeSceneCharEventCardVM : DDCVHomeSceneCardVMBase 11 | { 12 | public DDCVHomeSceneCharEventCardVM() 13 | { 14 | InitializeDashboard(DDCCPoolType.CharacterEvent, 180, 90); 15 | softPityThreshold = 73; 16 | brLuckyLimit = 50; 17 | rndLuckyLimit = 72; 18 | rndUnluckyLimit = 130; 19 | } 20 | public override void RefreshGlobalDashboard() 21 | { 22 | SetDBVRate(DBVGlobalR5, GlobalRank5, GlobalTotal, 1.1, 2.1); 23 | SetDBVRate(DBVGlobalR5Up, GlobalRank5Up, GlobalTotal, 0.5, 1.6); 24 | SetDBVRate(DBVGlobalR4, GlobalRank4, GlobalTotal, 8, 18); 25 | SetDBVRate(DBVGlobalR4Up, GlobalRank4Up, GlobalTotal, 3.6, 13.6); 26 | if (CurrentBasicRoundCount > softPityThreshold) 27 | { 28 | SoftPityActivated = true; 29 | SoftPityChance = Math.Max(0.006 + (CurrentBasicRoundCount - softPityThreshold) * 0.06, 1); 30 | SoftPityChance *= (CurrentRoundCurrent == CurrentBasicRoundCount) ? 0.5625 : 1; 31 | } 32 | else 33 | { 34 | SoftPityActivated = false; 35 | SoftPityChance = 0.006; 36 | SoftPityChance *= (CurrentRoundCurrent == CurrentBasicRoundCount) ? 0.5625 : 1; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Cards/DDCVHomeSceneLCEventCardVM.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Gui.ViewModels.Cards 9 | { 10 | public class DDCVHomeSceneLCEventCardVM : DDCVHomeSceneCardVMBase 11 | { 12 | public DDCVHomeSceneLCEventCardVM() 13 | { 14 | InitializeDashboard(DDCCPoolType.LCEvent, 160, 80); 15 | softPityThreshold = 65; 16 | brLuckyLimit = 48; 17 | rndLuckyLimit = 50; 18 | rndUnluckyLimit = 80; 19 | } 20 | public override void RefreshGlobalDashboard() 21 | { 22 | SetDBVRate(DBVGlobalR5, GlobalRank5, GlobalTotal, 1.25, 2.45); 23 | SetDBVRate(DBVGlobalR5Up, GlobalRank5Up, GlobalTotal, 0.6, 2.38); 24 | SetDBVRate(DBVGlobalR4, GlobalRank4, GlobalTotal, 9, 19.5); 25 | SetDBVRate(DBVGlobalR4Up, GlobalRank4Up, GlobalTotal, 5, 18.8); 26 | if (CurrentBasicRoundCount > softPityThreshold) 27 | { 28 | SoftPityActivated = true; 29 | SoftPityChance = Math.Max(0.008 + (CurrentBasicRoundCount - softPityThreshold) * 0.07, 1); 30 | SoftPityChance *= (CurrentRoundCurrent == CurrentBasicRoundCount) ? 0.78125 : 1; 31 | } 32 | else 33 | { 34 | SoftPityActivated = false; 35 | SoftPityChance = 0.008; 36 | SoftPityChance *= (CurrentRoundCurrent == CurrentBasicRoundCount) ? 0.78125 : 1; 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Cards/DDCVHomeScenePermanentCardVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Common.Enums; 3 | using DodocoTales.SR.Gui.Models; 4 | using DodocoTales.SR.Library; 5 | using DodocoTales.SR.Library.Enums; 6 | using DodocoTales.SR.Library.UserDataLibrary.Models; 7 | using LiveChartsCore; 8 | using LiveChartsCore.Defaults; 9 | using LiveChartsCore.SkiaSharpView; 10 | using LiveChartsCore.SkiaSharpView.Painting; 11 | using SkiaSharp; 12 | using System; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.Text; 17 | using System.Threading.Tasks; 18 | 19 | namespace DodocoTales.SR.Gui.ViewModels.Cards 20 | { 21 | public class DDCVHomeScenePermanentCardVM : DDCVHomeSceneCardVMBase 22 | { 23 | public DDCVHomeScenePermanentCardVM() 24 | { 25 | InitializeDashboard(DDCCPoolType.Permanent, 90, 90); 26 | softPityThreshold = 73; 27 | brLuckyLimit = 50; 28 | rndLuckyLimit = 50; 29 | rndUnluckyLimit = 72; 30 | } 31 | public override void RefreshGlobalDashboard() 32 | { 33 | SetDBVRate(DBVGlobalR5, GlobalRank5, GlobalTotal, 1.1, 2.1); 34 | SetDBVRate(DBVGlobalR4, GlobalRank4, GlobalTotal, 8, 18); 35 | if (CurrentBasicRoundCount > softPityThreshold) 36 | { 37 | SoftPityActivated = true; 38 | SoftPityChance = Math.Max(0.006 + (CurrentBasicRoundCount - softPityThreshold) * 0.06, 1); 39 | } 40 | else 41 | { 42 | SoftPityActivated = false; 43 | SoftPityChance = 0.006; 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Dialogs/DDCVGameClientManagerWindowEditDialogVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Library; 3 | using DodocoTales.SR.Library.Enums; 4 | using DodocoTales.SR.Library.GameClient.Models; 5 | using DodocoTales.SR.Loader; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | using System.Linq; 10 | using System.Text; 11 | using System.Threading.Tasks; 12 | 13 | namespace DodocoTales.SR.Gui.ViewModels.Dialogs 14 | { 15 | public class DDCVGameClientManagerWindowEditDialogVM : ObservableObject 16 | { 17 | private Dictionary clientOptions; 18 | public Dictionary ClientOptions 19 | { 20 | get => clientOptions; 21 | set => SetProperty(ref clientOptions, value); 22 | } 23 | private Dictionary timeZoneOptions; 24 | public Dictionary TimeZoneOptions 25 | { 26 | get => timeZoneOptions; 27 | set => SetProperty(ref timeZoneOptions, value); 28 | } 29 | 30 | private DDCLGameClientType clientType; 31 | public DDCLGameClientType ClientType 32 | { 33 | get => clientType; 34 | set 35 | { 36 | SetProperty(ref clientType, value); 37 | switch(ClientType) 38 | { 39 | case DDCLGameClientType.CN: 40 | if(string.IsNullOrEmpty(Name)|| Name== DDCG.GameClientLoader.ClientName_OS) 41 | Name = DDCG.GameClientLoader.ClientName_CN; 42 | break; 43 | case DDCLGameClientType.Global: 44 | if (string.IsNullOrEmpty(Name) || Name == DDCG.GameClientLoader.ClientName_CN) 45 | Name = DDCG.GameClientLoader.ClientName_OS; 46 | break; 47 | } 48 | } 49 | } 50 | private int timeZone; 51 | public int TimeZone 52 | { 53 | get => timeZone; 54 | set => SetProperty(ref timeZone, value); 55 | } 56 | 57 | private string name; 58 | public string Name 59 | { 60 | get => name; 61 | set => SetProperty(ref name, value); 62 | } 63 | 64 | private string path; 65 | public string Path 66 | { 67 | get => path; 68 | set => SetProperty(ref path, value); 69 | } 70 | 71 | public DDCLGameClientItem GameClientItem { get; set; } 72 | 73 | public DDCVGameClientManagerWindowEditDialogVM() 74 | { 75 | ClientOptions = new Dictionary 76 | { 77 | { "国服客户端", DDCLGameClientType.CN }, 78 | { "国际服客户端", DDCLGameClientType.Global } 79 | }; 80 | 81 | } 82 | 83 | public void NewGameClientItem() 84 | { 85 | GameClientItem = null; 86 | } 87 | 88 | public void LoadGameClientItem(DDCLGameClientItem item) 89 | { 90 | GameClientItem = item; 91 | Name = item.Name; 92 | ClientType = item.ClientType; 93 | Path = item.Path; 94 | } 95 | 96 | readonly string filefilter = "Honkai Star Rail Executable|StarRail.exe"; 97 | public void EditGamePath() 98 | { 99 | var dialog = new System.Windows.Forms.OpenFileDialog 100 | { 101 | Filter = filefilter, 102 | 103 | }; 104 | if (Path != null) dialog.InitialDirectory = Directory.GetParent(Path).Parent.FullName; 105 | if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) 106 | { 107 | var item = DDCG.GameClientLoader.LoadGameClientItemFromExecutablePath(dialog.FileName); 108 | if (item != null) 109 | { 110 | if (Name == null) Name = item.Name; 111 | if (ClientType == DDCLGameClientType.Unknown) ClientType = item.ClientType; 112 | Path = item.Path; 113 | } 114 | 115 | } 116 | } 117 | public bool CheckValid() 118 | { 119 | return !string.IsNullOrEmpty(Name) 120 | && ClientType != DDCLGameClientType.Unknown 121 | && !string.IsNullOrEmpty(Path); 122 | } 123 | 124 | 125 | public bool SaveAsCopy() 126 | { 127 | if (!CheckValid()) return false; 128 | var item = new DDCLGameClientItem 129 | { 130 | Name = Name, 131 | ClientType = ClientType, 132 | Path = Path, 133 | }; 134 | DDCL.GameClientLib.AddClients(new List { item }); 135 | return true; 136 | } 137 | 138 | public async Task Save() 139 | { 140 | if (GameClientItem == null) 141 | { 142 | return SaveAsCopy(); 143 | } 144 | if (!CheckValid()) return false; 145 | GameClientItem.Name = Name; 146 | GameClientItem.ClientType = ClientType; 147 | GameClientItem.Path = Path; 148 | await DDCL.GameClientLib.SaveLibraryAsync(); 149 | return true; 150 | } 151 | public void Delete() 152 | { 153 | if (GameClientItem == null) return; 154 | DDCL.GameClientLib.RemoveClients(new List { GameClientItem }); 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Screens/DDCVDependenciesDownloadScreenVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Common; 3 | using DodocoTales.SR.Loader.Models; 4 | using Panuon.UI.Silver; 5 | using SkiaSharp.Internals; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows.Threading; 12 | 13 | namespace DodocoTales.SR.Gui.ViewModels.Screens 14 | { 15 | public class DDCVDependenciesDownloadScreenVM : ObservableObject 16 | { 17 | 18 | private readonly string initialHint = "正在初始化下载……"; 19 | private readonly string failedHint = "下载失败,请稍后再试或尝试手动下载"; 20 | 21 | private string downloadHint; 22 | public string DownloadHint 23 | { 24 | get => downloadHint; 25 | set => SetProperty(ref downloadHint, value); 26 | } 27 | 28 | private int progressBarLength; 29 | public int ProgressBarLength 30 | { 31 | get => progressBarLength; 32 | set => SetProperty(ref progressBarLength, value); 33 | } 34 | 35 | private int progressBarMaxLength; 36 | public int ProgressBarMaxLength 37 | { 38 | get => progressBarMaxLength; 39 | set => SetProperty(ref progressBarMaxLength, value); 40 | } 41 | 42 | 43 | public DDCVDependenciesDownloadScreenVM() 44 | { 45 | ProgressBarLength = 0; 46 | ProgressBarMaxLength = 500; 47 | DownloadHint = initialHint; 48 | 49 | DDCS.ClientUpdateDownloadStatusReport += OnDependencyUpdateStatusReported; 50 | DDCS.DependencyUpdateDownloadFailed += OnDependecyUpdateFailed; 51 | } 52 | 53 | private void OnDependencyUpdateStatusReported(dynamic var) 54 | { 55 | DDCGDownloadTask task = var; 56 | 57 | DownloadHint = $"{task.LocalFileName} {task.DownloadedSize / 1024.0:F2}KB/{task.FileSize / 1024.0:F2}KB {task.EstSpeed / 1024:F2}KB/s EST:{(task.FileSize - task.DownloadedSize) / task.EstSpeed:F2}s"; 58 | ProgressBarLength = Convert.ToInt32(ProgressBarMaxLength * (1.0 * task.DownloadedSize / task.FileSize)); 59 | } 60 | 61 | private void OnDependecyUpdateFailed() 62 | { 63 | DownloadHint = failedHint; 64 | } 65 | 66 | 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Screens/DDCVSettingsWindowAboutScreenVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Library; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Gui.ViewModels.Screens 10 | { 11 | public class DDCVSettingsWindowAboutScreenVM : ObservableObject 12 | { 13 | private string clientVersion; 14 | public string ClientVersion 15 | { 16 | get => clientVersion; 17 | set => SetProperty(ref clientVersion, value); 18 | } 19 | 20 | private string bannerLibraryVersion; 21 | public string BannerLibraryVersion 22 | { 23 | get => bannerLibraryVersion; 24 | set => SetProperty(ref bannerLibraryVersion, value); 25 | } 26 | 27 | public DDCVSettingsWindowAboutScreenVM() 28 | { 29 | ClientVersion = DDCL.MetaVersionLib.ClientVersion; 30 | BannerLibraryVersion = DDCL.MetaVersionLib.BannerLibraryVersion; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Screens/DDCVSettingsWindowChangeLogScreenVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Loader; 3 | using Panuon.UI.Silver; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Gui.ViewModels.Screens 11 | { 12 | public class DDCVSettingsWindowChangeLogScreenVM : ObservableObject 13 | { 14 | private string changelog; 15 | public string ChangeLog 16 | { 17 | get => changelog; 18 | set => SetProperty(ref changelog, value); 19 | } 20 | 21 | public async void Refresh() 22 | { 23 | if (DDCG.UpdateLoader.ChangeLog == null) 24 | { 25 | await DDCG.UpdateLoader.LoadChangeLog(); 26 | } 27 | if (DDCG.UpdateLoader.ChangeLog == null) 28 | { 29 | Notice.Show("更新日志载入失败。", "错误", MessageBoxIcon.Error); 30 | } 31 | ChangeLog = DDCG.UpdateLoader.ChangeLog; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Screens/DDCVSettingsWindowUsersScreenVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Gui.Models; 3 | using DodocoTales.SR.Library; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DodocoTales.SR.Gui.ViewModels.Screens 12 | { 13 | public class DDCVSettingsWindowUsersScreenVM : ObservableObject 14 | { 15 | private ObservableCollection users; 16 | public ObservableCollection Users 17 | { 18 | get => users; 19 | set => SetProperty(ref users, value); 20 | } 21 | 22 | 23 | public void Refresh() 24 | { 25 | List list = new List(); 26 | foreach (var log in DDCL.UserDataLib.U.Values) 27 | { 28 | list.Add(new DDCVUserlogItem 29 | { 30 | UID = log.UID, 31 | ClientType = log.ClientType, 32 | TimeZone = log.TimeZone, 33 | IsSelected = DDCL.CurrentUser.IsCurrentUser(log.UID), 34 | }); 35 | } 36 | Users = new ObservableCollection(list); 37 | 38 | } 39 | 40 | public void SwapUser(DDCVUserlogItem user) 41 | { 42 | DDCL.CurrentUser.SwapUser(user.UID); 43 | Refresh(); 44 | } 45 | 46 | public async void RemoveUser(DDCVUserlogItem user) 47 | { 48 | await DDCL.UserDataLib.RemoveUserByUid(user.UID); 49 | Refresh(); 50 | } 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Screens/DDCVVersionViewScreenVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Common.Enums; 3 | using DodocoTales.SR.Gui.Models; 4 | using DodocoTales.SR.Library; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Collections.ObjectModel; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace DodocoTales.SR.Gui.ViewModels.Screens 13 | { 14 | public class DDCVVersionViewScreenVM : ObservableObject 15 | { 16 | private ObservableCollection versions; 17 | public ObservableCollection Versions 18 | { 19 | get => versions; 20 | set => SetProperty(ref versions, value); 21 | } 22 | 23 | 24 | 25 | 26 | public void ReloadData() 27 | { 28 | var ls = new List(); 29 | var typeEmpty = new Dictionary(); 30 | foreach (DDCCPoolType type in Enum.GetValues(typeof(DDCCPoolType))) 31 | { 32 | typeEmpty[type] = true; 33 | } 34 | var tz = DDCL.CurrentUser.GetActivatingTimeZone(); 35 | foreach (var version in DDCL.BannerLib.Versions) 36 | { 37 | DDCVVersionItemModel vermodel = new DDCVVersionItemModel 38 | { 39 | VersionID = version.ID, 40 | VersionName = version.Name, 41 | Version = version.Version, 42 | BeginTime = DDCL.GetSyncTimeOffset(version.BeginTime).ToLocalTime(), 43 | EndTime = DDCL.GetSyncTimeOffset(version.EndTime).ToLocalTime() 44 | }; 45 | var r5s = new List(); 46 | var banls = new List(); 47 | var banners = DDCL.CurrentUser.GetBannersByVersion(version.ID); 48 | foreach (var banner in banners) 49 | { 50 | var baninfo = DDCL.BannerLib.GetBanner(banner.BannerInternalID); 51 | DDCVBannerItemModel banmodel = new DDCVBannerItemModel 52 | { 53 | VersionID = version.ID, 54 | Version = version.Version, 55 | BannerName = baninfo.Name, 56 | BannerInternalID = banner.BannerInternalID, 57 | BannerHint = baninfo.Hint, 58 | PoolType = banner.CategorizedGachaType, 59 | BeginTime = DDCL.GetBannerTimeOffset(baninfo.BeginTime, baninfo.BeginTimeSync, tz).ToLocalTime(), 60 | EndTime = DDCL.GetBannerTimeOffset(baninfo.EndTime, baninfo.EndTimeSync, tz).ToLocalTime(), 61 | 62 | }; 63 | 64 | banmodel.Total = banner.Logs.Count; 65 | 66 | if (banmodel.Total > 0) 67 | { 68 | typeEmpty[banner.CategorizedGachaType] = false; 69 | } 70 | 71 | var r5 = banner.Logs.FindAll(x => x.Rank == 5); 72 | banmodel.Rank5 = r5.Count; 73 | var r5ups = new List(); 74 | foreach (var up in baninfo.Rank5Up) 75 | { 76 | r5ups.Add(new DDCVUnitIndicatorModel 77 | { 78 | Name = up, 79 | Count = r5.FindAll(x => x.Name == up).Count 80 | }); 81 | } 82 | banmodel.Rank5Ups = new ObservableCollection(r5ups); 83 | foreach (var item in r5) 84 | { 85 | r5s.Add(new DDCVUnitIndicatorModel 86 | { 87 | Name = item.Name, 88 | Time = DDCL.GetTimeOffset(item.Time, tz), 89 | Version = version.Version, 90 | Banner = baninfo.Name, 91 | ID = item.ID, 92 | Count = DDCL.CurrentUser.Logs.Values.Where(x => x.RoundID == item.RoundID).Count() 93 | }); 94 | } 95 | 96 | 97 | var r4 = banner.Logs.FindAll(x => x.Rank == 4); 98 | banmodel.Rank4 = r4.Count; 99 | var r4ups = new List(); 100 | foreach (var up in baninfo.Rank4Up) 101 | { 102 | r4ups.Add(new DDCVUnitIndicatorModel 103 | { 104 | Name = up, 105 | Count = r4.FindAll(x => x.Name == up).Count 106 | }); 107 | } 108 | r4ups.Sort((x, y) => x.Name.Length.CompareTo(y.Name.Length)); 109 | banmodel.Rank4Ups = new ObservableCollection(r4ups); 110 | 111 | 112 | if (!typeEmpty[banner.CategorizedGachaType]) 113 | { 114 | banls.Add(banmodel); 115 | } 116 | typeEmpty[DDCCPoolType.Beginner] = typeEmpty[DDCCPoolType.Null] = true; 117 | } 118 | 119 | 120 | if (banls.Count > 0) 121 | { 122 | banls.Reverse(); 123 | vermodel.Banners = new ObservableCollection(banls); 124 | r5s.Sort((x, y) => y.ID.CompareTo(x.ID)); 125 | vermodel.Rank5s = new ObservableCollection(r5s); 126 | ls.Add(vermodel); 127 | } 128 | 129 | 130 | } 131 | ls.Reverse(); 132 | Versions = new ObservableCollection(ls); 133 | } 134 | 135 | 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Windows/DDCVGameClientManagerWindowVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Library; 3 | using DodocoTales.SR.Library.GameClient.Models; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DodocoTales.SR.Gui.ViewModels.Windows 12 | { 13 | public class DDCVGameClientManagerWindowVM : ObservableObject 14 | { 15 | private ObservableCollection clients; 16 | public ObservableCollection Clients 17 | { 18 | get => clients; 19 | set => SetProperty(ref clients, value); 20 | } 21 | public void ReloadData() 22 | { 23 | Clients = new ObservableCollection(DDCL.GameClientLib.GetClients()); 24 | } 25 | 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/ViewModels/Windows/DDCVSettingsWindowVM.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using DodocoTales.SR.Gui.Models; 3 | using DodocoTales.SR.Gui.Views.Screens; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows; 11 | using System.Windows.Controls; 12 | 13 | namespace DodocoTales.SR.Gui.ViewModels.Windows 14 | { 15 | public class DDCVSettingsWindowVM : ObservableObject 16 | { 17 | public readonly Dictionary Screens = new Dictionary(); 18 | public Grid Navigater; 19 | public DDCVSwapableScreen Current; 20 | 21 | private ObservableCollection menuItems; 22 | public ObservableCollection MenuItems 23 | { 24 | get => menuItems; 25 | set => SetProperty(ref menuItems, value); 26 | } 27 | 28 | public DDCVSettingsWindowVM() 29 | { 30 | Screens = new Dictionary(); 31 | 32 | MenuItems = new ObservableCollection() 33 | { 34 | new DDCVMainPanelItemModel("用户","Users", 0), 35 | new DDCVMainPanelItemModel("关于","About",0), 36 | new DDCVMainPanelItemModel("更新日志","ChangeLog",0), 37 | }; 38 | } 39 | 40 | public void Initialize(Grid navigator) 41 | { 42 | Navigater = navigator; 43 | RegisterScreen("Users", new DDCVSettingsWindowUsersScreen()); 44 | RegisterScreen("About", new DDCVSettingsWindowAboutScreen()); 45 | RegisterScreen("ChangeLog", new DDCVSettingsWindowChangeLogScreen()); 46 | SelectMenu("About"); 47 | } 48 | 49 | public void RegisterScreen(string tag, DDCVSwapableScreen screen) 50 | { 51 | Screens.Add(tag, screen); 52 | screen.Visibility = Visibility.Collapsed; 53 | Navigater.Children.Add(screen); 54 | } 55 | 56 | public void SwapScreen(string tag) 57 | { 58 | if (!Screens.TryGetValue(tag, out DDCVSwapableScreen ns)) 59 | { 60 | return; 61 | } 62 | if(Current != null) 63 | { 64 | Current.Visibility = Visibility.Collapsed; 65 | } 66 | Current = ns; 67 | Current.Visibility=Visibility.Visible; 68 | Current.Refresh(); 69 | } 70 | 71 | public void SelectMenu(string tag) 72 | { 73 | MenuItems.ToList().ForEach(x=>x.IsSelected = (x.Tag == tag)); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Cards/DDCVHomeSceneCharEventCard.xaml.cs: -------------------------------------------------------------------------------- 1 | using Panuon.UI.Silver; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace DodocoTales.SR.Gui.Views.Cards 18 | { 19 | /// 20 | /// DDCVHomeSceneCharEventCard.xaml 的交互逻辑 21 | /// 22 | public partial class DDCVHomeSceneCharEventCard : UserControl 23 | { 24 | public DDCVHomeSceneCharEventCard() 25 | { 26 | InitializeComponent(); 27 | } 28 | public void Refresh() 29 | { 30 | VM.ReloadData(); 31 | } 32 | private void RadioButton_Checked(object sender, RoutedEventArgs e) 33 | { 34 | var btn = sender as RadioButton; 35 | if (btn != null) 36 | { 37 | var idx = Convert.ToInt32(btn.Tag); 38 | VM.UnitIndicatorCurrentPageIndex = idx; 39 | } 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Cards/DDCVHomeSceneLCEventCard.xaml.cs: -------------------------------------------------------------------------------- 1 | using Panuon.UI.Silver; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace DodocoTales.SR.Gui.Views.Cards 18 | { 19 | /// 20 | /// DDCVHomeSceneLCEventCard.xaml 的交互逻辑 21 | /// 22 | public partial class DDCVHomeSceneLCEventCard : UserControl 23 | { 24 | public DDCVHomeSceneLCEventCard() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | 30 | public void Refresh() 31 | { 32 | VM.ReloadData(); 33 | } 34 | 35 | private void RadioButton_Checked(object sender, RoutedEventArgs e) 36 | { 37 | var btn = sender as RadioButton; 38 | if (btn != null) 39 | { 40 | var idx = Convert.ToInt32(btn.Tag); 41 | VM.UnitIndicatorCurrentPageIndex = idx; 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Cards/DDCVHomeScenePermanentCard.xaml.cs: -------------------------------------------------------------------------------- 1 | using Panuon.UI.Silver; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace DodocoTales.SR.Gui.Views.Cards 18 | { 19 | /// 20 | /// DDCVHomeScenePermanentCard.xaml 的交互逻辑 21 | /// 22 | public partial class DDCVHomeScenePermanentCard : UserControl 23 | { 24 | public DDCVHomeScenePermanentCard() 25 | { 26 | InitializeComponent(); 27 | } 28 | public void Refresh() 29 | { 30 | VM.ReloadData(); 31 | } 32 | 33 | private void RadioButton_Checked(object sender, RoutedEventArgs e) 34 | { 35 | var btn = sender as RadioButton; 36 | if (btn != null) 37 | { 38 | var idx = Convert.ToInt32(btn.Tag); 39 | VM.UnitIndicatorCurrentPageIndex = idx; 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Dialogs/DDCVExportDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Shapes; 15 | 16 | namespace DodocoTales.SR.Gui.Views.Dialogs 17 | { 18 | /// 19 | /// DDCVExportDialog.xaml 的交互逻辑 20 | /// 21 | public partial class DDCVExportDialog : Window 22 | { 23 | public DDCVExportDialog() 24 | { 25 | InitializeComponent(); 26 | } 27 | 28 | private void FilePathBox_MouseDown(object sender, MouseButtonEventArgs e) 29 | { 30 | VM.SelectExportPath(); 31 | } 32 | 33 | private async void ExportButton_Click(object sender, RoutedEventArgs e) 34 | { 35 | VM.SelectedUIDMulti.Clear(); 36 | foreach(KeyValuePair x in MultiUIDSelect.SelectedItems) 37 | { 38 | VM.SelectedUIDMulti.Add(x.Key); 39 | } 40 | if(await VM.Export()) 41 | Close(); 42 | } 43 | 44 | private void CancelButton_Click(object sender, RoutedEventArgs e) 45 | { 46 | Close(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Dialogs/DDCVGameClientManagerWindowEditDialog.xaml: -------------------------------------------------------------------------------- 1 |  15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 41 | 42 | 52 | 53 | 54 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVGachaPredictionScreen.xaml.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Common.Services; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.ComponentModel; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows; 11 | using System.Windows.Controls; 12 | using System.Windows.Data; 13 | using System.Windows.Documents; 14 | using System.Windows.Input; 15 | using System.Windows.Media; 16 | using System.Windows.Media.Imaging; 17 | using System.Windows.Navigation; 18 | using System.Windows.Shapes; 19 | 20 | namespace DodocoTales.SR.Gui.Views.Screens 21 | { 22 | /// 23 | /// DDCVGachaPredictionScreen.xaml 的交互逻辑 24 | /// 25 | public partial class DDCVGachaPredictionScreen : DDCVSwapableScreen 26 | { 27 | public DDCVGachaPredictionScreen() 28 | { 29 | InitializeComponent(); 30 | } 31 | 32 | private void Button_Click(object sender, RoutedEventArgs e) 33 | { 34 | 35 | } 36 | 37 | public override void Refresh() 38 | { 39 | 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVHomeScreen.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVHomeScreen.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace DodocoTales.SR.Gui.Views.Screens 17 | { 18 | /// 19 | /// DDCVHomeScreen.xaml 的交互逻辑 20 | /// 21 | public partial class DDCVHomeScreen : DDCVSwapableScreen 22 | { 23 | public DDCVHomeScreen() 24 | { 25 | InitializeComponent(); 26 | } 27 | 28 | public override void Refresh() 29 | { 30 | CharEvent.Refresh(); 31 | LCEvent.Refresh(); 32 | Permanant.Refresh(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVSettingsWindowAboutScreen.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 星穹铁道跃迁观测工具 16 | Star Rail Wrap Observe (Starwo) 17 | (Codename: DodocoTales.StarRail) 18 | 19 | 20 | 网站: 21 | 22 | 地址 23 | 24 | 25 | 26 | 项目: 27 | 28 | TremblingMoeNew/StarRailWarpObserve 29 | 30 | 31 | 许可证: MIT协议 32 | 33 | 34 | 35 | 本程序基于.NET Framework 4.7.2构建,依赖以下项目: 36 | 37 | JamesNK/Newtonsoft.Json 38 | 39 | 40 | Mochengvia/PanuonUI.Silver 41 | 42 | 43 | beto-rodriguez/LiveCharts2 44 | 45 | 46 | CommunityToolkit/dotnet 47 | 48 | 49 | CommunityToolkit/WindowsCommunityToolkit 50 | 51 | 52 | justcoding121/Titanium-Web-Proxy 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVSettingsWindowAboutScreen.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace DodocoTales.SR.Gui.Views.Screens 18 | { 19 | /// 20 | /// DDCVSettingsWindowAboutScreen.xaml 的交互逻辑 21 | /// 22 | public partial class DDCVSettingsWindowAboutScreen : DDCVSwapableScreen 23 | { 24 | public DDCVSettingsWindowAboutScreen() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) 30 | { 31 | Process.Start(e.Uri.AbsoluteUri); 32 | e.Handled = true; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVSettingsWindowChangeLogScreen.xaml: -------------------------------------------------------------------------------- 1 |  10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVSettingsWindowChangeLogScreen.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace DodocoTales.SR.Gui.Views.Screens 17 | { 18 | /// 19 | /// DDCVSettingsWindowChangeLogScreen.xaml 的交互逻辑 20 | /// 21 | public partial class DDCVSettingsWindowChangeLogScreen : DDCVSwapableScreen 22 | { 23 | public DDCVSettingsWindowChangeLogScreen() 24 | { 25 | InitializeComponent(); 26 | } 27 | public override void Refresh() 28 | { 29 | VM.Refresh(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVSettingsWindowUsersScreen.xaml.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Gui.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace DodocoTales.SR.Gui.Views.Screens 18 | { 19 | /// 20 | /// DDCVSettingsWindowUsersScreen.xaml 的交互逻辑 21 | /// 22 | public partial class DDCVSettingsWindowUsersScreen : DDCVSwapableScreen 23 | { 24 | public DDCVSettingsWindowUsersScreen() 25 | { 26 | InitializeComponent(); 27 | } 28 | public override void Refresh() 29 | { 30 | VM.Refresh(); 31 | } 32 | 33 | private void SwapButton_Click(object sender, RoutedEventArgs e) 34 | { 35 | VM.SwapUser((sender as Button).DataContext as DDCVUserlogItem); 36 | } 37 | 38 | private void RemoveButton_Click(object sender, RoutedEventArgs e) 39 | { 40 | VM.RemoveUser((sender as Button).DataContext as DDCVUserlogItem); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVSwapableScreen.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows.Controls; 7 | 8 | namespace DodocoTales.SR.Gui.Views.Screens 9 | { 10 | public class DDCVSwapableScreen : UserControl 11 | { 12 | public virtual void Refresh() { } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Screens/DDCVVersionViewScreen.xaml.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Gui.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | using System.Windows.Data; 10 | using System.Windows.Documents; 11 | using System.Windows.Input; 12 | using System.Windows.Media; 13 | using System.Windows.Media.Imaging; 14 | using System.Windows.Navigation; 15 | using System.Windows.Shapes; 16 | 17 | namespace DodocoTales.SR.Gui.Views.Screens 18 | { 19 | /// 20 | /// DDCVVersionViewScreen.xaml 的交互逻辑 21 | /// 22 | public partial class DDCVVersionViewScreen : DDCVSwapableScreen 23 | { 24 | public DDCVVersionViewScreen() 25 | { 26 | InitializeComponent(); 27 | } 28 | public override void Refresh() 29 | { 30 | VM.ReloadData(); 31 | } 32 | 33 | private void ListViewItem_MouseDown(object sender, MouseButtonEventArgs e) 34 | { 35 | var model = (sender as Grid).DataContext as DDCVBannerItemModel; 36 | DDCV.CreateBannerViewScreen(model.VersionID, model.BannerInternalID); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Windows/DDCVGameClientManagerWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Gui.Views.Dialogs; 2 | using DodocoTales.SR.Library; 3 | using DodocoTales.SR.Library.GameClient.Models; 4 | using DodocoTales.SR.Loader; 5 | using Panuon.UI.Silver; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Controls; 13 | using System.Windows.Data; 14 | using System.Windows.Documents; 15 | using System.Windows.Input; 16 | using System.Windows.Media; 17 | using System.Windows.Media.Imaging; 18 | using System.Windows.Shapes; 19 | 20 | namespace DodocoTales.SR.Gui.Views.Windows 21 | { 22 | /// 23 | /// DDCVGameClientManagerWindow.xaml 的交互逻辑 24 | /// 25 | public partial class DDCVGameClientManagerWindow : WindowX 26 | { 27 | public DDCVGameClientManagerWindow() 28 | { 29 | InitializeComponent(); 30 | VM.ReloadData(); 31 | } 32 | 33 | private void CloseButton_Click(object sender, RoutedEventArgs e) 34 | { 35 | DialogResult = false; 36 | Close(); 37 | } 38 | 39 | private void LoadFromLog_Click(object sender, RoutedEventArgs e) 40 | { 41 | DDCG.GameClientLoader.LoadGameClientFromGameLog(); 42 | VM.ReloadData(); 43 | } 44 | 45 | private void SetButton_Click(object sender, RoutedEventArgs e) 46 | { 47 | DDCLGameClientItem item = (sender as Button).DataContext as DDCLGameClientItem; 48 | DDCL.GameClientLib.SetSelectedClient(item); 49 | DialogResult = true; 50 | Close(); 51 | } 52 | 53 | private void CleanButton_Click(object sender, RoutedEventArgs e) 54 | { 55 | DDCLGameClientItem item = (sender as Button).DataContext as DDCLGameClientItem; 56 | DDCG.GameClientLoader.RemoveCacheFile(item); 57 | } 58 | 59 | private void EditButton_Click(object sender, RoutedEventArgs e) 60 | { 61 | DDCLGameClientItem item = (sender as Button).DataContext as DDCLGameClientItem; 62 | DDCVGameClientManagerWindowEditDialog dialog = new DDCVGameClientManagerWindowEditDialog 63 | { 64 | Owner = this 65 | }; 66 | dialog.LoadGameClientItem(item); 67 | dialog.ShowDialog(); 68 | 69 | VM.ReloadData(); 70 | } 71 | 72 | private void AddNewButton_Click(object sender, RoutedEventArgs e) 73 | { 74 | DDCLGameClientItem item = (sender as Button).DataContext as DDCLGameClientItem; 75 | 76 | DDCVGameClientManagerWindowEditDialog dialog = new DDCVGameClientManagerWindowEditDialog 77 | { 78 | Owner = this 79 | }; 80 | dialog.NewGameClientItem(); 81 | dialog.ShowDialog(); 82 | 83 | VM.ReloadData(); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Windows/DDCVSettingsWindow.xaml: -------------------------------------------------------------------------------- 1 |  15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 33 | 34 | 35 | 42 | 43 | 44 | 45 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Gui/Views/Windows/DDCVSettingsWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Gui.Models; 2 | using Panuon.UI.Silver; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | using System.Windows; 9 | using System.Windows.Controls; 10 | using System.Windows.Data; 11 | using System.Windows.Documents; 12 | using System.Windows.Input; 13 | using System.Windows.Media; 14 | using System.Windows.Media.Imaging; 15 | using System.Windows.Shapes; 16 | 17 | namespace DodocoTales.SR.Gui.Views.Windows 18 | { 19 | /// 20 | /// DDCVSettingsWindow.xaml 的交互逻辑 21 | /// 22 | public partial class DDCVSettingsWindow : WindowX 23 | { 24 | public DDCVSettingsWindow() 25 | { 26 | InitializeComponent(); 27 | VM.Initialize(Navigator); 28 | } 29 | 30 | private void MainPanel_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) 31 | { 32 | var item = MainPanel.SelectedItem as DDCVMainPanelItemModel; 33 | if (item != null) 34 | VM.SwapScreen(item.Tag); 35 | } 36 | private void TreeViewItem_MouseDown(object sender, MouseButtonEventArgs e) 37 | { 38 | var item = (sender as Label).DataContext as DDCVMainPanelItemModel; 39 | if (item == MainPanel.SelectedItem) 40 | VM.SwapScreen(item.Tag); 41 | } 42 | 43 | public DDCVSettingsWindow SwapToUsersScreen() 44 | { 45 | VM.SelectMenu("Users"); 46 | return this; 47 | } 48 | 49 | public DDCVSettingsWindow SwapToChangeLogScreen() 50 | { 51 | VM.SelectMenu("ChangeLog"); 52 | return this; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/BannerLibrary/Models/DDCLBannerInfo.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Library.Enums; 3 | using Newtonsoft.Json; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.ComponentModel; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace DodocoTales.SR.Library.BannerLibrary.Models 12 | { 13 | public class DDCLBannerInfo 14 | { 15 | public ulong ID { get; set; } 16 | public DDCCPoolType Type { get; set; } 17 | public string Name { get; set; } 18 | public string Hint { get; set; } 19 | public List Rank5Up { get; set; } 20 | public List Rank4Up { get; set; } 21 | public DateTime BeginTime { get; set; } 22 | public DateTime EndTime { get; set; } 23 | 24 | [DefaultValue(false)] 25 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] 26 | public bool BeginTimeSync { get; set; } 27 | 28 | [DefaultValue(false)] 29 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] 30 | public bool EndTimeSync { get; set; } 31 | 32 | [JsonIgnore] 33 | public ulong VersionID { get; set; } 34 | 35 | [JsonIgnore] 36 | public ulong InternalID 37 | { 38 | get { return VersionID * 1000 + ID; } 39 | } 40 | 41 | public DDCLBannerInfo Copy() 42 | { 43 | return new DDCLBannerInfo 44 | { 45 | ID = this.ID, 46 | Type = this.Type, 47 | Name = this.Name, 48 | Hint = this.Hint, 49 | Rank5Up = this.Rank5Up.FindAll(x => true), 50 | Rank4Up = this.Rank4Up.FindAll(x => true), 51 | BeginTime = this.BeginTime, 52 | EndTime = this.EndTime, 53 | BeginTimeSync = this.BeginTimeSync, 54 | EndTimeSync = this.EndTimeSync, 55 | VersionID = this.VersionID, 56 | }; 57 | } 58 | 59 | 60 | [JsonIgnore] 61 | public DDCLActivateStatus ActivateStatus 62 | { 63 | get 64 | { 65 | var now = DDCL.GetNowDateTimeOffset(); 66 | return BannerStatusAtTime(now); 67 | } 68 | } 69 | 70 | public DDCLActivateStatus BannerStatusAtTime(DateTimeOffset time) 71 | { 72 | var tz = DDCL.DefaultTimeZone;//Temp //DDCL.CurrentUser.GetActivatingTimeZone(); 73 | var begin = DDCL.GetBannerTimeOffset(BeginTime, BeginTimeSync, tz); 74 | var end = DDCL.GetBannerTimeOffset(EndTime, EndTimeSync, tz); 75 | var res = DDCL.CheckTimeIsBetween(begin, end, time); 76 | if (res == 0) return DDCLActivateStatus.Activating; 77 | else if (res < 0) return DDCLActivateStatus.Post; 78 | else return DDCLActivateStatus.Incoming; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/BannerLibrary/Models/DDCLBannerLibModel.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Library.BannerLibrary.Models 9 | { 10 | public class DDCLBannerLibModel 11 | { 12 | [JsonProperty(PropertyName = "Beginner")] 13 | public List BeginnerPools { get; set; } 14 | [JsonProperty(PropertyName = "Permanent")] 15 | public List PermanentPools { get; set; } 16 | 17 | [JsonProperty(PropertyName = "Event")] 18 | public List EventPools { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/BannerLibrary/Models/DDCLVersionInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Library.BannerLibrary.Models 8 | { 9 | public class DDCLVersionInfo 10 | { 11 | public ulong ID { get; set; } 12 | public string Version { get; set; } 13 | public string Name { get; set; } 14 | public DateTime BeginTime { get; set; } 15 | public DateTime EndTime { get; set; } 16 | public List Banners { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/CurrentUser/Models/DDCLBannerLogItem.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Library.UserDataLibrary.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Library.CurrentUser.Models 10 | { 11 | public class DDCLBannerLogItem 12 | { 13 | public ulong BannerInternalID { get; set; } 14 | 15 | public ulong VersionID { get; set; } 16 | 17 | public DDCCPoolType CategorizedGachaType { get; set; } 18 | 19 | public List GreaterRounds { get; set; } 20 | public List Logs { get; set; } 21 | 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/CurrentUser/Models/DDCLRoundLogItem.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Library.UserDataLibrary.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Library.CurrentUser.Models 10 | { 11 | public class DDCLRoundLogItem 12 | { 13 | public ulong VersionID { get; set; } 14 | public ulong BannerInternalID { get; set; } 15 | public DDCCPoolType CategorizedGachaType { get; set; } 16 | public List Logs { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/Enums/DDCLActivateStatus.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Library.Enums 8 | { 9 | public enum DDCLActivateStatus 10 | { 11 | Post, 12 | Activating, 13 | Incoming 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/Enums/DDCLGameClientType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Library.Enums 8 | { 9 | public enum DDCLGameClientType 10 | { 11 | Unknown, 12 | CN, 13 | Global 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/Enums/DDCLUnitMetadataSource.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Library.Enums 8 | { 9 | public enum DDCLUnitMetadataSource 10 | { 11 | None, 12 | Hakush, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/GameClient/DDCLGameClientLibrary.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library.GameClient.Models; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Library.GameClient 11 | { 12 | public class DDCLGameClientLibrary 13 | { 14 | private List clients; 15 | private DDCLGameClientItem SelectedClient; 16 | 17 | public readonly string libPath = @"library/GameClientLibrary.json"; 18 | 19 | public DDCLGameClientLibrary() 20 | { 21 | clients = new List(); 22 | } 23 | 24 | 25 | public DDCLGameClientItem GetSelectedClient() 26 | { 27 | if (SelectedClient == null) 28 | { 29 | if (clients.Count == 1) 30 | { 31 | SelectedClient = clients.First(); 32 | } 33 | if (clients.Count(x => x.IsDefault) == 1) 34 | { 35 | SelectedClient = clients.Find(x => x.IsDefault); 36 | } 37 | } 38 | return SelectedClient; 39 | } 40 | public void SetSelectedClient(DDCLGameClientItem item) 41 | { 42 | if (clients.Contains(item)) SelectedClient = item; else SelectedClient = null; 43 | clients.ForEach(x => x.IsDefault = (x == SelectedClient)); 44 | SaveLibraryAsync(); 45 | } 46 | 47 | public List GetClients() 48 | { 49 | return clients; 50 | } 51 | 52 | public void AddClients(List clients) 53 | { 54 | this.clients.AddRange(clients); 55 | SaveLibraryAsync(); 56 | //DDCS.Emit_GameClientLibReloadCompleted(); 57 | } 58 | 59 | public void RemoveClients(List clients) 60 | { 61 | this.clients.RemoveAll(x => clients.Contains(x)); 62 | SaveLibraryAsync(); 63 | //DDCS.Emit_GameClientLibReloadCompleted(); 64 | } 65 | 66 | 67 | public async Task LoadLibraryAsync() 68 | { 69 | clients.Clear(); 70 | try 71 | { 72 | var stream = File.Open(libPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 73 | StreamReader reader = new StreamReader(stream); 74 | var buffer = await reader.ReadToEndAsync(); 75 | reader.Close(); 76 | stream.Close(); 77 | clients = JsonConvert.DeserializeObject>(buffer); 78 | } 79 | catch (Exception) 80 | { 81 | clients = new List(); 82 | //DDCLog.Error(DCLN.Lib, "GameClientLib damaged or not exist. Reset to default."); 83 | SaveLibraryAsync(); 84 | } 85 | //DDCLog.Info(DCLN.Lib, "GameClientLib successfully loaded."); 86 | //DDCS.Emit_GameClientLibReloadCompleted(); 87 | return true; 88 | } 89 | 90 | public async Task SaveLibraryAsync() 91 | { 92 | try 93 | { 94 | using (var stream = File.Open(libPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)) 95 | { 96 | StreamWriter writer = new StreamWriter(stream); 97 | var serialized = JsonConvert.SerializeObject(clients, Formatting.Indented); 98 | await writer.WriteAsync(serialized); 99 | await writer.FlushAsync(); 100 | } 101 | //DDCLog.Info(DCLN.Lib, "GameClientLib successfully saved."); 102 | } 103 | catch (Exception e) 104 | { 105 | //DDCLog.Error(DCLN.Lib, "Failed to save GameClientLib. ", e); 106 | } 107 | 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/GameClient/Models/DDCLGameClientItem.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library.Enums; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Library.GameClient.Models 11 | { 12 | public class DDCLGameClientItem 13 | { 14 | public string Name { get; set; } 15 | public string Path { get; set; } 16 | public DDCLGameClientType ClientType { get; set; } 17 | 18 | [DefaultValue(false)] 19 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 20 | public bool IsDefault { get; set; } 21 | } 22 | } -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/MetadataLibrary/Models/DDCLMetadataVersion.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Library.MetadataLibrary.Models 10 | { 11 | public class DDCLMetadataVersion 12 | { 13 | public string ClientVersion { get; set; } 14 | public string BannerLibraryVersion { get; set; } 15 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 16 | public string ExportersLibraryVersion { get; set; } 17 | 18 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 19 | public DateTime UnitLibLastUpdateAt { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/Settings/DDCLSettingsLibrary.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common; 2 | using DodocoTales.SR.Library.Enums; 3 | using DodocoTales.SR.Library.Settings.Models; 4 | using Newtonsoft.Json; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace DodocoTales.SR.Library.Settings 13 | { 14 | public class DDCLSettingsLibrary 15 | { 16 | public DDCLSettingsInfo model = null; 17 | public readonly string libPath = @"Library/Settings.json"; 18 | 19 | public long LastUserUID { get { return model?.LastUserUID ?? -1; } set { model.LastUserUID = value; SaveSettings(); } } 20 | 21 | public DDCLUnitMetadataSource MetadataSource { get { return model?.MetadataSource ?? DDCLUnitMetadataSource.None; } set { model.MetadataSource = value; SaveSettings(); } } 22 | 23 | public DDCLSettingsLibrary() 24 | { 25 | DDCS.CurUserSwapCompleted += OnUIDSwapCompleted; 26 | } 27 | 28 | public bool IsLoaded() 29 | { 30 | return model != null; 31 | } 32 | 33 | public async Task LoadSettingsAsync() 34 | { 35 | try 36 | { 37 | var stream = File.Open(libPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 38 | StreamReader reader = new StreamReader(stream); 39 | var buffer = await reader.ReadToEndAsync(); 40 | model = JsonConvert.DeserializeObject(buffer); 41 | } 42 | catch (Exception) 43 | { 44 | model = new DDCLSettingsInfo(); 45 | return false; 46 | } 47 | return true; 48 | } 49 | public bool SaveSettings() 50 | { 51 | if (model == null) return false; 52 | try 53 | { 54 | var stream = File.Open(libPath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite); 55 | StreamWriter writer = new StreamWriter(stream); 56 | var serialized = JsonConvert.SerializeObject(model, Formatting.Indented); 57 | writer.Write(serialized); 58 | writer.Flush(); 59 | stream.Close(); 60 | } 61 | catch (Exception) 62 | { 63 | /// TODO: 报告保存错误? 64 | return false; 65 | } 66 | return true; 67 | } 68 | 69 | 70 | 71 | private void OnUIDSwapCompleted(long uid) 72 | { 73 | LastUserUID = uid; 74 | SaveSettings(); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/Settings/Models/DDCLSettingsInfo.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library.Enums; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Library.Settings.Models 11 | { 12 | public class DDCLSettingsInfo 13 | { 14 | public long LastUserUID { get; set; } 15 | 16 | [DefaultValue(DDCLUnitMetadataSource.Hakush)] 17 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)] 18 | public DDCLUnitMetadataSource MetadataSource { get; set; } = DDCLUnitMetadataSource.Hakush; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/TrustedExporters/DDCLTrustedExportersLibrary.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library.TrustedExporters.Models; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Library.TrustedExporters 11 | { 12 | public class DDCLTrustedExportersLibrary 13 | { 14 | public readonly string libPath = @"Library/Exporters.json"; 15 | DDCLTrustedExporters model; 16 | List exporters = new List(); 17 | 18 | public async Task LoadLibraryAsync() 19 | { 20 | exporters.Clear(); 21 | try 22 | { 23 | var stream = File.Open(libPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 24 | StreamReader reader = new StreamReader(stream); 25 | var buffer = await reader.ReadToEndAsync(); 26 | stream.Close(); 27 | model = JsonConvert.DeserializeObject(buffer); 28 | } 29 | catch (Exception) 30 | { 31 | model = null; 32 | return false; 33 | } 34 | model.Trusted.ForEach(x => { x.ExporterType = DDCLExporterType.Trusted; }); 35 | model.BlackList.ForEach(x => { x.ExporterType = DDCLExporterType.Blacklist; }); 36 | model.Untested.ForEach(x => { x.ExporterType = DDCLExporterType.Untested; }); 37 | exporters.AddRange(model.Trusted); 38 | exporters.AddRange(model.BlackList); 39 | exporters.AddRange(model.Untested); 40 | 41 | return true; 42 | } 43 | 44 | public DDCLTrustedExporter GetExporter(string export_app) 45 | { 46 | var res = exporters.FirstOrDefault(x=>x.Application == export_app); 47 | if (res == null) 48 | { 49 | res = new DDCLTrustedExporter 50 | { 51 | Application = export_app, 52 | ApplicationNameChinese = export_app, 53 | ApplicationNameEnglish = export_app, 54 | Author = "Unknown", 55 | ExporterType = DDCLExporterType.Unknown, 56 | OpenSource = true 57 | }; 58 | } 59 | return res; 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/TrustedExporters/Models/DDCLTrustedExporters.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Library.TrustedExporters.Models 9 | { 10 | 11 | public enum DDCLExporterType 12 | { 13 | Unknown, 14 | Trusted, 15 | Untested, 16 | Blacklist 17 | } 18 | 19 | public class DDCLTrustedExporter 20 | { 21 | [JsonProperty(PropertyName = "export_app")] 22 | public string Application { get; set; } 23 | 24 | [JsonProperty(PropertyName = "zh-cn")] 25 | public string ApplicationNameChinese { get; set; } 26 | 27 | [JsonProperty(PropertyName = "en-us")] 28 | public string ApplicationNameEnglish { get; set; } 29 | 30 | [JsonProperty(PropertyName = "author")] 31 | public string Author { get; set; } 32 | 33 | [JsonProperty(PropertyName = "opensource")] 34 | public bool OpenSource { get; set; } 35 | 36 | [JsonProperty(PropertyName = "srgf-partnership", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 37 | public bool SRGFPartnership { get; set; } 38 | 39 | [JsonProperty(PropertyName = "new-uigf-partnership", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 40 | public bool NUIGFPartnership { get; set; } 41 | 42 | [JsonIgnore] 43 | public DDCLExporterType ExporterType { get; set; } 44 | 45 | } 46 | 47 | public class DDCLTrustedExporters 48 | { 49 | [JsonProperty(PropertyName = "trusted")] 50 | public List Trusted { get; set; } 51 | 52 | [JsonProperty(PropertyName = "untested")] 53 | public List Untested { get; set; } 54 | 55 | [JsonProperty(PropertyName = "blacklist")] 56 | public List BlackList { get; set; } 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/UnitLibrary/DDCLUnitLibrary.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library.Enums; 2 | using DodocoTales.SR.Library.Settings.Models; 3 | using DodocoTales.SR.Library.UnitLibrary.Models; 4 | using Newtonsoft.Json; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | 12 | namespace DodocoTales.SR.Library.UnitLibrary 13 | { 14 | public class DDCLUnitLibrary 15 | { 16 | public readonly string libPath = @"Library/UnitLibrary.json"; 17 | List model; 18 | 19 | Dictionary dict; 20 | 21 | public DDCLUnitLibrary() 22 | { 23 | model = null; 24 | dict = new Dictionary(); 25 | } 26 | 27 | public bool IsLoaded() 28 | { 29 | return model != null; 30 | } 31 | 32 | public bool Enabled() 33 | { 34 | return DDCL.SettingsLib.MetadataSource != DDCLUnitMetadataSource.None; 35 | } 36 | 37 | public async Task LoadLibraryAsync() 38 | { 39 | dict.Clear(); 40 | if (!Enabled()) 41 | { 42 | model = null; 43 | return true; 44 | } 45 | try 46 | { 47 | var stream = File.Open(libPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 48 | StreamReader reader = new StreamReader(stream); 49 | var buffer = await reader.ReadToEndAsync(); 50 | model = JsonConvert.DeserializeObject>(buffer); 51 | } 52 | catch (Exception) 53 | { 54 | model = null; 55 | return false; 56 | } 57 | foreach (var item in model) 58 | { 59 | dict.Add(item.ItemID, item); 60 | } 61 | return true; 62 | } 63 | 64 | public DDCLUnitItem GetUnitInfo(string item_id) 65 | { 66 | return dict.TryGetValue(item_id, out var unitInfo) ? unitInfo : null; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/UnitLibrary/Models/DDCLUnitItem.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Library.UnitLibrary.Models 9 | { 10 | public class DDCLUnitItem 11 | { 12 | public string ItemID { get; set; } 13 | public string Name { get; set; } 14 | public ulong Rank { get; set; } 15 | public DDCCUnitType UnitType { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/UserDataLibrary/Models/DDCLGachaLogItem.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Library.UserDataLibrary.Models 10 | { 11 | public class DDCLGachaLogItem 12 | { 13 | public ulong VersionID { get; set; } 14 | [JsonProperty(PropertyName = "BannerID")] 15 | public ulong BannerInternalID { get; set; } 16 | public ulong RoundID { get; set; } 17 | 18 | public ulong ID { get; set; } 19 | public string Name { get; set; } 20 | public DateTime Time { get; set; } 21 | 22 | public DDCCPoolType PoolType { get; set; } 23 | 24 | public ulong Rank { get; set; } 25 | public DDCCUnitType UnitType { get; set; } 26 | 27 | public DDCLGachaLogItemRawData Raw { get; set; } 28 | 29 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 30 | public bool Imported; 31 | 32 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 33 | public string ImportApplication; 34 | 35 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 36 | public bool Untrusted; 37 | 38 | } 39 | public class DDCLGachaLogItemRawData 40 | { 41 | public string gacha_id { get; set; } 42 | public ulong gacha_type { get; set; } 43 | public string item_id { get; set; } 44 | public string count { get; set; } 45 | } 46 | } -------------------------------------------------------------------------------- /DodocoTales.StarRail/Library/UserDataLibrary/Models/DDCLUserGachaLog.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library.Enums; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Library.UserDataLibrary.Models 10 | { 11 | public class DDCLUserGachaLog 12 | { 13 | public long UID { get; set; } 14 | public int TimeZone { get; set; } 15 | 16 | public DDCLGameClientType ClientType { get; set; } 17 | 18 | public List LogsV1 { get; set; } 19 | 20 | [JsonIgnore] 21 | public List Logs 22 | { 23 | get { return LogsV1; } 24 | set { LogsV1 = value; } 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/DDCG.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Loader 8 | { 9 | public static partial class DDCG 10 | { 11 | public static DDCGGameClientLoader GameClientLoader = new DDCGGameClientLoader(); 12 | public static DDCGProxyLoader ProxyLoader = new DDCGProxyLoader(); 13 | 14 | public static DDCGWebGachaLogLoader WebLogLoader = new DDCGWebGachaLogLoader(); 15 | 16 | public static DDCGUpdateLoader UpdateLoader = new DDCGUpdateLoader(); 17 | 18 | public static DDCGUniversalFormatImporter UFImporter = new DDCGUniversalFormatImporter(); 19 | public static DDCGUniversalFormatExporter UFExporter = new DDCGUniversalFormatExporter(); 20 | 21 | public static DDCGItemMetadataLoader UnitLibLoader = new DDCGItemMetadataLoader(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/DDCGItemMetadataLoader.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Library; 2 | using DodocoTales.SR.Library.Enums; 3 | using DodocoTales.SR.Library.UnitLibrary.Models; 4 | using Newtonsoft.Json; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.IO; 8 | using System.Linq; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | namespace DodocoTales.SR.Loader 12 | { 13 | public class DDCGItemMetadataLoader 14 | { 15 | readonly ItemMetadataLoaders.HakushLoader.DDCGItemMetadataLoader HakushLoader = new ItemMetadataLoaders.HakushLoader.DDCGItemMetadataLoader(); 16 | 17 | public readonly string LocalLibPath = "Library/"; 18 | public readonly string UnitLibraryFileName = "UnitLibrary.json"; 19 | 20 | public async Task UpdateUnitLibrary() 21 | { 22 | List items = null; 23 | switch (DDCL.SettingsLib.MetadataSource) 24 | { 25 | case DDCLUnitMetadataSource.Hakush: 26 | items = await HakushLoader.UpdateUnitLibrary(); 27 | break; 28 | default: 29 | return true; 30 | } 31 | if (items == null) 32 | { 33 | return false; 34 | } 35 | 36 | var lib = JsonConvert.SerializeObject(items, Formatting.Indented); 37 | 38 | if (lib == null) 39 | { 40 | return false; 41 | } 42 | try 43 | { 44 | var libPath = LocalLibPath + UnitLibraryFileName; 45 | var stream = File.Open(libPath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite); 46 | StreamWriter writer = new StreamWriter(stream); 47 | await writer.WriteAsync(lib); 48 | await writer.FlushAsync(); 49 | stream.Close(); 50 | 51 | DDCL.MetaVersionLib.UnitLibLastUpdateAt = DateTime.Now; 52 | } 53 | catch (Exception) 54 | { 55 | DDCL.MetaVersionLib.UnitLibLastUpdateAt = DateTime.MinValue; 56 | return false; 57 | } 58 | return true; 59 | 60 | } 61 | 62 | 63 | public bool IsUpdateNeeded() 64 | { 65 | return DDCL.UnitLib.Enabled() && (DDCL.MetaVersionLib.UnitLibLastUpdateAt < DateTime.Now.AddDays(-14)); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/DDCGProxyLoader.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common; 2 | using DodocoTales.SR.Library.Enums; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Text.RegularExpressions; 9 | using System.Threading.Tasks; 10 | using Titanium.Web.Proxy; 11 | using Titanium.Web.Proxy.EventArguments; 12 | using Titanium.Web.Proxy.Models; 13 | namespace DodocoTales.SR.Loader 14 | { 15 | public class DDCGProxyLoader 16 | { 17 | public ProxyServer PServer { get; set; } 18 | private ExplicitProxyEndPoint EndPoint; 19 | 20 | public string Authkey { get; set; } 21 | public DDCLGameClientType CapturedClientType { get; set; } 22 | 23 | public DDCGProxyLoader() 24 | { 25 | PServer = null; 26 | Authkey = null; 27 | CapturedClientType = DDCLGameClientType.Unknown; 28 | } 29 | 30 | public bool InitializeProxy() 31 | { 32 | if (PServer == null) 33 | { 34 | PServer = new ProxyServer(); 35 | PServer.CertificateManager.EnsureRootCertificate(); 36 | PServer.BeforeRequest += BeforeRequest; 37 | EndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 12199); 38 | //DDCLog.Info(DCLN.Loader, "Proxy server initialized"); 39 | return true; 40 | } 41 | return false; 42 | } 43 | 44 | public void StartProxy() 45 | { 46 | Authkey = null; 47 | CapturedClientType = DDCLGameClientType.Unknown; 48 | 49 | PServer.AddEndPoint(EndPoint); 50 | PServer.Start(); 51 | PServer.SetAsSystemHttpProxy(EndPoint); 52 | PServer.SetAsSystemHttpsProxy(EndPoint); 53 | //DDCLog.Info(DCLN.Loader, "Proxy Mode On"); 54 | } 55 | 56 | public void EndProxy() 57 | { 58 | if (PServer == null) return; 59 | if (PServer.ProxyRunning) 60 | { 61 | PServer.Stop(); 62 | } 63 | PServer.DisableAllSystemProxies(); 64 | //DDCLog.Info(DCLN.Loader, "Proxy Mode Off"); 65 | } 66 | 67 | private Task BeforeRequest(object sender, SessionEventArgs e) 68 | { 69 | var request = e.HttpClient.Request; 70 | string authkey = null; 71 | if (((request.Host == "api-takumi.mihoyo.com")||(request.Host == "api-os-takumi.mihoyo.com")) && request.RequestUri.AbsolutePath == "/common/gacha_record/api/getGachaLog") 72 | { 73 | string pattern = @".+\?(\S+&game_biz=hkrpg_(cn|global))"; 74 | var result = Regex.Matches(request.Url, pattern); 75 | Regex regex = new Regex(@"lang=.+?&"); 76 | authkey = regex.Replace(result[result.Count - 1].Groups[1].Value, "lang=zh-cn&"); 77 | } 78 | if (authkey != null) 79 | { 80 | Authkey = authkey; 81 | if (Authkey.Contains("game_biz=hkrpg_cn")) 82 | CapturedClientType = DDCLGameClientType.CN; 83 | else if (Authkey.Contains("game_biz=hkrpg_global")) 84 | CapturedClientType = DDCLGameClientType.CN; 85 | else 86 | CapturedClientType = DDCLGameClientType.Unknown; 87 | 88 | //DDCLog.Info(DCLN.Loader, "Authkey captured by proxy server."); 89 | DDCS.Emit_ProxyCaptured(); 90 | } 91 | return Task.CompletedTask; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/DDCGUniversalFormatImporter.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Library; 3 | using DodocoTales.SR.Library.Enums; 4 | using DodocoTales.SR.Library.UserDataLibrary.Models; 5 | using DodocoTales.SR.Loader.Models; 6 | using Newtonsoft.Json; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.IO; 10 | using System.Linq; 11 | using System.Text; 12 | using System.Threading.Tasks; 13 | 14 | namespace DodocoTales.SR.Loader 15 | { 16 | public class DDCGUniversalFormatImporter 17 | { 18 | public async Task Load(string filepath) 19 | { 20 | try 21 | { 22 | var stream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 23 | StreamReader reader = new StreamReader(stream); 24 | var buffer = await reader.ReadToEndAsync(); 25 | return EnsureToNewFormat(JsonConvert.DeserializeObject(buffer)); 26 | } 27 | catch (Exception) 28 | { 29 | return null; 30 | } 31 | } 32 | 33 | public DDCGUniversalFormatLog EnsureToNewFormat(DDCGUniversalFormatLog log) 34 | { 35 | if (log.Info == null) return null; 36 | 37 | if (log.StarRailSections == null) 38 | { 39 | if (log.List == null) return null; 40 | 41 | log.StarRailSections = new List 42 | { 43 | new DDCGUniversalFormatLogSRSection 44 | { 45 | UID = log.Info.UID, 46 | Language = log.Info.Language, 47 | TimeZone = log.Info.TimeZone, 48 | GameBiz = log.Info.GameBiz, 49 | List = log.List 50 | } 51 | }; 52 | } 53 | return log; 54 | } 55 | 56 | 57 | public bool IsAcceptableFormat(DDCGUniversalFormatLog log) 58 | => ((log?.Info?.LegacyStandardVersion != null && log?.Info.UID != null) || (log?.Info?.NewStandardVersion != null) || (log?.Info?.AnonymousExport == "true")) && log?.StarRailSections != null; 59 | 60 | public bool IsAcceptableSection(DDCGUniversalFormatLogSRSection section) 61 | => (section.UID != null) && (section?.List != null); 62 | 63 | public bool IsAcceptableLanguage(DDCGUniversalFormatLogSRSection section) 64 | => section?.Language == "zh-cn"; 65 | 66 | public bool IsAnonymousFormat(DDCGUniversalFormatLog log) 67 | => log?.Info?.AnonymousExport == "true"; 68 | 69 | 70 | public DDCLGameClientType ConvertGameBizStringToGameClientType(string game_biz) 71 | { 72 | switch (game_biz) 73 | { 74 | case "hkrpg_cn": 75 | return DDCLGameClientType.CN; 76 | case "hkrpg_global": 77 | return DDCLGameClientType.Global; 78 | default: 79 | return DDCLGameClientType.Unknown; 80 | } 81 | } 82 | public DDCLGachaLogItem ConvertToDDCLLogItem(DDCGUniversalFormatLogItem UFItem) 83 | { 84 | var item = new DDCLGachaLogItem() 85 | { 86 | Raw = new DDCLGachaLogItemRawData 87 | { 88 | count = UFItem.count??"1", 89 | gacha_id = UFItem.gacha_id, 90 | item_id = UFItem.item_id, 91 | }, 92 | }; 93 | var unitinfo = DDCL.UnitLib.GetUnitInfo(UFItem.item_id); 94 | if (unitinfo == null) 95 | { 96 | return null; 97 | } 98 | item.Name = unitinfo.Name; 99 | item.Rank = unitinfo.Rank; 100 | item.UnitType = unitinfo.UnitType; 101 | 102 | try 103 | { 104 | if (UFItem.id == null || UFItem.time == null) return null; 105 | if (UFItem.gacha_type == null) return null; 106 | 107 | item.ID = Convert.ToUInt64(UFItem.id); 108 | item.Time = Convert.ToDateTime(UFItem.time); 109 | item.Raw.gacha_type = Convert.ToUInt64(UFItem.gacha_type); 110 | item.PoolType = JsonConvert.DeserializeObject(UFItem.gacha_type); 111 | } 112 | catch 113 | { 114 | return null; 115 | } 116 | return item; 117 | } 118 | 119 | public List ConvertList(List UFList) 120 | { 121 | var res = new SortedList(); 122 | foreach(var UFItem in UFList) 123 | { 124 | var item = ConvertToDDCLLogItem(UFItem); 125 | if (item != null) res.Add(item.ID, item); 126 | } 127 | return res.Values.ToList(); 128 | } 129 | 130 | public int Import(long uid, List loglist, DDCLGameClientType clientType, int timezone, string export_app) 131 | { 132 | var userlog = DDCL.UserDataLib.GetUserLogByUid(uid); 133 | var merger = new DDCGGachaLogMerger(userlog); 134 | if (userlog.ClientType == DDCLGameClientType.Unknown) 135 | { 136 | userlog.ClientType = clientType; 137 | merger.SetTimeZone(timezone); 138 | } 139 | else if (userlog.TimeZone != timezone) 140 | { 141 | foreach (var item in loglist) 142 | { 143 | item.Time = item.Time.AddHours(userlog.TimeZone - timezone); 144 | } 145 | } 146 | loglist.ForEach(log => { log.Imported = true; log.ImportApplication = export_app; }); 147 | return merger.Merge(loglist, false); 148 | } 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/ItemMetadataLoaders/HakushLoader/DDCGItemMetadataLoader.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Common.Enums; 2 | using DodocoTales.SR.Library.UnitLibrary.Models; 3 | using DodocoTales.SR.Loader.ItemMetadataLoaders.HakushLoader.Enums; 4 | using DodocoTales.SR.Loader.ItemMetadataLoaders.HakushLoader.Models; 5 | using Newtonsoft.Json; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.IO; 9 | using System.Linq; 10 | using System.Net; 11 | using System.Net.Http; 12 | using System.Net.Http.Headers; 13 | using System.Reflection; 14 | using System.Text; 15 | using System.Threading.Tasks; 16 | 17 | namespace DodocoTales.SR.Loader.ItemMetadataLoaders.HakushLoader 18 | { 19 | internal class DDCGItemMetadataLoader 20 | { 21 | HttpClient client; 22 | 23 | public readonly List HakushAPILists = new List 24 | { 25 | "https://api.hakush.in/hsr/data/character.json", 26 | "https://api.hakush.in/hsr/data/lightcone.json", 27 | }; 28 | 29 | public DDCGItemMetadataLoader() 30 | { 31 | var handler = new HttpClientHandler() 32 | { 33 | AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip 34 | }; 35 | client = new HttpClient(handler); 36 | CacheControlHeaderValue cacheControl = new CacheControlHeaderValue 37 | { 38 | NoCache = true, 39 | NoStore = true 40 | }; 41 | client.DefaultRequestHeaders.CacheControl = cacheControl; 42 | } 43 | 44 | public async Task GetMetadataFile(string url) 45 | { 46 | try 47 | { 48 | return await client.GetStringAsync(url); 49 | } 50 | catch (Exception e) 51 | { 52 | return null; 53 | } 54 | } 55 | 56 | public async Task> UpdateUnitLibrary() 57 | { 58 | List items = new List(); 59 | foreach (var url in HakushAPILists) 60 | { 61 | var content = await GetMetadataFile(url); 62 | 63 | if (content == null) 64 | { 65 | return null; 66 | } 67 | 68 | var res = JsonConvert.DeserializeObject>(content); 69 | if (res == null) 70 | { 71 | continue; 72 | } 73 | 74 | foreach (var kvp in res) 75 | { 76 | var item = new DDCLUnitItem 77 | { 78 | ItemID = kvp.Key, 79 | Name = kvp.Value.cn, 80 | 81 | }; 82 | switch (kvp.Value.rank) 83 | { 84 | case DDCGHakushMetadataItemTypeRarity.CombatPowerLightconeRarity3: 85 | case DDCGHakushMetadataItemTypeRarity.CombatPowerLightconeRarity4: 86 | case DDCGHakushMetadataItemTypeRarity.CombatPowerLightconeRarity5: 87 | item.UnitType = DDCCUnitType.LightCone; break; 88 | case DDCGHakushMetadataItemTypeRarity.CombatPowerAvatarRarityType4: 89 | case DDCGHakushMetadataItemTypeRarity.CombatPowerAvatarRarityType5: 90 | item.UnitType = DDCCUnitType.Character; break; 91 | default: 92 | item = null; break; 93 | } 94 | if (item == null) { continue; } 95 | switch (kvp.Value.rank) 96 | { 97 | case DDCGHakushMetadataItemTypeRarity.CombatPowerLightconeRarity3: 98 | item.Rank = 3; break; 99 | case DDCGHakushMetadataItemTypeRarity.CombatPowerLightconeRarity4: 100 | case DDCGHakushMetadataItemTypeRarity.CombatPowerAvatarRarityType4: 101 | item.Rank = 4; break; 102 | case DDCGHakushMetadataItemTypeRarity.CombatPowerLightconeRarity5: 103 | case DDCGHakushMetadataItemTypeRarity.CombatPowerAvatarRarityType5: 104 | item.Rank = 5; break; 105 | default: 106 | item = null; break; 107 | } 108 | if (item != null) 109 | { 110 | items.Add(item); 111 | } 112 | } 113 | } 114 | return items; 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/ItemMetadataLoaders/HakushLoader/Enums/DDCGHakushMetadataItemTypeRarity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Loader.ItemMetadataLoaders.HakushLoader.Enums 8 | { 9 | internal enum DDCGHakushMetadataItemTypeRarity 10 | { 11 | Unknown, 12 | 13 | CombatPowerAvatarRarityType4, 14 | CombatPowerAvatarRarityType5, 15 | 16 | CombatPowerLightconeRarity3, 17 | CombatPowerLightconeRarity4, 18 | CombatPowerLightconeRarity5, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/ItemMetadataLoaders/HakushLoader/Models/DDCGHakushMetadataItem.cs: -------------------------------------------------------------------------------- 1 | using DodocoTales.SR.Loader.ItemMetadataLoaders.HakushLoader.Enums; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Loader.ItemMetadataLoaders.HakushLoader.Models 9 | { 10 | internal class DDCGHakushMetadataItem 11 | { 12 | public DDCGHakushMetadataItemTypeRarity rank { get; set; } 13 | public string cn { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/Models/DDCGDownloadTask.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Loader.Models 8 | { 9 | public enum DDCGDownloadTaskType 10 | { 11 | ClientUpdate, 12 | DependencyUpdate 13 | } 14 | 15 | public class DDCGDownloadTask 16 | { 17 | public DDCGDownloadTaskType TaskType { get; set; } 18 | public string RemoteFileName { get; set; } 19 | public string LocalFileName { get; set; } 20 | public long? FileSize { get; set; } 21 | public long? DownloadedSize { get; set; } 22 | public double EstSpeed { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/Models/DDCGGachaLogResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Loader.Models 8 | { 9 | public class DDCGGachaLogResponse 10 | { 11 | public int retcode { get; set; } 12 | public string message { get; set; } 13 | public DDCGGachaLogResponseData data { get; set; } 14 | } 15 | public class DDCGGachaLogResponseData 16 | { 17 | public int page { get; set; } 18 | public int size { get; set; } 19 | public string region { get; set; } 20 | public int region_time_zone { get; set; } 21 | public List list { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/Models/DDCGGachaLogResponseItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace DodocoTales.SR.Loader.Models 8 | { 9 | public class DDCGGachaLogResponseItem 10 | { 11 | public long uid { get; set; } 12 | public string gacha_id { get; set; } 13 | public ulong gacha_type { get; set; } 14 | public string item_id { get; set; } 15 | public string count { get; set; } 16 | public DateTime time { get; set; } 17 | public string name { get; set; } 18 | public string lang { get; set; } 19 | public string item_type { get; set; } 20 | public ulong rank_type { get; set; } 21 | public ulong id { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/Models/DDCGUniversalFormatLog.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Loader.Models 9 | { 10 | public class DDCGUniversalFormatLog 11 | { 12 | [JsonProperty(PropertyName = "info")] 13 | public DDCGUniversalFormatLogInfo Info { get; set; } 14 | 15 | [JsonProperty(PropertyName = "list", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 16 | public List List { get; set; } 17 | 18 | [JsonProperty(PropertyName = "hkrpg", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 19 | public List StarRailSections { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/Models/DDCGUniversalFormatLogInfo.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.ComponentModel; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace DodocoTales.SR.Loader.Models 11 | { 12 | 13 | public class DDCGUniversalFormatLogInfo 14 | { 15 | [JsonProperty(PropertyName = "uid",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 16 | public string UID { get; set; } 17 | 18 | [JsonProperty(PropertyName = "lang", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 19 | public string Language { get; set; } 20 | 21 | [JsonProperty(PropertyName = "export_time", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 22 | public string ExportTime { get; set; } 23 | 24 | [JsonIgnore] 25 | public string ExportTimestamp { get; set; } 26 | 27 | [JsonProperty(PropertyName = "export_timestamp", NullValueHandling = NullValueHandling.Ignore)] 28 | public JToken SerializedTimestamp 29 | { 30 | get => int.TryParse(ExportTimestamp, out var ts) ? new JValue(ts) : null; 31 | set => ExportTimestamp = value?.ToString(); 32 | } 33 | 34 | [JsonProperty(PropertyName = "export_app", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 35 | public string Application { get; set; } 36 | 37 | [JsonProperty(PropertyName = "export_app_version", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 38 | public string ApplicationVersion { get; set; } 39 | 40 | [JsonIgnore] 41 | public string TimeZone { get; set; } 42 | 43 | [JsonProperty(PropertyName = "region_time_zone", NullValueHandling = NullValueHandling.Ignore)] 44 | public JToken SerializedTimeZone 45 | { 46 | get => int.TryParse(TimeZone, out var tz) ? new JValue(tz) : null; 47 | set => TimeZone = value?.ToString(); 48 | } 49 | 50 | [JsonProperty(PropertyName = "srgf_version", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 51 | public string LegacyStandardVersion { get; set; } 52 | 53 | [JsonProperty(PropertyName = "version", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 54 | public string NewStandardVersion { get; set; } 55 | 56 | [JsonProperty(PropertyName = "game", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 57 | public string Game { get; set; } 58 | 59 | [JsonProperty(PropertyName = "game_biz", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 60 | public string GameBiz { get; set; } 61 | 62 | [JsonProperty(PropertyName = "anonymous_export",DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 63 | public string AnonymousExport { get; set; } 64 | 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/Models/DDCGUniversalFormatLogItem.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace DodocoTales.SR.Loader.Models 9 | { 10 | public class DDCGUniversalFormatLogItem 11 | { 12 | public string gacha_id { get; set; } 13 | public string gacha_type { get; set; } 14 | public string item_id { get; set; } 15 | public string count { get; set; } 16 | public string time { get; set; } 17 | public string name { get; set; } 18 | public string item_type { get; set; } 19 | public string rank_type { get; set; } 20 | public string id { get; set; } 21 | [JsonProperty(DefaultValueHandling=DefaultValueHandling.IgnoreAndPopulate)] 22 | public string __hash { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Loader/Models/DDCGUniversalFormatLogSRSection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace DodocoTales.SR.Loader.Models 10 | { 11 | public class DDCGUniversalFormatLogSRSection 12 | { 13 | [JsonProperty(PropertyName = "uid", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 14 | public string UID { get; set; } 15 | 16 | [JsonProperty(PropertyName = "lang", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 17 | public string Language { get; set; } = "zh-cn"; 18 | 19 | [JsonIgnore] 20 | public string TimeZone { get; set; } 21 | 22 | [JsonProperty(PropertyName = "timezone")] 23 | public JToken SerializedTimeZone 24 | { 25 | get => int.TryParse(TimeZone, out var tz) ? new JValue(tz) : null; 26 | set => TimeZone = value?.ToString(); 27 | } 28 | 29 | [JsonProperty(PropertyName = "list")] 30 | public List List { get; set; } 31 | 32 | 33 | 34 | // Non-standard Fields 35 | 36 | [JsonProperty(PropertyName = "game_biz", DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)] 37 | public string GameBiz { get; set; } 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // 有关程序集的一般信息由以下 8 | // 控制。更改这些特性值可修改 9 | // 与程序集关联的信息。 10 | [assembly: AssemblyTitle("DodocoTales.StarRail")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("DodocoTales.StarRail")] 15 | [assembly: AssemblyCopyright("Copyright © 2024")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // 将 ComVisible 设置为 false 会使此程序集中的类型 20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | //若要开始生成可本地化的应用程序,请设置 25 | //.csproj 文件中的 CultureYouAreCodingWith 26 | //例如,如果您在源文件中使用的是美国英语, 27 | //使用的是美国英语,请将 设置为 en-US。 然后取消 28 | //对以下 NeutralResourceLanguage 特性的注释。 更新 29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置 36 | //(未在页面中找到资源时使用, 37 | //或应用程序资源字典中找到时使用) 38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 39 | //(未在页面中找到资源时使用, 40 | //、应用程序或任何主题专用资源字典中找到时使用) 41 | )] 42 | 43 | 44 | // 程序集的版本信息由下列四个值组成: 45 | // 46 | // 主版本 47 | // 次版本 48 | // 生成号 49 | // 修订号 50 | // 51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 52 | //通过使用 "*",如下所示: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.5.0.0")] 55 | [assembly: AssemblyFileVersion("1.5.0.0")] 56 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace DodocoTales.SR.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("DodocoTales.SR.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性,对 51 | /// 使用此强类型资源类的所有资源查找执行重写。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace DodocoTales.SR.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /DodocoTales.StarRail/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TremblingMoeNew/StarRailWarpObserve/d930b7603720da2252cf3b8d2ef7b4da899ccc56/DodocoTales.StarRail/icon.ico -------------------------------------------------------------------------------- /DodocoTales.StarRail/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 TremblingMoeNew 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 星穹铁道跃迁观测工具 2 | 3 | 星穹铁道跃迁观测工具(Star Rail Warp Observe), 简称Starwo,是一款针对游戏《崩坏:星穹铁道》开发的抽卡历史记录导出与管理工具。 4 | 5 | *本工具为基于为游戏《原神》所设计、但开发暂停的祈愿记录导出工具[“嘟嘟可故事集”重制版本](https://github.com/TremblingMoeNew/DodocoTales)所改造而来的姊妹版本。Codename: DodocoTales.StarRail.* 6 | 7 | 本工具的主要特色为,采用游戏版本-卡池-轮次的三级结构对玩家的跃迁历史记录进行整理与展示,帮助玩家更好的梳理抽取概率提升的五星单位的过程中的抽取情况。同时,仪表盘中也对您的四星与五星单位抽取概率相对于期望值的高低进行了展示。 8 | 9 | 本工具仅支持简体中文语言的界面及跃迁历史记录项。 10 | 11 | --- 12 | 13 | 本工具基于.NET Framework 4.7.2构建,依赖以下项目: 14 | 15 | - [JamesNK/Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json) 16 | - [Mochengvia/PanuonUI.Silver](https://github.com/Mochengvia/PanuonUI.Silver) 17 | - [beto-rodriguez/LiveCharts2](https://github.com/beto-rodriguez/LiveCharts2) 18 | - [CommunityToolkit/dotnet](https://github.com/CommunityToolkit/dotnet) 19 | - [CommunityToolkit/WindowsCommunityToolkit](https://github.com/CommunityToolkit/WindowsCommunityToolkit) 20 | - [justcoding121/titanium-web-proxy](https://github.com/justcoding121/Titanium-Web-Proxy) 21 | 22 | 本工具为[UIGF组织](https://uigf.org/zh)的成员。 -------------------------------------------------------------------------------- /StarRailWarpObserve.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.2.32616.157 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DodocoTales.StarRail", "DodocoTales.StarRail\DodocoTales.StarRail.csproj", "{4C70370C-2661-4088-9821-5FA391564627}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Updater", "Updater\Updater.csproj", "{2B10FF4B-41B8-41C4-A5D1-FDEA5F52A16D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4C70370C-2661-4088-9821-5FA391564627}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {4C70370C-2661-4088-9821-5FA391564627}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {4C70370C-2661-4088-9821-5FA391564627}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {4C70370C-2661-4088-9821-5FA391564627}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {2B10FF4B-41B8-41C4-A5D1-FDEA5F52A16D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {2B10FF4B-41B8-41C4-A5D1-FDEA5F52A16D}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {2B10FF4B-41B8-41C4-A5D1-FDEA5F52A16D}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {2B10FF4B-41B8-41C4-A5D1-FDEA5F52A16D}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {B9CFFDA0-B2B6-40E0-AD0D-280381CD89AE} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /Updater/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Updater/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace Updater 12 | { 13 | internal class Program 14 | { 15 | static void Main(string[] args) 16 | { 17 | DirectoryInfo dir = new DirectoryInfo("update/Latest"); 18 | 19 | if (!dir.Exists) 20 | { 21 | MessageBox.Show("错误:未找到更新文件。请不要手动运行本更新程序", "更新", MessageBoxButtons.OK); 22 | return; 23 | } 24 | Thread.Sleep(5000); 25 | var prols = Process.GetProcessesByName("SRWarpObserve"); 26 | if (prols.Any()) 27 | { 28 | foreach (var pro in prols) 29 | { 30 | pro.Kill(); 31 | Thread.Sleep(1000); 32 | } 33 | foreach (var pro in prols) 34 | { 35 | if (!pro.HasExited) pro.WaitForExit(); 36 | 37 | } 38 | } 39 | 40 | MoveFromDirectory(dir, new DirectoryInfo(Directory.GetCurrentDirectory())); 41 | 42 | try 43 | { 44 | if (File.Exists("update/Latest.zip")) 45 | File.Delete("update/Latest.zip"); 46 | Directory.Delete("update"); 47 | if (File.Exists("DodocoTales.StarRail.exe")) 48 | File.Delete("DodocoTales.StarRail.exe"); 49 | Directory.Delete("update"); 50 | } 51 | catch (Exception) 52 | { 53 | 54 | } 55 | } 56 | 57 | static void MoveFromDirectory(DirectoryInfo sourceDir, DirectoryInfo destDir) 58 | { 59 | foreach (var dir in sourceDir.GetDirectories()) 60 | { 61 | var destl = destDir.GetDirectories(dir.Name); 62 | if (!destl.Any()) 63 | { 64 | dir.MoveTo(destDir.FullName + "/" + dir.Name); 65 | } 66 | else 67 | { 68 | MoveFromDirectory(dir, destl[0]); 69 | } 70 | } 71 | foreach (var file in sourceDir.GetFiles()) 72 | { 73 | var destl = destDir.GetFiles(file.Name); 74 | if (destl.Any()) 75 | { 76 | destl[0].Delete(); 77 | } 78 | file.MoveTo(destDir.FullName + "/" + file.Name); 79 | } 80 | sourceDir.Delete(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Updater/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 有关程序集的一般信息由以下 6 | // 控制。更改这些特性值可修改 7 | // 与程序集关联的信息。 8 | [assembly: AssemblyTitle("Updater")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Updater")] 13 | [assembly: AssemblyCopyright("Copyright © 2023")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // 将 ComVisible 设置为 false 会使此程序集中的类型 18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 19 | //请将此类型的 ComVisible 特性设置为 true。 20 | [assembly: ComVisible(false)] 21 | 22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID 23 | [assembly: Guid("2b10ff4b-41b8-41c4-a5d1-fdea5f52a16d")] 24 | 25 | // 程序集的版本信息由下列四个值组成: 26 | // 27 | // 主版本 28 | // 次版本 29 | // 生成号 30 | // 修订号 31 | // 32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值 33 | //通过使用 "*",如下所示: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Updater/Updater.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {2B10FF4B-41B8-41C4-A5D1-FDEA5F52A16D} 8 | WinExe 9 | Updater 10 | Updater 11 | v4.7.2 12 | 512 13 | true 14 | true 15 | publish\ 16 | true 17 | Disk 18 | false 19 | Foreground 20 | 7 21 | Days 22 | false 23 | false 24 | true 25 | 0 26 | 1.0.0.%2a 27 | false 28 | false 29 | true 30 | 31 | 32 | AnyCPU 33 | true 34 | full 35 | false 36 | bin\Debug\ 37 | DEBUG;TRACE 38 | prompt 39 | 0 40 | 41 | 42 | AnyCPU 43 | pdbonly 44 | true 45 | bin\Release\ 46 | TRACE 47 | prompt 48 | 4 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | False 74 | Microsoft .NET Framework 4.7.2 %28x86 和 x64%29 75 | true 76 | 77 | 78 | False 79 | .NET Framework 3.5 SP1 80 | false 81 | 82 | 83 | 84 | --------------------------------------------------------------------------------