Решение на Concurrent Tasks от Ангел Ангелов

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

Към профила на Ангел Ангелов

Резултати

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

Код

package main
import (
"encoding/json"
"encoding/xml"
"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 BookAuthor struct {
XMLName xml.Name `xml:"author"`
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
func (a *BookAuthor) String() string {
return fmt.Sprintf("%s %s", a.FirstName, a.LastName)
}
type Book struct {
XMLName xml.Name `xml:"book"`
Isbn string `json:"isbn" xml:"isbn,attr"`
Title string `json:"title" xml:"title"`
Author *BookAuthor `json:"author" xml:"author"`
}
func (b *Book) String() string {
return fmt.Sprintf("[%s] %s от %s", b.Isbn, b.Title, b.Author)
}
type MyLibrary struct {
books map[string]*Book
copies map[string]int
available map[string]int
librarians int
requestMutex *sync.Mutex
}
func NewLibrary(librarians int) Library {
library := MyLibrary{}
library.books = make(map[string]*Book, 0)
library.copies = make(map[string]int)
library.available = make(map[string]int)
library.librarians = librarians
library.requestMutex = new(sync.Mutex)
return library
}
func (m MyLibrary) AddBookJSON(data []byte) (int, error) {
book := new(Book)
err := json.Unmarshal(data, book)
if err != nil {
return 0, err
}
return m.addBook(book)
}
func (m MyLibrary) AddBookXML(data []byte) (int, error) {
book := new(Book)
err := xml.Unmarshal(data, book)
if err != nil {
return 0, err
}
return m.addBook(book)
}
type MyRequest struct {
requestType int
requestIsbn string
}
func (m MyRequest) GetType() int {
return m.requestType
}
func (m MyRequest) GetISBN() string {
return m.requestIsbn
}
type MyResponse struct {
book *Book
err error
available int
registered int
}
func (m MyResponse) GetBook() (fmt.Stringer, error) {
return m.book, m.err
}
func (m MyResponse) GetAvailability() (available int, registered int) {
return m.available, m.registered
}
func (m *MyLibrary) addBook(book *Book) (int, error) {
m.requestMutex.Lock()
defer m.requestMutex.Unlock()
m.books[book.Isbn] = book
if m.copies[book.Isbn] >= 4 {
return 0, fmt.Errorf("Има 4 копия на книга %s", book.Isbn)
}
m.copies[book.Isbn]++
m.available[book.Isbn]++
return m.copies[book.Isbn], nil
}
func (m *MyLibrary) handle(request LibraryRequest) LibraryResponse {
m.requestMutex.Lock()
defer m.requestMutex.Unlock()
response := MyResponse{}
isbn := request.GetISBN()
book := m.books[isbn]
if book == nil {
response.err = fmt.Errorf("Непозната книга %s", isbn)
return response
}
switch request.GetType() {
case 1:
if m.available[isbn] > 0 {
m.available[isbn]--
} else {
response.err = fmt.Errorf("Няма наличност на книга %s", isbn)
}
case 2:
if m.available[isbn] < m.copies[isbn] {
m.available[isbn]++
} else {
response.err = fmt.Errorf("Всички копия са налични %s", isbn)
}
}
response.book = book
response.available = m.available[isbn]
response.registered = m.copies[isbn]
return response
}
func (m *MyLibrary) librarian(requests chan LibraryRequest,
responses chan LibraryResponse) {
for request := range requests {
responses <- m.handle(request)
}
return
}
func (m MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
requests := make(chan LibraryRequest)
responses := make(chan LibraryResponse)
for i := 0; i < m.librarians; i++ {
go m.librarian(requests, responses)
}
return requests, responses
}

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

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

История (1 версия и 0 коментара)

Ангел обнови решението на 05.12.2015 00:07 (преди над 2 години)

+package main
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "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 BookAuthor struct {
+ XMLName xml.Name `xml:"author"`
+ FirstName string `json:"first_name" xml:"first_name"`
+ LastName string `json:"last_name" xml:"last_name"`
+}
+
+func (a *BookAuthor) String() string {
+ return fmt.Sprintf("%s %s", a.FirstName, a.LastName)
+}
+
+type Book struct {
+ XMLName xml.Name `xml:"book"`
+ Isbn string `json:"isbn" xml:"isbn,attr"`
+ Title string `json:"title" xml:"title"`
+ Author *BookAuthor `json:"author" xml:"author"`
+}
+
+func (b *Book) String() string {
+ return fmt.Sprintf("[%s] %s от %s", b.Isbn, b.Title, b.Author)
+}
+
+type MyLibrary struct {
+ books map[string]*Book
+ copies map[string]int
+ available map[string]int
+ librarians int
+ requestMutex *sync.Mutex
+}
+
+func NewLibrary(librarians int) Library {
+ library := MyLibrary{}
+ library.books = make(map[string]*Book, 0)
+ library.copies = make(map[string]int)
+ library.available = make(map[string]int)
+ library.librarians = librarians
+ library.requestMutex = new(sync.Mutex)
+ return library
+}
+
+func (m MyLibrary) AddBookJSON(data []byte) (int, error) {
+ book := new(Book)
+ err := json.Unmarshal(data, book)
+ if err != nil {
+ return 0, err
+ }
+ return m.addBook(book)
+}
+
+func (m MyLibrary) AddBookXML(data []byte) (int, error) {
+ book := new(Book)
+ err := xml.Unmarshal(data, book)
+ if err != nil {
+ return 0, err
+ }
+ return m.addBook(book)
+}
+
+type MyRequest struct {
+ requestType int
+ requestIsbn string
+}
+
+func (m MyRequest) GetType() int {
+ return m.requestType
+}
+
+func (m MyRequest) GetISBN() string {
+ return m.requestIsbn
+}
+
+type MyResponse struct {
+ book *Book
+ err error
+ available int
+ registered int
+}
+
+func (m MyResponse) GetBook() (fmt.Stringer, error) {
+ return m.book, m.err
+}
+
+func (m MyResponse) GetAvailability() (available int, registered int) {
+ return m.available, m.registered
+}
+
+func (m *MyLibrary) addBook(book *Book) (int, error) {
+ m.requestMutex.Lock()
+ defer m.requestMutex.Unlock()
+
+ m.books[book.Isbn] = book
+ if m.copies[book.Isbn] >= 4 {
+ return 0, fmt.Errorf("Има 4 копия на книга %s", book.Isbn)
+ }
+ m.copies[book.Isbn]++
+ m.available[book.Isbn]++
+ return m.copies[book.Isbn], nil
+}
+
+func (m *MyLibrary) handle(request LibraryRequest) LibraryResponse {
+ m.requestMutex.Lock()
+ defer m.requestMutex.Unlock()
+
+ response := MyResponse{}
+ isbn := request.GetISBN()
+
+ book := m.books[isbn]
+ if book == nil {
+ response.err = fmt.Errorf("Непозната книга %s", isbn)
+ return response
+ }
+
+ switch request.GetType() {
+ case 1:
+ if m.available[isbn] > 0 {
+ m.available[isbn]--
+ } else {
+ response.err = fmt.Errorf("Няма наличност на книга %s", isbn)
+ }
+ case 2:
+ if m.available[isbn] < m.copies[isbn] {
+ m.available[isbn]++
+ } else {
+ response.err = fmt.Errorf("Всички копия са налични %s", isbn)
+ }
+ }
+
+ response.book = book
+ response.available = m.available[isbn]
+ response.registered = m.copies[isbn]
+ return response
+}
+
+func (m *MyLibrary) librarian(requests chan LibraryRequest,
+ responses chan LibraryResponse) {
+ for request := range requests {
+ responses <- m.handle(request)
+ }
+ return
+}
+
+func (m MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+ requests := make(chan LibraryRequest)
+ responses := make(chan LibraryResponse)
+ for i := 0; i < m.librarians; i++ {
+ go m.librarian(requests, responses)
+ }
+ return requests, responses
+}