# fix2-2025.ps1 - Comprehensive fix for 2025 restaurant JSON # 1. Fix all prices using authoritative data from price listing page # 2. Fix HTML entities in all text fields # 3. Report remaining issues $projectDir = Split-Path -Parent $MyInvocation.MyCommand.Definition $jsonPath = Join-Path $projectDir '2025-restaurants.json' # Load JSON $data = Get-Content $jsonPath -Raw -Encoding UTF8 | ConvertFrom-Json # ---- Authoritative price map from price listing page ---- $authPrices = @{ "1898"="45"; "24taps"="25"; "315cuisine"="45"; "ambrosia"="45"; "anthonys"="45"; "arrowhead"="25"; "baba"="45"; "backyardpublichouse"="35"; "bangkokthai"="35"; "bardenay"="45"; "barkrescuepub"="25"; "beverlys"="45"; "blackpearl"="25"; "borracho"="35"; "burgerdock"="25"; "cascadia"="25"; "cedars"="45"; "centennial"="35"; "chaps"="45"; "chinook"="45"; "chowderhead"="35"; "clinkerdagger"="45"; "cochinito"="25"; "collectivekitchen"="45"; "dassteinhaus"="35"; "deleons"="25"; "deleonstexmex"="25"; "dockside"="35"; "downriver"="45"; "dryfly"="35"; "durkins"="45"; "east"="45"; "emrys"="25"; "feastworldkitchen"="35"; "flameandcork"="35"; "flatstick"="25"; "flyinggoat"="25"; "fortheloveofgod"="35"; "francaise"="45"; "ganderryegrass"="35"; "gardenparty"="35"; "gildedunicorn"="45"; "hang10"="25"; "heritage"="35"; "hogwash"="45"; "honey"="35"; "hulapot"="35"; "indiahouse"="35"; "indicana"="45"; "inlandpacifickitchen"="45"; "irongoat"="35"; "ironwoodice"="35"; "karma"="35"; "kasa"="25"; "kismet"="35"; "kunisthai"="35"; "latahbistro"="45"; "lebanon"="35"; "legendsoffire"="45"; "littledragon"="25"; "littlenoodle"="25"; "longhornbbq"="25"; "loren"="45"; "lumberbeard"="35"; "macdaddys"="35"; "mackenzieriver"="25"; "mammamias"="25"; "mangotree"="25"; "maryhill"="45"; "masselowslounge"="45"; "max"="45"; "meltingpot"="45"; "mortys"="25"; "northhill"="35"; "odohertys"="35"; "osprey"="35"; "outsider"="45"; "palmcourtgrill"="45"; "ponderosa"="35"; "purenorthwest"="35"; "purgatory"="45"; "qqsushi"="35"; "redtail"="35"; "republickitchen"="35"; "republicpi"="25"; "rut"="35"; "safariroom"="45"; "saranac"="35"; "satay"="45"; "sauced"="25"; "screamingyak"="25"; "seasons"="45"; "shawnodonnells"="25"; "shelbys"="25"; "skewers"="25"; "southhillgrill"="45"; "southperrylantern"="45"; "spencers"="45"; "steamplant"="35"; "steelhead"="35"; "stylus"="35"; "sweetlous"="35"; "swinglounge"="35"; "table13"="45"; "tavolata"="45"; "terraza"="35"; "thaibamboo"="25"; "thedambar"="45"; "titos"="35"; "tomatostreet"="35"; "tonysonthelake"="45"; "torratea"="45"; "truelegends"="25"; "twigs"="35"; "uprise"="25"; "vaqueros"="35"; "vicinopizza"="25"; "victoryburger"="25"; "vieuxcarre"="35"; "vineolive"="45"; "wileys"="45" } function Decode-Html($str) { if (-not $str) { return $str } $s = $str $s = $s -replace '&', '&' $s = $s -replace ''', "'" $s = $s -replace '"', '"' $s = $s -replace '<', '<' $s = $s -replace '>', '>' $s = $s -replace ' ', ' ' $s = $s -replace '\s+', ' ' $s.Trim() } $priceFixed = 0 $entitiesFixed = 0 foreach ($r in $data) { # Fix price from authoritative map if ($authPrices.ContainsKey($r.slug)) { $correctPrice = [int]$authPrices[$r.slug] if ($r.price -ne $correctPrice) { Write-Host "Price fix: $($r.slug) $($r.price) -> $correctPrice" $r.price = $correctPrice $priceFixed++ } } # Fix HTML entities $oldName = $r.name $r.name = Decode-Html $r.name $r.cuisine = Decode-Html $r.cuisine $r.menu.hours = Decode-Html $r.menu.hours if ($oldName -ne $r.name) { $entitiesFixed++ } foreach ($course in @('First Course', 'Second Course', 'Third Course')) { $items = $r.menu.courses.$course if ($items) { foreach ($item in $items) { $item.name = Decode-Html $item.name $item.desc = Decode-Html $item.desc } } } } Write-Host "" Write-Host "Fixed prices: $priceFixed" Write-Host "Fixed names with entities: $entitiesFixed" Write-Host "" # ---- Report remaining issues ---- Write-Host "=== Remaining Issues ===" Write-Host "" Write-Host "Zero-course restaurants (all 3 empty):" $data | Where-Object { $_.menu.courses.'First Course'.Count -eq 0 -and $_.menu.courses.'Second Course'.Count -eq 0 -and $_.menu.courses.'Third Course'.Count -eq 0 } | ForEach-Object { Write-Host " $($_.slug) [$($_.price)] $($_.name)" } Write-Host "" Write-Host "Partial courses (any course count not 3):" $data | Where-Object { ($_.menu.courses.'First Course'.Count -ne 3 -or $_.menu.courses.'Second Course'.Count -ne 3 -or $_.menu.courses.'Third Course'.Count -ne 3) -and -not ( $_.menu.courses.'First Course'.Count -eq 0 -and $_.menu.courses.'Second Course'.Count -eq 0 -and $_.menu.courses.'Third Course'.Count -eq 0 ) } | ForEach-Object { $c1 = $_.menu.courses.'First Course'.Count $c2 = $_.menu.courses.'Second Course'.Count $c3 = $_.menu.courses.'Third Course'.Count Write-Host " $($_.slug) [$($_.price)]: $c1/$c2/$c3 - $($_.name)" } # ---- Save ---- $json = $data | ConvertTo-Json -Depth 10 [System.IO.File]::WriteAllText($jsonPath, $json, [System.Text.Encoding]::UTF8) Write-Host "" Write-Host "Saved to $jsonPath"