131 lines
5.3 KiB
PowerShell
131 lines
5.3 KiB
PowerShell
# 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"
|