Newer
Older
package address_utils
import (
"crypto/md5"
"fmt"
"gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/string_utils"
var southAfricaVariations = []string{
"ZA",
"South Africa",
"Suid-Afrika",
"Suid Afrika",
"Iningizimu Afrika",
"Mzantsi Afrika",
"Afrika Boroa",
"Africa Kusini",
}
Cornel Rautenbach
committed
type Province struct {
Names []string
DisplayName string
Cornel Rautenbach
committed
}
var Provinces = map[string]Province{
"EC": {
DisplayName: "Eastern Cape",
Cornel Rautenbach
committed
Names: []string{
"Eastern Cape",
"Eastern-Cape",
"Oos-Kaap",
"iPumalanga-Kapa",
"Kapa Bohlabela",
"Kapa Botjhabela",
"Kapa-Vuxa",
"Kapa Botlhaba",
"Kapa Vhubvaḓuvha",
"Mpuma-Koloni",
"Mpumalanga-Kapa",
"Mpumalanga-Koloni",
},
},
"FS": {
DisplayName: "Free State",
Cornel Rautenbach
committed
Names: []string{
"Free State",
"Freestate",
"Vrystaat",
"iFreyistata",
"Freistata",
"Foreisetata",
"Fureisitata",
"Freyistata",
"Fuleyisitata",
"Freyisitata",
},
},
"GP": {
DisplayName: "Gauteng",
Cornel Rautenbach
committed
Names: []string{
Cornel Rautenbach
committed
"Gauteng",
"iGauteng",
"Kgauteng",
"Rhawuti",
},
},
"KZN": {
DisplayName: "KwaZulu-Natal",
Cornel Rautenbach
committed
Names: []string{
Cornel Rautenbach
committed
"KwaZulu-Natal",
"KwaZulu Natal",
"iKwaZulu-Natal",
"GaZulu-Natala",
"Hazolo-Natala",
"KwaZulu-Natali",
"HaZulu-Natal",
"KwaZulu-Natala",
},
},
"LP": {
DisplayName: "Limpopo",
Cornel Rautenbach
committed
Names: []string{
Cornel Rautenbach
committed
"Limpopo",
"Vhembe",
},
},
"MP": {
DisplayName: "Mpumalanga",
Cornel Rautenbach
committed
Names: []string{
"Mpumalanga",
"iMpumalanga",
},
},
"NC": {
DisplayName: "Northern Cape",
Cornel Rautenbach
committed
Names: []string{
"Northern Cape",
"Northern-Cape",
"Noord-Kaap",
"Noord Kaap",
"iTlhagwini-Kapa",
"Kapa Leboya",
"Kapa-N'walungu",
"Kapa Bokone",
"Kapa Leboa",
"Kapa Devhula",
"Mntla-Koloni",
"Nyakatho-Kapa",
"Nyakatho-Koloni",
},
},
"NW": {
DisplayName: "North West",
Cornel Rautenbach
committed
Names: []string{
"North West",
"North-West",
"Noordwes",
"Noord-wes",
"iTlhagwini-Tjhingalanga",
"Lebowa Bodikela",
"Leboya Bophirima",
"Leboya le Bophirima",
"N'walungu-Vupeladyambu",
"Bokone Bophirima",
"Mntla-Ntshona",
"Nyakatho-Ntshonalanga",
},
},
"WC": {
DisplayName: "Western Cape",
Cornel Rautenbach
committed
Names: []string{
"Western Cape",
"Western-Cape",
"Wes-Kaap",
"Wes Kaap",
"iTjhingalanga-Kapa",
"Kapa Bodikela",
"Kapa Bophirimela",
"Kapa-Vupeladyambu",
"Kapa Bophirima",
"Kapa Vhukovhela",
"Ntshona-Koloni",
"Ntshonalanga-Kapa",
"Ntshonalanga-Koloni",
},
},
// MD5HashOfAddress m(E,L,L) - calculates and returns the MD5 hash of the entered address, lat and lng concatenated together. If lat and lng is blank, it is only the hash of the entered address
func MD5HashOfAddress(enteredAddress string, lat *float64, lng *float64, addressType *string) string {
valueToHash := enteredAddress
if lat != nil && lng != nil {
valueToHash += fmt.Sprintf(",%v,%v", *lat, *lng)
}
if addressType != nil && len(*addressType) > 0 && *addressType != "unknown" {
valueToHash += fmt.Sprintf(",%s", *addressType)
}
return fmt.Sprintf("%X", md5.Sum([]byte(valueToHash)))
}
// MD5HashOfLowerCaseEnteredAddress m(e) - calculates and returns the MD5 hash of a string after preparing the string properly.
func MD5HashOfLowerCaseEnteredAddress(enteredAddress string) string {
valueToHash := cleanLowerCaseAddress(enteredAddress)
return fmt.Sprintf("%X", md5.Sum([]byte(valueToHash)))
}
// cleanLowerCaseAddress makes the entered address lowercase, removes unwanted chars, strip street terms and removes all whitespace
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
func cleanLowerCaseAddress(enteredAddress string) string {
// Lowercase.
enteredAddress = strings.ToLower(enteredAddress)
// Remove unwanted characters.
enteredAddress = stripUnwantedCharacters(enteredAddress)
// Remove ave, str, etc.
enteredAddress = stripStreetTerms(enteredAddress)
// Remove all whitespace.
enteredAddress = string_utils.RemoveAllWhiteSpaces(enteredAddress)
return enteredAddress
}
func stripStreetTerms(s string) string {
terms := []string{
"ave",
"avenue",
"str",
"street",
"st",
"straat",
"lane",
"ln",
"laan",
"road",
"rd",
"boulevard",
"blvd",
"drive",
"drv",
"way",
"weg",
}
re := regexp.MustCompile(`\s+(` + strings.Join(terms, "|") + `)[\s]*`)
s = re.ReplaceAllString(s, "")
return s
}
func stripUnwantedCharacters(s string) string {
re := regexp.MustCompile(`[^\s\w,-]`)
s = re.ReplaceAllString(s, "")
return s
}
Cornel Rautenbach
committed
func CleanZone(countryToClean, zoneToClean *string) (newCountry, newZone *string) {
newCountry = countryToClean
Cornel Rautenbach
committed
for _, southAfricaVariation := range southAfricaVariations {
if countryToClean == nil || len(*countryToClean) == 0 || strings.ToLower(*countryToClean) == strings.ToLower(southAfricaVariation) {
Cornel Rautenbach
committed
defaultCountry := "South Africa"
Cornel Rautenbach
committed
newCountry = &defaultCountry
break
}
Cornel Rautenbach
committed
if *newCountry == "South Africa" && zoneToClean != nil {
zone := string_utils.RemoveAllWhiteSpaces(*zoneToClean)
for provinceCode, province := range Provinces {
Cornel Rautenbach
committed
for _, name := range province.Names {
if strings.ToLower(zone) == strings.ToLower(string_utils.RemoveAllWhiteSpaces(name)) ||
strings.ToLower(zone) == strings.ToLower(provinceCode) {
Cornel Rautenbach
committed
}
Cornel Rautenbach
committed
}
newZone = &zone
}
return
}
func IsProvince(address string) bool {
for provinceCode, province := range Provinces {
if strings.ToLower(address) == strings.ToLower(fmt.Sprintf("%v, South Africa", provinceCode)) {
if strings.ToLower(address) == strings.ToLower(fmt.Sprintf("%v, South Africa", province.DisplayName)) {
return true
}
for _, provinceName := range province.Names {
if strings.ToLower(address) == strings.ToLower(fmt.Sprintf("%v, South Africa", provinceName)) {
return true
}
}
func GetZoneDisplayName(zone string) string {
if province, ok := Provinces[zone]; ok {
return province.DisplayName
}
return zone
}
func GetDistanceInKmBetweenCoordinates(lat1 float64, lng1 float64, lat2 float64, lng2 float64) float64 {
radlat1 := float64(math.Pi * lat1 / 180)
radlat2 := float64(math.Pi * lat2 / 180)
theta := float64(lng1 - lng2)
radtheta := float64(math.Pi * theta / 180)
dist := math.Sin(radlat1)*math.Sin(radlat2) + math.Cos(radlat1)*math.Cos(radlat2)*math.Cos(radtheta)
if dist > 1 {
dist = 1
}
dist = math.Acos(dist)
dist = dist * 180 / math.Pi
dist = dist * 60 * 1.1515
// Return in kilometers
return dist * 1.609344
}