grokify/mogo

View on GitHub
strconv/phonenumber/phonenumber.go

Summary

Maintainability
A
0 mins
Test Coverage
package phonenumber

/*
import (
    "fmt"
    "io"
    "os"
    "path"
    "strconv"

    "github.com/grokify/mogo/encoding/csvutil"
    "github.com/grokify/mogo/sort/sortutil"
    geo "github.com/kellydunn/golang-geo"
)

const (
    A2gCsvRelPath = "github.com/grokify/mogo/strconv/phonenumber/us-area-code-geo.csv"
)

type AreaCodeInfo struct {
    AreaCode uint16
    Point    *geo.Point
}

// NewAreaCodeInfoStrings returns an AreaCodeInfo based on string area code,
// lat and lon values.
func NewAreaCodeInfoStrings(ac, lat, lon string) (AreaCodeInfo, error) {
    aci := AreaCodeInfo{}
    i, err := strconv.Atoi(ac)
    if err != nil {
        return aci, err
    }
    if i < 100 || i > 999 {
        return aci, fmt.Errorf("Invalid Area Code %v", i)
    }
    aci.AreaCode = uint16(i)
    geo, err := NewPointString(lat, lon)
    if err != nil {
        return aci, err
    }
    aci.Point = geo
    return aci, nil
}

// NewPointString returns a *geo.Point based on string lat and lon values.
func NewPointString(lat string, lon string) (*geo.Point, error) {
    f1, err := strconv.ParseFloat(lat, 64)
    if err != nil {
        return geo.NewPoint(0, 0), err
    }
    f2, err := strconv.ParseFloat(lon, 64)
    if err != nil {
        return geo.NewPoint(0, 0), err
    }
    return geo.NewPoint(f1, f2), nil
}

type AreaCodeToGeo struct {
    AreaCodeInfos  map[uint16]AreaCodeInfo
    DistanceMatrix map[uint16]map[uint16]float64
}

func NewAreaCodeToGeo() AreaCodeToGeo {
    return AreaCodeToGeo{AreaCodeInfos: map[uint16]AreaCodeInfo{}}
}

func (a2g *AreaCodeToGeo) ReadData() error {
    return a2g.ReadCsvPath(A2gCsvFullPath())
}

func (a2g *AreaCodeToGeo) ReadCsvPath(csvpath string) error {
    csv, file, err := csvutil.NewReaderFile(A2gCsvFullPath(), ',')
    if err != nil {
        return err
    }

    for {
        rec, errx := csv.Read()
        if errx == io.EOF {
            break
        } else if errx != nil {
            err = errx
            break
        } else if len(rec) != 3 {
            err = fmt.Errorf("Bad LatLon Data: %v\n", rec)
            break
        }
        aci, errx := NewAreaCodeInfoStrings(rec[0], rec[1], rec[2])
        if errx != nil {
            err = errx
            break
        }
        a2g.AreaCodeInfos[aci.AreaCode] = aci
    }
    file.Close()
    if err != nil {
        return err
    }
    a2g.Inflate()
    return nil
}

func (a2g *AreaCodeToGeo) AreaCodeSlice() []AreaCodeInfo {
    acSlice := []AreaCodeInfo{}
    for _, aci := range a2g.AreaCodeInfos {
        acSlice = append(acSlice, aci)
    }
    return acSlice
}

func (a2g *AreaCodeToGeo) AreaCodes() []uint16 {
    acSlice := []uint16{}
    for _, aci := range a2g.AreaCodeInfos {
        acSlice = append(acSlice, aci.AreaCode)
    }
    return acSlice
}

func (a2g *AreaCodeToGeo) AreaCodesSorted() []uint16 {
    acs := a2g.AreaCodes()
    sortutil.Uint16s(acs)
    return acs
}

func (a2g *AreaCodeToGeo) Inflate() {
    a2g.DistanceMatrix = a2g.GetDistanceMatrix()
}

func (a2g *AreaCodeToGeo) GetDistanceMatrix() map[uint16]map[uint16]float64 {
    acis := a2g.AreaCodeSlice()
    distanceMatrix := map[uint16]map[uint16]float64{}

    l := len(acis)
    for i := 0; i < l; i++ {
        for j := i + 1; j < l; j++ {
            ac1 := acis[i]
            ac2 := acis[j]
            gcd := ac1.Point.GreatCircleDistance(ac2.Point)
            if _, ok := distanceMatrix[ac1.AreaCode]; !ok {
                distanceMatrix[ac1.AreaCode] = map[uint16]float64{}
            }
            distanceMatrix[ac1.AreaCode][ac2.AreaCode] = gcd
            if _, ok := distanceMatrix[ac2.AreaCode]; !ok {
                distanceMatrix[ac2.AreaCode] = map[uint16]float64{}
            }
            distanceMatrix[ac2.AreaCode][ac1.AreaCode] = gcd
        }
    }
    return distanceMatrix
}

func (a2g *AreaCodeToGeo) GcdAreaCodes(ac1Int uint16, ac2Int uint16) (float64, error) {
    ac1, ok := a2g.AreaCodeInfos[ac1Int]
    if !ok {
        return 0, fmt.Errorf("AreaCode %v Not Found.", ac1Int)
    }
    ac2, ok := a2g.AreaCodeInfos[ac2Int]
    if !ok {
        return 0, fmt.Errorf("AreaCode %v Not Found.", ac2Int)
    }

    dist2 := ac1.Point.GreatCircleDistance(ac2.Point)
    return dist2, nil
}

// A2gCsvFullPath reads data from:
// https://github.com/ravisorg/Area-Code-Geolocation-Database
func A2gCsvFullPath() string {
    return path.Join(os.Getenv("GOPATH"), "src", A2gCsvRelPath)
}
*/