fix(outages): do not space-pad ordinals in the portal LIKE pattern
likePattern padded every token containing a digit, including ordinals like "3-я". When the ordinal starts the address, " 3-я " never matches, so "3-я Механическая улица 24а" returned no outages. Pad only pure-numeric house tokens; precision is enforced by the local house filter regardless.
This commit is contained in:
@@ -220,24 +220,29 @@ func actionFor(system string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// likePattern builds the substring pattern the portal supports. Numeric tokens
|
// likePattern builds the substring pattern the portal supports. Only pure
|
||||||
// are padded with spaces, matching the historical integration, so that "1" does
|
// numeric tokens (house numbers) are padded with spaces, so "1" does not
|
||||||
// not incidentally match "10".
|
// incidentally match "10". Ordinals ("3-я") and houses with a letter ("24а")
|
||||||
|
// are left as-is: padding an ordinal breaks the match when it starts the
|
||||||
|
// string, and precision is guaranteed by the local house filter anyway.
|
||||||
func likePattern(canonical string) string {
|
func likePattern(canonical string) string {
|
||||||
parts := strings.Fields(canonical)
|
parts := strings.Fields(canonical)
|
||||||
for i, part := range parts {
|
for i, part := range parts {
|
||||||
if containsDigit(part) {
|
if isPureDigits(part) {
|
||||||
parts[i] = " " + part + " "
|
parts[i] = " " + part + " "
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "%" + strings.Join(parts, "%") + "%"
|
return "%" + strings.Join(parts, "%") + "%"
|
||||||
}
|
}
|
||||||
|
|
||||||
func containsDigit(s string) bool {
|
func isPureDigits(s string) bool {
|
||||||
for _, r := range s {
|
if s == "" {
|
||||||
if r >= '0' && r <= '9' {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
|
}
|
||||||
|
for _, r := range s {
|
||||||
|
if r < '0' || r > '9' {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -92,3 +93,18 @@ func TestQueryStripsDistrictSuffix(t *testing.T) {
|
|||||||
t.Errorf("house not parsed at the boundary: %+v", rows[0].Unit)
|
t.Errorf("house not parsed at the boundary: %+v", rows[0].Unit)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestLikePattern guards the ordinal/house padding rule: padding an ordinal
|
||||||
|
// that starts the string breaks the portal match.
|
||||||
|
func TestLikePattern(t *testing.T) {
|
||||||
|
got := likePattern("3-я Механическая улица 24а")
|
||||||
|
if strings.Contains(got, " 3-я ") {
|
||||||
|
t.Errorf("ordinal must not be space-padded: %q", got)
|
||||||
|
}
|
||||||
|
if strings.Contains(got, " 24а ") {
|
||||||
|
t.Errorf("house with a letter must not be space-padded: %q", got)
|
||||||
|
}
|
||||||
|
if !strings.Contains(likePattern("Ленина улица 1"), "% 1 %") {
|
||||||
|
t.Errorf("pure numeric house must be space-padded: %q", likePattern("Ленина улица 1"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user