-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
633 lines (541 loc) · 21.2 KB
/
Program.cs
File metadata and controls
633 lines (541 loc) · 21.2 KB
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
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
61
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace EasingPathPositionCalculator;
public class Program
{
public static List<Group> Groups => GlobalState.Groups;
public static string version = "v1.0 release";
public static string targetArch = "win";
public static string relTime = "071025_1154";
public static void ShowAbout()
{
string about = $"""
缓动曲线路径采样生成器
{version} for [{targetArch}] built at {relTime} by 不吃bug的鱼鱼鱼sakanya
输入 "help" 获取更多信息.
""";
Console.WriteLine(about);
}
public static void Main(String[] args)
{
Log.Normal($"""
EasingPathCalc
{version} for [{targetArch}] released at {relTime} by 不吃exception的鱼鱼鱼sakanya
欢迎bug回报:Q=2973858503
""");
bool guideMode = args.Length > 0 && args[0] switch
{
"-g" => true,
_ => false
};
Log.Normal($"{guideMode}");
if (guideMode)
GuideMode();
else
CommandMode();
Console.WriteLine("按任意键继续...");
Console.ReadKey();
}
public static void GuideMode()
{
}
public static void CommandMode()
{
Log.SetLevel(LogLevel.NORMAL);
Log.Normal($"当前日志等级{Log.GetCurrentStatus()}");
Log.Normal("命令模式");
ShowAbout();
while (true)
{
Console.Write(">>> ");
string? input = Console.ReadLine()?.Trim();
if (string.IsNullOrEmpty(input))
continue;
string[] args = input.Split(' ', StringSplitOptions.RemoveEmptyEntries);
string command = args[0].ToLower();
try
{
switch (command)
{
case "help":
Help();
break;
case "el":
ShowEasing();
break;
case "cc":
ArgHandler.HandleGroupCommand(["group", "create", "FASTCREATE", "-o"]);
break;
case "ex":
ArgHandler.HandleGroupCommand(["group", "export", "all"]);
break;
case "show":
Utils.OpenExplorer(AppDomain.CurrentDomain.BaseDirectory);
break;
case "group":
if (args.Length < 2)
{
Console.WriteLine("错误:group 命令需要子命令");
break;
}
ArgHandler.HandleGroupCommand(args);
break;
case "log":
ArgHandler.HandleLogCommand(args);
break;
case "clr":
ArgHandler.HandleClearCommand(args);
break;
case "exit":
case "back":
case "quit":
case "bye":
Log.Normal("用户退出程序");
return;
case "waht":
Candies.GiveMeCandy(-1);
break;
case "who":
Candies.GiveMeCandy(0);
break;
case "badapple":
Candies.GiveMeCandy(Candies.Shenmi.BadApple);
break;
case "scarlet":
case "funky":
Candies.GiveMeCandy(Candies.Shenmi.Funky);
break;
case "baka":
Candies.GiveMeCandy(Candies.Shenmi.Baka);
break;
case "gugugaga":
Candies.GiveMeCandy(Candies.Shenmi.gugugaga);
break;
case "soyo":
case "chunriyin":
case "haruhikage":
Candies.GiveMeCandy(Candies.Shenmi.Haruhikage);
break;
case "avemujica":
Candies.GiveMeCandy(Candies.Shenmi.AveMujica);
break;
case "nailong":
Candies.GiveMeCandy(Candies.Shenmi.NaiLong);
break;
case "nyamu":
Candies.GiveMeCandy(Candies.Shenmi.nyamu);
break;
case "rickroll":
Candies.GiveMeCandy(Candies.Shenmi.RickRoll);
break;
case "qianlianwanhua":
Candies.GiveMeCandy(Candies.Shenmi.SRBK);
break;
case "0721":
Candies.GiveMeCandy(Candies.Shenmi._0721);
break;
case "genshin":
case "yuanshen":
Candies.GiveMeCandy(Candies.Shenmi.YS);
break;
case "fuck":
case "fucku":
case "fuckyou":
Console.WriteLine("(深度思考中...)");
Console.WriteLine("| 我草,用户彻底怒了,...");
break;
case "iloveu":
Console.WriteLine("我已知悉");
break;
default:
Console.WriteLine($"未知命令: {command}。输入 'help' 查看帮助。");
Log.Debug($"Unknown command: {command}");
break;
}
}
catch (Exception ex)
{
Console.WriteLine($"执行命令时出错: {ex.Message}");
Log.Fatal($"command error: {ex.Message}\n{ex.StackTrace}");
}
Console.WriteLine($"\n\n{Candies.Dividing()}\n\n");
Log.FlushLogs(); // 刷新日志防止异常退出
}
}
public static void Help()
{
string help = """
用法:
help 显示帮助
el 显示缓动函数参考列表
cc 快速开始曲线路径创建(等同于group create -o)
ex 快速导出所有路径组(等同于group export all)
show 打开程序根目录
group [create]|[list]|[remove]|[export]
group create [name] [-o]创建一个曲线路径,名为name(可选,不填则默认unnamed),可通过选择-o即刻导出
group list 列出所有已创建的曲线路径组
group remove <UID> [-q] 通过UID删除一个曲线路径,可通过选择-q来跳过确认
group remove all 删除所有曲线路径组
group export <UID> 通过UID导出一个曲线路径到文件
group export all [-d] 导出所有已创建的曲线路径组,可通过选择-d来按文件分隔每个组
log [normal]|[warning]|{[debug] [intime]}|[status]|[show]
log debug intime 实时输出日志到控制台(使用任意一个其他等级以取消)
log status 显示日志等级
log show 打开log文件夹
clr [log]|[tmp] 清理日志/缓存文件
waht 这是什么
back 任何时候(并非)返回上一步
exit 退出程序
""";
Console.WriteLine(help);
}
public static void ShowEasing()
{
string ease = """
Linear = 1,
InSine = 2, OutSine = 3,
InQuad = 4, OutQuad = 5, InOutQuad = 6, OutInQuad = 7,
InCubic = 8, OutCubic = 9,
InQuart = 10, OutQuart = 11,
InQuint = 12, OutQuint = 13,
InExpo = 14, OutExpo = 15,
InCirc = 16, OutCirc = 17,
InBack = 18, OutBack = 19, InOutBack = 20, OutInBack = 21,
InElastic = 22, OutElastic = 23,
InBounce = 24, OutBounce = 25, InOutBounce = 26, OutInBounce = 27
In: 由慢到快
Out: 由快到慢
InOut: 慢-快-慢
OutIn: 快-慢-快
Elastic: 弹簧收缩
Bounce: 弹性小球落地
""";
Console.WriteLine(ease);
}
/// <summary>
/// 创建group
/// </summary>
/// <param name="name">group name</param>
/// <param name="withOpen">open after create</param>
public static void GroupCreate(string name, bool withOpen)
{
Group g = new(name);
EasingType easeType;
inputInfo:
Log.Normal("数据输入");
Console.WriteLine("输入:开始位置X 结束位置X 间隔拍数 采样密度 (空格分隔)");
Console.WriteLine("例:> 10 20 4.25 4");
double sx = 0.0, ex = 0.0, duration = 0.0;
int density = 1;
Console.Write("> ");
string? input = Console.ReadLine();
if (input?.Trim().ToLower().Equals("back") ?? false)
return;
// 解析输入参数
string[] parts = input?.Split(' ', StringSplitOptions.RemoveEmptyEntries) ?? [];
if (parts.Length < 4)
{
Console.WriteLine("!!!> 错误:需要4个参数");
goto inputInfo;
}
// 解析开始位置X
if (!double.TryParse(parts[0], out sx))
{
Console.WriteLine("!!!> 错误:开始位置X格式不正确");
goto inputInfo;
}
// 解析结束位置X
if (!double.TryParse(parts[1], out ex))
{
Console.WriteLine("!!!> 错误:结束位置X格式不正确");
goto inputInfo;
}
// 解析间隔拍数
if (!double.TryParse(parts[2], out duration) || duration <= 0)
{
Console.WriteLine("!!!> 错误:间隔拍数必须是大于0的数字");
goto inputInfo;
}
// 解析采样密度
if (!int.TryParse(parts[3], out density) || density <= 0)
{
Console.WriteLine("!!!> 错误:采样密度必须是大于0的整数");
goto inputInfo;
}
inputEasing:
// 选择缓动类型
Console.WriteLine("请选择缓动类型(输入数字或名称):");
ShowEasing(); // 显示可用的缓动类型
Console.Write("> ");
string? easingInput = Console.ReadLine();
if (easingInput?.Trim().ToLower().Equals("back") ?? false)
goto inputInfo;
if (!(int.TryParse(easingInput, out int easingNumber) && easingNumber <= 27))
{
Console.WriteLine();
Console.WriteLine("!!!> 错误:无效的缓动类型");
Console.WriteLine();
goto inputEasing;
}
if (int.TryParse(easingInput, out easingNumber) &&
Enum.IsDefined(typeof(EasingType), easingNumber))
{
easeType = (EasingType)easingNumber;
}
else if (Enum.TryParse(easingInput, true, out EasingType parsedEasing))
{
easeType = parsedEasing;
}
else
{
Console.WriteLine();
Console.WriteLine("!!!> 错误:无效的缓动类型");
Console.WriteLine();
goto inputEasing;
}
// 设置Group属性
g.StartX = sx;
g.EndX = ex;
g.Duration = duration;
g.Density = density;
g.Easing = easeType;
// 计算点
g.CalcPoints();
Console.WriteLine("#############################");
Console.WriteLine($"路径组 '{name}' 创建成功!");
Console.WriteLine($"共计 {g.Count} 个采样点");
Console.WriteLine();
Log.Normal($"已创建路径组{g}\n{g.Count}次采样");
// 显示前几个点作为预览
if (g.Count > 0)
{
Console.WriteLine("> 预览:");
foreach (var point in g.Points.Take(3))
{
Console.WriteLine($"{point}");
}
if (g.Count > 3)
{
Console.WriteLine("...");
}
}
if (withOpen)
{
Utils.OpenInNotepad(g);
}
Groups.Add(g);
Console.WriteLine($"已将曲线路径\"{name}\"添加至list!");
Log.Normal($"{name}已添加至list");
}
/// <summary>
/// 列出group
/// </summary>
public static void GroupList()
{
if (GlobalState.Groups.Count == 0)
{
Console.WriteLine("没有已创建的路径组");
Log.Normal("Group list is empty");
return;
}
Console.WriteLine($"共有 {GlobalState.Groups.Count} 个路径组:");
Console.WriteLine(new string('-', 80));
foreach (var group in GlobalState.Groups)
{
Console.WriteLine($"{group}");
}
Log.Normal($"Group list: {GlobalState.Groups.Count} groups in total");
}
/// <summary>
/// 移除Group
/// </summary>
/// <param name="UID">uid</param>
/// <param name="quite">安静删除</param>
/// <returns>是否成功删除</returns>
public static bool GroupRemove(short UID, bool quite)
{
var group = GlobalState.Groups.FirstOrDefault(g => g.GroupUID == UID);
if (group == null)
{
Console.WriteLine($"找不到 UID 为 {UID} 的路径组,使用\"group list\"来查看组的uid");
Log.Warning($"Undefined UID: {UID} when remove");
return false;
}
if (!quite)
{
Console.WriteLine($"匹配的路径组:{group}");
Console.WriteLine($"确定要删除此路径组 (UID: {UID}) 吗?(y/N)");
string? confirm = Console.ReadLine()?.Trim().ToLower();
if (confirm != "y" && confirm != "yes")
{
Console.WriteLine("删除操作已取消!");
Log.Normal($"Deletion canceled, UID: {UID}");
return false;
}
}
GlobalState.Groups.Remove(group);
Console.WriteLine($"已删除路径组 '{group.GroupName}' (UID: {UID})");
Log.Normal($"Deletion confirmed: {group.GroupName} (UID: {UID})");
return true;
}
/// <summary>
/// 删除所有路径组
/// </summary>
public static void GroupRemoveAll()
{
if (GlobalState.Groups.Count == 0)
{
Console.WriteLine("没有可删除的路径组");
return;
}
Console.WriteLine($"共 {GlobalState.Groups.Count} 个路径组");
Console.WriteLine($"确定要删除所有吗?(y/N)");
string? confirm = Console.ReadLine()?.Trim().ToLower();
if (confirm != "y" && confirm != "yes")
{
Console.WriteLine("取消删除操作");
Log.Normal("DeletionAll canceled");
return;
}
int count = GlobalState.Groups.Count;
GlobalState.Groups.Clear();
Console.WriteLine($"已删除所有 {count} 个路径组");
Log.Normal($"Delete All confirmed");
}
/// <summary>
/// 导出uid路径组
/// </summary>
/// <param name="UID">uid</param>
/// <param name="autoOpen">是否自动打开文件</param>
/// <returns>是否成功</returns>
public static bool ExportGroup(int UID, bool autoOpen = true)
{
var group = GlobalState.Groups.FirstOrDefault(g => g.GroupUID == UID);
if (group == null)
{
Console.WriteLine($"找不到 UID 为 {UID} 的路径组");
Log.Warning($"Undefine UID: {UID} when export");
return false;
}
try
{
// 确保输出目录存在
if (!Directory.Exists(GlobalState.OutputDirectory))
{
Directory.CreateDirectory(GlobalState.OutputDirectory);
}
string fileName = $"{group.GroupName.Replace(" ", "_")}({group.GroupUID}).txt";
string filePath = Path.Combine(GlobalState.OutputDirectory, fileName);
using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
writer.WriteLine($"{group}");
writer.WriteLine("(注意!所有时间标尺均为 相对于起点 !)");
writer.WriteLine(new string('-', 40));
foreach (var point in group.Points)
{
writer.WriteLine(point.ToString());
}
writer.WriteLine(new string('-', 40));
writer.WriteLine($"Total points: {group.Count}");
}
Console.WriteLine($"已导出到: {filePath}");
Log.Normal($"导出了路径组: {group.GroupName} (UID: {UID}) 到 {filePath}");
// 只有autoOpen为true时才打开文件
if (autoOpen)
{
Utils.OpenTextFile(filePath);
}
return true;
}
catch (Exception ex)
{
Console.WriteLine($"导出失败: {ex.Message}");
Log.Fatal($"Export failed: {ex.Message}");
return false;
}
}
/// <summary>
/// 导出所有
/// </summary>
/// <param name="dividedly">分隔导出</param>
public static void ExportGroupAll(bool dividedly)
{
Log.Normal("准备导出");
if (GlobalState.Groups.Count == 0)
{
Console.WriteLine("没有可导出的路径组");
Log.Warning("Group list is empty");
return;
}
try
{
// 确保输出目录存在
if (!Directory.Exists(GlobalState.OutputDirectory))
{
Directory.CreateDirectory(GlobalState.OutputDirectory);
}
if (dividedly)
{
// 分隔导出:每个组一个文件,但不自动打开每个文件
int successCount = 0;
foreach (var group in GlobalState.Groups)
{
// 传入false,不自动打开单个文件
if (ExportGroup(group.GroupUID, false))
{
successCount++;
}
}
Console.WriteLine($"成功导出 {successCount}/{GlobalState.Groups.Count} 个路径组");
Log.Normal($"{successCount}/{GlobalState.Groups.Count} groups have already exported");
if (successCount != GlobalState.Groups.Count)
Log.Warning("不是所有的组都被成功导出!");
// 打开资源管理器
Utils.OpenExplorer(GlobalState.OutputDirectory);
}
else
{
// 合并导出:所有组到一个文件
string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
int processId = System.Diagnostics.Process.GetCurrentProcess().Id;
string filePath = Path.Combine(
GlobalState.OutputDirectory,
$"Groups_{DateTime.Now:yyyyMMdd}_{processId}_{timestamp}.txt");
using (StreamWriter writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
foreach (var group in GlobalState.Groups)
{
writer.WriteLine($"> {group}");
writer.WriteLine(new string('#', 40));
foreach (var point in group.Points)
{
writer.WriteLine(point.ToString());
}
writer.WriteLine(new string('#', 40));
writer.WriteLine($"#Total points: {group.Count}#");
writer.WriteLine(); // 空行分隔不同组
}
writer.WriteLine($">>> Total groups: {GlobalState.Groups.Count}#");
}
Console.WriteLine($"已合并导出到: {filePath}");
Log.Normal($"export {GlobalState.Groups.Count} groups to {filePath} in merge");
// 打开文件
Utils.OpenTextFile(filePath);
}
}
catch (Exception ex)
{
Console.WriteLine($"导出失败: {ex.Message}");
Log.Fatal($"Export failed: {ex.Message}");
}
}
// 全局状态
public static class GlobalState
{
public static List<Group> Groups { get; } = new List<Group>();
public static string OutputDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "output");
}
}