Станимир обнови решението на 06.12.2015 17:07 (преди над 2 години)
+package main
+
+import "fmt"
+import "encoding/xml"
+import "encoding/json"
+import "errors"
+
+const (
+        _ = iota
+        BorrowBook
+        ReturnBook
+        GetAvailability
+)
+
+type Author struct {
+        First_name string `xml:"first_name"`
+        Last_name  string `xml:"last_name"`
+}
+
+func (author Author) ToString() string {
+        return author.First_name + " " + author.Last_name
+}
+
+type Book struct {
+        XMLNAME xml.Name `xml:"book"`
+        Isbn    string   `xml:"isbn,attr"`
+        Title   string   `xml:"title"`
+        Author  Author   `xml:"author"`
+        Genre   string   `xml:"genre"`
+        Pages   int      `xml:"pages"`
+        Ratings []int    `xml:"ratings>rating"`
+}
+
+// Връща "отворена" библиотека
+func NewLibrary(librarians int) Library {
+        var library Library
+        coll := make(map[string]*Book)
+        inv := make(map[string]*Record)
+        library = LocalLibrary{coll, librarians, inv}
+        return library
+}
+
+type Record struct {
+        total   int
+        current int
+}
+
+type LocalLibrary struct {
+        collection map[string]*Book
+        librarians int
+        inventar   map[string]*Record
+}
+
+func (library LocalLibrary) AddBook(book *Book) (int, error) {
+
+        if value, ok := library.inventar[book.Isbn]; ok {
+                if value.total > 3 {
+                        return value.total, errors.New(fmt.Sprintf("Има 4 копия на книга %s", book.Isbn))
+                } else {
+                        library.inventar[book.Isbn].total++
+                        library.inventar[book.Isbn].current++
+                }
+        }
+
+        if _, ok := library.inventar[book.Isbn]; !ok {
+                library.collection[book.Isbn] = book
+                library.inventar[book.Isbn] = &Record{1, 1}
+        }
+
+        return library.inventar[book.Isbn].total, nil
+}
+
+func (library LocalLibrary) AddBookJSON(data []byte) (int, error) {
+        var book Book
+        json.Unmarshal(data, &book)
+
+        return library.AddBook(&book)
+}
+
+func (library LocalLibrary) AddBookXML(data []byte) (int, error) {
+        var book Book
+        xml.Unmarshal(data, &book)
+
+        return library.AddBook(&book)
+}
+
+func (library LocalLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+        request := make(chan LibraryRequest)
+        response := make(chan LibraryResponse)
+        go func(req chan LibraryRequest, res chan LibraryResponse) {
+                var newreq LibraryRequest
+                newreq = <-req
+                switch {
+                case newreq.GetType() == BorrowBook:
+                        var asw LibraryResponse
+                        if val, ok := library.inventar[newreq.GetISBN()]; ok {
+                                book := library.collection[newreq.GetISBN()]
+                                if val.current != 0 {
+                                        library.inventar[newreq.GetISBN()].current--
+                                        asw = Response{
+                                                library.inventar[newreq.GetISBN()].total,
+                                                library.inventar[newreq.GetISBN()].current,
+                                                stringer{fmt.Sprintf("[%s] %s от %s",
+                                                        book.Isbn,
+                                                        book.Title,
+                                                        book.Author.ToString(),
+                                                )}, nil}
+                                } else {
+                                        asw = Response{
+                                                library.inventar[newreq.GetISBN()].total,
+                                                library.inventar[newreq.GetISBN()].current,
+                                                stringer{fmt.Sprintf("[%s] %s от %s",
+                                                        book.Isbn,
+                                                        book.Title,
+                                                        book.Author.ToString())},
+                                                errors.New(fmt.Sprintf("Няма наличност на книга %s)", book.Isbn)),
+                                        }
+                                }
+                        } else {
+                                asw = Response{0, 0, stringer{""},
+                                        errors.New(fmt.Sprintf("Непозната книга %s)", newreq.GetISBN()))}
+                        }
+                        res <- asw
+
+                case newreq.GetType() == ReturnBook:
+                        var asw LibraryResponse
+                        if _, ok := library.inventar[newreq.GetISBN()]; ok {
+                                library.inventar[newreq.GetISBN()].current++
+                                asw = Response{
+                                        library.inventar[newreq.GetISBN()].total,
+                                        library.inventar[newreq.GetISBN()].current,
+                                        stringer{""},
+                                        nil,
+                                }
+                        } else {
+                                asw = Response{0, 0, stringer{""},
+                                        errors.New(fmt.Sprintf("Непозната книга %s)", newreq.GetISBN())),
+                                }
+                        }
+                        res <- asw
+                case newreq.GetType() == GetAvailability:
+                        var asw LibraryResponse
+                        if _, ok := library.inventar[newreq.GetISBN()]; ok {
+                                book := library.collection[newreq.GetISBN()]
+                                library.inventar[newreq.GetISBN()].current++
+                                asw = Response{
+                                        library.inventar[newreq.GetISBN()].total,
+                                        library.inventar[newreq.GetISBN()].current,
+                                        stringer{fmt.Sprintf("[%s] %s от %s",
+                                                book.Isbn,
+                                                book.Title,
+                                                book.Author.ToString(),
+                                        )},
+                                        nil,
+                                }
+                        } else {
+                                asw = Response{0, 0, stringer{""},
+                                        errors.New(fmt.Sprintf("Непозната книга %s)", newreq.GetISBN())),
+                                }
+                        }
+                        res <- asw
+                }
+        }(request, response)
+        return request, response
+}
+
+type Library interface {
+
+        AddBookJSON(data []byte) (int, error)
+
+        AddBookXML(data []byte) (int, error)
+
+        Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
+}
+
+type Request struct {
+        Type int
+        Isbn string
+}
+
+func (rq Request) GetISBN() string {
+        return rq.Isbn
+}
+
+func (rq Request) SetIsbn(isbn string) {
+        rq.Isbn = isbn
+}
+
+type LibraryRequest interface {
+
+        GetType() int
+
+        GetISBN() string
+}
+
+type stringer struct {
+        data string
+}
+
+func (s stringer) String() string { return s.data }
+
+type Response struct {
+        registered, available int
+        bookInfo              stringer
+        err                   error
+}
+
+func (rp Response) GetBook() (fmt.Stringer, error) {
+        return rp.bookInfo, rp.err
+}
+
+func (rp Response) GetAvailability() (available int, registered int) {
+        return rp.available, rp.registered
+}
+
+type LibraryResponse interface {
+
+        GetBook() (fmt.Stringer, error)
+
+        GetAvailability() (available int, registered int)
+}
