Skip to content

Solution #187

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

Open
wants to merge 2 commits 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
125 changes: 99 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,114 @@
# Real Image Challenge 2016
# Distributor Permission Tool - Instructions

In the cinema business, a feature film is usually provided to a regional distributor based on a contract for exhibition in a particular geographical territory.
This tool allows you to manage distributors and their regional permissions via a command-line interface.

Each authorization is specified by a combination of included and excluded regions. For example, a distributor might be authorzied in the following manner:
## Commands and Their Functionality

### 1. Creating a New Distributor
**Command:**
```sh
make <distributor_name>
```
Permissions for DISTRIBUTOR1
INCLUDE: INDIA
INCLUDE: UNITEDSTATES
EXCLUDE: KARNATAKA-INDIA
EXCLUDE: CHENNAI-TAMILNADU-INDIA
**Example:**
```sh
make a
```
This allows `DISTRIBUTOR1` to distribute in any city inside the United States and India, *except* cities in the state of Karnataka (in India) and the city of Chennai (in Tamil Nadu, India).

At this point, asking your program if `DISTRIBUTOR1` has permission to distribute in `CHICAGO-ILLINOIS-UNITEDSTATES` should get `YES` as the answer, and asking if distribution can happen in `CHENNAI-TAMILNADU-INDIA` should of course be `NO`. Asking if distribution is possible in `BANGALORE-KARNATAKA-INDIA` should also be `NO`, because the whole state of Karnataka has been excluded.

Sometimes, a distributor might split the work of distribution amount smaller sub-distiributors inside their authorized geographies. For instance, `DISTRIBUTOR1` might assign the following permissions to `DISTRIBUTOR2`:
**Functionality:**
- Creates a new distributor named `a`.
- If the distributor already exists, an error message is displayed.

### 2. Creating a Distributor with a Parent
**Command:**
```sh
make <child_distributor> < parent_distributor
```
Permissions for DISTRIBUTOR2 < DISTRIBUTOR1
INCLUDE: INDIA
EXCLUDE: TAMILNADU-INDIA
**Example:**
```sh
make b < a
```
Now, `DISTRIBUTOR2` can distribute the movie anywhere in `INDIA`, except inside `TAMILNADU-INDIA` and `KARNATAKA-INDIA` - `DISTRIBUTOR2`'s permissions are always a subset of `DISTRIBUTOR1`'s permissions. It's impossible/invalid for `DISTRIBUTOR2` to have `INCLUDE: CHINA`, for example, because `DISTRIBUTOR1` isn't authorized to do that in the first place.
**Functionality:**
- Creates a new distributor `b` and assigns `a` as its parent.
- If the parent does not exist, an error message is displayed.
- If the child distributor already exists, an error message is displayed.

If `DISTRIBUTOR2` authorizes `DISTRIBUTOR3` to handle just the city of Hubli, Karnataka, India, for example:
### 3. Adding an Include Permission
**Command:**
```sh
for <distributor_name> include <place_code>,...
```
Permissions for DISTRIBUTOR3 < DISTRIBUTOR2 < DISTRIBUTOR1
INCLUDE: HUBLI-KARNATAKA-INDIA
**Example:**
```sh
for a include IN
for a include IN,US
```
Again, `DISTRIBUTOR2` cannot authorize `DISTRIBUTOR3` with a region that they themselves do not have access to.
**Functionality:**
- Grants `a` access to `IN` (India) in first example.
- Use , for multiple code
- If the distributor does not exist, an error message is displayed.

We've provided a CSV with the list of all countries, states and cities in the world that we know of - please use the data mentioned there for this program. *The codes you see there may be different from what you see here, so please always use the codes in the CSV*. This Readme is only an example.

Write a program in any language you want (If you're here from Gophercon, use Go :D) that does this. Feel free to make your own input and output format / command line tool / GUI / Webservice / whatever you want. Feel free to hold the dataset in whatever structure you want, but try not to use external databases - as far as possible stick to your langauage without bringing in MySQL/Postgres/MongoDB/Redis/Etc.
### 4. Adding an Exclude Permission
**Command:**
```sh
for <distributor_name> exclude <place_code>,...
```
**Example:**
```sh
for a exclude AR-IN
for a exclude AR-IN,US
```
**Functionality:**
- Revokes access to `AR-IN` (Arunachal Pradesh, India) for `a` in first example.
- Use , for multiple code
- If the distributor does not exist, an error message is displayed.

To submit a solution, fork this repo and send a Pull Request on Github.
### 5. Listing Permissions
**Command:**
```sh
for <distributor_name> list
```
**Example:**
```sh
for a list
```
**Functionality:**
- Displays the include and exclude permissions for `a`.
- If the distributor does not exist, an error message is displayed.

For any questions or clarifications, raise an issue on this repo and we'll answer your questions as fast as we can.
### 6. Exiting the CLI
**Command:**
```sh
exit
```
**Functionality:**
- Terminates the CLI tool.

## Notes
- `place_code` can be:
- `CountryCode` (e.g., `IN` for India)
- `ProvinceCode-CountryCode` (e.g., `UP-IN` for Uttar Pradesh, India)
- `CityCode-ProvinceCode-CountryCode` (e.g., `ZAIDR-UP-IN` for a specific city in Uttar Pradesh, India)

## Example Workflow
```sh
make a
for a include IN
for a exclude AR-IN
make b < a
for a list
for b list
exit
```
### Expected Output:
```
Created distributor: a
a now includes IN
a now excludes AR-IN
Created distributor: b with parent: a
Permissions for a:
Includes: map[IN:true]
Excludes: map[AR-IN:true]
Permissions for b:
Includes: map[]
Excludes: map[]
Exiting CLI...
```
122 changes: 122 additions & 0 deletions app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package main

import "fmt"

func (app *App) New_Distributor(name string) error {
_, distrubutor_exist := app.Distributors[name]
if distrubutor_exist {
err := fmt.Errorf("distributor %v already exits", name)
return err
}

app.Distributors[name] = Distributor{
Name: name,
IncludeRegions: make(map[string]bool),
ExcludeRegions: make(map[string]bool),
Parent: nil,
}
fmt.Printf("%v addedd successfull\n", name)
return nil
}

func (app *App) Include_Permissions(name string, place_code string) error {
distributor, exist := app.Distributors[name]
if !exist {
err := fmt.Errorf("no distrubutor with name %v", name)
return err
}

is_place := app.Places.Place_Exist(place_code)
if !is_place {
err := fmt.Errorf("invalid place code: %v", place_code)
return err
}

if distributor.Parent != nil {
if !distributor.Parent.Has_Permission(place_code) {
err := fmt.Errorf("parent distrubutor has not the permissions")
return err
}
}

_, exist = distributor.ExcludeRegions[place_code]
if exist {
delete(distributor.ExcludeRegions, place_code)
}

distributor.IncludeRegions[place_code] = true
fmt.Println("added permissions to ", name)
return nil
}

func (app *App) Exclude_Permissions(name, place_code string) error {
d, exist := app.Distributors[name]
if !exist {
err := fmt.Errorf("no distrubutor with name %v", name)
return err
}

if !app.Places.Place_Exist(place_code) {
err := fmt.Errorf("invalid place code: %v", place_code)
return err
}

_, exist = d.IncludeRegions[place_code]
if exist {
delete(d.IncludeRegions, place_code)
}

_, exist = d.ExcludeRegions[place_code]
if !exist {
d.ExcludeRegions[place_code] = true
}
fmt.Println("added exlcude permissions to ", name)
return nil
}

func (app *App) New_Dist_With_Parent(parent_name, name string) error {
parent_dist, parent_exist := app.Distributors[parent_name]
if !parent_exist {
err := fmt.Errorf("distributor %v does not exits", parent_name)
return err
}

dist, dist_exist := app.Distributors[name]
if dist_exist {
if dist.Parent != nil {
err := fmt.Errorf("%v already has a parent", name)
return err
}
dist.Parent = &parent_dist
fmt.Printf("%v addedd successfull", name)
return nil
}

app.Distributors[name] = Distributor{
Name: name,
IncludeRegions: make(map[string]bool),
ExcludeRegions: make(map[string]bool),
Parent: &parent_dist,
}
fmt.Printf("%v addedd successfull\n", name)
return nil
}

func (app *App) Get_Permissions(name string) error {
dist, e := app.Distributors[name]
if !e {
err := fmt.Errorf("no distributor with name: %v", name)
return err
}

fmt.Println("INCLUDE")
for k := range dist.IncludeRegions {
app.Places.Get_Name_From_Codes(k)
}
fmt.Println("==============================")
fmt.Println("EXCLUDE")
for k := range dist.ExcludeRegions {
app.Places.Get_Name_From_Codes(k)
}
return nil
}
68 changes: 68 additions & 0 deletions distributor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package main

import (
"strings"
)

type Distributor struct {
Name string
IncludeRegions map[string]bool
ExcludeRegions map[string]bool
Parent *Distributor
}

func (d *Distributor) Has_Permission(place_code string) bool {
// exact code in exlude map
_, exclude_exist := d.ExcludeRegions[place_code]
if exclude_exist {
return false
}

codes := strings.Split(place_code, "-")

switch len(codes) {
case 1:
_, include_exist := d.IncludeRegions[codes[0]]
// _, e_exist := d.ExcludeRegions[codes[0]] // this case redundant when providing only country code
return include_exist

case 2:
province_code := codes[0] + "-" + codes[1]
county_code := codes[1]
_, inlude_exist := d.IncludeRegions[province_code]
if inlude_exist {
return true
}
_, include_country_exist := d.IncludeRegions[county_code]
_, exclude_province_exist := d.ExcludeRegions[province_code]

if include_country_exist {
return !exclude_province_exist
}
return false

case 3:
_, include_city_exist := d.IncludeRegions[place_code]
if include_city_exist {
return true
}

province_code := codes[1] + "-" + codes[2]
_, include_province_exist := d.IncludeRegions[province_code]
_, exclude_city_exist := d.ExcludeRegions[place_code]
if include_province_exist {
return !exclude_city_exist
}

country_code := codes[2]
_, include_country_exist := d.IncludeRegions[country_code]
_, exclude_province_exist := d.ExcludeRegions[province_code]
if include_country_exist {
return !exclude_province_exist
}

default:
return false
}
return false
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module rajma

go 1.23.4
Loading