Prototype spatial GPS edge weights

This commit is contained in:
2026-06-26 21:24:24 -05:00
parent 55f4087458
commit 56ef79d14a
6 changed files with 982 additions and 37 deletions
+42 -4
View File
@@ -6,8 +6,8 @@ Current date/time context: 2026-06-26, local timezone America/Chicago.
- Installed RED4ext state is safe: the game plugin directory contains - Installed RED4ext state is safe: the game plugin directory contains
`EdgeWeightGPS.dll.disabled`, not an active `EdgeWeightGPS.dll`. `EdgeWeightGPS.dll.disabled`, not an active `EdgeWeightGPS.dll`.
- Latest committed safe source before this update: `d68a874 Disable unstable - Latest committed safe source before this update: `55f4087 Document VAND GPS
traffic scorer hook`. search graph`.
- Current source has `kEnableGpsTrafficEdgeWeightPatch = false` and - Current source has `kEnableGpsTrafficEdgeWeightPatch = false` and
`kEnableGpsLocalSearchHooks = false`. `kEnableGpsLocalSearchHooks = false`.
- The real route search is confirmed at `0x44f054`, called from - The real route search is confirmed at `0x44f054`, called from
@@ -44,6 +44,42 @@ Current date/time context: 2026-06-26, local timezone America/Chicago.
highway/arterial corridors, or patch the navigation VAND graph/classes after highway/arterial corridors, or patch the navigation VAND graph/classes after
extracting the relevant streamingsector resources. extracting the relevant streamingsector resources.
## 2026-06-26 Spatial Edge-Cost Prototype
- Added `tools/generate_spatial_edge_grid.py`, which combines
`work/raw-segment-json/all.traffic_persistent.json` lane flags with
`work/traffic-companions/json/all.lane_polygons.json` polygons.
- Generated
`red4ext/EdgeWeightGPS/src/GeneratedSpatialRoadGrid.hpp`. The grid is
332 x 361 cells at 32 m/cell, origin `(-4640, -7392)`, with final cell
counts `H=7574`, `R=19617`, `G=20`, `P=996`, `unknown=91645`.
- Added disabled-by-default runtime plumbing behind
`kEnableGpsSpatialEdgeWeightPatch = false`. When enabled, it attaches only
`GPSRouteProducer 0x44cc7c` and `GPSEdgeCost 0x44f838` unless the old verbose
local-search probe is also enabled.
- The patch reads search-state vectors as `(world X, height, world Y)`, samples
the current endpoint, neighbor endpoint, and midpoint, chooses the strongest
spatial road class, then applies a multiplier after native `0x44f838`
returns. Current test multipliers are highway `0.62`, road `1.0`,
GPS-only `1.20`, pavement `1.35`, unknown `1.05`.
- The patch intentionally does not rewrite VAND point class bits. Static
materialization code branches on those bits later, so changing them in data is
riskier than adjusting cost at the edge-cost vtable slot.
- Fixed `DetourGpsEdgeCost` logging: native `0x44f838` indexes the provider
cost table by neighbor point class, not source point class.
- Build verification passed in the Fedora toolbox:
`toolbox run -c 2077 tools/build_red4ext_shim.sh`.
- The resulting DLL remains uninstalled. Game install still has only
`EdgeWeightGPS.dll.disabled`, not an active plugin DLL.
Important caveat:
- Runtime logs show long visible GPS routes are decomposed into many
`0x44cc7c` local searches. The `ret_rva=0x70aa22` caller with
`query_f78=10` and `query_ptr98_rva=0x8d76c4` mostly produces tiny connector
searches, not the whole route. Do not gate the spatial patch only on that
caller unless a later test proves it covers the desired route segment.
## Current Installed State ## Current Installed State
- Installed RED4ext plugin is disabled: - Installed RED4ext plugin is disabled:
@@ -76,12 +112,14 @@ In `red4ext/EdgeWeightGPS/src/Main.cpp`:
- `kEnableGpsQueryLifecycleHooks = true` - `kEnableGpsQueryLifecycleHooks = true`
- `kEnableGpsRouteJobLifecycleHooks = false` - `kEnableGpsRouteJobLifecycleHooks = false`
- `kEnableGpsRouteJobStartTrace = false` - `kEnableGpsRouteJobStartTrace = false`
- `kEnableGpsSpatialEdgeWeightPatch = false`
- `kEnableGpsLocalSearchHooks = false` - `kEnableGpsLocalSearchHooks = false`
- `kEnableRouteUiTraceHooks = false` - `kEnableRouteUiTraceHooks = false`
If rebuilt with the current defaults, active hooks are query/async lifecycle If rebuilt with the current defaults, active hooks are query/async lifecycle
only. The local search/cost hooks below require `kEnableGpsLocalSearchHooks = only. The spatial edge-cost patch requires `kEnableGpsSpatialEdgeWeightPatch =
true`: true`. The full local search/cost hooks below require
`kEnableGpsLocalSearchHooks = true`:
- query lifecycle: - query lifecycle:
- `GPSQuerySubmit 0x70a42c` - `GPSQuerySubmit 0x70a42c`
+21 -8
View File
@@ -66,14 +66,23 @@ Current behavior:
Active build note: Active build note:
- The currently installed build is read-only. It disables provider class - The currently installed build is disabled on disk:
multiplier overrides and enables GPS query lifecycle tracing plus local GPS `EdgeWeightGPS.dll.disabled`. There is no active `EdgeWeightGPS.dll` in the
search tracing. game plugin directory.
- Source defaults are still read-only for route behavior. They disable provider
class multiplier overrides and the spatial edge-cost patch, while keeping GPS
query lifecycle tracing available for probe builds.
- The async route-job hooks are split behind `kEnableGpsRouteJobLifecycleHooks` - The async route-job hooks are split behind `kEnableGpsRouteJobLifecycleHooks`
and are disabled in the active probe; this keeps the log focused on and are disabled in the active probe; this keeps the log focused on
`0x70a42c` submissions, `0x7094b8` result records, and local `0x70a42c` submissions, `0x7094b8` result records, and local
search/provider-cost stats. search/provider-cost stats.
- It hooks `GPSSearch` (`0x44f054`), `GPSRouteProducer` (`0x44cc7c`), - `kEnableGpsSpatialEdgeWeightPatch` is a disabled-by-default implementation
path. When enabled, it hooks `GPSRouteProducer` (`0x44cc7c`) and
`GPSEdgeCost` (`0x44f838`), samples a generated traffic-lane spatial grid
using the search-state coordinates, and applies highway/road/pavement
multipliers to returned edge costs.
- The old verbose local-search probe is still available behind
`kEnableGpsLocalSearchHooks`. It hooks `GPSSearch` (`0x44f054`),
`GPSResolveHandle` (`0x44e1a8`), `GPSEdgeCost` (`0x44f838`), and the two `GPSResolveHandle` (`0x44e1a8`), `GPSEdgeCost` (`0x44f838`), and the two
cost-provider filters `0x44ff68`/`0x450b08`. cost-provider filters `0x44ff68`/`0x450b08`.
- The filter probe records pass/fail counts by point class and by the - The filter probe records pass/fail counts by point class and by the
@@ -345,10 +354,14 @@ Current static producer lead:
`(*(routePoint + 0x13) & 0x3f)`. The GPS planner is therefore weighted, but `(*(routePoint + 0x13) & 0x3f)`. The GPS planner is therefore weighted, but
by a compact baked road-class table, not by traffic `maxSpeed` or lane by a compact baked road-class table, not by traffic `maxSpeed` or lane
connection probabilities. connection probabilities.
- The active probe now hooks `0x44f054` and `0x44f838` read-only. It logs the - The read-only local-search probe can still hook `0x44f054` and `0x44f838` to
live provider vtable, the 64 class multipliers, start/target handles, and a log the live provider vtable, the 64 class multipliers, start/target handles,
capped sample of edge-cost calls with point class IDs, masks, handles, and and a capped sample of edge-cost calls with point class IDs, masks, handles,
returned costs. and returned costs.
- The new spatial edge-cost path is implemented but disabled by default. Its
generated grid is built from traffic lane polygons/flags, not from VAND point
classes, so it can bias the search toward highway cells without rewriting
VAND metadata that later materialization code branches on.
Autodrive finding: Autodrive finding:
+27 -13
View File
@@ -836,18 +836,30 @@ renamed to `EdgeWeightGPS.dll.disabled`.
The main takeaway is still valuable, but narrower than first suspected: The main takeaway is still valuable, but narrower than first suspected:
traffic lane flags are available in native route-side endpoint/candidate code, traffic lane flags are available in native route-side endpoint/candidate code,
and `0x8d46cc` is an excellent landmark. It is not the city-wide graph-cost and `0x8d46cc` is an excellent landmark. It is not the city-wide graph-cost
function. The safer cost target is `0x44f838`, or a data patch against the function.
navigation `VAND` blobs it consumes. The next native work should avoid a full
detour of `0x8d46cc` and instead look for either:
- a `0x44f838` edge-cost hook that classifies graph edges by spatial proximity The current prototype therefore targets `0x44f838` instead. It generates a
to highway/arterial corridors compact spatial grid from traffic lane polygons/flags and samples that grid
- a navigation streamingsector patch that marks/weights selected `VAND` graph from the search-state coordinates passed to the edge-cost callback. The first
points or edges test multipliers are:
- an inline patch around the vanilla constants/branches if the selector proves
sufficient ```text
- a safer result-stage rewrite only if upstream weighting cannot be patched highway 0.62
without desynchronizing the planner and renderer road 1.00
GPSOnly 1.20
pavement 1.35
unknown 1.05
```
This deliberately leaves VAND point class bits untouched. The materialization
path branches on those bits after search, so rewriting them in data could alter
route construction or instructions as well as cost.
Runtime logs also show that long visible routes are decomposed into many local
`0x44cc7c` route-producer searches. The tempting world-map caller
`ret_rva=0x70aa22` mostly produced tiny connector searches in the resolver
logs, so the first spatial test should patch edge cost across route-producer
calls instead of gating only on that caller.
## Future Improvements ## Future Improvements
@@ -861,8 +873,10 @@ Better versions of this mod could:
polygons and highway flags polygons and highway flags
- extract the full Night City navigation streamingsector set into workspace - extract the full Night City navigation streamingsector set into workspace
storage and summarize it with `tools/analyze_vand_navigation.py` storage and summarize it with `tools/analyze_vand_navigation.py`
- implement a bounded `0x44f838` edge-cost hook or `VAND` data patch using that - tune the generated spatial grid resolution and multipliers after in-game A/B
join, rather than traffic `maxSpeed` tests
- add route-mode gating if the spatial edge-cost hook affects pedestrians,
autodrive, or other local navigation too broadly
- inspect `GPSOnly` connector lanes if a later native trace proves they are - inspect `GPSOnly` connector lanes if a later native trace proves they are
consumed by the player GPS consumed by the player GPS
- build district-specific presets if a real data-cost surface is found - build district-specific presets if a real data-cost surface is found
@@ -0,0 +1,382 @@
#pragma once
#include <array>
#include <cstdint>
#include <string_view>
namespace EdgeWeightGPS::Generated
{
constexpr float kSpatialRoadGridMinX = -4640.0f;
constexpr float kSpatialRoadGridMinY = -7392.0f;
constexpr float kSpatialRoadGridCellSize = 32.0f;
constexpr uint32_t kSpatialRoadGridWidth = 332;
constexpr uint32_t kSpatialRoadGridHeight = 361;
// Cell codes: H=highway, R=road, G=GPS-only, P=pavement, .=unknown.
// Generated by tools/generate_spatial_edge_grid.py from all.traffic_persistent and all.lane_polygons.
// Counts: H=7574 R=19617 G=20 P=996 unknown=91645.
constexpr std::array<std::string_view, kSpatialRoadGridHeight> kSpatialRoadGridRows = {{
".....HHHHHHHHHHHH...........................................................................................................................................................................................................................................................................................................................",
".....HHHHHHHHHHHHHHH........................................................................................................................................................................................................................................................................................................................",
".....HHHHHHHHHHHHHHHH...................................RRR.................................................................................................................................................................................................................................................................................",
"...........HHHHHHHHHHH..................................RRR.................................................................................................................................................................................................................................................................................",
"...............HHHHHHHH.................................RRRR................................................................................................................................................................................................................................................................................",
".................HHHHHH.................................RRRR................................................................................................................................................................................................................................................................................",
"..................HHHHHH................................RRRR................................................................................................................................................................................................................................................................................",
"...................HHHHH................................RRRR................................................................................................................................................................................................................................................................................",
"...................HHHHHH...............................RRRR................................................................................................................................................................................................................................................................................",
"....................HHHHHH..............................RRRR................................................................................................................................................................................................................................................................................",
".....................HHHHH..............................RRRR................................................................................................................................................................................................................................................................................",
".....................HHHHHH.............................RRRR................................................................................................................................................................................................................................................................................",
"......................HHHHHH...........................RRRRR................................................................................................................................................................................................................................................................................",
".......................HHHHH..........................RRRRRR................................................................................................................................................................................................................................................................................",
".......................HHHHHH....................RRRRRRRRRR.................................................................................................................................................................................................................................................................................",
"........................HHHHHH...............RRRRRRRRRRRRRR.................................................................................................................................................................................................................................................................................",
"........................HHHHHH...........RRRRRRRRRRRRRRRR...................................................................................................................................................................................................................................................................................",
".........................HHHHHH......RRRRRRRRRRRRRRRRR......................................................................................................................................................................................................................................................................................",
"..........................HHHHHH....RRRRRRRRRRRRR...........................................................................................................................................................................................................................................................................................",
"..........................HHHHHH..RRRRRRRRRRR...............................................................................................................................................................................................................................................................................................",
"...........................HHHHHHRRRRRRRRRRRR...............................................................................................................................................................................................................................................................................................",
"............................HHHHHHRRRRR...RRR...............................................................................................................................................................................................................................................................................................",
"...............RRRR.........HHHHHHRRRR......................................................................................................................................................................................................................................................................................................",
"...............RRRRRRRRR....RHHHHHHR........................................................................................................................................................................................................................................................................................................",
"...............RRRRRRRRR..RRRRHHHHHH........................................................................................................................................................................................................................................................................................................",
"...............RRRRRRRRRRRRRRRRHHHHHH.......................................................................................................................................................................................................................................................................................................",
"................RRRRRRRRRRRRRRRHHHHHHH......................................................................................................................................................................................................................................................................................................",
"...............RRRRRRRRRRRRRRR..HHHHHH......................................................................................................................................................................................................................................................................................................",
".........RRRRRRRRRRRRRRRRR.......HHHHHH.....................................................................................................................................................................................................................................................................................................",
"....RRRRRRRRRRRRRRRRRR............HHHHHH....................................................................................................................................................................................................................................................................................................",
"..RRRRRRRRRRRRRRRRR...............HHHHHHH...................................................................................................................................................................................................................................................................................................",
".RRRRRRRRRRRRRR....................HHHHHH...................................................................................................................................................................................................................................................................................................",
"RRRRRRRR............................HHHHHH..................................................................................................................................................................................................................................................................................................",
"RRRRR................................HHHHHH.................................................................................................................................................................................................................................................................................................",
"RRRR.................................HHHHHHH................................................................................................................................................................................................................................................................................................",
"RRRR..................................HHHHHHH...............................................................................................................................................................................................................................................................................................",
"RRRR...................................HHHHHHR..............................................................................................................................................................................................................................................................................................",
"RRRR....................................HHHHHHRRR...........................................................................................................................................................................................................................................................................................",
".RRR....................................RHHHHHHRR...........................................................................................................................................................................................................................................................................................",
".RRR.....................................HHHHHHHRR..........................................................................................................................................................................................................................................................................................",
".........................................RHHHHHHRRR.........................................................................................................................................................................................................................................................................................",
".........................................RRHHHHHHRRR........................................................................................................................................................................................................................................................................................",
".........................................RRRHHHHHHRR........................................................................................................................................................................................................................................................................................",
"..........................................RRHHHHHHHRR.......................................................................................................................................................................................................................................................................................",
"...........................................RRHHHHHHRR.......................................................................................................................................................................................................................................................................................",
"............................................RRHHHHHHR.......................................................................................................................................................................................................................................................................................",
"............................................RRRHHHHHR.......................................................................................................................................................................................................................................................................................",
".............................................RRHHHHHRR......................................................................................................................................................................................................................................................................................",
".............................................RRRHHHHRRR.........................................RRR.........................................................................................................................................................................................................................................",
"..............................................RRRRRRRRRR........................................RRR.........................................................................................................................................................................................................................................",
".................................................RRRRRRRR.......................................RRR.........................................................................................................................................................................................................................................",
"..................................................RRRRRRRR........................RRRRRRRRRRRRRRRRR...................RRR...................................................................................................................................................................................................................",
"...................................................RRRRRRR....................RRRRRRRRRRRRRRRRRRRRRRRR................RRR...................................................................................................................................................................................................................",
"....................................................RRRRRRR...............RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.............RRR........RRR........................................................................................................................................................................................................",
"....................................................RRRRRRRR...........RRRRRRRRRRRRRRRR......RRRRRRRRRRRRRRRR.........RRR........RRR........................................................................................................................................................................................................",
".....................................................RRRRRRR..........RRRRRRRRRRRR...............RRRRRRRRRRRRRRRR.....RRR........RRR........................................................................................................................................................................................................",
"......................................................RRRRRRR.......RRRRRRRRRRRR.....................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR........................................................................................................................................................................................................",
"......................................................RRRRRRRR......RRRRRRR.RRRR........................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRR......................................................................................................................................................................................................",
"......................................................RRRRRRRR.....RRRRRRRRRRRRR.........................RRR.RRRRRRRRRRRRRRRRRRRRRRRRR......................................................................................................................................................................................................",
"......................................................RRRRRRRRR...RRRRRRRRRRRRRR.........................RRR...................RRRRRRR......................................................................................................................................................................................................",
"........................................................RRRHHHHH.RRRRRRRRRRRRRR...................................................RRRR......................................................................................................................................................................................................",
"........................................................RRRHHHHHHRRRRR..RRRRRRR............................................RRR.....RRRR.....................................................................................................................................................................................................",
".....................................................RRRRRRHHHHHHRRRRR.RRRRRRR.............................................RRR.....RRRR.....................................................................................................................................................................................................",
".....................................................RRRRRRRHHHHHHRRR.RRRRRRRRRR...........................................RRR.....RRRR.....................................................................................................................................................................................................",
".....................................................RRRRRRRRHHHHHH...RRRRRRRRRRRRRRRRRRRRRRRRRRRRPPPP.....................RRR.....RRRR.....................................................................................................................................................................................................",
".....................................................RRRRR...HHHHHHH.RRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR..RRR......RRRR....................................................................................................................................................................................................",
".....................................................RRRRR....HHHHHHRRRRR...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR...............................................................................................................................................................................................",
"....................................................RRRRRRR....HHHHHHRRRR...RRRRRRRR....RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR............................................................................................................................................................................................",
"...................................................RRRRRRRRR....HHHHHHRR.....RRRRRRR......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR............................................................................................................................................................................................",
"..................................................RRRRRRRRRRR...HHHHHHH.......RRRRRR.............RRRRRRRRRRRRRRRRRRRR......RRR....RRRRRRRRRRRRRR............................................................................................................................................................................................",
"................................................RRRRRRRRRRRRRR...HHHHHHH.......RRRRR............RRRRRRRRRRRRRRRRRRRRRRR....RRR....RRRRRRR...................................................................................................................................................................................................",
"...............................................RRRRRRR...RRRRR....HHHHHH........RRRRR.........RRRRRRRRRRRR....RRRRRRRRRRR..RRR....RRRRRRR...................................................................................................................................................................................................",
"..............................................RRRRRRR..RRRRRRRR....HHHHHH.......RRRRRR.......RRRRRRRRRRRR........RRRRRRRRRRRRRRRRRRRRRRRRR..................................................................................................................................................................................................",
"............................................RRRRRRRR..RRRRRRRRRR...RHHHHHH.......RRRRRR....RRRRRRRRRRR..............RRRRRRRRRRRRRRRRRRRRRRR.................................................................................................................................................................................................",
"...........................................RRRRRRR...RRRRRRRRRRRR.RRHHHHHHH.......RRRRRR..RRRRRRRRRRRR................RRRRRRRRRRRRRRRRRRRRR.................................................................................................................................................................................................",
"..........................................RRRRRRRRRRRRRRRRR.RRRRRRRRRHHHHHH........RRRRR.RRRRRRRR.RRR......................RRRRRRRR...RRRRRR................................................................................................................................................................................................",
".......................................RRRRRRRRRRRRRRRRRRR..RRRRRRRRRRHHHHHHRRRR...RRRRRRRRRRRR............................RRRRRRRRR.RRRRRRRR...............................................................................................................................................................................................",
".......................................RRRRRRRRRRRRRRRRR.....RRRRRRRRR.HHHHHHRRRR...RRRRRRRRRR................................RRRRRRRRRRRRRRRRRRRR..........................................................................................................................................................................................",
".......................................RRRRRR...RRRRRRR.....RRRRRRRR....HHHHHHRRR....RRRRRRRR...................................RRRRRRRRRRRRRRRRRRR.........................................................................................................................................................................................",
".......................................RRRRR..RRRRRRRR......RRRRRRR.....HHHHHHHRRR..RRRRRRRR.....................................RRRRRRR.RRRRRRRRRRRRRR.....................................................................................................................................................................................",
".......................................RRRRRRRRRRRRRRRRRR.RRRRRRRR.......HHHHHHRRRRRRRRRRRRR......................................RRRRR...RRRRRRRRRRRRR.....................................................................................................................................................................................",
"........................................RRRRRRRRRRRRRRRRRRRRRRRRR.........HHHHHHRRRRRRRRRRRRR....................................RRRRR.....RRRRRRRRRRRR.....................................................................................................................................................................................",
".........................................RRRRRRRRR.RRRRRRRRRRRR............HHHHHHRRRRRR.RRRRRR.................................RRRRRR......RRRRRRRRRRR......................................................................................................................................................................................",
".........................................RRRRRRR...RRRRRRRRRRR.............HHHHHHHRRRR...RRRRRR..............................RRRRRRRR.......RRRR.RRRR.......................................................................................................................................................................................",
"........................................RRRRRRRR...RRRRRRRRRR...............HHHHHHHRR.....RRRRR............................RRRRRRRRRRR......RRRR............................................................................................................................................................................................",
"......................................RRRRRRRRRRR..RRRRRRRR..................HHHHHH.......RRRRRR..................RRRRRRRRRRRRRRRRRRRR.......RRR............................................................................................................................................................................................",
".....................................RRRRRRRRRRRR..RRRRRRR....................HHHHHH.......RRRRRR..........RRRRRRRRRRRRRRRRRRRRR..RRRRR......RRR............................................................................................................................................................................................",
".....................................RRRRRR.RRRRRRRRRRRRR.....................HHHHHHH.......RRRRRR.......RRRRRRRRRRRRRRRRRRRRR....RRRRR......RRR............................................................................................................................................................................................",
".....................................RRRRR...RRRRRRRRRRR.......................HHHHHHH.......RRRRRR......RRRRRRRRRRRR.....RRRRR....RRRR......RRR............................................................................................................................................................................................",
".....................................RRRR.....RRRRRRRR.........................RHHHHHH........RRRRR..RRRRRRRRR..RRRR.......RRRR..............RRR............................................................................................................................................................................................",
".............................................RRRRRRRR.........................RRRHHHHHH.......RRRRRRRRRRRRRRR..............RRRRR............RRRR............................................................................................................................................................................................",
"........................................RRR.RRRRRRRRR........................RRRRRHHHHHH.......RRRRRRRRRRRRR................RRRR...........RRRRR............................................................................................................................................................................................",
"........................................RRRRRRRRRRRRRR......................RRRRRRHHHHHHH.......RRRRRRRRRRRR................RRRRR..........RRRRR............................................................................................................................................................................................",
"........................................RRRRRRRRRRRRRRR.......RRR.........RRRRRRRR.HHHHHHR.......RRRRR.......................RRRRRRR.......RRRRR............................................................................................................................................................................................",
"........................................RRRRRRRR..RRRRRR......RRRR.......RRRRRRR....HHHHHRP......RRRRRR......................RRRRRRRR......RRRRR............................................................................................................................................................................................",
".......................................RRRRRRR.....RRRRR......RRRRR.....RRRRRRR......HHHHRR.......RRRRRR......................RRRRRRRR......RRRR............................................................................................................................................................................................",
".................................RRRR.RRRRRRR......RRRRRR.....RRRRR...RRRRRRRR........RRRRRR.......RRRRRR..................RRRRRRRRRRRR......RRR............................................................................................................................................................................................",
".................................RRRRRRRRRRR........RRRRRR....RRRRRRRRRRRRRRR.........RRRHHHH.......RRRRRR................RRRRRRRRRRRRR......RRR............................................................................................................................................................................................",
".................................RRRRRRRRRR..........RRRRRR....RRRRRRRRRRRR...........RRRHHHHH......RRRRRR..............RRRRRRRRRRRRRRR....RRRRRRR..........................................................................................................................................................................................",
".................................RRRRRRRR.............RRRRRR....RRRRRRRRRR.............RRHHHHH.RRRRRRRRRRRR............RRRRRRRR.....RRRRRRRRRRRRRRRR........................................................................................................................................................................................",
".................................RRRRRRR...............RRRRR.....RRRRRRRR................HHHHHHRRRRRRRRRRRRR...........RRRRRR.......RRRRRRRRRRRRRRRRR.......................................................................................................................................................................................",
"...........................RRRRRRRRRRRRRR..............RRRRRR...RRRRRRR...................HHHHHHRRRRRRRRRRRRR..........RRRR......RRRRRRRRRRRRRRRRRRRRR......................................................................................................................................................................................",
"...........................RRRRRRRRRRRRRR...............RRRRRR.RRRRRRR....................HHHHHHHRRR....RRRRR..........RRRR...RRRRRRRRRRRRR....RRRRRRR......................................................................................................................................................................................",
"...........................RRRRRRRRRRRRRRRG......RRR.....RRRRRRRRRRRR......................HHHHHH.......RRRRRR.........RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR......................................................................................................................................................................................",
"............................RRRRRRRRRRRRRRG......RRRR.....RRRRRRRRRR........................HHHHHH.......RRRRRR.........RRRRRRRRRRRRR..RRRRRRRRRRRRRRR......................................................................................................................................................................................",
"............................RRRRRR.RRRRRRRG......RRRRR....RRRRRRRR...........................HHHHHH.......RRRRRR......RRRRRRRRRRRR.....RRRRRRRRRRR.RRR......................................................................................................................................................................................",
"............................GRRRRR.....GGGG......RRRRRR...RRRRRRR............................HHHHHHH.......RRRRRR..RRRRRRRRRRRR........RRRRRRRRRR..RRR.................RRR..................................................................................................................................................................",
"..............................RRRRR...............RRRRRRRRRRRRRR..............................HHHHHHH.......RRRRRRRRRRRRRRRRR..........RRRR..RRRR..RRR.................RRR..................................................................................................................................................................",
"..............................RRRRRR...............RRRRRRRRRRR.................................HHHHHH.......RRRRRRRRRRRRRRRRR..........RRR....RRRR.RRR.................RRR..................................................................................................................................................................",
"...............................RRRRRR..............RRRRRRRRRR...................................HHHHHH......RRRRRRRRRRR..RRRRRR........RRR....RRRR.RRR.................RRR..................................................................................................................................................................",
"................................RRRRRR..............RRRRRRRR.....................................HHHHHH.RRRRRRRRRRRR......RRRRR........RRRRRRRRRRRRRRR.................RRRR.................................................................................................................................................................",
".................................RRRRR.............RRRRRRRR......................................HHHHHHRRRRRRRRRRRRR......RRRRR........RRRRRRRRRRRRRRR.................RRRR.................................................................................................................................................................",
".................................RRRRRR...........RRRRRRRR........................................HHHHHHHRRRRRRRRRRRR......RRRR.......RRRRRRRRRRRRRRRR.................RRRR.................................................................................................................................................................",
"..................................RRRRRR.........RRRRRRRRR.........................................HHHHHHRRRRR..RRRRRR................RRRR.....RRRRRRR..................RRR.................................................................................................................................................................",
"...................................RRRRRR........RRRRRR.............................................RHHHHHRR.....RRRRRR...............RRRR....RRRRRRRR..................RRRR................................................................................................................................................................",
"....................................RRRRR........RRRR...............................................RHHHHHH.......RRRRRR..............RRRRRRRRRRRRRRRR.....RRRRR........RRRR...RRR..........................................................................................................................................................",
".....................................RRRRR.........................................................RRHHHHHHR.......RRRRRRRR...........RRRRRRRRRRRRRRR....RRRRRRRRR......RRRR.RRRRR..........................................................................................................................................................",
".....................................RRRRRR........................................................RRRHHHHHH.......RRRRRRRR...........RRRRRRRRRRR.RRR...RRRRRRRRRRRR....RRRRRRRRRR..........................................................................................................................................................",
"......................................RRRRRR.......................................................RRRRHHHHHH.......RRRRRRR...........RRR.RRRRRR.RRRRRRRRRRRRRRRRRRR.....RRRRRRRRR..........................................................................................................................................................",
".......................................RRRRRR...........................................................HHHHHH.......RRRRRR...........RRR...RRRRRRRRRRRRRRRR...RRRRRR....RRRRRRRRRR.........................................................................................................................................................",
"........................................RRRRR...........................................................HHHHHHH.......RRRRR...........RRR....RRRRRRRRRRRRRR......RRRRR...RRRRRRRRRRRR.......................................................................................................................................................",
"......................................RRRRRRRR...........................................................HHHHHH.......RRRRRR.........RRRR....RRRRRRRR............RRRRR...RRRRRRRRRRRR.......................................................................................................................................................",
".....................................RRRRRRRRRR..........................................................RHHHHHH.......RRRRRR........RRRRRRRRRRRRRRRR.............RRRRR...RRRRRRRRRRR.......................................................................................................................................................",
"....................................RRRRRRRRRRRR.........................................................RRHHHHHH.......RRRRRR.......RRRRRRRRRRRRRRRR..............RRRR...RRRRRRR.RRR.......................................................................................................................................................",
"...................................RRRRRRR.RRRRR.........................................................RRHHHHHH........RRRRRR......RRRRRRRRRRRRRRRRR.............RRRRR.RRRRR..............................................................................................................................................................",
".................................RRRRRRRR...RRRRR...........................................................HHHHHR........RRRRR......RRRR..RRRRRRRRRRRR.............RRRRRRRRRR..............................................................................................................................................................",
"................................RRRRRRR.....RRRRRR..........................................................HHHHHH........RRRRRR.....RRR.....RRRRRRRRRRRR...........RRRRRRRRR...............................................................................................................................................................",
"...............................RRRRRRR.......RRRRRR........................................................HHHHHHH.........RRRRRRR...RRRR...RRRRRRRRRRRRRRR..........RRRRRRRR...............................................................................................................................................................",
".............................RRRRRRRR.........RRRRRR.........................HHHH.........................HHHHHHHHH.........RRRRRR...RRRRRRRRRRRRRRRRRRRRRR...........RRRRRR................................................................................................................................................................",
"............................RRRRRRR............RRRRR.......................HHHHHHHH.....................HHHHHHHHHHH..........RRRRRR.RRRRRRRRRRRRRRRR..RRRRR............RRRRR................................................................................................................................................................",
"............................RRRRRR.............RRRRRR.....................HHHHHHHHHH...................HHHHHHHHHHHHH..........RRRRR.RRRRRRRRRRR.RRRR...................RRRR......RRR........................................................................................................................................................",
"............................RRRRR...............RRRRRR..................PRHHHHHHHHHHH...............HHHHHHHHHHHHHHHH..........RRRRRRRRRR..RRRRR.RRR....................RRRR......RRR........................................................................................................................................................",
".................................................RRRRRR.................RRHHHHHHHHHHHHH...........HHHHHHHHHHHHHHHHHHH..........RRRRRRRRR...RRRR.RRR....................RRRR......RRR........................................................................................................................................................",
"..................................................RRRRR..............RRRRRHHHHRPHHHHHHHH......HHHHHHHHHHHHHHH.HHHHHHH...........RRRRRRRR...RRRRRRRR...................RRRR.......RRR........................................................................................................................................................",
"..................................................RRRRRR.............RRRRRRRRRRR.HHHHHHHHHHHHHHHHHHHHHHHHH.....HHHHHHH...........RRRRRRR....RRRRRRR...................RRRRRRR...............................................................................................................................................................",
"...................................................RRRRRR............RRRRRRRRRRR.PHHHHHHHHHHHHHHHHHHHHH.........HHHHHH...........RRRRRR.....RRRRRRR..................RRRRRRRRR..............................................................................................................................................................",
"....................................................RRRRRR...........PRRRRRRRRRRRRRRHHHHHHHHHHHHHHHH.............HHHHHH...........RRRRR...RRRRRRRRR................RRRRRRRRRRRRP............................................................................................................................................................",
".....................................................RRRRR...........RRRRRRRRRRRRRRRPHHHHHHHHHHHH................HHHHHH............RRRR...RRRRRRRRR................RRRRRRRRRRRRRP...........................................................................................................................................................",
"......................................................RRRRR.........RRRRRRRRRRRRRRRRRPP...........................HHHHHH...........RRRR...RRRRRRRRR...............RRRRRR..PRRRRRRRRPPP......................................................................................................................................................",
"......................................................RRRRR.....PPPRRRRRRPRRRRRRRRRRRRRRRR.........................HHHHHRRRRRRR....RRRR...RRRR.RRR................RRRRR....PRRRRRRRRRRRRRRRP................................................................................................................................................",
".......................................................RRRR.....PPRRRRRRRPRRRRRRRRRRRRRRRR.............RRR.........HHHHHHRRRRRRRRRRRRRR.RRRRRR.RRR...............RRRRR.......RRRRRRRRRRRRRRRR...............................................................................................................................................",
"......................................................RRRRR....PPRRRRRRRPPRRRRRRRRRRRRRRRR.............RRRRRR.....RRHHHHHHRRRRRRRRRRRRR.RRRRRR.RRR...............RRRR.........PRRRRRRRRRRRRRRRP.............................................................................................................................................",
".....................................................RRRRRR...PPRRRRRRRPPPPPPRRRRRRRRRRRRRRRPPPP.......RRRRRRR....RRRHHHHHRRRRRRRRRRRRR.RRRRRR.RRRRRRRRRRR.......RRRR.................PRRRRRRRRR............................................................................................................................................",
".....................................................RRRRRR...PRRRRRRRPPPPPPPPPRRRRRRRRRRRRRRPPP.......RRRRRRRR..RRRRHHHHHH.....RRRRRR..RRRRRRRRRRRRRRRRRR......PRRRR....................PRRRRRRRP..........................................................................................................................................",
"....................................................RRRRRR....RRRRRRRPPPPPPPPRRRRRRRRRRRRRRRRPPP........RRRRRRR..RRRRRHHHHHH.......RRR..RRRRRRRRRRRRRRRRRR......RRRR.......................RRRRRRRR.........................................................................................................................................",
"....................................................RRRRRRRRRRRRRRRRPPPPPPPPPRRRRRRRRRRRRRRRRRPP...........RRRR..RRRR.HHHHHH.......RRR..RRRRRRRRRR..RRRRRR.....RRRRR.......................RRRRRRRRR........................................................................................................................................",
"....................................................RRRRRRRRRRRRRRRRPPPPPPPPPRRRRRRRRRRRRRRRRRR....PPP.....RRRRR.RRRR..HHHHHH......RRRRRRRRRRRRRRR............RRRRRR.........................PRRRRRR........................................................................................................................................",
"....................................................RRRRRRRRRRRRRRRRRRRRRRRRRPRRRRRRRRRRRRRRRRRR.PPPPP......RRRRRRRRR...HHHHHH.....RRRRRRRRRRRRRRRRRR......RRRRRRRRP...........................RRRRR........................................................................................................................................",
"......................................................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRPPPPP......RRRRRRRRR...HHHHHHH....RRRRRRRRRRRRRRRRRRR.....RRRRRRRP.............................PRRR........................................................................................................................................",
".....................................................PPPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRPPPP.......RRRRRRRRR...HHHHHH....RRRRRRRRRRRRRRRRRRRRPPPRRRRRRRP..........................................................................................................................................................................",
".....................................................PPPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRP.PPPP....RRRRRRRRR...HHHHHHH...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRR...........................................................................................................................................................................",
".....................................................PPPRRRRRRRRRRRRRRRPRRRRRRRRRRRRRRRRRRRRRRRRRRRR.PPPP...RRRRRRRRRRR..HHHHHHHH..RRRRRRRRRRRRR...RRRRRRRRRRRRR............................................................................................................................................................................",
".....................................................PPPRRRRRRRRRRRRRRRRRPPPPRRRRRRRRRRRRRRRRRRRRRRRRPPPP..RRRRRR.RRRRR...HHHHHHHH.RRRRR.....RRR...RRRRRRRRRRRRP............................................................................................................................................................................",
".....................................................PPPRRRRRRRRRRRRRRRRRRRRP.RRRRRRRRRRRRRRRRRRRRRRRRPPP.RRRRRR...RRRRRRRRHHHHHHHHRRRRRRRRRRRRR...PRRRRRRRRRRR.............................................................................................................................................................................",
".....................................................PPPRRRRRPRRRRRRRRRRRRRRPPRRRRRRRRRRRRRRRRRRRRRRRRRPP.RRRRR....RRRRRRRRHHHHHHHHHRRRRRRRRRRRR....HHHRRRRRRRP.............................................................................RRRR............................................................................................",
".....................................................PPPRRRRRPRRRRRRRRRRRRRRRPRRRRRRRRRRRRRRRRRRRRRRRRRPPRRRRR......RRRRRRRRHHHHHHHHHHHHHHRRRRRR....HHHHRRRRRRRRPP..........................................................................RRRR............................................................................................",
"......................................................PRRRRRPPRRRRRRRRRRRRRRRRPRRRRRRRRRRRRRRRRRRRRRRRRP.RRRR........RRRRRRR.HHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRR.....................................................................RRRRR...........................................................................................",
"......................................................PRRRRRPPPRRRRRRRRRRRRRRRRRRRRRRPPRRRRRRRRRRRRRRRRP.RRRR........RRRRRR..HHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRR.....................................................................RRRRR..........................................................................................",
"......................................................RRRRRPPPPPPPPPRRRRRRRRRRRRRRRRPPPRRRRRRRRRRRRRRRR...............RRRRR...HHHHHHHHHHHHHHHHHHHHHHHHHHHHR.RRRRRRRRRRRRR....................................................................RRRRR..........................................................................................",
"......................................................RRRRR....PPPPPRRRRR.RRRRRRRRR.PPPRRRRRRRRRRRRRPP.................RRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHH....RRRPRRRRRRR....................................................................RRRR..........................................................................................",
"......................................................RRRRR.........RRRRRPPRRRRRRR..PPPRRRRRRRRRRRRR...................RRRRRHHHHHHHHHHHHHHHHHRRRRRHHHHHHHHHHHHRRRRRRRRRRRRP...................................................................RRRRR.........................................................................................",
"......................................................RRRR...........RRRRRRRRRRRRRRPRRRRRRRRRRRRRRRR....................RRRHHHHHHHHHHHHHH.PPRRRRRRRRHHHHHHHHHHHHRRRRRRRRRRR..................................................RRR...............RRRRR........................................................................................",
"......................................................RRRR...........RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRP..................RRHHHHHHHHHHHHHHH.PRRRRRRRRRHHHHHHHHHHHHRRRRRRRRRRRR...............................................RRRRR...............RRRRR..................................RRRRRRRRRR............................................",
"......................................................RRRR...........PRRRRRRRRRRRRRRRRRRPPPRRRRRRRRRRPPP...............RRHHHHHHHHHHHHHHHHHRRRRRRRRRRHHHHHHHHHHHHRRRRRR.RRRRR..............................................RRRRRR................RRRRRRRRRRR..........................RRRRRRRRRRRR...........................................",
"......................................................RRRRR..........PPRRRRRRRRRRRRRRRRRRRPPRRRRRRRRRPPP.............RRRHHHHHHHHHHHHHHHHHHRRRRRRRRRRHHHRRHHHHHHHHRRRRR.RRRRR..............................................RRRRRR................RRRRRRRRRRRRR.....RRRRRR............RRRRRRRRRRRRRRR.........................................",
"......................................................RRRRR.........PPP.PRRRRRRRRRRRRRRRRRPPPPRRRRRRRPPP.............RRHHHHHHHHHHRRHHHHHHHRRRRRRRRRRRRRRRRRHHHHHHHRRRR..RRRRRRR...........................................RRRRRRR................RRRRRRRRRRRR...RRRRRRRRR...........RRRRR...RRRRRRRR........................................",
"......................................................RRRRR.........PPP.PPRRRRRRRRRRRRRRRRRR.....RRRPPPP.............HHHHHHHHHHHRRRRHHHHHHHRRRRRRRRRRRRRRRRRHHHHHHHRRRRRRRRRRRR...........................................RRRRRRRRR.............RRRRRR..RRRRRRRRRRRRRRRRR..........RRRRR......RRRRRRR.......................................",
"......................................................PRRRRP........PPPPPPRRRRRR...RRRRRRRRRRPP..RRRPPP.............HHHHHHHHHHHRRRRRRHHHHHHHRRRRRRRRRRRRRRRRRHHHHHHRRRRRRRRRRRR............................................RRRRRRRRR.......RRRRRRRRRR....RRRRRRRRRRRRRRRR.........RRRRR........RRRRRR.......................................",
".......................................................RRRRR.........PPPPPRRRRRP.RHHHHRRRRRRHHHPPRRRPPPP...........HHHHHHHHHRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHRRRRRRRRHHHH................RRR..........................RRRRRRR.....RRRRRRRRRRRR.....RRRRRRRRRR.............RRRRRR..........RRRR.......................................",
".......................................................RRRRR.........PPPPPRRRRRRRHHHHHRRRRRRHHHRRP.PPPPP.........HHHHHHHHHHRRRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHRRRRRRRHHHH...............RRRR.............................RRRRRR.RRRRRRRRRRRR.......RRRRRRRRR..............RRRRR...........RRRR.......................................",
".......................................................PRRRRP........PPPPPRRRRRRRHHHHHRRRRRHHHHRRP.PPPPP........HHHHHHHHHRRRRRRRRRRRRRRRHHHHHRRRRRRRRRRRRRRRRRRRHHHHHRRRRRRRHHHH...............RRRR.............................RRRRRRRRRRRRRRRR.........RRRR.RRRRRR............RRRRR.............RRRR......................................",
"........................................................RRRRR.........PPPPPRRRRRRHHHHRRRRRHHHHHRRR.PPPPP.......HHHHHHHHHHHRRRRRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHRRRRRRRHHHHH..............RRRR..............................RRRRRRRRRRRRRRRRR.......RRRR...RRRR...........RRRRRR.............RRRR......................................",
"........................................................RRRRR..........PPPPPPPPPRHHHHHRRRRHHHHHRRR...PPP......HHHHHHHHHHHHHHRHHHRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHRRRRR..HHHHH..............RRR................................RRRRRRRRRRRRRRRR.......RRRR...RRRR...........RRRRR..............RRRR......................................",
"........................................................PRRRRP...............PPPPRHHHHRRRRHHHHHRRR..........RHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRHHHHHRRRHHHRRRRRRRRRRRRRRRRRRRRR..HHHH..............RRR...............RRRRR............RRRRRRR.RRRRRRRR.......RRRR...RRRR..........RRRRR...............RRRR......................................",
".........................................................RRRRR...............PPPPPHHHHHRRRHHHRRRRRRRRR....RRRHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRHHHHHRRHHHHRRRRRRRRRRRRRRRRRRRRR..HHHHH.............RRR...............RRRRR...........RRRRRR..RRRRRRRRR.......RRRR...RRRR..........RRRRR..RRRR.........RRRR......................................",
".........................................................RRRRR...............PPPPPHHHHHRRRRRRRRRRRRRRRR..RRRHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRHHHHHHRHHHHHRRRRRRRRRRRRRRRRRRRRP.HHHHH.............RRR...............RRRRR..........RRRRRR..RRRRRRRRR.......RRRR.....RRRR........RRRRRRRRRRRRRRR......RRRR......................................",
".........................................................PRRRRP.................PPPHHHHRRRRRPRRRRRRRRRR..RRHHHHHHHHRRRRHHHHHHHHHHRRRRRRRRRRRHHHHHHHHHHHHRRRRRRRRRRRRRRRRRRRR.HHHHH.........RRRRRRR...............RRRRR........RRRRRRR..RRRRRRRRRR.......RRRR.....RRRRR......RRRRRRRRRRRRRRRRRRRRRRRRRR..RRR.................................",
"..........................................................RRRRR..................PPHHHHHR....RRRRRRRRRRRRRRHHHHHHHRRRRHHHHHHHHHRRPRRRRRRRRRRRHHHHHRHHHHHRRRRRRRRRRRRRRRRRRRR.HHHHHH.......RRRRRRRR................RRRR......RRRRRRRR..RRRRRRRRRR........RRRR.....RRRRRR...RRRRRRRRRRRRRRRRRRRRRRRRRRRR..RRR.................................",
"..........................................................RRRRR...................PPHHHHR....HHHHHHHRRHHHRHHHHHHHRRRRRHHHHHHHHHHRP.RRRRRRRRRRHHHHHHRHHHHRRRRRRRRRPRRRRRRRRRR.HHHHHH.......RRRRRRRR...............RRRRR...RRRRRRRRRRRRRRRRRRR...........RRRRR.....RRRRRRRRRRRRRRRRRRR....RRRRRRRRRRRRRRR.RRRR................................",
"..........................................................PRRRRR..................PPHHHHHRHHHHHHHHHHHHHHHHHHHHHHRRRRHHHHHHHHHHHHH...RRRRRRRPRRHHHHHHHHHHRRRRRRRRPPRRRRRRRRR..HHHHHH.......RRRRRRRR...............RRRRR.RRRRRRRRRRRRRRRRRRRR............RRRRR......RRRRRRRRRRRRR...............RRRRRRRRRRRRRR................................",
"...........................................................RRRRR.................PPPPHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRHHHHHHHHHHHHHH..RRRRRRRRPRHHHHHHHRRRRRRRRRRRRRRRRRRRRRRPPHHHHHH.......RRRRRRRR...............RRRRRRRRRRRRRRRRRRRRRRRRRRR.........RRRRRRRR......RRRRRRRRRRR...................RRRRRRRRRRRRRRRRRR.........................",
"...........................................................RRRRRP..............PPPPPHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRHHHHHHHPHHHHHHHHRRRRRRRRRPPRHHHHHHHRRRRRRRRRRRRRRRRPPPPPPP.HHHHH.......RRRRRRR...............RRRRRRRRRRRRR....RRRRRRRRRRR......RRRRRRRRRRRRR..RRRRRRRRRRR....................RRRRRRRRRRRRRRRRRRR.........................",
"...........................................................PRRRRR............PPPPPPHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRHHHHHHP.HHHHHHHHRRRRRRRRRRPRRHHHHHHHRRRRRRRRRRRRRRRPPPPPPP.HHHHH.......RRRRRRR...........RRRRRRRRRRRRRRR......RRRRRR.RRRR.....RRRRRRRRRRRRRRRRRRRRRRRRRRR....................RRRRRRRRRRRRRRRRRRR.........................",
"............................................................RRRRR............PPPPPHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRHHHHHR...HHHHHHHHRRRRRRRRRRRRRHHHHHHHRRRRRRRRRRRRRRPPPPPPPHHHHHH.......RRRRRRR........RRRRRRRRRRRRRRR........RRRRRRR.......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRR....................RRRR..RRRRRRRRRR............................",
"............................................................PRRRRR...........PPPPHHHHHHHHHHHHH.HHHHHHHHHHHHHHRRRRRHHHHHRRR..PHHHHHHHHRRRRRRRRRRRRHHHHHHHHRRRRRRRRRRRRRPPPPPPHHHHHHH....RRRRRRRRRR.....RRRRRRRRRRRRRRR..........RRRRRRRR......RRRRRRRRRRRRR.RRRRRRRRRRRRRRRRRR..................RRRRRR..RRRRRRRRR............................",
".............................................................RRRRR...........PPP.HHHHHHHHHHH...HHHHHPPPHHHHHHHRRRRHHHHHRRRPRRHHHHHHHHRRRRRRRRRRRRRHHHHHHHRRRRRRRRRRRRRPPPPHHHHHHHHHH...RRRRRRRRRR..RRRRRRRRRRRRRRRRRR..........RRRRRRR......RRRRRRRRR.RRRR.RRRRRRRR.....RRRRR..................RRRRRR..RRRRRRRRR............................",
".............................................................RRRRRR.............HHHHHHHPHHHHHRRHHHHHRRRRRHHHHHHRRRHHHHHRRRRHHHHHHHHHHHRRRRRRRRRR.RRHHHHHHHRRRRRRRRRRRRPPPHHHHHHHHHHH...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR........RRRRRR.......RRRRRRR.....RRRRRRRRRR........RRRRR.................RRRRRR......RRRR.............................",
".............................................................PRRRRR..........RRRHHHHHHRRRHHHHRRHHHHHRRRRRHHHHHHRRHHHHHHRRRRHHHHHHHHHHH.RRRRRRRRRRRHHHHHHHHHHHHHRRRRRRRRHHHHHHHHHHHHH..RRRR..RRRRRRRRRRRRRRRR..RRRRRRRR......RRRRRRR.......RRRRRR.......RRRRRRRR..........RRRRRR................RRRR..RRRR..RRRR.............................",
"..............................................................RRRRRR.....PPPRRRRHHHHHRRRRHHHHRRHHHHHRRRRRRHHHHHHHHHHHHHHRRRHHHH.HHHHHHHRRRR.RRRRRRHHHHHHHHHHHHHRRRRRRRHHHHHHHHHHHHHH.RRRRR..RRRRRRRRRRRR.RRR...RRRRRRRR...RRRRRRRR.......RRRRRR........RRRRRRR............RRRRRRRRRRRRR........RRRR.RRRRR..RRRRR............................",
"..............................................................PRRRRRR....PPPRRRRHHHHHRRRRRRRRPPRHHHHRRRRRRRPPRHHHHHHHHHHRRRHHHH.HHHHHHHHRRR.PRRRRRHHHHHHHHHHHHHRRRRRHHHHHHHHHHHHHHHHHRRRRR.RRRRRRRRRRRRRRRRRR...RRRRRRRRRRRRRRRRRR......RRRRRR.........RRRRRR..............RRRRRRRRRRRRRR.....RRRRRRRRRRR...RRRR............................",
"...............................................................RRRRRRP...PPPRRRRHHHHHRRRRHHHHHHHHHHHRRRRRRRR.RHHHHHHHHHHRRRHHHH..HHHHHHHRR...RRRRRRRHHHHHHHHHHHRRRRHHHHHHHHHHP.HHHHHHRRRR..RRRRR...RRRRRRRRRR...RRRRRRRRRRRRRRRRR.....RRRRRRR..........RRRRRR...............RRRRRRRRRRRRRRR...RRRRRRRRRRR...RRRR............................",
"................................................................RRRRRR..PPPRRRRRHHHHHRHHHHHHHHHHHHHHRRRRRRRR.PHHHHHHHHHHRRRHHHHRRRHHHHHHH.....RRRRRRRRHHHHHHHHRRRRRHHHHHHHHPPPPHHHHHHRRR...RRRR......RRRRRRRR...RRRRRRRRRRRRRRRRR....RRRRRRR...........RRRRR................RRRRRRRRRRRRRRRR..RRRRRRRRRR.....RRR............................",
"................................................................PRRRRRR.RRRRRRRRHHHHHRHHHHHHHHHHHHHHRRRRRRRR.PHHHHHHHHHRRRRHHHHRRRHHHHHHHH....PRRRRRHHHHHHHHHRRRRRRHHHHHHRRRPPP.HHHHHHRR...RRRR.......RRRRRRR...RRRRRRRRRR.RRRRR...RRRRRRRR.............RRRRR............RRRRRRRRRR..RRRRRRRR.RRRRRRRRR......RRR............................",
".................................................................RRRRRRRRRRRRRRHHHHHHRHHHHHHHHHHHHHHRRRRHHHRRPPHHHHHHHHRRRRHHHHRRRRHHHHHHHH...HHHRRHHHHHHHHHHHRRRRRHHHHRRRRRRPPPHHHHHHRR...RRR.........RRRRRR..RRRRR.......RRRRR..RRRRRRRR..............RRRRRRRRRR.....RRRRRRRRRRRRR....RRRRRRRRRRR..........RRR............................",
"..................................................................RRRRRRRRRRRRRHHHHHHRHHHHHRRPPPHHHHRRRHHHHHRRPHHHHHRRRRRRRHHHHRRRRRHHHHHHHH.HHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRPPPHHHHHHR...RRRR.........RRRRRRRRRRRR.......RRRRR..RRRRRRRR...............RRRRRRRRRRRRRRRRRRRRRRRRRRRRR....RRRRRRRRR..RRRRR.RRRRRR..................RRRRRRRRRR",
"...................................................................RRRRRRRRRRRRHHHHHHRRRRPRRRPPPHHHHRRRHHHHHRRRHHHHHRRRRRRHHHHHRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRPPHHHHHHR...RRRR..........RRRRRRRRRRR.......RRRRR.RRRRRRRR................RRRRRRRRRRRRRRRRRRRRR...RRRRR.....RRRRRRRRRRRRRRRRRRRRRRR.......RRRRRRRRRRRRRRRRRRRR",
"...................................................................PRRRRRRRPRRRHHHHHHHRRRRRRRPPPHHHHRRRHHHHHRRRHHHHRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRHHHHRRRRRRRRRRRRRRRRPRRHHHHH....RRRR...........RRRRRRRRR.......RRRRR..RRRRRRRRRRR.............RRRRRRRRRRRRRRRRRRR......RRRRR......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR",
"....................................................................RRRRRRPPRRRRHHHHHHHRRRRRRPPPHHHHRRRHHHHRRRHHHHHRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRHHHHRRRRRRRRRRRRRRRRRRRHHHHH....RRRR...........RRRRRRR.......RRRRRRR.RRRRRRRRRRRRR............RRRRRRR....RRRRRRRR......RRRRR.......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR",
"....................................................................RRRRRRRPRRRRHHHHHHHHRRRRRRRRHHHHRRRRRRRRRRHHHHHRRRHHHHHHHHHHHHHHHHRHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRRHHHRRRRRRRRRHHHHR...RRRR...........RRRRRR........RRRRRR..RRRRR.RRRRRRRR...........RRRR...........RRRR.......RRRR....RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR...........",
"..................................................................PPRRRRRRRRRRRPHHHHHHHHRRRRRRRRRHHHRRRRRRRRRRHHHHHPRHHHHHHHHRRRRHHHHHRRHHHHHHHHHHHPRRRRRRRRRHHHHRRRRHHHHHRRRRRRRRHHHHH...RRR............RRR...........RRRRRR.RRRRR.....RRRRRR...........RRRR..RRRRRRR.RRRR.......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.....................",
"..................................................................PPRRRRRRRRRRRPHHHHHHHHRPRRRRRRRHHHRRRRRRRRRRHHHHR.HHHHHHHHRRRRRRRRRRP.RHHHHHHHHHHHRRRRRRRRRHHHHHRRRHHHHHHRRRRRRRHHHHH...RRR..........................RRRRR..RRRRR......RRRRR...........RRRR..RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.RRRR..........................",
"..................................................................PPRRRRRRRRRRRPHHHHHHHHRRRRRRRRRHHHRRRRRHHHRHHHHHHHHHHHHHHRRRRRRRRRRRPRRHHHHHHHHHHHHHRRRRRRRHHHHHHRRHHHHHHRRRRRHHHHHHH..RRRR..........................RRRRR..RRRR........RRRRR..........RRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR............RRR..........................",
"..................................................................PPRRRRRRRRRRRRHHHHHHHHRRRRRRRRRHHHPPHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRHHHHHHHHHHHHHHRRRRRRRHHHHHHRRHHHHHHRRRRHHHHHHH..RRRR.........................RRRRR..RRRRR.........RRRR..........RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR..RRRR...............RRR..........................",
"..................................................................PPRRRRRRRRRRRRHHHHHHHHRRRRRRRRRRRRPHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRRHHHHRHHHHHHHHHHRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHH..RRRR.........................RRRR...RRRR..........RRRR........RRRRRRRRRRRRRRRRRRRRRRRRRRR.RRRRR....RRRR...............RRRR.........................",
"..................................................................PPRRRRRRRRRRRRHHHHHHHHRRRRRRRRRRRRHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRRRRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRR........................RRRRRRRRRRRR...........RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR........RRRR....RRRR...............RRRR.........................",
"..................................................................PPRRRRRRRRRRRRHHHHHHHHRRRRRPRRRRRHHHHHHHHHHHHHHHHHHRPPRRRRRRRRRRRRRRRRRRRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRR..RRRRRR.............RRRRR.RRRRRRR......RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR..........RRRRR...RRRR...............RRRR.........................",
"..................................................................PPRRRRRRRRRRRRHHHHHHHHPPRRRRRRRRHHHHHHHHPRHHHHHHHHRRRPPRRRRRRRRRRRRRRRRRRRR.RRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRR...........RRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR........RRRRRR........RRRRRRRRRRRR.........RRRRRRRRRR.........................",
"...................................................................PRRRRPRRRRRPPHHHHHHHHHPRRRRRRRRHHHHHHRRRRHHHHHHHHHRRRPRRRRRRRRRRRRRP..PPP...RRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRRRR.......RRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRR...RRRR.........RRRRRRR.......RRRRRRRRRRR...RRRRRRRRRRRRRRRR.........................",
"...................................................................PPRRRPPRRRRPPHHHHHHHHHPRRRRRRRHHHHHHRRRRRHHHHHHHHHHRRPPRRRRRRRRRRR..........PRHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRHHHHH..RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR...........RRRR.........RRRRRRRR.......RRRRRRRRR....RRRRRRRRRRRRRRR..........................",
"...................................................................PPRRRPPRRRRPPHHHHHHHHHHRRRPRRRHHHHHRRRRRRHHHHHHHHHHRRRPPHHHHHRRRRR...........RHHHHHHHHHHHHHHRRHHHHRRRRRRRRRRRRRHHHHRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR...RRRRR..........RRRRRR.........RRRRRR.......RRRRRRR......RRRRRRRRRRRRRR...........................",
"...................................................................PGRRRPPRRRRPPHHHHHHHHHHRRRRRRRHHHHHRRRRRRHHHHRHHHHHHRRRHHHHHHRRRRRP..........HHHHHHHHHHHHHRRRRHHHHRRRRRRRRRRRRRRHHHRR....RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR..........RRRR..........RRRRRRR.........RRRRRR.......RRRRR.......RRRR....RRR..............................",
"...................................................................PGRRRRRRRRRRRHHHHHHHHHHHHRRRRRHHHHRRRRRRRHHHHRRHHHHHHHHHHHHHHRRRRRR..........HHHHHHHHHHHPRRRRRHHHHRRRRRRRRRRRRRRRRRRR......RRRRRRRR.RRRRRRRRRRRRRRRRRRR.........RRRRRRRRRRRRR...........RRRRRRR.........RRRRRRR.....RRRRR.......RRR.....RRR..............................",
".............................................................RRRP..PGRRRRRRRRRRRHHHHHHHHHHHHHRRRHHHHHRRRRRRRHHHHRRHHHHHHHHHHHHHHRRRRRRR........HHHHHHHHHHRRRRRRRRHHHHRRRRRRRRRRRRRR.RRRR........RRRRRRRRRRRRRRRRRRR...............RRRRRRRRRRRRRR...........RRRRRRRRRR.......RRRRRRRRRRRRRRRR.......RRR......................................",
".............................................................RRRP.PPGRRRRRRRRRRRHHHHHRHHHHHHHHHHHHHHHPPPPRRRHHHHRRRHHHHHHHHHHHRRRRRRRRRR......RHHHHHHHHHRRRRRRRRRHHHHRRRRRRRRRRRRR..RRRR..........RRRRRRRRRRRRRRRRRR..............RRRRRRRRRRRRRR...........RRRRRRRRRRRR......RRRRRRRRRRRRRRR.......RRR......................................",
".............................................................RRRP.PPGRRRPPRRRRPPHHHHHRRHHHHHHHHHHHHHHRRRRRRHHHHHRRRRHHHHHHHHHRRRRRRRRRRR....GRRHHHHHHH.RRRRRRRRRRHHHHRRRRRRRRRRR....RRRRR..........RRRRRRRRRRRRRRRRRR.............RRRRRR..RRRRRR...........RRRRRRRRRRRRR......RRRRRRRRRRRRRR......RRRR......................................",
".............................................................RRRP.RRRRRRPPRRRRPPHHHHHRRRHHHHHHHHHHHHRRRRRRRHHHHRRRHHHHHHHHHHRRRRRRRRRRRRR..PRRHHHHHHH..RRRRRRRRRRHHHHRRRRRRRRR......RRRRRRRR.......RRRRRRRRRRRRRRRRRRR..............RRRR....RRRRRR........RRRRR..RRRRRRRRR.......RRRRRRRRRRRR.....RRRR......................................",
".............................................................RRRP.RRRRRRPPRRRRPPHHHHHRRRRHHHHHHHHHHHHHRRRRRHHHHRRHHHHHHHHHRRRRRRRRR.RRRRRRRRRRHHHHHHPPRRRRRRRRRRHHHHHR.RRRRRRRR.....RRRRRRRR........RRRRRRRRRR..RRRRRRR..RRRRR.....RRRRR....RRRRRRR.....RRRRRRR..RRRRRRRRRRR......RRRRRRRRRRRR...RRRRR......................................",
".............................................................RRRP.RRRRRRRPRRRRPPHHHHHRRRRRHHHHHHHHHHHHHHHHHHHHHRHHHHHHHHHRRRRRRRRRRR.RRRRRRRRRHHHHHH.RRRRRRRRRRHHHHHHR....RRRRRRR....RRRRRRR.........RRRRRRRRR...RRRRRRR.RRRRRRR..RRRRR.....RRRRRRR.....RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.RRRRRRRRRRRRR......................................",
".............................................................RRRP.RRRRRRRPRRRRRRHHHHHRRRRPHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRPRRRHHHHHHHHHH..RRRRRRRRRRHHHHHHP.....RRRRRRR......RRRR.........RRRRRR.......RRRRRRRRRRRRRRRRRRRRR.......RRRRR...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR....RRRRRRRRRRR.......................................",
".............................................................RRRP.RRRRRRRRRRRRRRHHHHHRRRRPPHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRR.RRHHHHHHHHHHHRRRRRRRRRRRRHHHHH........RRRRRRR.....RRRR..........RRRRR........RRRRRRRRRRRRRRRRRRR..........RRRRRRRRRRRRRRRRRRRRR...RRRRRRRRRRRRR......RRRRRRRRR........................................",
".............................................................RRRPRRRRRRRRRRRRRRRHHHHHRRRRPHHHHHHHHPP...HHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRHHHHHHHHHHHHHRRRRRRRRRRRHHHH..........RRRRRRR....RRRR..........RRRRR.........RRRRRRRR.RRRRRRRR...........RRRRRRRRRRRRRRRRR.........RRRRRRRRRR........RRRRRRR.........................................",
".............................................................RRRPRRRRRRRRRRRRRRRRHHHHRRRRPHHHHHHHHHPPPPPPHHHHHHHHHHRRRHHHHHHRRRRRRRRRRRHHHHHHHHHHHHHHRRRRRRRRRRRRR.............RRRRRR...RRRR...........RRRRR.........RRRRRRR....................RRRRRRRRRRRRRRRR.........RRRRR................RRRRR.........................................",
".............................................................RRRRRRRRRRRRPRRRRPRRHHHHRRRRHHHHHHHHHHHHRRRHHHHHHHHHHRRRRHHHHHHRRRRRRRRRRRHHHHRRRHHHHHHHHRRRRRRRRRRR...............RRRRRRRRRRRR............RRRR..........RRRRRRR....................RRRRRR.RRRRRRR.........RRRRR..................RRRR.........................................",
".............................................................RRRRRRRRRRRRPRRRRPRRHHHHRRRRHHHHHHHHHHHHRHHHHHHHHHHRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHRRRRRRRRRRR................RRRRRRRRRR.............RRRRR..........RRRRRRR....................RRRRRRRRRRRRR.........RRRRR...............................................................",
".............................................................RRRRR.RRRRRRPRRRRPRRHHHHRRRRHHHHHHHHHHHHRHHHHHHHHHHRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRHHHHHHHHRRRRRRRRRP.................RRRRRRRRR..............RRRR...........RRRRRRR....................RRRRRRRRRRRR........RRRRRR...............................................................",
".............................................................PRRRRR.PRRRRPRRRRPRRHHHHRRRRHHHHPRHHHHHHHHHHHHHHHHHRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHHRRPPRRRR......................RRR................RRRR.............RRRRRRRRR.................RRRRRRRR..........RRRRRR................................................................",
"..............................................................RRRRRPPRRRRPRRRRRRHHHHHRRRRHHHRRRHHHHHHHHHHHHHHHHHRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHR..RRRRR.........................................RRRR..............RRRRRRRRR................RRRRRRRR.........RRRRRR.................................................................",
"..............................................................PRRRRRRRRRRRRRRRRRHHHHHRRRRHHHRRRRHHHHHHHHHHHPPHHHRRRRRRRRRRHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHHRRRRRRR.........................................RRRR...............RRRRRRRRR................RRRRRRRRRRR....RRRRRR..................................................................",
"...............................................................RRRRRRRRRRRRRRRRRHHHHHRRRRHHHRRRRHHHHHHHHHHHRRHHHRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHHRRRRRP..........................................RRR................RRRRRRRRRRRRRRR..........RRRRRRRRRRRRRRRRRRR...................................................................",
"................................................................RRRRRRRRRRRRRRRRHHHHHRRRRRRRRRHHHHHHHHHHRRRRRHHHRRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHRRRRR...........................................RRR................RRRRRRRRRRRRRRRR..........RRRRRRRRRRRRRRRRR....................................................................",
"...................................................................RRRRRR.RRRRRRHHHHHRRRRRRR.HHHHHHHHHHHHHRRRHHHRRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHHRRRR...........................................RRR................RRRRRRRRRRRRRRRRR..........RRRRRRRRRRRRRRR.....................................................................",
"...................................................................RRRRRRRRRRRRRHHHHHRRRRRRRHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHHRRRR...........................................RRRR................RRRRRRRRRRRRRRRR..........RRRRRR.RRRRRRRR.....................................................................",
"...............................PPPP..................................RRRRRRRRRRRHHHHHRRRRRHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRRPHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHRRR............................................RRRR................RRRRRRRRRRRRRRRR...........RRRRR...RRRRRR.....................................................................",
"...............................PPPPP.................................RRRRRRRRRRHHHHHHRRRRHHHHHHHHHHRHHHHHHHRRRRRRRRRRRRRRRRRRHHHHHHRRRRRRRRRRPRRRRRRRHHHHHHRRR............................................RRRRRRR.............RRRRRRRRRRRRRRRR............RRRR.....RRRR..........RRRR.......................................................",
"...............................PPPPP.................................RRRRRRRRRRHHHHH.RRHHHHHHHHHHRRRHHHHHHHHHHRP.RRRRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRHHHHHHRRR.............................................RRRRRRRR...........RRRRRRRRRRRRRRR.............RRRR......RRRR.......RRRRRR.......................................................",
"...............................PPPPP.................................RRRRRRRRRHHHHHH.RRHHHHHHHHHPPRRRHHHHHHHHHRRRRRRRRRRRRRRRRRHHHHHHRRRRRRRRRRRRRRPRHHHHHHRRR.............................................RRRRRRRRR...........RRRRRRRRRRRRR..............RRRR......RRRR.....RRRRRRRR.......................................................",
".....................................................................PRRR.RRRRHHHHHHPHHHHHHHHHRRRPRRRRHHHHHHHHRRRRRRRRPPPRRRRRRHHHHHHRRRRRRRRRRRRRPPHHHHHHHRRR................................................RRRRRRR...........RRRRRRRRRRRR.............RRRRR......RRRR..RRRRRRRRRR........................................................",
"..............................PPP....................................PRRR.RRRRHHHHHHHHHHHHHHHRRRRRRRRRRHHHHHHHHRRRRRR.PPP.RRRRRRHHHHHHRRRRRRRRRRPPPHHHHHHHHRR...................................................RRRRRR..........RRRRRRRRRRRRRR...........RRRRR......RRRRRRRRRRRRRR..........................................................",
".............................PPPPPPPPPP..............................PRRR.RRRRHHHHHHHHHHHHHHPRRRRRRRRRRHHHHHHHHRRRRR.PPPPPRRRRRRRHHHHHHRRRRRRRRPPHHHHHHHHHRRR....................................................RRRRRR.......RRRRRRRRRRRRRRRRR.........RRRRR........RRRRRRRRRRR............................................................",
".............................PPPPPRRRRRRP............................PRRR.RRRRHHHHHHHHHHHRRRRRRRRRRRRRRHHHHHHHHHRR...PPPPRRRRRRRRHHHHHHHRRRRRRPPHHHHHHHHHRRR......................................................RRRRRRR....RRRRRRRRRRR.RRRRRRRR.......RRRRR........RRRRRRRR...............................................................",
".............................PPPPRRRRRRRR..........................HHHHHHHHHHHHHHHHHHHHHRRRRRRHHHHRRRRRRRHHHHHHHH....PPPPRRRRRRRRRHHHHHHRRRRPPPHHHHHHHHHHRRR.......................................................RRRRRRRR.RRRRRRRRRRR...RRRRRRRR.....RRRRR.........RRRRRR.................................................................",
".............................PPPPRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRHHHHRHHHHRRRRRRRRHHHHHHH....PPPPRRRRRRRRRRHHHHHHRRPPPHHHHHHHHHHRRRR........................................................RRRRRRRRRRRRRR..........RRRRRRRR..RRRRRR.........RRRR...................................................................",
".............................PPPPRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRHHHHRHHHHRRRRRRRRRHHHHHHH....PPRRRRRRRRRRRRHHHHHHRPPHHHHHHHHH.RRRRR.........................................................RRRRRRRRRRRR............RRRRRRRRRRRRRR..........RRRR...................................................................",
".............................PPPPRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRHHHHRHHHHRRRRRRRRRRHHHHHHH...PPRRRRRRRRRRRRHHHHHHRRHHHHHHHHH.RRRRRP...........................................................RRRRRRRRR...............RRRRRRRRRRR...........RRRR...................................................................",
"...............................PPRRRRRHHHHHHHHHHHHHHHHHHH............PHHHHHHHHHHHHHRRRHHHHHHHRHHHHRRRRRRRRR.HHHHHHHH..PPRRRRRRRRRRRRRHHHHHHRHHHHHHHH.RRRRRR..........................................................RRRRRRRRRR..................RRRRRRRRR..........RRRRR...................................................................",
".................................RRRRRRRR............................PRRRRRRRHHHHHRRRRHHHHHHHRHHHHRRRRRRRRPP.HHHHHHHH.HHHHRRRRRRRRRRRRHHHHHHHHHHHHH..RRRRR..........................................................RRRRRRRRR.....................RRRRRRRRR.........RRRR....................................................................",
".................................PRRRRRRP............................PPPPRRRRHHHHHRRRRHHHHHHHPHHHHRPP..RRRPP..HHHHHHHHHHHHRRRRRRRRRRRRHHHHHHHHHHHH..RRRRRP.........................................................RRRRRRRRR........................RRRRRRRR........RRRR....................................................................",
".................................PPPPPP....................................RRHHHHHRRRRHHHHHHH.HHHHRP...RRRPP...HHHHHHHHHHHRRRRRRRRRRRRRHHHHHHHHHH...RRRRR..........................................................RRRRRRRRR........................RRRRRRRRRR......RRRR....................................................................",
"...........................................................................RRHHHHHRRRRRHHHHHH.HHHHRP...RRRP.....HHHHHHHHHHRRRRRRRRRRRRRRHHHHHHHH....RRRRPP........................................................RRRRRRRRRR........................RRRRRRRRRRR....RRRR.....................................................................",
"...........................................................................RRHHHHHRRRRRRHHHHHHHHHHRP...RRRPP.....HHHHHHHHHHPRRRRRRRRRRRRHHHHHHHH....RRRRPP........................................................RRRRRRRRR.........................RRRRRRRRRRRRR..RRRR.....................................................................",
".............................................................................HHHHH...PRRRHHHHHHHHHRRRRRRRRPP......HHHHHHHHHHHRRRRRRRRRRRHHHHHHHHRRRRRRRRRRR......................................................RRRRRRRRRR.........................RRRRRRRRRRRRRRRRRRR.....................................................................",
".............................................................................HHHHH...PRRRHHHHHHHHHRRRRRRRRPP.......HHHHHHHHHHHHRRRRRRRRRHHHHHHHRRRRRRRRRRRRR.....................................................RRRR...............................RRRRRR..RRRRRRRRRRR.....................................................................",
".............................................................................HHHHH...PRRRRHHHHHHHHRRRRRRRRPP.......HHHHHHHHHHHHHHHRRRRHHHHHHHHHRRRRRRRRRRRRR....................................................RRRRR...............................RRRRRR...RRRRRRRRR......................................................................",
".............................................................................HHHHH....RRRRHHHHHHHHRRRRRRRRP.........HHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRR....................................................RRRRR.........................................RRRRRRRR......................................................................",
".............................................................................HHHHH........HHHHHHHH..................HHHHRRHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRR...................................................RRRRR............................................RRRRRRR.....................................................................",
"..............................................................................HHHH........HHHHHHHHH.................RRRRRRRRHHHHHHHHHHHHHHHHHHHRRRRRRRRPRRRR...................................................RRRRR.............................................RRRRRR.....................................................................",
"..............................................................................HHHH........HHHHHHHHH.................RRRRRRRRRRRRHHHHHHHHHHHHHHHRRRRRRRRRRRRR..................................................RRRRR...............................................RRRRR.....................................................................",
"..............................................................................HHHH........HHHHHHHHH.................RHHHRRHHHHHPPRRRRRRHHHHHHHHPRRRRR.RRRRRR..................................................RRRRR................................................RRRR.....................................................................",
"..............................................................................HHHHH.......HHHHHHHHHHHHHHHHH.........RHHHHHHHHHHHRRRRRRRHHHHHHH..RRRRR.RRRRRR.................................................RRRRR..........................................................................................................................",
"..............................................................................HHHHH.......HHHHHHHHHHHHHHHHH.......HHHHHHHHHHHHHHHHHRRRRRRHHHH...RRRR..RRRRRR.................................................RRRRR......................................................RRRR................................................................",
"..............................................................................HHHHHH..HHHHHHHHHHHHHHHHHHHHHH.....HHHHHHHHHRHHHHHHHHRRRRRHHHHH..RRRRR.RRRRRR.................................................RRRRR.......................................................RRRRR...............................................................",
"..............................................................................HHHHHHHHHHHHHHHHHHHHHRRRRHHHHHHHHHHHHHHHHHHHRRRHHHHHHRRHHHHHHHH..RRRRR.RRRRRR.................................................RRRRR.......................................................RRRRRRRRR...........................................................",
"..............................................................................HHHHHHHHHHHHHHHHRHHHHRRRRRHHHHHHHHHHHHHHHHHHRRHHHHHHHRHHHHHHHHH.PRRRRR.RRRRR.................................................RRRRR.........................................................RRRRRRRRR..........................................................",
"...............................................................................HHHHHHHHHHHHHHHPHHHHRRRRRHHHHHHHHHHHHHHHHHHRRHHHHHHHHHHHHHHHHH.RRRRRR.RRRRRP................................................RRRR...........................................................RRRRRRRR..........................................................",
"...............................................................................HHHHHHHHHHHHHHHHHHHHRRRRRHHHHHHHHHHHHHHHHHHRRHHHHHHHHHHHHHHHHH.RRRRRR.RRRRRRRRRRRRRRRR.....................................RRRRR............................................................RRRRRRRR.........................................................",
"................................................................................HHHHHHHP..HHHHHHHHHHRRRRRRRHHHH...HHHHHHRRRRHHHHHHHHHHHHHHHHPRRRRRRR..RRRRRRRRRRRRRRR.....................................RRRR................................................................RRRRRR........................................................",
"................................................................................HHHHHHH...PHHHHRHHHHHRRRRRRHHHH...HHHHHRRRRRHHHHHHHHHHRHHHHHPRRRRRRRR..RRRRRRRRRRRRRR.....................................RRRR.................................................................RRRRRRRRR....................................................",
"................................................................................HHHHHHHH..PHHHHRHHHHHRRRRRRHHHH....RRRRRRRRRHHHHHHHHRRRHHHHH.RRRRRRRR...PRRRRRRRRRRRR....................................RRRRR.................................................................RRRRRRRRRR...................................................",
"...............................................................................PHHHHHHHH...HHHHHHHHHHRRRRRRRRRRRRR.RRRRRRRRHHHHHHHHPRRHHHHHH.RRRRRRRRR.RRRRRRRRRRRRR.....................................RRRR...................................................................RRRRRRRRR...................................................",
"...............................................................................PHHHHHHHHHHHHHHHHHRHHHRRRRRRRRRRRRR.RRRRRRHHHHHHHHHRRRRHHHHHHRRRRRRRRRRRRRRRRRRRRRRR......................................RRRR........................................................................RRRRR..................................................",
"...............................................................................PHHHHHHHHHHHHHHHHHRHHHHHHHRRRRRRRRR.HHHHRHHHHHHHHRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRRRRRR......................................RRRR........................................................................RRRRRR.................................................",
"..............................................................................PPRRRHHHHHHHHHHHHHHRHHHHHHHRRRRRRRRRHHHHHHHHHHHHHRRRRRRRHHHHHHRRRRRRRRRRRRRRRRRRRRRRR......................................RRRR.........................................................................RRRRRRR...............................................",
"..............................................................................PPRRRRHHHHHHHHHHHRRRHHHHHHHRRRRRRRRRHHHHHHHHHHHHRRRRRRRRHHHHHHRRRR......RRRRRRRRRR.........................................RRRR.........................................................................RRRRRRRRRRRRR.........................................",
"..............................................................................PPRRRRHHHHH..HHHHRRRHHHHHHHHHHRRRRRPHHHHHHHHHHHRRRRRRRRRHHHHHHRRRR.......PRRRRRRRR.........................................RRRRR..........................................................................RRRRRRRRRRR.........................................",
"..............................................................................PPRRRRHHHHH..HHHHRRRHHHHRGRHHHRRRRRPHHHHHHHHHHRRRRRRRRRRHHHHHHRRRR.....RRRRRRRRRRR..........................................RRRR...........................................................................RRRRRRRRRR.........................................",
"..............................................................................PPRRRRHHHHHRRRHHHRRRHHHHRRRHHHRRRRRHHHHHHHHHHHRRRRRRRRRRHHHHHHRRRRR....RRRRRRRRRRR..........................................RRRRR.............................................................................................................................",
".............................................................................PPPRRRRHHHHHRRRHHHRRRHHHHHRRHHHHRRHHHHHHHHHHHRRRRRRRRRRRRHHHHHRRRRRR....RRRRRRRRRR...........................................RRRRR.............................................................................................................................",
".............................................................................PPRRRRRHHHHHRRRHHHHRRHHHHHRHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRHHHHHRRRRRR....RRRRRRRR..............................................RRRR.............................................................................................................................",
"............................................................................PPPRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRHHHHH..RRRRPPP.RRRRRRRR..............................................RRRRR............................................................................................................................",
"............................................................................PPPRRRRPHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH...RRRRRRRRRRRRRRHHHHH...RRRPPP.RRRRRRRR...............................................RRRR............................................................................................................................",
"............................................................................PPPRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHR.....PRRRRHHHHHRRHHHHHH...RRRPPP..RRRRRP................................................RRRR............................................................................................................................",
"........................................................................RRRRRPPRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRR.......RRRHHHHHHHHHHHHH...RRRRPP........................................................RRRR............................................................................................................................",
"........................................................................RRRRRRPRHHHHHHHHHHHHRRRRRRRRHHHHHHHHRHHHRRRR......PRRRHHHHHHHHHHHHH...RRRRRP.........................................................RRR............................................................................................................................",
".......................................................................RRRRRRRRHHHHHHHHHHH..RRRRRRRRRHHHHHHHRRRRRRRRP.....RRRRHHHHHHHHHHHHH...RRRRRRRRR......................................................RRR............................................................................................................................",
".......................................................................RRRRRRRRHHHHHHHHHHHHHRRRRRRRRRHHHHHHHRRRRRRRPPPP...RRRRRHHHHHHHHHHHH...RRRRRRRRR......................................................RRR............................................................................................................................",
".......................................................................RRRRRRRHHHHHHHHHHHHHHHRRRRRRRRHHHHHHHRRRRRRRRPPP..PRRRRP..HHHHHHHHHHH...RRRRRRRR......................................................RRRR...........................................................................................................................",
".......................................................................RRRRRRRHHHHHHHHHHHHHHHHHRRRRRRHHHHHHHRRRRRRRRRRRRRRRRRRRRRPHHHHHHHHHH.......RRRR......................................................RRRR...........................................................................................................................",
".........................................................................RRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRRRRRRRRRRRRRRRRRRRRHHHHHHHHHH.......RRRR......................................................RRRRR..........................................................................................................................",
"..........................................................................RRHHHHHHRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHRRRHHHRHHHHHHHRRRHHHHHHHHHHH......RRRRR......................................................RRRRRR.........................................................................................................................",
"............................................................................HHHHHHRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH...RRRRRR........................................................RRRRRR........................................................................................................................",
"...........................................................................RHHHHHRRRRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHPPRRRRRRR.........................................................RRRRRR.......................................................................................................................",
"...........................................................................RHHHHR.RRRRRRRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHPRRRRRRR...........................................................RRRRR.......................................................................................................................",
"..........................................................................GRHHHHP..RRRRRRRRRRRRRRRRHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHPRRRRRR.............................................................RRRRRRR....................................................................................................................",
"..........................................................................GRRRRRP.PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRPPPPHHHHRHHHHHHHHHHHHHHHHHHHRRRRR...............................................................RRRRRRR....................................................................................................................",
"..........................................................................GRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRHHHHRHHHHRRRRHHHHHHHHHHHRRRRR...............................................................RRRRRRR....................................................................................................................",
"..........................................................................GRRRRRRRRRRRPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRHHHHRHHHHRRRRRHHHHHHHHHHRRRRR.............................................................RRRRRRRRR....................................................................................................................",
"...........................................................................PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRHHHHRRHHH.....HHHHHHHHHRRRRRR............................................................RRRRRRR.......................................................................................................................",
".............................................................................PRRRRRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRHHHH......HHHHHHHRRRRRRR..........................................................RRRRRRRR........................................................................................................................",
"...............................................................................RRRRRRRRRRRR...RRRRRRRRRRRRRRRRRRRRRRRPRRRRHHHH......HHHHHHRRRRRRRR........................................................RRRRRRRR..........................................................................................................................",
".................................................................................RRRRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRPRRRRHHHH......HHHHHHRRRRRRR........................................................RRRRRRRR...........................................................................................................................",
"...................................................................................RRRRRRRRRR.RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.....HHHHHH..............................................................RRRRRRR.............................................................................................................................",
"...................................................................................PRRRRRRRRRPRRRRRRRRRRRRRRP.RRRRRRRRRRRRRRRRRRR...HHHHH...............................................................RRRRR...............................................................................................................................",
"...................................................................................RRRRRRRRRRRRRRRRRRRRRRRRRRPRRRRRRRRRRRRRRRRRRR..HHHHHH...............................................................RRRR................................................................................................................................",
"..................................................................................PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.RRRRRR.HHHHHH................................................................RRR.................................................................................................................................",
"..................................................................................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRHHHRRRR..RRRRRHHHHHHH....................................................................................................................................................................................................",
".................................................................................PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRHHHHHRRRR..RRRHHHHHHH.....................................................................................................................................................................................................",
".................................................................................RRRRRRRRRRRRRRRRRRRRRRR..PRRRRRRRHHHHHRRRRR.RRRHHHHHHH.....................................................................................................................................................................................................",
"................................................................................RRRRRRRRRRRRRRRRRRRRRR......RRRRRHHHHHHRRRRRRRRRHHHHHH......................................................................................................................................................................................................",
"................................................................................RRRRRRRRRRRRRRRRRRRRRR.......RRRRHHHHHRRRRRRRRRRHHHHH.......................................................................................................................................................................................................",
"...............................................................................RRRRRRRRRRRRRRRRRRRRRRRRR.....PRRHHHHHHRRRRRRRRRRHHHH........................................................................................................................................................................................................",
"...............................................................................RRRRRRRRRRRRRRRRRRRRRRRRRRRRR..RRHHHHHRRRPRRRRRRRRRP.........................................................................................................................................................................................................",
"............................................................................PPRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR..RHHHHHRRRRRRRRRRRRP..........................................................................................................................................................................................................",
"...........................................................................RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRHHHHHRRRRRRRRRRRRR...........................................................................................................................................................................................................",
"..........................................................................RRRRRRRRRRRRRRRRRRRRRPRRRRRRRRRRRRRRRHHHHHRRRRRRRRRRRRRR..........................................................................................................................................................................................................",
"..........................................................................RRRRRRRRRRRRRRRRRRRR...RRRRRRRRRRRRRRHHHHRRRRRRRRRRRRRRR..........................................................................................................................................................................................................",
".........................................................................RRRRRRRRRRRRRRRRRRR......RRRRRRRRRRRRRHHHHRRRR.......RRRRP.........................................................................................................................................................................................................",
"........................................................................RRRRRRRRRRRRRRRRRRR........RRRRRR.RRRRHHHHHRRRRR......RRRRR.........................................................................................................................................................................................................",
"........................................................................RRRRRRRRRRRRRRRRRP.........RRRRRR.RRRRHHHHHRRRRR.......RRRR.........................................................................................................................................................................................................",
"........................................................................RRRRRRRRRRRRRRRR...........RRRRRRRRRRHHHHHRRRRRR.......RRRR.........................................................................................................................................................................................................",
".........................................................................RRRRRRRRRRRRRP............PRRRRRRP.HHHHHHRRRRRR.......RRRR.........................................................................................................................................................................................................",
"..........................................................................RRRRRRRRRRR............RRRRRRRRRHHHHHHHHRRRRRRR......RRRR.........................................................................................................................................................................................................",
"...........................................................................PRRRRRRRR............RRRRRRRRHHHHHHHHHRRRRRRRRRRP...RRRRR........................................................................................................................................................................................................",
"..............................................................................RRRR.............PRRRRRRRHHHHHHHHHRRRRRRRRRRRR...RRRRR........................................................................................................................................................................................................",
"..............................................................................................PPRRRRRRHHHHHHHHHRRRRRPRRRRRRRRRRRRRRR........................................................................................................................................................................................................",
".............................................................................................PPPRRRRHHHHHHHHHHRRRRRR...RRRRRRRRRRRR.........................................................................................................................................................................................................",
".............................................................................................PPRRRRHHHHHHHHHRRRRRRRR...RRRR.RRRRRRP.........................................................................................................................................................................................................",
".............................................................................................PRRRRHHHHHHHHRPRRRRRRRP..RRRRR..RRRRR..........................................................................................................................................................................................................",
".............................................................................................PRRHHHHHHHHHRR.RRRRRRRRRRRRRR...RRRRR..........................................................................................................................................................................................................",
".............................................................................................RRHHHHHHHH......RRRRRRRRRRRRR....RRRR..........................................................................................................................................................................................................",
"............................................................................................RRRHHHHHHH.......GRRRRRRRRRRRRRRRRRRRR..........................................................................................................................................................................................................",
"............................................................................................RRRHHHHH...............RRRRRRRRRRRRRRR..........................................................................................................................................................................................................",
"............................................................................................RRRHHHH...................RRRRRRRRRRRR..........................................................................................................................................................................................................",
"............................................................................................RRRHHHR.........RRRRR.....RRRRRRRRRRRR..........................................................................................................................................................................................................",
"............................................................................................HHHHRRRR.......RRRRRR......RRRRRRRRRRR..........................................................................................................................................................................................................",
"...........................................................................................HHHHHRRRRR....RRRRRRRRR......RRRRRRRRRR..........................................................................................................................................................................................................",
"..........................................................................................HHHHHHRRRRRR..RRRRRRRRRRR.....RRRRRRRRR...........................................................................................................................................................................................................",
"..........................................................................................HHHHHHRRRRRRRRRRRRRRRRRRRR....RRRRRRRRR...........................................................................................................................................................................................................",
".........................................................................................HHHHHHRRRRRRRRRRRRRR..RRRRR..RRRRRRRRRRR...........................................................................................................................................................................................................",
"........................................................................................HHHHHH.RRRRRRRRRRRRR...RRRRRRRRRRRRRRRRRR...........................................................................................................................................................................................................",
"..................................................................PPP..................HHHHHHH.RRRRRRRRRRRRRR...RRRRRRRRRRR.RRRRR...........................................................................................................................................................................................................",
"..................................................................PPP..................HHHHHH..RRRRRRRRRRRRRR...RRRRRRRRRR.RRRRRR...........................................................................................................................................................................................................",
".................................................................PPPPP.............PPPRHHHHH...PRRRRRRRRRRRRRR.RRRRRRRRR.PRRRRRR............................................................................................................................................................................................................",
"........................................................PPRRRRRRRRRRRRRRP..RRRRRRRRRRRRHHHH.....RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.............................................................................................................................................................................................................",
"................................................PRRRRRRRRRRRRRRRRRRRRRRRRRPRRRRRRRRRRRRRRRR.......RRRRRRRRRRRRRRRRRRRRRRRRRRRR..............................................................................................................................................................................................................",
".............................................PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR.........RRRRRRRRRRRRRRRRRRRRRRRRRR...............................................................................................................................................................................................................",
"............................................RRRRRRRRRRRRRRRRRRRRRRPPRRRRRRRRRRRRRRRRRRRRR..............RRRRRRRRRRRRRRRRRRRP.................................................................................................................................................................................................................",
"..........................................PRRRRRRRRRRRRRRPP..........PRRRRRRRRRRRRRRRRRRRR................RRRRRRRRRRPRRR....................................................................................................................................................................................................................",
".........................................RRRRRRRRRP....................PRRRRRRPP.....RRRRRP.................................................................................................................................................................................................................................................",
"........................................RRRRRRRRP....................................RRRRRR.................................................................................................................................................................................................................................................",
"...............PPPPP..................PRRRRRRRR......................................RRRRRRR................................................................................................................................................................................................................................................",
"............RRRRRRRRRRRR............RRRRRRRRRR.......................................RRRRRRRP...............................................................................................................................................................................................................................................",
".........PRRRRRRRRRRRRRRRRR.....PRRRRRRRRRRRP....................................RRRRRRRRRRRR...............................................................................................................................................................................................................................................",
".......PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR....................................RRRRRRRRRRRRRRR..............................................................................................................................................................................................................................................",
"......RRRRRRRRRRRPRRRRRRRRRRRRRRRRRRRRRRRP...................................RRRRRRRRRRR.RRRRR..............................................................................................................................................................................................................................................",
"....RRRRRRRRRRP......PRRRRRRRRRRRRRRRRP.....................................RRRRRRRRRRR..PRRRRR.............................................................................................................................................................................................................................................",
"..PRRRRRRRRRP...........PRRRRRRRRRRP.......................................RRRRRRR........RRRRRR............................................................................................................................................................................................................................................",
"RRRRRRRRRRP................................................................RRRRRR..........RRRRRP...........................................................................................................................................................................................................................................",
"RRRRRRRRR................................................................RRRRRR............PRRRRR...........................................................................................................................................................................................................................................",
"RRRRRRR..................................................................RRRRR..............RRRRRR..........................................................................................................................................................................................................................................",
"RRRRRP...................................................................RRRRR...............RRRRR..........................................................................................................................................................................................................................................",
"RRRR.....................................................................RRRR.................RRRR..........................................................................................................................................................................................................................................",
}};
} // namespace EdgeWeightGPS::Generated
+183 -12
View File
@@ -11,6 +11,7 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <chrono> #include <chrono>
#include <cmath>
#include <cstring> #include <cstring>
#include <cstdint> #include <cstdint>
#include <filesystem> #include <filesystem>
@@ -22,6 +23,8 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include "GeneratedSpatialRoadGrid.hpp"
namespace RED4ext::v1 namespace RED4ext::v1
{ {
struct Logger struct Logger
@@ -103,10 +106,15 @@ constexpr bool kEnableGpsTraceHooks = true;
constexpr bool kEnableGpsQueryLifecycleHooks = true; constexpr bool kEnableGpsQueryLifecycleHooks = true;
constexpr bool kEnableGpsAsyncTrafficProbe = true; constexpr bool kEnableGpsAsyncTrafficProbe = true;
constexpr bool kEnableGpsTrafficEdgeWeightPatch = false; constexpr bool kEnableGpsTrafficEdgeWeightPatch = false;
constexpr bool kEnableGpsSpatialEdgeWeightPatch = false;
constexpr bool kEnableGpsSpatialEdgeWeightPatchTrace = false;
constexpr bool kEnableGpsRouteJobLifecycleHooks = false; constexpr bool kEnableGpsRouteJobLifecycleHooks = false;
constexpr bool kEnableGpsRouteJobStartTrace = false; constexpr bool kEnableGpsRouteJobStartTrace = false;
constexpr bool kEnableGpsLocalSearchHooks = false; constexpr bool kEnableGpsLocalSearchHooks = false;
constexpr bool kEnableRouteUiTraceHooks = false; constexpr bool kEnableRouteUiTraceHooks = false;
constexpr bool kEnableGpsLocalSearchTraceHooks = kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks;
constexpr bool kEnableGpsRouteProducerHook = kEnableGpsLocalSearchTraceHooks || kEnableGpsSpatialEdgeWeightPatch;
constexpr bool kEnableGpsEdgeCostHook = kEnableGpsLocalSearchTraceHooks || kEnableGpsSpatialEdgeWeightPatch;
constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C; constexpr uintptr_t kGpsSystemTickRva = 0x0E6B62C;
constexpr uintptr_t kJournalTrackEntryImplRva = 0x05944FC; constexpr uintptr_t kJournalTrackEntryImplRva = 0x05944FC;
constexpr uintptr_t kJournalListenerArrayOffset = 0x210; constexpr uintptr_t kJournalListenerArrayOffset = 0x210;
@@ -197,6 +205,12 @@ constexpr uint16_t kTrafficLaneFlagGpsOnly = 0x0200;
constexpr uint16_t kTrafficLaneFlagNoAiDriving = 0x2000; constexpr uint16_t kTrafficLaneFlagNoAiDriving = 0x2000;
constexpr uint16_t kTrafficLaneFlagHighway = 0x4000; constexpr uint16_t kTrafficLaneFlagHighway = 0x4000;
constexpr uint16_t kTrafficLaneFlagNoAutodrive = 0x8000; constexpr uint16_t kTrafficLaneFlagNoAutodrive = 0x8000;
constexpr bool kGpsSpatialPatchRequiresRouteProducer = true;
constexpr float kGpsSpatialHighwayMultiplier = 0.62f;
constexpr float kGpsSpatialRoadMultiplier = 1.0f;
constexpr float kGpsSpatialGpsOnlyMultiplier = 1.20f;
constexpr float kGpsSpatialPavementMultiplier = 1.35f;
constexpr float kGpsSpatialUnknownMultiplier = 1.05f;
struct GpsProviderClassOverride struct GpsProviderClassOverride
{ {
@@ -982,6 +996,122 @@ struct Vector3Value
float z; float z;
}; };
int GpsSpatialRoadClassRank(char aCode)
{
switch (aCode)
{
case 'H':
return 4;
case 'R':
return 3;
case 'G':
return 2;
case 'P':
return 1;
default:
return 0;
}
}
const char* GpsSpatialRoadClassName(char aCode)
{
switch (aCode)
{
case 'H':
return "highway";
case 'R':
return "road";
case 'G':
return "gpsonly";
case 'P':
return "pavement";
default:
return "unknown";
}
}
float GpsSpatialRoadClassMultiplier(char aCode)
{
switch (aCode)
{
case 'H':
return kGpsSpatialHighwayMultiplier;
case 'R':
return kGpsSpatialRoadMultiplier;
case 'G':
return kGpsSpatialGpsOnlyMultiplier;
case 'P':
return kGpsSpatialPavementMultiplier;
default:
return kGpsSpatialUnknownMultiplier;
}
}
char LookupGpsSpatialRoadClass(float aX, float aMapY)
{
using namespace EdgeWeightGPS::Generated;
if (!std::isfinite(aX) || !std::isfinite(aMapY))
{
return '.';
}
const auto columnFloat = (aX - kSpatialRoadGridMinX) / kSpatialRoadGridCellSize;
const auto rowFloat = (aMapY - kSpatialRoadGridMinY) / kSpatialRoadGridCellSize;
if (columnFloat < 0.0f || rowFloat < 0.0f)
{
return '.';
}
const auto column = static_cast<int64_t>(std::floor(columnFloat));
const auto row = static_cast<int64_t>(std::floor(rowFloat));
if (column < 0 || row < 0 || column >= static_cast<int64_t>(kSpatialRoadGridWidth) ||
row >= static_cast<int64_t>(kSpatialRoadGridHeight))
{
return '.';
}
const auto& rowData = kSpatialRoadGridRows[static_cast<size_t>(row)];
if (static_cast<size_t>(column) >= rowData.size())
{
return '.';
}
return rowData[static_cast<size_t>(column)];
}
bool TryLookupGpsSpatialEdgeClass(void* aCurrentState, void* aNeighborState, char& aCode)
{
Vector3Value current{};
Vector3Value neighbor{};
if (!aCurrentState || !aNeighborState || !TryReadMemory(aCurrentState, current) ||
!TryReadMemory(aNeighborState, neighbor))
{
return false;
}
const auto midpointX = (current.x + neighbor.x) * 0.5f;
const auto midpointMapY = (current.z + neighbor.z) * 0.5f;
// Search states are (world X, height, world Y); route producer query vectors use (X, Y, Z, W).
const std::array candidates = {
LookupGpsSpatialRoadClass(midpointX, midpointMapY),
LookupGpsSpatialRoadClass(current.x, current.z),
LookupGpsSpatialRoadClass(neighbor.x, neighbor.z),
};
aCode = '.';
for (const auto candidate : candidates)
{
if (GpsSpatialRoadClassRank(candidate) > GpsSpatialRoadClassRank(aCode))
{
aCode = candidate;
}
}
return true;
}
void AppendVector3Pointer(std::ostringstream& aLine, const char* aLabel, const void* aVector) void AppendVector3Pointer(std::ostringstream& aLine, const char* aLabel, const void* aVector)
{ {
Vector3Value value{}; Vector3Value value{};
@@ -4068,7 +4198,7 @@ int32_t DetourGpsRouteProducer(void* aGraph, void* aQuery, void* aOutResult)
{ {
std::lock_guard lock(gGpsCostLogMutex); std::lock_guard lock(gGpsCostLogMutex);
callCount = gGpsRouteProducerLogCount++; callCount = gGpsRouteProducerLogCount++;
shouldLog = callCount < kMaxCalls; shouldLog = kEnableGpsLocalSearchTraceHooks && callCount < kMaxCalls;
} }
if (shouldLog) if (shouldLog)
@@ -4331,6 +4461,21 @@ float DetourGpsEdgeCost(void* aCostProvider, void* aCurrentState, void* aNeighbo
const auto sourceClass = ReadGpsPointClass(aCurrentPoint); const auto sourceClass = ReadGpsPointClass(aCurrentPoint);
const auto neighborClass = ReadGpsPointClass(aNeighborPoint); const auto neighborClass = ReadGpsPointClass(aNeighborPoint);
const auto originalResult = result;
char spatialClass = '.';
float spatialMultiplier = 1.0f;
bool spatialAdjusted = false;
const auto spatialPatchAllowed =
kEnableGpsSpatialEdgeWeightPatch &&
(!kGpsSpatialPatchRequiresRouteProducer || gActiveGpsRouteProducerCall != UINT32_MAX);
if (spatialPatchAllowed && result > 0.0f && std::isfinite(result) &&
TryLookupGpsSpatialEdgeClass(aCurrentState, aNeighborState, spatialClass))
{
spatialMultiplier = GpsSpatialRoadClassMultiplier(spatialClass);
result *= spatialMultiplier;
spatialAdjusted = spatialMultiplier != 1.0f;
}
if (gActiveGpsEdgeCostStats) if (gActiveGpsEdgeCostStats)
{ {
@@ -4339,9 +4484,9 @@ float DetourGpsEdgeCost(void* aCostProvider, void* aCurrentState, void* aNeighbo
} }
float multiplier = 0.0f; float multiplier = 0.0f;
const auto hasMultiplier = sourceClass < 64 && const auto hasMultiplier =
TryReadFloatField(aCostProvider, 0x08 + static_cast<uintptr_t>(sourceClass) * sizeof(float), neighborClass < 64 &&
multiplier); TryReadFloatField(aCostProvider, 0x08 + static_cast<uintptr_t>(neighborClass) * sizeof(float), multiplier);
uint32_t callCount = 0; uint32_t callCount = 0;
uint32_t classCallCount = 0; uint32_t classCallCount = 0;
@@ -4349,21 +4494,29 @@ float DetourGpsEdgeCost(void* aCostProvider, void* aCurrentState, void* aNeighbo
{ {
std::lock_guard lock(gGpsCostLogMutex); std::lock_guard lock(gGpsCostLogMutex);
callCount = gGpsEdgeCostLogCount++; callCount = gGpsEdgeCostLogCount++;
if (sourceClass < gGpsEdgeCostClassLogCounts.size()) if (neighborClass < gGpsEdgeCostClassLogCounts.size())
{ {
classCallCount = gGpsEdgeCostClassLogCounts[sourceClass]++; classCallCount = gGpsEdgeCostClassLogCounts[neighborClass]++;
} }
shouldLog = callCount < 32 || (sourceClass < 64 && classCallCount < 1); shouldLog =
(kEnableGpsLocalSearchTraceHooks && (callCount < 32 || (neighborClass < 64 && classCallCount < 1))) ||
(kEnableGpsSpatialEdgeWeightPatchTrace && spatialAdjusted && callCount < 128);
} }
if (shouldLog) if (shouldLog)
{ {
const auto baseCost = hasMultiplier && multiplier != 0.0f ? result / multiplier : 0.0f; const auto baseCost = hasMultiplier && multiplier != 0.0f ? originalResult / multiplier : 0.0f;
std::ostringstream line; std::ostringstream line;
line << "hook GPSEdgeCost 0x44f838 call=" << callCount << " classCall=" << classCallCount line << "hook GPSEdgeCost 0x44f838 call=" << callCount << " classCall=" << classCallCount
<< " sourceClass=" << static_cast<uint32_t>(sourceClass) << " sourceClass=" << static_cast<uint32_t>(sourceClass)
<< " neighborClass=" << static_cast<uint32_t>(neighborClass) << " value=" << result; << " neighborClass=" << static_cast<uint32_t>(neighborClass) << " value=" << result;
if (spatialPatchAllowed)
{
line << " originalValue=" << originalResult << " spatialClass=" << GpsSpatialRoadClassName(spatialClass)
<< " spatialMultiplier=" << spatialMultiplier
<< " spatialAdjusted=" << static_cast<uint32_t>(spatialAdjusted);
}
if (hasMultiplier) if (hasMultiplier)
{ {
line << " multiplier=" << multiplier << " baseCost=" << baseCost; line << " multiplier=" << multiplier << " baseCost=" << baseCost;
@@ -4815,21 +4968,30 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
reinterpret_cast<void*>(&DetourGpsRouteJobStart), reinterpret_cast<void*>(&DetourGpsRouteJobStart),
reinterpret_cast<void**>(&gOriginalGpsRouteJobStart)); reinterpret_cast<void**>(&gOriginalGpsRouteJobStart));
} }
if (kEnableGpsProviderClassPatch || (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks)) if (kEnableGpsProviderClassPatch || kEnableGpsLocalSearchTraceHooks)
{ {
AttachProbeHook("GPSSearch 0x44f054", kGpsSearchRva, reinterpret_cast<void*>(&DetourGpsSearch), AttachProbeHook("GPSSearch 0x44f054", kGpsSearchRva, reinterpret_cast<void*>(&DetourGpsSearch),
reinterpret_cast<void**>(&gOriginalGpsSearch)); reinterpret_cast<void**>(&gOriginalGpsSearch));
} }
if (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks) if (kEnableGpsRouteProducerHook)
{ {
AttachProbeHook("GPSRouteProducer 0x44cc7c", kGpsRouteProducerRva, AttachProbeHook("GPSRouteProducer 0x44cc7c", kGpsRouteProducerRva,
reinterpret_cast<void*>(&DetourGpsRouteProducer), reinterpret_cast<void*>(&DetourGpsRouteProducer),
reinterpret_cast<void**>(&gOriginalGpsRouteProducer)); reinterpret_cast<void**>(&gOriginalGpsRouteProducer));
}
if (kEnableGpsLocalSearchTraceHooks)
{
AttachProbeHook("GPSResolveHandle 0x44e1a8", kGpsResolveHandleRva, AttachProbeHook("GPSResolveHandle 0x44e1a8", kGpsResolveHandleRva,
reinterpret_cast<void*>(&DetourGpsResolveHandle), reinterpret_cast<void*>(&DetourGpsResolveHandle),
reinterpret_cast<void**>(&gOriginalGpsResolveHandle)); reinterpret_cast<void**>(&gOriginalGpsResolveHandle));
}
if (kEnableGpsEdgeCostHook)
{
AttachProbeHook("GPSEdgeCost 0x44f838", kGpsEdgeCostRva, reinterpret_cast<void*>(&DetourGpsEdgeCost), AttachProbeHook("GPSEdgeCost 0x44f838", kGpsEdgeCostRva, reinterpret_cast<void*>(&DetourGpsEdgeCost),
reinterpret_cast<void**>(&gOriginalGpsEdgeCost)); reinterpret_cast<void**>(&gOriginalGpsEdgeCost));
}
if (kEnableGpsLocalSearchTraceHooks)
{
AttachProbeHook("GPSFilteredProviderFilter 0x44ff68", kGpsFilteredProviderFilterRva, AttachProbeHook("GPSFilteredProviderFilter 0x44ff68", kGpsFilteredProviderFilterRva,
reinterpret_cast<void*>(&DetourGpsFilteredProviderFilter), reinterpret_cast<void*>(&DetourGpsFilteredProviderFilter),
reinterpret_cast<void**>(&gOriginalGpsFilteredProviderFilter)); reinterpret_cast<void**>(&gOriginalGpsFilteredProviderFilter));
@@ -4993,15 +5155,24 @@ RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::v1::PluginHandle aHandle, RED4e
{ {
DetachProbeHook("GPSRouteJobStart 0x818928", kGpsRouteJobStartRva); DetachProbeHook("GPSRouteJobStart 0x818928", kGpsRouteJobStartRva);
} }
if (kEnableGpsProviderClassPatch || (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks)) if (kEnableGpsProviderClassPatch || kEnableGpsLocalSearchTraceHooks)
{ {
DetachProbeHook("GPSSearch 0x44f054", kGpsSearchRva); DetachProbeHook("GPSSearch 0x44f054", kGpsSearchRva);
} }
if (kEnableGpsTraceHooks && kEnableGpsLocalSearchHooks) if (kEnableGpsRouteProducerHook)
{ {
DetachProbeHook("GPSRouteProducer 0x44cc7c", kGpsRouteProducerRva); DetachProbeHook("GPSRouteProducer 0x44cc7c", kGpsRouteProducerRva);
}
if (kEnableGpsLocalSearchTraceHooks)
{
DetachProbeHook("GPSResolveHandle 0x44e1a8", kGpsResolveHandleRva); DetachProbeHook("GPSResolveHandle 0x44e1a8", kGpsResolveHandleRva);
}
if (kEnableGpsEdgeCostHook)
{
DetachProbeHook("GPSEdgeCost 0x44f838", kGpsEdgeCostRva); DetachProbeHook("GPSEdgeCost 0x44f838", kGpsEdgeCostRva);
}
if (kEnableGpsLocalSearchTraceHooks)
{
DetachProbeHook("GPSFilteredProviderFilter 0x44ff68", kGpsFilteredProviderFilterRva); DetachProbeHook("GPSFilteredProviderFilter 0x44ff68", kGpsFilteredProviderFilterRva);
DetachProbeHook("GPSBaseProviderFilter 0x450b08", kGpsBaseProviderFilterRva); DetachProbeHook("GPSBaseProviderFilter 0x450b08", kGpsBaseProviderFilterRva);
} }
+327
View File
@@ -0,0 +1,327 @@
#!/usr/bin/env python3
"""Generate a compact road-class grid for the RED4ext GPS edge-cost shim."""
from __future__ import annotations
import argparse
import json
import math
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Iterable
FLAGS = {
"Pavement": 0x0008,
"Road": 0x0010,
"GPSOnly": 0x0200,
"Highway": 0x4000,
}
CATEGORY_CODES = {
"unknown": ".",
"pavement": "P",
"gpsonly": "G",
"road": "R",
"highway": "H",
}
CATEGORY_PRIORITY = {
".": 0,
"P": 1,
"G": 2,
"R": 3,
"H": 4,
}
@dataclass(frozen=True)
class GridSpec:
min_x: float
min_y: float
width: int
height: int
cell_size: float
def flag_value(value: Any) -> int:
if isinstance(value, int):
return value
if isinstance(value, str):
return int(value)
if isinstance(value, dict):
for key in ("Value", "$value", "value"):
if key in value:
return flag_value(value[key])
return int(value or 0)
def lane_category(flags: int) -> str:
if flags & FLAGS["Highway"]:
return "highway"
if flags & FLAGS["GPSOnly"]:
return "gpsonly"
if flags & FLAGS["Road"]:
return "road"
if flags & FLAGS["Pavement"]:
return "pavement"
return "unknown"
def load_lanes(path: Path) -> list[dict[str, Any]]:
data = json.loads(path.read_text(encoding="utf-8"))
return data["Data"]["RootChunk"]["data"]["lanes"]
def load_lane_polygons(path: Path) -> list[list[tuple[float, float]]]:
data = json.loads(path.read_text(encoding="utf-8"))
rows = data["Data"]["RootChunk"]["data"]
polygons: list[list[tuple[float, float]]] = []
for row in rows:
polygon = row.get("value", {}).get("polygon") or []
polygons.append([(float(point["X"]), float(point["Y"])) for point in polygon])
return polygons
def point_in_polygon(x: float, y: float, polygon: list[tuple[float, float]]) -> bool:
inside = False
count = len(polygon)
if count < 3:
return False
previous_x, previous_y = polygon[-1]
for current_x, current_y in polygon:
if (current_y > y) != (previous_y > y):
edge_x = (previous_x - current_x) * (y - current_y) / (previous_y - current_y) + current_x
if x < edge_x:
inside = not inside
previous_x, previous_y = current_x, current_y
return inside
def orientation(ax: float, ay: float, bx: float, by: float, cx: float, cy: float) -> float:
return (by - ay) * (cx - bx) - (bx - ax) * (cy - by)
def on_segment(ax: float, ay: float, bx: float, by: float, cx: float, cy: float) -> bool:
return min(ax, cx) <= bx <= max(ax, cx) and min(ay, cy) <= by <= max(ay, cy)
def segments_intersect(
ax: float,
ay: float,
bx: float,
by: float,
cx: float,
cy: float,
dx: float,
dy: float,
) -> bool:
o1 = orientation(ax, ay, bx, by, cx, cy)
o2 = orientation(ax, ay, bx, by, dx, dy)
o3 = orientation(cx, cy, dx, dy, ax, ay)
o4 = orientation(cx, cy, dx, dy, bx, by)
if (o1 > 0) != (o2 > 0) and (o3 > 0) != (o4 > 0):
return True
eps = 1e-5
if abs(o1) <= eps and on_segment(ax, ay, cx, cy, bx, by):
return True
if abs(o2) <= eps and on_segment(ax, ay, dx, dy, bx, by):
return True
if abs(o3) <= eps and on_segment(cx, cy, ax, ay, dx, dy):
return True
if abs(o4) <= eps and on_segment(cx, cy, bx, by, dx, dy):
return True
return False
def polygon_intersects_cell(
polygon: list[tuple[float, float]],
min_x: float,
min_y: float,
max_x: float,
max_y: float,
) -> bool:
center_x = (min_x + max_x) * 0.5
center_y = (min_y + max_y) * 0.5
if point_in_polygon(center_x, center_y, polygon):
return True
corners = ((min_x, min_y), (max_x, min_y), (max_x, max_y), (min_x, max_y))
if any(point_in_polygon(x, y, polygon) for x, y in corners):
return True
if any(min_x <= x <= max_x and min_y <= y <= max_y for x, y in polygon):
return True
cell_edges = (
(min_x, min_y, max_x, min_y),
(max_x, min_y, max_x, max_y),
(max_x, max_y, min_x, max_y),
(min_x, max_y, min_x, min_y),
)
previous_x, previous_y = polygon[-1]
for current_x, current_y in polygon:
for edge in cell_edges:
if segments_intersect(previous_x, previous_y, current_x, current_y, *edge):
return True
previous_x, previous_y = current_x, current_y
return False
def grid_index(spec: GridSpec, x: float, y: float) -> tuple[int, int]:
column = math.floor((x - spec.min_x) / spec.cell_size)
row = math.floor((y - spec.min_y) / spec.cell_size)
return int(column), int(row)
def mark_cell(grid: list[list[str]], column: int, row: int, code: str) -> bool:
if row < 0 or row >= len(grid) or column < 0 or column >= len(grid[row]):
return False
if CATEGORY_PRIORITY[code] <= CATEGORY_PRIORITY[grid[row][column]]:
return False
grid[row][column] = code
return True
def iter_cells_for_polygon(spec: GridSpec, polygon: list[tuple[float, float]]) -> Iterable[tuple[int, int]]:
xs = [point[0] for point in polygon]
ys = [point[1] for point in polygon]
min_col, min_row = grid_index(spec, min(xs), min(ys))
max_col, max_row = grid_index(spec, max(xs), max(ys))
for row in range(max(0, min_row), min(spec.height - 1, max_row) + 1):
for column in range(max(0, min_col), min(spec.width - 1, max_col) + 1):
cell_min_x = spec.min_x + column * spec.cell_size
cell_min_y = spec.min_y + row * spec.cell_size
if polygon_intersects_cell(
polygon,
cell_min_x,
cell_min_y,
cell_min_x + spec.cell_size,
cell_min_y + spec.cell_size,
):
yield column, row
def build_grid(
lanes: list[dict[str, Any]],
polygons: list[list[tuple[float, float]]],
cell_size: float,
inflate_cells: int,
) -> tuple[GridSpec, list[list[str]], dict[str, int]]:
points = [point for polygon in polygons for point in polygon]
if not points:
raise ValueError("no polygon points found")
min_x = math.floor(min(point[0] for point in points) / cell_size) * cell_size
min_y = math.floor(min(point[1] for point in points) / cell_size) * cell_size
max_x = math.ceil(max(point[0] for point in points) / cell_size) * cell_size
max_y = math.ceil(max(point[1] for point in points) / cell_size) * cell_size
spec = GridSpec(
min_x=min_x,
min_y=min_y,
width=int(round((max_x - min_x) / cell_size)),
height=int(round((max_y - min_y) / cell_size)),
cell_size=cell_size,
)
grid = [[CATEGORY_CODES["unknown"] for _ in range(spec.width)] for _ in range(spec.height)]
for index, (lane, polygon) in enumerate(zip(lanes, polygons, strict=True)):
if len(polygon) < 3:
continue
code = CATEGORY_CODES[lane_category(flag_value(lane.get("flags", 0)))]
if code == CATEGORY_CODES["unknown"]:
continue
changed_cells: set[tuple[int, int]] = set()
for column, row in iter_cells_for_polygon(spec, polygon):
for dy in range(-inflate_cells, inflate_cells + 1):
for dx in range(-inflate_cells, inflate_cells + 1):
changed_cells.add((column + dx, row + dy))
for column, row in changed_cells:
mark_cell(grid, column, row, code)
counts = {code: sum(row.count(code) for row in grid) for code in CATEGORY_PRIORITY}
return spec, grid, counts
def write_header(path: Path, spec: GridSpec, grid: list[list[str]], counts: dict[str, int]) -> None:
lines = [
"#pragma once",
"",
"#include <array>",
"#include <cstdint>",
"#include <string_view>",
"",
"namespace EdgeWeightGPS::Generated",
"{",
f"constexpr float kSpatialRoadGridMinX = {spec.min_x:.1f}f;",
f"constexpr float kSpatialRoadGridMinY = {spec.min_y:.1f}f;",
f"constexpr float kSpatialRoadGridCellSize = {spec.cell_size:.1f}f;",
f"constexpr uint32_t kSpatialRoadGridWidth = {spec.width};",
f"constexpr uint32_t kSpatialRoadGridHeight = {spec.height};",
"",
"// Cell codes: H=highway, R=road, G=GPS-only, P=pavement, .=unknown.",
"// Generated by tools/generate_spatial_edge_grid.py from all.traffic_persistent and all.lane_polygons.",
f"// Counts: H={counts['H']} R={counts['R']} G={counts['G']} P={counts['P']} unknown={counts['.']}.",
"constexpr std::array<std::string_view, kSpatialRoadGridHeight> kSpatialRoadGridRows = {{",
]
for row in grid:
lines.append(f' "{("").join(row)}",')
lines.extend(
[
"}};",
"",
"} // namespace EdgeWeightGPS::Generated",
"",
]
)
path.write_text("\n".join(lines), encoding="utf-8")
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--traffic-json", type=Path, default=Path("work/raw-segment-json/all.traffic_persistent.json"))
parser.add_argument(
"--lane-polygons-json",
type=Path,
default=Path("work/traffic-companions/json/all.lane_polygons.json"),
)
parser.add_argument(
"--output",
type=Path,
default=Path("red4ext/EdgeWeightGPS/src/GeneratedSpatialRoadGrid.hpp"),
)
parser.add_argument("--cell-size", type=float, default=32.0)
parser.add_argument("--inflate-cells", type=int, default=1)
args = parser.parse_args()
lanes = load_lanes(args.traffic_json)
polygons = load_lane_polygons(args.lane_polygons_json)
if len(lanes) != len(polygons):
raise ValueError(f"lane/polygon count mismatch: {len(lanes)} != {len(polygons)}")
spec, grid, counts = build_grid(lanes, polygons, args.cell_size, args.inflate_cells)
args.output.parent.mkdir(parents=True, exist_ok=True)
write_header(args.output, spec, grid, counts)
total = spec.width * spec.height
covered = total - sum(row.count(".") for row in grid)
print(
f"wrote {args.output} cells={total} covered={covered} "
f"size={spec.width}x{spec.height} origin=({spec.min_x},{spec.min_y}) cell={spec.cell_size}"
)
print("counts " + " ".join(f"{code}={counts[code]}" for code in ("H", "R", "G", "P", ".")))
return 0
if __name__ == "__main__":
raise SystemExit(main())