StarSim

StarSim.git
git clone git://git.lenczewski.org/StarSim.git
Log | Files | Refs | README | LICENSE

commit e2b70a7261bed5934ca246252b9a43c4378f0c2d
parent 9e6d2b930741e0d94a7b39a9ad6aeb61d685f3d9
Author: Mikolaj Lenczewski <33129490+EnderRifter@users.noreply.github.com>
Date:   Mon, 26 Aug 2019 14:27:18 +0200

Configuration file is now respected throughout application.

Diffstat:
MStarSim/StarSim/Program.cs | 75+++++++++++++++++++++++++++++++++++++++++----------------------------------
MStarSim/StarSimGui/Program.cs | 59+++++++++++++++++++++++++++++++++++------------------------
MStarSim/StarSimGui/Source/BodyDummy.cs | 29++++++++++++++++++++---------
MStarSim/StarSimGui/ViewModels/Database ViewModels/CreateUsersViewModel.cs | 34+++++++++++++++++++++-------------
MStarSim/StarSimGui/ViewModels/Database ViewModels/ReadSystemsViewModel.cs | 2+-
MStarSim/StarSimGui/ViewModels/Database ViewModels/UpdateUsersViewModel.cs | 36++++++++++++++++++++++--------------
MStarSim/StarSimGui/ViewModels/DatabaseViewModel.cs | 15+++++----------
MStarSim/StarSimGui/ViewModels/MainWindowViewModel.cs | 26++++++++++++++++++--------
MStarSim/StarSimGui/ViewModels/SimulationViewModel.cs | 21+++++++++++++++------
AStarSim/StarSimLib/Configuration/Config.cs | 279+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MStarSim/StarSimLib/StarSimLib.xml | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MStarSim/StarSimLib/UI/SimulationScreen.cs | 8+++++++-
12 files changed, 620 insertions(+), 120 deletions(-)

diff --git a/StarSim/StarSim/Program.cs b/StarSim/StarSim/Program.cs @@ -9,7 +9,10 @@ using StarSimLib.UI; using System; using System.Collections.Generic; +using System.IO; using System.Text; +using Newtonsoft.Json; +using StarSimLib.Configuration; namespace StarSim { @@ -30,24 +33,23 @@ namespace StarSim private static readonly Dictionary<Body, CircleShape> bodyShapeMap; /// <summary> - /// The database context to use for the lifetime of the program. + /// The simulation which we will render, once the user sets it up. /// </summary> - private static readonly SimulatorContext databaseContext; + private static readonly SimulationScreen simulationScreen; /// <summary> - /// The simulation which we will render, once the user sets it up. + /// The current configuration of the application. /// </summary> - private static readonly SimulationScreen simulationScreen; + public static Config configuration; /// <summary> /// Initialises a new instance of the <see cref="Program"/> class, /// </summary> static Program() { - // set up the database context for the program - databaseContext = new SimulatorContext(); + ReadConfigFile(); - bodies = BodyGenerator.GenerateBodies(Constants.BodyCount, true); + bodies = BodyGenerator.GenerateBodies(configuration.BodyCount, true); bodyShapeMap = BodyGenerator.GenerateShapes(bodies); #if DEBUG @@ -65,34 +67,10 @@ namespace StarSim IInputHandler simulationInputHandler = new SimulationInputHandler(ref bodies); - simulationScreen = new SimulationScreen(simulationWindow, simulationInputHandler, ref bodies, ref bodyShapeMap, bodyPositionUpdater); - } - - /// <summary> - /// Converts the given enumerable to a string representation of its contents. - /// </summary> - /// <typeparam name="T">The type of object held in the enumerable.</typeparam> - /// <param name="enumerable">The enumerable to convert.</param> - /// <param name="itemConverter">The custom function to use to convert a single enumerable item to its string form.</param> - /// <returns>The contents of the enumerable as a string.</returns> - private static string EnumerableToString<T>(IEnumerable<T> enumerable, Func<T, string> itemConverter = null) - { - StringBuilder enumerableStringBuilder = new StringBuilder("["); - - if (itemConverter == null) - { - // the default converter function is just calling the Object.ToString() function - itemConverter = item => item.ToString(); - } - - foreach (T item in enumerable) + simulationScreen = new SimulationScreen(simulationWindow, simulationInputHandler, ref bodies, ref bodyShapeMap, bodyPositionUpdater) { - enumerableStringBuilder.Append($"{itemConverter(item) ?? ""},"); - } - - enumerableStringBuilder.Append("]"); - - return enumerableStringBuilder.ToString(); + Configuration = configuration, + }; } /// <summary> @@ -121,5 +99,34 @@ namespace StarSim $"Attributes: {settings.AttributeFlags}, " + $"Version: {settings.MajorVersion}.{settings.MinorVersion}"); } + + /// <summary> + /// Reads in and deserialises the configuration file at the given path. + /// </summary> + /// <param name="path">The path at which the configuration is located.</param> + private static void ReadConfigFile(string path = @"./config.txt") + { + try + { + string fullPath = Path.GetFullPath(path); + + if (!File.Exists(fullPath)) + { + File.WriteAllText(fullPath, JsonConvert.SerializeObject(new Config(), Formatting.Indented)); + } + + using (FileStream fs = File.OpenRead(fullPath)) + { + using (StreamReader fileReader = new StreamReader(fs)) + { + configuration = Config.Load(fileReader.ReadToEnd()); + } + } + } + catch (Exception) + { + configuration = new Config(); + } + } } } \ No newline at end of file diff --git a/StarSim/StarSimGui/Program.cs b/StarSim/StarSimGui/Program.cs @@ -7,6 +7,10 @@ using StarSimGui.Views; using StarSimLib.Cryptography; using System; +using System.IO; +using Newtonsoft.Json; +using Splat; +using StarSimLib.Configuration; namespace StarSimGui { @@ -15,42 +19,49 @@ namespace StarSimGui /// </summary> internal class Program { + /// <summary> + /// The current configuration of the application. + /// </summary> + public static Config configuration; + // Your application's entry point. Here you can initialize your MVVM framework, DI container, etc. private static void AppMain(Application app, string[] args) { MainWindow window = new MainWindow { - DataContext = new MainWindowViewModel(), + DataContext = new MainWindowViewModel(configuration) }; app.Run(window); } - private static void TestHashing(string password) + /// <summary> + /// Reads in and deserialises the configuration file at the given path. + /// </summary> + /// <param name="path">The path at which the configuration is located.</param> + private static void ReadConfigFile(string path = @"./config.txt") { - // set a shorthand for nicety reasons - string BytesToString(byte[] contents) => CryptographyHelper.BytesToString(contents); - - Console.WriteLine($"Password to hash: {password}"); - - byte[] passwordBytes = CryptographyHelper.StringToBytes(password); - Console.WriteLine($"Password bytes:\n{BytesToString(passwordBytes)}"); - - // generates a salt of the default length - byte[] saltBytes = CryptographyHelper.GenerateSalt(); - Console.WriteLine($"Generated salt:\n{BytesToString(saltBytes)}"); - - // generates a hash of the default length - byte[] passwordHash = CryptographyHelper.GenerateHash(passwordBytes, saltBytes); - Console.WriteLine($"Generated valid hash:\n{BytesToString(passwordHash)}"); - - byte[] invalidPasswordBytes = CryptographyHelper.StringToBytes("password "); - Console.WriteLine($"Invalid password bytes:\n{BytesToString(invalidPasswordBytes)}"); + try + { + string fullPath = Path.GetFullPath(path); - byte[] invalidPasswordHash = CryptographyHelper.GenerateHash(invalidPasswordBytes, saltBytes); - Console.WriteLine($"Generated invalid hash:\n{BytesToString(invalidPasswordHash)}"); + if (!File.Exists(fullPath)) + { + File.WriteAllText(fullPath, JsonConvert.SerializeObject(new Config(), Formatting.Indented)); + } - Console.WriteLine($"Valid hash == invalid hash: {CryptographyHelper.HashesEqual(passwordHash, invalidPasswordHash)}"); + using (FileStream fs = File.OpenRead(fullPath)) + { + using (StreamReader fileReader = new StreamReader(fs)) + { + configuration = Config.Load(fileReader.ReadToEnd()); + } + } + } + catch (Exception) + { + configuration = new Config(); + } } // Avalonia configuration, don't remove; also used by visual designer. @@ -64,7 +75,7 @@ namespace StarSimGui // before AppMain is called: things aren't initialized yet and stuff might break. public static void Main(string[] args) { - //TestHashing("Hello World!"); + ReadConfigFile(); BuildAvaloniaApp().Start(AppMain, args); } } diff --git a/StarSim/StarSimGui/Source/BodyDummy.cs b/StarSim/StarSimGui/Source/BodyDummy.cs @@ -1,7 +1,7 @@ using System.ComponentModel; using System.Runtime.CompilerServices; using JetBrains.Annotations; -using StarSimLib; +using StarSimLib.Configuration; using StarSimLib.Data_Structures; namespace StarSimGui.Source @@ -37,12 +37,15 @@ namespace StarSimGui.Source /// Initialises a new instance of the <see cref="BodyDummy"/> class. /// </summary> /// <param name="body">The <see cref="Body"/> instance around which to construct a dummy.</param> - public BodyDummy(Body body) + /// <param name="configuration">The current configuration of the application.</param> + public BodyDummy(Body body, Config configuration) { + Configuration = configuration; + Generation = body.Generation; Id = body.Id; - mass = body.Mass / Constants.SolarMass; - positionVector = body.Position / Constants.AstronomicalUnit; + mass = body.Mass / Configuration.SolarMass; + positionVector = body.Position / Configuration.AstronomicalUnit; velocityVector = body.Velocity / 1000; } @@ -52,6 +55,11 @@ namespace StarSimGui.Source public event PropertyChangedEventHandler PropertyChanged; /// <summary> + /// The current configuration of the application. + /// </summary> + public Config Configuration { get; internal set; } + + /// <summary> /// The generation of this instance. /// </summary> public uint Generation { get; set; } @@ -124,6 +132,8 @@ namespace StarSimGui.Source set { velocityVector.Z = value; } } +#pragma warning disable IDE0051 + /// <summary> /// Invokes the <see cref="PropertyChanged"/> event with the name of the caller property that changed. /// </summary> @@ -134,14 +144,15 @@ namespace StarSimGui.Source PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } +#pragma warning restore IDE0051 + /// <summary> - /// Implements an explicit conversion between a <see cref="BodyDummy"/> instance to a <see cref="Body"/> instance. + /// Implements a conversion between a <see cref="BodyDummy"/> instance to a <see cref="Body"/> instance. /// </summary> - /// <param name="instance">The <see cref="BodyDummy"/> instance to convert.</param> - public static explicit operator Body(BodyDummy instance) + public Body AsBody() { - return new Body(instance.positionVector * Constants.AstronomicalUnit, instance.velocityVector * 1000, - instance.Mass * Constants.SolarMass, instance.Generation, instance.Id); + return new Body(positionVector * Configuration.AstronomicalUnit, velocityVector * 1000, + Mass * Configuration.SolarMass, Generation, Id); } } } \ No newline at end of file diff --git a/StarSim/StarSimGui/ViewModels/Database ViewModels/CreateUsersViewModel.cs b/StarSim/StarSimGui/ViewModels/Database ViewModels/CreateUsersViewModel.cs @@ -5,6 +5,7 @@ using System.Text.RegularExpressions; using System.Windows.Input; using ReactiveUI; using StarSimLib; +using StarSimLib.Configuration; using StarSimLib.Contexts; using StarSimLib.Cryptography; using StarSimLib.Models; @@ -48,15 +49,28 @@ namespace StarSimGui.ViewModels.Database_ViewModels { privileges = UserPrivileges.Default; + ResetUserCommand = ReactiveCommand.Create(ResetUserCommandImpl); + } + + /// <summary> + /// Initialises a new instance of the <see cref="CreateUsersViewModel"/> class. + /// </summary> + /// <param name="context">The <see cref="SimulatorContext"/> instance in which program data is stored.</param> + /// <param name="configuration">The current configuration of the application.</param> + public CreateUsersViewModel(in SimulatorContext context, in Config configuration) : this() + { + dbContext = context; + Configuration = configuration; + #region Regex Pattern Builder StringBuilder regexBuilder = new StringBuilder(@"\w[^@]@("); - for (int i = 0; i < Constants.AcceptedEmailProviders.Length; i++) + for (int i = 0; i < Configuration.AcceptedEmailProviders.Length; i++) { regexBuilder.Append(i == 0 - ? $"{Constants.AcceptedEmailProviders[i].Replace(".", @"\.")}" - : $"|{Constants.AcceptedEmailProviders[i].Replace(".", @"\.")}"); + ? $"{Configuration.AcceptedEmailProviders[i].Replace(".", @"\.")}" + : $"|{Configuration.AcceptedEmailProviders[i].Replace(".", @"\.")}"); } regexBuilder.Append(")$"); @@ -85,23 +99,17 @@ namespace StarSimGui.ViewModels.Database_ViewModels }); CreateUserCommand = ReactiveCommand.Create(CreateUserCommandImpl, canCreate); - - ResetUserCommand = ReactiveCommand.Create(ResetUserCommandImpl); } /// <summary> - /// Initialises a new instance of the <see cref="CreateUsersViewModel"/> class. + /// Signifies that the database should be updated. /// </summary> - /// <param name="context">The <see cref="SimulatorContext"/> instance in which program data is stored.</param> - public CreateUsersViewModel(in SimulatorContext context) : this() - { - dbContext = context; - } + public event Action DatabaseEdited; /// <summary> - /// Signifies that the database should be updated. + /// The current configuration of the application. /// </summary> - public event Action DatabaseEdited; + public Config Configuration { get; internal set; } /// <summary> /// Command invoked whenever the user wants to add the currently edited user to the database. diff --git a/StarSim/StarSimGui/ViewModels/Database ViewModels/ReadSystemsViewModel.cs b/StarSim/StarSimGui/ViewModels/Database ViewModels/ReadSystemsViewModel.cs @@ -133,7 +133,7 @@ namespace StarSimGui.ViewModels.Database_ViewModels /// </summary> public IObservableCollection<BodyToSystemJoin> SelectedSystemBodies { - get { return new ObservableCollectionExtended<BodyToSystemJoin>(SelectedSystem?.BodyToSystemJoins); } + get { return new ObservableCollectionExtended<BodyToSystemJoin>(SelectedSystem?.BodyToSystemJoins ?? new BodyToSystemJoin[0]); } } /// <summary> diff --git a/StarSim/StarSimGui/ViewModels/Database ViewModels/UpdateUsersViewModel.cs b/StarSim/StarSimGui/ViewModels/Database ViewModels/UpdateUsersViewModel.cs @@ -6,6 +6,7 @@ using System.Windows.Input; using DynamicData.Binding; using ReactiveUI; using StarSimLib; +using StarSimLib.Configuration; using StarSimLib.Contexts; using StarSimLib.Cryptography; using StarSimLib.Models; @@ -59,15 +60,28 @@ namespace StarSimGui.ViewModels.Database_ViewModels { users = new ObservableCollectionExtended<User>(); + ResetUserCommand = ReactiveCommand.Create(ResetUserCommandImpl); + } + + /// <summary> + /// Initialises a new instance of the <see cref="UpdateUsersViewModel"/> class. + /// </summary> + /// <param name="context">The <see cref="SimulatorContext"/> instance in which program data is stored.</param> + /// <param name="configuration">The current configuration of the application.</param> + public UpdateUsersViewModel(in SimulatorContext context, in Config configuration) : this() + { + dbContext = context; + Configuration = configuration; + #region Regex Pattern Builder StringBuilder regexBuilder = new StringBuilder(@"\w[^@]@("); - for (int i = 0; i < Constants.AcceptedEmailProviders.Length; i++) + for (int i = 0; i < Configuration.AcceptedEmailProviders.Length; i++) { regexBuilder.Append(i == 0 - ? $"{Constants.AcceptedEmailProviders[i].Replace(".", @"\.")}" - : $"|{Constants.AcceptedEmailProviders[i].Replace(".", @"\.")}"); + ? $"{Configuration.AcceptedEmailProviders[i].Replace(".", @"\.")}" + : $"|{Configuration.AcceptedEmailProviders[i].Replace(".", @"\.")}"); } regexBuilder.Append(")$"); @@ -109,17 +123,6 @@ namespace StarSimGui.ViewModels.Database_ViewModels UpdateUserCommand = ReactiveCommand.Create(UpdateUserCommandImpl, canUpdate); - ResetUserCommand = ReactiveCommand.Create(ResetUserCommandImpl); - } - - /// <summary> - /// Initialises a new instance of the <see cref="UpdateUsersViewModel"/> class. - /// </summary> - /// <param name="context">The <see cref="SimulatorContext"/> instance in which program data is stored.</param> - public UpdateUsersViewModel(in SimulatorContext context) : this() - { - dbContext = context; - Users.Load(dbContext.Users); } @@ -129,6 +132,11 @@ namespace StarSimGui.ViewModels.Database_ViewModels public event Action DatabaseEdited; /// <summary> + /// The current configuration of the application. + /// </summary> + public Config Configuration { get; internal set; } + + /// <summary> /// The email of the user to update. /// </summary> public string Email diff --git a/StarSim/StarSimGui/ViewModels/DatabaseViewModel.cs b/StarSim/StarSimGui/ViewModels/DatabaseViewModel.cs @@ -6,6 +6,7 @@ using DynamicData.Binding; using Microsoft.EntityFrameworkCore; using ReactiveUI; using StarSimGui.ViewModels.Database_ViewModels; +using StarSimLib.Configuration; using StarSimLib.Contexts; using StarSimLib.Models; using Console = System.Console; @@ -28,11 +29,6 @@ namespace StarSimGui.ViewModels private readonly CreateUsersViewModel createUsersViewModel; /// <summary> - /// The program database. - /// </summary> - private readonly SimulatorContext dbContext; - - /// <summary> /// Represents the delete systems view. /// </summary> private readonly DeleteSystemsViewModel deleteSystemsViewModel; @@ -100,10 +96,9 @@ namespace StarSimGui.ViewModels /// Initialises a new instance of the <see cref="DatabaseViewModel"/> class. /// </summary> /// <param name="context">The <see cref="SimulatorContext"/> instance in which program data is stored.</param> - public DatabaseViewModel(in SimulatorContext context) : this() + /// <param name="configuration">The current configuration of the application.</param> + public DatabaseViewModel(in SimulatorContext context, in Config configuration) : this() { - dbContext = context; - // unbind handlers to ensure that no memory leaks occur upon garbage collection of old objects createSystemsViewModel.DatabaseEdited -= OnDatabaseEdited; createUsersViewModel.DatabaseEdited -= OnDatabaseEdited; @@ -114,7 +109,7 @@ namespace StarSimGui.ViewModels createSystemsViewModel = new CreateSystemsViewModel(in context); - createUsersViewModel = new CreateUsersViewModel(in context); + createUsersViewModel = new CreateUsersViewModel(in context, in configuration); deleteSystemsViewModel = new DeleteSystemsViewModel(in context); @@ -126,7 +121,7 @@ namespace StarSimGui.ViewModels updateSystemsViewModel = new UpdateSystemsViewModel(in context); - updateUsersViewModel = new UpdateUsersViewModel(in context); + updateUsersViewModel = new UpdateUsersViewModel(in context, in configuration); // binding of new handlers createSystemsViewModel.DatabaseEdited += OnDatabaseEdited; diff --git a/StarSim/StarSimGui/ViewModels/MainWindowViewModel.cs b/StarSim/StarSimGui/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,6 @@ using System; using ReactiveUI; +using StarSimLib.Configuration; using StarSimLib.Contexts; using StarSimLib.Models; @@ -29,22 +30,31 @@ namespace StarSimGui.ViewModels simulatorContext.ChangeTracker.AutoDetectChangesEnabled = true; - DatabaseViewModel = new DatabaseViewModel(simulatorContext); + OverviewViewModel = new OverviewViewModel(in simulatorContext); - OverviewViewModel = new OverviewViewModel(simulatorContext); + UserLoginViewModel = new UserLoginViewModel(in simulatorContext); - SimulationViewModel = new SimulationViewModel(simulatorContext); + UserLoginViewModel.LoggedIn += user => CurrentUser = user; + UserLoginViewModel.LoggedIn += OverviewViewModel.HandleLogin; - UserLoginViewModel = new UserLoginViewModel(simulatorContext); + UserLoginViewModel.LoggedOut += () => CurrentUser = null; + UserLoginViewModel.LoggedOut += OverviewViewModel.HandleLogout; + } + + /// <summary> + /// Initialises a new instance of the <see cref="MainWindowViewModel"/> class. + /// </summary> + /// <param name="configuration">The current configuration of the application.</param> + public MainWindowViewModel(Config configuration) : this() + { + DatabaseViewModel = new DatabaseViewModel(in simulatorContext, in configuration); + + SimulationViewModel = new SimulationViewModel(in simulatorContext, in configuration); - UserLoginViewModel.LoggedIn += user => CurrentUser = user; UserLoginViewModel.LoggedIn += DatabaseViewModel.HandleLogin; - UserLoginViewModel.LoggedIn += OverviewViewModel.HandleLogin; UserLoginViewModel.LoggedIn += SimulationViewModel.HandleLogin; - UserLoginViewModel.LoggedOut += () => CurrentUser = null; UserLoginViewModel.LoggedOut += DatabaseViewModel.HandleLogout; - UserLoginViewModel.LoggedOut += OverviewViewModel.HandleLogout; UserLoginViewModel.LoggedOut += SimulationViewModel.HandleLogout; SimulationViewModel.DatabaseUpdated += HandleDatabaseUpdated; diff --git a/StarSim/StarSimGui/ViewModels/SimulationViewModel.cs b/StarSim/StarSimGui/ViewModels/SimulationViewModel.cs @@ -10,6 +10,7 @@ using SFML.Graphics; using SFML.Window; using StarSimGui.Source; using StarSimLib; +using StarSimLib.Configuration; using StarSimLib.Contexts; using StarSimLib.Data_Structures; using StarSimLib.Models; @@ -87,7 +88,7 @@ namespace StarSimGui.ViewModels /// <summary> /// The backing field for the <see cref="SimulatedBodyCount"/> property. /// </summary> - private int simulatedBodyCount = Constants.BodyCount; + private int simulatedBodyCount; /// <summary> /// Holds the circle shapes for the bodies participating in the simulation. @@ -179,10 +180,13 @@ namespace StarSimGui.ViewModels /// Initialises a new instance of the <see cref="SimulationViewModel"/> class. /// </summary> /// <param name="context">The <see cref="SimulatorContext"/> instance in which program data is stored.</param> - public SimulationViewModel(in SimulatorContext context) : this() + /// <param name="configuration">The current configuration of the application.</param> + public SimulationViewModel(in SimulatorContext context, in Config configuration) : this() { dbContext = context; + Configuration = configuration; + simulatedBodyCount = Configuration.BodyCount; PublishedSystems.Load(dbContext.PublishedSystems.Include(system => system.System)); } @@ -246,6 +250,11 @@ namespace StarSimGui.ViewModels public event Action DatabaseUpdated; /// <summary> + /// The current configuration of the application. + /// </summary> + public Config Configuration { get; internal set; } + + /// <summary> /// The <see cref="Body"/> instance currently selected for editing or viewing. /// </summary> public BodyDummy CurrentBody @@ -330,7 +339,7 @@ namespace StarSimGui.ViewModels if (selectedItemIndex >= 0) { - CurrentBody = new BodyDummy(SimulatedBodies?[value]); + CurrentBody = new BodyDummy(SimulatedBodies?[value], Configuration); } } } @@ -432,7 +441,7 @@ namespace StarSimGui.ViewModels CurrentBody.Id = 0; } - Body currentBody = (Body)CurrentBody; + Body currentBody = CurrentBody.AsBody(); SimulatedBodies.Add(currentBody); @@ -455,7 +464,7 @@ namespace StarSimGui.ViewModels CurrentBody.Generation = BodyGenerator.CurrentGeneration; CurrentBody.Id = SimulatedBodies[SimulatedBodies.Count - 1].Id + 1; - Body currentBody = (Body)CurrentBody; + Body currentBody = CurrentBody.AsBody(); SimulatedBodies.Add(currentBody); } @@ -626,7 +635,7 @@ namespace StarSimGui.ViewModels /// </summary> private void UpdateBodyCommandImpl() { - SimulatedBodies[SelectedItemIndex] = (Body)CurrentBody; + SimulatedBodies[SelectedItemIndex] = CurrentBody.AsBody(); } #endregion Command Implementations diff --git a/StarSim/StarSimLib/Configuration/Config.cs b/StarSim/StarSimLib/Configuration/Config.cs @@ -0,0 +1,278 @@ +using System.IO; +using System.Text; +using Microsoft.EntityFrameworkCore.ValueGeneration.Internal; +using Newtonsoft.Json; +using StarSimLib.Data_Structures; + +namespace StarSimLib.Configuration +{ + /// <summary> + /// Stores constants used to configure the simulation. + /// </summary> + public class Config + { + /// <summary> + /// Initialises a new instance of the <see cref="Config"/> class. + /// </summary> + public Config() + { + #region Copy over values from Constants class + + AcceptedEmailProviders = Constants.AcceptedEmailProviders; + + AstronomicalUnit = Constants.AstronomicalUnit; + + BodyCount = Constants.BodyCount; + + CentralBodyMass = Constants.CentralBodyMass; + + EulerRotationStep = Constants.EulerRotationStep; + + FrameRate = Constants.FrameRate; + + G = Constants.G; + + MinimumTreeWidth = Constants.MinimumTreeWidth; + + OutputFileDirectory = Constants.OutputFileDirectory; + + SecondsPerTick = Constants.SecondsPerTick; + + SimulationRate = Constants.SimulationRate; + + SofteningFactor = Constants.SofteningFactor; + + SofteningFactor2 = Constants.SofteningFactor2; + + SolarMass = Constants.SolarMass; + + StoredPreviousPositionCount = Constants.StoredPreviousPositionCount; + + TimeStep = Constants.TimeStep; + + TreeTheta = Constants.TreeTheta; + + UniverseOctant = Constants.UniverseOctant; + + UniverseSize = Constants.UniverseSize; + + ZoomStep = Constants.ZoomStep; + + #endregion Copy over values from Constants class + } + + /// <summary> + /// Initialises a new instance of the <see cref="Config"/> class. + /// </summary> + /// <param name="acceptedEmailProviders">The value to use for the <see cref="AcceptedEmailProviders"/> property.</param> + /// <param name="astronomicalUnit">The value to use for the <see cref="AstronomicalUnit"/> property.</param> + /// <param name="bodyCount">The value to use for the <see cref="BodyCount"/> property.</param> + /// <param name="centralBodyMass">The value to use for the <see cref="CentralBodyMass"/> property.</param> + /// <param name="eulerRotationStep">The value to use for the <see cref="EulerRotationStep"/> property.</param> + /// <param name="frameRate">The value to use for the <see cref="FrameRate"/> property.</param> + /// <param name="g">The value to use for the <see cref="G"/> property.</param> + /// <param name="minimumTreeWidth">The value to use for the <see cref="MinimumTreeWidth"/> property.</param> + /// <param name="outputFileDirectory">The value to use for the <see cref="OutputFileDirectory"/> property.</param> + /// <param name="secondsPerTick">The value to use for the <see cref="SecondsPerTick"/> property.</param> + /// <param name="simulationRate">The value to use for the <see cref="SimulationRate"/> property.</param> + /// <param name="softeningFactor">The value to use for the <see cref="SofteningFactor"/> property.</param> + /// <param name="softeningFactor2">The value to use for the <see cref="SofteningFactor2"/> property.</param> + /// <param name="solarMass">The value to use for the <see cref="SolarMass"/> property.</param> + /// <param name="storedPreviousPositionCount">The value to use for the <see cref="StoredPreviousPositionCount"/> property.</param> + /// <param name="timeStep">The value to use for the <see cref="TimeStep"/> property.</param> + /// <param name="treeTheta">The value to use for the <see cref="TreeTheta"/> property.</param> + /// <param name="universeOctant">The value to use for the <see cref="UniverseOctant"/> property.</param> + /// <param name="universeSize">The value to use for the <see cref="UniverseSize"/> property.</param> + /// <param name="zoomStep">The value to use for the <see cref="ZoomStep"/> property.</param> + /// <remarks> + /// Intended to only be used with serialisers when setting the read-only properties on this instance. + /// </remarks> + public Config(string[] acceptedEmailProviders, double astronomicalUnit, int bodyCount, + double centralBodyMass, double eulerRotationStep, uint frameRate, double g, + double minimumTreeWidth, string outputFileDirectory, double secondsPerTick, + uint simulationRate, double softeningFactor, double softeningFactor2, double solarMass, + int storedPreviousPositionCount, double timeStep, double treeTheta, Octant universeOctant, + double universeSize, double zoomStep) + { + #region Setting values from parameters + + AcceptedEmailProviders = acceptedEmailProviders; + + AstronomicalUnit = astronomicalUnit; + + BodyCount = bodyCount; + + CentralBodyMass = centralBodyMass; + + EulerRotationStep = eulerRotationStep; + + FrameRate = frameRate; + + G = g; + + MinimumTreeWidth = minimumTreeWidth; + + OutputFileDirectory = outputFileDirectory; + + SecondsPerTick = secondsPerTick; + + SimulationRate = simulationRate; + + SofteningFactor = softeningFactor; + + SofteningFactor2 = softeningFactor2; + + SolarMass = solarMass; + + StoredPreviousPositionCount = storedPreviousPositionCount; + + TimeStep = timeStep; + + TreeTheta = treeTheta; + + UniverseOctant = universeOctant; + + UniverseSize = universeSize; + + ZoomStep = zoomStep; + + #endregion Setting values from parameters + } + + /// <summary> + /// The list of accepted email providers. + /// </summary> + [JsonProperty] + public string[] AcceptedEmailProviders { get; private set; } + + /// <summary> + /// Definition of an astronomical unit. + /// </summary> + [JsonProperty] + public double AstronomicalUnit { get; private set; } + + /// <summary> + /// The amount of bodies that are rendered by default. + /// </summary> + [JsonProperty] + public int BodyCount { get; private set; } + + /// <summary> + /// The mass of the central body, if it is included. + /// </summary> + [JsonProperty] + public double CentralBodyMass { get; private set; } + + /// <summary> + /// The amount of degrees by which the view will be rotated in any given direction. + /// </summary> + [JsonProperty] + public double EulerRotationStep { get; private set; } + + /// <summary> + /// The frame rate limit for the program. + /// </summary> + [JsonProperty] + public uint FrameRate { get; private set; } + + /// <summary> + /// The gravitational constant (m^3 kg^-1 s^-2). + /// </summary> + [JsonProperty] + public double G { get; private set; } + + /// <summary> + /// The minimum width of a tree. Subtrees are not created when if their width would be smaller than this value, + /// to prevent widths of NaN as a result of division errors. + /// </summary> + [JsonProperty] + public double MinimumTreeWidth { get; private set; } + + /// <summary> + /// The directory path at which all the simulation output files are stored. + /// </summary> + [JsonProperty] + public string OutputFileDirectory { get; private set; } + + /// <summary> + /// The number of seconds that each simulation tick represents. + /// </summary> + [JsonProperty] + public double SecondsPerTick { get; private set; } + + /// <summary> + /// The tick rate limit for the simulation. + /// </summary> + [JsonProperty] + public uint SimulationRate { get; private set; } + + /// <summary> + /// Softens the force between <see cref="Body"/>s to avoid infinities. + /// </summary> + [JsonProperty] + public double SofteningFactor { get; private set; } + + /// <summary> + /// The square of the <see cref="SofteningFactor"/>. + /// </summary> + [JsonProperty] + public double SofteningFactor2 { get; private set; } + + /// <summary> + /// The mass of the sun (1.98892e30f). + /// </summary> + [JsonProperty] + public double SolarMass { get; private set; } + + /// <summary> + /// The number of previous positions that will be stored by a body + /// </summary> + [JsonProperty] + public int StoredPreviousPositionCount { get; private set; } + + /// <summary> + /// The default time step for the simulation. + /// </summary> + [JsonProperty] + public double TimeStep { get; private set; } + + /// <summary> + /// The tolerance of the mass grouping approximation in the simulation. A body is only accelerated when the + /// ratio of the tree's width to the distance (from the tree's center of mass to the body) is less than this. + /// </summary> + [JsonProperty] + public double TreeTheta { get; private set; } + + /// <summary> + /// The <see cref="Octant"/> instance representing the rendered universe. + /// </summary> + [JsonProperty] + public Octant UniverseOctant { get; private set; } + + /// <summary> + /// The maximum radius within which <see cref="Body"/>s will be placed. + /// </summary> + [JsonProperty] + public double UniverseSize { get; private set; } + + /// <summary> + /// The amount by which the zoom level will be increased or decreased. + /// </summary> + [JsonProperty] + public double ZoomStep { get; private set; } + + /// <summary> + /// Loads the serialised instance from the given file contents. + /// </summary> + /// <param name="serialisedConfigurationFileContents"> + /// The file contents from which a serialised instance should be deserialised. + /// </param> + /// <returns> + /// The deserialised instance. + /// </returns> + public static Config Load(string serialisedConfigurationFileContents) + { + return JsonConvert.DeserializeObject<Config>(serialisedConfigurationFileContents) ?? new Config(); + } + } +} +\ No newline at end of file diff --git a/StarSim/StarSimLib/StarSimLib.xml b/StarSim/StarSimLib/StarSimLib.xml @@ -4,6 +4,157 @@ <name>StarSimLib</name> </assembly> <members> + <member name="T:StarSimLib.Configuration.Config"> + <summary> + Stores constants used to configure the simulation. + </summary> + </member> + <member name="M:StarSimLib.Configuration.Config.#ctor"> + <summary> + Initialises a new instance of the <see cref="T:StarSimLib.Configuration.Config"/> class. + </summary> + </member> + <member name="M:StarSimLib.Configuration.Config.#ctor(System.String[],System.Double,System.Int32,System.Double,System.Double,System.UInt32,System.Double,System.Double,System.String,System.Double,System.UInt32,System.Double,System.Double,System.Double,System.Int32,System.Double,System.Double,StarSimLib.Data_Structures.Octant,System.Double,System.Double)"> + <summary> + Initialises a new instance of the <see cref="T:StarSimLib.Configuration.Config"/> class. + </summary> + <param name="acceptedEmailProviders">The value to use for the <see cref="P:StarSimLib.Configuration.Config.AcceptedEmailProviders"/> property.</param> + <param name="astronomicalUnit">The value to use for the <see cref="P:StarSimLib.Configuration.Config.AstronomicalUnit"/> property.</param> + <param name="bodyCount">The value to use for the <see cref="P:StarSimLib.Configuration.Config.BodyCount"/> property.</param> + <param name="centralBodyMass">The value to use for the <see cref="P:StarSimLib.Configuration.Config.CentralBodyMass"/> property.</param> + <param name="eulerRotationStep">The value to use for the <see cref="P:StarSimLib.Configuration.Config.EulerRotationStep"/> property.</param> + <param name="frameRate">The value to use for the <see cref="P:StarSimLib.Configuration.Config.FrameRate"/> property.</param> + <param name="g">The value to use for the <see cref="P:StarSimLib.Configuration.Config.G"/> property.</param> + <param name="minimumTreeWidth">The value to use for the <see cref="P:StarSimLib.Configuration.Config.MinimumTreeWidth"/> property.</param> + <param name="outputFileDirectory">The value to use for the <see cref="P:StarSimLib.Configuration.Config.OutputFileDirectory"/> property.</param> + <param name="secondsPerTick">The value to use for the <see cref="P:StarSimLib.Configuration.Config.SecondsPerTick"/> property.</param> + <param name="simulationRate">The value to use for the <see cref="P:StarSimLib.Configuration.Config.SimulationRate"/> property.</param> + <param name="softeningFactor">The value to use for the <see cref="P:StarSimLib.Configuration.Config.SofteningFactor"/> property.</param> + <param name="softeningFactor2">The value to use for the <see cref="P:StarSimLib.Configuration.Config.SofteningFactor2"/> property.</param> + <param name="solarMass">The value to use for the <see cref="P:StarSimLib.Configuration.Config.SolarMass"/> property.</param> + <param name="storedPreviousPositionCount">The value to use for the <see cref="P:StarSimLib.Configuration.Config.StoredPreviousPositionCount"/> property.</param> + <param name="timeStep">The value to use for the <see cref="P:StarSimLib.Configuration.Config.TimeStep"/> property.</param> + <param name="treeTheta">The value to use for the <see cref="P:StarSimLib.Configuration.Config.TreeTheta"/> property.</param> + <param name="universeOctant">The value to use for the <see cref="P:StarSimLib.Configuration.Config.UniverseOctant"/> property.</param> + <param name="universeSize">The value to use for the <see cref="P:StarSimLib.Configuration.Config.UniverseSize"/> property.</param> + <param name="zoomStep">The value to use for the <see cref="P:StarSimLib.Configuration.Config.ZoomStep"/> property.</param> + <remarks> + Intended to only be used with serialisers when setting the read-only properties on this instance. + </remarks> + </member> + <member name="P:StarSimLib.Configuration.Config.AcceptedEmailProviders"> + <summary> + The list of accepted email providers. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.AstronomicalUnit"> + <summary> + Definition of an astronomical unit. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.BodyCount"> + <summary> + The amount of bodies that are rendered by default. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.CentralBodyMass"> + <summary> + The mass of the central body, if it is included. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.EulerRotationStep"> + <summary> + The amount of degrees by which the view will be rotated in any given direction. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.FrameRate"> + <summary> + The frame rate limit for the program. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.G"> + <summary> + The gravitational constant (m^3 kg^-1 s^-2). + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.MinimumTreeWidth"> + <summary> + The minimum width of a tree. Subtrees are not created when if their width would be smaller than this value, + to prevent widths of NaN as a result of division errors. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.OutputFileDirectory"> + <summary> + The directory path at which all the simulation output files are stored. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.SecondsPerTick"> + <summary> + The number of seconds that each simulation tick represents. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.SimulationRate"> + <summary> + The tick rate limit for the simulation. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.SofteningFactor"> + <summary> + Softens the force between <see cref="T:StarSimLib.Data_Structures.Body"/>s to avoid infinities. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.SofteningFactor2"> + <summary> + The square of the <see cref="P:StarSimLib.Configuration.Config.SofteningFactor"/>. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.SolarMass"> + <summary> + The mass of the sun (1.98892e30f). + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.StoredPreviousPositionCount"> + <summary> + The number of previous positions that will be stored by a body + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.TimeStep"> + <summary> + The default time step for the simulation. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.TreeTheta"> + <summary> + The tolerance of the mass grouping approximation in the simulation. A body is only accelerated when the + ratio of the tree's width to the distance (from the tree's center of mass to the body) is less than this. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.UniverseOctant"> + <summary> + The <see cref="T:StarSimLib.Data_Structures.Octant"/> instance representing the rendered universe. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.UniverseSize"> + <summary> + The maximum radius within which <see cref="T:StarSimLib.Data_Structures.Body"/>s will be placed. + </summary> + </member> + <member name="P:StarSimLib.Configuration.Config.ZoomStep"> + <summary> + The amount by which the zoom level will be increased or decreased. + </summary> + </member> + <member name="M:StarSimLib.Configuration.Config.Load(System.String)"> + <summary> + Loads the serialised instance from the given file contents. + </summary> + <param name="serialisedConfigurationFileContents"> + The file contents from which a serialised instance should be deserialised. + </param> + <returns> + The deserialised instance. + </returns> + </member> <member name="T:StarSimLib.Constants"> <summary> Holds common constants and helper functions. @@ -1996,6 +2147,11 @@ <param name="bodyShapeMap">The shapes for the bodies managed by this instance.</param> <param name="bodyPositionUpdater">The body position update delegate for this instance.</param> </member> + <member name="P:StarSimLib.UI.SimulationScreen.Configuration"> + <summary> + The current configuration of the simulation. + </summary> + </member> <member name="M:StarSimLib.UI.SimulationScreen.CreateFileWriter"> <summary> Creates a <see cref="T:System.IO.StreamWriter"/> to allow for logging the frame-by-frame state of the simulation to a file. diff --git a/StarSim/StarSimLib/UI/SimulationScreen.cs b/StarSim/StarSimLib/UI/SimulationScreen.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using System.Text; using System.Timers; +using StarSimLib.Configuration; namespace StarSimLib.UI { @@ -89,7 +90,7 @@ namespace StarSimLib.UI this.bodyPositionUpdater = bodyPositionUpdater; - simulationDrawer = new SimulationDrawer(renderWindow, ref bodies, ref bodyShapeMap); + simulationDrawer = new SimulationDrawer(renderWindow, ref this.bodies, ref this.bodyShapeMap); simulationInputHandler = (SimulationInputHandler)inputHandler; simulationInputHandler.SetSimulationDrawer(simulationDrawer); @@ -107,6 +108,11 @@ namespace StarSimLib.UI } /// <summary> + /// The current configuration of the simulation. + /// </summary> + public Config Configuration { get; set; } + + /// <summary> /// Creates a <see cref="StreamWriter"/> to allow for logging the frame-by-frame state of the simulation to a file. /// </summary> private StreamWriter CreateFileWriter()