diff --git a/AuroraRecordGenerator.sln b/AuroraRecordGenerator.sln
new file mode 100644
index 0000000..d7a4ef6
--- /dev/null
+++ b/AuroraRecordGenerator.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuroraRecordGenerator", "AuroraRecordGenerator\AuroraRecordGenerator.csproj", "{2E1295C2-7BD9-454E-B13E-8A22448DD5F6}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {2E1295C2-7BD9-454E-B13E-8A22448DD5F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2E1295C2-7BD9-454E-B13E-8A22448DD5F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2E1295C2-7BD9-454E-B13E-8A22448DD5F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2E1295C2-7BD9-454E-B13E-8A22448DD5F6}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/AuroraRecordGenerator/App.config b/AuroraRecordGenerator/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/AuroraRecordGenerator/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AuroraRecordGenerator/App.xaml b/AuroraRecordGenerator/App.xaml
new file mode 100644
index 0000000..ed174d1
--- /dev/null
+++ b/AuroraRecordGenerator/App.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AuroraRecordGenerator/App.xaml.cs b/AuroraRecordGenerator/App.xaml.cs
new file mode 100644
index 0000000..4f57d35
--- /dev/null
+++ b/AuroraRecordGenerator/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace AuroraRecordGenerator
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/AuroraRecordGenerator/AuroraRecordGenerator.csproj b/AuroraRecordGenerator/AuroraRecordGenerator.csproj
new file mode 100644
index 0000000..86d24a6
--- /dev/null
+++ b/AuroraRecordGenerator/AuroraRecordGenerator.csproj
@@ -0,0 +1,135 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {2E1295C2-7BD9-454E-B13E-8A22448DD5F6}
+ WinExe
+ Properties
+ AuroraRecordGenerator
+ AuroraRecordGenerator
+ v4.5.2
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Humanizer.Core.2.1.0\lib\netstandard1.0\Humanizer.dll
+ True
+
+
+ ..\packages\MahApps.Metro.1.3.0\lib\net45\MahApps.Metro.dll
+ True
+
+
+ ..\packages\protobuf-net.2.1.0\lib\net451\protobuf-net.dll
+ True
+
+
+
+
+ ..\packages\MahApps.Metro.1.3.0\lib\net45\System.Windows.Interactivity.dll
+ True
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ GeneratedResultWindow.xaml
+
+
+
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ RecordEditor.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AuroraRecordGenerator/GeneratedResultWindow.xaml b/AuroraRecordGenerator/GeneratedResultWindow.xaml
new file mode 100644
index 0000000..571d784
--- /dev/null
+++ b/AuroraRecordGenerator/GeneratedResultWindow.xaml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AuroraRecordGenerator/GeneratedResultWindow.xaml.cs b/AuroraRecordGenerator/GeneratedResultWindow.xaml.cs
new file mode 100644
index 0000000..6581d4a
--- /dev/null
+++ b/AuroraRecordGenerator/GeneratedResultWindow.xaml.cs
@@ -0,0 +1,18 @@
+namespace AuroraRecordGenerator
+{
+ public partial class GeneratedResultWindow
+ {
+ public GeneratedResultWindow()
+ {
+ InitializeComponent();
+ }
+
+ public GeneratedResultWindow(Record record) : this()
+ {
+ var formatter = new RecordFormatter(record);
+ EmploymentBox.Text = formatter.EmploymentRecords;
+ MedicalBox.Text = formatter.MedicalRecords;
+ SecurityBox.Text = formatter.SecurityRecords;
+ }
+ }
+}
diff --git a/AuroraRecordGenerator/Properties/AssemblyInfo.cs b/AuroraRecordGenerator/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..217f1fa
--- /dev/null
+++ b/AuroraRecordGenerator/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AuroraRecordGenerator")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("AuroraRecordGenerator")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/AuroraRecordGenerator/Properties/Resources.Designer.cs b/AuroraRecordGenerator/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..b385641
--- /dev/null
+++ b/AuroraRecordGenerator/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AuroraRecordGenerator.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("AuroraRecordGenerator.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/AuroraRecordGenerator/Properties/Resources.resx b/AuroraRecordGenerator/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/AuroraRecordGenerator/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/AuroraRecordGenerator/Properties/Settings.Designer.cs b/AuroraRecordGenerator/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..5ea6d6e
--- /dev/null
+++ b/AuroraRecordGenerator/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AuroraRecordGenerator.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/AuroraRecordGenerator/Properties/Settings.settings b/AuroraRecordGenerator/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/AuroraRecordGenerator/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AuroraRecordGenerator/Record.cs b/AuroraRecordGenerator/Record.cs
new file mode 100644
index 0000000..1d94c70
--- /dev/null
+++ b/AuroraRecordGenerator/Record.cs
@@ -0,0 +1,117 @@
+using System;
+using ProtoBuf;
+
+namespace AuroraRecordGenerator
+{
+ [ProtoContract]
+ public class Record
+ {
+ // Defaults defined here will automatically populate the form on program load
+ [ProtoMember(1)]
+ public string FirstName { get; set; } = string.Empty;
+
+ [ProtoMember(2)]
+ public string MiddleName { get; set; } = string.Empty;
+
+ [ProtoMember(3)]
+ public string LastName { get; set; } = string.Empty;
+
+ [ProtoMember(4)]
+ public string NameSuffix { get; set; } = string.Empty;
+
+ [ProtoMember(5, IsRequired = true)]
+ public SpeciesType Species { get; set; } = SpeciesType.Human;
+
+ [ProtoMember(6, IsRequired = true)]
+ public GenderType Gender { get; set; }
+
+ [ProtoMember(7)]
+ public DateTime BirthDate { get; set; } = DateTime.Parse("1/1/2458");
+
+ [ProtoMember(8)]
+ public double? CharHeight { get; set; } = 170;
+
+ [ProtoMember(9)]
+ public double? Weight { get; set; } = 70;
+
+ [ProtoMember(10)]
+ public string SkinColor { get; set; } = string.Empty;
+
+ [ProtoMember(11)]
+ public string EyeColor { get; set; } = string.Empty;
+
+ [ProtoMember(12)]
+ public string DistinguishingFeatures { get; set; } = string.Empty;
+
+ [ProtoMember(13)]
+ public string HairColor { get; set; } = string.Empty;
+
+ [ProtoMember(14)]
+ public string EmployedAs { get; set; } = string.Empty;
+
+ [ProtoMember(15)]
+ public string Citizenship { get; set; } = string.Empty;
+
+ // 16 & 17 used to be PictureUrl and PictureCredit, now unused.
+
+ [ProtoMember(18)]
+ public string Clearance { get; set; } = string.Empty;
+
+ [ProtoMember(19)]
+ public string MedicalPublicRecord { get; set; } = string.Empty;
+
+ [ProtoMember(20)]
+ public string MedicalHistory { get; set; } = string.Empty;
+
+ [ProtoMember(21)]
+ public string MedicalNotes { get; set; } = string.Empty;
+
+ [ProtoMember(22)]
+ public string MedicalPsychHistory { get; set; } = string.Empty;
+
+ [ProtoMember(23)]
+ public string MedicalPsychNotes { get; set; } = string.Empty;
+
+ [ProtoMember(24)]
+ public bool NoBorg { get; set; } = false;
+
+ [ProtoMember(25)]
+ public bool NoClone { get; set; } = false;
+
+ [ProtoMember(26)]
+ public bool NoRevive { get; set; } = false;
+
+ [ProtoMember(27)]
+ public bool NoProsthetic { get; set; } = false;
+
+ [ProtoMember(28)]
+ public string MedicalPrescriptions { get; set; } = string.Empty;
+
+ [ProtoMember(29)]
+ public string SecurityPublicRecord { get; set; } = string.Empty;
+
+ [ProtoMember(30)]
+ public string SecurityRecords { get; set; } = string.Empty;
+
+ [ProtoMember(31)]
+ public string SecurityNotes { get; set; } = string.Empty;
+
+ [ProtoMember(32)]
+ public string EmploymentPublicRecord { get; set; } = string.Empty;
+
+ [ProtoMember(33)]
+ public string EmploymentExperience { get; set; } = string.Empty;
+
+ [ProtoMember(34)]
+ public string EmploymentPreNtEmployment { get; set; } = string.Empty;
+
+ [ProtoMember(35)]
+ public string EmploymentFormalEducation { get; set; } = string.Empty;
+
+ [ProtoMember(36)]
+ public string EmploymentNtEmploymentHistory { get; set; } = string.Empty;
+
+ [ProtoMember(37)]
+ public string EmploymentSkills { get; set; } = string.Empty;
+ }
+}
\ No newline at end of file
diff --git a/AuroraRecordGenerator/RecordEditor.xaml b/AuroraRecordGenerator/RecordEditor.xaml
new file mode 100644
index 0000000..b57c511
--- /dev/null
+++ b/AuroraRecordGenerator/RecordEditor.xaml
@@ -0,0 +1,385 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AuroraRecordGenerator/RecordEditor.xaml.cs b/AuroraRecordGenerator/RecordEditor.xaml.cs
new file mode 100644
index 0000000..eb42bbe
--- /dev/null
+++ b/AuroraRecordGenerator/RecordEditor.xaml.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Windows;
+using System.Windows.Controls;
+using MahApps.Metro.Controls.Dialogs;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace AuroraRecordGenerator
+{
+ ///
+ /// Interaction logic for RecordEditor.xaml
+ ///
+ public partial class RecordEditor
+ {
+ public RecordEditor()
+ {
+ // Initialize the record object used for storage and generation
+ Data = new Record();
+ DataContext = Data;
+ ProtoBuf.Serializer.PrepareSerializer();
+ ProtoBuf.Serializer.PrepareSerializer();
+ ProtoBuf.Serializer.PrepareSerializer();
+ InitializeComponent();
+ SubSpeciesCombo.ItemsSource = GetSpeciesOptions();
+ }
+
+ 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;
+
+ switch (type)
+ {
+ // non-gendered species
+ case SpeciesType.Diona:
+ case SpeciesType.IPC:
+ case SpeciesType.Vaurca:
+ Debug.WriteLine("Disabled GenderCombo, type is " + type);
+ GenderCombo.IsEnabled = false;
+ GenderCombo.Text = "N/A";
+ break;
+ // gendered species
+ case SpeciesType.Human:
+ case SpeciesType.Skrell:
+ case SpeciesType.Tajara:
+ case SpeciesType.Unathi:
+ Debug.WriteLine("Enabled GenderCombo, type is " + type);
+ GenderCombo.IsEnabled = true;
+ break;
+ case SpeciesType.None:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ SubSpeciesCombo.ItemsSource = GetSpeciesOptions(type);
+ }
+
+ private void WindowLoaded(object sender, RoutedEventArgs e)
+ {
+ SpeciesCombo.SelectedIndex = 0;
+ }
+
+ private void GenerateRecord(object sender, RoutedEventArgs e)
+ {
+ // THIS IS IT
+ var wnd = new GeneratedResultWindow(Data);
+ wnd.Show();
+ }
+
+ private async void SaveContent(object sender, RoutedEventArgs e)
+ {
+ if (string.IsNullOrWhiteSpace(_currentFilePath))
+ SaveContentAs(null, null);
+ else
+ {
+ // have a path, attempt to save to it
+ if (!File.Exists(_currentFilePath))
+ {
+ switch (
+ await
+ this.ShowMessageAsync("File Error",
+ "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();
+ }
+ }
+
+ var fs = File.Open(_currentFilePath, FileMode.Truncate);
+ ProtoBuf.Serializer.Serialize(fs, Data);
+ }
+ }
+
+ private void OpenContent(object sender, RoutedEventArgs e)
+ {
+ var dialog = new Microsoft.Win32.OpenFileDialog
+ {
+ AddExtension = true,
+ CheckFileExists = true,
+ CheckPathExists = true,
+ Filter = "Character Profiles (*.ss13prof)|*.ss13prof|All Files (*.*)|*.*"
+ };
+
+ if (!(dialog.ShowDialog() ?? false)) return;
+
+ var fs = File.Open(dialog.FileName, FileMode.Open);
+ Data = ProtoBuf.Serializer.Deserialize(fs);
+ _currentFilePath = dialog.FileName;
+ // So WPF updates bindings
+ DataContext = Data;
+ }
+
+ private void SaveContentAs(object sender, RoutedEventArgs e)
+ {
+ var dialog = new Microsoft.Win32.SaveFileDialog
+ {
+ AddExtension = true, CheckPathExists = true, Filter = "Character Profiles (*.ss13prof)|*.ss13prof|All Files (*.*)|*.*"
+ };
+ if (!(dialog.ShowDialog() ?? false)) return;
+ var fs = File.Open(dialog.FileName, FileMode.Create);
+ ProtoBuf.Serializer.Serialize(fs, Data);
+ _currentFilePath = dialog.FileName;
+ }
+
+ public static IList GetSpeciesOptions()
+ {
+ return Enum.GetValues(typeof(SpeciesSubType)).Cast().Select(item => Utility.SubspeciesNiceName(item)).ToList();
+ }
+
+ public static IList GetSpeciesOptions(SpeciesType limitTo)
+ {
+ return Enum.GetValues(typeof(SpeciesSubType)).Cast().Select(item => Utility.SubspeciesNiceName(item)).ToList();
+ }
+ }
+}
diff --git a/AuroraRecordGenerator/RecordFormatter.cs b/AuroraRecordGenerator/RecordFormatter.cs
new file mode 100644
index 0000000..bcbe6ba
--- /dev/null
+++ b/AuroraRecordGenerator/RecordFormatter.cs
@@ -0,0 +1,166 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace AuroraRecordGenerator
+{
+ internal partial class RecordFormatter
+ {
+ public Record TargetRecord
+ {
+ get { return _targetRecord; }
+ set
+ {
+ UpdateSplitRecords();
+ MakeCommonRecords();
+ _lastRecordHash = value.GetHashCode();
+ _targetRecord = value;
+ }
+ }
+
+ 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;
+ private IList _medicalPsychHistory;
+ private IList _medicalPsychNotes;
+ private IList _medicalPrescriptions;
+
+ private IList _securityPublicRecord;
+ private IList _securityRecords;
+ private IList _securityNotes;
+
+ private IList _employmentPublicRecord;
+ private IList _employmentExperience;
+ private IList _employmentPreNtEmployment;
+ private IList _employmentFormalEducation;
+ private IList _employmentNtEmployment;
+ private IList _employmentSkills;
+
+
+ private void UpdateSplitRecords()
+ {
+ if (_targetRecord == null)
+ {
+ _targetRecord = new Record();
+ }
+
+ // Medical
+ _medicalPublicRecord = _targetRecord.MedicalPublicRecord?.LineSplit();
+ _medicalHistory = _targetRecord.MedicalHistory?.LineSplit();
+ _medicalNotes = _targetRecord.MedicalNotes?.LineSplit();
+ _medicalPsychHistory = _targetRecord.MedicalPsychHistory?.LineSplit();
+ _medicalPsychNotes = _targetRecord.MedicalPsychNotes?.LineSplit();
+ _medicalPrescriptions = _targetRecord.MedicalPrescriptions?.LineSplit();
+
+ // security
+ _securityPublicRecord = _targetRecord.SecurityPublicRecord?.LineSplit();
+ _securityRecords = _targetRecord.SecurityRecords?.LineSplit();
+ _securityNotes = _targetRecord.SecurityNotes?.LineSplit();
+
+ // employment
+ _employmentPublicRecord = _targetRecord.EmploymentPublicRecord?.LineSplit();
+ _employmentExperience = _targetRecord.EmploymentExperience?.LineSplit();
+ _employmentPreNtEmployment = _targetRecord.EmploymentPreNtEmployment?.LineSplit();
+ _employmentFormalEducation = _targetRecord.EmploymentFormalEducation?.LineSplit();
+ _employmentNtEmployment = _targetRecord.EmploymentNtEmploymentHistory?.LineSplit();
+ _employmentSkills = _targetRecord.EmploymentSkills?.LineSplit();
+
+ // 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;
+
+ private string _commonRecords;
+
+
+ ///
+ /// Writes the form of a record section to the specified , as long as there's entries to write.
+ ///
+ /// The to write to.
+ /// The title for the section.
+ /// The entries of this section.
+ private static void WriteSectionIfAny(ref StringBuilder builder, string header, IList entries)
+ {
+ if (entries == null || !entries.Any() || entries[0].Trim().Length == 0)
+ return;
+ builder.AppendLine(header);
+ 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: ");
+ builder.Append(_targetRecord.FirstName);
+ builder.Append(_targetRecord.MiddleName.SpaceIfValue());
+ builder.Append($" {_targetRecord.LastName}");
+ builder.Append(_targetRecord.NameSuffix.SpaceIfValue());
+ return builder.ToString();
+ }
+
+ private static void MakeMedicalNote(ref StringBuilder b, string s) =>
+ b.AppendLine($" - {s}");
+ }
+}
diff --git a/AuroraRecordGenerator/RecordFormatterGenerationMethods.cs b/AuroraRecordGenerator/RecordFormatterGenerationMethods.cs
new file mode 100644
index 0000000..18e72e1
--- /dev/null
+++ b/AuroraRecordGenerator/RecordFormatterGenerationMethods.cs
@@ -0,0 +1,196 @@
+using System.Linq;
+using System.Text;
+using Humanizer;
+
+namespace AuroraRecordGenerator
+{
+ internal partial class RecordFormatter
+ {
+ private void MakeCommonRecords()
+ {
+ var record = new StringBuilder();
+ record.AppendLine("/// PUBLIC RECORD ///");
+ record.AppendLine(MakeNameLine());
+ record.AppendLine($"Date of Birth: {_targetRecord.BirthDate.ToString("MMMM")} {_targetRecord.BirthDate.Day.Ordinalize()}, {_targetRecord.BirthDate.Year}");
+ record.AppendLine($"Species: {_targetRecord.Species.Humanize()}");// might fuck up the names
+ record.AppendLine(_targetRecord.Species.HasGender()
+ ? $"Gender: {_targetRecord.Gender.Humanize()}"
+ : "Gender: Not Applicable.");
+ record.AppendLine($"Citizenship: {_targetRecord.Citizenship.IfEmpty("None.")}");
+ 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)})");
+
+ if (_targetRecord.Weight != null)
+ record.AppendLine($"Weight: {_targetRecord.Weight} kg ({Utility.KgToLb(_targetRecord.Weight ?? 0)})");
+
+ record.AppendLine();
+
+ // identifying features
+ // TODO: identifying features
+
+ // general notes
+ WriteSectionIfAny(ref record,
+ "General Notes:",
+ _employmentPublicRecord);
+
+ WriteSectionIfAny(ref record,
+ "Medical Notes:",
+ _medicalPublicRecord);
+
+ WriteSectionIfAny(ref record,
+ "Security Notes:",
+ _securityPublicRecord);
+
+ _commonRecords = record.ToString();
+ }
+
+ private void MakeEmploymentRecords()
+ {
+ var recordText = new StringBuilder();
+ if (_commonRecords.IsEmpty())
+ MakeCommonRecords();
+
+ recordText.Append(_commonRecords);
+
+ if (!_employmentExperience.Any() &&
+ !_employmentFormalEducation.Any() &&
+ !_employmentNtEmployment.Any() &&
+ !_employmentPreNtEmployment.Any() &&
+ !_employmentPublicRecord.Any() &&
+ !_employmentSkills.Any())
+ {
+ recordText.AppendLine("/// NO EMPLOYMENT RECORD FOUND ///");
+ }
+ else
+ {
+ recordText.AppendLine("/// EMPLOYMENT RECORD ///");
+ recordText.AppendLine();
+
+ WriteSectionIfAny(ref recordText,
+ "Experience:",
+ _employmentExperience);
+
+ WriteSectionIfAny(ref recordText,
+ "Formal Education History:",
+ _employmentFormalEducation);
+
+ WriteSectionIfAny(ref recordText,
+ "Pre-NanoTrasen Employment History:",
+ _employmentPreNtEmployment);
+
+ WriteSectionIfAny(ref recordText,
+ "NanoTrasen Employment History:",
+ _employmentNtEmployment);
+
+ WriteSectionIfAny(ref recordText,
+ "Trained in the following:",
+ _employmentSkills);
+ }
+
+ _employmentRecordGenerated = recordText.ToString();
+ }
+
+ private void MakeMedicalRecords()
+ {
+ var recordText = new StringBuilder();
+ if (_commonRecords.IsEmpty())
+ MakeCommonRecords();
+
+ recordText.Append(_commonRecords);
+
+ // TODO: make this less horrible
+ if (!_medicalHistory.Any() &&
+ !_medicalNotes.Any() &&
+ !_medicalPsychHistory.Any() &&
+ !_medicalPsychNotes.Any() &&
+ !_medicalPrescriptions.Any() &&
+ !TargetRecord.NoBorg &&
+ !TargetRecord.NoClone &&
+ !TargetRecord.NoProsthetic &&
+ !TargetRecord.NoRevive)
+ {
+ recordText.AppendLine("/// NO MEDICAL RECORD FOUND ///");
+ }
+ else
+ {
+ recordText.AppendLine("/// MEDICAL RECORD ///");
+ recordText.AppendLine();
+
+ 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)
+ {
+ recordText.AppendLine("IMPORTANT NOTES:");
+
+ if (TargetRecord.NoBorg)
+ MakeMedicalNote(ref recordText, "DO NOT BORGIFY");
+
+ if (TargetRecord.NoClone)
+ MakeMedicalNote(ref recordText, "DO NOT CLONE");
+
+ if (TargetRecord.NoProsthetic)
+ MakeMedicalNote(ref recordText, "DO NOT INSTALL PROSTHETICS");
+
+ if (TargetRecord.NoRevive)
+ MakeMedicalNote(ref recordText, "DO NOT REVIVE");
+
+ recordText.AppendLine();
+ }
+
+ WriteSectionIfAny(ref recordText,
+ "Notes:",
+ _medicalNotes);
+
+ WriteSectionIfAny(ref recordText,
+ "Medical History:",
+ _medicalHistory);
+
+ WriteSectionIfAny(ref recordText,
+ "Psychiatric Notes:",
+ _medicalPsychNotes);
+
+ WriteSectionIfAny(ref recordText,
+ "Psychiatric History:",
+ _medicalPsychHistory);
+
+ WriteSectionIfAny(ref recordText,
+ "Prescriptions:",
+ _medicalPrescriptions);
+ }
+
+ _medicalRecordGenerated = recordText.ToString();
+ }
+
+ private void MakeSecurityRecords()
+ {
+ var recordText = new StringBuilder();
+ if (_commonRecords.IsEmpty())
+ MakeCommonRecords();
+
+ recordText.Append(_commonRecords);
+
+ if (!_securityRecords.Any() && !_securityNotes.Any())
+ {
+ recordText.AppendLine("/// NO SECURITY RECORD FOUND ///");
+ }
+ else
+ {
+ recordText.AppendLine("/// SECURITY RECORD ///");
+ recordText.AppendLine();
+
+ WriteSectionIfAny(ref recordText,
+ "Notes:",
+ _securityNotes);
+
+ WriteSectionIfAny(ref recordText,
+ "Record:",
+ _securityRecords);
+ }
+
+ _securityRecordGenerated = recordText.ToString();
+ }
+ }
+}
diff --git a/AuroraRecordGenerator/Types.cs b/AuroraRecordGenerator/Types.cs
new file mode 100644
index 0000000..a32b443
--- /dev/null
+++ b/AuroraRecordGenerator/Types.cs
@@ -0,0 +1,66 @@
+using System;
+using ProtoBuf;
+
+namespace AuroraRecordGenerator
+{
+ [ProtoContract]
+ public enum SpeciesType
+ {
+ [ProtoEnum]
+ None = 0,
+ [ProtoEnum]
+ Human,
+ [ProtoEnum]
+ Skrell,
+ [ProtoEnum]
+ Tajara,
+ [ProtoEnum]
+ Unathi,
+ [ProtoEnum]
+ Vaurca,
+ [ProtoEnum]
+ Diona,
+ [ProtoEnum]
+ IPC
+ }
+
+ [ProtoContract]
+ public enum SpeciesSubType
+ {
+ [ProtoEnum]
+ None = 0,
+ [ProtoEnum]
+ MsaiTajara,
+ [ProtoEnum]
+ ZhanTajara,
+ [ProtoEnum]
+ VaurcaWorker,
+ [ProtoEnum]
+ VaurcaWarrior,
+ [ProtoEnum]
+ IpcShell,
+ [ProtoEnum]
+ IpcG1Industrial
+ }
+
+ [ProtoContract]
+ public enum GenderType
+ {
+ [ProtoEnum]
+ NotApplicable = 0,
+ [ProtoEnum]
+ Male,
+ [ProtoEnum]
+ Female
+ }
+
+ public static class Info
+ {
+ ///
+ /// The current in-character date.
+ ///
+ public static DateTime IcDate => new DateTime(2458,
+ DateTime.Now.Month,
+ DateTime.Now.Day);
+ }
+}
diff --git a/AuroraRecordGenerator/Utility.cs b/AuroraRecordGenerator/Utility.cs
new file mode 100644
index 0000000..2f0110f
--- /dev/null
+++ b/AuroraRecordGenerator/Utility.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+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) =>
+ 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";
+
+ ///
+ /// Returns and a trailing space if val is not whitespace, otherwise.
+ ///
+ ///
+ ///
+ public static string SpaceIfValue(this string val) => string.IsNullOrWhiteSpace(val) ? string.Empty : " " + val + " ";
+
+ public static string IfEmpty(this string target, string fallback) =>
+ target.IsEmpty() ? fallback : target;
+
+ public static bool IsEmpty(this string val) => string.IsNullOrWhiteSpace(val);
+
+ 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);
+ for (var i = 0; i < repeatNum; i++)
+ builder.Append(target);
+
+ return builder.ToString();
+ }
+
+ ///
+ /// Returns true if the specified species has gender.
+ ///
+ ///
+ ///
+ public static bool HasGender(this SpeciesType species) =>
+ !(species == SpeciesType.Diona || species == SpeciesType.IPC || species == SpeciesType.Vaurca);
+
+ 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);
+ }
+ }
+ }
+}
diff --git a/AuroraRecordGenerator/packages.config b/AuroraRecordGenerator/packages.config
new file mode 100644
index 0000000..b4c8275
--- /dev/null
+++ b/AuroraRecordGenerator/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file