Михаил обнови решението на 06.12.2015 14:48 (преди над 2 години)
+package solution
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "errors"
+ "fmt"
+ "sync"
+)
+
+type Library interface {
+ AddBookJSON(data []byte) (int, error)
+
+ AddBookXML(data []byte) (int, error)
+
+ Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
+}
+
+type LibraryRequest interface {
+ GetType() int
+
+ GetISBN() string
+}
+
+type LibraryResponse interface {
+ GetBook() (fmt.Stringer, error)
+
+ GetAvailability() (available int, registered int)
+}
+
+type Librarian struct {
+ input chan LibraryRequest
+ output chan LibraryResponse
+}
+
+func (l *Librarian) Animate(library *LibraryOfAlexandria, librarians chan Librarian) {
+ go func() {
+ for request := range l.input {
+ isbn := request.GetISBN()
+
+ response := new(Response)
+ switch request.GetType() {
+ case 1: // Borrow
+ if book, ok := library.Books[isbn]; !ok {
+ response.Err = errors.New("Непозната книга " + isbn)
+ } else if book.Available < 1 {
+ response.Err = errors.New("Няма наличност на книга " + isbn)
+ } else {
+ book.Available -= 1
+ }
+ case 2: // Return
+ if book, ok := library.Books[isbn]; !ok {
+ response.Err = errors.New("Непозната книга " + isbn)
+ } else if book.Available >= 4 {
+ response.Err = errors.New("Всички копия са налични " + isbn)
+ } else {
+ book.Available += 1
+ }
+ case 3: // Availability
+ if book, ok := library.Books[isbn]; !ok {
+ response.Err = errors.New("Непозната книга " + isbn)
+ } else if book.Available >= 4 {
+ response.Err = errors.New("Всички копия са налични " + isbn)
+ }
+ }
+
+ if book, ok := library.Books[isbn]; ok {
+ response.Book = book.Book
+ response.Available = book.Available
+ response.All = book.All
+ } else {
+ response.All = 0
+ response.Available = 0
+ }
+
+ l.output <- response
+ }
+
+ l.input = make(chan LibraryRequest)
+ librarians <- *l
+ }()
+}
+
+type BookCopies struct {
+ Book
+ Available, All int
+}
+
+type LibraryOfAlexandria struct {
+ Books map[string]*BookCopies
+ booksLock sync.Mutex
+ librarians chan Librarian
+}
+
+func (lib LibraryOfAlexandria) AddBookJSON(data []byte) (int, error) {
+ var book Book
+ if err := json.Unmarshal(data, &book); err != nil {
+ return 0, err
+ }
+
+ return lib.addBook(book)
+}
+
+func (lib LibraryOfAlexandria) AddBookXML(data []byte) (int, error) {
+ var book Book
+ if err := xml.Unmarshal(data, &book); err != nil {
+ return 0, err
+ }
+
+ return lib.addBook(book)
+}
+
+func (lib *LibraryOfAlexandria) addBook(book Book) (int, error) {
+ lib.booksLock.Lock()
+
+ if lib.Books[book.ISBN] == nil {
+ lib.Books[book.ISBN] = new(BookCopies)
+ lib.Books[book.ISBN].Book = book
+ } else if lib.Books[book.ISBN].All >= 4 {
+ return 0, errors.New("Има 4 копия на книга " + book.ISBN)
+ }
+
+ lib.Books[book.ISBN].Available += 1
+ lib.Books[book.ISBN].All += 1
+
+ lib.booksLock.Unlock()
+
+ return lib.Books[book.ISBN].All, nil
+}
+
+func (lib LibraryOfAlexandria) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+ var librarian Librarian
+ var ok bool
+ // try take from the pool until we get a librarian
+ for librarian, ok = <-lib.librarians; !ok; {
+ }
+
+ return librarian.input, librarian.output
+}
+
+type Request struct {
+ RequestType int
+ Book
+}
+
+func (req Request) GetType() int {
+ return req.RequestType
+}
+
+func (req Request) GetISBN() string {
+ return req.ISBN
+}
+
+type Response struct {
+ Book
+ Err error
+ Available, All int
+}
+
+func (res *Response) GetBook() (fmt.Stringer, error) {
+ return res.Book, res.Err
+}
+
+func (res *Response) GetAvailability() (available int, registered int) {
+ return res.Available, res.All
+}
+
+type Author struct {
+ FirstName string `json:"first_name" xml:"author>first_name"`
+ LastName string `json:"last_name" xml:"author>last_name"`
+}
+
+type Book struct {
+ ISBN string `xml:"isbn,attr"`
+ Title string `xml:"title"`
+ Author `json:"author"`
+ Ratings []int
+}
+
+func (b Book) String() string {
+ return fmt.Sprintf("[%s] %s от %s %s", b.ISBN, b.Title, b.Author.FirstName, b.Author.LastName)
+}
+
+func NewLibrary(librarians int) LibraryOfAlexandria {
+ library := &LibraryOfAlexandria{Books: make(map[string]*BookCopies), librarians: make(chan Librarian, librarians)}
+
+ for i := 0; i < librarians; i++ {
+ librarian := &Librarian{input: make(chan LibraryRequest), output: make(chan LibraryResponse)}
+ library.librarians <- *librarian
+ librarian.Animate(library, library.librarians)
+ }
+
+ return *library
+}
пакета ти трябва да е main не solution