Решение на Concurrent Tasks от Михаил Здравков

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

Към профила на Михаил Здравков

Резултати

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

Код

package main
import (
"encoding/json"
"encoding/xml"
"errors"
"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 Librarian struct {
input chan LibraryRequest
output chan LibraryResponse
}
func (l *Librarian) Animate(library *LibraryOfAlexandria, librarians chan Librarian) {
go func() {
for request := range l.input {
isbn := request.GetISBN()
response := new(Response)
switch request.GetType() {
case 1: // Borrow
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available < 1 {
response.Err = errors.New("Няма наличност на книга " + isbn)
} else {
response.Book = book.Book
book.Available -= 1
}
case 2: // Return
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available >= book.All {
response.Err = errors.New("Всички копия са налични " + isbn)
} else {
response.Book = book.Book
book.Available += 1
}
case 3: // Availability
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available >= 4 {
response.Err = errors.New("Всички копия са налични " + isbn)
} else {
response.Book = book.Book
}
}
if book, ok := library.Books[isbn]; ok {
response.Available = book.Available
response.All = book.All
} else {
response.All = 0
response.Available = 0
}
l.output <- response
}
l.input = make(chan LibraryRequest)
librarians <- *l
}()
}
type BookCopies struct {
Book
Available, All int
}
type LibraryOfAlexandria struct {
Books map[string]*BookCopies
booksLock sync.Mutex
librarians chan Librarian
}
func (lib LibraryOfAlexandria) AddBookJSON(data []byte) (int, error) {
var book Book
if err := json.Unmarshal(data, &book); err != nil {
return 0, err
}
return lib.addBook(book)
}
func (lib LibraryOfAlexandria) AddBookXML(data []byte) (int, error) {
var book Book
if err := xml.Unmarshal(data, &book); err != nil {
return 0, err
}
return lib.addBook(book)
}
func (lib *LibraryOfAlexandria) addBook(book Book) (int, error) {
lib.booksLock.Lock()
if lib.Books[book.ISBN] == nil {
lib.Books[book.ISBN] = new(BookCopies)
lib.Books[book.ISBN].Book = book
} else if lib.Books[book.ISBN].All >= 4 {
return lib.Books[book.ISBN].All, errors.New("Има 4 копия на книга " + book.ISBN)
}
lib.Books[book.ISBN].Available += 1
lib.Books[book.ISBN].All += 1
lib.booksLock.Unlock()
return lib.Books[book.ISBN].All, nil
}
func (lib LibraryOfAlexandria) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
var librarian Librarian
var ok bool
// try take from the pool until we get a librarian
for librarian, ok = <-lib.librarians; !ok; {
}
return librarian.input, librarian.output
}
type Request struct {
RequestType int
Book
}
func (req Request) GetType() int {
return req.RequestType
}
func (req Request) GetISBN() string {
return req.ISBN
}
type Response struct {
Book
Err error
Available, All int
}
func (res *Response) GetBook() (fmt.Stringer, error) {
if res.Book.ISBN == "" {
return nil, res.Err
}
return res.Book, res.Err
}
func (res *Response) GetAvailability() (available int, registered int) {
return res.Available, res.All
}
type Author struct {
FirstName string `json:"first_name" xml:"author>first_name"`
LastName string `json:"last_name" xml:"author>last_name"`
}
type Book struct {
ISBN string `xml:"isbn,attr"`
Title string `xml:"title"`
Author `json:"author"`
Ratings []int
}
func (b Book) String() string {
return fmt.Sprintf("[%s] %s от %s %s", b.ISBN, b.Title, b.Author.FirstName, b.Author.LastName)
}
func NewLibrary(librarians int) LibraryOfAlexandria {
library := &LibraryOfAlexandria{Books: make(map[string]*BookCopies), librarians: make(chan Librarian, librarians)}
for i := 0; i < librarians; i++ {
librarian := &Librarian{input: make(chan LibraryRequest), output: make(chan LibraryResponse)}
library.librarians <- *librarian
librarian.Animate(library, library.librarians)
}
return *library
}

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

PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.003s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.003s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s
PASS
ok  	_/tmp/d20151207-5667-1t01qxw	0.004s

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

Михаил обнови решението на 06.12.2015 14:48 (преди над 2 години)

+package solution
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "errors"
+ "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 Librarian struct {
+ input chan LibraryRequest
+ output chan LibraryResponse
+}
+
+func (l *Librarian) Animate(library *LibraryOfAlexandria, librarians chan Librarian) {
+ go func() {
+ for request := range l.input {
+ isbn := request.GetISBN()
+
+ response := new(Response)
+ switch request.GetType() {
+ case 1: // Borrow
+ if book, ok := library.Books[isbn]; !ok {
+ response.Err = errors.New("Непозната книга " + isbn)
+ } else if book.Available < 1 {
+ response.Err = errors.New("Няма наличност на книга " + isbn)
+ } else {
+ book.Available -= 1
+ }
+ case 2: // Return
+ if book, ok := library.Books[isbn]; !ok {
+ response.Err = errors.New("Непозната книга " + isbn)
+ } else if book.Available >= 4 {
+ response.Err = errors.New("Всички копия са налични " + isbn)
+ } else {
+ book.Available += 1
+ }
+ case 3: // Availability
+ if book, ok := library.Books[isbn]; !ok {
+ response.Err = errors.New("Непозната книга " + isbn)
+ } else if book.Available >= 4 {
+ response.Err = errors.New("Всички копия са налични " + isbn)
+ }
+ }
+
+ if book, ok := library.Books[isbn]; ok {
+ response.Book = book.Book
+ response.Available = book.Available
+ response.All = book.All
+ } else {
+ response.All = 0
+ response.Available = 0
+ }
+
+ l.output <- response
+ }
+
+ l.input = make(chan LibraryRequest)
+ librarians <- *l
+ }()
+}
+
+type BookCopies struct {
+ Book
+ Available, All int
+}
+
+type LibraryOfAlexandria struct {
+ Books map[string]*BookCopies
+ booksLock sync.Mutex
+ librarians chan Librarian
+}
+
+func (lib LibraryOfAlexandria) AddBookJSON(data []byte) (int, error) {
+ var book Book
+ if err := json.Unmarshal(data, &book); err != nil {
+ return 0, err
+ }
+
+ return lib.addBook(book)
+}
+
+func (lib LibraryOfAlexandria) AddBookXML(data []byte) (int, error) {
+ var book Book
+ if err := xml.Unmarshal(data, &book); err != nil {
+ return 0, err
+ }
+
+ return lib.addBook(book)
+}
+
+func (lib *LibraryOfAlexandria) addBook(book Book) (int, error) {
+ lib.booksLock.Lock()
+
+ if lib.Books[book.ISBN] == nil {
+ lib.Books[book.ISBN] = new(BookCopies)
+ lib.Books[book.ISBN].Book = book
+ } else if lib.Books[book.ISBN].All >= 4 {
+ return 0, errors.New("Има 4 копия на книга " + book.ISBN)
+ }
+
+ lib.Books[book.ISBN].Available += 1
+ lib.Books[book.ISBN].All += 1
+
+ lib.booksLock.Unlock()
+
+ return lib.Books[book.ISBN].All, nil
+}
+
+func (lib LibraryOfAlexandria) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+ var librarian Librarian
+ var ok bool
+ // try take from the pool until we get a librarian
+ for librarian, ok = <-lib.librarians; !ok; {
+ }
+
+ return librarian.input, librarian.output
+}
+
+type Request struct {
+ RequestType int
+ Book
+}
+
+func (req Request) GetType() int {
+ return req.RequestType
+}
+
+func (req Request) GetISBN() string {
+ return req.ISBN
+}
+
+type Response struct {
+ Book
+ Err error
+ Available, All int
+}
+
+func (res *Response) GetBook() (fmt.Stringer, error) {
+ return res.Book, res.Err
+}
+
+func (res *Response) GetAvailability() (available int, registered int) {
+ return res.Available, res.All
+}
+
+type Author struct {
+ FirstName string `json:"first_name" xml:"author>first_name"`
+ LastName string `json:"last_name" xml:"author>last_name"`
+}
+
+type Book struct {
+ ISBN string `xml:"isbn,attr"`
+ Title string `xml:"title"`
+ Author `json:"author"`
+ Ratings []int
+}
+
+func (b Book) String() string {
+ return fmt.Sprintf("[%s] %s от %s %s", b.ISBN, b.Title, b.Author.FirstName, b.Author.LastName)
+}
+
+func NewLibrary(librarians int) LibraryOfAlexandria {
+ library := &LibraryOfAlexandria{Books: make(map[string]*BookCopies), librarians: make(chan Librarian, librarians)}
+
+ for i := 0; i < librarians; i++ {
+ librarian := &Librarian{input: make(chan LibraryRequest), output: make(chan LibraryResponse)}
+ library.librarians <- *librarian
+ librarian.Animate(library, library.librarians)
+ }
+
+ return *library
+}

Михаил обнови решението на 06.12.2015 17:08 (преди над 2 години)

package solution
import (
"encoding/json"
"encoding/xml"
"errors"
"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 Librarian struct {
input chan LibraryRequest
output chan LibraryResponse
}
func (l *Librarian) Animate(library *LibraryOfAlexandria, librarians chan Librarian) {
go func() {
for request := range l.input {
isbn := request.GetISBN()
response := new(Response)
+
switch request.GetType() {
case 1: // Borrow
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available < 1 {
response.Err = errors.New("Няма наличност на книга " + isbn)
} else {
+ response.Book = book.Book
book.Available -= 1
}
case 2: // Return
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
- } else if book.Available >= 4 {
+ } else if book.Available >= book.All {
response.Err = errors.New("Всички копия са налични " + isbn)
} else {
+ response.Book = book.Book
book.Available += 1
}
case 3: // Availability
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available >= 4 {
response.Err = errors.New("Всички копия са налични " + isbn)
+ } else {
+ response.Book = book.Book
}
}
if book, ok := library.Books[isbn]; ok {
- response.Book = book.Book
response.Available = book.Available
response.All = book.All
} else {
response.All = 0
response.Available = 0
}
l.output <- response
}
l.input = make(chan LibraryRequest)
librarians <- *l
}()
}
type BookCopies struct {
Book
Available, All int
}
type LibraryOfAlexandria struct {
Books map[string]*BookCopies
booksLock sync.Mutex
librarians chan Librarian
}
func (lib LibraryOfAlexandria) AddBookJSON(data []byte) (int, error) {
var book Book
if err := json.Unmarshal(data, &book); err != nil {
return 0, err
}
return lib.addBook(book)
}
func (lib LibraryOfAlexandria) AddBookXML(data []byte) (int, error) {
var book Book
if err := xml.Unmarshal(data, &book); err != nil {
return 0, err
}
return lib.addBook(book)
}
func (lib *LibraryOfAlexandria) addBook(book Book) (int, error) {
lib.booksLock.Lock()
if lib.Books[book.ISBN] == nil {
lib.Books[book.ISBN] = new(BookCopies)
lib.Books[book.ISBN].Book = book
} else if lib.Books[book.ISBN].All >= 4 {
- return 0, errors.New("Има 4 копия на книга " + book.ISBN)
+ return lib.Books[book.ISBN].All, errors.New("Има 4 копия на книга " + book.ISBN)
}
lib.Books[book.ISBN].Available += 1
lib.Books[book.ISBN].All += 1
lib.booksLock.Unlock()
return lib.Books[book.ISBN].All, nil
}
func (lib LibraryOfAlexandria) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
var librarian Librarian
var ok bool
// try take from the pool until we get a librarian
for librarian, ok = <-lib.librarians; !ok; {
}
return librarian.input, librarian.output
}
type Request struct {
RequestType int
Book
}
func (req Request) GetType() int {
return req.RequestType
}
func (req Request) GetISBN() string {
return req.ISBN
}
type Response struct {
Book
Err error
Available, All int
}
func (res *Response) GetBook() (fmt.Stringer, error) {
+ if res.Book.ISBN == "" {
+ return nil, res.Err
+ }
return res.Book, res.Err
}
func (res *Response) GetAvailability() (available int, registered int) {
return res.Available, res.All
}
type Author struct {
FirstName string `json:"first_name" xml:"author>first_name"`
LastName string `json:"last_name" xml:"author>last_name"`
}
type Book struct {
ISBN string `xml:"isbn,attr"`
Title string `xml:"title"`
Author `json:"author"`
Ratings []int
}
func (b Book) String() string {
return fmt.Sprintf("[%s] %s от %s %s", b.ISBN, b.Title, b.Author.FirstName, b.Author.LastName)
}
func NewLibrary(librarians int) LibraryOfAlexandria {
library := &LibraryOfAlexandria{Books: make(map[string]*BookCopies), librarians: make(chan Librarian, librarians)}
for i := 0; i < librarians; i++ {
librarian := &Librarian{input: make(chan LibraryRequest), output: make(chan LibraryResponse)}
library.librarians <- *librarian
librarian.Animate(library, library.librarians)
}
return *library
}

Михаил обнови решението на 06.12.2015 17:10 (преди над 2 години)

-package solution
+package main
import (
"encoding/json"
"encoding/xml"
"errors"
"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 Librarian struct {
input chan LibraryRequest
output chan LibraryResponse
}
func (l *Librarian) Animate(library *LibraryOfAlexandria, librarians chan Librarian) {
go func() {
for request := range l.input {
isbn := request.GetISBN()
response := new(Response)
switch request.GetType() {
case 1: // Borrow
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available < 1 {
response.Err = errors.New("Няма наличност на книга " + isbn)
} else {
response.Book = book.Book
book.Available -= 1
}
case 2: // Return
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available >= book.All {
response.Err = errors.New("Всички копия са налични " + isbn)
} else {
response.Book = book.Book
book.Available += 1
}
case 3: // Availability
if book, ok := library.Books[isbn]; !ok {
response.Err = errors.New("Непозната книга " + isbn)
} else if book.Available >= 4 {
response.Err = errors.New("Всички копия са налични " + isbn)
} else {
response.Book = book.Book
}
}
if book, ok := library.Books[isbn]; ok {
response.Available = book.Available
response.All = book.All
} else {
response.All = 0
response.Available = 0
}
l.output <- response
}
l.input = make(chan LibraryRequest)
librarians <- *l
}()
}
type BookCopies struct {
Book
Available, All int
}
type LibraryOfAlexandria struct {
Books map[string]*BookCopies
booksLock sync.Mutex
librarians chan Librarian
}
func (lib LibraryOfAlexandria) AddBookJSON(data []byte) (int, error) {
var book Book
if err := json.Unmarshal(data, &book); err != nil {
return 0, err
}
return lib.addBook(book)
}
func (lib LibraryOfAlexandria) AddBookXML(data []byte) (int, error) {
var book Book
if err := xml.Unmarshal(data, &book); err != nil {
return 0, err
}
return lib.addBook(book)
}
func (lib *LibraryOfAlexandria) addBook(book Book) (int, error) {
lib.booksLock.Lock()
if lib.Books[book.ISBN] == nil {
lib.Books[book.ISBN] = new(BookCopies)
lib.Books[book.ISBN].Book = book
} else if lib.Books[book.ISBN].All >= 4 {
return lib.Books[book.ISBN].All, errors.New("Има 4 копия на книга " + book.ISBN)
}
lib.Books[book.ISBN].Available += 1
lib.Books[book.ISBN].All += 1
lib.booksLock.Unlock()
return lib.Books[book.ISBN].All, nil
}
func (lib LibraryOfAlexandria) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
var librarian Librarian
var ok bool
// try take from the pool until we get a librarian
for librarian, ok = <-lib.librarians; !ok; {
}
return librarian.input, librarian.output
}
type Request struct {
RequestType int
Book
}
func (req Request) GetType() int {
return req.RequestType
}
func (req Request) GetISBN() string {
return req.ISBN
}
type Response struct {
Book
Err error
Available, All int
}
func (res *Response) GetBook() (fmt.Stringer, error) {
if res.Book.ISBN == "" {
return nil, res.Err
}
return res.Book, res.Err
}
func (res *Response) GetAvailability() (available int, registered int) {
return res.Available, res.All
}
type Author struct {
FirstName string `json:"first_name" xml:"author>first_name"`
LastName string `json:"last_name" xml:"author>last_name"`
}
type Book struct {
ISBN string `xml:"isbn,attr"`
Title string `xml:"title"`
Author `json:"author"`
Ratings []int
}
func (b Book) String() string {
return fmt.Sprintf("[%s] %s от %s %s", b.ISBN, b.Title, b.Author.FirstName, b.Author.LastName)
}
func NewLibrary(librarians int) LibraryOfAlexandria {
library := &LibraryOfAlexandria{Books: make(map[string]*BookCopies), librarians: make(chan Librarian, librarians)}
for i := 0; i < librarians; i++ {
librarian := &Librarian{input: make(chan LibraryRequest), output: make(chan LibraryResponse)}
library.librarians <- *librarian
librarian.Animate(library, library.librarians)
}
return *library
}