namespace MAF1.Decisions;
///
/// CLI 版确认框。回车 / 1 = 结束查询;2 = 再输入城市;也可以直接打「成都」。
/// ReadLine 和超时赛跑:到期返回 TimedOut,走默认方案。
/// MAF1 工作流 CLI 与 MAF1.Route 共用。
///
public static class ConsoleDecisionPrompt
{
public static async Task WaitAsync(DecisionRequest request)
{
Console.WriteLine();
Console.WriteLine("[需要确认]");
Console.WriteLine(request.Prompt);
if (!string.IsNullOrWhiteSpace(request.Reason))
{
Console.WriteLine($"原因:{request.Reason}");
}
Console.WriteLine($"未及时确认将使用默认方案。等待 {request.TimeoutSeconds} 秒。");
for (int i = 0; i < request.Options.Count; i++)
{
DecisionOption option = request.Options[i];
string mark = option.IsDefault ? " ← 默认" : "";
Console.WriteLine($" {i + 1}) {option.Label}{mark}");
if (!string.IsNullOrWhiteSpace(option.Description))
{
Console.WriteLine($" {option.Description}");
}
}
Console.Write("输入序号,或直接回车采用默认:");
string? line = await ReadLineOrTimeoutAsync(request.Deadline);
if (line is null)
{
Console.WriteLine();
Console.WriteLine("未及时确认,采用默认方案:结束查询。");
return new DecisionAnswer { OptionId = request.DefaultOptionId, TimedOut = true };
}
line = line.Trim();
if (line.Length == 0 || line is "1" || line.Equals("stop", StringComparison.OrdinalIgnoreCase))
{
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop };
}
if (line is "2" || line.Equals(DecisionOptionIds.QueryCities, StringComparison.OrdinalIgnoreCase))
{
Console.Write("请输入城市名(例如 成都、北京):");
string? cities = await ReadLineOrTimeoutAsync(request.Deadline);
if (cities is null)
{
Console.WriteLine();
Console.WriteLine("未及时输入城市,采用默认方案:结束查询。");
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop, TimedOut = true };
}
if (EmptyCityDecision.ParseCities(cities).Count == 0)
{
Console.WriteLine("没有有效城市名,采用默认方案:结束查询。");
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop };
}
return new DecisionAnswer { OptionId = DecisionOptionIds.QueryCities, Text = cities };
}
if (EmptyCityDecision.ParseCities(line).Count > 0)
{
return new DecisionAnswer { OptionId = DecisionOptionIds.QueryCities, Text = line };
}
Console.WriteLine("无法识别输入,采用默认方案:结束查询。");
return new DecisionAnswer { OptionId = DecisionOptionIds.Stop };
}
/// 超时返回 null。注意:超时后后台的 ReadLine 仍可能阻塞,学习项目可接受。
private static async Task ReadLineOrTimeoutAsync(DateTimeOffset deadline)
{
TimeSpan remain = deadline - DateTimeOffset.UtcNow;
if (remain <= TimeSpan.Zero)
{
return null;
}
Task read = Task.Run(() => Console.ReadLine());
Task delay = Task.Delay(remain);
Task finished = await Task.WhenAny(read, delay);
if (finished == delay)
{
return null;
}
return await read;
}
}