Решение на Concurrent Tasks от Екатерина Горанова

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

Към профила на Екатерина Горанова

Резултати

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

Код

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"sync"
)
const MaxRegistered = 4
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 MyLibrary struct {
books map[string]*Book
librarians chan struct{}
mu *sync.Mutex
}
type MyLibraryResponse struct {
book *Book
err error
}
type Book struct {
Isbn string `json:"isbn" xml:"isbn,attr"`
Title string `json:"title" xml:"title"`
Author *Author `json:"author" xml:"author"`
Ratings []int `json:"ratings" xml:"ratings"`
available int
registered int
mu *sync.Mutex
}
type Author struct {
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
func (b *Book) String() string {
author := b.Author.FirstName + " " + b.Author.LastName
return "[" + b.Isbn + "] " + b.Title + " от " + author
}
func (b *Book) getRegistered() int {
b.mu.Lock()
defer b.mu.Unlock()
return b.registered
}
func (b *Book) incrementRegistered() {
b.mu.Lock()
defer b.mu.Unlock()
b.registered++
}
func (b *Book) getAvailable() int {
b.mu.Lock()
defer b.mu.Unlock()
return b.available
}
func (b *Book) incrementAvailable() {
b.mu.Lock()
defer b.mu.Unlock()
b.available++
}
func (b *Book) decrementAvailable() {
b.mu.Lock()
defer b.mu.Unlock()
b.available--
}
func (resp *MyLibraryResponse) GetBook() (fmt.Stringer, error) {
return resp.book, resp.err
}
func (resp *MyLibraryResponse) GetAvailability() (int, int) {
if resp.book == nil {
return 0, 0
}
return resp.book.getAvailable(), resp.book.getRegistered()
}
func (lib *MyLibrary) getBook(isbn string) (*Book, bool) {
lib.mu.Lock()
defer lib.mu.Unlock()
b, ok := lib.books[isbn]
return b, ok
}
func (lib *MyLibrary) addBook(newBook Book) (int, error) {
isbn := newBook.Isbn
if b, ok := lib.getBook(isbn); ok {
if b.getRegistered() >= MaxRegistered {
err := fmt.Errorf("Има %d копия на книга %s", b.getRegistered(), isbn)
return b.getRegistered(), err
}
} else {
lib.mu.Lock()
lib.books[isbn] = &newBook
lib.mu.Unlock()
}
lib.books[isbn].incrementAvailable()
lib.books[isbn].incrementRegistered()
return lib.books[isbn].getRegistered(), nil
}
func (lib *MyLibrary) AddBookJSON(data []byte) (int, error) {
newBook := Book{mu: &sync.Mutex{}}
json.Unmarshal(data, &newBook)
return lib.addBook(newBook)
}
func (lib *MyLibrary) AddBookXML(data []byte) (int, error) {
newBook := Book{mu: &sync.Mutex{}}
xml.Unmarshal(data, &newBook)
return lib.addBook(newBook)
}
func (lib *MyLibrary) occupyLibrarian(reqs chan LibraryRequest, resps chan LibraryResponse) {
for req := range reqs {
var err error
isbn := req.GetISBN()
book, ok := lib.getBook(isbn)
if ok {
switch req.GetType() {
case 1:
if book.getAvailable() == 0 {
err = fmt.Errorf("Няма наличност на книга %s", isbn)
} else {
book.decrementAvailable()
}
case 2:
if book.getAvailable() >= book.getRegistered() {
err = fmt.Errorf("Всички копия са налични %s", isbn)
} else {
book.incrementAvailable()
}
}
} else {
err = fmt.Errorf("Непозната книга %s", isbn)
}
resps <- &MyLibraryResponse{book, err}
}
close(resps)
<-lib.librarians
}
func (lib *MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
requests := make(chan LibraryRequest)
responses := make(chan LibraryResponse)
lib.librarians <- struct{}{}
go lib.occupyLibrarian(requests, responses)
return requests, responses
}
func NewLibrary(librarians int) Library {
return &MyLibrary{
books: make(map[string]*Book),
librarians: make(chan struct{}, librarians),
mu: &sync.Mutex{},
}
}

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

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

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

Екатерина обнови решението на 03.12.2015 23:57 (преди над 2 години)

+package main
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "fmt"
+ "sync"
+)
+
+const MaxRegistered = 4
+
+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 MyLibrary struct {
+ books map[string]*Book
+ librarians chan struct{}
+ mu *sync.Mutex
+}
+
+type MyLibraryResponse struct {
+ book *Book
+ err error
+}
+
+type Book struct {
+ Isbn string `json:"isbn" xml:"isbn,attr"`
+ Title string `json:"title" xml:"title"`
+ Author *Author `json:"author" xml:"author"`
+ Ratings []int `json:"ratings" xml:"ratings"`
+ available int
+ registered int
+ mu *sync.Mutex
+}
+
+type Author struct {
+ FirstName string `json:"first_name" xml:"first_name"`
+ LastName string `json:"last_name" xml:"last_name"`
+}
+
+func (b *Book) String() string {
+ author := b.Author.FirstName + " " + b.Author.LastName
+ return "[" + b.Isbn + "] " + b.Title + " от " + author
+}
+
+func (b *Book) getRegistered() int {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ return b.registered
+}
+
+func (b *Book) incrementRegistered() {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ b.registered++
+}
+
+func (b *Book) getAvailable() int {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ return b.available
+}
+
+func (b *Book) incrementAvailable() {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ b.available++
+}
+
+func (b *Book) decrementAvailable() {
+ b.mu.Lock()
+ defer b.mu.Unlock()
+ b.available--
+}
+
+func (resp *MyLibraryResponse) GetBook() (fmt.Stringer, error) {
+ return resp.book, resp.err
+}
+
+func (resp *MyLibraryResponse) GetAvailability() (int, int) {
+ if resp.book == nil {
+ return 0, 0
+ }
+ return resp.book.getAvailable(), resp.book.getRegistered()
+}
+
+func (lib *MyLibrary) getBook(isbn string) (*Book, bool) {
+ lib.mu.Lock()
+ defer lib.mu.Unlock()
+ b, ok := lib.books[isbn]
+ return b, ok
+}
+
+func (lib *MyLibrary) addBook(newBook Book) (int, error) {
+ isbn := newBook.Isbn
+ if b, ok := lib.getBook(isbn); ok {
+ if b.getRegistered() >= MaxRegistered {
+ err := fmt.Errorf("Има %d копия на книга %s", b.getRegistered(), isbn)
+ return b.getRegistered(), err
+ }
+ } else {
+ lib.mu.Lock()
+ lib.books[isbn] = &newBook
+ lib.mu.Unlock()
+ }
+ lib.books[isbn].incrementAvailable()
+ lib.books[isbn].incrementRegistered()
+ return lib.books[isbn].getRegistered(), nil
+}
+
+func (lib MyLibrary) AddBookJSON(data []byte) (int, error) {
+ newBook := Book{mu: &sync.Mutex{}}
+ json.Unmarshal(data, &newBook)
+ return lib.addBook(newBook)
+}
+
+func (lib MyLibrary) AddBookXML(data []byte) (int, error) {
+ newBook := Book{mu: &sync.Mutex{}}
+ xml.Unmarshal(data, &newBook)
+ return lib.addBook(newBook)
+}
+
+func (lib MyLibrary) occupyLibrarian(reqs chan LibraryRequest, resps chan LibraryResponse) {
+ for req := range reqs {
+ var err error
+ isbn := req.GetISBN()
+
+ book, ok := lib.getBook(isbn)
+ if ok {
+ switch req.GetType() {
+ case 1:
+ if book.getAvailable() == 0 {
+ err = fmt.Errorf("Няма наличност на книга %s", isbn)
+ } else {
+ book.decrementAvailable()
+ }
+ case 2:
+ if book.getAvailable() >= book.getRegistered() {
+ err = fmt.Errorf("Всички копия са налични %s", isbn)
+ } else {
+ book.incrementAvailable()
+ }
+ }
+ } else {
+ err = fmt.Errorf("Непозната книга %s", isbn)
+ }
+ resps <- &MyLibraryResponse{book, err}
+ }
+ close(resps)
+ <-lib.librarians
+}
+
+func (lib MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+ requests := make(chan LibraryRequest)
+ responses := make(chan LibraryResponse)
+ lib.librarians <- struct{}{}
+ go lib.occupyLibrarian(requests, responses)
+ return requests, responses
+}
+
+func NewLibrary(librarians int) Library {
+ return MyLibrary{
+ books: make(map[string]*Book),
+ librarians: make(chan struct{}, librarians),
+ mu: &sync.Mutex{},
+ }
+}

Екатерина обнови решението на 04.12.2015 22:36 (преди над 2 години)

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"sync"
)
const MaxRegistered = 4
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 MyLibrary struct {
books map[string]*Book
librarians chan struct{}
mu *sync.Mutex
}
type MyLibraryResponse struct {
book *Book
err error
}
type Book struct {
Isbn string `json:"isbn" xml:"isbn,attr"`
Title string `json:"title" xml:"title"`
Author *Author `json:"author" xml:"author"`
Ratings []int `json:"ratings" xml:"ratings"`
available int
registered int
mu *sync.Mutex
}
type Author struct {
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
func (b *Book) String() string {
author := b.Author.FirstName + " " + b.Author.LastName
return "[" + b.Isbn + "] " + b.Title + " от " + author
}
func (b *Book) getRegistered() int {
b.mu.Lock()
defer b.mu.Unlock()
return b.registered
}
func (b *Book) incrementRegistered() {
b.mu.Lock()
defer b.mu.Unlock()
b.registered++
}
func (b *Book) getAvailable() int {
b.mu.Lock()
defer b.mu.Unlock()
return b.available
}
func (b *Book) incrementAvailable() {
b.mu.Lock()
defer b.mu.Unlock()
b.available++
}
func (b *Book) decrementAvailable() {
b.mu.Lock()
defer b.mu.Unlock()
b.available--
}
func (resp *MyLibraryResponse) GetBook() (fmt.Stringer, error) {
return resp.book, resp.err
}
func (resp *MyLibraryResponse) GetAvailability() (int, int) {
if resp.book == nil {
return 0, 0
}
return resp.book.getAvailable(), resp.book.getRegistered()
}
func (lib *MyLibrary) getBook(isbn string) (*Book, bool) {
lib.mu.Lock()
defer lib.mu.Unlock()
b, ok := lib.books[isbn]
return b, ok
}
func (lib *MyLibrary) addBook(newBook Book) (int, error) {
isbn := newBook.Isbn
if b, ok := lib.getBook(isbn); ok {
if b.getRegistered() >= MaxRegistered {
err := fmt.Errorf("Има %d копия на книга %s", b.getRegistered(), isbn)
return b.getRegistered(), err
}
} else {
lib.mu.Lock()
lib.books[isbn] = &newBook
lib.mu.Unlock()
}
lib.books[isbn].incrementAvailable()
lib.books[isbn].incrementRegistered()
return lib.books[isbn].getRegistered(), nil
}
-func (lib MyLibrary) AddBookJSON(data []byte) (int, error) {
+func (lib *MyLibrary) AddBookJSON(data []byte) (int, error) {
newBook := Book{mu: &sync.Mutex{}}
json.Unmarshal(data, &newBook)
return lib.addBook(newBook)
}
-func (lib MyLibrary) AddBookXML(data []byte) (int, error) {
+func (lib *MyLibrary) AddBookXML(data []byte) (int, error) {
newBook := Book{mu: &sync.Mutex{}}
xml.Unmarshal(data, &newBook)
return lib.addBook(newBook)
}
-func (lib MyLibrary) occupyLibrarian(reqs chan LibraryRequest, resps chan LibraryResponse) {
+func (lib *MyLibrary) occupyLibrarian(reqs chan LibraryRequest, resps chan LibraryResponse) {
for req := range reqs {
var err error
isbn := req.GetISBN()
book, ok := lib.getBook(isbn)
if ok {
switch req.GetType() {
case 1:
if book.getAvailable() == 0 {
err = fmt.Errorf("Няма наличност на книга %s", isbn)
} else {
book.decrementAvailable()
}
case 2:
if book.getAvailable() >= book.getRegistered() {
err = fmt.Errorf("Всички копия са налични %s", isbn)
} else {
book.incrementAvailable()
}
}
} else {
err = fmt.Errorf("Непозната книга %s", isbn)
}
resps <- &MyLibraryResponse{book, err}
}
close(resps)
<-lib.librarians
}
-func (lib MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+func (lib *MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
requests := make(chan LibraryRequest)
responses := make(chan LibraryResponse)
lib.librarians <- struct{}{}
go lib.occupyLibrarian(requests, responses)
return requests, responses
}
func NewLibrary(librarians int) Library {
- return MyLibrary{
+ return &MyLibrary{
books: make(map[string]*Book),
librarians: make(chan struct{}, librarians),
mu: &sync.Mutex{},
}
}