Решение на Concurrent Tasks от Диана Генева

Обратно към всички решения

Към профила на Диана Генева

Резултати

  • 10 точки от тестове
  • 0 бонус точки
  • 10 точки общо
  • 10 успешни тест(а)
  • 0 неуспешни тест(а)

Код

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
const (
_ = iota
TakeBook
ReturnBook
CheckAvailability
)
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 TheLibraryRequest struct {
Isbn string
Type int
}
func (t TheLibraryRequest) GetType() int {
return t.Type
}
func (t TheLibraryRequest) GetISBN() string {
return t.Isbn
}
type LibraryResponse interface {
GetBook() (fmt.Stringer, error)
GetAvailability() (available int, registered int)
}
type TheLibraryResponse struct {
book *Book
isbn string
err error
availableNumber, registeredNumber int
}
func (t TheLibraryResponse) GetBook() (fmt.Stringer, error) {
if t.book == nil {
return t.book, fmt.Errorf("Непозната книга %s", t.isbn)
}
return t.book, t.err
}
func (t TheLibraryResponse) GetAvailability() (available int, registered int) {
if t.book == nil {
return 0, 0
}
return t.availableNumber, t.registeredNumber
}
type AuthorName struct {
XMLName xml.Name `xml:"author"`
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
func (a *AuthorName) String() string {
return a.FirstName + " " + a.LastName
}
type Book struct {
XMLName xml.Name `xml:"book"`
Isbn string `xml:"isbn,attr" json:"isbn"`
Author *AuthorName `json:"author"`
Title string `json:"title" xml:"title"`
Ratings []int `json:"rating" xml:"ratings>rating"`
}
func newBook() *Book {
return &Book{Ratings: make([]int, 0)}
}
func (b *Book) String() string {
return fmt.Sprintf("[%s] %s от %s", b.Isbn, b.Title, b.Author)
}
type TheLibrary struct {
books *[]*Book
AvailableBooks map[string]int
librarians int
BorrowedBooks map[string]int
locker chan struct{}
}
func (l TheLibrary) GetBook(isbn string) *Book {
for _, book := range *l.books {
if book.Isbn == isbn {
return book
}
}
return nil
}
func (l TheLibrary) AddBook(data []byte, unmarshal func([]byte, interface{}) error) (int, error) {
l.locker <- struct{}{}
var newBook Book
err := unmarshal(data, &newBook)
if err != nil {
<-l.locker
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], err
}
*l.books = append(*l.books, &newBook)
if l.AvailableBooks[newBook.Isbn]+l.BorrowedBooks[newBook.Isbn] < 4 {
l.AvailableBooks[newBook.Isbn]++
<-l.locker
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], nil
}
<-l.locker
return 4, fmt.Errorf("Има 4 копия на книга %s", newBook.Isbn)
}
func (l TheLibrary) AddBookJSON(data []byte) (int, error) {
return l.AddBook(data, json.Unmarshal)
}
func (l TheLibrary) AddBookXML(data []byte) (int, error) {
return l.AddBook(data, xml.Unmarshal)
}
func (l TheLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
resChannel := make(chan LibraryResponse)
reqChannel := make(chan LibraryRequest)
for i := 0; i < l.librarians; i++ {
go l.HandleRequest(reqChannel, resChannel)
}
return reqChannel, resChannel
}
func (l TheLibrary) HandleRequest(reqChannel chan LibraryRequest, resChannel chan LibraryResponse) {
for request := range reqChannel {
l.locker <- struct{}{}
isbn := request.GetISBN()
response := TheLibraryResponse{book: l.GetBook(isbn), isbn: isbn}
switch request.GetType() {
case TakeBook:
if l.AvailableBooks[isbn] > 0 {
l.AvailableBooks[isbn]--
l.BorrowedBooks[isbn]++
response.err = nil
} else {
response.err = fmt.Errorf("Няма наличност на книга %s", isbn)
}
case ReturnBook:
if l.AvailableBooks[isbn] == 4 {
response.err = fmt.Errorf("Всички копия са налични %s", isbn)
} else {
l.AvailableBooks[isbn]++
l.BorrowedBooks[isbn]--
response.err = nil
}
case CheckAvailability:
response.err = nil
}
response.availableNumber = l.AvailableBooks[isbn]
response.registeredNumber = l.AvailableBooks[isbn] + l.BorrowedBooks[isbn]
<-l.locker
resChannel <- response
}
}
func NewLibrary(librarians int) Library {
var books []*Book
return TheLibrary{librarians: librarians,
books: &books, BorrowedBooks: make(map[string]int),
AvailableBooks: make(map[string]int),
locker: make(chan struct{}, 1),
}
}

Лог от изпълнението

PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.003s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.003s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s
PASS
ok  	_/tmp/d20151207-5667-fpt2nr	0.004s

История (4 версии и 2 коментара)

Диана обнови решението на 03.12.2015 20:37 (преди над 2 години)

+package main
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "fmt"
+)
+
+const (
+ _ = iota
+ TakeBook
+ ReturnBook
+ CheckAvailability
+)
+
+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 TheLibraryRequest struct {
+ Isbn string
+ Type int
+}
+
+func (t TheLibraryRequest) GetType() int {
+ return t.Type
+}
+
+func (t TheLibraryRequest) GetISBN() string {
+ return t.Isbn
+}
+
+type LibraryResponse interface {
+ GetBook() (fmt.Stringer, error)
+ GetAvailability() (available int, registered int)
+}
+
+type TheLibraryResponse struct {
+ book *Book
+ isbn string
+ err error
+ availableNumber, registeredNumber int
+}
+
+func (t TheLibraryResponse) GetBook() (fmt.Stringer, error) {
+ if t.book == nil {
+ return t.book, fmt.Errorf("Непозната книга %s", t.isbn)
+ }
+ return t.book, t.err
+}
+
+func (t TheLibraryResponse) GetAvailability() (available int, registered int) {
+ return t.availableNumber, t.registeredNumber
+}
+
+type AuthorName struct {
+ XMLName xml.Name `xml:"author"`
+ FirstName string `json:"first_name" xml:"first_name"`
+ LastName string `json:"last_name" xml:"last_name"`
+}
+
+func (a *AuthorName) String() string {
+ return a.FirstName + " " + a.LastName
+}
+
+type Book struct {
+ XMLName xml.Name `xml:"book"`
+ Isbn string `xml:"isbn,attr" json:"isbn"`
+ Author *AuthorName `json:"author"`
+ Title string `json:"title" xml:"title"`
+ Ratings []int `json:"rating" xml:"ratings>rating"`
+}
+
+func newBook() *Book {
+ return &Book{Ratings: make([]int, 0)}
+}
+
+func (b *Book) String() string {
+ return fmt.Sprintf("[%s] %s от %s", b.Isbn, b.Title, b.Author)
+}
+
+type TheLibrary struct {
+ books *[]*Book
+ AvailableBooks map[string]int
+ librarians int
+ BorrowedBooks map[string]int
+}
+
+func (l TheLibrary) GetBook(isbn string) *Book {
+ for _, book := range *l.books {
+ if book.Isbn == isbn {
+ return book
+ }
+ }
+ return nil
+}
+
+func (l TheLibrary) AddBook(data []byte, unmarshal func([]byte, interface{}) error) (int, error) {
+ var newBook Book
+ err := unmarshal(data, &newBook)
+ if err != nil {
+ return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], err
+ }
+ *l.books = append(*l.books, &newBook)
+ if l.AvailableBooks[newBook.Isbn]+l.BorrowedBooks[newBook.Isbn] < 4 {
+ l.AvailableBooks[newBook.Isbn]++
+ return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], nil
+ }
+ return 4, fmt.Errorf("Има 4 копия на книга %s", newBook.Isbn)
+}
+
+func (l TheLibrary) AddBookJSON(data []byte) (int, error) {
+ return l.AddBook(data, json.Unmarshal)
+}
+
+func (l TheLibrary) AddBookXML(data []byte) (int, error) {
+ return l.AddBook(data, xml.Unmarshal)
+}
+
+func (l TheLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+ resChannel := make(chan LibraryResponse)
+ reqChannel := make(chan LibraryRequest)
+ for i := 0; i < l.librarians; i++ {
+ go l.HandleRequest(reqChannel, resChannel)
+ }
+ return reqChannel, resChannel
+}
+
+func (l TheLibrary) HandleRequest(reqChannel chan LibraryRequest, resChannel chan LibraryResponse) {
+ for request := range reqChannel {
+ isbn := request.GetISBN()
+ switch request.GetType() {
+ case TakeBook:
+ if l.AvailableBooks[isbn] > 0 {
+ l.AvailableBooks[isbn]--
+ l.BorrowedBooks[isbn]++
+ resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
+ isbn: isbn, availableNumber: l.AvailableBooks[isbn],
+ registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
+ err: nil,
+ }
+ } else {
+ resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
+ isbn: isbn, availableNumber: l.AvailableBooks[isbn],
+ registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
+ err: fmt.Errorf("Няма наличност на книга %s", isbn),
+ }
+ }
+
+ case ReturnBook:
+ if l.AvailableBooks[isbn]+l.BorrowedBooks[isbn] == 4 {
+ resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
+ isbn: isbn, availableNumber: l.AvailableBooks[isbn],
+ registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
+ err: fmt.Errorf("Всички копия са налични %s", isbn),
+ }
+ } else {
+ l.AvailableBooks[isbn]++
+ l.BorrowedBooks[isbn]--
+ resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
+ isbn: isbn, availableNumber: l.AvailableBooks[isbn],
+ registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
+ err: nil,
+ }
+ }
+ case CheckAvailability:
+ resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
+ isbn: isbn, availableNumber: l.AvailableBooks[isbn],
+ registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
+ err: nil,
+ }
+ }
+ }
+}
+
+func NewLibrary(librarians int) Library {
+ var books []*Book
+ return TheLibrary{librarians: librarians, books: &books, BorrowedBooks: make(map[string]int), AvailableBooks: make(map[string]int)}
+}
+
+func main() {
+ library := NewLibrary(5)
+ for i := 0; i < 5; i++ {
+ library.AddBookXML([]byte(`
+<book isbn="0954540018">
+<title>Who said the race is Over?</title>
+<author>
+<first_name>Anno</first_name>
+<last_name>Birkin</last_name>
+</author>
+<genre>poetry</genre>
+<pages>80</pages>
+<ratings>
+<rating>5</rating>
+<rating>4</rating>
+<rating>4</rating>
+<rating>5</rating>
+<rating>3</rating>
+</ratings>
+</book>
+`))
+ }
+
+ requests, responses := library.Hello()
+
+ go func() {
+ requests <- TheLibraryRequest{Type: 1, Isbn: "0954540018"}
+ }()
+ response := <-responses
+ a, b := response.GetAvailability()
+ fmt.Printf("A: %d, B: %d\n", a, b)
+}

Диана обнови решението на 03.12.2015 20:37 (преди над 2 години)

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
const (
_ = iota
TakeBook
ReturnBook
CheckAvailability
)
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 TheLibraryRequest struct {
Isbn string
Type int
}
func (t TheLibraryRequest) GetType() int {
return t.Type
}
func (t TheLibraryRequest) GetISBN() string {
return t.Isbn
}
type LibraryResponse interface {
GetBook() (fmt.Stringer, error)
GetAvailability() (available int, registered int)
}
type TheLibraryResponse struct {
book *Book
isbn string
err error
availableNumber, registeredNumber int
}
func (t TheLibraryResponse) GetBook() (fmt.Stringer, error) {
if t.book == nil {
return t.book, fmt.Errorf("Непозната книга %s", t.isbn)
}
return t.book, t.err
}
func (t TheLibraryResponse) GetAvailability() (available int, registered int) {
return t.availableNumber, t.registeredNumber
}
type AuthorName struct {
XMLName xml.Name `xml:"author"`
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
func (a *AuthorName) String() string {
return a.FirstName + " " + a.LastName
}
type Book struct {
XMLName xml.Name `xml:"book"`
Isbn string `xml:"isbn,attr" json:"isbn"`
Author *AuthorName `json:"author"`
Title string `json:"title" xml:"title"`
Ratings []int `json:"rating" xml:"ratings>rating"`
}
func newBook() *Book {
return &Book{Ratings: make([]int, 0)}
}
func (b *Book) String() string {
return fmt.Sprintf("[%s] %s от %s", b.Isbn, b.Title, b.Author)
}
type TheLibrary struct {
books *[]*Book
AvailableBooks map[string]int
librarians int
BorrowedBooks map[string]int
}
func (l TheLibrary) GetBook(isbn string) *Book {
for _, book := range *l.books {
if book.Isbn == isbn {
return book
}
}
return nil
}
func (l TheLibrary) AddBook(data []byte, unmarshal func([]byte, interface{}) error) (int, error) {
var newBook Book
err := unmarshal(data, &newBook)
if err != nil {
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], err
}
*l.books = append(*l.books, &newBook)
if l.AvailableBooks[newBook.Isbn]+l.BorrowedBooks[newBook.Isbn] < 4 {
l.AvailableBooks[newBook.Isbn]++
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], nil
}
return 4, fmt.Errorf("Има 4 копия на книга %s", newBook.Isbn)
}
func (l TheLibrary) AddBookJSON(data []byte) (int, error) {
return l.AddBook(data, json.Unmarshal)
}
func (l TheLibrary) AddBookXML(data []byte) (int, error) {
return l.AddBook(data, xml.Unmarshal)
}
func (l TheLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
resChannel := make(chan LibraryResponse)
reqChannel := make(chan LibraryRequest)
for i := 0; i < l.librarians; i++ {
go l.HandleRequest(reqChannel, resChannel)
}
return reqChannel, resChannel
}
func (l TheLibrary) HandleRequest(reqChannel chan LibraryRequest, resChannel chan LibraryResponse) {
for request := range reqChannel {
isbn := request.GetISBN()
switch request.GetType() {
case TakeBook:
if l.AvailableBooks[isbn] > 0 {
l.AvailableBooks[isbn]--
l.BorrowedBooks[isbn]++
resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
isbn: isbn, availableNumber: l.AvailableBooks[isbn],
registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
err: nil,
}
} else {
resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
isbn: isbn, availableNumber: l.AvailableBooks[isbn],
registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
err: fmt.Errorf("Няма наличност на книга %s", isbn),
}
}
case ReturnBook:
if l.AvailableBooks[isbn]+l.BorrowedBooks[isbn] == 4 {
resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
isbn: isbn, availableNumber: l.AvailableBooks[isbn],
registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
err: fmt.Errorf("Всички копия са налични %s", isbn),
}
} else {
l.AvailableBooks[isbn]++
l.BorrowedBooks[isbn]--
resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
isbn: isbn, availableNumber: l.AvailableBooks[isbn],
registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
err: nil,
}
}
case CheckAvailability:
resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
isbn: isbn, availableNumber: l.AvailableBooks[isbn],
registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
err: nil,
}
}
}
}
func NewLibrary(librarians int) Library {
var books []*Book
return TheLibrary{librarians: librarians, books: &books, BorrowedBooks: make(map[string]int), AvailableBooks: make(map[string]int)}
}
-
-func main() {
- library := NewLibrary(5)
- for i := 0; i < 5; i++ {
- library.AddBookXML([]byte(`
-<book isbn="0954540018">
-<title>Who said the race is Over?</title>
-<author>
-<first_name>Anno</first_name>
-<last_name>Birkin</last_name>
-</author>
-<genre>poetry</genre>
-<pages>80</pages>
-<ratings>
-<rating>5</rating>
-<rating>4</rating>
-<rating>4</rating>
-<rating>5</rating>
-<rating>3</rating>
-</ratings>
-</book>
-`))
- }
-
- requests, responses := library.Hello()
-
- go func() {
- requests <- TheLibraryRequest{Type: 1, Isbn: "0954540018"}
- }()
- response := <-responses
- a, b := response.GetAvailability()
- fmt.Printf("A: %d, B: %d\n", a, b)
-}

Диана обнови решението на 03.12.2015 22:41 (преди над 2 години)

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
const (
_ = iota
TakeBook
ReturnBook
CheckAvailability
)
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 TheLibraryRequest struct {
Isbn string
Type int
}
func (t TheLibraryRequest) GetType() int {
return t.Type
}
func (t TheLibraryRequest) GetISBN() string {
return t.Isbn
}
type LibraryResponse interface {
GetBook() (fmt.Stringer, error)
GetAvailability() (available int, registered int)
}
type TheLibraryResponse struct {
book *Book
isbn string
err error
availableNumber, registeredNumber int
}
func (t TheLibraryResponse) GetBook() (fmt.Stringer, error) {
if t.book == nil {
return t.book, fmt.Errorf("Непозната книга %s", t.isbn)
}
return t.book, t.err
}
func (t TheLibraryResponse) GetAvailability() (available int, registered int) {
+ if t.book == nil {
+ return 0, 0
+ }
return t.availableNumber, t.registeredNumber
}
type AuthorName struct {
XMLName xml.Name `xml:"author"`
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
func (a *AuthorName) String() string {
return a.FirstName + " " + a.LastName
}
type Book struct {
XMLName xml.Name `xml:"book"`
Isbn string `xml:"isbn,attr" json:"isbn"`
Author *AuthorName `json:"author"`
Title string `json:"title" xml:"title"`
Ratings []int `json:"rating" xml:"ratings>rating"`
}
func newBook() *Book {
return &Book{Ratings: make([]int, 0)}
}
func (b *Book) String() string {
return fmt.Sprintf("[%s] %s от %s", b.Isbn, b.Title, b.Author)
}
type TheLibrary struct {
books *[]*Book
AvailableBooks map[string]int
librarians int
BorrowedBooks map[string]int
}
func (l TheLibrary) GetBook(isbn string) *Book {
for _, book := range *l.books {
if book.Isbn == isbn {
return book
}
}
return nil
}
func (l TheLibrary) AddBook(data []byte, unmarshal func([]byte, interface{}) error) (int, error) {
var newBook Book
err := unmarshal(data, &newBook)
if err != nil {
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], err
}
*l.books = append(*l.books, &newBook)
if l.AvailableBooks[newBook.Isbn]+l.BorrowedBooks[newBook.Isbn] < 4 {
l.AvailableBooks[newBook.Isbn]++
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], nil
}
return 4, fmt.Errorf("Има 4 копия на книга %s", newBook.Isbn)
}
func (l TheLibrary) AddBookJSON(data []byte) (int, error) {
return l.AddBook(data, json.Unmarshal)
}
func (l TheLibrary) AddBookXML(data []byte) (int, error) {
return l.AddBook(data, xml.Unmarshal)
}
func (l TheLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
resChannel := make(chan LibraryResponse)
reqChannel := make(chan LibraryRequest)
for i := 0; i < l.librarians; i++ {
go l.HandleRequest(reqChannel, resChannel)
}
return reqChannel, resChannel
}
func (l TheLibrary) HandleRequest(reqChannel chan LibraryRequest, resChannel chan LibraryResponse) {
+ ch := make(chan struct{}, 1)
for request := range reqChannel {
+ ch <- struct{}{}
isbn := request.GetISBN()
+ response := TheLibraryResponse{book: l.GetBook(isbn), isbn: isbn}
switch request.GetType() {
case TakeBook:
if l.AvailableBooks[isbn] > 0 {
l.AvailableBooks[isbn]--
l.BorrowedBooks[isbn]++
- resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
- isbn: isbn, availableNumber: l.AvailableBooks[isbn],
- registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
- err: nil,
- }
+ response.err = nil
} else {
- resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
- isbn: isbn, availableNumber: l.AvailableBooks[isbn],
- registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
- err: fmt.Errorf("Няма наличност на книга %s", isbn),
- }
+ response.err = fmt.Errorf("Няма наличност на книга %s", isbn)
}
-
case ReturnBook:
- if l.AvailableBooks[isbn]+l.BorrowedBooks[isbn] == 4 {
- resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
- isbn: isbn, availableNumber: l.AvailableBooks[isbn],
- registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
- err: fmt.Errorf("Всички копия са налични %s", isbn),
- }
+ if l.AvailableBooks[isbn] == 4 {
+ response.err = fmt.Errorf("Всички копия са налични %s", isbn)
} else {
l.AvailableBooks[isbn]++
l.BorrowedBooks[isbn]--
- resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
- isbn: isbn, availableNumber: l.AvailableBooks[isbn],
- registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
- err: nil,
- }
+ response.err = nil
}
case CheckAvailability:
- resChannel <- &TheLibraryResponse{book: l.GetBook(isbn),
- isbn: isbn, availableNumber: l.AvailableBooks[isbn],
- registeredNumber: l.AvailableBooks[isbn] + l.BorrowedBooks[isbn],
- err: nil,
- }
+ response.err = nil
}
+ response.availableNumber = l.AvailableBooks[isbn]
+ response.registeredNumber = l.AvailableBooks[isbn] + l.BorrowedBooks[isbn]
+ <-ch
+ resChannel <- response
}
}
func NewLibrary(librarians int) Library {
var books []*Book
return TheLibrary{librarians: librarians, books: &books, BorrowedBooks: make(map[string]int), AvailableBooks: make(map[string]int)}
}

Диана обнови решението на 04.12.2015 13:02 (преди над 2 години)

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
const (
_ = iota
TakeBook
ReturnBook
CheckAvailability
)
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 TheLibraryRequest struct {
Isbn string
Type int
}
func (t TheLibraryRequest) GetType() int {
return t.Type
}
func (t TheLibraryRequest) GetISBN() string {
return t.Isbn
}
type LibraryResponse interface {
GetBook() (fmt.Stringer, error)
GetAvailability() (available int, registered int)
}
type TheLibraryResponse struct {
book *Book
isbn string
err error
availableNumber, registeredNumber int
}
func (t TheLibraryResponse) GetBook() (fmt.Stringer, error) {
if t.book == nil {
return t.book, fmt.Errorf("Непозната книга %s", t.isbn)
}
return t.book, t.err
}
func (t TheLibraryResponse) GetAvailability() (available int, registered int) {
if t.book == nil {
return 0, 0
}
return t.availableNumber, t.registeredNumber
}
type AuthorName struct {
XMLName xml.Name `xml:"author"`
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
func (a *AuthorName) String() string {
return a.FirstName + " " + a.LastName
}
type Book struct {
XMLName xml.Name `xml:"book"`
Isbn string `xml:"isbn,attr" json:"isbn"`
Author *AuthorName `json:"author"`
Title string `json:"title" xml:"title"`
Ratings []int `json:"rating" xml:"ratings>rating"`
}
func newBook() *Book {
return &Book{Ratings: make([]int, 0)}
}
func (b *Book) String() string {
return fmt.Sprintf("[%s] %s от %s", b.Isbn, b.Title, b.Author)
}
type TheLibrary struct {
books *[]*Book
AvailableBooks map[string]int
librarians int
BorrowedBooks map[string]int
+ locker chan struct{}
}
func (l TheLibrary) GetBook(isbn string) *Book {
for _, book := range *l.books {
if book.Isbn == isbn {
return book
}
}
return nil
}
func (l TheLibrary) AddBook(data []byte, unmarshal func([]byte, interface{}) error) (int, error) {
+ l.locker <- struct{}{}
var newBook Book
err := unmarshal(data, &newBook)
if err != nil {
+ <-l.locker
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], err
}
*l.books = append(*l.books, &newBook)
if l.AvailableBooks[newBook.Isbn]+l.BorrowedBooks[newBook.Isbn] < 4 {
l.AvailableBooks[newBook.Isbn]++
+ <-l.locker
return l.AvailableBooks[newBook.Isbn] + l.BorrowedBooks[newBook.Isbn], nil
}
+ <-l.locker
return 4, fmt.Errorf("Има 4 копия на книга %s", newBook.Isbn)
}
func (l TheLibrary) AddBookJSON(data []byte) (int, error) {
return l.AddBook(data, json.Unmarshal)
}
func (l TheLibrary) AddBookXML(data []byte) (int, error) {
return l.AddBook(data, xml.Unmarshal)
}
func (l TheLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
resChannel := make(chan LibraryResponse)
reqChannel := make(chan LibraryRequest)
for i := 0; i < l.librarians; i++ {
go l.HandleRequest(reqChannel, resChannel)
}
return reqChannel, resChannel
}
func (l TheLibrary) HandleRequest(reqChannel chan LibraryRequest, resChannel chan LibraryResponse) {
- ch := make(chan struct{}, 1)
for request := range reqChannel {
- ch <- struct{}{}
+ l.locker <- struct{}{}
isbn := request.GetISBN()
response := TheLibraryResponse{book: l.GetBook(isbn), isbn: isbn}
switch request.GetType() {
case TakeBook:
if l.AvailableBooks[isbn] > 0 {
l.AvailableBooks[isbn]--
l.BorrowedBooks[isbn]++
response.err = nil
} else {
response.err = fmt.Errorf("Няма наличност на книга %s", isbn)
}
case ReturnBook:
if l.AvailableBooks[isbn] == 4 {
response.err = fmt.Errorf("Всички копия са налични %s", isbn)
} else {
l.AvailableBooks[isbn]++
l.BorrowedBooks[isbn]--
response.err = nil
}
case CheckAvailability:
response.err = nil
}
response.availableNumber = l.AvailableBooks[isbn]
response.registeredNumber = l.AvailableBooks[isbn] + l.BorrowedBooks[isbn]
- <-ch
+ <-l.locker
resChannel <- response
}
}
func NewLibrary(librarians int) Library {
var books []*Book
- return TheLibrary{librarians: librarians, books: &books, BorrowedBooks: make(map[string]int), AvailableBooks: make(map[string]int)}
+ return TheLibrary{librarians: librarians,
+ books: &books, BorrowedBooks: make(map[string]int),
+ AvailableBooks: make(map[string]int),
+ locker: make(chan struct{}, 1),
+ }
}