├── .gitignore ├── App.xaml ├── App.xaml.cs ├── Article ├── ArticleConfig.cs ├── ArticleManager.cs ├── Filter.cs ├── TxtFileEncoder.cs ├── WinArticle.xaml └── WinArticle.xaml.cs ├── ArticleConfig.cs ├── ArticleManager.cs ├── ChangSheng.cs ├── Colors.cs ├── Config.cs ├── CounterLog.cs ├── DebugLog.cs ├── Diff ├── DiffNode.cs ├── DiffRes.cs ├── DiffTool.cs ├── GroupedDiffRes.cs ├── PartSplitedDiffRes.cs ├── PathNode.cs ├── Snake.cs └── SplitedDiffRes.cs ├── DiffNode.cs ├── DiffRes.cs ├── DiffTool.cs ├── FileComparer.cs ├── Filter.cs ├── GroupedDiffRes.cs ├── IntStringDict.cs ├── LICENSE ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Paginator.cs ├── PartSplitedDiffRes.cs ├── PathNode.cs ├── QQHelper.cs ├── Recorder.cs ├── RetypeCouner.cs ├── Score.cs ├── Sender.cs ├── Single ├── winSingle.xaml └── winSingle.xaml.cs ├── Snake.cs ├── SplitedDiffRes.cs ├── StateManager.cs ├── StringToFontFamily.cs ├── TextInfo.cs ├── TxtConfig.cs ├── TypeB.csproj ├── TypeB.csproj.user ├── TypeB.sln ├── TypeB_gmojvlcg_wpftmp.csproj ├── TypeB_j5ve5n4e_wpftmp.csproj ├── Util.cs ├── Win32.cs ├── WinConfig ├── WinConfig.xaml └── WinConfig.xaml.cs ├── WinTrainer ├── TrainerConfig.cs ├── WinTrainer.xaml └── WinTrainer.xaml.cs ├── app.config ├── net ├── ChangSheng.cs ├── JBS.cs ├── Sender.cs └── Util.cs ├── packages.config ├── packages ├── Interop.UIAutomationClient.10.19041.0 │ ├── .signature.p7s │ ├── Interop.UIAutomationClient.10.19041.0.nupkg │ ├── LICENSE.txt │ ├── build │ │ └── Interop.UIAutomationClient.targets │ ├── lib │ │ ├── net35 │ │ │ └── Interop.UIAutomationClient.dll │ │ ├── net40 │ │ │ └── Interop.UIAutomationClient.dll │ │ ├── net45 │ │ │ └── Interop.UIAutomationClient.dll │ │ ├── netcoreapp3.0 │ │ │ └── Interop.UIAutomationClient.dll │ │ └── netstandard2.0 │ │ │ └── Interop.UIAutomationClient.dll │ └── tools │ │ └── install.ps1 └── Newtonsoft.Json.13.0.3 │ ├── .signature.p7s │ ├── LICENSE.md │ ├── Newtonsoft.Json.13.0.3.nupkg │ ├── README.md │ ├── lib │ ├── net20 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── net35 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── net40 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── net45 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── net6.0 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── netstandard1.0 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ ├── netstandard1.3 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ └── netstandard2.0 │ │ ├── Newtonsoft.Json.dll │ │ └── Newtonsoft.Json.xml │ └── packageIcon.png └── paindutch.ico /.gitignore: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # 此 .gitignore 文件已由 Microsoft(R) Visual Studio 自动创建。 3 | ################################################################################ 4 | 5 | /.vs 6 | /bin 7 | /obj 8 | /Properties 9 | -------------------------------------------------------------------------------- /App.xaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /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 TypeB 10 | { 11 | /// 12 | /// App.xaml 的交互逻辑 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Article/ArticleConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace TypeB 10 | { 11 | internal class ArticleConfig 12 | { 13 | static public Dictionary dicts = new Dictionary(); 14 | static public string Path = "ArticleConfig.txt"; 15 | 16 | static public void SetDefault(params string[] args) 17 | { 18 | for (int i = 0; i + 1 < args.Length; i += 2) 19 | { 20 | dicts[args[i]] = args[i + 1]; 21 | } 22 | 23 | } 24 | 25 | 26 | static private Timer WriteTimer = null; 27 | 28 | 29 | static private void WriteNow(object obj) 30 | { 31 | 32 | if (Path == "") 33 | return; 34 | 35 | 36 | StreamWriter sw = new StreamWriter(Path); 37 | 38 | foreach (var c in dicts) 39 | { 40 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 41 | } 42 | 43 | 44 | sw.Close(); 45 | if (WriteTimer != null) 46 | { 47 | WriteTimer.Dispose(); 48 | WriteTimer = null; 49 | } 50 | 51 | } 52 | 53 | static public void WriteConfig(int Delay = 0) 54 | { 55 | 56 | if (Path == "") 57 | return; 58 | 59 | if (Delay == 0) 60 | { 61 | if (WriteTimer != null) 62 | { 63 | WriteTimer.Dispose(); 64 | WriteTimer = null; 65 | } 66 | 67 | StreamWriter sw = new StreamWriter(Path); 68 | 69 | foreach (var c in dicts) 70 | { 71 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 72 | } 73 | 74 | 75 | sw.Close(); 76 | } 77 | else if (Delay > 0) 78 | { 79 | if (WriteTimer == null) 80 | { 81 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 82 | } 83 | else 84 | { 85 | WriteTimer.Dispose(); 86 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 87 | // WriteTimer.Change(Delay, Timeout.Infinite); 88 | 89 | } 90 | } 91 | } 92 | 93 | static public void ReadConfig() 94 | { 95 | // char[] sp = { '\r', ' ', '\t' }; 96 | 97 | if (!File.Exists(Path)) 98 | { 99 | WriteConfig(); 100 | return; 101 | } 102 | 103 | char[] sp1 = { '\n' }; 104 | 105 | string[] lines = File.ReadAllText(Path).Split(sp1, StringSplitOptions.RemoveEmptyEntries); 106 | 107 | 108 | foreach (string line in lines) 109 | { 110 | if (line.Substring(0, 1) == "#") 111 | continue; 112 | string line_p = line.Replace("\r", "").Replace("\n", ""); 113 | 114 | string[] sp = { "\t", " ", "," }; 115 | 116 | 117 | 118 | foreach (string s in sp) 119 | { 120 | if (line_p.Contains(s)) 121 | { 122 | int pos = line_p.IndexOf(s); 123 | if (pos >= 1 && pos <= line_p.Length - 2) 124 | { 125 | string key = line_p.Substring(0, pos); 126 | string value = line_p.Substring(pos + 1); 127 | dicts[key] = value; 128 | break; 129 | } 130 | } 131 | } 132 | 133 | 134 | 135 | } 136 | 137 | 138 | WriteConfig(); 139 | 140 | 141 | 142 | } 143 | 144 | static public bool GetBool(string key) 145 | { 146 | if (dicts.ContainsKey(key) && dicts[key] == "是") 147 | return true; 148 | else 149 | return false; 150 | } 151 | static public string GetString(string key) 152 | { 153 | if (dicts.ContainsKey(key)) 154 | return dicts[key]; 155 | else 156 | return ""; 157 | } 158 | 159 | static public int GetInt(string key) 160 | { 161 | if (dicts.ContainsKey(key) && Int32.TryParse(dicts[key], out int num)) 162 | return num; 163 | else 164 | return 0; 165 | } 166 | 167 | 168 | static public double GetDouble(string key) 169 | { 170 | if (dicts.ContainsKey(key) && Double.TryParse(dicts[key], out double num)) 171 | return num; 172 | else 173 | return 0; 174 | } 175 | 176 | static public void Set(string key, bool value) 177 | { 178 | if (value) 179 | dicts[key] = "是"; 180 | else 181 | dicts[key] = "否"; 182 | 183 | WriteConfig(3000); 184 | } 185 | static public void Set(string key, int value) 186 | { 187 | dicts[key] = value.ToString(); 188 | WriteConfig(3000); 189 | } 190 | 191 | static public void Set(string key, string value) 192 | { 193 | dicts[key] = value; 194 | WriteConfig(3000); 195 | } 196 | 197 | static public void Set(string key, double value, int fraction = -1) 198 | { 199 | string f = "F" + fraction.ToString(); 200 | if (fraction > 0) 201 | dicts[key] = value.ToString(f); 202 | else 203 | dicts[key] = value.ToString(); 204 | 205 | WriteConfig(3000); 206 | 207 | } 208 | } 209 | 210 | 211 | 212 | } 213 | -------------------------------------------------------------------------------- /Article/ArticleManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Windows.Data; 8 | 9 | 10 | namespace TypeB 11 | { 12 | public class Article 13 | { 14 | public string Title { get; set; } 15 | public StringInfo Text { get; set; } 16 | 17 | 18 | public Article(string title, string text)//, int progress = 0) 19 | { 20 | Title = title; 21 | Text = new StringInfo(text.Replace("\n","").Replace("\r", "").Replace("\t", "")); 22 | // Text = new StringInfo(text.Replace("\r", "").Replace("\t", "").Replace("\n","\t")); 23 | } 24 | } 25 | internal static class ArticleManager 26 | { 27 | const string FolderPath = "文章"; 28 | 29 | 30 | 31 | 32 | 33 | public static Dictionary Articles = new Dictionary (); 34 | 35 | 36 | 37 | public static void ReadFiles () 38 | { 39 | Articles.Clear(); 40 | DirectoryInfo dir = new DirectoryInfo(FolderPath); 41 | 42 | if (!dir.Exists ) 43 | { 44 | dir.Create (); 45 | return; 46 | } 47 | 48 | foreach (FileInfo file in dir.GetFiles("*.txt")) 49 | { 50 | string name = file.Name; 51 | 52 | Encoding enc = TxtFileEncoder.GetEncoding(file.FullName); 53 | string txt = File.ReadAllText(file.FullName,enc); 54 | 55 | 56 | Articles.Add(name, new Article(name, txt)); 57 | 58 | 59 | } 60 | 61 | 62 | } 63 | 64 | public static int SectionSize 65 | { 66 | get 67 | { 68 | return ArticleConfig.GetInt("每段字数"); 69 | } 70 | set 71 | { 72 | ArticleConfig.Set("每段字数", value); 73 | UpdateWindows(); 74 | ArticleConfig.WriteConfig(500); 75 | } 76 | } 77 | 78 | 79 | public static string GetCurrentSection() 80 | { 81 | 82 | string rt; 83 | if (!Articles.ContainsKey(Title)) 84 | return ""; 85 | 86 | if (Progress >= TotalSize) 87 | return "没了"; 88 | 89 | if (Progress + SectionSize < TotalSize) 90 | rt = Articles[Title].Text.SubstringByTextElements((Index - 1) * SectionSize, SectionSize); 91 | else 92 | rt = Articles[Title].Text.SubstringByTextElements((Index - 1) * SectionSize); 93 | 94 | 95 | 96 | if (EnableFilter) 97 | { 98 | // txt = Filter.ProcFilter(txt); 99 | 100 | rt = Filter.ProcFilter(rt); 101 | } 102 | 103 | if (RemoveSpace) 104 | rt = rt.Replace(" ", "").Replace(" ", ""); 105 | else //去除首末空格 106 | { 107 | if (rt.Length >= 1 && rt.Substring(0, 1) == " ") 108 | rt = rt.Substring(1, rt.Length - 1); 109 | 110 | if (rt.Length >= 1 && rt.Substring(rt.Length - 1, 1) == " ") 111 | rt = rt.Substring(0, rt.Length - 1); 112 | } 113 | return rt; 114 | } 115 | 116 | public static void NextSection() 117 | { 118 | if (!Articles.ContainsKey(Title)) 119 | return; 120 | 121 | if (Progress >= TotalSize) 122 | return; 123 | 124 | Progress = Math.Min(Progress + SectionSize, TotalSize); 125 | 126 | 127 | UpdateWindows(); 128 | } 129 | 130 | public static void PrevSection() 131 | { 132 | if (!Articles.ContainsKey(Title)) 133 | return; 134 | 135 | if (Progress == 0) 136 | return; 137 | Progress = Math.Max(Progress - SectionSize, 0); 138 | UpdateWindows(); 139 | } 140 | 141 | public static string GetFormattedCurrentSection() 142 | { 143 | if (!Articles.ContainsKey(Title)) 144 | return ""; 145 | 146 | StringBuilder sb = new StringBuilder(); 147 | sb.Append(Title.Replace(".txt","").Replace(".Txt", "").Replace(".TXT", "")); 148 | sb.AppendLine(); 149 | string txt = GetCurrentSection(); 150 | sb.Append(txt); 151 | sb.AppendLine(); 152 | sb.Append("-----第"); 153 | sb.Append(Index); 154 | sb.Append("段"); 155 | 156 | 157 | sb.Append("-"); 158 | 159 | sb.Append(" 共"); 160 | sb.Append(MaxIndex); 161 | sb.Append("段 "); 162 | 163 | sb.Append(" 进度 "); 164 | sb.Append((Index - 1) * SectionSize); 165 | sb.Append("/"); 166 | sb.Append(TotalSize); 167 | sb.Append("字 "); 168 | 169 | sb.Append(" 本段"); 170 | sb.Append(new StringInfo(txt).LengthInTextElements); 171 | sb.Append("字 "); 172 | 173 | sb.Append("Pain散播器"); 174 | return sb.ToString(); 175 | 176 | } 177 | 178 | public static string GetFormattedNextSection() 179 | { 180 | 181 | string rt; 182 | if (!Articles.ContainsKey(Title)) 183 | return ""; 184 | else 185 | { 186 | rt = GetFormattedCurrentSection(); 187 | NextSection(); 188 | } 189 | return rt; 190 | } 191 | 192 | public static int Index 193 | { 194 | get 195 | { 196 | if (!Articles.ContainsKey(Title)) 197 | return 1; 198 | else 199 | { 200 | int counter = 0; 201 | 202 | 203 | while (true) 204 | { 205 | if (SectionSize * counter -1 >= Progress) 206 | break; 207 | 208 | counter++; 209 | } 210 | 211 | 212 | return counter; 213 | } 214 | 215 | } 216 | 217 | 218 | } 219 | 220 | public static int TotalSize 221 | { 222 | get 223 | { 224 | if (!Articles.ContainsKey(Title)) 225 | return 0; 226 | else 227 | return Articles[Title].Text.LengthInTextElements; 228 | } 229 | } 230 | 231 | public static int MaxIndex 232 | { 233 | get 234 | { 235 | if (!Articles.ContainsKey(Title)) 236 | return 1; 237 | else 238 | { 239 | int counter = 0; 240 | 241 | while (true) 242 | { 243 | if (SectionSize * counter - 1 >= TotalSize -1 ) 244 | break; 245 | 246 | counter++; 247 | } 248 | 249 | return counter; 250 | } 251 | 252 | } 253 | 254 | 255 | 256 | } 257 | 258 | public static string Title 259 | { 260 | get 261 | { 262 | return ArticleConfig.GetString("当前文章"); 263 | } 264 | set 265 | { 266 | if (!Articles.ContainsKey(value) || ArticleConfig.GetString("当前文章") == value) 267 | return; 268 | else 269 | { 270 | ArticleConfig.Set("当前文章", value); 271 | UpdateWindows(); 272 | } 273 | 274 | } 275 | } 276 | 277 | private static void UpdateWindows() 278 | { 279 | ((MainWindow)App.Current.Windows[0]).UpdateButtonProgress(); 280 | 281 | ((MainWindow)App.Current.Windows[0]).winArticle?.UpdateDisplay(); 282 | 283 | } 284 | public static int Progress 285 | { 286 | get 287 | { 288 | if (!Articles.ContainsKey(Title)) 289 | return 0; 290 | else 291 | return ArticleConfig.GetInt("进度_" + Title); 292 | } 293 | set 294 | { 295 | if (Articles.ContainsKey(Title)) 296 | { 297 | int v = Math.Min( Math.Max(0, value), TotalSize - 1); 298 | 299 | ArticleConfig.Set("进度_" + Title, v); 300 | UpdateWindows(); 301 | ArticleConfig.WriteConfig(500); 302 | 303 | } 304 | 305 | } 306 | } 307 | 308 | public static bool EnableFilter 309 | { 310 | get 311 | { 312 | 313 | return ArticleConfig.GetBool("字集过滤"); 314 | } 315 | set 316 | { 317 | 318 | ArticleConfig.Set("字集过滤" , value); 319 | ArticleConfig.WriteConfig(500); 320 | 321 | 322 | } 323 | } 324 | 325 | public static bool RemoveSpace 326 | { 327 | get 328 | { 329 | 330 | return ArticleConfig.GetBool("去除空格"); 331 | } 332 | set 333 | { 334 | 335 | ArticleConfig.Set("去除空格", value); 336 | ArticleConfig.WriteConfig(500); 337 | 338 | 339 | } 340 | } 341 | 342 | 343 | public static int Search(string text, int startIndex) 344 | { 345 | int rt = -1; 346 | 347 | rt = Articles[Title].Text.String.IndexOf(text,startIndex); 348 | if (rt > 0) 349 | rt = new StringInfo( Articles[Title].Text.String.Substring(0, rt)).LengthInTextElements; 350 | 351 | return rt; 352 | } 353 | 354 | static ArticleManager() 355 | { 356 | ArticleConfig.SetDefault 357 | ( 358 | "每段字数", "200", 359 | "字集过滤", "是", 360 | "去除空格", "是" 361 | 362 | ); 363 | 364 | ArticleConfig.ReadConfig(); 365 | 366 | ArticleManager.ReadFiles(); 367 | } 368 | } 369 | } 370 | -------------------------------------------------------------------------------- /Article/TxtFileEncoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace TypeB 9 | { 10 | /// 11 | /// 用于取得一个文本文件的编码方式(Encoding)。 12 | /// 13 | public class TxtFileEncoder 14 | { 15 | public TxtFileEncoder() 16 | { 17 | // 18 | // TODO: 在此处添加构造函数逻辑 19 | // 20 | } 21 | /// 22 | /// 取得一个文本文件的编码方式。如果无法在文件头部找到有效的前导符,Encoding.Default将被返回。 23 | /// 24 | /// 文件名。 25 | /// 26 | public static Encoding GetEncoding(string fileName) 27 | { 28 | return GetEncoding(fileName, Encoding.Default); 29 | } 30 | /// 31 | /// 取得一个文本文件流的编码方式。 32 | /// 33 | /// 文本文件流。 34 | /// 35 | public static Encoding GetEncoding(FileStream stream) 36 | { 37 | return GetEncoding(stream, Encoding.Default); 38 | } 39 | /// 40 | /// 取得一个文本文件的编码方式。 41 | /// 42 | /// 文件名。 43 | /// 默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。 44 | /// 45 | public static Encoding GetEncoding(string fileName, Encoding defaultEncoding) 46 | { 47 | FileStream fs = new FileStream(fileName, FileMode.Open); 48 | Encoding targetEncoding = GetEncoding(fs, defaultEncoding); 49 | fs.Close(); 50 | return targetEncoding; 51 | } 52 | /// 53 | /// 取得一个文本文件流的编码方式。 54 | /// 55 | /// 文本文件流。 56 | /// 默认编码方式。当该方法无法从文件的头部取得有效的前导符时,将返回该编码方式。 57 | /// 58 | 59 | 60 | 61 | // 新增加一个方法,解决了不带BOM的 UTF8 编码问题 62 | 63 | /// 64 | /// 通过给定的文件流,判断文件的编码类型 65 | /// 66 | /// 文件流 67 | /// 文件的编码类型 68 | public static System.Text.Encoding GetEncoding(Stream fs, Encoding defaultEncoding) 69 | { 70 | byte[] Unicode = new byte[] { 0xFF, 0xFE, 0x41 }; 71 | byte[] UnicodeBIG = new byte[] { 0xFE, 0xFF, 0x00 }; 72 | byte[] UTF8 = new byte[] { 0xEF, 0xBB, 0xBF }; //带BOM 73 | Encoding reVal = defaultEncoding; 74 | 75 | BinaryReader r = new BinaryReader(fs, System.Text.Encoding.Default); 76 | byte[] ss = r.ReadBytes(4); 77 | 78 | if (ss[0] == 0xFE && ss[1] == 0xFF && ss[2] == 0x00) 79 | { 80 | reVal = Encoding.BigEndianUnicode; 81 | } 82 | else if (ss[0] == 0xFF && ss[1] == 0xFE && ss[2] == 0x41) 83 | { 84 | reVal = Encoding.Unicode; 85 | } 86 | else 87 | { 88 | if (ss[0] == 0xEF && ss[1] == 0xBB && ss[2] == 0xBF) 89 | { 90 | reVal = Encoding.UTF8; 91 | } 92 | else 93 | { 94 | int i; 95 | int.TryParse(fs.Length.ToString(), out i); 96 | r.BaseStream.Seek(0, SeekOrigin.Begin); 97 | ss = r.ReadBytes(i); 98 | 99 | if (IsUTF8Bytes(ss)) 100 | reVal = Encoding.UTF8; 101 | } 102 | } 103 | r.Close(); 104 | return reVal; 105 | 106 | } 107 | 108 | /// 109 | /// 判断是否是不带 BOM 的 UTF8 格式 110 | /// 111 | /// 112 | /// 113 | private static bool IsUTF8Bytes(byte[] data) 114 | { 115 | int charByteCounter = 1; //计算当前正分析的字符应还有的字节数 116 | byte curByte; //当前分析的字节. 117 | for (int i = 0; i < data.Length; i++) 118 | { 119 | curByte = data[i]; 120 | if (charByteCounter == 1) 121 | { 122 | if (curByte >= 0x80) 123 | { 124 | //判断当前 125 | while (((curByte <<= 1) & 0x80) != 0) 126 | { 127 | charByteCounter++; 128 | } 129 | //标记位首位若为非0 则至少以2个1开始 如:110XXXXX...........1111110X  130 | if (charByteCounter == 1 || charByteCounter > 6) 131 | { 132 | return false; 133 | } 134 | } 135 | } 136 | else 137 | { 138 | //若是UTF-8 此时第一位必须为1 139 | if ((curByte & 0xC0) != 0x80) 140 | { 141 | return false; 142 | } 143 | charByteCounter--; 144 | } 145 | } 146 | if (charByteCounter > 1) 147 | { 148 | throw new Exception("非预期的byte格式!"); 149 | } 150 | return true; 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Article/WinArticle.xaml: -------------------------------------------------------------------------------- 1 |  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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /Article/WinArticle.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | 7 | using System.Windows.Input; 8 | 9 | namespace TypeB 10 | { 11 | /// 12 | /// MainWindow.xaml 的交互逻辑 13 | /// 14 | public partial class WinArticle : Window 15 | { 16 | public WinArticle() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | private void InitTxtFiles() 22 | { 23 | 24 | 25 | CbFiles.ItemsSource = ArticleManager.Articles.Keys; 26 | 27 | string cur = ArticleManager.Title; 28 | if (CbFiles.Items.Contains(cur)) 29 | { 30 | CbFiles.SelectedItem = cur; 31 | } 32 | CbFiles.Items.Refresh(); 33 | } 34 | 35 | bool AllLoaded; 36 | private void InitControls() 37 | { 38 | 39 | 40 | 41 | SldSecLen.Value = ArticleManager.SectionSize; 42 | 43 | 44 | CbFilter.IsChecked = ArticleManager.EnableFilter; 45 | CbRemoveSpace.IsChecked = ArticleManager.RemoveSpace; 46 | 47 | 48 | } 49 | 50 | public void UpdateDisplay() 51 | { 52 | 53 | SldProgress.Maximum = ArticleManager.MaxIndex; 54 | 55 | if (SldProgress.Maximum != ArticleManager.MaxIndex) 56 | SldProgress.Maximum = ArticleManager.MaxIndex; 57 | 58 | if (SldProgress.Value != ArticleManager.Index) 59 | SldProgress.Value = ArticleManager.Index; 60 | 61 | 62 | TbTest.Text = ArticleManager.GetFormattedCurrentSection(); 63 | } 64 | 65 | private void Window_Loaded(object sender, RoutedEventArgs e) 66 | { 67 | InitTxtFiles(); 68 | InitControls(); 69 | UpdateDisplay(); 70 | AllLoaded = true; 71 | 72 | 73 | } 74 | 75 | 76 | private void Reload() 77 | { 78 | ArticleManager.ReadFiles(); 79 | AllLoaded = false; 80 | InitTxtFiles(); 81 | InitControls(); 82 | UpdateDisplay(); 83 | AllLoaded = true; 84 | 85 | } 86 | 87 | 88 | 89 | 90 | private void CbFiles_SelectionChanged(object sender, SelectionChangedEventArgs e) 91 | { 92 | if (AllLoaded) 93 | { 94 | ArticleManager.Title = CbFiles.SelectedItem.ToString(); 95 | 96 | 97 | 98 | } 99 | 100 | } 101 | 102 | private void SldSecLen_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) 103 | { 104 | if (AllLoaded) 105 | { 106 | ArticleManager.SectionSize = (int)SldSecLen.Value; 107 | 108 | } 109 | 110 | } 111 | 112 | 113 | 114 | private void SldProgress_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) 115 | { 116 | if (AllLoaded) 117 | { 118 | // ArticleManager.Progress = (ArticleManager.SectionSize * (int)(SldProgress.Value - 1)); 119 | 120 | 121 | } 122 | 123 | } 124 | 125 | private void Search() 126 | { 127 | if (TbSearch.Text == "") 128 | return; 129 | 130 | int startindex = 0; 131 | // if (ArticleManager.Progress > 0) 132 | startindex = Math.Min(ArticleManager.Progress + ArticleManager.SectionSize, ArticleManager.TotalSize - 1); 133 | 134 | int s = ArticleManager.Search(TbSearch.Text, startindex); 135 | if (s >= 0) 136 | { 137 | ArticleManager.Progress = s; 138 | // UpdateDisplay(); UpdateTxt(); 139 | } 140 | else if (ArticleManager.Progress > 0) 141 | { 142 | if (MessageBox.Show("查找不到,是否从头开始查找?", "查找", MessageBoxButton.OKCancel, MessageBoxImage.Question) == MessageBoxResult.OK) 143 | { 144 | int s0 = ArticleManager.Search(TbSearch.Text, 0); 145 | if (s0 >= 0) 146 | { 147 | ArticleManager.Progress = s0; 148 | // UpdateDisplay(); UpdateTxt(); 149 | } 150 | else 151 | { 152 | MessageBox.Show("查找不到", "查找", MessageBoxButton.OK, MessageBoxImage.Information); 153 | } 154 | } 155 | } 156 | else 157 | { 158 | MessageBox.Show("查找不到", "查找", MessageBoxButton.OK, MessageBoxImage.Information); 159 | } 160 | } 161 | private void BtnSearch_Click(object sender, RoutedEventArgs e) 162 | { 163 | Search(); 164 | } 165 | 166 | public void Prev() 167 | { 168 | ArticleManager.PrevSection(); 169 | // UpdateDisplay(); UpdateTxt(); 170 | } 171 | private void BtnPrev_Click(object sender, RoutedEventArgs e) 172 | { 173 | Prev(); 174 | } 175 | 176 | public void Next() 177 | { 178 | ArticleManager.NextSection(); 179 | // UpdateDisplay(); UpdateTxt(); 180 | } 181 | private void BtnNext_Click(object sender, RoutedEventArgs e) 182 | { 183 | Next(); 184 | } 185 | 186 | private void BtnReload_Click(object sender, RoutedEventArgs e) 187 | { 188 | Reload(); 189 | } 190 | 191 | private void BtnOpen_Click(object sender, RoutedEventArgs e) 192 | { 193 | string folderPath = AppDomain.CurrentDomain.BaseDirectory + "文章" ; 194 | Process.Start(folderPath); 195 | } 196 | 197 | 198 | 199 | private void BtnSend_Click(object sender, RoutedEventArgs e) 200 | { 201 | 202 | ((MainWindow)App.Current.Windows[0]).SendArticle(); 203 | // MainWindow.SendArticle(); 204 | 205 | } 206 | 207 | 208 | 209 | private void CbFilter_Checked(object sender, RoutedEventArgs e) 210 | { 211 | if (AllLoaded) 212 | { 213 | ArticleManager.EnableFilter = (CbFilter.IsChecked == true); 214 | Reload(); 215 | } 216 | 217 | } 218 | 219 | private void CbFilter_Unchecked(object sender, RoutedEventArgs e) 220 | { 221 | if (AllLoaded) 222 | { 223 | ArticleManager.EnableFilter = (CbFilter.IsChecked == true); 224 | Reload(); 225 | } 226 | 227 | } 228 | 229 | private void CbRemoveSpace_Checked(object sender, RoutedEventArgs e) 230 | { 231 | if (AllLoaded) 232 | { 233 | ArticleManager.RemoveSpace = (CbRemoveSpace.IsChecked == true); 234 | Reload(); 235 | } 236 | } 237 | 238 | private void CbRemoveSpace_Unchecked(object sender, RoutedEventArgs e) 239 | { 240 | if (AllLoaded) 241 | { 242 | ArticleManager.RemoveSpace = (CbRemoveSpace.IsChecked == true); 243 | Reload(); 244 | } 245 | } 246 | 247 | private void TbSearch_PreviewKeyDown(object sender, KeyEventArgs e) 248 | { 249 | if (e.Key == Key.Enter) 250 | { 251 | Search (); 252 | } 253 | } 254 | 255 | private void SldProgress_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e) 256 | { 257 | if (AllLoaded) 258 | { 259 | ArticleManager.Progress = (ArticleManager.SectionSize * (int)(SldProgress.Value - 1)); 260 | 261 | } 262 | } 263 | 264 | 265 | } 266 | } 267 | 268 | -------------------------------------------------------------------------------- /ArticleConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace TestArticle 10 | { 11 | internal class ArticleConfig 12 | { 13 | static public Dictionary dicts = new Dictionary(); 14 | static public string Path = "config.txt"; 15 | 16 | static public void SetDefault(params string[] args) 17 | { 18 | for (int i = 0; i + 1 < args.Length; i += 2) 19 | { 20 | dicts[args[i]] = args[i + 1]; 21 | } 22 | 23 | } 24 | 25 | 26 | static private Timer WriteTimer = null; 27 | 28 | 29 | static private void WriteNow(object obj) 30 | { 31 | 32 | if (Path == "") 33 | return; 34 | 35 | 36 | StreamWriter sw = new StreamWriter(Path); 37 | 38 | foreach (var c in dicts) 39 | { 40 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 41 | } 42 | 43 | 44 | sw.Close(); 45 | if (WriteTimer != null) 46 | { 47 | WriteTimer.Dispose(); 48 | WriteTimer = null; 49 | } 50 | 51 | } 52 | 53 | static public void WriteConfig(int Delay = 0) 54 | { 55 | 56 | if (Path == "") 57 | return; 58 | 59 | if (Delay == 0) 60 | { 61 | if (WriteTimer != null) 62 | { 63 | WriteTimer.Dispose(); 64 | WriteTimer = null; 65 | } 66 | 67 | StreamWriter sw = new StreamWriter(Path); 68 | 69 | foreach (var c in dicts) 70 | { 71 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 72 | } 73 | 74 | 75 | sw.Close(); 76 | } 77 | else if (Delay > 0) 78 | { 79 | if (WriteTimer == null) 80 | { 81 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 82 | } 83 | else 84 | { 85 | WriteTimer.Dispose(); 86 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 87 | // WriteTimer.Change(Delay, Timeout.Infinite); 88 | 89 | } 90 | } 91 | } 92 | 93 | static public void ReadConfig() 94 | { 95 | // char[] sp = { '\r', ' ', '\t' }; 96 | 97 | if (!File.Exists(Path)) 98 | { 99 | WriteConfig(); 100 | return; 101 | } 102 | 103 | char[] sp1 = { '\n' }; 104 | 105 | string[] lines = File.ReadAllText(Path).Split(sp1, StringSplitOptions.RemoveEmptyEntries); 106 | 107 | 108 | foreach (string line in lines) 109 | { 110 | if (line.Substring(0, 1) == "#") 111 | continue; 112 | string line_p = line.Replace("\r", "").Replace("\n", ""); 113 | 114 | string[] sp = { "\t", " ", "," }; 115 | 116 | 117 | 118 | foreach (string s in sp) 119 | { 120 | if (line_p.Contains(s)) 121 | { 122 | int pos = line_p.IndexOf(s); 123 | if (pos >= 1 && pos <= line_p.Length - 2) 124 | { 125 | string key = line_p.Substring(0, pos); 126 | string value = line_p.Substring(pos + 1); 127 | dicts[key] = value; 128 | break; 129 | } 130 | } 131 | } 132 | 133 | 134 | 135 | } 136 | 137 | 138 | WriteConfig(); 139 | 140 | 141 | 142 | } 143 | 144 | static public bool GetBool(string key) 145 | { 146 | if (dicts.ContainsKey(key) && dicts[key] == "是") 147 | return true; 148 | else 149 | return false; 150 | } 151 | static public string GetString(string key) 152 | { 153 | if (dicts.ContainsKey(key)) 154 | return dicts[key]; 155 | else 156 | return ""; 157 | } 158 | 159 | static public int GetInt(string key) 160 | { 161 | if (dicts.ContainsKey(key) && Int32.TryParse(dicts[key], out int num)) 162 | return num; 163 | else 164 | return 0; 165 | } 166 | 167 | 168 | static public double GetDouble(string key) 169 | { 170 | if (dicts.ContainsKey(key) && Double.TryParse(dicts[key], out double num)) 171 | return num; 172 | else 173 | return 0; 174 | } 175 | 176 | static public void Set(string key, bool value) 177 | { 178 | if (value) 179 | dicts[key] = "是"; 180 | else 181 | dicts[key] = "否"; 182 | 183 | WriteConfig(3000); 184 | } 185 | static public void Set(string key, int value) 186 | { 187 | dicts[key] = value.ToString(); 188 | WriteConfig(3000); 189 | } 190 | 191 | static public void Set(string key, string value) 192 | { 193 | dicts[key] = value; 194 | WriteConfig(3000); 195 | } 196 | 197 | static public void Set(string key, double value, int fraction = -1) 198 | { 199 | string f = "F" + fraction.ToString(); 200 | if (fraction > 0) 201 | dicts[key] = value.ToString(f); 202 | else 203 | dicts[key] = value.ToString(); 204 | 205 | WriteConfig(3000); 206 | 207 | } 208 | } 209 | 210 | 211 | 212 | } 213 | -------------------------------------------------------------------------------- /ArticleManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Globalization; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Text; 8 | 9 | 10 | namespace TestArticle 11 | { 12 | public class Article 13 | { 14 | public string Title { get; set; } 15 | public StringInfo Text { get; set; } 16 | 17 | 18 | public Article(string title, string text)//, int progress = 0) 19 | { 20 | Title = title; 21 | Text = new StringInfo(text.Replace("\n","").Replace("\r", "").Replace("\t", "")); 22 | 23 | } 24 | } 25 | internal static class ArticleManager 26 | { 27 | const string FolderPath = "文章"; 28 | 29 | 30 | 31 | public static Dictionary Articles = new Dictionary (); 32 | 33 | 34 | 35 | public static void ReadFiles () 36 | { 37 | Articles.Clear(); 38 | DirectoryInfo dir = new DirectoryInfo(FolderPath); 39 | 40 | 41 | foreach (FileInfo file in dir.GetFiles("*.txt")) 42 | { 43 | string name = file.Name; 44 | 45 | Encoding enc = TxtFileEncoder.GetEncoding(file.FullName); 46 | string txt = File.ReadAllText(file.FullName,enc); 47 | 48 | 49 | Articles.Add(name, new Article(name, txt)); 50 | 51 | 52 | } 53 | 54 | 55 | } 56 | 57 | public static int SectionSize 58 | { 59 | get 60 | { 61 | return ArticleConfig.GetInt("每段字数"); 62 | } 63 | set 64 | { 65 | ArticleConfig.Set("每段字数", value); 66 | ArticleConfig.WriteConfig(500); 67 | } 68 | } 69 | 70 | 71 | public static string GetCurrentSection() 72 | { 73 | 74 | string rt; 75 | if (!Articles.ContainsKey(Title)) 76 | return ""; 77 | 78 | if (Progress >= TotalSize) 79 | return "没了"; 80 | 81 | if (Progress + SectionSize < TotalSize) 82 | rt = Articles[Title].Text.SubstringByTextElements((Index - 1) * SectionSize, SectionSize); 83 | else 84 | rt = Articles[Title].Text.SubstringByTextElements((Index - 1) * SectionSize); 85 | 86 | 87 | 88 | if (EnableFilter) 89 | { 90 | // txt = Filter.ProcFilter(txt); 91 | 92 | rt = Filter.ProcFilter(rt); 93 | } 94 | 95 | if (RemoveSpace) 96 | rt = rt.Replace(" ", "").Replace(" ", ""); 97 | 98 | return rt; 99 | } 100 | 101 | public static void NextSection() 102 | { 103 | if (!Articles.ContainsKey(Title)) 104 | return; 105 | 106 | if (Progress >= TotalSize) 107 | return; 108 | 109 | Progress = Math.Min(Progress + SectionSize, TotalSize); 110 | 111 | 112 | } 113 | 114 | public static void PrevSection() 115 | { 116 | if (!Articles.ContainsKey(Title)) 117 | return; 118 | 119 | if (Progress == 0) 120 | return; 121 | 122 | Progress = Math.Max(Progress - SectionSize, 0); 123 | 124 | 125 | } 126 | 127 | public static string GetFormattedCurrentSection() 128 | { 129 | if (!Articles.ContainsKey(Title)) 130 | return ""; 131 | 132 | StringBuilder sb = new StringBuilder(); 133 | sb.Append(Title); 134 | sb.AppendLine(); 135 | string txt = GetCurrentSection(); 136 | sb.Append(txt); 137 | sb.AppendLine(); 138 | sb.Append("-----第"); 139 | sb.Append(Index); 140 | sb.Append("段"); 141 | 142 | 143 | sb.Append("-"); 144 | 145 | sb.Append(" 共"); 146 | sb.Append(MaxIndex); 147 | sb.Append("段 "); 148 | 149 | sb.Append(" 进度 "); 150 | sb.Append((Index - 1) * SectionSize); 151 | sb.Append("/"); 152 | sb.Append(TotalSize); 153 | sb.Append("字 "); 154 | 155 | sb.Append(" 本段"); 156 | sb.Append(new StringInfo(txt).LengthInTextElements); 157 | sb.Append("字 "); 158 | 159 | sb.Append("Pain散播器"); 160 | return sb.ToString(); 161 | 162 | } 163 | 164 | public static string GetFormattedNextSection() 165 | { 166 | 167 | string rt; 168 | if (!Articles.ContainsKey(Title)) 169 | return ""; 170 | else 171 | { 172 | rt = GetFormattedCurrentSection(); 173 | NextSection(); 174 | } 175 | return rt; 176 | } 177 | 178 | public static int Index 179 | { 180 | get 181 | { 182 | if (!Articles.ContainsKey(Title)) 183 | return 1; 184 | else 185 | { 186 | int counter = 0; 187 | 188 | 189 | while (true) 190 | { 191 | if (SectionSize * counter -1 >= Progress) 192 | break; 193 | 194 | counter++; 195 | } 196 | 197 | 198 | return counter; 199 | } 200 | 201 | } 202 | 203 | 204 | } 205 | 206 | public static int TotalSize 207 | { 208 | get 209 | { 210 | return Articles[Title].Text.LengthInTextElements; 211 | } 212 | } 213 | 214 | public static int MaxIndex 215 | { 216 | get 217 | { 218 | if (!Articles.ContainsKey(Title)) 219 | return 1; 220 | else 221 | { 222 | int counter = 0; 223 | 224 | while (true) 225 | { 226 | if (SectionSize * counter - 1 >= TotalSize -1 ) 227 | break; 228 | 229 | counter++; 230 | } 231 | 232 | return counter; 233 | } 234 | 235 | } 236 | 237 | 238 | 239 | } 240 | 241 | public static string Title 242 | { 243 | get 244 | { 245 | return ArticleConfig.GetString("当前文章"); 246 | } 247 | } 248 | 249 | public static int Progress 250 | { 251 | get 252 | { 253 | if (!Articles.ContainsKey(Title)) 254 | return 0; 255 | else 256 | return ArticleConfig.GetInt("进度_" + Title); 257 | } 258 | set 259 | { 260 | if (Articles.ContainsKey(Title)) 261 | { 262 | int v = Math.Min( Math.Max(0, value), TotalSize - 1); 263 | 264 | ArticleConfig.Set("进度_" + Title, v); 265 | ArticleConfig.WriteConfig(500); 266 | 267 | } 268 | 269 | } 270 | } 271 | 272 | public static bool EnableFilter 273 | { 274 | get 275 | { 276 | 277 | return ArticleConfig.GetBool("字集过滤"); 278 | } 279 | set 280 | { 281 | 282 | ArticleConfig.Set("字集过滤" , value); 283 | ArticleConfig.WriteConfig(500); 284 | 285 | 286 | } 287 | } 288 | 289 | public static bool RemoveSpace 290 | { 291 | get 292 | { 293 | 294 | return ArticleConfig.GetBool("去除空格"); 295 | } 296 | set 297 | { 298 | 299 | ArticleConfig.Set("去除空格", value); 300 | ArticleConfig.WriteConfig(500); 301 | 302 | 303 | } 304 | } 305 | 306 | 307 | public static int Search(string text, int startIndex) 308 | { 309 | int rt = -1; 310 | 311 | rt = Articles[Title].Text.String.IndexOf(text,startIndex); 312 | if (rt > 0) 313 | rt = new StringInfo( Articles[Title].Text.String.Substring(0, rt)).LengthInTextElements; 314 | 315 | return rt; 316 | } 317 | 318 | static ArticleManager() 319 | { 320 | ArticleConfig.SetDefault 321 | ( 322 | "每段字数", "200", 323 | "字集过滤", "是", 324 | "去除空格", "是" 325 | 326 | ); 327 | 328 | ArticleConfig.ReadConfig(); 329 | 330 | 331 | } 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /ChangSheng.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Newtonsoft.Json.Linq; 5 | 6 | namespace Net 7 | { 8 | public class ChangSheng 9 | { 10 | private string token = ""; 11 | private string userName; 12 | private string password; 13 | 14 | private int articleId = 666; 15 | private string typeDate = "1970-01-01"; 16 | 17 | public ChangSheng() 18 | { 19 | } 20 | 21 | public ChangSheng(string userName, string password) 22 | { 23 | this.userName = userName; 24 | this.password = password; 25 | InitToken(); 26 | } 27 | 28 | private void InitToken() 29 | { 30 | string url = "https://cl.tyu.wiki/home/login/" + userName + "/" + password; 31 | Dictionary dictionary = Util.DoPost(url); 32 | if (dictionary.ContainsKey("result")) 33 | { 34 | token = (string)dictionary["result"]; 35 | } 36 | } 37 | 38 | public string GetArticle() 39 | { 40 | string url = "https://cl.tyu.wiki/tljMatch/today/" + token + "?isMobile=0"; 41 | Dictionary dictionary = Util.DoGet(url); 42 | string title = ""; 43 | string article = ""; 44 | try 45 | { 46 | title = ((JObject)dictionary["result"])["article"]["title"].ToString(); 47 | article = ((JObject)dictionary["result"])["article"]["content"].ToString(); 48 | articleId = Convert.ToInt32(((JObject)dictionary["result"])["articleId"].ToString()); 49 | typeDate = ((JObject)dictionary["result"])["holdDate"].ToString(); 50 | } 51 | catch (Exception) 52 | { 53 | return article; 54 | } 55 | 56 | return title + "\r\n" + article + "\r\n" + "-----第0段-" + title; 57 | } 58 | 59 | /** 60 | * @param 61 | * deleteNum 退格 62 | * deleteText 回改 63 | * keyAccuracy 键准 64 | * keyLength 键数 65 | * keyMethod 键法 66 | * keySpeed 击键 67 | * mistake 错字 68 | * number 字数 69 | * repeatNum 选重 70 | * speed 速度 71 | * time 用时 72 | * wordRate 打词率 73 | */ 74 | public string SendScore(int deleteNum, int deleteText, double keyAccuracy, double keyLength, double keyMethod, 75 | double keySpeed, int mistake, int number, int repeatNum, double speed, double time, double wordRate) 76 | { 77 | string url = "https://cl.tyu.wiki/tljMatch/uploadTljMatchAch/" + token; 78 | 79 | keyAccuracy = Math.Round(keyAccuracy, 2); 80 | keyLength = Math.Round(keyLength, 2); 81 | keyMethod = Math.Round(keyMethod, 2); 82 | keySpeed = Math.Round(keySpeed, 2); 83 | speed = Math.Round(speed, 2); 84 | time = Math.Round(time, 3); 85 | wordRate = Math.Round(wordRate, 2); 86 | 87 | StringBuilder sb = new StringBuilder(); 88 | sb.Append("{"); 89 | sb.Append("\"articleId\":").Append(articleId).Append(","); 90 | sb.Append("\"deleteNum\":").Append(deleteNum).Append(","); 91 | sb.Append("\"deleteText\":").Append(deleteText).Append(","); 92 | sb.Append("\"keyAccuracy\":").Append(keyAccuracy).Append(","); 93 | sb.Append("\"keyLength\":").Append(keyLength).Append(","); 94 | sb.Append("\"keyMethod\":").Append(keyMethod).Append(","); 95 | sb.Append("\"keySpeed\":").Append(keySpeed).Append(","); 96 | sb.Append("\"mistake\":").Append(mistake).Append(","); 97 | sb.Append("\"mobile\":").Append("false").Append(","); 98 | sb.Append("\"number\":").Append(number).Append(","); 99 | sb.Append("\"paragraph\":").Append(0).Append(","); 100 | sb.Append("\"repeatNum\":").Append(repeatNum).Append(","); 101 | sb.Append("\"speed\":").Append(speed).Append(","); 102 | sb.Append("\"time\":").Append(time).Append(","); 103 | sb.Append("\"typeDate\":").Append("\"").Append(typeDate).Append("\"").Append(","); 104 | sb.Append("\"wordRate\":").Append(wordRate); 105 | sb.Append("}"); 106 | string content = sb.ToString(); 107 | 108 | string message = "请求异常"; 109 | Dictionary dictionary = Util.DoPost(url, content); 110 | if (dictionary.ContainsKey("message")) 111 | { 112 | message = (string)dictionary["message"]; 113 | } 114 | 115 | return message; 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /Colors.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.Media; 7 | 8 | 9 | namespace TypeB 10 | { 11 | static internal class Colors 12 | { 13 | 14 | public static SolidColorBrush DisplayForeground; 15 | public static SolidColorBrush CorrectBackground; 16 | public static SolidColorBrush IncorrectBackground; 17 | 18 | public static SolidColorBrush FromString (string str) 19 | { 20 | return new SolidColorBrush((Color)ColorConverter.ConvertFromString("#" + str)); 21 | 22 | } 23 | 24 | public static SolidColorBrush[] Levels = 25 | { 26 | Brushes.Crimson, 27 | Brushes.HotPink, 28 | Brushes.BlueViolet, 29 | Brushes.RoyalBlue, 30 | Brushes.ForestGreen, 31 | Brushes.Gray 32 | }; 33 | 34 | public static SolidColorBrush GetAccColor(double? accuracy) 35 | { 36 | if (accuracy == null) 37 | { 38 | return null; 39 | } 40 | 41 | int index = (int)(Score.GetAccuracy() * 100) - 94; 42 | 43 | if (index < 0) index = 0; 44 | if (index > 5) index = 5; 45 | 46 | index = 5 - index; 47 | 48 | return Levels[index]; 49 | } 50 | 51 | 52 | 53 | 54 | 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Config.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.IO; 7 | using System.Windows.Automation.Peers; 8 | using System.Configuration; 9 | using System.Threading; 10 | using System.Windows.Threading; 11 | using System.Reflection; 12 | 13 | namespace TypeB 14 | { 15 | static internal class Config 16 | { 17 | static public Dictionary dicts = new Dictionary(); 18 | static public string Path = "config.txt"; 19 | 20 | static public void SetDefault(params string[] args) 21 | { 22 | for (int i = 0; i + 1 < args.Length; i+=2) 23 | { 24 | dicts[args[i]] = args[i+1]; 25 | } 26 | 27 | } 28 | 29 | 30 | static private Timer WriteTimer = null; 31 | 32 | 33 | static private void WriteNow(object obj) 34 | { 35 | 36 | if (Path == "") 37 | return; 38 | 39 | try 40 | { 41 | StreamWriter sw = new StreamWriter(Path); 42 | 43 | foreach (var c in dicts) 44 | { 45 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 46 | } 47 | 48 | 49 | sw.Close(); 50 | if (WriteTimer != null) 51 | { 52 | WriteTimer.Dispose(); 53 | WriteTimer = null; 54 | } 55 | } 56 | catch (Exception) 57 | { 58 | 59 | 60 | } 61 | finally 62 | { 63 | 64 | } 65 | 66 | 67 | 68 | 69 | } 70 | 71 | static public void WriteConfig (int Delay = 0) 72 | { 73 | 74 | if (Path == "") 75 | return; 76 | 77 | try 78 | { 79 | if (Delay == 0) 80 | { 81 | if (WriteTimer != null) 82 | { 83 | WriteTimer.Dispose(); 84 | WriteTimer = null; 85 | } 86 | 87 | StreamWriter sw = new StreamWriter(Path); 88 | 89 | foreach (var c in dicts) 90 | { 91 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 92 | } 93 | 94 | 95 | sw.Close(); 96 | } 97 | else if (Delay > 0) 98 | { 99 | if (WriteTimer == null) 100 | { 101 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 102 | } 103 | else 104 | { 105 | WriteTimer.Dispose(); 106 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 107 | // WriteTimer.Change(Delay, Timeout.Infinite); 108 | 109 | } 110 | } 111 | } 112 | catch (Exception) 113 | { 114 | 115 | 116 | } 117 | finally { } 118 | 119 | 120 | } 121 | 122 | static public void ReadConfig () 123 | { 124 | // char[] sp = { '\r', ' ', '\t' }; 125 | 126 | if (!File.Exists(Path)) 127 | { 128 | WriteConfig(); 129 | return; 130 | } 131 | 132 | char[] sp1 = { '\n' }; 133 | 134 | string[] lines = File.ReadAllText(Path).Split(sp1, StringSplitOptions.RemoveEmptyEntries); 135 | 136 | 137 | foreach (string line in lines) 138 | { 139 | if (line.Substring(0, 1) == "#") 140 | continue; 141 | string line_p = line.Replace("\r", "").Replace("\n", ""); 142 | 143 | string[] sp = { "\t", " ", "," }; 144 | 145 | 146 | 147 | foreach (string s in sp) 148 | { 149 | if (line_p.Contains(s)) 150 | { 151 | int pos = line_p.IndexOf(s); 152 | if (pos >= 1 && pos <= line_p.Length - 2) 153 | { 154 | string key = line_p.Substring(0, pos); 155 | string value = line_p.Substring(pos + 1); 156 | dicts[key] = value; 157 | break; 158 | } 159 | } 160 | } 161 | 162 | 163 | 164 | } 165 | 166 | 167 | WriteConfig(); 168 | 169 | 170 | 171 | } 172 | 173 | static public bool GetBool (string key) 174 | { 175 | if (dicts.ContainsKey(key) && dicts[key] == "是") 176 | return true; 177 | else 178 | return false; 179 | } 180 | static public string GetString(string key) 181 | { 182 | if (dicts.ContainsKey(key)) 183 | return dicts[key]; 184 | else 185 | return ""; 186 | } 187 | 188 | static public int GetInt(string key) 189 | { 190 | if (dicts.ContainsKey(key) && Int32.TryParse(dicts[key], out int num)) 191 | return num; 192 | else 193 | return 0; 194 | } 195 | 196 | 197 | static public double GetDouble(string key) 198 | { 199 | if (dicts.ContainsKey(key) && Double.TryParse(dicts[key], out double num)) 200 | return num; 201 | else 202 | return 0; 203 | } 204 | 205 | static public void Set (string key, bool value) 206 | { 207 | if (value) 208 | dicts[key] = "是"; 209 | else 210 | dicts[key] = "否"; 211 | 212 | WriteConfig(3000); 213 | } 214 | static public void Set(string key, int value) 215 | { 216 | dicts[key] = value.ToString() ; 217 | WriteConfig(3000); 218 | } 219 | 220 | static public void Set(string key, string value) 221 | { 222 | dicts[key] = value; 223 | WriteConfig(3000); 224 | } 225 | 226 | static public void Set(string key, double value, int fraction = -1) 227 | { 228 | string f = "F" + fraction.ToString(); 229 | if (fraction > 0) 230 | dicts[key] = value.ToString(f); 231 | else 232 | dicts[key] = value.ToString(); 233 | 234 | WriteConfig(3000); 235 | 236 | } 237 | } 238 | 239 | 240 | 241 | } 242 | -------------------------------------------------------------------------------- /CounterLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace LibB 9 | { 10 | static internal class CounterLog 11 | { 12 | static public string Path = "统计.txt"; 13 | static public string SumKey = "合计"; 14 | static public int HourThresh = 6; 15 | static public bool Loaded = false; 16 | static private Dictionary> Dict = new Dictionary>(); 17 | static public int[] Buffer = new int[1000]; 18 | 19 | 20 | public static int GetCurrent(string key) 21 | { 22 | if (!Loaded) 23 | Read(); 24 | 25 | int hour = DateTime.Now.Hour; 26 | 27 | string date = ""; 28 | if (hour < HourThresh) 29 | date = DateTime.Now.AddDays(-1).ToString("d"); 30 | else 31 | date = DateTime.Now.ToString("d"); 32 | 33 | 34 | if (!Dict.ContainsKey(date)) 35 | { 36 | Dict[date] = new Dictionary(); 37 | } 38 | 39 | if (!Dict[date].ContainsKey(key)) 40 | Dict[date].Add(key, 0); 41 | 42 | 43 | Write(); 44 | return Dict[date][key]; 45 | } 46 | 47 | public static int GetSum(string key) 48 | { 49 | if (!Dict.ContainsKey(SumKey)) 50 | { 51 | Dict[SumKey] = new Dictionary(); 52 | } 53 | 54 | if (!Dict[SumKey].ContainsKey(key)) 55 | Dict[SumKey].Add(key, 0); 56 | 57 | 58 | return Dict[SumKey][key]; 59 | } 60 | static public void Add(string key, int value) 61 | { 62 | if (!Loaded) 63 | Read(); 64 | 65 | int hour = DateTime.Now.Hour; 66 | 67 | string date = ""; 68 | if (hour < HourThresh) 69 | date = DateTime.Now.AddDays(-1).ToString("d"); 70 | else 71 | date = DateTime.Now.ToString("d"); 72 | 73 | 74 | if (!Dict.ContainsKey(date)) 75 | { 76 | Dict[date] = new Dictionary(); 77 | } 78 | 79 | if (!Dict[date].ContainsKey(key)) 80 | Dict[date].Add(key, value); 81 | else 82 | Dict[date][key] = Dict[date][key] + value; 83 | 84 | if (!Dict.ContainsKey(SumKey)) 85 | { 86 | Dict[SumKey] = new Dictionary(); 87 | } 88 | 89 | if (!Dict[SumKey].ContainsKey(key)) 90 | Dict[SumKey].Add(key, value); 91 | else 92 | Dict[SumKey][key] = Dict[SumKey][key] + value; 93 | 94 | Write(); 95 | 96 | } 97 | 98 | static private void Read() 99 | { 100 | Loaded = true; 101 | 102 | if (!File.Exists(Path)) 103 | return; 104 | 105 | string txt = File.ReadAllText(Path).Replace("\r", ""); 106 | string[] lines = txt.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); 107 | 108 | 109 | string date = ""; 110 | foreach (string line in lines) 111 | { 112 | string[] ls = line.Split(new char[] { '\t', ' ', ',', ',' }, StringSplitOptions.RemoveEmptyEntries); 113 | 114 | if (ls.Length == 1) 115 | { 116 | Dict[ls[0]] = new Dictionary(); 117 | date = ls[0]; 118 | } 119 | else if (ls.Length >= 2) 120 | { 121 | Int32.TryParse(ls[1], out int value); 122 | if (value > 0) 123 | Dict[date][ls[0]] = value; 124 | } 125 | } 126 | 127 | } 128 | 129 | static public void Write() 130 | { 131 | 132 | if (!Loaded) 133 | Read(); 134 | 135 | try 136 | { 137 | StreamWriter sw = new StreamWriter(Path); 138 | 139 | 140 | Dictionary sum = new Dictionary(); 141 | 142 | 143 | if (Dict.ContainsKey(SumKey)) 144 | { 145 | sw.WriteLine(SumKey); 146 | foreach (var Record in Dict[SumKey]) 147 | sw.WriteLine(Record.Key + "\t" + Record.Value); 148 | } 149 | sw.WriteLine(); 150 | 151 | foreach (var DayRecord in Dict) 152 | { 153 | if (DayRecord.Key == SumKey) 154 | continue; 155 | 156 | sw.WriteLine(DayRecord.Key); 157 | foreach (var Record in DayRecord.Value) 158 | sw.WriteLine(Record.Key + "\t" + Record.Value); 159 | 160 | 161 | } 162 | sw.WriteLine(); 163 | 164 | sw.Close(); 165 | } 166 | catch (Exception) 167 | { 168 | 169 | 170 | } 171 | finally 172 | { 173 | 174 | } 175 | 176 | } 177 | } 178 | 179 | } 180 | -------------------------------------------------------------------------------- /DebugLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace TypeB 5 | { 6 | 7 | static internal class DebugLog 8 | { 9 | static public string Path = "log.txt"; 10 | static public bool Enable = false; 11 | 12 | static public void AppendLine(string text) 13 | { 14 | if (Enable) 15 | { 16 | string t = "[" + DateTime.Now.ToString("g") + "]: " + text + "\n"; 17 | File.AppendAllText(Path, t); 18 | } 19 | 20 | 21 | } 22 | 23 | static public void AppendSection(string name, string text) 24 | { 25 | if (Enable) 26 | { 27 | string split = "\n**************************\n"; 28 | string t = "[" + DateTime.Now.ToString("g") + "]: " + name + split + text + split + "\n"; 29 | File.AppendAllText(Path, t); 30 | } 31 | 32 | } 33 | 34 | static public void a(string text) 35 | { 36 | if (Enable) 37 | { 38 | AppendLine(text); 39 | } 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /Diff/DiffNode.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 Diff 8 | { 9 | class DiffNode : PathNode 10 | { 11 | public DiffNode(int i, int j, PathNode prev) : base(i, j, prev) { } 12 | 13 | public override bool IsSnake() 14 | { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Diff/DiffRes.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 Diff 8 | { 9 | public enum DiffType {Add, Delete, None}; 10 | public class DiffRes 11 | { 12 | private DiffType type; 13 | public DiffType Type 14 | { 15 | get { return type; } 16 | set { type = value; } 17 | } 18 | private int origIndex; 19 | private int revIndex; 20 | public int OrigIndex 21 | { 22 | get { return origIndex; } 23 | set { origIndex = value; } 24 | } 25 | 26 | public int RevIndex 27 | { 28 | get { return revIndex; } 29 | set { revIndex = value; } 30 | } 31 | 32 | public DiffRes(DiffType type, int origIndex, int revIndex) 33 | { 34 | Type = type; 35 | OrigIndex = origIndex; 36 | RevIndex = revIndex; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Diff/GroupedDiffRes.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 Diff 8 | { 9 | public class GroupedDiffRes 10 | { 11 | private int rangeStart; 12 | private int rangeEnd; 13 | private DiffType type; 14 | 15 | public int RangeStart { get => rangeStart; set => rangeStart = value; } 16 | public int RangeEnd { get => rangeEnd; set => rangeEnd = value; } 17 | public DiffType Type { get => type; set => type = value; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Diff/PartSplitedDiffRes.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 Diff 8 | { 9 | class PartSplitedDiffRes 10 | { 11 | private int index; 12 | 13 | public int Index { get => index; set => index = value; } 14 | 15 | public PartSplitedDiffRes(int index) 16 | { 17 | Index = index; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Diff/PathNode.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 Diff 8 | { 9 | public abstract class PathNode 10 | { 11 | public int i; 12 | public int j; 13 | public PathNode prev; 14 | 15 | public PathNode(int i, int j, PathNode prev) 16 | { 17 | this.i = i; 18 | this.j = j; 19 | this.prev = prev; 20 | } 21 | 22 | public abstract bool IsSnake(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Diff/Snake.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 Diff 8 | { 9 | class Snake : PathNode 10 | { 11 | public Snake(int i, int j, PathNode prev) : base(i, j, prev) { } 12 | public override bool IsSnake() 13 | { 14 | return true; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Diff/SplitedDiffRes.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 Diff 8 | { 9 | public enum SplitedDiffType { Add, Delete, None, Modify } 10 | public class SplitedDiffRes 11 | { 12 | private int origIndex; 13 | private int revIndex; 14 | private SplitedDiffType type; 15 | 16 | public int OrigIndex { get => origIndex; set => origIndex = value; } 17 | public int RevIndex { get => revIndex; set => revIndex = value; } 18 | public SplitedDiffType Type { get => type; set => type = value; } 19 | 20 | public SplitedDiffRes(int origIndex, int revIndex, SplitedDiffType type) 21 | { 22 | OrigIndex = origIndex; 23 | RevIndex = revIndex; 24 | Type = type; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /DiffNode.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 Diff 8 | { 9 | class DiffNode : PathNode 10 | { 11 | public DiffNode(int i, int j, PathNode prev) : base(i, j, prev) { } 12 | 13 | public override bool IsSnake() 14 | { 15 | return false; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /DiffRes.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 Diff 8 | { 9 | public enum DiffType {Add, Delete, None}; 10 | public class DiffRes 11 | { 12 | private DiffType type; 13 | public DiffType Type 14 | { 15 | get { return type; } 16 | set { type = value; } 17 | } 18 | private int origIndex; 19 | private int revIndex; 20 | public int OrigIndex 21 | { 22 | get { return origIndex; } 23 | set { origIndex = value; } 24 | } 25 | 26 | public int RevIndex 27 | { 28 | get { return revIndex; } 29 | set { revIndex = value; } 30 | } 31 | 32 | public DiffRes(DiffType type, int origIndex, int revIndex) 33 | { 34 | Type = type; 35 | OrigIndex = origIndex; 36 | RevIndex = revIndex; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /GroupedDiffRes.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 Diff 8 | { 9 | public class GroupedDiffRes 10 | { 11 | private int rangeStart; 12 | private int rangeEnd; 13 | private DiffType type; 14 | 15 | public int RangeStart { get => rangeStart; set => rangeStart = value; } 16 | public int RangeEnd { get => rangeEnd; set => rangeEnd = value; } 17 | public DiffType Type { get => type; set => type = value; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /IntStringDict.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.IO; 7 | 8 | namespace TypeB 9 | { 10 | static internal class IntStringDict 11 | { 12 | static public Dictionary BiaoDing = new Dictionary(); 13 | static public Dictionary Selection = new Dictionary(); 14 | 15 | static private Dictionary DefautlBiaoDing = new Dictionary 16 | { 17 | {48, "))"}, 18 | {49, "!!"}, 19 | {50, "@"}, 20 | {51, "#"}, 21 | {52, "¥$"}, 22 | {53, "%"}, 23 | {54, "……^"}, 24 | {55, "&"}, 25 | {56, "*"}, 26 | {57, "(("}, 27 | {186, ";:;:"}, 28 | {187, "+="}, 29 | {188, ",《,<"}, 30 | {189, "——-_"}, 31 | {190, "。》.>"}, 32 | {191, "?/?、"}, 33 | {192, "·`~"}, 34 | {219, "【[{"}, 35 | {220, "、\\|"}, 36 | {221, "】]}"}, 37 | {222, "“”‘’\"'"}, 38 | }; 39 | static private Dictionary DefautlSelection = new Dictionary 40 | { 41 | {48, "))0"}, 42 | {49, "!!"}, 43 | {50, "@2"}, 44 | {51, "#3"}, 45 | {52, "¥$4"}, 46 | {53, "%5"}, 47 | {54, "……^6"}, 48 | {55, "&7"}, 49 | {56, "*8"}, 50 | {57, "((9"}, 51 | {186, ";:;:"}, 52 | {187, "+="}, 53 | {188, ",《,<"}, 54 | {189, "—-_"}, 55 | {190, "。》.>"}, 56 | {191, "?/?、"}, 57 | {192, "·`~"}, 58 | {219, "【[{"}, 59 | {220, "、\\|"}, 60 | {221, "】]}"}, 61 | {222, "“”‘’\"'"}, 62 | }; 63 | 64 | 65 | static public void Load() 66 | { 67 | BiaoDing = Read("标顶键符映射.txt", DefautlBiaoDing); 68 | Selection = Read("选重键符映射.txt", DefautlSelection); 69 | 70 | } 71 | 72 | static private Dictionary Read (string path, Dictionary defautDict) 73 | { 74 | 75 | Dictionary outDict = new Dictionary(); 76 | 77 | if (File.Exists (path)) 78 | { 79 | string txt = File.ReadAllText (path).Replace ("\r\n", "\n"); 80 | string[]lines = txt.Split (new char[] {'\n'}, StringSplitOptions.RemoveEmptyEntries); 81 | 82 | foreach (string line in lines) 83 | { 84 | string[] ls = line.Split(new char[] { '\t' }, StringSplitOptions.RemoveEmptyEntries); ; 85 | if (ls.Length == 1) 86 | { 87 | Int32.TryParse(ls[0], out int val); 88 | if (val > 0) 89 | outDict.Add(val, ""); 90 | 91 | } 92 | else if (ls.Length >= 2) 93 | { 94 | Int32.TryParse(ls[0], out int val); 95 | if (val > 0) 96 | outDict.Add(val, ls[1]); 97 | } 98 | } 99 | 100 | } 101 | else //不存在文件 102 | { 103 | outDict = defautDict; 104 | StreamWriter sw = new StreamWriter(path); 105 | foreach(var v in outDict) 106 | sw.WriteLine(v.Key + "\t" + v.Value); 107 | 108 | sw.Close(); 109 | } 110 | 111 | return outDict; 112 | } 113 | 114 | static public Dictionary ReadTmp(string path, Dictionary defautDict) 115 | { 116 | 117 | Dictionary outDict = new Dictionary(); 118 | 119 | 120 | foreach(var v in defautDict) 121 | { 122 | if (outDict.ContainsKey(v.Value)) 123 | outDict[v.Value] = outDict[v.Value] + v.Key; 124 | else 125 | outDict.Add(v.Value, v.Key); 126 | outDict = outDict.OrderBy(o=>o.Key).ToDictionary(o=>o.Key, o => o.Value); 127 | } 128 | { 129 | 130 | StreamWriter sw = new StreamWriter(path); 131 | foreach (var v in outDict) 132 | sw.WriteLine("{"+v.Key + ", " + "\""+v.Value + "\"},"); 133 | sw.Close(); 134 | } 135 | 136 | return outDict; 137 | } 138 | 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /Paginator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace TypeB 5 | { 6 | 7 | class Page 8 | { 9 | public int HeadStart = -1; 10 | public int HeadEnd = -1; 11 | public int BodyStart = -1; 12 | public int BodyEnd = -1; 13 | public int FootStart = -1; 14 | public int FootEnd = -1; 15 | 16 | 17 | } 18 | static class Paginator 19 | { 20 | public static int WordsNum = 0; 21 | 22 | public static List Pages = new List(); 23 | private static int PageSize = 0; 24 | 25 | 26 | 27 | 28 | public static int nx, ny; 29 | 30 | public static void ArrangePage(double x, double y, double fontsize, int wordnum) 31 | { 32 | Pages.Clear(); 33 | 34 | if (wordnum <= 0) 35 | return; 36 | 37 | 38 | nx = Convert.ToInt32(Math.Floor((x - 20) / (fontsize + 0) -0.5 )); 39 | ny = Convert.ToInt32(Math.Floor((y - 10 ) / (fontsize * (Config.GetDouble("行距") + 1))) ) ; 40 | 41 | //至少三行一列 42 | if (nx < 3) 43 | nx = 3; 44 | if (ny < 3) 45 | ny = 3; 46 | 47 | 48 | PageSize = nx * ny; 49 | if (Config.GetBool("允许滚动")) 50 | PageSize = 1000; 51 | //首页 52 | 53 | 54 | int headsize = 2; 55 | int footsize = nx /2 ; 56 | int bodysize = PageSize - headsize - footsize; 57 | 58 | 59 | if (wordnum <= PageSize) //单页 60 | { 61 | Page p0 = new Page(); 62 | p0.BodyStart = 0; 63 | p0.BodyEnd = wordnum - 1; 64 | 65 | Pages.Add(p0); 66 | } 67 | else 68 | { 69 | //第一页 70 | Page p0 = new Page(); 71 | p0.BodyStart = 0; 72 | p0.BodyEnd = bodysize + headsize - 1; 73 | p0.FootStart = p0.BodyEnd + 1; 74 | p0.FootEnd = Math.Min(p0.FootStart + footsize - 1, wordnum - 1); 75 | 76 | 77 | Pages.Add(p0); 78 | 79 | for (int i = 1; i < wordnum; i++) 80 | { 81 | 82 | 83 | Page p = new Page(); 84 | p.HeadStart = Pages[i - 1].BodyEnd - headsize + 1; 85 | p.HeadEnd = Pages[i - 1].BodyEnd; 86 | 87 | 88 | 89 | if (p.HeadStart + PageSize - 1 >= wordnum - 1) //最后一页 90 | { 91 | p.BodyStart = p.HeadEnd + 1; 92 | p.BodyEnd = wordnum - 1; 93 | Pages.Add(p); 94 | break; 95 | } 96 | else 97 | { 98 | p.BodyStart = p.HeadEnd + 1; 99 | p.BodyEnd = p.BodyStart + bodysize - 1; 100 | p.FootStart = p.BodyEnd + 1; 101 | p.FootEnd = Math.Min(p.FootStart + footsize - 1, wordnum - 1); 102 | Pages.Add(p); 103 | } 104 | 105 | 106 | } 107 | 108 | } 109 | 110 | 111 | 112 | } 113 | 114 | public static Tuple GetRenderRange(int index) 115 | { 116 | int start = -1; 117 | int end = -1; 118 | 119 | 120 | 121 | 122 | int pagenum = GetPageNum(index); 123 | if (pagenum >= 0) 124 | { 125 | Page p = Pages[pagenum]; 126 | 127 | if (p.HeadStart >= 0) 128 | start = p.HeadStart; 129 | else 130 | start = p.BodyStart; 131 | 132 | if (p.FootEnd >= 0) 133 | end = p.FootEnd; 134 | else 135 | end = p.BodyEnd; 136 | 137 | } 138 | 139 | return new Tuple(start, end); 140 | 141 | 142 | } 143 | public static int GetPageNum(int index) 144 | { 145 | 146 | 147 | int pos = -1; 148 | 149 | for (int i = 0; i < Pages.Count; i++) 150 | { 151 | 152 | if (index >= Pages[i].BodyStart && index <= Pages[i].BodyEnd) 153 | { 154 | pos = i; 155 | } 156 | } 157 | 158 | 159 | return pos; 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /PartSplitedDiffRes.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 Diff 8 | { 9 | class PartSplitedDiffRes 10 | { 11 | private int index; 12 | 13 | public int Index { get => index; set => index = value; } 14 | 15 | public PartSplitedDiffRes(int index) 16 | { 17 | Index = index; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /PathNode.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 Diff 8 | { 9 | public abstract class PathNode 10 | { 11 | public int i; 12 | public int j; 13 | public PathNode prev; 14 | 15 | public PathNode(int i, int j, PathNode prev) 16 | { 17 | this.i = i; 18 | this.j = j; 19 | this.prev = prev; 20 | } 21 | 22 | public abstract bool IsSnake(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Recorder.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; 7 | using System.Threading.Tasks; 8 | using System.Windows.Input; 9 | using System.Windows.Media; 10 | 11 | namespace TypeB 12 | { 13 | static internal class Recorder 14 | { 15 | public enum RecorderState 16 | { 17 | Stopped = 0, 18 | Recording = 1, 19 | Playing = 2 20 | } 21 | public struct RecItem 22 | { 23 | public int key; 24 | public long time; 25 | public int keystate; 26 | public int modifier; 27 | 28 | } 29 | 30 | static public RecorderState State = RecorderState.Stopped; 31 | static Stopwatch Rs = new Stopwatch(); 32 | static public List RecItems = new List< RecItem> (); 33 | 34 | static public void Start() 35 | { 36 | if (State !=Recorder.RecorderState.Playing) 37 | { 38 | Rs.Start(); 39 | State = RecorderState.Recording; 40 | } 41 | 42 | } 43 | static public void Reset() 44 | { 45 | if (State != Recorder.RecorderState.Playing) 46 | { 47 | RecItems.Clear(); 48 | Rs.Reset(); 49 | // Rs.Stop(); 50 | State = Recorder.RecorderState.Stopped; 51 | } 52 | } 53 | 54 | static public void Stop () 55 | { 56 | if (State != Recorder.RecorderState.Playing) 57 | { 58 | Rs.Stop(); 59 | State = Recorder.RecorderState.Stopped; 60 | } 61 | 62 | } 63 | 64 | 65 | 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /RetypeCouner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using static TypeB.MainWindow; 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | namespace TypeB 16 | { 17 | 18 | static internal class RetypeCounter 19 | { 20 | static public string Path = "RetypeCounter20230804.txt"; 21 | // static public string SumKey = "合计"; 22 | static public int HourThresh = 6; 23 | static public bool Loaded = false; 24 | static private Dictionary> Dict = new Dictionary>(); 25 | static public int[] Buffer = new int[1000]; 26 | 27 | 28 | 29 | 30 | /* 31 | static public void Add(string key, int value) 32 | { 33 | 34 | 35 | 36 | 37 | if (!Loaded) 38 | Read(); 39 | 40 | int hour = DateTime.Now.Hour; 41 | 42 | string date = ""; 43 | if (hour < HourThresh) 44 | date = DateTime.Now.AddDays(-1).ToString("d"); 45 | else 46 | date = DateTime.Now.ToString("d"); 47 | 48 | 49 | if (!Dict.ContainsKey(date)) 50 | { 51 | Dict[date] = new Dictionary(); 52 | } 53 | 54 | if (!Dict[date].ContainsKey(key)) 55 | Dict[date].Add(key, value); 56 | else 57 | Dict[date][key] = Dict[date][key] + value; 58 | 59 | if (!Dict.ContainsKey(SumKey)) 60 | { 61 | Dict[SumKey] = new Dictionary(); 62 | } 63 | 64 | if (!Dict[SumKey].ContainsKey(key)) 65 | Dict[SumKey].Add(key, value); 66 | else 67 | Dict[SumKey][key] = Dict[SumKey][key] + value; 68 | 69 | Write(); 70 | 71 | } 72 | */ 73 | static public void Add(string key, int value) 74 | { 75 | 76 | 77 | 78 | 79 | if (!Loaded) 80 | Read(); 81 | 82 | int hour = DateTime.Now.Hour; 83 | 84 | string date = ""; 85 | if (hour < HourThresh) 86 | date = DateTime.Now.AddDays(-1).ToString("d"); 87 | else 88 | date = DateTime.Now.ToString("d"); 89 | 90 | 91 | if (!Dict.ContainsKey(date)) 92 | { 93 | Dict.Clear(); 94 | Dict[date] = new Dictionary(); 95 | } 96 | 97 | if (!Dict[date].ContainsKey(key)) 98 | Dict[date].Add(key, value); 99 | else 100 | Dict[date][key] = Dict[date][key] + value; 101 | 102 | 103 | 104 | Write(); 105 | 106 | } 107 | 108 | 109 | static public int Get(string key) 110 | { 111 | 112 | 113 | if (!Loaded) 114 | Read(); 115 | 116 | int hour = DateTime.Now.Hour; 117 | 118 | string date = ""; 119 | if (hour < HourThresh) 120 | date = DateTime.Now.AddDays(-1).ToString("d"); 121 | else 122 | date = DateTime.Now.ToString("d"); 123 | 124 | 125 | if (!Dict.ContainsKey(date)) 126 | return 0; 127 | else if (!Dict[date].ContainsKey(key)) 128 | return 0; 129 | else 130 | return Dict[date][key]; 131 | 132 | 133 | 134 | } 135 | 136 | static private void Read() 137 | { 138 | try 139 | { 140 | Loaded = true; 141 | string folder = Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile); 142 | 143 | string fullpath = folder + "\\" + Path; 144 | if (!File.Exists(fullpath)) 145 | return; 146 | 147 | string txt = File.ReadAllText(fullpath).Replace("\r", ""); 148 | string[] lines = txt.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); 149 | 150 | 151 | string date = ""; 152 | foreach (string line in lines) 153 | { 154 | string[] ls = line.Split(new char[] { '\t', ' ', ',', ',' }, StringSplitOptions.RemoveEmptyEntries); 155 | 156 | if (ls.Length == 1) 157 | { 158 | Dict[ls[0]] = new Dictionary(); 159 | date = ls[0]; 160 | } 161 | else if (ls.Length >= 2) 162 | { 163 | Int32.TryParse(ls[1], out int value); 164 | if (value > 0) 165 | Dict[date][ls[0]] = value; 166 | } 167 | } 168 | 169 | } 170 | catch (Exception) 171 | { 172 | 173 | Dict.Clear(); 174 | Loaded = true; 175 | } 176 | 177 | } 178 | /* 179 | static public void Write1() 180 | { 181 | 182 | string folder = Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile); 183 | 184 | string fullpath = folder + "\\" + Path; 185 | 186 | StreamWriter sw = new StreamWriter(fullpath); 187 | 188 | 189 | 190 | 191 | 192 | 193 | Dictionary sum = new Dictionary(); 194 | 195 | 196 | if (Dict.ContainsKey(SumKey)) 197 | { 198 | sw.WriteLine(SumKey); 199 | foreach (var Record in Dict[SumKey]) 200 | sw.WriteLine(Record.Key + "\t" + Record.Value); 201 | } 202 | sw.WriteLine(); 203 | 204 | foreach (var DayRecord in Dict) 205 | { 206 | if (DayRecord.Key == SumKey) 207 | continue; 208 | 209 | sw.WriteLine(DayRecord.Key); 210 | foreach (var Record in DayRecord.Value) 211 | sw.WriteLine(Record.Key + "\t" + Record.Value); 212 | 213 | 214 | } 215 | sw.WriteLine(); 216 | 217 | sw.Close(); 218 | } 219 | 220 | */ 221 | static public void Write() 222 | { 223 | 224 | try 225 | { 226 | string folder = Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile); 227 | 228 | string fullpath = folder + "\\" + Path; 229 | 230 | StreamWriter sw = new StreamWriter(fullpath); 231 | 232 | 233 | 234 | 235 | int hour = DateTime.Now.Hour; 236 | 237 | string date = ""; 238 | if (hour < HourThresh) 239 | date = DateTime.Now.AddDays(-1).ToString("d"); 240 | else 241 | date = DateTime.Now.ToString("d"); 242 | 243 | 244 | 245 | foreach (var DayRecord in Dict) 246 | { 247 | if (DayRecord.Key != date) 248 | continue; 249 | 250 | sw.WriteLine(DayRecord.Key); 251 | foreach (var Record in DayRecord.Value) 252 | sw.WriteLine(Record.Key + "\t" + Record.Value); 253 | 254 | 255 | } 256 | sw.WriteLine(); 257 | 258 | sw.Close(); 259 | } 260 | catch (Exception) 261 | { 262 | 263 | 264 | } 265 | 266 | } 267 | } 268 | 269 | 270 | } 271 | -------------------------------------------------------------------------------- /Sender.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net.Http; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace Net 9 | { 10 | public class Sender 11 | { 12 | private static HttpClient client = new HttpClient(); 13 | private static int WaitingTime = 5000; 14 | 15 | public static void SetWaitingTime(int milliseconds) => Sender.WaitingTime = milliseconds; 16 | 17 | public static string Get(string url) 18 | { 19 | url = Sender.FixUrl(url); 20 | Task async = Sender.client.GetAsync(url); 21 | try 22 | { 23 | return Sender.RunTask(async); 24 | } 25 | catch (Exception ex) 26 | { 27 | throw ex; 28 | } 29 | } 30 | 31 | public static string Post(string url, string content) 32 | { 33 | url = Sender.FixUrl(url); 34 | StreamContent content1 = new StreamContent((Stream)new MemoryStream(Encoding.UTF8.GetBytes(content))); 35 | content1.Headers.Add("Content-Type", "application/json;charset=utf8"); 36 | Task task = Sender.client.PostAsync(url, (HttpContent)content1); 37 | try 38 | { 39 | return Sender.RunTask(task); 40 | } 41 | catch (Exception ex) 42 | { 43 | throw ex; 44 | } 45 | } 46 | 47 | public static string Post(string url, Dictionary content) 48 | { 49 | url = Sender.FixUrl(url); 50 | Task task = Sender.client.PostAsync(url, 51 | (HttpContent)new FormUrlEncodedContent((IEnumerable>)content)); 52 | try 53 | { 54 | return Sender.RunTask(task); 55 | } 56 | catch (Exception ex) 57 | { 58 | throw ex; 59 | } 60 | } 61 | 62 | public static string Put(string url) 63 | { 64 | url = Sender.FixUrl(url); 65 | Task task = Sender.client.PutAsync(url, (HttpContent)null); 66 | try 67 | { 68 | return Sender.RunTask(task); 69 | } 70 | catch (Exception ex) 71 | { 72 | throw ex; 73 | } 74 | } 75 | 76 | public static string Put(string url, Dictionary content) 77 | { 78 | url = Sender.FixUrl(url); 79 | Task task = Sender.client.PutAsync(url, 80 | (HttpContent)new FormUrlEncodedContent((IEnumerable>)content)); 81 | try 82 | { 83 | return Sender.RunTask(task); 84 | } 85 | catch (Exception ex) 86 | { 87 | throw ex; 88 | } 89 | } 90 | 91 | public static string Delete(string url) 92 | { 93 | url = Sender.FixUrl(url); 94 | Task task = Sender.client.DeleteAsync(url); 95 | try 96 | { 97 | return Sender.RunTask(task); 98 | } 99 | catch (Exception ex) 100 | { 101 | throw ex; 102 | } 103 | } 104 | 105 | private static string RunTask(Task task) 106 | { 107 | bool flag; 108 | try 109 | { 110 | flag = task.Wait(Sender.WaitingTime); 111 | } 112 | catch (Exception ex) 113 | { 114 | Exception exception = ex; 115 | while (exception.InnerException != null) 116 | exception = exception.InnerException; 117 | throw exception; 118 | } 119 | 120 | if (!flag) 121 | throw new TimeoutException("Timeout"); 122 | return task.Result.Content.ReadAsStringAsync().Result; 123 | } 124 | 125 | private static string FixUrl(string url) => 126 | !url.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? "http://" + url : url; 127 | } 128 | } -------------------------------------------------------------------------------- /Single/winSingle.xaml: -------------------------------------------------------------------------------- 1 |  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 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /WinConfig/WinConfig.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using System.Windows.Controls; 9 | 10 | 11 | namespace TypeB 12 | { 13 | /// 14 | /// WinConfig.xaml 的交互逻辑 15 | /// 16 | public partial class WinConfig : Window 17 | { 18 | public WinConfig() 19 | { 20 | InitializeComponent(); 21 | } 22 | 23 | private void Window_Loaded(object sender, RoutedEventArgs e) 24 | { 25 | string[] SkipedConfigItems = 26 | { 27 | "窗口坐标X"," 447", 28 | "窗口坐标Y" ,"119", 29 | "窗口高度", "600", 30 | "窗口宽度", "800", 31 | "字体大小", "30", 32 | "字体", "微软雅黑", 33 | "盲打模式", "否", 34 | "看打模式", "否", 35 | "成绩面板展开", "是", 36 | "获取更新", "QQ群775237860", 37 | "QQ窗口切换模式(1-2)","1", 38 | "载文模式(1-4)", "1", 39 | "新版QQ", "否", 40 | 41 | }; 42 | 43 | int counter = 0; 44 | var mg = new Thickness(10,3,10, 3); 45 | foreach(var item in Config.dicts) 46 | { 47 | 48 | if (SkipedConfigItems.Contains(item.Key)) 49 | continue; 50 | 51 | GridMain.RowDefinitions.Add(new RowDefinition()); 52 | 53 | TextBlock tbk = new TextBlock(); 54 | tbk.Text = item.Key; 55 | 56 | 57 | // tbk.HorizontalAlignment = HorizontalAlignment.Center; 58 | tbk.VerticalAlignment = VerticalAlignment.Center; 59 | tbk.SetValue(Grid.RowProperty, counter); 60 | tbk.SetValue(Grid.ColumnProperty, 0); 61 | tbk.Margin = mg; 62 | tbk.FontSize = 14; 63 | 64 | GridMain.Children.Add(tbk); 65 | 66 | 67 | if (item.Value =="是" || item.Value == "否") 68 | { 69 | CheckBox tbv = new CheckBox(); 70 | tbv.IsChecked = item.Value == "是"; 71 | tbv.VerticalAlignment = VerticalAlignment.Center; 72 | tbv.SetValue(Grid.RowProperty, counter); 73 | tbv.SetValue(Grid.ColumnProperty, 1); 74 | tbv.Margin = mg; 75 | tbv.FontSize = 14; 76 | 77 | GridMain.Children.Add(tbv); 78 | } 79 | else 80 | { 81 | TextBox tbv = new TextBox(); 82 | tbv.Text = item.Value; 83 | // tbv.HorizontalAlignment = HorizontalAlignment.Center; 84 | tbv.VerticalAlignment = VerticalAlignment.Center; 85 | tbv.SetValue(Grid.RowProperty, counter); 86 | tbv.SetValue(Grid.ColumnProperty, 1); 87 | tbv.Margin = mg; 88 | tbv.FontSize = 14; 89 | 90 | GridMain.Children.Add(tbv); 91 | } 92 | 93 | 94 | 95 | counter++; 96 | } 97 | } 98 | 99 | 100 | 101 | private void Cancel_Click(object sender, RoutedEventArgs e) 102 | { 103 | 104 | 105 | this.Close(); 106 | } 107 | 108 | public delegate void DelegateConfigSaved(); 109 | 110 | public event DelegateConfigSaved ConfigSaved; 111 | private void Save_Click(object sender, RoutedEventArgs e) 112 | { 113 | List key = new List(); 114 | List value = new List(); 115 | foreach (var item in GridMain.Children) 116 | { 117 | 118 | if (item.GetType() == typeof(TextBlock)) 119 | { 120 | var tb = (TextBlock)item; 121 | key.Add(tb.Text); 122 | } 123 | if (item.GetType() == typeof(TextBox)) 124 | { 125 | var tb = (TextBox)item; 126 | value.Add(tb.Text); 127 | } 128 | else if (item.GetType() == typeof(CheckBox)) 129 | { 130 | var tb = (CheckBox)item; 131 | if (tb.IsChecked == true) 132 | value.Add("是"); 133 | else 134 | value.Add("否"); 135 | } 136 | 137 | } 138 | 139 | bool modified = false; 140 | for (int i = 0; i < key.Count; i++) 141 | { 142 | 143 | if (value[i] != Config.GetString(key[i])) 144 | { 145 | modified = true; 146 | Config.Set(key[i], value[i]); 147 | } 148 | 149 | } 150 | if (modified) 151 | { 152 | ConfigSaved(); 153 | } 154 | } 155 | 156 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) 157 | { 158 | List key = new List(); 159 | List value = new List(); 160 | foreach (var item in GridMain.Children) 161 | { 162 | 163 | if (item.GetType() == typeof(TextBlock)) 164 | { 165 | var tb = (TextBlock)item; 166 | key.Add(tb.Text); 167 | } 168 | if (item.GetType() == typeof(TextBox)) 169 | { 170 | var tb = (TextBox)item; 171 | value.Add(tb.Text); 172 | } 173 | else if (item.GetType() == typeof(CheckBox)) 174 | { 175 | var tb = (CheckBox)item; 176 | if (tb.IsChecked == true) 177 | value.Add("是"); 178 | else 179 | value.Add("否"); 180 | } 181 | 182 | } 183 | 184 | bool modified = false; 185 | for (int i = 0; i < key.Count; i++) 186 | { 187 | 188 | if (value[i] != Config.GetString(key[i])) 189 | { 190 | modified = true; 191 | } 192 | 193 | } 194 | if (modified) 195 | { 196 | if (MessageBox.Show("设置已修改,是否保存?", 197 | "保存设置", 198 | MessageBoxButton.YesNo, 199 | MessageBoxImage.Question) == MessageBoxResult.Yes) 200 | { 201 | 202 | for (int i = 0; i < key.Count; i++) 203 | { 204 | if (value[i] != Config.GetString(key[i])) 205 | { 206 | Config.Set(key[i], value[i]); 207 | } 208 | 209 | } 210 | 211 | ConfigSaved(); 212 | 213 | } 214 | } 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /WinTrainer/TrainerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace TypeB 10 | { 11 | internal class TrainerConfig 12 | { 13 | static public Dictionary dicts = new Dictionary(); 14 | static public string Path = "ArticleConfig.txt"; 15 | 16 | static public void SetDefault(params string[] args) 17 | { 18 | for (int i = 0; i + 1 < args.Length; i += 2) 19 | { 20 | dicts[args[i]] = args[i + 1]; 21 | } 22 | 23 | } 24 | 25 | 26 | static private Timer WriteTimer = null; 27 | 28 | 29 | static private void WriteNow(object obj) 30 | { 31 | 32 | if (Path == "") 33 | return; 34 | 35 | 36 | StreamWriter sw = new StreamWriter(Path); 37 | 38 | foreach (var c in dicts) 39 | { 40 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 41 | } 42 | 43 | 44 | sw.Close(); 45 | if (WriteTimer != null) 46 | { 47 | WriteTimer.Dispose(); 48 | WriteTimer = null; 49 | } 50 | 51 | } 52 | 53 | static public void WriteConfig(int Delay = 0) 54 | { 55 | 56 | if (Path == "") 57 | return; 58 | 59 | if (Delay == 0) 60 | { 61 | if (WriteTimer != null) 62 | { 63 | WriteTimer.Dispose(); 64 | WriteTimer = null; 65 | } 66 | 67 | StreamWriter sw = new StreamWriter(Path); 68 | 69 | foreach (var c in dicts) 70 | { 71 | sw.WriteLineAsync(c.Key + "\t" + c.Value); 72 | } 73 | 74 | 75 | sw.Close(); 76 | } 77 | else if (Delay > 0) 78 | { 79 | if (WriteTimer == null) 80 | { 81 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 82 | } 83 | else 84 | { 85 | WriteTimer.Dispose(); 86 | WriteTimer = new Timer(WriteNow, null, Delay, Timeout.Infinite); 87 | // WriteTimer.Change(Delay, Timeout.Infinite); 88 | 89 | } 90 | } 91 | } 92 | 93 | static public void ReadConfig() 94 | { 95 | // char[] sp = { '\r', ' ', '\t' }; 96 | 97 | if (!File.Exists(Path)) 98 | { 99 | WriteConfig(); 100 | return; 101 | } 102 | 103 | char[] sp1 = { '\n' }; 104 | 105 | string[] lines = File.ReadAllText(Path).Split(sp1, StringSplitOptions.RemoveEmptyEntries); 106 | 107 | 108 | foreach (string line in lines) 109 | { 110 | if (line.Substring(0, 1) == "#") 111 | continue; 112 | string line_p = line.Replace("\r", "").Replace("\n", ""); 113 | 114 | string[] sp = { "\t", " ", "," }; 115 | 116 | 117 | 118 | foreach (string s in sp) 119 | { 120 | if (line_p.Contains(s)) 121 | { 122 | int pos = line_p.IndexOf(s); 123 | if (pos >= 1 && pos <= line_p.Length - 2) 124 | { 125 | string key = line_p.Substring(0, pos); 126 | string value = line_p.Substring(pos + 1); 127 | dicts[key] = value; 128 | break; 129 | } 130 | } 131 | } 132 | 133 | 134 | 135 | } 136 | 137 | 138 | WriteConfig(); 139 | 140 | 141 | 142 | } 143 | 144 | static public bool GetBool(string key) 145 | { 146 | if (dicts.ContainsKey(key) && dicts[key] == "是") 147 | return true; 148 | else 149 | return false; 150 | } 151 | static public string GetString(string key) 152 | { 153 | if (dicts.ContainsKey(key)) 154 | return dicts[key]; 155 | else 156 | return ""; 157 | } 158 | 159 | static public int GetInt(string key) 160 | { 161 | if (dicts.ContainsKey(key) && Int32.TryParse(dicts[key], out int num)) 162 | return num; 163 | else 164 | return 0; 165 | } 166 | 167 | 168 | static public double GetDouble(string key) 169 | { 170 | if (dicts.ContainsKey(key) && Double.TryParse(dicts[key], out double num)) 171 | return num; 172 | else 173 | return 0; 174 | } 175 | 176 | static public void Set(string key, bool value) 177 | { 178 | if (value) 179 | dicts[key] = "是"; 180 | else 181 | dicts[key] = "否"; 182 | 183 | WriteConfig(3000); 184 | } 185 | static public void Set(string key, int value) 186 | { 187 | dicts[key] = value.ToString(); 188 | WriteConfig(3000); 189 | } 190 | 191 | static public void Set(string key, string value) 192 | { 193 | dicts[key] = value; 194 | WriteConfig(3000); 195 | } 196 | 197 | static public void Set(string key, double value, int fraction = -1) 198 | { 199 | string f = "F" + fraction.ToString(); 200 | if (fraction > 0) 201 | dicts[key] = value.ToString(f); 202 | else 203 | dicts[key] = value.ToString(); 204 | 205 | WriteConfig(3000); 206 | 207 | } 208 | } 209 | 210 | } 211 | -------------------------------------------------------------------------------- /WinTrainer/WinTrainer.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |