diff --git a/CHANGES.md b/CHANGES.md index e92bf17..c691cf5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,14 @@ +## v0.3.0 +##### New +- Skin temperature added as a new metric. + +##### Changes +- *Incompatible:* Configuration structure for temperature metrics has changed. +- "Temperature" in context menus abbreviated to "Temp." + +##### Fixes +- Fix Internal Thermal Rate metric always being 0kW. + ## v0.2.0 ##### New - Added thermal rate metrics to both overlays and context menu. These measure the change in thermal energy of a part @@ -11,11 +22,11 @@ the temperature unit, the overlay metric, and the gradient scheme for the metric. Currently this options are not persisted between loads. -##### Change +##### Changes - *Incompatible:* Configuration structure has changed significantly. ## v0.1.1 -##### Fix +##### Fixes - Fix settings being loaded multiple times which would eventually cause the thermal overlays to fail. ## v0.1.0 diff --git a/Configuration/HotSpot.cfg b/Configuration/HotSpot.cfg index eae676f..edef2d2 100644 --- a/Configuration/HotSpot.cfg +++ b/Configuration/HotSpot.cfg @@ -7,6 +7,13 @@ HOT_SPOT CONTEXT_MENU { + METRIC + { + name = TemperatureTemplate + enable = true + unit = Kelvin + } + METRIC { name = ThermalRateTemplate @@ -180,11 +187,14 @@ HOT_SPOT { @CONTEXT_MENU { - %METRIC[Temperature] + +METRIC[TemperatureTemplate] { - @name = Temperature - %enable = true - %unit = Kelvin + @name = TemperatureInternal + } + + +METRIC[TemperatureTemplate] + { + @name = TemperatureSkin } +METRIC[ThermalRateTemplate] @@ -215,11 +225,50 @@ HOT_SPOT @OVERLAY { - %metric = Temperature + %metric = TemperatureInternal + + +METRIC[TemperatureTemplate] + { + @name = TemperatureInternal + %scheme = TemperaturePartAbsolute + + +SCHEME[TemperatureTemplate] + { + @name = TemperaturePartAbsolute + %friendlyName = Part Absolute + + @GRADIENT + { + %max = PartAbsoluteMaximum + } + } + + +SCHEME[TemperatureTemplate] + { + @name = TemperatureVesselCurrent + %friendlyName = Vessel Current + + @GRADIENT + { + %max = VesselCurrentMaximum + } + } + + +SCHEME[TemperatureTemplate] + { + @name = TemperatureVesselAbsolute + %friendlyName = Vessel Absolute + + @GRADIENT + { + %max = VesselAbsoluteMaximum + } + } + } +METRIC[TemperatureTemplate] { - @name = Temperature + @name = TemperatureSkin %scheme = TemperaturePartAbsolute +SCHEME[TemperatureTemplate] diff --git a/HotSpot.sln.DotSettings b/HotSpot.sln.DotSettings index 276e623..fcd2992 100644 --- a/HotSpot.sln.DotSettings +++ b/HotSpot.sln.DotSettings @@ -5,6 +5,7 @@ DO_NOT_SHOW DO_NOT_SHOW HINT + DO_NOT_SHOW DO_NOT_SHOW DO_NOT_SHOW UseKeyword diff --git a/README.md b/README.md index e8a0114..6d93647 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,22 @@ # Hot Spot [![Build status][build-badge]][build] -**Hot Spot** is a [MIT-licensed](LICENSE.md) Kerbal Space Program mod that displays better thermal metric data to the -user. It currently supports the following metrics: +**Hot Spot** is a [MIT-licensed](LICENSE.md) Kerbal Space Program mod that displays better thermal data. It currently +supports the following metrics: - Temperature - Thermal Rate +Hot Spot and display two kinds of temperatures: + +- *Internal Temperature* - The temperature of the interior of a part. +- *Skin Temperature* - The temperature of the exposed surface of a part. + Thermal rate is the rate at which thermal energy is added or removed from a part. It is measured as energy per unit time, i.e. [*power*][wiki-power]. Positive thermal rates indicate a part is gaining thermal energy, negative thermal rates indicate a part is losing thermal energy. There are multiple kinds of thermal rates: - *Internal Thermal Rate* - The change in thermal energy due to reactions/processes occuring within the part itself. -- *Conductive Thremal Rate* - The change in thermal energy due to being in contact with other parts. +- *Conductive Thermal Rate* - The change in thermal energy due to being in contact with other parts. - *Convective Thermal Rate* - The change in thermal energy due to being in contact with a fluid, like the atmosphere. - *Radiative Thermal Rate* - The change in thermal energy due to the emission or absorption of light. - *Thermal Rate* - An aggregate value of the four previous rates. @@ -45,11 +50,33 @@ The *Maximum* value depends on the scheme used: - *Vessel Current* - The maximum current temperature of any part in the vessel. - *Vessel Absolute* - The maximum temperature of any part in the vessel. +#### Thermal Rate +The color gradient used for thermal rates is as follows: + +- Purple (*Vessel Current Minimum*, if negative) +- Blue (0.1×*Vessel Current Minimum*, if negative) +- Transparent (0) +- Yellow (0.1×*Vessel Current Maxmimum*, if positive) +- Orange (0.5×*Vessel Current Maxmimum*, if positive) +- Red (*Vessel Current Maxmimum*, if positive) + ## Installation -To install, extract the contents of the archive to your KSP directory. This should create an `HotSpot` directory under -the `/GameData` directory. All dependencies should also be installed. +### CKAN +Hot Spot's CKAN identifier is `HotSpot`. It may be installed from the command line with: + +``` +> ckan install HotSpot +``` + +It can also be installed from the GUI. + +### Manual +1. Download the distribution package from [Kerbal Stuff][kerbalstuff] or [GitHub][github-releases]. +2. Extract the contents of the archive to your KSP directory. This should create an `HotSpot` directory under +the `/GameData` directory. +3. Follow the installation instructions for all dependencies. -Dependencies: +#### Dependencies - [Module Manager][module-manager] ## Usage @@ -64,6 +91,8 @@ please see the Module Manager documentation for more information. [build]: https://ci.appveyor.com/project/Apokee/hotspot/branch/develop [build-badge]: https://ci.appveyor.com/api/projects/status/ik9la5jusinnpu5n/branch/develop?svg=true +[github-releases]: https://github.com/Apokee/HotSpot/releases +[kerbalstuff]: https://kerbalstuff.com/mod/937/Hot%20Spot [module-manager]: http://forum.kerbalspaceprogram.com/threads/55219 [wiki-celsius]: https://en.wikipedia.org/wiki/Celsius [wiki-fahrenheit]: https://en.wikipedia.org/wiki/Fahrenheit diff --git a/Source/HotSpot/Configuration/OverlayNode.cs b/Source/HotSpot/Configuration/OverlayNode.cs index deef767..50ec770 100644 --- a/Source/HotSpot/Configuration/OverlayNode.cs +++ b/Source/HotSpot/Configuration/OverlayNode.cs @@ -31,7 +31,7 @@ public MetricNode GetActiveMetric() public static OverlayNode GetDefault() { - return new OverlayNode(false, true, Metric.Temperature, new MetricNode[] { }); + return new OverlayNode(false, true, Metric.TemperatureInternal, new MetricNode[] { }); } public static OverlayNode TryParse(ConfigNode node) diff --git a/Source/HotSpot/Extensions/PartExtensions.cs b/Source/HotSpot/Extensions/PartExtensions.cs index 61a8343..6463ff3 100644 --- a/Source/HotSpot/Extensions/PartExtensions.cs +++ b/Source/HotSpot/Extensions/PartExtensions.cs @@ -4,7 +4,7 @@ internal static class PartExtensions { public static double GetThermalFlux(this Part part) { - return part.thermalInternalFlux + return part.thermalInternalFluxPrevious + part.thermalConductionFlux + part.thermalConvectionFlux + part.thermalRadiationFlux diff --git a/Source/HotSpot/HotSpotGuiBehavior.cs b/Source/HotSpot/HotSpotGuiBehavior.cs index bc8b8d2..bc90077 100644 --- a/Source/HotSpot/HotSpotGuiBehavior.cs +++ b/Source/HotSpot/HotSpotGuiBehavior.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using HotSpot.Model; using HotSpot.Reflection; @@ -20,7 +21,7 @@ public sealed class HotSpotGuiBehavior : MonoBehaviour private bool _showConfigWindow; private Rect _configWindowRect; private ConfigWindowTab _configWindowTabActive = ConfigWindowTab.Context; - private bool _configWindowContextShowTemperatureUnit; + private readonly Dictionary _configWindowContextShowUnits = new Dictionary(); private bool _configWindowOverlayShowMetrics; private bool _configWindowOverlayShowSchemes; @@ -30,6 +31,11 @@ public void Start() { Log.Trace("Entering HotSpotGuiBehavior.Start()"); + foreach (var metricNode in Config.Instance.ContextMenu.Metrics) + { + _configWindowContextShowUnits[metricNode.Name.Name] = false; + } + var buttonTexture = GameDatabase .Instance .GetTexture(Config.Instance.Gui.ButtonTexture, asNormalMap: false); @@ -117,7 +123,7 @@ private void LateUpdateScreenMessage() { var scheme = Config.Instance.Overlay.GetActiveMetric().GetActiveScheme(); - var metricMsg = Config.Instance.Overlay.Metric.FriendlyName; + var metricMsg = Config.Instance.Overlay.Metric.LongFriendlyName; var schemMsg = scheme.FriendlyName == null ? string.Empty : $" ({scheme.FriendlyName})"; var stateMsg = PhysicsGlobals.ThermalColorsDebug ? "Enabled" : "Disabled"; @@ -194,60 +200,40 @@ private void OnContextTab() { GUILayout.BeginHorizontal(); - metricNode.Enable = GUILayout.Toggle(metricNode.Enable, metricNode.Name.FriendlyName); + metricNode.Enable = GUILayout.Toggle(metricNode.Enable, metricNode.Name.LongFriendlyName); - var isTemperatureMetric = metricNode.Name.Name == "Temperature"; - - if (isTemperatureMetric) + if (metricNode.Name.Units.Length > 1) { GUILayout.FlexibleSpace(); if (GUILayout.Button("Unit")) { - _configWindowContextShowTemperatureUnit = !_configWindowContextShowTemperatureUnit; + _configWindowContextShowUnits[metricNode.Name.Name] = + !_configWindowContextShowUnits[metricNode.Name.Name]; } } GUILayout.EndHorizontal(); - if (_configWindowContextShowTemperatureUnit && isTemperatureMetric) + if (_configWindowContextShowUnits[metricNode.Name.Name]) { - var temperatureMetricNode = Config - .Instance - .ContextMenu - .Metrics - .SingleOrDefault(i => i.Name.Name == "Temperature"); + GUILayout.BeginVertical(); - if (temperatureMetricNode != null) + var unitIndex = 0; + for (var i = 0; i < metricNode.Name.Units.Length; i++) { - GUILayout.BeginVertical(); - var units = new[] { Unit.Kelvin, Unit.Rankine, Unit.Celsius, Unit.Fahrenheit }; - - int unitIndex; - switch (temperatureMetricNode.Unit) + if (metricNode.Name.Units[i] == metricNode.Unit) { - case Unit.Kelvin: - unitIndex = 0; - break; - case Unit.Rankine: - unitIndex = 1; - break; - case Unit.Celsius: - unitIndex = 2; - break; - case Unit.Fahrenheit: - unitIndex = 3; - break; - default: - throw new ArgumentOutOfRangeException(); + unitIndex = i; + break; } + } - var newUnitIndex = GUILayout.SelectionGrid(unitIndex, units.Select(i => i.ToString()).ToArray(), 2); + var newUnitIndex = GUILayout.SelectionGrid(unitIndex, metricNode.Name.Units.Select(i => i.ToString()).ToArray(), 2); - temperatureMetricNode.Unit = units[newUnitIndex]; + metricNode.Unit = metricNode.Name.Units[newUnitIndex]; - GUILayout.EndVertical(); - } + GUILayout.EndVertical(); } } GUILayout.EndVertical(); @@ -261,7 +247,7 @@ private void OnOverlayTab() GUILayout.Label("Metric:", new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold }, GUILayout.Width(55)); - GUILayout.Label(Config.Instance.Overlay.Metric.FriendlyName); + GUILayout.Label(Config.Instance.Overlay.Metric.LongFriendlyName); GUILayout.FlexibleSpace(); if (GUILayout.Button("Select", GUILayout.Width(50))) { @@ -285,7 +271,7 @@ private void OnOverlayTab() } var newMetricIndex = GUILayout.SelectionGrid( - metricIndex, metrics.Select(i => i.Name.FriendlyName).ToArray(), 1 + metricIndex, metrics.Select(i => i.Name.LongFriendlyName).ToArray(), 1 ); Config.Instance.Overlay.Metric = metrics[newMetricIndex].Name; diff --git a/Source/HotSpot/HotSpotModule.cs b/Source/HotSpot/HotSpotModule.cs index 26cdcfd..3e3cd5f 100644 --- a/Source/HotSpot/HotSpotModule.cs +++ b/Source/HotSpot/HotSpotModule.cs @@ -1,143 +1,45 @@ -using System; -using HotSpot.Model; - -namespace HotSpot +namespace HotSpot { public sealed class HotSpotModule : PartModule { - [KSPField(guiActive = false, guiName = "Temperature")] - // ReSharper disable once NotAccessedField.Global - public string Temperature; + [KSPField(guiActive = false)] + public string TemperatureInternal; + + [KSPField(guiActive = false)] + public string TemperatureSkin; - [KSPField(guiActive = false, guiName = "Thermal Rate")] - // ReSharper disable once NotAccessedField.Global + [KSPField(guiActive = false)] public string ThermalRate; - [KSPField(guiActive = false, guiName = "Thermal Rate [I]")] - // ReSharper disable once NotAccessedField.Global + [KSPField(guiActive = false)] public string ThermalRateInternal; - [KSPField(guiActive = false, guiName = "Thermal Rate [Cd]")] - // ReSharper disable once NotAccessedField.Global + [KSPField(guiActive = false)] public string ThermalRateConductive; - [KSPField(guiActive = false, guiName = "Thermal Rate [Cv]")] - // ReSharper disable once NotAccessedField.Global + [KSPField(guiActive = false)] public string ThermalRateConvective; - [KSPField(guiActive = false, guiName = "Thermal Rate [R]")] - // ReSharper disable once NotAccessedField.Global + [KSPField(guiActive = false)] public string ThermalRateRadiative; public override void OnUpdate() { - UpdateTemperature(); - UpdateThermalRate(); - UpdateThermalRateInternal(); - UpdateThermalRateConductive(); - UpdateThermalRateConvective(); - UpdateThermalRateRadiative(); - } - - #region Updaters - - private void UpdateTemperature() - { - var metric = Config.Instance.ContextMenu.GetMetric(Metric.Temperature); - - double temp; - double maxTemp; - string unit; - - switch (metric.Unit) + if (HighLogic.LoadedSceneIsFlight) { - case Unit.Kelvin: - temp = part.temperature; - maxTemp = part.maxTemp; - unit = "K"; - break; - case Unit.Rankine: - temp = ConvertKelvinToRankine(part.temperature); - maxTemp = ConvertKelvinToRankine(part.maxTemp); - unit = "°R"; - break; - case Unit.Celsius: - temp = ConvertKelvinToCelsius(part.temperature); - maxTemp = ConvertKelvinToCelsius(part.maxTemp); - unit = "°C"; - break; - case Unit.Fahrenheit: - temp = ConvertKelvinToFahrenheit(part.temperature); - maxTemp = ConvertKelvinToFahrenheit(part.maxTemp); - unit = "°F"; - break; - default: - throw new ArgumentOutOfRangeException(); - } - - Fields["Temperature"].guiActive = metric.Enable; - Temperature = metric.Enable ? $"{temp:F2}{unit} / {maxTemp:F2}{unit}" : null; - } - - private void UpdateThermalRate() - { - var metric = Config.Instance.ContextMenu.GetMetric(Metric.ThermalRate); - - Fields["ThermalRate"].guiActive = metric.Enable; - ThermalRate = metric.Enable ? $"{part.GetThermalFlux():F2}kW" : null; - } - - private void UpdateThermalRateInternal() - { - var metric = Config.Instance.ContextMenu.GetMetric(Metric.ThermalRateInternal); - - Fields["ThermalRateInternal"].guiActive = metric.Enable; - ThermalRateInternal = metric.Enable ? $"{part.thermalInternalFlux:F2}kW" : null; - } - - private void UpdateThermalRateConductive() - { - var metric = Config.Instance.ContextMenu.GetMetric(Metric.ThermalRateConductive); - - Fields["ThermalRateConductive"].guiActive = metric.Enable; - ThermalRateConductive = metric.Enable ? $"{part.thermalConductionFlux:F2}kW" : null; - } - - private void UpdateThermalRateConvective() - { - var metric = Config.Instance.ContextMenu.GetMetric(Metric.ThermalRateConvective); - - Fields["ThermalRateConvective"].guiActive = metric.Enable; - ThermalRateConvective = metric.Enable ? $"{part.thermalConvectionFlux:F2}kW" : null; - } - - private void UpdateThermalRateRadiative() - { - var metric = Config.Instance.ContextMenu.GetMetric(Metric.ThermalRateRadiative); - - Fields["ThermalRateRadiative"].guiActive = metric.Enable; - ThermalRateRadiative = metric.Enable ? $"{part.thermalRadiationFlux:F2}kW" : null; - } - - #endregion - - #region Helpers + foreach (var metricNode in Config.Instance.ContextMenu.Metrics) + { + var metric = metricNode.Name; + var field = Fields[metric.Name]; - private static double ConvertKelvinToRankine(double temp) - { - return temp * (9.0 / 5.0); - } + field.guiName = metric.ShortFriendlyName; + field.guiActive = metricNode.Enable; - private static double ConvertKelvinToCelsius(double temp) - { - return temp - 273.15; - } + var value = metric.GetPartCurrentString(part, metricNode.Unit); - private static double ConvertKelvinToFahrenheit(double temp) - { - return temp * (9.0 / 5.0) - 459.67; + field.SetValue(value, this); + } + } } - - #endregion } } diff --git a/Source/HotSpot/Model/Metric.cs b/Source/HotSpot/Model/Metric.cs index 470462f..bbf6163 100644 --- a/Source/HotSpot/Model/Metric.cs +++ b/Source/HotSpot/Model/Metric.cs @@ -7,8 +7,10 @@ namespace HotSpot.Model { internal sealed class Metric { - public static readonly Metric Temperature = new Metric("Temperature", - "Temperature", + public static readonly Metric TemperatureInternal = new Metric("TemperatureInternal", + "Temp. [I]", + "Internal Temperature", + new[] { Unit.Kelvin, Unit.Celsius, Unit.Rankine, Unit.Fahrenheit }, vessel => new Dictionary { [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.temperature), @@ -21,82 +23,191 @@ internal sealed class Metric [Variable.PartAbsoluteMinimum] = 0, [Variable.PartAbsoluteMaximum] = part.maxTemp }, - part => part.temperature + part => part.temperature, + (part, unit) => + { + double temp; + double maxTemp; + string unitSymbol; + + switch (unit) + { + case Unit.Kelvin: + temp = part.temperature; + maxTemp = part.maxTemp; + unitSymbol = "K"; + break; + case Unit.Rankine: + temp = ConvertKelvinToRankine(part.temperature); + maxTemp = ConvertKelvinToRankine(part.maxTemp); + unitSymbol = "°R"; + break; + case Unit.Celsius: + temp = ConvertKelvinToCelsius(part.temperature); + maxTemp = ConvertKelvinToCelsius(part.maxTemp); + unitSymbol = "°C"; + break; + case Unit.Fahrenheit: + temp = ConvertKelvinToFahrenheit(part.temperature); + maxTemp = ConvertKelvinToFahrenheit(part.maxTemp); + unitSymbol = "°F"; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return $"{temp:F2}{unitSymbol} / {maxTemp:F2}{unitSymbol}"; + } + ); + + public static readonly Metric TemperatureSkin = new Metric("TemperatureSkin", + "Temp. [S]", + "Skin Temperature", + new[] { Unit.Kelvin, Unit.Celsius, Unit.Rankine, Unit.Fahrenheit }, + vessel => new Dictionary + { + [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.skinTemperature), + [Variable.VesselCurrentMaximum] = vessel.Parts.Max(i => i.skinTemperature), + [Variable.VesselAbsoluteMinimum] = 0, + [Variable.VesselAbsoluteMaximum] = vessel.Parts.Max(i => i.skinMaxTemp) + }, + part => new Dictionary + { + [Variable.PartAbsoluteMinimum] = 0, + [Variable.PartAbsoluteMaximum] = part.skinMaxTemp + }, + part => part.skinTemperature, + (part, unit) => + { + double temp; + double maxTemp; + string unitSymbol; + + switch (unit) + { + case Unit.Kelvin: + temp = part.skinTemperature; + maxTemp = part.skinMaxTemp; + unitSymbol = "K"; + break; + case Unit.Rankine: + temp = ConvertKelvinToRankine(part.skinTemperature); + maxTemp = ConvertKelvinToRankine(part.skinMaxTemp); + unitSymbol = "°R"; + break; + case Unit.Celsius: + temp = ConvertKelvinToCelsius(part.skinTemperature); + maxTemp = ConvertKelvinToCelsius(part.skinMaxTemp); + unitSymbol = "°C"; + break; + case Unit.Fahrenheit: + temp = ConvertKelvinToFahrenheit(part.skinTemperature); + maxTemp = ConvertKelvinToFahrenheit(part.skinMaxTemp); + unitSymbol = "°F"; + break; + default: + throw new ArgumentOutOfRangeException(); + } + + return $"{temp:F2}{unitSymbol} / {maxTemp:F2}{unitSymbol}"; + } ); public static readonly Metric ThermalRate = new Metric("ThermalRate", "Thermal Rate", + "Thermal Rate", + new[] { Unit.Kilowatt }, vessel => new Dictionary { [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.GetThermalFlux()), [Variable.VesselCurrentMaximum] = vessel.Parts.Max(i => i.GetThermalFlux()) }, part => new Dictionary(), - part => part.GetThermalFlux() + part => part.GetThermalFlux(), + (part, unit) => $"{part.GetThermalFlux():F2}kW" ); public static readonly Metric ThermalRateInternal = new Metric("ThermalRateInternal", + "Thermal Rate [I]", "Internal Thermal Rate", + new[] { Unit.Kilowatt }, vessel => new Dictionary { - [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.thermalInternalFlux), - [Variable.VesselCurrentMaximum] = vessel.Parts.Max(i => i.thermalInternalFlux) + [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.thermalInternalFluxPrevious), + [Variable.VesselCurrentMaximum] = vessel.Parts.Max(i => i.thermalInternalFluxPrevious) }, part => new Dictionary(), - part => part.thermalInternalFlux + part => part.thermalInternalFluxPrevious, + (part, unit) => $"{part.thermalInternalFluxPrevious:F2}kW" ); public static readonly Metric ThermalRateConductive = new Metric("ThermalRateConductive", + "Thermal Rate [Cd]", "Conductive Thermal Rate", + new[] { Unit.Kilowatt }, vessel => new Dictionary { [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.thermalConductionFlux), [Variable.VesselCurrentMaximum] = vessel.Parts.Max(i => i.thermalConductionFlux) }, part => new Dictionary(), - part => part.thermalConductionFlux + part => part.thermalConductionFlux, + (part, unit) => $"{part.thermalConductionFlux:F2}kW" ); public static readonly Metric ThermalRateConvective = new Metric("ThermalRateConvective", + "Thermal Rate [Cv]", "Convective Thermal Rate", + new[] { Unit.Kilowatt }, vessel => new Dictionary { [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.thermalConvectionFlux), [Variable.VesselCurrentMaximum] = vessel.Parts.Max(i => i.thermalConvectionFlux) }, part => new Dictionary(), - part => part.thermalConvectionFlux + part => part.thermalConvectionFlux, + (part, unit) => $"{part.thermalConvectionFlux:F2}kW" ); public static readonly Metric ThermalRateRadiative = new Metric("ThermalRateRadiative", + "Thermal Rate [R]", "Radiative Thermal Rate", + new[] { Unit.Kilowatt }, vessel => new Dictionary { [Variable.VesselCurrentMinimum] = vessel.Parts.Min(i => i.thermalRadiationFlux), [Variable.VesselCurrentMaximum] = vessel.Parts.Max(i => i.thermalRadiationFlux) }, part => new Dictionary(), - part => part.thermalRadiationFlux + part => part.thermalRadiationFlux, + (part, unit) => $"{part.thermalRadiationFlux:F2}kW" ); private readonly Func> _getVesselValues; private readonly Func> _getPartValues; private readonly Func _getPartCurrent; + private readonly Func _getPartCurrentString; public string Name { get; } - public string FriendlyName { get; } + public string ShortFriendlyName { get; } + public string LongFriendlyName { get; } + public Unit[] Units { get; } - private Metric(string name, string friendlyName, + private Metric(string name, string shortFriendlyName, string longFriendlyName, Unit[] units, Func> getVesselValues, Func> getPartValues, - Func getPartCurrent + Func getPartCurrent, + Func getPartCurrentString ) { Name = name; - FriendlyName = friendlyName; + ShortFriendlyName = shortFriendlyName; + LongFriendlyName = longFriendlyName; + Units = units; _getVesselValues = getVesselValues; _getPartValues = getPartValues; _getPartCurrent = getPartCurrent; + _getPartCurrentString = getPartCurrentString; } public Dictionary GetVesselValues(Vessel vessel) @@ -114,6 +225,11 @@ public double GetPartCurrent(Part part) return _getPartCurrent(part); } + public string GetPartCurrentString(Part part, Unit unit) + { + return _getPartCurrentString(part, unit); + } + public static Metric Parse(string s) { var metric = TryParse(s); @@ -137,5 +253,24 @@ public static Metric TryParse(string s) return null; } + + #region Helpers + + private static double ConvertKelvinToRankine(double temp) + { + return temp * (9.0 / 5.0); + } + + private static double ConvertKelvinToCelsius(double temp) + { + return temp - 273.15; + } + + private static double ConvertKelvinToFahrenheit(double temp) + { + return temp * (9.0 / 5.0) - 459.67; + } + + #endregion } } diff --git a/Source/HotSpot/Model/Unit.cs b/Source/HotSpot/Model/Unit.cs index 4448707..9b85a3d 100644 --- a/Source/HotSpot/Model/Unit.cs +++ b/Source/HotSpot/Model/Unit.cs @@ -2,7 +2,7 @@ { internal enum Unit { - // Temperature + // TemperatureInternal Kelvin, Rankine, Celsius, diff --git a/appveyor.yml b/appveyor.yml index a8c3181..cf9c44e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,7 +8,7 @@ configuration: install: ps: | $kspLibs = "Assembly-CSharp.dll", "Assembly-CSharp-firstpass.dll", "UnityEngine.dll" - $kspLibsUrl = "http://build.apokee.com/dependencies/ksp/1.0.3" + $kspLibsUrl = "http://build.apokee.com/dependencies/ksp/1.0.4" $kspLibsDir = "$env:APPVEYOR_BUILD_FOLDER/Library/KSP" New-Item $kspLibsDir -Type Directory -Force | Out-Null @@ -43,7 +43,7 @@ after_build: ps: | $env:BUILD_VERSION = (cat Output/VERSION) $env:BUILD_PRELEASE = (cat Output/PRELEASE) - $env:BUILD_CHANGELOG = (cat Output/CHANGELOG).Replace("`r`n", "\n").Replace("`n", "\n").Replace("`r", "\n") + $env:BUILD_CHANGELOG = [System.String]::Join("\n", (cat Output/CHANGELOG)) $versionMessage = "Version: $env:BUILD_VERSION"