Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: f56524114623
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3957b9979861
Choose a head ref
  • 7 commits
  • 6 files changed
  • 1 contributor

Commits on Apr 20, 2020

  1. Copy the full SHA
    d269c28 View commit details
  2. Copy the full SHA
    de74219 View commit details
  3. Fix the clients.

    pleroy committed Apr 20, 2020
    Copy the full SHA
    790e3dd View commit details
  4. Fix formatting.

    pleroy committed Apr 20, 2020
    Copy the full SHA
    284a50d View commit details
  5. Cleanup.

    pleroy committed Apr 20, 2020
    Copy the full SHA
    6ff3dc3 View commit details

Commits on Apr 21, 2020

  1. After egg's review.

    pleroy committed Apr 21, 2020
    Copy the full SHA
    2058136 View commit details

Commits on Apr 22, 2020

  1. Merge pull request #2539 from pleroy/2520

    Add a C# class PrincipiaTimeSpan to gather time formatting and parsing
    pleroy authored Apr 22, 2020
    Copy the full SHA
    3957b99 View commit details
14 changes: 9 additions & 5 deletions ksp_plugin_adapter/burn_editor.cs
Original file line number Diff line number Diff line change
@@ -271,16 +271,20 @@ private void UseTheForceLuke() {
specific_impulse_in_seconds_g0_ = range;
}

internal string FormatPreviousCoastDuration(double value) {
return FlightPlanner.FormatPositiveTimeSpan(TimeSpan.FromSeconds(value));
internal string FormatPreviousCoastDuration(double seconds) {
return new PrincipiaTimeSpan(seconds).FormatPositive(
with_leading_zeroes: true,
with_seconds: true);
}

internal bool TryParsePreviousCoastDuration(string str, out double value) {
internal bool TryParsePreviousCoastDuration(string text, out double value) {
value = 0;
if (!FlightPlanner.TryParseTimeSpan(str, out TimeSpan ts)) {
if (!PrincipiaTimeSpan.TryParse(text,
with_seconds: true,
out PrincipiaTimeSpan ts)) {
return false;
}
value = ts.TotalSeconds;
value = ts.total_seconds;
return true;
}

110 changes: 26 additions & 84 deletions ksp_plugin_adapter/flight_planner.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;

namespace principia {
namespace ksp_plugin_adapter {
@@ -323,17 +321,16 @@ private void RenderUpcomingEvents() {
UnityEngine.GUILayout.Label("Upcoming manœuvre #" +
(first_future_manœuvre + 1) + ":");
UnityEngine.GUILayout.Label(
"Ignition " + FormatTimeSpan(TimeSpanFromSeconds(
current_time - manœuvre.burn.initial_time)),
"Ignition " +
FormatTimeSpan(current_time - manœuvre.burn.initial_time),
style : Style.RightAligned(UnityEngine.GUI.skin.label));
}
} else {
using (new UnityEngine.GUILayout.HorizontalScope()) {
UnityEngine.GUILayout.Label("Ongoing manœuvre #" +
(first_future_manœuvre + 1) + ":");
UnityEngine.GUILayout.Label(
"Cutoff " + FormatTimeSpan(TimeSpanFromSeconds(
current_time - manœuvre.final_time)),
"Cutoff " + FormatTimeSpan(current_time - manœuvre.final_time),
style : Style.RightAligned(UnityEngine.GUI.skin.label));
}
}
@@ -360,89 +357,33 @@ private void RenderUpcomingEvents() {
}
}

// A conversion function that swallows the overflow/NaN exceptions and
// saturates. Better than killing the UI.
internal static TimeSpan TimeSpanFromSeconds(double seconds) {
try {
return TimeSpan.FromSeconds(seconds);
} catch (OverflowException) {
if (seconds >= 0.0) {
return TimeSpan.MaxValue;
} else {
return TimeSpan.MinValue;
}
} catch (ArgumentException) {
return TimeSpan.Zero;
}
internal static string FormatPositiveTimeSpan(double seconds) {
return new PrincipiaTimeSpan(seconds).FormatPositive(
with_leading_zeroes: true,
with_seconds: true);
}

internal static string FormatPositiveTimeSpan(TimeSpan span) {
return (GameSettings.KERBIN_TIME
? (span.Days * 4 + span.Hours / 6).ToString("0000;0000") +
" d6 " + (span.Hours % 6).ToString("0;0") + " h "
: span.Days.ToString("000;000") + " d " +
span.Hours.ToString("00;00") + " h ") +
span.Minutes.ToString("00;00") + " min " +
(span.Seconds + span.Milliseconds / 1000m).ToString("00.0;00.0") +
" s";
internal static string FormatTimeSpan (double seconds) {
return new PrincipiaTimeSpan(seconds).Format(
with_leading_zeroes: true,
with_seconds: true);
}

internal static string FormatTimeSpan (TimeSpan span) {
return span.Ticks.ToString("+;-") + FormatPositiveTimeSpan(span);
}

internal static bool TryParseTimeSpan(string str, out TimeSpan value) {
value = TimeSpan.Zero;
// Using a technology that is customarily used to parse HTML.
string pattern = @"^[+]?\s*(\d+)\s*" +
(GameSettings.KERBIN_TIME ? "d6" : "d") +
@"\s*(\d+)\s*h\s*(\d+)\s*min\s*([0-9.,']+)\s*s$";
var regex = new Regex(pattern);
var match = regex.Match(str);
if (!match.Success) {
return false;
}
string days = match.Groups[1].Value;
string hours = match.Groups[2].Value;
string minutes = match.Groups[3].Value;
string seconds = match.Groups[4].Value;
if (!int.TryParse(days, out int d) ||
!int.TryParse(hours, out int h) ||
!int.TryParse(minutes, out int min) ||
!double.TryParse(seconds.Replace(',', '.'),
NumberStyles.AllowDecimalPoint |
NumberStyles.AllowThousands,
Culture.culture.NumberFormat,
out double s)) {
return false;
}
// Fail to parse if the user gives us overflowing input.
try {
value =
TimeSpan.FromDays((double)d / (GameSettings.KERBIN_TIME ? 4 : 1)) +
TimeSpan.FromHours(h) +
TimeSpan.FromMinutes(min) +
TimeSpan.FromSeconds(s);
return true;
} catch (OverflowException) {
return false;
} catch (ArgumentException) {
return false;
}
}

internal string FormatPlanLength(double value) {
return FormatPositiveTimeSpan(TimeSpanFromSeconds(
value - plugin.FlightPlanGetInitialTime(
predicted_vessel.id.ToString())));
return FormatPositiveTimeSpan(
value - plugin.FlightPlanGetInitialTime(
predicted_vessel.id.ToString()));
}

internal bool TryParsePlanLength(string str, out double value) {
internal bool TryParsePlanLength(string text, out double value) {
value = 0;
if (!TryParseTimeSpan(str, out TimeSpan ts)) {
if (!PrincipiaTimeSpan.TryParse(text,
with_seconds: true,
out PrincipiaTimeSpan ts)) {
return false;
}
value = ts.TotalSeconds +
value = ts.total_seconds +
plugin.FlightPlanGetInitialTime(predicted_vessel.id.ToString());
return true;
}
@@ -476,12 +417,13 @@ private string GetStatusMessage() {

string remedy_message = "changing the flight plan"; // Preceded by "Try".
string status_message = "computation failed"; // Preceded by "The".
string time_out_message =
timed_out ? " after " +
FormatPositiveTimeSpan(TimeSpanFromSeconds(
actual_final_time -
plugin.FlightPlanGetInitialTime(vessel_guid)))
: "";
string time_out_message = timed_out
? " after " +
FormatPositiveTimeSpan(
actual_final_time -
plugin.FlightPlanGetInitialTime(
vessel_guid))
: "";
if (status_.is_aborted()) {
status_message = "integrator reached the maximum number of steps" +
time_out_message;
1 change: 1 addition & 0 deletions ksp_plugin_adapter/ksp_plugin_adapter.csproj
Original file line number Diff line number Diff line change
@@ -135,6 +135,7 @@
<Compile Include="source_location.cs" />
<Compile Include="style.cs" />
<Compile Include="mono_marshaler.cs" />
<Compile Include="time_span.cs" />
<Compile Include="utf8_marshaler.cs" />
<Compile Include="utf16_marshaler.cs" />
<Compile Include="window_renderer.cs" />
5 changes: 3 additions & 2 deletions ksp_plugin_adapter/map_node_pool.cs
Original file line number Diff line number Diff line change
@@ -262,8 +262,9 @@ private KSP.UI.Screens.Mapview.MapNode MakePoolNode() {
}
if (properties.object_type != MapObject.ObjectType.PatchTransition) {
caption.captionLine1 =
"T" + FlightPlanner.FormatTimeSpan(TimeSpan.FromSeconds(
Planetarium.GetUniversalTime() - properties.time));
"T" + new PrincipiaTimeSpan(
Planetarium.GetUniversalTime() - properties.time).
Format(with_leading_zeroes: false, with_seconds: true);
}
};
new_node.OnUpdatePosition +=
105 changes: 31 additions & 74 deletions ksp_plugin_adapter/orbit_analyser.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace principia {
namespace ksp_plugin_adapter {
@@ -95,39 +90,16 @@ public static string FormatEquatorialAngleInterval(this Interval interval,
// leading 0s on the days; optionally exclude seconds.
public static string FormatDuration(this double seconds,
bool show_seconds = true) {
if (double.IsNaN(seconds)) {
return seconds.ToString();
}
var span = TimeSpan.FromSeconds(seconds);
int days = GameSettings.KERBIN_TIME ? span.Days * 4 + span.Hours / 6
: span.Days;
int hours = GameSettings.KERBIN_TIME ? span.Hours % 6
: span.Hours;
var components = new List<string>();
const string nbsp = "\xA0";
if (days > 0) {
components.Add(GameSettings.KERBIN_TIME ? $"{days}{nbsp}d6"
: $"{days}{nbsp}d");
}
if (components.Count > 0 || hours > 0) {
components.Add(
GameSettings.KERBIN_TIME ? $"{hours:0}{nbsp}h"
: $"{hours:00}{nbsp}h");
}
if (components.Count > 0 || span.Minutes > 0 || !show_seconds) {
components.Add($"{span.Minutes:00}{nbsp}min");
}
if (show_seconds) {
components.Add($"{span.Seconds + span.Milliseconds / 1000m:00.0}{nbsp}s");
}
return string.Join(" ", components.ToArray());
return new PrincipiaTimeSpan(seconds).FormatPositive(
with_leading_zeroes: false,
with_seconds: show_seconds);
}

// Formats an angular frequency (passed in rad/s), in °/d or °/d6.
public static string FormatAngularFrequency(this double radians_per_second) {
const double degree = Math.PI / 180;
double day = GameSettings.KERBIN_TIME ? 6 * 60 * 60 : 24 * 60 * 60;
string day_unit = GameSettings.KERBIN_TIME ? "d6" : "d";
double day = PrincipiaTimeSpan.day_duration;
string day_unit = PrincipiaTimeSpan.day_symbol;
double degrees_per_day = radians_per_second / (degree / day);
return $"{degrees_per_day.FormatN(2)}°/{day_unit}";
}
@@ -136,38 +108,22 @@ public static string FormatAngularFrequency(this double radians_per_second) {
// seconds (they are irrelevant for a selector that shows durations much
// longer than a revolution).
public static string FormatMissionDuration(double seconds) {
var span = TimeSpan.FromSeconds(seconds);
return (GameSettings.KERBIN_TIME
? (span.Days * 4 + span.Hours / 6).ToString("0000") +
" d6 " + (span.Hours % 6).ToString("0") + " h "
: span.Days.ToString("000") + " d " +
span.Hours.ToString("00") + " h ") +
span.Minutes.ToString("00") + " min";
return new PrincipiaTimeSpan(seconds).FormatPositive(
with_leading_zeroes: true,
with_seconds: false);
}

public static bool TryParseMissionDuration(string str, out double value) {
value = 0;
// Using a technology that is customarily used to parse HTML.
string pattern = @"^[+]?\s*(\d+)\s*" +
(GameSettings.KERBIN_TIME ? "d6" : "d") +
@"\s*(\d+)\s*h\s*(\d+)\s*min$";
var regex = new Regex(pattern);
var match = regex.Match(str);
if (!match.Success) {
return false;
}
string days = match.Groups[1].Value;
string hours = match.Groups[2].Value;
string minutes = match.Groups[3].Value;
if (!int.TryParse(days, out int d) ||
!int.TryParse(hours, out int h) ||
!int.TryParse(minutes, out int min)) {
public static bool TryParseMissionDuration(string str,
out double seconds) {
seconds = 0;
if (PrincipiaTimeSpan.TryParse(str,
with_seconds: false,
out PrincipiaTimeSpan ts)) {
seconds = ts.total_seconds;
return true;
} else {
return false;
}
value = (TimeSpan.FromDays((double)d / (GameSettings.KERBIN_TIME ? 4 : 1)) +
TimeSpan.FromHours(h) +
TimeSpan.FromMinutes(min)).TotalSeconds;
return true;
}
}

@@ -403,19 +359,20 @@ private void LabeledField(string label, string value) {
private const string em_dash = "—";

private readonly PrincipiaPluginAdapter adapter_;
private DifferentialSlider mission_duration_ = new DifferentialSlider(
label : "Duration",
unit : null,
log10_lower_rate : 0,
log10_upper_rate : 7,
min_value : 10,
max_value : double.PositiveInfinity,
formatter : Formatters.FormatMissionDuration,
parser : Formatters.TryParseMissionDuration,
label_width : 2,
field_width : 5) {
value = 7 * 24 * 60 * 60
};
private readonly DifferentialSlider mission_duration_ =
new DifferentialSlider(
label : "Duration",
unit : null,
log10_lower_rate : 0,
log10_upper_rate : 7,
min_value : 10,
max_value : double.PositiveInfinity,
formatter : Formatters.FormatMissionDuration,
parser : Formatters.TryParseMissionDuration,
label_width : 2,
field_width : 5) {
value = 7 * 24 * 60 * 60
};
private bool autodetect_recurrence_ = true;
private int revolutions_per_cycle_ = 1;
private int days_per_cycle_ = 1;
Loading