Files
C4IT-F4SD-Client/FasdCockpitCommunicationDemo/TicketOverviewDataStore.cs
2026-02-10 16:53:06 +01:00

356 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Newtonsoft.Json;
namespace FasdCockpitCommunicationDemo
{
public class DemoTicketJournalEntry
{
public string Header { get; set; }
public string Description { get; set; }
public string DescriptionHtml { get; set; }
public bool IsVisibleForUser { get; set; }
public DateTime CreationDate { get; set; }
}
public class DemoTicketDetail
{
public string AffectedUser { get; set; }
public string Asset { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public string DescriptionHtml { get; set; }
public int? Priority { get; set; }
public string Solution { get; set; }
public string SolutionHtml { get; set; }
public List<DemoTicketJournalEntry> Journal { get; set; } = new List<DemoTicketJournalEntry>();
}
public class DemoTicketTemplate
{
public string TileKey { get; set; } = "TicketsNew";
public bool UseRoleScope { get; set; }
public Guid? UserId { get; set; }
public string ActivityType { get; set; }
public string DisplayNamePrefix { get; set; } = "TCK";
public string Summary { get; set; }
public string StatusId { get; set; } = "New";
public string UserDisplayName { get; set; }
public string UserAccount { get; set; }
public string UserDomain { get; set; }
public DemoTicketDetail Detail { get; set; } = new DemoTicketDetail();
}
public class DemoTicketRecord
{
public Guid TicketId { get; set; }
public Guid UserId { get; set; }
public string TileKey { get; set; }
public bool UseRoleScope { get; set; }
public string ActivityType { get; set; }
public string DisplayName { get; set; }
public string Summary { get; set; }
public string StatusId { get; set; }
public string UserDisplayName { get; set; }
public string UserAccount { get; set; }
public string UserDomain { get; set; }
public DateTime CreatedAt { get; set; }
public DemoTicketDetail Detail { get; set; } = new DemoTicketDetail();
}
public class DemoTicketData
{
public List<DemoTicketTemplate> Templates { get; set; } = new List<DemoTicketTemplate>();
public List<DemoTicketRecord> Tickets { get; set; } = new List<DemoTicketRecord>();
}
public static class TicketOverviewDataStore
{
private const string FileName = "TicketOverviewGeneratedTickets.json";
private static readonly object SyncRoot = new object();
private const int DefaultNumberWidth = 5;
private static readonly Dictionary<string, int> SeedNumbers = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
{
["TCK"] = 766,
["INC"] = 475
};
private static readonly Dictionary<string, int> SeedWidths = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
{
["TCK"] = DefaultNumberWidth,
["INC"] = DefaultNumberWidth
};
private static List<DemoTicketTemplate> _templateCache = new List<DemoTicketTemplate>();
private static List<DemoTicketRecord> _runtimeTickets = new List<DemoTicketRecord>();
private static readonly Dictionary<string, int> _nextNumbers = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
private static readonly Dictionary<string, int> _numberWidths = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
private static bool _isLoaded;
private static string ResolveDirectory()
{
var assembly = typeof(TicketOverviewDataStore).GetTypeInfo().Assembly;
var baseDirectory = Path.GetDirectoryName(assembly.Location);
return Path.Combine(baseDirectory ?? string.Empty, "MockupTicketOverview");
}
private static string ResolveFilePath()
{
var directory = ResolveDirectory();
return Path.Combine(directory, FileName);
}
private static DemoTicketData ReadDataUnsafe()
{
try
{
var filePath = ResolveFilePath();
if (!File.Exists(filePath))
return new DemoTicketData();
var json = File.ReadAllText(filePath);
if (string.IsNullOrWhiteSpace(json))
return new DemoTicketData();
var data = JsonConvert.DeserializeObject<DemoTicketData>(json);
return data ?? new DemoTicketData();
}
catch
{
return new DemoTicketData();
}
}
private static DemoTicketJournalEntry CloneJournalEntry(DemoTicketJournalEntry source)
{
if (source == null)
return new DemoTicketJournalEntry();
return new DemoTicketJournalEntry
{
Header = source.Header,
Description = source.Description,
DescriptionHtml = source.DescriptionHtml,
IsVisibleForUser = source.IsVisibleForUser,
CreationDate = source.CreationDate
};
}
private static DemoTicketDetail CloneDetail(DemoTicketDetail source)
{
if (source == null)
return new DemoTicketDetail();
return new DemoTicketDetail
{
AffectedUser = source.AffectedUser,
Asset = source.Asset,
Category = source.Category,
Description = source.Description,
DescriptionHtml = source.DescriptionHtml,
Priority = source.Priority,
Solution = source.Solution,
SolutionHtml = source.SolutionHtml,
Journal = source.Journal?.Select(CloneJournalEntry).ToList() ?? new List<DemoTicketJournalEntry>()
};
}
private static DemoTicketTemplate CloneTemplate(DemoTicketTemplate source)
{
if (source == null)
return new DemoTicketTemplate();
return new DemoTicketTemplate
{
TileKey = source.TileKey,
UseRoleScope = source.UseRoleScope,
UserId = source.UserId,
ActivityType = source.ActivityType,
DisplayNamePrefix = source.DisplayNamePrefix,
Summary = source.Summary,
StatusId = source.StatusId,
UserDisplayName = source.UserDisplayName,
UserAccount = source.UserAccount,
UserDomain = source.UserDomain,
Detail = CloneDetail(source.Detail)
};
}
private static DemoTicketRecord CloneRecord(DemoTicketRecord source)
{
if (source == null)
return null;
return new DemoTicketRecord
{
TicketId = source.TicketId,
UserId = source.UserId,
TileKey = source.TileKey,
UseRoleScope = source.UseRoleScope,
ActivityType = source.ActivityType,
DisplayName = source.DisplayName,
Summary = source.Summary,
StatusId = source.StatusId,
UserDisplayName = source.UserDisplayName,
UserAccount = source.UserAccount,
UserDomain = source.UserDomain,
CreatedAt = source.CreatedAt,
Detail = CloneDetail(source.Detail)
};
}
private static void EnsureLoaded()
{
if (_isLoaded)
return;
var data = ReadDataUnsafe();
_templateCache = data.Templates?.Select(CloneTemplate).ToList() ?? new List<DemoTicketTemplate>();
_runtimeTickets = data.Tickets?.Select(CloneRecord).Where(r => r != null).ToList() ?? new List<DemoTicketRecord>();
ResetNumberCounters();
_isLoaded = true;
}
private static void ResetNumberCounters()
{
_nextNumbers.Clear();
_numberWidths.Clear();
foreach (var kvp in SeedNumbers)
{
_nextNumbers[kvp.Key] = kvp.Value;
_numberWidths[kvp.Key] = SeedWidths.TryGetValue(kvp.Key, out var width)
? Math.Max(width, DefaultNumberWidth)
: DefaultNumberWidth;
}
foreach (var ticket in _runtimeTickets)
{
UpdateNumberCounterFromDisplayName(ticket?.DisplayName);
}
}
private static void UpdateNumberCounterFromDisplayName(string displayName)
{
if (string.IsNullOrWhiteSpace(displayName))
return;
int i = 0;
while (i < displayName.Length && char.IsLetter(displayName[i]))
i++;
if (i == 0)
return;
var prefix = displayName.Substring(0, i).ToUpperInvariant();
int j = i;
while (j < displayName.Length && char.IsDigit(displayName[j]))
j++;
if (j == i)
return;
var numericSegment = displayName.Substring(i, j - i);
if (!int.TryParse(numericSegment, out var number))
return;
var width = Math.Max(DefaultNumberWidth, numericSegment.Length);
if (!_nextNumbers.TryGetValue(prefix, out var current))
current = SeedNumbers.TryGetValue(prefix, out var seedValue) ? seedValue : 1;
if (number >= current)
_nextNumbers[prefix] = number + 1;
if (_numberWidths.TryGetValue(prefix, out var currentWidth))
_numberWidths[prefix] = Math.Max(currentWidth, width);
else
_numberWidths[prefix] = width;
}
private static string ReserveDisplayName(string prefix)
{
prefix = string.IsNullOrWhiteSpace(prefix) ? "TCK" : prefix.ToUpperInvariant();
if (!_nextNumbers.TryGetValue(prefix, out var next))
next = SeedNumbers.TryGetValue(prefix, out var seedValue) ? seedValue : 1;
var width = _numberWidths.TryGetValue(prefix, out var storedWidth) ? Math.Max(storedWidth, DefaultNumberWidth) : DefaultNumberWidth;
var nextString = next.ToString();
if (nextString.Length > width)
width = nextString.Length;
var displayName = $"{prefix}{nextString.PadLeft(width, '0')}";
_nextNumbers[prefix] = next + 1;
_numberWidths[prefix] = width;
return displayName;
}
public static DemoTicketData LoadData()
{
lock (SyncRoot)
{
EnsureLoaded();
return new DemoTicketData
{
Templates = _templateCache.Select(CloneTemplate).ToList(),
Tickets = _runtimeTickets.Select(CloneRecord).Where(r => r != null).ToList()
};
}
}
public static List<DemoTicketRecord> LoadTickets()
{
lock (SyncRoot)
{
EnsureLoaded();
return _runtimeTickets.Select(CloneRecord).Where(r => r != null).ToList();
}
}
public static List<DemoTicketTemplate> LoadTemplates()
{
lock (SyncRoot)
{
EnsureLoaded();
return _templateCache.Select(CloneTemplate).ToList();
}
}
public static bool AppendTicket(DemoTicketRecord record)
{
if (record == null)
return false;
lock (SyncRoot)
{
EnsureLoaded();
if (_runtimeTickets.Any(t => t.TicketId == record.TicketId))
return false;
var clone = CloneRecord(record);
if (clone == null)
return false;
_runtimeTickets.Add(clone);
UpdateNumberCounterFromDisplayName(clone.DisplayName);
return true;
}
}
public static string GetNextDisplayName(string prefix)
{
lock (SyncRoot)
{
EnsureLoaded();
return ReserveDisplayName(prefix);
}
}
}
}