using System;
using System.Diagnostics.CodeAnalysis;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
using WIDESEAWCS_Tasks.StackerCraneJob;
namespace WIDESEAWCS_Tasks
{
///
/// 堆垛机命令构建器:封装任务到命令对象的转换与地址解析。
///
public class StackerCraneCommandBuilder
{
private readonly ITaskService _taskService;
private readonly IRouterService _routerService;
private readonly StackerCraneCommandConfig _config;
public StackerCraneCommandBuilder(
ITaskService taskService,
IRouterService routerService,
StackerCraneCommandConfig config)
{
_taskService = taskService;
_routerService = routerService;
_config = config;
}
public object? ConvertToStackerCraneTaskCommand([NotNull] Dt_Task task)
{
string commandType = GetCommandType(task.Roadway);
return commandType switch
{
"Formation" => BuildCommand(task, CreateFormationCommand(task)),
_ => BuildCommand(task, CreateStandardCommand(task))
};
}
private string GetCommandType(string roadway)
{
foreach (var mapping in _config.RoadwayCommandMapping)
{
if (roadway.Contains(mapping.Key))
{
return mapping.Value;
}
}
return _config.DefaultCommandType;
}
private static StackerCraneTaskCommand CreateStandardCommand(Dt_Task task)
{
return new StackerCraneTaskCommand
{
TaskNum = task.TaskNum,
WorkType = 1,
WorkAction = 1
};
}
private static FormationStackerCraneTaskCommand CreateFormationCommand(Dt_Task task)
{
return new FormationStackerCraneTaskCommand
{
Barcode = task.PalletCode,
TaskNum = task.TaskNum,
WorkType = 1,
WorkAction = 1,
FireAlarm = 0,
HeartBeat = 0,
FieldName = string.Empty
};
}
private T? BuildCommand(Dt_Task task, T command) where T : class
{
TaskTypeGroup taskTypeGroup = task.TaskType.GetTaskTypeGroup();
return taskTypeGroup switch
{
TaskTypeGroup.InboundGroup => BuildInboundCommand(task, command),
TaskTypeGroup.OutbondGroup => BuildOutboundCommand(task, command),
TaskTypeGroup.RelocationGroup => BuildRelocationCommand(task, command),
_ => command
};
}
private T? BuildInboundCommand(Dt_Task task, T command) where T : class
{
int taskType = 0;
if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
{
taskType = 100;
}
else
taskType = task.TaskType;
Dt_Router? router = _routerService.QueryNextRoute(task.CurrentAddress, task.Roadway, taskType);
if (router == null)
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.CurrentAddress}】信息,无法获取对应的堆垛机取货站台信息");
return null;
}
SetCommandProperty(command, "StartRow", Convert.ToInt16(router.SrmRow));
SetCommandProperty(command, "StartColumn", Convert.ToInt16(router.SrmColumn));
SetCommandProperty(command, "StartLayer", Convert.ToInt16(router.SrmLayer));
if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer))
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"入库任务终点错误,终点:【{task.NextAddress}】");
return null;
}
SetCommandProperty(command, "EndRow", endRow);
SetCommandProperty(command, "EndColumn", endColumn);
SetCommandProperty(command, "EndLayer", endLayer);
return command;
}
private T? BuildOutboundCommand(Dt_Task task, T command) where T : class
{
int taskType = 0;
if (task.TaskType == (int)TaskOutboundTypeEnum.OutEmpty)
{
taskType = 100;
}
else
taskType = task.TaskType;
Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.TargetAddress, taskType);
if (router == null)
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.TargetAddress}】信息,无法获取对应的堆垛机放货站台信息");
return null;
}
SetCommandProperty(command, "EndRow", Convert.ToInt16(router.SrmRow));
SetCommandProperty(command, "EndColumn", Convert.ToInt16(router.SrmColumn));
SetCommandProperty(command, "EndLayer", Convert.ToInt16(router.SrmLayer));
if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer))
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"出库任务起点错误,起点:【{task.CurrentAddress}】");
return null;
}
SetCommandProperty(command, "StartRow", startRow);
SetCommandProperty(command, "StartColumn", startColumn);
SetCommandProperty(command, "StartLayer", startLayer);
return command;
}
private T? BuildRelocationCommand(Dt_Task task, T command) where T : class
{
if (!TryParseAddress(task.NextAddress, out short endRow, out short endColumn, out short endLayer))
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务终点错误,终点:【{task.NextAddress}】");
return null;
}
SetCommandProperty(command, "EndRow", endRow);
SetCommandProperty(command, "EndColumn", endColumn);
SetCommandProperty(command, "EndLayer", endLayer);
if (!TryParseAddress(task.CurrentAddress, out short startRow, out short startColumn, out short startLayer))
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"移库任务起点错误,起点:【{task.CurrentAddress}】");
return null;
}
SetCommandProperty(command, "StartRow", startRow);
SetCommandProperty(command, "StartColumn", startColumn);
SetCommandProperty(command, "StartLayer", startLayer);
return command;
}
private static void SetCommandProperty(T command, string propertyName, object value) where T : class
{
var property = typeof(T).GetProperty(propertyName);
property?.SetValue(command, value);
}
private static bool TryParseAddress(string address, out short row, out short column, out short layer)
{
row = column = layer = 0;
string[] parts = address.Split("-");
if (parts.Length != 3)
{
return false;
}
return short.TryParse(parts[0], out row)
&& short.TryParse(parts[1], out column)
&& short.TryParse(parts[2], out layer);
}
}
}