5.14 시작전

This commit is contained in:
2026-05-14 09:38:45 +09:00
parent 8b5c92194f
commit e76c37ef56
24 changed files with 3638 additions and 717 deletions

View File

@@ -155,7 +155,9 @@ internal static class CurrentApiCutDiagnostics
districtCache,
electionType,
station,
options.RegionScope == "all" || IsNormalPanseMapTemplate(template))
options.RegionScope == "all" || IsNormalPanseMapTemplate(template),
template,
preElectionHistoryService)
.ConfigureAwait(false);
}
catch (Exception ex)
@@ -620,6 +622,10 @@ internal static class CurrentApiCutDiagnostics
? overview.TurnoutVotes
: primaryItem?.TurnoutVotes ?? 0;
var snapshotReferenceTimeLabel = includeNationalSlot
? overview.ReferenceTimeLabel
: FirstNonWhiteSpace(primaryItem?.ReferenceTimeLabel, overview.ReferenceTimeLabel);
return new ElectionDataSnapshot
{
BroadcastPhase = BroadcastPhase.PreElection,
@@ -634,7 +640,8 @@ internal static class CurrentApiCutDiagnostics
CountedVotesFromApi = null,
RemainingVotesFromApi = null,
CountedRateFromApi = null,
ReceivedAt = DateTimeOffset.Now,
ReceivedAt = overview.ReceivedAt == default ? DateTimeOffset.Now : overview.ReceivedAt,
ReferenceTimeLabel = snapshotReferenceTimeLabel,
TurnoutBoardSlots = turnoutBoardSlots,
NationalTurnoutRateOverride = overview.NationalTurnoutRate
};
@@ -1104,6 +1111,7 @@ internal static class CurrentApiCutDiagnostics
RemainingVotesFromApi = null,
CountedRateFromApi = null,
ReceivedAt = overview.ReceivedAt == default ? DateTimeOffset.Now : overview.ReceivedAt,
ReferenceTimeLabel = FirstNonWhiteSpace(item.ReferenceTimeLabel, overview.ReferenceTimeLabel),
NationalTurnoutRateOverride = overview.NationalTurnoutRate
};
}
@@ -1318,8 +1326,15 @@ internal static class CurrentApiCutDiagnostics
IDictionary<string, IReadOnlyList<SbsElectionApiClient.DistrictSelectionOption>> districtCache,
string electionType,
BroadcastStationProfile station,
bool useAllRegions = false)
bool useAllRegions,
FormatTemplateDefinition template,
PreElectionHistoryService preElectionHistoryService)
{
if (UsesHistoricalStoredOptions(template))
{
return GetStoredHistoryDistricts(electionType, preElectionHistoryService);
}
var regionFilters = useAllRegions ? Array.Empty<string>() : station.RegionFilters;
var cacheKey = $"{electionType}|{string.Join(",", regionFilters)}";
if (!districtCache.TryGetValue(cacheKey, out var districts))
@@ -1333,6 +1348,59 @@ internal static class CurrentApiCutDiagnostics
return districts;
}
private static IReadOnlyList<SbsElectionApiClient.DistrictSelectionOption> GetStoredHistoryDistricts(
string electionType,
PreElectionHistoryService preElectionHistoryService)
{
return preElectionHistoryService
.GetSelectionRecords(electionType)
.Where(record => !string.IsNullOrWhiteSpace(ResolveStoredHistoryDisplayName(record)))
.OrderBy(record => SbsElectionApiClient.ResolveBasicApiSidoCode(record.RegionName), StringComparer.Ordinal)
.ThenBy(record => ResolveStoredHistoryDisplayName(record), StringComparer.Ordinal)
.Select(CreateStoredHistoryDistrict)
.ToArray();
}
private static SbsElectionApiClient.DistrictSelectionOption CreateStoredHistoryDistrict(
PreElectionHistoryRecord record)
{
var regionName = string.IsNullOrWhiteSpace(record.RegionName)
? record.DisplayName
: record.RegionName;
var districtName = string.IsNullOrWhiteSpace(record.DistrictName)
? ResolveStoredHistoryDisplayName(record)
: record.DistrictName;
var parentRegionCode = SbsElectionApiClient.ResolveBasicApiSidoCode(regionName);
var districtCode = string.Equals(
PreElectionHistoryService.NormalizeElectionType(record.ElectionType),
"기초단체장",
StringComparison.Ordinal)
? record.Key
: parentRegionCode;
return new SbsElectionApiClient.DistrictSelectionOption(
ResolveStoredHistoryDisplayName(record),
districtCode,
regionName,
districtName,
parentRegionCode);
}
private static string ResolveStoredHistoryDisplayName(PreElectionHistoryRecord record)
{
if (!string.IsNullOrWhiteSpace(record.DisplayName))
{
return record.DisplayName;
}
if (!string.IsNullOrWhiteSpace(record.DistrictName))
{
return record.DistrictName;
}
return record.RegionName ?? string.Empty;
}
private static IEnumerable<SbsElectionApiClient.DistrictSelectionOption> ResolveTargets(
IReadOnlyList<SbsElectionApiClient.DistrictSelectionOption> districts,
BroadcastStationProfile station,
@@ -1398,7 +1466,8 @@ internal static class CurrentApiCutDiagnostics
CountedVotesFromApi = refreshResult.CountedVotes,
RemainingVotesFromApi = refreshResult.RemainingVotes,
CountedRateFromApi = refreshResult.CountedRate,
ReceivedAt = refreshResult.ReceivedAt == default ? DateTimeOffset.Now : refreshResult.ReceivedAt
ReceivedAt = refreshResult.ReceivedAt == default ? DateTimeOffset.Now : refreshResult.ReceivedAt,
ReferenceTimeLabel = refreshResult.ReferenceTimeLabel
};
}
@@ -2297,12 +2366,22 @@ internal static class CurrentApiCutDiagnostics
return "기초단체장";
}
if (ScheduleTemplatePolicy.IsHistoricalTurnoutFormat(template.Name))
{
return "광역단체장";
}
return ResolveScheduleElectionType(template.Name, phase, defaultElectionType);
}
private static string ResolveScheduleElectionType(string? formatName, BroadcastPhase phase, string defaultElectionType)
{
var resolvedFormatName = formatName ?? string.Empty;
if (ScheduleTemplatePolicy.IsHistoricalTurnoutFormat(resolvedFormatName))
{
return "광역단체장";
}
if (resolvedFormatName.Contains("교육감", StringComparison.Ordinal))
{
return "교육감";
@@ -2343,6 +2422,12 @@ internal static class CurrentApiCutDiagnostics
return defaultElectionType;
}
private static bool UsesHistoricalStoredOptions(FormatTemplateDefinition template)
{
return ScheduleTemplatePolicy.IsHistoricalTurnoutFormat(template.Name) ||
ScheduleTemplatePolicy.IsHistoricalWinnerFormat(template.Name);
}
private static bool SupportsPreElectionTurnout(string? electionType)
{
return string.Equals(electionType, "광역단체장", StringComparison.Ordinal) ||