diff --git a/MeetUpPlanner/Server/Controllers/UtilController.cs b/MeetUpPlanner/Server/Controllers/UtilController.cs index fa5d799..93454ca 100644 --- a/MeetUpPlanner/Server/Controllers/UtilController.cs +++ b/MeetUpPlanner/Server/Controllers/UtilController.cs @@ -20,7 +20,7 @@ public class UtilController : ControllerBase { private readonly MeetUpFunctions _meetUpFunctions; private readonly ILogger logger; - const string serverVersion = "2024-01-02"; + const string serverVersion = "2024-01-20"; string functionsVersion = "tbd"; public UtilController(ILogger logger, MeetUpFunctions meetUpFunctions) diff --git a/MeetUpPlanner/Server/Controllers/WebcalController.cs b/MeetUpPlanner/Server/Controllers/WebcalController.cs index 5a69fb8..e566caf 100644 --- a/MeetUpPlanner/Server/Controllers/WebcalController.cs +++ b/MeetUpPlanner/Server/Controllers/WebcalController.cs @@ -16,6 +16,7 @@ using System.Text; using System; using System.Web; +using MeetUpPlanner.Client.Shared; namespace MeetUpPlanner.Server.Controllers { @@ -66,8 +67,8 @@ public async Task GetMeetUps([FromRoute] string key) Summary = meetUp.Title, Description = description.ToString(), Start = new CalDateTime(meetUp.StartDate), - // Ends 1 hours later. - End = new CalDateTime(meetUp.StartDate.AddHours(1.0)), + // Calculate/estimate end of event, default is 2 hours + End = new CalDateTime(meetUp.StartDate.AddHours(GetEstimatedDurationInHours(meetUp))), Location = meetUp.Place }; webCal.Events.Add(icalEvent); @@ -99,5 +100,69 @@ public static string StripHTML(string HTMLText, bool decode = true) } } + public uint GetTempoAsKilometersPerHour(ExtendedCalendarItem meetUp) + { + // Usual formats: '25 - 30km/h', '30km/h', '~20kmh'. We simply parse + // the first 2-3 digit number and interpret it as km/h. the result + // is also clamped between 0..40 to guard against unexpected inputs. + uint kmh = 0; + try + { + var match = Regex.Match(meetUp.Tempo, @"(\d{1,3})"); + if (match.Success) + { + kmh = uint.Parse(match.Groups[1].ToString()); + } + } + catch (Exception ex) + { + _logger.LogError(ex.ToString()); + // in case of any exception ==> fallback to defaults + } + + return Math.Clamp(kmh, 0, 40); + } + public uint GetDistanceAsKilometers(ExtendedCalendarItem meetUp) + { + // Usual formats include '65km / 200Hm' with or without spaces, '40 + // oder 60km'. Return value is clamped between 0 and 300 to guard + // against unexpected inputs. + uint distance = 0; + try + { + var match = Regex.Match(meetUp.LevelDescription, @"(\d{1,4})\s*(?:km)?"); + if (match.Success) + { + distance = uint.Parse(match.Groups[1].ToString()); + } + } + catch (Exception ex) + { + _logger.LogError(ex.ToString()); + // in case of any exception ==> fallback to defaults + } + + return Math.Clamp(distance, 0, 300); + } + /// + /// To get a better fit for the duration (instead of 1 hour as default) this function tries to estimate the duration by parsing the tempo and length. + /// If no appropriate tempo/distance is detected ==> use 2 hours + /// Contributed by: Moritz von Göwels https://github.com/the-kenny + /// + /// + /// + public double GetEstimatedDurationInHours(ExtendedCalendarItem meetUp) + { + var distance = GetDistanceAsKilometers(meetUp); // 0..inf + if (distance == 0) { distance = 50; } // default to 50km + + var speed = GetTempoAsKilometersPerHour(meetUp); // 0..100 + if (speed == 0) { speed = 25; } // Default to 25km/h + + double duration = (double)distance / (double)speed; + // Clamp between 15 minutes and 24 hours + return Math.Clamp(duration, 0.25, 24.0); + } + } } diff --git a/MeetUpPlanner/Server/MeetUpPlanner.Server.csproj b/MeetUpPlanner/Server/MeetUpPlanner.Server.csproj index 483787f..1e664c5 100644 --- a/MeetUpPlanner/Server/MeetUpPlanner.Server.csproj +++ b/MeetUpPlanner/Server/MeetUpPlanner.Server.csproj @@ -7,7 +7,7 @@ - +