using System; using System.Collections.Generic; using System.Linq; namespace Nox.Game { public interface IPartyFactory { PartyDefinition Create(CharacterDefinition protagonist, IEnumerable companions = null); } public sealed class PartyFactory : IPartyFactory { private readonly StarterCharacterSettings starterCharacterSettings; public PartyFactory(StarterCharacterSettings starterCharacterSettings) { this.starterCharacterSettings = starterCharacterSettings; } public PartyDefinition Create(CharacterDefinition protagonist, IEnumerable companions = null) { if(protagonist == null) { throw new ArgumentNullException(nameof(protagonist)); } var party = new PartyDefinition { maxPartySize = starterCharacterSettings.maxPartySize <= 0 ? int.MaxValue : starterCharacterSettings.maxPartySize }; var protagonistClone = protagonist.Clone(); protagonistClone.Role = CharacterRole.Protagonist; party.members.Add(protagonistClone); if(companions != null) { foreach(var companion in companions.Where(c => c != null)) { var companionClone = companion.Clone(); companionClone.Role = CharacterRole.Companion; party.members.Add(companionClone); } } ValidateParty(party); return party; } private void ValidateParty(PartyDefinition party) { if(party.members.Count > party.maxPartySize) { throw new ArgumentException($"Party size {party.members.Count} exceeds max {party.maxPartySize}."); } var protagonistCount = party.members.Count(m => m.Role == CharacterRole.Protagonist); if(protagonistCount != 1) { throw new ArgumentException($"Party must contain exactly one protagonist, found {protagonistCount}."); } var uniqueIds = party.members .Where(m => m.ID != Guid.Empty) .Select(m => m.ID) .Distinct() .Count(); if(uniqueIds != party.members.Count) { throw new ArgumentException("Party contains duplicate or missing character ids."); } } } }