Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changes added #169

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions distributor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package main

import (
"encoding/csv"
"fmt"
"os"
"strings"
)

type PermissionType int

const (
Include PermissionType = iota
Exclude
)

type Permission struct {
Type PermissionType
Region string
}

type Distributor struct {
Name string
Permissions []Permission
SubDistributors []*Distributor
}

var distributors map[string]*Distributor
var cityData map[string]City

type City struct {
Code string
ProvinceCode string
CountryCode string
CityName string
ProvinceName string
CountryName string
}

func loadCities() {
cityData = make(map[string]City)
file, err := os.Open("cities.csv")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()

reader := csv.NewReader(file)
_, _ = reader.Read() // Skip header row

for {
record, err := reader.Read()
if err != nil {
break
}
city := City{
Code: record[0],
ProvinceCode: record[1],
CountryCode: record[2],
CityName: record[3],
ProvinceName: record[4],
CountryName: record[5],
}
cityData[city.Code] = city
}
}

func createDistributor(name string) *Distributor {
if distributors == nil {
distributors = make(map[string]*Distributor)
}
distributor := &Distributor{Name: name}
distributors[name] = distributor
return distributor
}

func addPermissions(distributor *Distributor, permissionType PermissionType, regions []string) {
for _, region := range regions {
distributor.Permissions = append(distributor.Permissions, Permission{
Type: permissionType,
Region: strings.TrimSpace(region),
})
}
}

func linkDistributor(parentName, childName string) error {
parent, parentExists := distributors[parentName]
if !parentExists {
return fmt.Errorf("parent distributor %s does not exist", parentName)
}
child, childExists := distributors[childName]
if !childExists {
return fmt.Errorf("child distributor %s does not exist", childName)
}

// Validate that the child permissions are within the parent permissions
for _, childPerm := range child.Permissions {
if childPerm.Type == Include && isRegionExcluded(parent, childPerm.Region) {
return fmt.Errorf("cannot link %s to %s: %s is excluded in parent distributor", childName, parentName, childPerm.Region)
}
}

parent.SubDistributors = append(parent.SubDistributors, child)
fmt.Printf("Successfully linked %s to %s\n", childName, parentName)
return nil
}

func isRegionExcluded(distributor *Distributor, region string) bool {
for _, perm := range distributor.Permissions {
if perm.Type == Exclude && perm.Region == region {
return true
}
}
return false
}

// showPermissionsWithInheritance recursively collects permissions, including from parent distributors
// func showPermissionsWithInheritance(distributor *Distributor) {
// fmt.Printf("Permissions for %s:\n", distributor.Name)
// effectivePermissions := gatherEffectivePermissions(distributor)
// for _, perm := range effectivePermissions {
// prefix := "INCLUDE"
// if perm.Type == Exclude {
// prefix = "EXCLUDE"
// }
// fmt.Printf("%s: %s\n", prefix, perm.Region)
// }
// }

func gatherEffectivePermissions(distributor *Distributor) []Permission {
permissions := make([]Permission, 0)
visited := make(map[string]PermissionType)

// Recursive function to gather permissions from parent distributors only
var gatherFromParents func(d *Distributor)
gatherFromParents = func(d *Distributor) {
for _, perm := range d.Permissions {
// Apply exclusion if it overrides an existing include
if existingType, exists := visited[perm.Region]; !exists || (perm.Type == Exclude && existingType == Include) {
visited[perm.Region] = perm.Type
}
}
// Continue up the parent chain (don't include children)
for _, parent := range d.SubDistributors {
gatherFromParents(parent)
}
}

// Gather own and parent permissions (without children)
gatherFromParents(distributor)

// Convert map to Permission slice
for region, permType := range visited {
permissions = append(permissions, Permission{
Type: permType,
Region: region,
})
}

return permissions
}

func showEffectivePermissions(distributor *Distributor) {
effectivePermissions := gatherEffectivePermissions(distributor)
fmt.Printf("Permissions for %s:\n", distributor.Name)
for _, perm := range effectivePermissions {
prefix := "INCLUDE"
if perm.Type == Exclude {
prefix = "EXCLUDE"
}
fmt.Printf("%s: %s\n", prefix, perm.Region)
}
}
82 changes: 82 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package main

import (
"bufio"
"fmt"
"os"
"strings"
)

func main() {
loadCities()
reader := bufio.NewReader(os.Stdin)

for {
fmt.Println("\nSelect an option:")
fmt.Println("1) Create distributor")
fmt.Println("2) Add permission")
fmt.Println("3) Link distributor")
fmt.Println("4) Check permissions")
fmt.Println("5) Exit")
fmt.Print("Enter choice: ")
choice, _ := reader.ReadString('\n')
choice = strings.TrimSpace(choice)

switch choice {
case "1":
fmt.Print("Enter distributor name: ")
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
createDistributor(name)
case "2":
fmt.Print("Enter distributor name: ")
name, _ := reader.ReadString('\n')
name = strings.TrimSpace(name)
distributor := distributors[name]
if distributor == nil {
fmt.Println("Distributor not found.")
continue
}
fmt.Print("Enter permission type (include/exclude): ")
permTypeInput, _ := reader.ReadString('\n')
permTypeInput = strings.TrimSpace(strings.ToLower(permTypeInput))
var permType PermissionType
if permTypeInput == "include" {
permType = Include
} else if permTypeInput == "exclude" {
permType = Exclude
} else {
fmt.Println("Invalid permission type.")
continue
}
fmt.Print("Enter regions (comma-separated, e.g., INDIA, UNITEDSTATES): ")
regionsInput, _ := reader.ReadString('\n')
regions := strings.Split(regionsInput, ",")
addPermissions(distributor, permType, regions)
fmt.Printf("Permissions added to %s\n", distributor.Name)
case "3":
fmt.Print("Enter parent distributor: ")
parent, _ := reader.ReadString('\n')
fmt.Print("Enter child distributor: ")
child, _ := reader.ReadString('\n')
err := linkDistributor(strings.TrimSpace(parent), strings.TrimSpace(child))
if err != nil {
fmt.Println("Error:", err)
}
case "4":
fmt.Print("Enter distributor name to check: ")
name, _ := reader.ReadString('\n')
distributor := distributors[strings.TrimSpace(name)]
if distributor == nil {
fmt.Println("Distributor not found.")
continue
}
showEffectivePermissions(distributor)
case "5":
fmt.Println("Exiting.")
return
default:
fmt.Println("Invalid choice.")
}
}
}