diff --git a/go.mod b/go.mod new file mode 100644 index 000000000..9ef846e37 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module Distributors + +go 1.22.0 diff --git a/main.go b/main.go new file mode 100644 index 000000000..a3e59fa26 --- /dev/null +++ b/main.go @@ -0,0 +1,151 @@ +package main + +import ( + "encoding/csv" + "fmt" + "log" + "os" + "strings" +) + +type Distributors struct { + Include map[string]bool + Exclude map[string]bool + Parent *Distributors +} + +func MakeCorrect(loc string) string { + return strings.ToUpper(strings.TrimSpace(loc)) +} + +func getHairarchy(loc string) []string { + parts := strings.Split(loc, "-") + var heir []string + for i := len(parts); i > 0; i-- { + heir = append(heir, strings.Join(parts[len(parts)-i:], "-")) + } + return heir +} + +func (d *Distributors) isIncluded(loc string) bool { + for _, part := range getHairarchy(loc) { + if d.Include[part] { + return true + } + } + return false +} + +func (d *Distributors) isExcluded(loc string) bool { + for _, part := range getHairarchy(loc) { + if d.Exclude[part] { + return true + } + } + return false +} + +func (d *Distributors) AddPermission(include, exclude []string) { + for _, loc := range include { + normLoc := MakeCorrect(loc) + + if d.Parent != nil && d.Parent.isExcluded(normLoc) { + fmt.Printf("Error: cant add %s coz parent excluded it\n", loc) + continue + } + + d.Include[normLoc] = true + } + + for _, loc := range exclude { + d.Exclude[MakeCorrect(loc)] = true + } +} + +func (d *Distributors) CanDistribute(loc string) bool { + normloc := MakeCorrect(loc) + + if d.Parent != nil && !d.Parent.CanDistribute(loc) { + return false + } + + if d.isExcluded(normloc) { + return false + } + + if d.isIncluded(normloc) { + return true + } + + if d.Parent == nil { + return false + } + + return d.Parent.CanDistribute(loc) +} + +func loadCSVData(filePath string) map[string]string { + file, err := os.Open(filePath) + if err != nil { + log.Fatal("failed to open csv:", err) + } + defer file.Close() + + reader := csv.NewReader(file) + records, err := reader.ReadAll() + if err != nil { + log.Fatal("failed to read csv:", err) + } + + cityMap := make(map[string]string) + for _, record := range records[1:] { + cityCode := MakeCorrect(record[0]) + provCode := MakeCorrect(record[1]) + countryCode := MakeCorrect(record[2]) + cityName := record[3] + fullCode := fmt.Sprintf("%s-%s-%s", cityCode, provCode, countryCode) + cityMap[cityName] = fullCode + } + return cityMap +} + +func main() { + cityMap := loadCSVData("cities.csv") + + d1 := &Distributors{Include: make(map[string]bool), Exclude: make(map[string]bool)} + d1.AddPermission( + []string{"IN", "CA"}, + []string{"KA-IN", "KLRAI-TN-IN"}, + ) + + d2 := &Distributors{Include: make(map[string]bool), Exclude: make(map[string]bool), Parent: d1} + d2.AddPermission( + []string{"IN"}, + []string{"TN-IN"}, + ) + + d3 := &Distributors{Include: make(map[string]bool), Exclude: make(map[string]bool), Parent: d2} + d3.AddPermission(nil, nil) + + testCities := []string{"Wellington", "Keelakarai", "Chennai", "Punch"} + + for _, city := range testCities { + code, ok := cityMap[city] + if !ok { + fmt.Printf("City %s not found in csv :( \n", city) + continue + } + + fmt.Printf("\nChecking for city: %s (%s)\n", city, code) + fmt.Printf("DISTRIBUTOR 1: %s\n", result(d1.CanDistribute(code))) + fmt.Printf("DISTRIBUTOR 2: %s\n", result(d2.CanDistribute(code))) + fmt.Printf("DISTRIBUTOR 3: %s\n", result(d3.CanDistribute(code))) + } +} + +func result(can bool) string { + if can { + return "YES......... :)" + } + return "No......... :(" +}