mirror of
https://github.com/CCOSTAN/Home-AssistantConfig.git
synced 2026-07-09 23:36:38 -07:00
162 lines
4.8 KiB
PowerShell
162 lines
4.8 KiB
PowerShell
param(
|
|
[int]$Months = 24,
|
|
[datetime]$StartDate = (Get-Date).Date
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
$repoRoot = Split-Path -Parent $PSScriptRoot
|
|
$holidayPath = Join-Path $repoRoot 'config/www/json_data/holidays.json'
|
|
$flagPath = Join-Path $repoRoot 'config/www/json_data/flag_days.json'
|
|
$scenePath = Join-Path $repoRoot 'config/scene/monthly_colors.yaml'
|
|
$endDate = $StartDate.Date.AddMonths($Months)
|
|
$errors = @()
|
|
|
|
function Read-JsonFile {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$Path
|
|
)
|
|
|
|
if (-not (Test-Path -LiteralPath $Path)) {
|
|
throw "Missing JSON file: $Path"
|
|
}
|
|
|
|
try {
|
|
return Get-Content -Raw -LiteralPath $Path | ConvertFrom-Json -AsHashtable
|
|
} catch {
|
|
throw "Invalid JSON in $Path`: $($_.Exception.Message)"
|
|
}
|
|
}
|
|
|
|
function Parse-DateKey {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[string]$DateText
|
|
)
|
|
|
|
return [datetime]::Parse(
|
|
$DateText,
|
|
[Globalization.CultureInfo]::InvariantCulture
|
|
).Date
|
|
}
|
|
|
|
function Get-DynamicEvents {
|
|
param(
|
|
[Parameter(Mandatory = $true)]
|
|
[object]$DynamicMap,
|
|
[Parameter(Mandatory = $true)]
|
|
[string[]]$Names
|
|
)
|
|
|
|
$events = @()
|
|
foreach ($dateText in $DynamicMap.Keys) {
|
|
$eventDate = Parse-DateKey -DateText ([string]$dateText)
|
|
$eventName = [string]$DynamicMap[$dateText]
|
|
if ($eventDate -ge $StartDate.Date -and $eventDate -lt $endDate -and $Names -contains $eventName) {
|
|
$events += [pscustomobject]@{
|
|
Name = $eventName
|
|
Date = $eventDate
|
|
}
|
|
}
|
|
}
|
|
return $events | Sort-Object Date, Name
|
|
}
|
|
|
|
$holidayJson = Read-JsonFile -Path $holidayPath
|
|
$flagJson = Read-JsonFile -Path $flagPath
|
|
$holidayData = $holidayJson['MAJOR_US']
|
|
$flagData = $flagJson['Flag_Days_US']
|
|
$holidayStatic = $holidayData['static']
|
|
$holidayDynamic = $holidayData['dynamic']
|
|
$flagDynamic = $flagData['dynamic']
|
|
|
|
$sceneText = Get-Content -Raw -LiteralPath $scenePath
|
|
$sceneNames = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal)
|
|
foreach ($match in [regex]::Matches($sceneText, '(?m)^\s*-\s+name:\s+(month_[A-Za-z0-9_]+_colors)\s*$')) {
|
|
[void]$sceneNames.Add($match.Groups[1].Value)
|
|
}
|
|
|
|
$lightingModes = @(
|
|
'standard',
|
|
'RWB',
|
|
'new_years_day',
|
|
'valentine',
|
|
'mardi_gras',
|
|
'pi',
|
|
'st_patty',
|
|
'easter',
|
|
'starwars',
|
|
'cinco_de_mayo',
|
|
'mothers_day',
|
|
'fathers_day',
|
|
'halloween',
|
|
'veterans',
|
|
'thanksgiving',
|
|
'hanukkah',
|
|
'christmas'
|
|
)
|
|
|
|
foreach ($mode in $lightingModes) {
|
|
$sceneName = "month_${mode}_colors"
|
|
if (-not $sceneNames.Contains($sceneName)) {
|
|
$errors += "Missing scene for lighting mode '$mode': expected $sceneName in $scenePath"
|
|
}
|
|
}
|
|
|
|
$staticRequirements = @(
|
|
@{ Key = '1/1'; Name = 'New Years Day' },
|
|
@{ Key = '2/14'; Name = 'Valentines Day' },
|
|
@{ Key = '3/14'; Name = 'Pi Day' },
|
|
@{ Key = '3/17'; Name = 'St. Patricks Day' },
|
|
@{ Key = '5/4'; Name = 'Star Wars Day' },
|
|
@{ Key = '5/5'; Name = 'Cinco de Mayo' },
|
|
@{ Key = '7/4'; Name = 'Independence Day' },
|
|
@{ Key = '10/31'; Name = 'Halloween' },
|
|
@{ Key = '11/11'; Name = 'Veterans Day' },
|
|
@{ Key = '12/25'; Name = 'Christmas Day' },
|
|
@{ Key = '12/31'; Name = 'New Years Eve' }
|
|
)
|
|
|
|
foreach ($requirement in $staticRequirements) {
|
|
if (-not $holidayStatic.ContainsKey($requirement.Key)) {
|
|
$errors += "Missing static holiday key $($requirement.Key) for $($requirement.Name)"
|
|
}
|
|
}
|
|
|
|
$dynamicRequirements = @(
|
|
@{ Name = 'Easter Sunday'; Source = 'holidays'; Map = $holidayDynamic },
|
|
@{ Name = 'Mothers Day'; Source = 'holidays'; Map = $holidayDynamic },
|
|
@{ Name = 'Fathers Day'; Source = 'holidays'; Map = $holidayDynamic },
|
|
@{ Name = 'Thanksgiving Day'; Source = 'holidays'; Map = $holidayDynamic },
|
|
@{ Name = 'Memorial Day'; Source = 'flag_days'; Map = $flagDynamic },
|
|
@{ Name = 'Labor Day'; Source = 'flag_days'; Map = $flagDynamic }
|
|
)
|
|
|
|
foreach ($requirement in $dynamicRequirements) {
|
|
$events = @(Get-DynamicEvents -DynamicMap $requirement.Map -Names @($requirement.Name))
|
|
if ($events.Count -eq 0) {
|
|
$errors += "No $($requirement.Source) calendar coverage for '$($requirement.Name)' between $($StartDate.ToString('yyyy-MM-dd')) and $($endDate.ToString('yyyy-MM-dd'))"
|
|
}
|
|
}
|
|
|
|
Write-Host "Holiday lighting coverage window: $($StartDate.ToString('yyyy-MM-dd')) to $($endDate.ToString('yyyy-MM-dd'))"
|
|
Write-Host "JSON: OK - parsed holidays.json and flag_days.json"
|
|
Write-Host "Scenes: $($sceneNames.Count) monthly scenes found"
|
|
|
|
if ($errors.Count -gt 0) {
|
|
foreach ($err in $errors) {
|
|
Write-Host "ERROR: $err"
|
|
}
|
|
exit 1
|
|
}
|
|
|
|
foreach ($requirement in $dynamicRequirements) {
|
|
$events = @(Get-DynamicEvents -DynamicMap $requirement.Map -Names @($requirement.Name))
|
|
$dates = ($events | ForEach-Object { $_.Date.ToString('yyyy-MM-dd') }) -join ', '
|
|
Write-Host "$($requirement.Name): $dates"
|
|
}
|
|
|
|
Write-Host "Coverage OK: required lighting scenes and dynamic holiday dates are present for the requested window."
|