Фабрика за регулярни изрази

Предадени решения

Краен срок:
31.12.2014 23:59
Точки:
10

Срокът за предаване на решения е отминал


В тази задача ще трябва да симулирате работата на фабрика за регулярни изрази. Всяка фабрика разполага с базови регулярни изрази, които ще наричаме матриали. Всяка фабрика има ограничено количество от материали и може конкурентно да получава поръчки от клиентите си. Поръчките се изпълняват конкурентно от работниците на фабриката. Всеки работник изпълнява само една поръчка в даден момент и всяка поръчка се изпълнява само веднъж и от точно един работник. Фабриката има фиксиран брой работници, който се задава при създаването ѝ.

Поръчките се изпълняват в реда, в който са били получени. След като завърши изпълнението на някоя от тях, то незабавно се връща резултат на клиента. Всяка поръчка има статус, който може да бъде проверяван по всяко време. Възможните статуси са:

const (
    DOES_NOT_EXIST = iota
    ENQUEUED
    IN_PROGRESS
    UNABLE_TO_PRODUCE
    DONE
)

Зa целта ще ви трябват следните типове и техните методи:

Поръчка

Поръчката съдържа множество от думи. При създаване на нова поръчка за нея се генерира уникален идентификационен номер. За да твърдим, че е изпълнена успешно е нужно да получим като резултат регулярен израз, който match-ва всяка една от думите в множеството. Всеки произведен регулярен израз трябва да започва с ^ и да завършва с $. Разполагате с неограничено количество и от двата символа и няма нужда да ги пазите в склад. Статусът на поръчката трябва да се държи актуален, което означава, че фабриката трябва да се грижи да го променя когато е необходимо.

type Order struct {
    Id      string
    Status  int //Състояние, което се обновява от фабриката
    Words   []string // Думи, за които трябва да бъде произведен
             // регулярен израз
    Result  string // Произведеният регулярен израз
    Channel chan *Order // Канал, по който да бъде върната
                // поръчката, когато бъде приключена
}

func NewOrder(words []string, channel chan *Order) *Order

Създава нова поръчка с подадените думи и канал. Тази функция трябва да генерира уникално Id.

Фабрика (type Factory)

Фабриката ще приема поръчки от клиентите, ще ги изпълнява и ще връща резултат щом приключи. При създаването се задава колко работници има, това е еквивалентно на броя поръчки, които могат да бъдат изпълнявани във всеки момент, тъй като един работник може да изпълнява само една поръчка в даден момент. Поръчка може да бъде изпълнена, ако фабриката разполага с необходимите материали, в противен случай се съобщава на клиента, че не може да бъде изпълнена. След изпълнението трябва материалите използвани за поръчката да бъдат изкарани от склада. Операциите за добавяне и премахване на материали трябва да бъдат "thread-safe".

func NewFactory(workers uint8) *Factory

Създава фабрика с подадения брой работници и започва да изпълнява поръчки.

func (f *Factory) Enqueue(order *Order)

Добавя поръчката в списъка на чакащите да бъдат изпълнени.

func (f *Factory) StartProducing()

Започва да изпълнява поръчки.

func (f *Factory) StopProducing()

Прекратява производството като изпълнява само поръчките със статус IN_PROGRESS.

func (f *Factory) StorageAdd(materials map[string]uint16)

Приема map с материал: количество и добавя съответните материали и техните количества в склада.

Пример:

materials := map[string]uint16{
    `[a-z0-9]{2,4}`: 3,
    `[aeouiy]`:      2,
}
factory.StorageAdd(materials)

func (f *Factory) generateRegexp(words []string) (string, error)

Генерира регулярен израз (или връща грешка при недостатъчно материали), който match-ва всички думи в слайса words. Върнатият регулярен израз трябва да започва с ^ и да завършва с $.

Клиент (type Client)

Клиентите изпращат поръчки към фабриката и чакат да получат резултат. Те могат да проверяват какво се случва с поръчките им във всеки момент.

type Client struct {
    Name    string
    Orders  map[string]*Order // Всички поръчки от този клиент
                  // където ключът е Order.Id
    Channel chan *Order // Канал, по който клиентът
                // получава поръчка в момента,
                // в който тя бъде приключена
}

func NewClient(name string) *Client

Създава нов клиент с подаденото име.

func (c *Client) Order(factory *Factory, words []string) string

Създава нова поръчка с думи, изпраща я на подадената фабрика и връща id-то на поръчката.

func (c *Client) CheckStatus(id string) int

Проверява статуса на клиентска поръчка с подаденото id.

Примери

factory := NewFactory(3)
factory.StorageAdd(map[string]uint16{
    `..2`:           1,
    `\w{3}`:         1,
    `bam`:           2,
    `che`:           1,
    `(kop|bob|top)`: 1,
})
client := NewClient("Robcho")
client.Order(factory, []string{"kopche", "bobche", "topche"})