sea-battle/Assets/Scripts/BlinkStartupInitializer.cs

181 lines
5.7 KiB
C#

using System;
using System.IO;
using UnityEngine;
public static class BlinkStartupInitializer
{
private const string ConfigFileName = "led_startup_config.ini";
private static bool subscribed;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Register()
{
if (subscribed)
return;
subscribed = true;
ComWrapper.OnInitialize += ApplyStartupCommands;
Application.quitting += Unregister;
}
private static void Unregister()
{
ComWrapper.OnInitialize -= ApplyStartupCommands;
Application.quitting -= Unregister;
subscribed = false;
}
private static void ApplyStartupCommands()
{
string configPath = Path.Combine(Application.streamingAssetsPath, ConfigFileName);
try
{
if (!File.Exists(configPath))
{
Directory.CreateDirectory(Application.streamingAssetsPath);
File.WriteAllText(configPath, GetDefaultConfig());
Debug.Log($"BlinkStartupInitializer: создан файл конфигурации {configPath}");
}
string[] lines = File.ReadAllLines(configPath);
for (int i = 0; i < lines.Length; i++)
ProcessLine(lines[i], i + 1);
}
catch (Exception ex)
{
Debug.LogWarning($"BlinkStartupInitializer: ошибка чтения {configPath}: {ex.Message}");
}
}
private static void ProcessLine(string rawLine, int lineNumber)
{
if (string.IsNullOrWhiteSpace(rawLine))
return;
string line = StripComments(rawLine).Trim();
if (string.IsNullOrWhiteSpace(line))
return;
int separatorIndex = line.IndexOf('=');
if (separatorIndex < 0)
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber} должна быть в формате player1=004 003");
return;
}
string playerToken = line.Substring(0, separatorIndex).Trim();
string commandsToken = line.Substring(separatorIndex + 1).Trim();
if (!TryParsePlayerId(playerToken, out int playerId))
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber}, неизвестный идентификатор '{playerToken}'");
return;
}
if (string.IsNullOrWhiteSpace(commandsToken))
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber} не содержит команд");
return;
}
string[] commands = commandsToken.Split(new[] { ' ', '\t', ',', ';' }, StringSplitOptions.RemoveEmptyEntries);
foreach (string command in commands)
SendValidatedCommand(command, playerId, lineNumber);
}
private static void SendValidatedCommand(string rawCommand, int playerId, int lineNumber)
{
if (!TryNormalizeCommand(rawCommand, out string command))
{
Debug.LogWarning($"BlinkStartupInitializer: строка {lineNumber}, команда '{rawCommand}' некорректна");
return;
}
ComWrapper.Send(command, playerId);
Debug.Log($"BlinkStartupInitializer: отправлена команда {command} для playerId={playerId}");
}
private static bool TryNormalizeCommand(string rawCommand, out string command)
{
command = null;
if (string.IsNullOrWhiteSpace(rawCommand))
return false;
string value = rawCommand.Trim();
if (value.StartsWith("89", StringComparison.Ordinal))
value = value.Substring(2);
if (value.Length != 3)
return false;
if (!char.IsDigit(value[0]) || !char.IsDigit(value[1]) || !char.IsDigit(value[2]))
return false;
int channel = value[0] - '0';
int mode = value[1] - '0';
int sequence = value[2] - '0';
if (channel < 0 || channel > 4)
return false;
if (mode != 0)
return false;
if (sequence < 0 || sequence > 5)
return false;
command = $"89{value}";
return true;
}
private static bool TryParsePlayerId(string token, out int playerId)
{
switch (token.Trim().ToLowerInvariant())
{
case "1":
case "player1":
case "plate1":
playerId = 1;
return true;
case "2":
case "player2":
case "plate2":
playerId = 2;
return true;
default:
playerId = 0;
return false;
}
}
private static string StripComments(string line)
{
int hashIndex = line.IndexOf('#');
int slashIndex = line.IndexOf("//", StringComparison.Ordinal);
int commentIndex = -1;
if (hashIndex >= 0)
commentIndex = hashIndex;
if (slashIndex >= 0 && (commentIndex < 0 || slashIndex < commentIndex))
commentIndex = slashIndex;
return commentIndex >= 0 ? line.Substring(0, commentIndex) : line;
}
private static string GetDefaultConfig()
{
return string.Join(Environment.NewLine, new[]
{
"# Команды инициализации LED-лент.",
"# Формат: player1=004 003",
"# player1/player2 = номер платы = playerId",
"# Команда: X0Z или 89X0Z",
"# X: 0 - все каналы, 1-4 - конкретный канал",
"# Z: 0-RGB, 1-RBG, 2-BRG, 3-BGR, 4-GRB, 5-GBR",
"player1=004",
"player2=004"
});
}
}