Skip to content

Commit

Permalink
Merge pull request #47 from OpenSpartan/release-1.0.8
Browse files Browse the repository at this point in the history
1.0.8 Release
  • Loading branch information
dend authored Jul 30, 2024
2 parents 3f55a9d + eb5002d commit d9f298d
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 57 deletions.
20 changes: 2 additions & 18 deletions CURRENTRELEASE.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
# OpenSpartan Workshop 1.0.7 (`CYLIX-06082024`)
# OpenSpartan Workshop 1.0.8 (`SLIPSPACE-06282024`)

- [#30] Prevent auth loops if incorrect release number is used.
- [#38] Battlepass data now correctly renders on smaller screens, allowing scrolling.
- [#39] Removes the odd cross-out line in the calendar view.
- [#41] Fixes average life positioning, ensuring that it can't cause overflow.
- [#43] Fixed the issue where the medals are not rendered on first cold boot.
- [#45] Fixed an issue where refreshing The Exchange with no internet will result in an infinite spinning loading indicator.
- Improved image fallback for The Exchange, so that missing items now render properly.
- Season calendar now includes background images for each event, operation, and battle pass season.
- Calendar colors are now easier to read.
- Fixes how ranked match percentage is calculated, now showing proper values for next level.
- Home page now can be scrolled on smaller screens.
- Inside match metadata, medals and ranked counterfactuals correctly flow when screen is resized.
- The app now correctly reacts at startup to an error with authentication token acquisition. A message is shown if that is not possible.
- General performance optimizations and maintainability cleanup.
- Fixed an issue where duplicate ranked playlist may render in the **Ranked Progression** view.
- Fixed an issue where duplicate items may render in the **Exchange** view.
- Massive speed up to the **Operations** view load times - the app no longer issues unnecessary REST API calls to get currency data.
- Individual match stats acquisition now supports retries, in case the initial call fails and we still need to obtain proper match data. This is helpful for scenarios where we're using loose match searches and need to make sure that the proper data is captured when inserting in the DB.

Refer to [**getting started guide**](https://openspartan.com/docs/workshop/guides/get-started/) to start using OpenSpartan Workshop.
16 changes: 11 additions & 5 deletions src/OpenSpartan.Workshop/Core/DateRangeParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,31 @@ internal static List<Tuple<DateTime, DateTime>> ExtractDateRanges(string input)
{
// There is a typo in one of the date range definitions, so we want to
// work around it by replacing it with the proper string.
input = input.Replace("Febraury", "February", StringComparison.OrdinalIgnoreCase);
input = input.Replace("Febraury", "February", StringComparison.OrdinalIgnoreCase)
.Replace("Sept ", "Sep ", StringComparison.OrdinalIgnoreCase);

// Updated regex pattern to handle variations in date formats
string pattern = @"(?<startMonth>\w+)\s(?<startDay>\d{1,2})(?:st|nd|rd|th)?,?\s(?<startYear>\d{4})(?:\s-\s(?<endMonth>\w+)\s(?<endDay>\d{1,2})(?:st|nd|rd|th)?,?\s(?<endYear>\d{4}))?";
Regex regex = new Regex(pattern);
string[] dateFormats = { "MMMM d, yyyy", "MMM d, yyyy", "MMMM d yyyy", "MMM d yyyy" };

// Added additional date formats to handle more variations
string[] dateFormats = { "MMMM d, yyyy", "MMM d, yyyy", "MMMM d yyyy", "MMM d yyyy", "MMMM dd, yyyy", "MMM dd, yyyy", "MMMM dd yyyy", "MMM dd yyyy" };

return regex.Matches(input).Cast<Match>()
.Select(match =>
{
string startDay = Regex.Replace(match.Groups["startDay"].Value, @"(st|nd|rd|th)", "");
string endDay = Regex.Replace(match.Groups["endDay"].Value, @"(st|nd|rd|th)", "");
string endDay = match.Groups["endDay"].Success ? Regex.Replace(match.Groups["endDay"].Value, @"(st|nd|rd|th)", "") : null;

string startDateStr = $"{match.Groups["startMonth"].Value} {startDay}, {match.Groups["startYear"].Value}";
string endDateStr = match.Groups["endMonth"].Success
? $"{match.Groups["endMonth"].Value} {endDay}, {match.Groups["endYear"].Value}"
: startDateStr;

if (DateTime.TryParseExact(startDateStr, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime startDate) &&
DateTime.TryParseExact(endDateStr, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime endDate))
bool startDateParsed = DateTime.TryParseExact(startDateStr, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime startDate);
bool endDateParsed = DateTime.TryParseExact(endDateStr, dateFormats, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime endDate);

if (startDateParsed && endDateParsed)
{
return new Tuple<DateTime, DateTime>(startDate, endDate);
}
Expand Down
File renamed without changes.
86 changes: 54 additions & 32 deletions src/OpenSpartan.Workshop/Core/UserContextManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Identity.Client.Extensions.Msal;
using Microsoft.UI;
using Microsoft.UI.Xaml;
using NLog;
using OpenSpartan.Workshop.Data;
using OpenSpartan.Workshop.Models;
using OpenSpartan.Workshop.ViewModels;
Expand Down Expand Up @@ -735,14 +736,28 @@ await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>

private static async Task<HaloApiResultContainer<MatchStats, RawResponseContainer>> GetMatchStats(string matchId, double completionProgress)
{
var matchStats = await SafeAPICall(async () => await HaloClient.StatsGetMatchStats(matchId));
if (matchStats == null || matchStats.Result == null)
int retryCount = 0;
const int maxRetries = 3;
HaloApiResultContainer<MatchStats, RawResponseContainer> matchStats = null;

while (retryCount < maxRetries)
{
LogEngine.Log($"[{completionProgress:#.00}%] [Error] Getting match stats from the Halo Infinite API failed for {matchId}.", LogSeverity.Error);
return null;
matchStats = await SafeAPICall(async () => await HaloClient.StatsGetMatchStats(matchId));
if (matchStats != null && matchStats.Result != null)
{
return matchStats;
}

retryCount++;
if (retryCount < maxRetries)
{
LogEngine.Log($"[{completionProgress:#.00}%] [Warning] Getting match stats from the Halo Infinite API failed for {matchId}. Retrying... ({retryCount}/{maxRetries})", LogSeverity.Warning);
await Task.Delay(1000); // Optional: delay between retries
}
}

return matchStats;
LogEngine.Log($"[{completionProgress:#.00}%] [Error] Getting match stats from the Halo Infinite API failed for {matchId} after {maxRetries} attempts.", LogSeverity.Error);
return null;
}

private static async Task<HaloApiResultContainer<MatchSkillInfo, RawResponseContainer>> GetPlayerStats(string matchId)
Expand Down Expand Up @@ -1156,41 +1171,48 @@ await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>

private async static Task ProcessRegularSeasonRanges(string rangeText, string name, int index, string backgroundPath = "")
{
List<Tuple<DateTime, DateTime>> ranges = DateRangeParser.ExtractDateRanges(rangeText);
foreach (var range in ranges)
try
{
var days = GenerateDateList(range.Item1, range.Item2);
if (days != null)
List<Tuple<DateTime, DateTime>> ranges = DateRangeParser.ExtractDateRanges(rangeText);
foreach (var range in ranges)
{
foreach (var day in days)
var days = GenerateDateList(range.Item1, range.Item2);
if (days != null)
{
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
foreach (var day in days)
{
var targetDay = SeasonCalendarViewModel.Instance.SeasonDays
.Where(x => x.DateTime.Date == day.Date)
.FirstOrDefault();

if (targetDay != null)
{
targetDay.RegularSeasonText = name;
targetDay.RegularSeasonMarkerColor = ColorConverter.FromHex(Configuration.SeasonColors[index]);
targetDay.BackgroundImagePath = backgroundPath;
}
else
await DispatcherWindow.DispatcherQueue.EnqueueAsync(() =>
{
SeasonCalendarViewDayItem calendarItem = new();
calendarItem.DateTime = day;
calendarItem.CSRSeasonText = string.Empty;
calendarItem.CSRSeasonMarkerColor = new Microsoft.UI.Xaml.Media.SolidColorBrush(Colors.White);
calendarItem.RegularSeasonText = name;
calendarItem.RegularSeasonMarkerColor = ColorConverter.FromHex(Configuration.SeasonColors[index]);
calendarItem.BackgroundImagePath = backgroundPath;
SeasonCalendarViewModel.Instance.SeasonDays.Add(calendarItem);
}
});
var targetDay = SeasonCalendarViewModel.Instance.SeasonDays
.Where(x => x.DateTime.Date == day.Date)
.FirstOrDefault();

if (targetDay != null)
{
targetDay.RegularSeasonText = name;
targetDay.RegularSeasonMarkerColor = ColorConverter.FromHex(Configuration.SeasonColors[index]);
targetDay.BackgroundImagePath = backgroundPath;
}
else
{
SeasonCalendarViewDayItem calendarItem = new();
calendarItem.DateTime = day;
calendarItem.CSRSeasonText = string.Empty;
calendarItem.CSRSeasonMarkerColor = new Microsoft.UI.Xaml.Media.SolidColorBrush(Colors.White);
calendarItem.RegularSeasonText = name;
calendarItem.RegularSeasonMarkerColor = ColorConverter.FromHex(Configuration.SeasonColors[index]);
calendarItem.BackgroundImagePath = backgroundPath;
SeasonCalendarViewModel.Instance.SeasonDays.Add(calendarItem);
}
});
}
}
}
}
catch (Exception ex)
{
LogEngine.Log($"Could not process regular season ranges. {ex.Message}", LogSeverity.Error);
}
}

static List<DateTime> GenerateDateList(DateTime? lowerDate, DateTime? upperDate)
Expand Down
4 changes: 2 additions & 2 deletions src/OpenSpartan.Workshop/ViewModels/HomeViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public double? RankProgress
{
if (CurrentRankExperience != null && RequiredRankExperience != null)
{
return Convert.ToDouble(CurrentRankExperience) / Convert.ToDouble(RequiredRankExperience);
return Convert.ToDouble(CurrentRankExperience, CultureInfo.CurrentCulture) / Convert.ToDouble(RequiredRankExperience, CultureInfo.CurrentCulture);
}
else
{
Expand Down Expand Up @@ -293,7 +293,7 @@ public int? ExperienceRemaining

public double? ExperienceProgress
{
get => Convert.ToDouble(ExperienceEarnedToDate, CultureInfo.InvariantCulture) / Convert.ToDouble(ExperienceTotalRequired, CultureInfo.InvariantCulture);
get => Convert.ToDouble(ExperienceEarnedToDate, CultureInfo.CurrentCulture) / Convert.ToDouble(ExperienceTotalRequired, CultureInfo.CurrentCulture);
}

public void NotifyPropertyChanged([CallerMemberName] string? propertyName = null)
Expand Down

0 comments on commit d9f298d

Please sign in to comment.