diff --git a/AuroraRecordGenerator/RecordEditor.xaml.cs b/AuroraRecordGenerator/RecordEditor.xaml.cs index eb42bbe..864d4f6 100644 --- a/AuroraRecordGenerator/RecordEditor.xaml.cs +++ b/AuroraRecordGenerator/RecordEditor.xaml.cs @@ -1,11 +1,11 @@ -using System; +using MahApps.Metro.Controls.Dialogs; +using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Linq; using System.Windows; using System.Windows.Controls; -using MahApps.Metro.Controls.Dialogs; -using System.Collections.Generic; -using System.Linq; namespace AuroraRecordGenerator { @@ -21,6 +21,7 @@ namespace AuroraRecordGenerator DataContext = Data; ProtoBuf.Serializer.PrepareSerializer(); ProtoBuf.Serializer.PrepareSerializer(); + ProtoBuf.Serializer.PrepareSerializer(); ProtoBuf.Serializer.PrepareSerializer(); InitializeComponent(); SubSpeciesCombo.ItemsSource = GetSpeciesOptions(); @@ -29,13 +30,12 @@ namespace AuroraRecordGenerator private Record Data { get; set; } private string _currentFilePath; - private void SpeciesSelectChanged(object sender, SelectionChangedEventArgs e) { if (SpeciesCombo.SelectionBoxItem == null) return; - var type = (SpeciesType) SpeciesCombo.SelectedValue; + var type = (SpeciesType)SpeciesCombo.SelectedValue; switch (type) { @@ -55,13 +55,19 @@ namespace AuroraRecordGenerator Debug.WriteLine("Enabled GenderCombo, type is " + type); GenderCombo.IsEnabled = true; break; + case SpeciesType.None: break; + default: throw new ArgumentOutOfRangeException(); } - SubSpeciesCombo.ItemsSource = GetSpeciesOptions(type); + Debug.WriteLine("Updating subspecies types."); + var types = GetSpeciesOptions(type); + var itemsSource = types as IList ?? types.ToList(); + SubSpeciesCombo.ItemsSource = itemsSource; + Debug.WriteLine($"New types: {string.Join(",", itemsSource)}"); } private void WindowLoaded(object sender, RoutedEventArgs e) @@ -88,15 +94,17 @@ namespace AuroraRecordGenerator switch ( await this.ShowMessageAsync("File Error", - "Current file missing, renamed or deleted. Do you want to save as another name?", + "Current file missing, renamed, or deleted. Do you want to save as another name?", MessageDialogStyle.AffirmativeAndNegative)) { case MessageDialogResult.Negative: _currentFilePath = null; return; + case MessageDialogResult.Affirmative: SaveContentAs(null, null); return; + default: throw new ArgumentOutOfRangeException(); } @@ -130,7 +138,9 @@ namespace AuroraRecordGenerator { var dialog = new Microsoft.Win32.SaveFileDialog { - AddExtension = true, CheckPathExists = true, Filter = "Character Profiles (*.ss13prof)|*.ss13prof|All Files (*.*)|*.*" + AddExtension = true, + CheckPathExists = true, + Filter = "Character Profiles (*.ss13prof)|*.ss13prof|All Files (*.*)|*.*" }; if (!(dialog.ShowDialog() ?? false)) return; var fs = File.Open(dialog.FileName, FileMode.Create); @@ -138,14 +148,17 @@ namespace AuroraRecordGenerator _currentFilePath = dialog.FileName; } - public static IList GetSpeciesOptions() - { - return Enum.GetValues(typeof(SpeciesSubType)).Cast().Select(item => Utility.SubspeciesNiceName(item)).ToList(); - } + private static IEnumerable GetSpeciesOptions() => Enum.GetValues(typeof(SpeciesSubType)).Cast().Select(Utility.SubspeciesNiceName); - public static IList GetSpeciesOptions(SpeciesType limitTo) + private static IEnumerable GetSpeciesOptions(SpeciesType limitTo) { - return Enum.GetValues(typeof(SpeciesSubType)).Cast().Select(item => Utility.SubspeciesNiceName(item)).ToList(); + var targetAttr = limitTo.GetAttributeOfType()?.AssociatedSpecies; + if (targetAttr == null) + return GetSpeciesOptions(); + return from item in Enum.GetValues(typeof(SpeciesSubType)).Cast() + let attr = item.GetAttributeOfType() + where attr != null && attr.AssociatedSpecies == targetAttr + select Utility.SubspeciesNiceName(item); } } -} +} \ No newline at end of file diff --git a/AuroraRecordGenerator/RecordFormatter.cs b/AuroraRecordGenerator/RecordFormatter.cs index bcbe6ba..c6c728b 100644 --- a/AuroraRecordGenerator/RecordFormatter.cs +++ b/AuroraRecordGenerator/RecordFormatter.cs @@ -6,30 +6,15 @@ namespace AuroraRecordGenerator { internal partial class RecordFormatter { - public Record TargetRecord - { - get { return _targetRecord; } - set - { - UpdateSplitRecords(); - MakeCommonRecords(); - _lastRecordHash = value.GetHashCode(); - _targetRecord = value; - } - } + private Record _targetRecord; public RecordFormatter(Record r) { _targetRecord = r; UpdateSplitRecords(); MakeCommonRecords(); - _lastRecordHash = r.GetHashCode(); } - private Record _targetRecord; - - private int? _lastRecordHash; - private IList _medicalPublicRecord; private IList _medicalHistory; private IList _medicalNotes; @@ -48,7 +33,6 @@ namespace AuroraRecordGenerator private IList _employmentNtEmployment; private IList _employmentSkills; - private void UpdateSplitRecords() { if (_targetRecord == null) @@ -79,50 +63,14 @@ namespace AuroraRecordGenerator // flush the record cache so they're regenerated _commonRecords = null; - _medicalRecordGenerated = null; - _securityRecordGenerated = null; - _employmentRecordGenerated = null; } - public string EmploymentRecords - { - get - { - //if (_employmentRecordGenerated.IsEmpty()) - MakeEmploymentRecords(); - return _employmentRecordGenerated; - } - } - - private string _employmentRecordGenerated; - - public string MedicalRecords - { - get - { - //if (_medicalRecordGenerated.IsEmpty()) - MakeMedicalRecords(); - return _medicalRecordGenerated; - } - } - - private string _medicalRecordGenerated; - - public string SecurityRecords - { - get - { - //if (_securityRecordGenerated.IsEmpty()) - MakeSecurityRecords(); - return _securityRecordGenerated; - } - } - - private string _securityRecordGenerated; + public string EmploymentRecords => MakeEmploymentRecords(); + public string MedicalRecords => MakeMedicalRecords(); + public string SecurityRecords => MakeSecurityRecords(); private string _commonRecords; - /// /// Writes the form of a record section to the specified , as long as there's entries to write. /// @@ -137,19 +85,6 @@ namespace AuroraRecordGenerator builder.AppendLine(entries.FormatAsList()); } - /// - /// Writes the form of a record section to the specified , as long as there's entries to write. - /// Inserts a newline before the section. - /// - /// The to write to. - /// The title for the section. - /// The entries of this section. - private static void WritePrefixedSectionifAny(ref StringBuilder builder, string header, IList entries) - { - builder.AppendLine(); - WriteSectionIfAny(ref builder, header, entries); - } - private string MakeNameLine() { var builder = new StringBuilder("Name: "); diff --git a/AuroraRecordGenerator/RecordFormatterGenerationMethods.cs b/AuroraRecordGenerator/RecordFormatterGenerationMethods.cs index 18e72e1..021abc2 100644 --- a/AuroraRecordGenerator/RecordFormatterGenerationMethods.cs +++ b/AuroraRecordGenerator/RecordFormatterGenerationMethods.cs @@ -1,6 +1,6 @@ -using System.Linq; +using Humanizer; +using System.Linq; using System.Text; -using Humanizer; namespace AuroraRecordGenerator { @@ -20,15 +20,17 @@ namespace AuroraRecordGenerator record.AppendLine($"Clearance Level: {_targetRecord.Clearance.IfEmpty("Not Specified")}"); record.AppendLine($"Employed As: {_targetRecord.EmployedAs.IfEmpty("Assistant")}"); if (_targetRecord.CharHeight != null) - record.AppendLine($"Height: {_targetRecord.CharHeight} cm ({Utility.CmToFeet(_targetRecord.CharHeight.Value)})"); + record.AppendLine($"Height: {_targetRecord.CharHeight} cm");// ({Utility.CmToFeet(_targetRecord.CharHeight.Value)}) if (_targetRecord.Weight != null) - record.AppendLine($"Weight: {_targetRecord.Weight} kg ({Utility.KgToLb(_targetRecord.Weight ?? 0)})"); - - record.AppendLine(); + record.AppendLine($"Weight: {_targetRecord.Weight} kg ({Utility.KgToLb(_targetRecord.Weight ?? 0)} lb)"); // identifying features - // TODO: identifying features + var trimmedFeatures = _targetRecord.DistinguishingFeatures.Trim(); + if (trimmedFeatures.Length > 0) + record.AppendLine($"Distinguishing Features: {trimmedFeatures}"); + + record.AppendLine(); // general notes WriteSectionIfAny(ref record, @@ -46,7 +48,7 @@ namespace AuroraRecordGenerator _commonRecords = record.ToString(); } - private void MakeEmploymentRecords() + private string MakeEmploymentRecords() { var recordText = new StringBuilder(); if (_commonRecords.IsEmpty()) @@ -89,10 +91,10 @@ namespace AuroraRecordGenerator _employmentSkills); } - _employmentRecordGenerated = recordText.ToString(); + return recordText.ToString(); } - private void MakeMedicalRecords() + private string MakeMedicalRecords() { var recordText = new StringBuilder(); if (_commonRecords.IsEmpty()) @@ -106,10 +108,10 @@ namespace AuroraRecordGenerator !_medicalPsychHistory.Any() && !_medicalPsychNotes.Any() && !_medicalPrescriptions.Any() && - !TargetRecord.NoBorg && - !TargetRecord.NoClone && - !TargetRecord.NoProsthetic && - !TargetRecord.NoRevive) + !_targetRecord.NoBorg && + !_targetRecord.NoClone && + !_targetRecord.NoProsthetic && + !_targetRecord.NoRevive) { recordText.AppendLine("/// NO MEDICAL RECORD FOUND ///"); } @@ -121,20 +123,20 @@ namespace AuroraRecordGenerator recordText.AppendLine( " The following information is protected by doctor-patient confidentiality laws. Do not release without patient's consent.\n"); - if (TargetRecord.NoBorg || TargetRecord.NoClone || TargetRecord.NoProsthetic || TargetRecord.NoRevive) + if (_targetRecord.NoBorg || _targetRecord.NoClone || _targetRecord.NoProsthetic || _targetRecord.NoRevive) { recordText.AppendLine("IMPORTANT NOTES:"); - if (TargetRecord.NoBorg) + if (_targetRecord.NoBorg) MakeMedicalNote(ref recordText, "DO NOT BORGIFY"); - if (TargetRecord.NoClone) + if (_targetRecord.NoClone) MakeMedicalNote(ref recordText, "DO NOT CLONE"); - if (TargetRecord.NoProsthetic) + if (_targetRecord.NoProsthetic) MakeMedicalNote(ref recordText, "DO NOT INSTALL PROSTHETICS"); - if (TargetRecord.NoRevive) + if (_targetRecord.NoRevive) MakeMedicalNote(ref recordText, "DO NOT REVIVE"); recordText.AppendLine(); @@ -161,10 +163,10 @@ namespace AuroraRecordGenerator _medicalPrescriptions); } - _medicalRecordGenerated = recordText.ToString(); + return recordText.ToString(); } - private void MakeSecurityRecords() + private string MakeSecurityRecords() { var recordText = new StringBuilder(); if (_commonRecords.IsEmpty()) @@ -190,7 +192,7 @@ namespace AuroraRecordGenerator _securityRecords); } - _securityRecordGenerated = recordText.ToString(); + return recordText.ToString(); } } } diff --git a/AuroraRecordGenerator/Types.cs b/AuroraRecordGenerator/Types.cs index a32b443..a1aba93 100644 --- a/AuroraRecordGenerator/Types.cs +++ b/AuroraRecordGenerator/Types.cs @@ -1,5 +1,5 @@ -using System; -using ProtoBuf; +using ProtoBuf; +using System; namespace AuroraRecordGenerator { @@ -8,18 +8,25 @@ namespace AuroraRecordGenerator { [ProtoEnum] None = 0, + [ProtoEnum] Human, + [ProtoEnum] Skrell, + [ProtoEnum] Tajara, + [ProtoEnum] Unathi, + [ProtoEnum] Vaurca, + [ProtoEnum] Diona, + [ProtoEnum] IPC } @@ -29,17 +36,23 @@ namespace AuroraRecordGenerator { [ProtoEnum] None = 0, - [ProtoEnum] + + [ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "M'sai")] MsaiTajara, - [ProtoEnum] + + [ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "Zhan-Khazan")] ZhanTajara, - [ProtoEnum] + + [ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type A (Worker)")] VaurcaWorker, - [ProtoEnum] + + [ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type B (Warrior)")] VaurcaWarrior, - [ProtoEnum] + + [ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Shell Frame")] IpcShell, - [ProtoEnum] + + [ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Industrial Frame")] IpcG1Industrial } @@ -48,8 +61,10 @@ namespace AuroraRecordGenerator { [ProtoEnum] NotApplicable = 0, + [ProtoEnum] Male, + [ProtoEnum] Female } @@ -59,8 +74,20 @@ namespace AuroraRecordGenerator /// /// The current in-character date. /// - public static DateTime IcDate => new DateTime(2458, + public static DateTime IcDate => new DateTime(DateTime.Now.Year + 442, DateTime.Now.Month, DateTime.Now.Day); } -} + + [AttributeUsage(AttributeTargets.Field)] + public class SubspeciesMetaAttribute : Attribute + { + public SpeciesType AssociatedSpecies {get; private set;} + public string NiceName { get; private set; } + public SubspeciesMetaAttribute(SpeciesType associatedType, string nicename) + { + AssociatedSpecies = associatedType; + NiceName = nicename; + } + } +} \ No newline at end of file diff --git a/AuroraRecordGenerator/Utility.cs b/AuroraRecordGenerator/Utility.cs index 2f0110f..568cec5 100644 --- a/AuroraRecordGenerator/Utility.cs +++ b/AuroraRecordGenerator/Utility.cs @@ -7,77 +7,20 @@ namespace AuroraRecordGenerator { public static class Utility { - /// - /// Splits a string into an array of strings. - /// - /// The string to split. - /// How large each string probably will be. Specify to theoretically improve performance. - /// Array of chars to split on. - /// - public static IEnumerable LazySplit(this string source, int predictedSplitLen, params char[] splitValues) - { - var builder = predictedSplitLen <= 0 - ? new StringBuilder() - : new StringBuilder(predictedSplitLen); - foreach (var c in source) - { - if (splitValues.Contains(c)) - { - // split off string - var result = builder.ToString(); - builder.Clear(); - yield return result; - } - - builder.Append(c); - } - } - - /// - /// Splits a string into an array of strings. - /// - /// The string to split. - /// Array of chars to split on. - /// - public static IEnumerable LazySplit(this string source, params char[] splitValues) => - source.LazySplit(-1, splitValues); - - /// - /// Splits a string into an array of strings. - /// - /// The string to split. - /// How large each string probably will be. Specify to theoretically improve performance. - /// Char to split on. - /// - public static IEnumerable LazySplit(this string source, int predictedSplitLen, char splitValue) - { - var builder = predictedSplitLen <= 0 - ? new StringBuilder() - : new StringBuilder(predictedSplitLen); - foreach (var c in source) - { - if (c == splitValue) - { - // split off string - var result = builder.ToString(); - builder.Clear(); - yield return result; - } - - builder.Append(c); - } - } - - public static IList LineSplit(this string source) => + public static IList LineSplit(this string source) => source.Split('\n').Where(item => item.Trim().Length != 0).ToList(); - public static string CmToFeet(double cm) { return "0'0\""; } - public static string KgToLb(double kg) => $"{Math.Round(kg * 2.2046, 2)} lb"; + /// + /// Converts a weight in Kilograms to Pounds. + /// + /// The weight in kilograms. + /// The weight converted to pounds. + public static double KgToLb(double kg) => Math.Round(kg * 2.2046, 2); /// /// Returns and a trailing space if val is not whitespace, otherwise. @@ -91,12 +34,12 @@ namespace AuroraRecordGenerator public static bool IsEmpty(this string val) => string.IsNullOrWhiteSpace(val); - public static string FormatAsList(this IEnumerable target) => + public static string FormatAsList(this IEnumerable target) => target.Aggregate(new StringBuilder(), (b, s) => b.AppendLine($" - {s.Trim()}")).ToString(); public static string Repeat(this string target, int repeatNum) { - var builder = new StringBuilder(target.Length*repeatNum); + var builder = new StringBuilder(target.Length * repeatNum); for (var i = 0; i < repeatNum; i++) builder.Append(target); @@ -113,23 +56,27 @@ namespace AuroraRecordGenerator public static string SubspeciesNiceName(SpeciesSubType species) { - switch (species) - { - case SpeciesSubType.MsaiTajara: - return "M'sai"; - case SpeciesSubType.ZhanTajara: - return "Zhan-Khazan"; - case SpeciesSubType.VaurcaWorker: - return "Worker (Type A)"; - case SpeciesSubType.VaurcaBreeder: - return "Warrior (Type B)"; - case SpeciesSubType.IpcShell: - return "Shell Frame"; - case SpeciesSubType.IpcG1Industrial: - return "Industrial Frame"; - default: - return Enum.GetName(typeof(SpeciesSubType), species); - } + var attr = species.GetAttributeOfType(); + return attr?.NiceName ?? Enum.GetName(typeof(SpeciesSubType), species); } } -} + + // From https://stackoverflow.com/questions/1799370/getting-attributes-of-enums-value + public static class EnumHelper + { + /// + /// Gets an attribute on an enum field value + /// + /// The type of the attribute you want to retrieve + /// The enum value + /// The attribute of type T that exists on the enum value + /// string desc = myEnumVariable.GetAttributeOfType().Description; + public static T GetAttributeOfType(this Enum enumVal) where T : Attribute + { + var type = enumVal.GetType(); + var memInfo = type.GetMember(enumVal.ToString()); + var attributes = memInfo[0].GetCustomAttributes(typeof(T), false); + return attributes.Length > 0 ? (T)attributes[0] : null; + } + } +} \ No newline at end of file