Merge branch 'dev'

This commit is contained in:
Llywelwyn 2022-07-25 11:47:29 +01:00
commit 9f6dc9adfc
29 changed files with 1152 additions and 1107 deletions

View file

@ -1,18 +0,0 @@
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;
}
}
}

View file

@ -1,71 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace AuroraRecordGenerator.Properties
{
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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()
{
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[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;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View file

@ -1,30 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View file

@ -1,120 +0,0 @@
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(16)]
public SpeciesSubType Subspecies { get; set; } = SpeciesSubType.None;
[ProtoMember(6, IsRequired = true)]
public GenderType Gender { get; set; }
[ProtoMember(7)]
public DateTime BirthDate { get; set; } = Info.IcDate;
[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;
}
}

View file

@ -1,193 +0,0 @@
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;
namespace AuroraRecordGenerator
{
/// <summary>
/// Interaction logic for RecordEditor.xaml
/// </summary>
public partial class RecordEditor
{
public RecordEditor()
{
// Initialize the record object used for storage and generation
Data = new Record();
DataContext = Data;
ProtoBuf.Serializer.PrepareSerializer<GenderType>();
ProtoBuf.Serializer.PrepareSerializer<SpeciesType>();
ProtoBuf.Serializer.PrepareSerializer<SpeciesSubType>();
ProtoBuf.Serializer.PrepareSerializer<Record>();
InitializeComponent();
SubSpeciesCombo.ItemsSource = GetSpeciesOptions();
VersionLabel.Content = $"v{Utility.GetVersion()}";
}
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();
}
Debug.WriteLine("Updating subspecies types.");
var types = GetSpeciesOptions(type);
var itemsSource = types as IList<string> ?? types.ToList();
SubSpeciesCombo.ItemsSource = itemsSource;
Debug.WriteLine($"New types: {string.Join(",", itemsSource)}");
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
SpeciesCombo.SelectedIndex = 0;
}
private void GenerateRecord(object sender, RoutedEventArgs e)
{
// Update medical checkboxes.
Data.NoClone = NoClone.IsChecked ?? false;
Data.NoBorg = NoBorg.IsChecked ?? false;
Data.NoProsthetic = NoProsthetic.IsChecked ?? false;
Data.NoRevive = NoRevive.IsChecked ?? false;
// Figure out what subspecies we've got.
var subspecies = SubSpeciesCombo.SelectedItem as string;
Data.Subspecies = subspecies != null ? Utility.SubspeciesNiceNameToEnum(subspecies) : SpeciesSubType.None;
// Figure out their species too.
Data.Species = (SpeciesType)SpeciesCombo.SelectedValue;
// Finally, gender.
switch ((string)GenderCombo.SelectionBoxItem)
{
case "Male":
Data.Gender = GenderType.Male;
break;
case "Female":
Data.Gender = GenderType.Female;
break;
default:
Data.Gender = GenderType.NotApplicable;
break;
}
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 async 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);
try
{
Data = ProtoBuf.Serializer.Deserialize<Record>(fs);
_currentFilePath = dialog.FileName;
// So WPF updates bindings
DataContext = Data;
}
catch (ProtoBuf.ProtoException)
{
await this.ShowMessageAsync("Profile Error", "An error occurred during loading of your profile. You may have selected a file that is not a profile file, or the profile is corrupted.");
}
}
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;
}
private static IEnumerable<string> GetSpeciesOptions() => Enum.GetValues(typeof(SpeciesSubType)).Cast<SpeciesSubType>().Select(Utility.SubspeciesNiceName);
private static IEnumerable<string> GetSpeciesOptions(SpeciesType limitTo) => from item in Enum.GetValues(typeof(SpeciesSubType)).Cast<SpeciesSubType>()
let attr = item.GetAttributeOfType<SubspeciesMetaAttribute>()
where attr != null && (attr.AssociatedSpecies == limitTo || attr.AssociatedSpecies == SpeciesType.None)
select Utility.SubspeciesNiceName(item);
}
}

View file

@ -1,101 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AuroraRecordGenerator
{
internal partial class RecordFormatter
{
private Record _targetRecord;
public RecordFormatter(Record r)
{
_targetRecord = r;
UpdateSplitRecords();
MakeCommonRecords();
}
private IList<string> _medicalPublicRecord;
private IList<string> _medicalHistory;
private IList<string> _medicalNotes;
private IList<string> _medicalPsychHistory;
private IList<string> _medicalPsychNotes;
private IList<string> _medicalPrescriptions;
private IList<string> _securityPublicRecord;
private IList<string> _securityRecords;
private IList<string> _securityNotes;
private IList<string> _employmentPublicRecord;
private IList<string> _employmentExperience;
private IList<string> _employmentPreNtEmployment;
private IList<string> _employmentFormalEducation;
private IList<string> _employmentNtEmployment;
private IList<string> _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;
}
public string EmploymentRecords => MakeEmploymentRecords();
public string MedicalRecords => MakeMedicalRecords();
public string SecurityRecords => MakeSecurityRecords();
private string _commonRecords;
/// <summary>
/// Writes the <see cref="string"/> form of a record section to the specified <see cref="StringBuilder"/>, as long as there's entries to write.
/// </summary>
/// <param name="builder">The <see cref="StringBuilder"/> to write to.</param>
/// <param name="header">The title for the section.</param>
/// <param name="entries">The entries of this section.</param>
private static void WriteSectionIfAny(ref StringBuilder builder, string header, IList<string> entries)
{
if (entries == null || !entries.Any() || entries[0].Trim().Length == 0)
return;
builder.AppendLine(header);
builder.AppendLine(entries.FormatAsList());
}
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}");
}
}

View file

@ -1,212 +0,0 @@
using Humanizer;
using System.Linq;
using System.Text;
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
if (_targetRecord.Subspecies != SpeciesSubType.None)
{
record.AppendLine($"{_targetRecord.Subspecies.GetAttributeOfType<SubspeciesMetaAttribute>()?.FieldName ?? "Subspecies"}: {Utility.SubspeciesNiceName(_targetRecord.Subspecies)}");
}
record.AppendLine(_targetRecord.Species.HasGender()
? $"Gender: {_targetRecord.Gender.Humanize()}"
: "Gender: Not Applicable.");
record.AppendLine($"Citizenship: {_targetRecord.Citizenship.IfEmpty("Not Specified.")}");
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)} lb)");
// Eye color
var trimmedEye = _targetRecord.EyeColor.Trim();
record.AppendFormat("Eye Color: {0}\n", trimmedEye.Length > 0 ? trimmedEye : "Not Specified.");
var bodyColor = _targetRecord.SkinColor.Trim();
record.AppendFormat("Skin/Body Color: {0}\n", bodyColor.Length > 0 ? bodyColor : "Not Specified.");
var hairColor = _targetRecord.HairColor.Trim();
record.AppendFormat("Hair Color: {0}\n", hairColor.Length > 0 ? hairColor : "Not Specified.");
// identifying features
var trimmedFeatures = _targetRecord.DistinguishingFeatures.Trim();
record.Append("Distinguishing Features: ");
record.AppendLine(trimmedFeatures.Length > 0 ? trimmedFeatures : "None noted.");
record.AppendLine();
// general notes
WriteSectionIfAny(ref record,
"General Notes:",
_employmentPublicRecord);
WriteSectionIfAny(ref record,
"Medical Notes:",
_medicalPublicRecord);
WriteSectionIfAny(ref record,
"Security Notes:",
_securityPublicRecord);
_commonRecords = record.ToString();
}
private string 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);
}
return recordText.ToString();
}
private string 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);
}
return recordText.ToString();
}
private string 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);
}
return recordText.ToString();
}
}
}

View file

@ -1,116 +0,0 @@
using ProtoBuf;
using System;
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, SubspeciesMeta(SpeciesType.None, "N/A")]
None = 0,
[ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "M'sai", "Ethnicity")]
MsaiTajara,
[ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "Zhan-Khazan", "Ethnicity")]
ZhanTajara,
[ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type A (Worker)", "Classification")]
VaurcaWorker,
[ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type B (Warrior)", "Classification")]
VaurcaWarrior,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Shell", "Model")]
IpcShell,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Hephaestus G1 Heavy", "Model")]
IpcG1Industrial,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Hephaestus G2 Heavy", "Model")]
IpcG2Industrial,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Bishop Accessory", "Model")]
IpcFancy,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Zeng-Hu Mobility", "Model")]
IpcMedsci,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Shell", "Model")]
IpcHumanoid,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Xion Industrial", "Model")]
IpcHeavy,
[ProtoEnum, SubspeciesMeta(SpeciesType.Unathi, "Aut'akh", "Variant")]
UnathiRobot,
[ProtoEnum, SubspeciesMeta(SpeciesType.Human, "Offworlder", "Variant")]
HumanOffworld
}
[ProtoContract]
public enum GenderType
{
[ProtoEnum]
NotApplicable = 0,
[ProtoEnum]
Male,
[ProtoEnum]
Female
}
public static class Info
{
/// <summary>
/// The current in-character date.
/// </summary>
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 string FieldName { get; private set; }
public SubspeciesMetaAttribute(SpeciesType associatedType, string nicename, string fieldname = "Subspecies")
{
AssociatedSpecies = associatedType;
NiceName = nicename;
FieldName = fieldname;
}
}
}

View file

@ -1,96 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace AuroraRecordGenerator
{
public static class Utility
{
public static IList<string> LineSplit(this string source) =>
source.Split('\n').Where(item => item.Trim().Length != 0).ToList();
public static string CmToFeet(double cm)
{
var feet = Math.Floor(cm * 0.0328084);
var inches = Math.Floor(cm * 0.39370079); // Isn't imperial a lovely system?
inches -= feet * 12;
return $"{feet}'{inches}\"";
}
/// <summary>
/// Converts a weight in Kilograms to Pounds.
/// </summary>
/// <param name="kg">The weight in kilograms.</param>
/// <returns>The weight converted to pounds.</returns>
public static double KgToLb(double kg) => Math.Round(kg * 2.2046, 2);
/// <summary>
/// Returns <paramref name="val"/> and a trailing space if val is not whitespace, <see cref="string.Empty"/> otherwise.
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
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<string> 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();
}
/// <summary>
/// Returns true if the specified species has gender.
/// </summary>
/// <param name="species"></param>
/// <returns></returns>
public static bool HasGender(this SpeciesType species) =>
!(species == SpeciesType.Diona || species == SpeciesType.IPC || species == SpeciesType.Vaurca);
public static string SubspeciesNiceName(SpeciesSubType species)
{
var attr = species.GetAttributeOfType<SubspeciesMetaAttribute>();
return attr?.NiceName ?? Enum.GetName(typeof(SpeciesSubType), species);
}
public static SpeciesSubType SubspeciesNiceNameToEnum(string nicename)
{
return (from item in Enum.GetValues(typeof(SpeciesSubType)).Cast<SpeciesSubType>()
let attr = item.GetAttributeOfType<SubspeciesMetaAttribute>()
where attr != null && attr.NiceName == nicename
select item).FirstOrDefault();
}
public static Version GetVersion() => Assembly.GetExecutingAssembly().GetName().Version;
}
// From https://stackoverflow.com/questions/1799370/getting-attributes-of-enums-value
public static class EnumHelper
{
/// <summary>
/// Gets an attribute on an enum field value
/// </summary>
/// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
/// <param name="enumVal">The enum value</param>
/// <returns>The attribute of type T that exists on the enum value</returns>
/// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
public static T GetAttributeOfType<T>(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;
}
}
}

View file

@ -1,9 +1,9 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 16
VisualStudioVersion = 15.0.28307.421 VisualStudioVersion = 16.0.31702.278
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuroraRecordGenerator", "AuroraRecordGenerator\AuroraRecordGenerator.csproj", "{2E1295C2-7BD9-454E-B13E-8A22448DD5F6}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CharacterRecordsGenerator", "CharacterRecordsGenerator\CharacterRecordsGenerator.csproj", "{2E1295C2-7BD9-454E-B13E-8A22448DD5F6}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution

View file

@ -1,7 +1,7 @@
<Application x:Class="AuroraRecordGenerator.App" <Application x:Class="CharacterRecordsGenerator.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:AuroraRecordGenerator" xmlns:local="clr-namespace:CharacterRecordsGenerator"
StartupUri="RecordEditor.xaml"> StartupUri="RecordEditor.xaml">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>

View file

@ -6,7 +6,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
namespace AuroraRecordGenerator namespace CharacterRecordsGenerator
{ {
/// <summary> /// <summary>
/// Interaction logic for App.xaml /// Interaction logic for App.xaml

View file

@ -7,13 +7,28 @@
<ProjectGuid>{2E1295C2-7BD9-454E-B13E-8A22448DD5F6}</ProjectGuid> <ProjectGuid>{2E1295C2-7BD9-454E-B13E-8A22448DD5F6}</ProjectGuid>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>AuroraRecordGenerator</RootNamespace> <RootNamespace>CharacterRecordsGenerator</RootNamespace>
<AssemblyName>AuroraRecordGenerator</AssemblyName> <AssemblyName>Character Records Generator</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>2.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@ -157,6 +172,18 @@
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5.2">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.5.2 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -1,9 +1,9 @@
<controls:MetroWindow x:Class="AuroraRecordGenerator.GeneratedResultWindow" <controls:MetroWindow x:Class="CharacterRecordsGenerator.GeneratedResultWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AuroraRecordGenerator" xmlns:local="clr-namespace:CharacterRecordsGenerator"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d" mc:Ignorable="d"
GlowBrush="{DynamicResource AccentColorBrush}" GlowBrush="{DynamicResource AccentColorBrush}"
@ -11,13 +11,13 @@
<Grid> <Grid>
<controls:MetroAnimatedTabControl Margin="10"> <controls:MetroAnimatedTabControl Margin="10">
<TabItem Header="Employment"> <TabItem Header="Employment">
<TextBox x:Name="EmploymentBox" IsReadOnly="True" IsUndoEnabled="False" AutoWordSelection="True" FontFamily="Consolas"/> <TextBox x:Name="EmploymentBox" IsReadOnly="True" IsUndoEnabled="False" AutoWordSelection="True" FontFamily="Consolas" TextWrapping="Wrap"/>
</TabItem> </TabItem>
<TabItem Header="Medical"> <TabItem Header="Medical">
<TextBox x:Name="MedicalBox" IsReadOnly="True" IsUndoEnabled="False" AutoWordSelection="True" FontFamily="Consolas"/> <TextBox x:Name="MedicalBox" IsReadOnly="True" IsUndoEnabled="False" AutoWordSelection="True" FontFamily="Consolas" TextWrapping="Wrap"/>
</TabItem> </TabItem>
<TabItem Header="Security"> <TabItem Header="Security">
<TextBox x:Name="SecurityBox" IsReadOnly="True" IsUndoEnabled="False" AutoWordSelection="True" FontFamily="Consolas"/> <TextBox x:Name="SecurityBox" IsReadOnly="True" IsUndoEnabled="False" AutoWordSelection="True" FontFamily="Consolas" TextWrapping="Wrap"/>
</TabItem> </TabItem>
</controls:MetroAnimatedTabControl> </controls:MetroAnimatedTabControl>
</Grid> </Grid>

View file

@ -0,0 +1,18 @@
namespace CharacterRecordsGenerator
{
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;
}
}
}

View file

@ -5,12 +5,12 @@ using System.Windows;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("Aurora Record Generator")] [assembly: AssemblyTitle("CRG")]
[assembly: AssemblyDescription("")] [assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")] [assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AuroraRecordGenerator")] [assembly: AssemblyProduct("Character Records Generator")]
[assembly: AssemblyCopyright("Copyright © 2020")] [assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
@ -49,5 +49,5 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers // You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below: // by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.4.*")] [assembly: AssemblyVersion("2.0.*")]
[assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyFileVersion("1.1.0.0")]

View file

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CharacterRecordsGenerator.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// 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", "16.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() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CharacterRecordsGenerator.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View file

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace CharacterRecordsGenerator.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.10.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;
}
}
}
}

View file

@ -0,0 +1,121 @@
using System;
using ProtoBuf;
namespace CharacterRecordsGenerator
{
[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 SpokenLanguages { get; set; } = string.Empty;
[ProtoMember(5)]
public SpeciesType Species { get; set; } = SpeciesType.Human;
[ProtoMember(6)]
public string Pronouns { get; set; } = string.Empty;
[ProtoMember(7)]
public DateTime BirthDate { get; set; } = Info.IcDate;
[ProtoMember(8)]
public double? CharHeight { get; set; } = null;
[ProtoMember(9)]
public double? Weight { get; set; } = null;
[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;
[ProtoMember(16)]
public SpeciesSubType Subspecies { get; set; } = SpeciesSubType.None;
[ProtoMember(17)]
public string PublicNotes { get; set; } = string.Empty;
[ProtoMember(18)]
public string NextOfKin { get; set; } = string.Empty;
// 19 was used for MedicalPublicRecord, now 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;
// 25 was NoClone, now unused
[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;
// 29 was used for SecurityPublicRecord, now empty
[ProtoMember(30)]
public string SecurityRecords { get; set; } = string.Empty;
[ProtoMember(31)]
public string SecurityNotes { get; set; } = string.Empty;
// 32 was used for EmploymentPublicRecord, now empty
[ProtoMember(33)]
public string EmploymentExperience { 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;
[ProtoMember(38)]
public string SecurityAttitudeScc { get; set; } = string.Empty;
[ProtoMember(39)]
public string SecurityAttitudeCrew { get; set; } = string.Empty;
}
}

View file

@ -1,13 +1,13 @@
<controls:MetroWindow x:Class="AuroraRecordGenerator.RecordEditor" <controls:MetroWindow x:Class="CharacterRecordsGenerator.RecordEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AuroraRecordGenerator" xmlns:local="clr-namespace:CharacterRecordsGenerator"
xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls"
mc:Ignorable="d" mc:Ignorable="d"
Title="Aurora Character Records Generator" Height="563" Width="719.583" Title="Character Records Generator" Height="697" Width="719.583"
GlowBrush="{DynamicResource AccentColorBrush}" GlowBrush="{DynamicResource AccentColorBrush}"
TitleCharacterCasing="Normal" Loaded="WindowLoaded"> TitleCharacterCasing="Normal" Loaded="WindowLoaded">
<controls:MetroWindow.Resources> <controls:MetroWindow.Resources>
@ -17,15 +17,27 @@
<x:Type TypeName="local:SpeciesType" /> <x:Type TypeName="local:SpeciesType" />
</ObjectDataProvider.MethodParameters> </ObjectDataProvider.MethodParameters>
</ObjectDataProvider> </ObjectDataProvider>
<ObjectDataProvider x:Key="ThreatLevelEnum" MethodName="GetValues" ObjectType="{x:Type system:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:ThreatLevel" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</controls:MetroWindow.Resources> </controls:MetroWindow.Resources>
<Grid> <Grid>
<controls:MetroAnimatedTabControl Margin="10,10,0,45" controls:TabControlHelper.IsUnderlined="True"> <Grid.ColumnDefinitions>
<ColumnDefinition Width="85*"/>
<ColumnDefinition Width="93*"/>
</Grid.ColumnDefinitions>
<controls:MetroAnimatedTabControl Margin="10,10,0,45" controls:TabControlHelper.IsUnderlined="True" Grid.ColumnSpan="2">
<!-- General Character Information --> <!-- General Character Information -->
<TabItem Header="General"> <TabItem Header="General">
<ScrollViewer> <ScrollViewer>
<StackPanel> <StackPanel>
<TextBlock Margin="10,10,10,10"
Text="- Bold fields with a * are required. Otherwise, if you leave a box blank, it'll just leave that field off the final result.&#x0a;- Hover over the fields for tooltips! Or look at the default watermark value for an idea about what to write."
VerticalAlignment="Top" FontWeight="SemiBold"/>
<GroupBox Header="Basic Information" controls:ControlsHelper.ContentCharacterCasing="Normal" <GroupBox Header="Basic Information" controls:ControlsHelper.ContentCharacterCasing="Normal"
Height="240"> Height="200">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="160" /> <ColumnDefinition Width="160" />
@ -36,81 +48,80 @@
Margin="10,26,5,0" Margin="10,26,5,0"
TextWrapping="Wrap" VerticalAlignment="Top" TextWrapping="Wrap" VerticalAlignment="Top"
ToolTip="Your character's first name. Required." ToolTip="Your character's first name. Required."
Text="{Binding Path=FirstName}" controls:TextBoxHelper.Watermark="Urist" TabIndex="1" /> Text="{Binding Path=FirstName}" controls:TextBoxHelper.Watermark="John" TabIndex="1" />
<TextBox Height="26" <TextBox Height="26"
Margin="0,26,0,0" Margin="0,26,0,0"
TextWrapping="Wrap" TextWrapping="Wrap"
ToolTip="Your character's middle name. Optional." Grid.Column="1" ToolTip="Your character's middle name." Grid.Column="1"
HorizontalAlignment="Left" Width="120" VerticalAlignment="Top" HorizontalAlignment="Left" Width="120" VerticalAlignment="Top"
Text="{Binding Path=MiddleName}" TabIndex="2" /> Text="{Binding Path=MiddleName}" TabIndex="2" />
<TextBox Height="26" <TextBox Height="26"
Margin="125,26,0,0" Margin="125,26,0,0"
TextWrapping="Wrap" VerticalAlignment="Top" TextWrapping="Wrap" VerticalAlignment="Top"
ToolTip="Your character's last name. Required." Grid.Column="1" ToolTip="Your character's last name. Required." Grid.Column="1"
Text="{Binding Path=LastName}" controls:TextBoxHelper.Watermark="McScientist" TabIndex="3" /> Text="{Binding Path=LastName}" controls:TextBoxHelper.Watermark="Doe" TabIndex="3" />
<TextBlock Grid.Column="0" Margin="10,10,10,0" TextWrapping="Wrap" <TextBlock Grid.Column="0" Margin="10,10,10,0" TextWrapping="Wrap"
Text="First" Text="First*" FontWeight="DemiBold"
VerticalAlignment="Top" Height="16" /> VerticalAlignment="Top" Height="16" />
<TextBlock HorizontalAlignment="Left" Margin="0,10,0,0" TextWrapping="Wrap" <TextBlock HorizontalAlignment="Left" Margin="0,10,0,0" TextWrapping="Wrap"
Text="Middle (Optional)" VerticalAlignment="Top" Grid.Column="1" Text="Middle" VerticalAlignment="Top" Grid.Column="1"
Height="15.96" Width="120"/> Height="15.96" Width="120"/>
<TextBlock Margin="125,10,10,0" TextWrapping="Wrap" <TextBlock Margin="125,10,10,0" TextWrapping="Wrap"
Text="Last" Text="Last"
VerticalAlignment="Top" Grid.Column="1" Height="15.96"/> VerticalAlignment="Top" Grid.Column="1" Height="15.96"/>
<TextBox Height="26" <TextBox Height="26"
Margin="5,26,10.5,0" TextWrapping="Wrap" Margin="5,26,10.5,0" TextWrapping="Wrap"
ToolTip="Your character's name suffix, if present. Optional." Grid.Column="2" ToolTip="Your character's citizenship." Grid.Column="2"
VerticalAlignment="Top" VerticalAlignment="Top"
Text="{Binding Path=NameSuffix}" controls:TextBoxHelper.Watermark="the Third" TabIndex="4" /> Text="{Binding Path=Citizenship}"
controls:TextBoxHelper.Watermark="Coalition of Colonies" TabIndex="4" />
<TextBlock HorizontalAlignment="Left" Margin="5,10,0,0" TextWrapping="Wrap" <TextBlock HorizontalAlignment="Left" Margin="5,10,0,0" TextWrapping="Wrap"
Text="Suffix (Optional)" VerticalAlignment="Top" Grid.Column="2" Text="Citizenship" VerticalAlignment="Top" Grid.Column="2"
Height="15.96" Width="150" /> Height="15.96" Width="150" />
<TextBlock Grid.Column="0" Margin="10,57,10,0" TextWrapping="Wrap" <TextBlock Grid.Column="0" Margin="10,57,10,0" TextWrapping="Wrap"
Text="Species" Text="Species*" FontWeight="DemiBold"
VerticalAlignment="Top" Height="15.96"/> VerticalAlignment="Top" Height="15.96"/>
<ComboBox Grid.Column="0" x:Name="SpeciesCombo" Margin="10,73,5,0" <ComboBox Grid.Column="0" x:Name="SpeciesCombo" Margin="10,73,5,0"
VerticalAlignment="Top" VerticalAlignment="Top"
ItemsSource="{Binding Source={StaticResource SpeciesEnum}}" ItemsSource="{Binding Source={StaticResource SpeciesEnum}}"
ToolTip="Your character's species. Required." ToolTip="Your character's species."
SelectionChanged="SpeciesSelectChanged" Height="26" TabIndex="5"/> SelectionChanged="SpeciesSelectChanged" Height="26" TabIndex="5"/>
<TextBlock HorizontalAlignment="Left" Margin="0,57,0,0" TextWrapping="Wrap" <TextBlock HorizontalAlignment="Left" Margin="0,57,0,0" TextWrapping="Wrap"
Text="Gender" Text="Pronouns"
VerticalAlignment="Top" Grid.Column="1" Height="15.96" Width="120"/> VerticalAlignment="Top" Grid.Column="1" Height="15.96" Width="120"/>
<ComboBox x:Name="GenderCombo" HorizontalAlignment="Left" Margin="0,73,0,0" <TextBox HorizontalAlignment="Left" Margin="0,73,0,0"
VerticalAlignment="Top" Width="120" VerticalAlignment="Top" Width="120"
ToolTip="Your character's gender. Does not apply to Dionae and IPCs." ToolTip="Your character's preferred pronouns."
Grid.Column="1" Height="26" TabIndex="6"> Text="{Binding Path=Pronouns}"
<ComboBoxItem Content="Male" /> controls:TextBoxHelper.Watermark="He/Him"
<!-- Define here instead of loading from enum as we don't want NotApplicable listed --> Grid.Column="1" Height="26" TabIndex="6"/>
<ComboBoxItem Content="Female" />
</ComboBox>
<DatePicker Margin="125,73,0,0" VerticalAlignment="Top" <DatePicker Margin="125,73,0,0" VerticalAlignment="Top"
SelectedDateFormat="Short" DisplayDateEnd="2470-01-01" SelectedDateFormat="Short" DisplayDateEnd="2470-01-01"
DisplayDateStart="1955-01-01" DisplayDate="2458-01-01" Grid.Column="1" DisplayDateStart="1955-01-01" DisplayDate="2464-01-01" Grid.Column="1"
Height="26" Height="26"
SelectedDate="{Binding Path=BirthDate}" TabIndex="7" /> SelectedDate="{Binding Path=BirthDate}" TabIndex="7" />
<TextBlock Margin="125,57,40.96,0" TextWrapping="Wrap" Text="Date of Birth" <TextBlock Margin="125,57,40.96,0" TextWrapping="Wrap" Text="Date of Birth*" FontWeight="DemiBold"
VerticalAlignment="Top" Grid.Column="1" Height="15.96" /> VerticalAlignment="Top" Grid.Column="1" Height="15.96" />
<TextBlock Grid.Column="0" Margin="10,0,0,34" TextWrapping="Wrap" Text="Clearance" <TextBlock Grid.Column="1" Margin="0,0,0,45" TextWrapping="Wrap" Text="Next of Kin"
VerticalAlignment="Bottom" HorizontalAlignment="Left" /> VerticalAlignment="Bottom" HorizontalAlignment="Left" />
<TextBox Height="23" Margin="10,0,0,8" TextWrapping="Wrap" <TextBox Height="23" Margin="0,0,0,19" TextWrapping="Wrap"
VerticalAlignment="Bottom" Grid.ColumnSpan="2" VerticalAlignment="Bottom" Grid.ColumnSpan="1"
Grid.Column="0" Grid.Column="1"
controls:TextBoxHelper.Watermark="Staff (Research, Xenobiology), Command (Research)" controls:TextBoxHelper.Watermark="e.g. Jane Doe (mother)"
Text="{Binding Path=Clearance}" TabIndex="11" /> Text="{Binding Path=NextOfKin}" TabIndex="10" />
<TextBlock HorizontalAlignment="Left" Margin="5,0,0,85" <TextBlock HorizontalAlignment="Left" Margin="5,0,0,45"
TextWrapping="Wrap" Text="Employed As" VerticalAlignment="Bottom" Grid.Column="2" /> TextWrapping="Wrap" Text="Employed As" VerticalAlignment="Bottom" Grid.Column="2" />
<TextBox Height="23" Margin="5,0,10,59" TextWrapping="Wrap" <TextBox Height="23" Margin="5,0,10,19" TextWrapping="Wrap"
VerticalAlignment="Bottom" controls:TextBoxHelper.Watermark="Xenobiologist" VerticalAlignment="Bottom" controls:TextBoxHelper.Watermark="Assistant"
Text="{Binding Path=EmployedAs}" Grid.Column="2" TabIndex="10" /> Text="{Binding Path=EmployedAs}" Grid.Column="2" TabIndex="11" />
<TextBox Grid.Column="2" Height="23" Margin="5,73,10.5,0" <TextBox Grid.Column="2" Height="23" Margin="5,73,10.5,0"
TextWrapping="Wrap" VerticalAlignment="Top" controls:TextBoxHelper.Watermark="Sol Alliance" TextWrapping="Wrap" VerticalAlignment="Top" controls:TextBoxHelper.Watermark="Tau Ceti Basic, Tradeband"
Text="{Binding Path=Citizenship}" TabIndex="8" /> Text="{Binding Path=SpokenLanguages}" TabIndex="8" />
<TextBlock Grid.Column="2" HorizontalAlignment="Left" Margin="5,57,0,0" TextWrapping="Wrap" Text="Citizenship" VerticalAlignment="Top" /> <TextBlock Grid.Column="2" HorizontalAlignment="Left" Margin="5,57,0,0" TextWrapping="Wrap" Text="Spoken Languages" VerticalAlignment="Top" />
<ComboBox Grid.Column="0" x:Name="SubSpeciesCombo" Margin="10,120,140,0" <ComboBox Grid.Column="0" x:Name="SubSpeciesCombo" Margin="10,120,5,0"
VerticalAlignment="Top" VerticalAlignment="Top"
ToolTip="Your character's ethnic group or subtype." ToolTip="Your character's ethnic group or subtype."
SelectionChanged="SpeciesSelectChanged" Height="26" TabIndex="9" Grid.ColumnSpan="2" SelectionChanged="SpeciesSelectChanged" Height="26" TabIndex="9"
/> />
<TextBlock Grid.Column="0" Margin="10,104,10,0" TextWrapping="Wrap" <TextBlock Grid.Column="0" Margin="10,104,10,0" TextWrapping="Wrap"
Text="Subtype/Ethnicity" Text="Subtype/Ethnicity"
@ -127,13 +138,13 @@
<TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" <TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap"
VerticalAlignment="Top" Text="Height (cm)" /> VerticalAlignment="Top" Text="Height (cm)" />
<controls:NumericUpDown Grid.Column="0" <controls:NumericUpDown Grid.Column="0"
Value="{Binding Path=CharHeight}" Value="{Binding Path=CharHeight}" controls:TextBoxHelper.Watermark="170.0"
HorizontalAlignment="Left" Margin="10,26,0,0" HorizontalAlignment="Left" Margin="10,26,0,0"
Minimum="10" Maximum="400" HideUpDownButtons="True" Width="1" Minimum="10" Maximum="400" HideUpDownButtons="True" Width="1"
StringFormat="N1" VerticalAlignment="Top" StringFormat="N1" VerticalAlignment="Top"
HorizontalContentAlignment="Center" TabIndex="12" /> HorizontalContentAlignment="Center" TabIndex="12" />
<controls:NumericUpDown Grid.Column="0" <controls:NumericUpDown Grid.Column="0"
Value="{Binding Path=Weight}" Value="{Binding Path=Weight}" controls:TextBoxHelper.Watermark="65.0"
HorizontalAlignment="Left" Margin="77.033,26,0,0" HorizontalAlignment="Left" Margin="77.033,26,0,0"
Minimum="10" Maximum="1000" HideUpDownButtons="True" Width="1" Minimum="10" Maximum="1000" HideUpDownButtons="True" Width="1"
StringFormat="N1" VerticalAlignment="Top" StringFormat="N1" VerticalAlignment="Top"
@ -146,13 +157,15 @@
Text="Skin/Body Color" VerticalAlignment="Top" /> Text="Skin/Body Color" VerticalAlignment="Top" />
<TextBox Grid.Column="0" Height="23" <TextBox Grid.Column="0" Height="23"
Margin="144.033,25.96,261.967,0" TextWrapping="Wrap" VerticalAlignment="Top" Margin="144.033,25.96,261.967,0" TextWrapping="Wrap" VerticalAlignment="Top"
ToolTip="The color of your character's skin/scales/fur/chassis. Not applicable for Dionae." ToolTip="The color of your character's skin/scales/fur/chassis."
controls:TextBoxHelper.Watermark="Brown"
d:LayoutOverrides="HorizontalAlignment" Text="{Binding Path=SkinColor}" TabIndex="14" /> d:LayoutOverrides="HorizontalAlignment" Text="{Binding Path=SkinColor}" TabIndex="14" />
<TextBlock Grid.Column="0" HorizontalAlignment="Left" Margin="10,57,0,52" <TextBlock Grid.Column="0" HorizontalAlignment="Left" Margin="10,57,0,52"
TextWrapping="Wrap" TextWrapping="Wrap"
Text="Distinguishing Features" d:LayoutOverrides="Height" /> Text="Distinguishing Features" d:LayoutOverrides="Height" />
<TextBox Grid.Column="0" Height="23" <TextBox Grid.Column="0" Height="23"
Margin="10,0,0,26" Text="{Binding Path=DistinguishingFeatures}" Margin="10,0,0,26" Text="{Binding Path=DistinguishingFeatures}"
controls:TextBoxHelper.Watermark="A full sleeve on their right arm; mechanical eyes."
TextWrapping="Wrap" VerticalAlignment="Bottom" TabIndex="17" /> TextWrapping="Wrap" VerticalAlignment="Bottom" TabIndex="17" />
<TextBox Grid.Column="0" Height="23" <TextBox Grid.Column="0" Height="23"
Margin="0,25.96,136.967,0" Margin="0,25.96,136.967,0"
@ -172,6 +185,30 @@
Text="Eye Color" VerticalAlignment="Top" /> Text="Eye Color" VerticalAlignment="Top" />
</Grid> </Grid>
</GroupBox> </GroupBox>
<GroupBox Header="Additional Information" controls:ControlsHelper.ContentCharacterCasing="Normal"
Height="150">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="122"
MinHeight="60"/>
<RowDefinition/>
</Grid.RowDefinitions>
<GridSplitter Grid.Row="0"
VerticalAlignment="Bottom"
Margin="0"
Height="10" />
<TextBox Grid.Row="0"
Margin="0,10,0,10"
AcceptsReturn="True"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.Watermark="Any additional notes that should be present on all three records.&#x0a;&#x0a;e.g.&#x0a;John Doe is here for a two-month cultural exchange.&#x0a;John Doe has been known to [...]."
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="Additional public notes that will be visible on all three records."
Text="{Binding Path=PublicNotes}"
d:LayoutOverrides="VerticalAlignment"/>
</Grid>
</GroupBox>
</StackPanel> </StackPanel>
</ScrollViewer> </ScrollViewer>
</TabItem> </TabItem>
@ -183,10 +220,6 @@
<RowDefinition Height="122" MinHeight="60" /> <RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="122" MinHeight="60" /> <RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="122" MinHeight="60" /> <RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="0" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<GridSplitter Grid.Row="0" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="0" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
@ -194,52 +227,26 @@
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="3" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="4" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="5" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Public Record" TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Employment History"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto" controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" Grid.Row="0" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" Grid.Row="0"
ToolTip="Public employment notes posted on security and medical records. One per line." ToolTip="Previous jobs that the character has worked. One per line.&#x0a;No need to put hyphens/bulletpoints; they'll be added automatically.&#x0a;&#x0a;e.g.&#x0a;Police Cadet, Mendell City [2450 - 2454]&#x0a;Police Officer, Mendell City [2454 - Ongoing]"
d:LayoutOverrides="VerticalAlignment" Text="{Binding Path=EmploymentPublicRecord}" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Experience"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" Grid.Row="1"
ToolTip="Jobs/departments worked with NT. One per line."
d:LayoutOverrides="VerticalAlignment" Text="{Binding Path=EmploymentExperience}" /> d:LayoutOverrides="VerticalAlignment" Text="{Binding Path=EmploymentExperience}" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" Grid.Row="1"
controls:TextBoxHelper.Watermark="Pre-NanoTrasen Employment History" controls:TextBoxHelper.Watermark="Formal Education / Qualifications"
controls:TextBoxHelper.UseFloatingWatermark="True" Grid.Row="2"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="Jobs/experience from before NT employment. One per line."
Text="{Binding Path=EmploymentPreNtEmployment}" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" Grid.Row="3"
controls:TextBoxHelper.Watermark="Formal Education"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto" controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="Formal education completed or in-progress. One per-line." ToolTip="Formal education completed / qualifications acquired. One per-line.&#x0a;No need for bulletpoints; they'll be added automatically.&#x0a;&#x0a;e.g.&#x0a;Manual handling certificate [2450]&#x0a;PhD in Psychology [2460]"
Text="{Binding Path=EmploymentFormalEducation}" /> Text="{Binding Path=EmploymentFormalEducation}" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" Grid.Row="4"
controls:TextBoxHelper.Watermark="NanoTrasen Employment History"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="History with employment with NT. One per line, should be in format &quot;Year Description&quot;."
Text="{Binding Path=EmploymentNtEmploymentHistory}" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" TextWrapping="Wrap"
controls:TextBoxHelper.Watermark="Trained-in/Skills" Grid.Row="5" controls:TextBoxHelper.Watermark="Other Skills / Ongoing Training" Grid.Row="2"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto" controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
Text="{Binding Path=EmploymentSkills}" Text="{Binding Path=EmploymentSkills}"
ToolTip="Training or Skills your character has. Anything marked as &quot;Trained&quot; or &quot;Professional&quot; in character skills should go here, along with any amatur skills of note." /> ToolTip="Any other skills of note, or training being undertaken currently.&#x0a;&#x0a;e.g.&#x0a;First Aid training&#x0a;Chemistry student at Mendell University" />
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
</TabItem> </TabItem>
@ -248,7 +255,7 @@
<ScrollViewer> <ScrollViewer>
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="60" /> <RowDefinition Height="50" />
<!-- Checkboxes --> <!-- Checkboxes -->
<RowDefinition Height="122" MinHeight="60" /> <RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="122" MinHeight="60" /> <RowDefinition Height="122" MinHeight="60" />
@ -259,22 +266,30 @@
<RowDefinition Height="0" /> <RowDefinition Height="0" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!-- Opt-Outs --> <!-- Opt-Outs -->
<Grid Grid.Row="0" ToolTip="If the character wishes to not be cloned."> <Grid Grid.Row="0" ToolTip="If the character should not be borged.">
<CheckBox x:Name="NoClone" Content="Do Not Clone" HorizontalAlignment="Left" <Grid.ColumnDefinitions>
Margin="10,10,0,0" VerticalAlignment="Top" TabIndex="1" /> <ColumnDefinition Width="163*"/>
<CheckBox x:Name="NoProsthetic" Content="No Prosthetics" <ColumnDefinition Width="163*"/>
HorizontalAlignment="Left" Margin="10,33,0,0" VerticalAlignment="Top" <ColumnDefinition Width="163*"/>
ToolTip="If the character should not be fitted with prosthetics." TabIndex="3" /> <ColumnDefinition Width="163*"/>
<CheckBox x:Name="NoBorg" Content="Do Not Borgify" HorizontalAlignment="Left" <ColumnDefinition Width="163*"/>
Margin="136,10,0,0" VerticalAlignment="Top" </Grid.ColumnDefinitions>
ToolTip="If the character should not be borged." TabIndex="2" /> <CheckBox x:Name="NoBorg" Content="Do Not Borgify"
HorizontalAlignment="Left"
Margin="0,10,0,0"
ToolTip="If the character should not be borged." TabIndex="1" Grid.Column="0" />
<CheckBox x:Name="NoRevive" Content="Do Not Resuscitate" <CheckBox x:Name="NoRevive" Content="Do Not Resuscitate"
HorizontalAlignment="Left" Margin="136,33,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"
ToolTip="If the character should not be revived." TabIndex="4" /> Margin="-10,10,0,0"
ToolTip="If the character should not be revived." TabIndex="2" Grid.Column="1" />
<CheckBox x:Name="NoProsthetic" Content="No Prosthetics"
HorizontalAlignment="Left"
Margin="0,10,0,0"
ToolTip="If the character should not be fitted with prosthetics." TabIndex="3" Grid.Column="2" />
</Grid> </Grid>
<!-- user-resizable stuff is fun! Not. --> <!-- user-resizable stuff is fun! Not. -->
<GridSplitter Grid.Row="1" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="1" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Height="10" />
<GridSplitter Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="3" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="3" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
@ -283,50 +298,40 @@
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="5" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="5" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="6" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <TextBox Margin="0,10" AcceptsReturn="True" TextWrapping="Wrap"
VerticalAlignment="Bottom" Margin="0" Height="10" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Public Record"
controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="Public medical notes posted on employment and security records. One per line."
Grid.Row="1" VerticalScrollBarVisibility="Auto"
Text="{Binding Path=MedicalPublicRecord}" TabIndex="5" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" TextWrapping="Wrap"
controls:TextBoxHelper.Watermark="Medical History" controls:TextBoxHelper.Watermark="Medical History"
controls:TextBoxHelper.UseFloatingWatermark="True" controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
ToolTip="Dated list of operations, surgeries, checkups of note, etc. One per line." ToolTip="Dated list of operations, surgeries, checkups of note, etc. One per line."
Grid.Row="2" Text="{Binding Path=MedicalHistory}" TabIndex="6" /> Grid.Row="1" Text="{Binding Path=MedicalHistory}" TabIndex="6" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" TextWrapping="Wrap" <TextBox Margin="0,10,0,10" AcceptsReturn="True" TextWrapping="Wrap"
controls:TextBoxHelper.Watermark="Medical Notes" controls:TextBoxHelper.Watermark="Medical Notes - prescriptions, allergies, etc."
controls:TextBoxHelper.UseFloatingWatermark="True" controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
ToolTip="Notes about physical/medical health. One per line." Grid.Row="3" ToolTip="Current prescriptions, allergies, etc. One per line." Grid.Row="2"
Text="{Binding Path=MedicalNotes}" TabIndex="7" /> Text="{Binding Path=MedicalNotes}" TabIndex="7" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Psychiatric History" TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Psychiatric History"
controls:TextBoxHelper.UseFloatingWatermark="True" controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
ToolTip="Dated records of psych evals and other psychological events." Grid.Row="4" ToolTip="Dated records of psych evals and other psychological events." Grid.Row="3"
Text="{Binding Path=MedicalPsychHistory}" TabIndex="8" /> Text="{Binding Path=MedicalPsychHistory}" TabIndex="8" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Psychiatric Notes" TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Psychiatric Notes"
controls:TextBoxHelper.UseFloatingWatermark="True" controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
ToolTip="Notes about mental/psychiatric health. One per line." Grid.Row="5" ToolTip="Notes about mental/psychiatric health. One per line." Grid.Row="4"
Text="{Binding Path=MedicalPsychNotes}" TabIndex="9" /> Text="{Binding Path=MedicalPsychNotes}" TabIndex="9" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Prescriptions" TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Prescriptions"
controls:TextBoxHelper.UseFloatingWatermark="True" controls:TextBoxHelper.UseFloatingWatermark="True"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
VerticalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
ToolTip="Notes regarding assigned prescriptions. One per line." Grid.Row="6" ToolTip="Notes regarding assigned prescriptions. One per line." Grid.Row="5"
Text="{Binding Path=MedicalPrescriptions}" TabIndex="10" /> Text="{Binding Path=MedicalPrescriptions}" TabIndex="10" />
</Grid> </Grid>
</ScrollViewer> </ScrollViewer>
@ -341,26 +346,39 @@
<RowDefinition Height="122" MinHeight="60" /> <RowDefinition Height="122" MinHeight="60" />
<RowDefinition Height="0" /> <RowDefinition Height="0" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Attitude Towards the SCC"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="A brief summary of the character's perceived attitude towards the conglomerate."
Text="{Binding Path=SecurityAttitudeScc}" />
<TextBox Grid.Column="1" Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Attitude Towards the Crew"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="A brief summary of the character's perceived attitude towards the rest of the crew."
Text="{Binding Path=SecurityAttitudeCrew}" />
</Grid>
<GridSplitter Grid.Row="0" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="0" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="1" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="1" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<GridSplitter Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Stretch" <GridSplitter Grid.Row="2" Grid.ColumnSpan="1" HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" Margin="0" Height="10" /> VerticalAlignment="Bottom" Margin="0" Height="10" />
<TextBox Grid.Row="0" Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Public Record"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="Public security notes added to employment and medical records. One per line."
Text="{Binding Path=SecurityPublicRecord}" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Records" TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Arrest History"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto" controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="List of charges, dated if possible. One per line." Grid.Row="1" ToolTip="List of charges, dated if possible. One per line." Grid.Row="1"
Text="{Binding Path=SecurityRecords}" /> Text="{Binding Path=SecurityRecords}" />
<TextBox Margin="0,10,0,10" AcceptsReturn="True" <TextBox Margin="0,10,0,10" AcceptsReturn="True"
TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Notes" TextWrapping="Wrap" controls:TextBoxHelper.Watermark="Other notes"
controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto" controls:TextBoxHelper.UseFloatingWatermark="True" VerticalScrollBarVisibility="Auto"
controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True" controls:TextBoxHelper.IsSpellCheckContextMenuEnabled="True"
ToolTip="Any things security should keep in mind when dealing with you. One per line." ToolTip="Any things security should keep in mind when dealing with you. One per line."
@ -370,7 +388,7 @@
</TabItem> </TabItem>
</controls:MetroAnimatedTabControl> </controls:MetroAnimatedTabControl>
<!-- Footer --> <!-- Footer -->
<Grid Height="45" VerticalAlignment="Bottom"> <Grid Height="45" VerticalAlignment="Bottom" Grid.ColumnSpan="2">
<Button Content="Open" HorizontalAlignment="Left" Margin="10,9.66,0,10" Width="75" <Button Content="Open" HorizontalAlignment="Left" Margin="10,9.66,0,10" Width="75"
d:LayoutOverrides="Height" Click="OpenContent" /> d:LayoutOverrides="Height" Click="OpenContent" />
<Button Content="Save" HorizontalAlignment="Left" Margin="90,10,0,9.66" Width="75" <Button Content="Save" HorizontalAlignment="Left" Margin="90,10,0,9.66" Width="75"

View file

@ -0,0 +1,151 @@
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;
namespace CharacterRecordsGenerator
{
/// <summary>
/// Interaction logic for RecordEditor.xaml
/// </summary>
public partial class RecordEditor
{
public RecordEditor()
{
// Initialize the record object used for storage and generation
Data = new Record();
DataContext = Data;
ProtoBuf.Serializer.PrepareSerializer<SpeciesType>();
ProtoBuf.Serializer.PrepareSerializer<SpeciesSubType>();
ProtoBuf.Serializer.PrepareSerializer<Record>();
InitializeComponent();
SubSpeciesCombo.ItemsSource = GetSpeciesOptions();
VersionLabel.Content = $"v{Utility.GetVersion()}";
}
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;
Debug.WriteLine("Updating subspecies types.");
var types = GetSpeciesOptions(type);
var itemsSource = types as IList<string> ?? types.ToList();
SubSpeciesCombo.ItemsSource = itemsSource;
Debug.WriteLine($"New types: {string.Join(",", itemsSource)}");
}
private void WindowLoaded(object sender, RoutedEventArgs e)
{
SpeciesCombo.SelectedIndex = 1;
}
private void GenerateRecord(object sender, RoutedEventArgs e)
{
// Update medical checkboxes.
Data.NoBorg = NoBorg.IsChecked ?? false;
Data.NoProsthetic = NoProsthetic.IsChecked ?? false;
Data.NoRevive = NoRevive.IsChecked ?? false;
// Figure out what subspecies we've got.
var subspecies = SubSpeciesCombo.SelectedItem as string;
Data.Subspecies = subspecies != null ? Utility.SubspeciesNiceNameToEnum(subspecies) : SpeciesSubType.None;
// Figure out their species too.
Data.Species = (SpeciesType)SpeciesCombo.SelectedValue;
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 async 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);
try
{
Data = ProtoBuf.Serializer.Deserialize<Record>(fs);
_currentFilePath = dialog.FileName;
// So WPF updates bindings
DataContext = Data;
}
catch (ProtoBuf.ProtoException)
{
await this.ShowMessageAsync("Profile Error", "An error occurred during loading of your profile. You may have selected a file that is not a profile file, or the profile is corrupted.");
}
}
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;
}
private static IEnumerable<string> GetSpeciesOptions() => Enum.GetValues(typeof(SpeciesSubType)).Cast<SpeciesSubType>().Select(Utility.SubspeciesNiceName);
private static IEnumerable<string> GetSpeciesOptions(SpeciesType limitTo) => from item in Enum.GetValues(typeof(SpeciesSubType)).Cast<SpeciesSubType>()
let attr = item.GetAttributeOfType<SubspeciesMetaAttribute>()
where attr != null && (attr.AssociatedSpecies == limitTo || attr.AssociatedSpecies == SpeciesType.None)
select Utility.SubspeciesNiceName(item);
}
}

View file

@ -0,0 +1,97 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CharacterRecordsGenerator
{
internal partial class RecordFormatter
{
private Record _targetRecord;
public RecordFormatter(Record r)
{
_targetRecord = r;
UpdateSplitRecords();
MakeCommonRecords();
}
private IList<string> _publicNotes;
private IList<string> _medicalHistory;
private IList<string> _medicalNotes;
private IList<string> _medicalPsychHistory;
private IList<string> _medicalPsychNotes;
private IList<string> _medicalPrescriptions;
private IList<string> _securityRecords;
private IList<string> _securityNotes;
private IList<string> _securityAttitudeScc;
private IList<string> _securityAttitudeCrew;
private IList<string> _employmentExperience;
private IList<string> _employmentFormalEducation;
private IList<string> _employmentSkills;
private void UpdateSplitRecords()
{
if (_targetRecord == null)
{
_targetRecord = new Record();
}
_publicNotes = _targetRecord.PublicNotes?.LineSplit();
// Medical
_medicalHistory = _targetRecord.MedicalHistory?.LineSplit();
_medicalNotes = _targetRecord.MedicalNotes?.LineSplit();
_medicalPsychHistory = _targetRecord.MedicalPsychHistory?.LineSplit();
_medicalPsychNotes = _targetRecord.MedicalPsychNotes?.LineSplit();
_medicalPrescriptions = _targetRecord.MedicalPrescriptions?.LineSplit();
// security
_securityRecords = _targetRecord.SecurityRecords?.LineSplit();
_securityNotes = _targetRecord.SecurityNotes?.LineSplit();
_securityAttitudeCrew = _targetRecord.SecurityAttitudeCrew?.LineSplit();
_securityAttitudeScc = _targetRecord.SecurityAttitudeScc?.LineSplit();
// employment
_employmentExperience = _targetRecord.EmploymentExperience?.LineSplit();
_employmentFormalEducation = _targetRecord.EmploymentFormalEducation?.LineSplit();
_employmentSkills = _targetRecord.EmploymentSkills?.LineSplit();
// flush the record cache so they're regenerated
_commonRecords = null;
}
public string EmploymentRecords => MakeEmploymentRecords();
public string MedicalRecords => MakeMedicalRecords();
public string SecurityRecords => MakeSecurityRecords();
private string _commonRecords;
/// <summary>
/// Writes the <see cref="string"/> form of a record section to the specified <see cref="StringBuilder"/>, as long as there's entries to write.
/// </summary>
/// <param name="builder">The <see cref="StringBuilder"/> to write to.</param>
/// <param name="header">The title for the section.</param>
/// <param name="entries">The entries of this section.</param>
private static void WriteSectionIfAny(ref StringBuilder builder, string header, IList<string> entries)
{
if (entries == null || !entries.Any() || entries[0].Trim().Length == 0)
return;
builder.AppendLine(header);
builder.AppendLine(entries.FormatAsList());
}
private string MakeNameLine()
{
var builder = new StringBuilder("Name: ");
builder.Append(_targetRecord.FirstName.SpaceIfValue());
builder.Append(_targetRecord.MiddleName.SpaceIfValue());
builder.Append(_targetRecord.LastName);
return builder.ToString();
}
private static void MakeMedicalNote(ref StringBuilder b, string s) =>
b.AppendLine($" - {s}");
}
}

View file

@ -0,0 +1,246 @@
using Humanizer;
using System.Linq;
using System.Text;
namespace CharacterRecordsGenerator
{
internal partial class RecordFormatter
{
private void MakeCommonRecords()
{
var record = new StringBuilder();
record.AppendLine("/// PUBLIC RECORD ///");
// TODO: most of this should be replaced by WriteRecordIfAny()
if (_targetRecord.FirstName.Any())
{
record.AppendLine(MakeNameLine());
}
else
{
record.AppendLine("Name: Not specified.");
}
record.AppendLine($"Date of Birth: {_targetRecord.BirthDate.ToString("MMMM")} {_targetRecord.BirthDate.Day.Ordinalize()}, {_targetRecord.BirthDate.Year}");
if (_targetRecord.Species != SpeciesType.None)
{
record.AppendLine($"Species: {_targetRecord.Species.Humanize()}"); // might fuck up the names
}
else
{
record.AppendLine("Species: Not specified.");
}
if (_targetRecord.Subspecies != SpeciesSubType.None)
{
record.AppendLine($"{_targetRecord.Subspecies.GetAttributeOfType<SubspeciesMetaAttribute>()?.FieldName ?? "Subspecies"}: {Utility.SubspeciesNiceName(_targetRecord.Subspecies)}");
}
if (_targetRecord.Pronouns.Any())
{
record.AppendLine($"Pronouns: {_targetRecord.Pronouns}");
}
if (_targetRecord.Citizenship.Any()) {
record.AppendLine($"Citizenship: {_targetRecord.Citizenship}");
}
if (_targetRecord.SpokenLanguages.Any())
{
record.AppendLine($"Spoken Languages: {_targetRecord.SpokenLanguages}");
}
if (_targetRecord.NextOfKin.Any()) {
record.AppendLine($"Next of Kin: {_targetRecord.NextOfKin}");
}
if (_targetRecord.EmployedAs.Any()) {
record.AppendLine($"Employed As: {_targetRecord.EmployedAs}");
}
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)} lb)");
// Eye color
if (_targetRecord.EyeColor.Any())
{
var trimmedEye = _targetRecord.EyeColor.Trim();
record.AppendFormat("Eye Color: {0}\n", trimmedEye.Length > 0 ? trimmedEye : "Not specified.");
}
if (_targetRecord.SkinColor.Any())
{
var bodyColor = _targetRecord.SkinColor.Trim();
record.AppendFormat("Skin/Body Color: {0}\n", bodyColor.Length > 0 ? bodyColor : "Not specified.");
}
if (_targetRecord.HairColor.Any())
{
var hairColor = _targetRecord.HairColor.Trim();
record.AppendFormat("Hair Color: {0}\n", hairColor.Length > 0 ? hairColor : "Not specified.");
}
if (_targetRecord.DistinguishingFeatures.Any())
{
// identifying features
var trimmedFeatures = _targetRecord.DistinguishingFeatures.Trim();
record.Append("Distinguishing Features: ");
record.AppendLine(trimmedFeatures.Length > 0 ? trimmedFeatures : "None noted.");
}
record.AppendLine();
// general notes
WriteSectionIfAny(ref record,
"Additional Notes:",
_publicNotes);
_commonRecords = record.ToString();
}
private string MakeEmploymentRecords()
{
var recordText = new StringBuilder();
if (_commonRecords.IsEmpty())
MakeCommonRecords();
recordText.Append(_commonRecords);
if (!_employmentExperience.Any() &&
!_employmentFormalEducation.Any() &&
!_employmentSkills.Any())
{
recordText.AppendLine("/// NO EMPLOYMENT RECORD FOUND ///");
recordText.AppendLine();
}
else
{
recordText.AppendLine("/// EMPLOYMENT RECORD ///");
recordText.AppendLine("This information has been verified by employment agents within the External Affairs department, and any comments, questions, or concerns about the legitimacy of such must be sent in a secure document to the same department.");
recordText.AppendLine();
WriteSectionIfAny(ref recordText,
"Employment History:",
_employmentExperience);
WriteSectionIfAny(ref recordText,
"Qualifications:",
_employmentFormalEducation);
WriteSectionIfAny(ref recordText,
"Other skills:",
_employmentSkills);
}
recordText.AppendLine($"LAST UPDATED: {Utility.HumanisedDate(Info.IcDate)}");
return recordText.ToString();
}
private string 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.NoProsthetic &&
!_targetRecord.NoRevive)
{
recordText.AppendLine("/// NO MEDICAL RECORD FOUND ///");
recordText.AppendLine();
}
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.NoProsthetic || _targetRecord.NoRevive)
{
recordText.AppendLine("IMPORTANT NOTES:");
if (_targetRecord.NoBorg)
MakeMedicalNote(ref recordText, "DO NOT BORGIFY");
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);
}
recordText.AppendLine($"LAST UPDATED: {Utility.HumanisedDate(Info.IcDate)}");
return recordText.ToString();
}
private string MakeSecurityRecords()
{
var recordText = new StringBuilder();
if (_commonRecords.IsEmpty())
MakeCommonRecords();
recordText.Append(_commonRecords);
if (!_securityRecords.Any() &&
!_securityNotes.Any() &&
!_securityAttitudeScc.Any() &&
!_securityAttitudeCrew.Any())
{
recordText.AppendLine("/// NO SECURITY RECORD FOUND ///");
recordText.AppendLine();
}
else
{
recordText.AppendLine("/// SECURITY RECORD ///");
recordText.AppendLine();
WriteSectionIfAny(ref recordText,
"Attitude Towards the SCC:",
_securityAttitudeScc);
WriteSectionIfAny(ref recordText,
"Attitude Towards the Crew:",
_securityAttitudeCrew);
WriteSectionIfAny(ref recordText,
"Notes:",
_securityNotes);
WriteSectionIfAny(ref recordText,
"Record:",
_securityRecords);
}
recordText.AppendLine($"LAST UPDATED: {Utility.HumanisedDate(Info.IcDate)}");
return recordText.ToString();
}
}
}

View file

@ -0,0 +1,136 @@
using ProtoBuf;
using System;
namespace CharacterRecordsGenerator
{
[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, SubspeciesMeta(SpeciesType.None, "N/A")]
None = 0,
// SKRELL VARIANTS
[ProtoEnum, SubspeciesMeta(SpeciesType.Skrell, "Axiori", "Ethnicity")]
SkrellAxiori,
[ProtoEnum, SubspeciesMeta(SpeciesType.Skrell, "Xiialt", "Ethnicity")]
SkrellXiialt,
[ProtoEnum, SubspeciesMeta(SpeciesType.Skrell, "Xiiori", "Ethnicity")]
SkrellXiiori,
// TAJARA VARIANTS
[ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "Hharar", "Ethnicity")]
TajaraHharar,
[ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "Zhan-Khazan", "Ethnicity")]
TajaraZhan,
[ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "Njarir'Akhran", "Ethnicity")]
TajaraNjarir,
[ProtoEnum, SubspeciesMeta(SpeciesType.Tajara, "M'sai", "Ethnicity")]
TajaraMsai,
// VAURCA VARIANTS
[ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type A (Worker)", "Classification")]
VaurcaWorker,
[ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type B (Warrior)", "Classification")]
VaurcaWarrior,
[ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type C (Breeder)", "Classification")]
VaurcaBreeder,
[ProtoEnum, SubspeciesMeta(SpeciesType.Vaurca, "Type E (Bulwark)", "Classification")]
VaurcaBulwark,
// IPC VARIANTS
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Baseline", "Model")]
IpcBaseline,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Shell", "Model")]
IpcShell,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Hephaestus G1 Industrial", "Model")]
IpcG1,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Hephaestus G2 Industrial", "Model")]
IpcG2,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Xion Industrial", "Model")]
IpcXion,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Zeng-Hu Mobility", "Model")]
IpcZengHu,
[ProtoEnum, SubspeciesMeta(SpeciesType.IPC, "Bishop Accessory", "Model")]
IpcBishop,
// UNATHI VARIANTS
[ProtoEnum, SubspeciesMeta(SpeciesType.Unathi, "Aut'akh", "Variant")]
UnathiAutakh,
// HUMAN VARIANTS
[ProtoEnum, SubspeciesMeta(SpeciesType.Human, "Offworlder", "Variant")]
HumanOffworld
}
// Currently unused
[ProtoContract]
public enum ThreatLevel
{
[ProtoEnum]
Minimal = 0,
[ProtoEnum]
Low,
[ProtoEnum]
Medium,
[ProtoEnum]
High,
[ProtoEnum]
Extreme
}
public static class Info
{
/// <summary>
/// The current in-character date.
/// </summary>
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 string FieldName { get; private set; }
public SubspeciesMetaAttribute(SpeciesType associatedType, string nicename, string fieldname = "Subspecies")
{
AssociatedSpecies = associatedType;
NiceName = nicename;
FieldName = fieldname;
}
}
}

View file

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Humanizer;
namespace CharacterRecordsGenerator
{
public static class Utility
{
public static IList<string> LineSplit(this string source) =>
source.Split('\n').Where(item => item.Trim().Length != 0).ToList();
public static string CmToFeet(double cm)
{
var feet = Math.Floor(cm * 0.0328084);
var inches = Math.Floor(cm * 0.39370079); // Isn't imperial a lovely system?
inches -= feet * 12;
return $"{feet}'{inches}\"";
}
/// <summary>
/// Converts a weight in Kilograms to Pounds.
/// </summary>
/// <param name="kg">The weight in kilograms.</param>
/// <returns>The weight converted to pounds.</returns>
public static double KgToLb(double kg) => Math.Round(kg * 2.2046, 2);
/// <summary>
/// Returns <paramref name="val"/> and a trailing space if val is not whitespace, <see cref="string.Empty"/> otherwise.
/// </summary>
/// <param name="val"></param>
/// <returns></returns>
public static string SpaceIfValue(this string val) => string.IsNullOrWhiteSpace(val) ? string.Empty : $"{val} ";
public static string HumanisedDate(DateTime date) => $"{date.ToString("MMMM")} {date.Day.Ordinalize()}, {date.Year}";
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<string> 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();
}
/// <summary>
/// Returns true if the specified species has gender.
/// </summary>
/// <param name="species"></param>
/// <returns></returns>
public static bool HasGender(this SpeciesType species) =>
!(species == SpeciesType.Diona || species == SpeciesType.IPC || species == SpeciesType.Vaurca);
public static string SubspeciesNiceName(SpeciesSubType species)
{
var attr = species.GetAttributeOfType<SubspeciesMetaAttribute>();
return attr?.NiceName ?? Enum.GetName(typeof(SpeciesSubType), species);
}
public static SpeciesSubType SubspeciesNiceNameToEnum(string nicename)
{
return (from item in Enum.GetValues(typeof(SpeciesSubType)).Cast<SpeciesSubType>()
let attr = item.GetAttributeOfType<SubspeciesMetaAttribute>()
where attr != null && attr.NiceName == nicename
select item).FirstOrDefault();
}
public static Version GetVersion() => Assembly.GetExecutingAssembly().GetName().Version;
}
// From https://stackoverflow.com/questions/1799370/getting-attributes-of-enums-value
public static class EnumHelper
{
/// <summary>
/// Gets an attribute on an enum field value
/// </summary>
/// <typeparam name="T">The type of the attribute you want to retrieve</typeparam>
/// <param name="enumVal">The enum value</param>
/// <returns>The attribute of type T that exists on the enum value</returns>
/// <example>string desc = myEnumVariable.GetAttributeOfType<DescriptionAttribute>().Description;</example>
public static T GetAttributeOfType<T>(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;
}
}
}