Станимир обнови решението на 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)
+}