Решение на Concurrent Tasks от Ралица Великова

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

Към профила на Ралица Великова

Резултати

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

Код

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 DogeLibrarySizeError struct {
isbn string
}
func (d DogeLibrarySizeError) Error() string {
return "Има 4 копия на книга " + d.isbn
}
type AuthorType struct {
First_name string `xml:"first_name"`
Last_name string `xml:"last_name"`
}
type Book struct {
XMLName xml.Name `xml:"book"`
Isbn string `xml:"isbn,attr"`
Title string `xml:"title"`
Author AuthorType `xml:"author"`
Ratings []int `xml:"ratings>rating"`
Pages int `xml:"pages"`
Genre string `xml:"genre"`
}
func (b Book) String() string {
var (
isbn = b.Isbn
title = b.Title
firstNameOfAuthor = b.Author.First_name
lastNameOfAuthor = b.Author.Last_name
)
return "[" + isbn + "] " + title + " от " + firstNameOfAuthor + " " + lastNameOfAuthor
}
type BookItem struct {
book *Book
count int
registered int
}
type DogeLibrary struct {
books map[string]*BookItem
librarians int
sem chan struct{}
mutex sync.RWMutex
}
func (d *DogeLibrary) AddBookJSON(data []byte) (int, error) {
var (
book Book
unmarshalError error
)
unmarshalError = json.Unmarshal(data, &book)
if unmarshalError != nil {
panic(fmt.Sprintf("%v", unmarshalError))
}
var (
copiesCount = d.getAvailable(book.Isbn)
sizeError *DogeLibrarySizeError
)
if copiesCount >= 4 {
sizeError = &DogeLibrarySizeError{isbn: book.Isbn}
} else {
d.addBook(book)
}
return copiesCount, sizeError
}
func (d *DogeLibrary) AddBookXML(data []byte) (int, error) {
var (
book Book
unmarshalError error
)
unmarshalError = xml.Unmarshal(data, &book)
if unmarshalError != nil {
panic(fmt.Sprintf("%v", unmarshalError))
}
var (
copiesCount = d.getAvailable(book.Isbn)
sizeError *DogeLibrarySizeError
)
if copiesCount >= 4 {
sizeError = &DogeLibrarySizeError{isbn: book.Isbn}
} else {
d.addBook(book)
}
return copiesCount, sizeError
}
func NewLibrary(librarians int) Library {
var d = new(DogeLibrary)
d.books = make(map[string]*BookItem)
d.librarians = librarians
d.sem = make(chan struct{}, d.librarians)
for i := 0; i < d.librarians; i++ {
d.sem <- struct{}{}
}
return d
}
func (d *DogeLibrary) getAvailable(isbn string) int {
if d.exists(isbn) {
var bookItem = d.books[isbn]
return bookItem.count
} else {
return 0
}
}
func (d *DogeLibrary) getRegistered(isbn string) int {
if d.exists(isbn) {
var bookItem = d.books[isbn]
return bookItem.registered
} else {
return 0
}
}
func (d *DogeLibrary) exists(isbn string) bool {
var _, exists = d.books[isbn]
return exists
}
func (d *DogeLibrary) addBook(b Book) bool {
if d.exists(b.Isbn) {
var bookItem = d.books[b.Isbn]
if bookItem.registered+1 > 4 {
return false
} else {
bookItem.count++
bookItem.registered++
}
} else {
d.books[b.Isbn] = &BookItem{book: &b, count: 1, registered: 1}
}
return true
}
func (d *DogeLibrary) removeBook(isbn string) (*Book, bool) {
if d.exists(isbn) {
var bookItem = d.books[isbn]
bookItem.count--
return bookItem.book, true
} else {
return nil, false
}
}
type ErrorUnknownBook struct {
message string
}
func (e *ErrorUnknownBook) Error() string {
return e.message
}
func (d *DogeLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
<-d.sem
var libraryRequestChannel = make(chan LibraryRequest)
var libraryResponseChannel = make(chan LibraryResponse, 1)
go func() {
for request := range libraryRequestChannel {
var requestType = request.GetType()
var isbn = request.GetISBN()
var response = new(DogeLibraryResponse)
d.mutex.Lock()
if d.exists(isbn) {
response.registered = d.getRegistered(isbn)
response.available = d.getAvailable(isbn)
response.error = nil
} else {
response.registered = 0
response.available = 0
response.error = &ErrorUnknownBook{message: "Непозната книга " + isbn}
}
if requestType == 1 {
var book, _ = d.removeBook(isbn)
response.book = book
} else if requestType == 2 {
//~ d.returnBook(isbn)
response.book = nil
} else if requestType == 3 {
//
}
d.mutex.Unlock()
libraryResponseChannel <- response
}
d.sem <- struct{}{}
}()
return libraryRequestChannel, libraryResponseChannel
}
type DogeLibraryResponse struct {
registered int
available int
book *Book
error error
}
func (d *DogeLibraryResponse) GetBook() (fmt.Stringer, error) {
return d.book, d.error
}
func (d *DogeLibraryResponse) GetAvailability() (available int, registered int) {
return d.available, d.registered
}

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

PASS
ok  	_/tmp/d20151207-5667-1x6vrhl	0.003s
--- FAIL: TestAddBookJSON (0.00s)
	solution_test.go:82: [solution_test.go:106] Expected:
		<nil>
		Got:
		<nil>
		Context: Error when adding a valid book
	solution_test.go:82: [solution_test.go:107] Expected:
		1
		Got:
		0
		Context: first book added
	solution_test.go:82: [solution_test.go:110] Expected:
		2
		Got:
		1
		Context: first book added 2nd time
	solution_test.go:82: [solution_test.go:113] Expected:
		3
		Got:
		2
		Context: first book added 3rd time
	solution_test.go:82: [solution_test.go:116] Expected:
		4
		Got:
		3
		Context: first book added 4th time
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1x6vrhl	0.004s
--- FAIL: TestAddBookXML (0.00s)
	solution_test.go:82: [solution_test.go:136] Expected:
		<nil>
		Got:
		<nil>
		Context: Error when adding a valid book
	solution_test.go:82: [solution_test.go:137] Expected:
		1
		Got:
		0
		Context: first book added
	solution_test.go:82: [solution_test.go:140] Expected:
		2
		Got:
		1
		Context: first book added 2nd time
	solution_test.go:82: [solution_test.go:143] Expected:
		3
		Got:
		2
		Context: first book added 3rd time
	solution_test.go:82: [solution_test.go:146] Expected:
		4
		Got:
		3
		Context: first book added 4th time
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1x6vrhl	0.004s
--- FAIL: TestAddBookCombined (0.00s)
	solution_test.go:82: [solution_test.go:167] Expected:
		<nil>
		Got:
		<nil>
		Context: Error when adding a valid book
	solution_test.go:82: [solution_test.go:168] Expected:
		1
		Got:
		0
		Context: first book added
	solution_test.go:82: [solution_test.go:171] Expected:
		<nil>
		Got:
		<nil>
		Context: Error when adding a valid book
	solution_test.go:82: [solution_test.go:172] Expected:
		2
		Got:
		1
		Context: first book added 2nd time
	solution_test.go:82: [solution_test.go:175] Expected:
		3
		Got:
		2
		Context: first book added 3rd time
	solution_test.go:82: [solution_test.go:176] Expected:
		<nil>
		Got:
		<nil>
		Context: Error when adding a valid book
	solution_test.go:82: [solution_test.go:179] Expected:
		4
		Got:
		3
		Context: first book added 4th time
	solution_test.go:82: [solution_test.go:180] Expected:
		<nil>
		Got:
		<nil>
		Context: Error when adding a valid book
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1x6vrhl	0.004s
--- FAIL: TestBookAvailability (0.00s)
	solution_test.go:82: [solution_test.go:202] Expected:
		<nil>
		Got:
		<nil>
		Context: error when adding a valid book
	solution_test.go:82: [solution_test.go:203] Expected:
		1
		Got:
		0
		Context: first book added 1st time
	solution_test.go:82: [solution_test.go:206] Expected:
		<nil>
		Got:
		<nil>
		Context: error when adding a valid book
	solution_test.go:82: [solution_test.go:207] Expected:
		2
		Got:
		1
		Context: first book added 2nd time
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1x6vrhl	0.004s
--- FAIL: TestTakeBookRequest (0.00s)
	solution_test.go:82: [solution_test.go:244] Expected:
		1
		Got:
		2
		Context:  available books left...
	solution_test.go:82: [solution_test.go:244] Expected:
		0
		Got:
		2
		Context:  available books left...
	solution_test.go:255: Expected error but got nil
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1x6vrhl	0.004s
PASS
ok  	_/tmp/d20151207-5667-1x6vrhl	0.003s
PASS
ok  	_/tmp/d20151207-5667-1x6vrhl	0.003s
--- FAIL: TestReturnSomeBooks (0.00s)
	solution_test.go:82: [solution_test.go:345] Expected:
		1
		Got:
		2
		Context: Available should increment with one
	solution_test.go:82: [solution_test.go:345] Expected:
		0
		Got:
		2
		Context: Available should increment with one
	solution_test.go:82: [solution_test.go:347] Expected:
		-1
		Got:
		1
		Context: all books to be returned
	solution_test.go:351: Expected error got nil
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1x6vrhl	0.004s
PASS
ok  	_/tmp/d20151207-5667-1x6vrhl	0.003s

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

Ралица обнови решението на 06.12.2015 17:58 (преди над 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 DogeLibrarySizeError struct {
+ isbn string
+}
+
+func (d DogeLibrarySizeError) Error() string {
+ return "Има 4 копия на книга " + d.isbn
+}
+
+type AuthorType struct {
+ First_name string `xml:"first_name"`
+ Last_name string `xml:"last_name"`
+}
+
+type Book struct {
+ XMLName xml.Name `xml:"book"`
+ Isbn string `xml:"isbn,attr"`
+ Title string `xml:"title"`
+ Author AuthorType `xml:"author"`
+ Ratings []int `xml:"ratings>rating"`
+ Pages int `xml:"pages"`
+ Genre string `xml:"genre"`
+}
+
+func (b Book) String() string {
+ var (
+ isbn = b.Isbn
+ title = b.Title
+ firstNameOfAuthor = b.Author.First_name
+ lastNameOfAuthor = b.Author.Last_name
+ )
+
+ return "[" + isbn + "] " + title + " от " + firstNameOfAuthor + " " + lastNameOfAuthor
+}
+
+type BookItem struct {
+ book *Book
+ count int
+ registered int
+}
+
+type DogeLibrary struct {
+ books map[string]*BookItem
+ librarians int
+ sem chan struct{}
+ mutex sync.RWMutex
+}
+
+func (d *DogeLibrary) AddBookJSON(data []byte) (int, error) {
+ var (
+ book Book
+ unmarshalError error
+ )
+
+ unmarshalError = json.Unmarshal(data, &book)
+ if unmarshalError != nil {
+ panic(fmt.Sprintf("%v", unmarshalError))
+ }
+
+ var (
+ copiesCount = d.getAvailable(book.Isbn)
+ sizeError *DogeLibrarySizeError
+ )
+
+ if copiesCount >= 4 {
+ sizeError = &DogeLibrarySizeError{isbn: book.Isbn}
+ } else {
+ d.addBook(book)
+ }
+
+ return copiesCount, sizeError
+}
+
+func (d *DogeLibrary) AddBookXML(data []byte) (int, error) {
+ var (
+ book Book
+ unmarshalError error
+ )
+
+ unmarshalError = xml.Unmarshal(data, &book)
+ if unmarshalError != nil {
+ panic(fmt.Sprintf("%v", unmarshalError))
+ }
+
+ var (
+ copiesCount = d.getAvailable(book.Isbn)
+ sizeError *DogeLibrarySizeError
+ )
+
+ if copiesCount >= 4 {
+ sizeError = &DogeLibrarySizeError{isbn: book.Isbn}
+ } else {
+ d.addBook(book)
+ }
+
+ return copiesCount, sizeError
+}
+
+func NewLibrary(librarians int) Library {
+
+ var d = new(DogeLibrary)
+ d.books = make(map[string]*BookItem)
+ d.librarians = librarians
+ d.sem = make(chan struct{}, d.librarians)
+
+ for i := 0; i < d.librarians; i++ {
+ d.sem <- struct{}{}
+ }
+
+ return d
+}
+
+func (d *DogeLibrary) getAvailable(isbn string) int {
+ if d.exists(isbn) {
+ var bookItem = d.books[isbn]
+ return bookItem.count
+ } else {
+ return 0
+ }
+}
+
+func (d *DogeLibrary) getRegistered(isbn string) int {
+ if d.exists(isbn) {
+ var bookItem = d.books[isbn]
+ return bookItem.registered
+ } else {
+ return 0
+ }
+}
+
+func (d *DogeLibrary) exists(isbn string) bool {
+ var _, exists = d.books[isbn]
+ return exists
+}
+
+func (d *DogeLibrary) addBook(b Book) bool {
+ if d.exists(b.Isbn) {
+ var bookItem = d.books[b.Isbn]
+ if bookItem.registered+1 > 4 {
+ return false
+ } else {
+ bookItem.count++
+ bookItem.registered++
+ }
+ } else {
+ d.books[b.Isbn] = &BookItem{book: &b, count: 1, registered: 1}
+ }
+
+ return true
+}
+
+func (d *DogeLibrary) removeBook(isbn string) (*Book, bool) {
+ if d.exists(isbn) {
+ var bookItem = d.books[isbn]
+ bookItem.count--
+ return bookItem.book, true
+ } else {
+ return nil, false
+ }
+}
+
+type ErrorUnknownBook struct {
+ message string
+}
+
+func (e *ErrorUnknownBook) Error() string {
+ return e.message
+}
+
+func (d *DogeLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+
+ <-d.sem
+
+ var libraryRequestChannel = make(chan LibraryRequest)
+ var libraryResponseChannel = make(chan LibraryResponse, 1)
+
+ go func() {
+ for request := range libraryRequestChannel {
+
+ var requestType = request.GetType()
+ var isbn = request.GetISBN()
+
+ var response = new(DogeLibraryResponse)
+
+ d.mutex.Lock()
+ if d.exists(isbn) {
+ response.registered = d.getRegistered(isbn)
+ response.available = d.getAvailable(isbn)
+ response.error = nil
+ } else {
+ response.registered = 0
+ response.available = 0
+ response.error = &ErrorUnknownBook{message: "Непозната книга " + isbn}
+ }
+
+ if requestType == 1 {
+ var book, _ = d.removeBook(isbn)
+ response.book = book
+ } else if requestType == 2 {
+ //~ d.returnBook(isbn)
+ response.book = nil
+ } else if requestType == 3 {
+ //
+ }
+
+ d.mutex.Unlock()
+
+ libraryResponseChannel <- response
+ }
+
+ d.sem <- struct{}{}
+ }()
+
+ return libraryRequestChannel, libraryResponseChannel
+}
+
+type DogeLibraryResponse struct {
+ registered int
+ available int
+ book *Book
+ error error
+}
+
+func (d *DogeLibraryResponse) GetBook() (fmt.Stringer, error) {
+ return d.book, d.error
+}
+
+func (d *DogeLibraryResponse) GetAvailability() (available int, registered int) {
+ return d.available, d.registered
+}
+
+func Dump(d *DogeLibrary) {
+ for _, book := range d.books {
+ fmt.Println(book)
+ }
+}
+
+func main() {
+ var json = []byte(`{
+ "isbn": "0954540018",
+ "title": "Who Said the Race is Over?",
+ "author": {
+ "first_name": "Anno",
+ "last_name": "Birkin"
+ },
+ "genre": "poetry",
+ "pages": 80,
+ "ratings": [5, 4, 4, 5, 3]
+ }`)
+
+ var xml = []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>
+ `)
+
+ var lib = NewLibrary(16)
+
+ lib.AddBookJSON(json)
+ lib.AddBookXML(xml)
+
+ Dump(lib.(*DogeLibrary))
+}

Ралица обнови решението на 06.12.2015 17:59 (преди над 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 DogeLibrarySizeError struct {
isbn string
}
func (d DogeLibrarySizeError) Error() string {
return "Има 4 копия на книга " + d.isbn
}
type AuthorType struct {
First_name string `xml:"first_name"`
Last_name string `xml:"last_name"`
}
type Book struct {
XMLName xml.Name `xml:"book"`
Isbn string `xml:"isbn,attr"`
Title string `xml:"title"`
Author AuthorType `xml:"author"`
Ratings []int `xml:"ratings>rating"`
Pages int `xml:"pages"`
Genre string `xml:"genre"`
}
func (b Book) String() string {
var (
isbn = b.Isbn
title = b.Title
firstNameOfAuthor = b.Author.First_name
lastNameOfAuthor = b.Author.Last_name
)
return "[" + isbn + "] " + title + " от " + firstNameOfAuthor + " " + lastNameOfAuthor
}
type BookItem struct {
book *Book
count int
registered int
}
type DogeLibrary struct {
books map[string]*BookItem
librarians int
sem chan struct{}
mutex sync.RWMutex
}
func (d *DogeLibrary) AddBookJSON(data []byte) (int, error) {
var (
book Book
unmarshalError error
)
unmarshalError = json.Unmarshal(data, &book)
if unmarshalError != nil {
panic(fmt.Sprintf("%v", unmarshalError))
}
var (
copiesCount = d.getAvailable(book.Isbn)
sizeError *DogeLibrarySizeError
)
if copiesCount >= 4 {
sizeError = &DogeLibrarySizeError{isbn: book.Isbn}
} else {
d.addBook(book)
}
return copiesCount, sizeError
}
func (d *DogeLibrary) AddBookXML(data []byte) (int, error) {
var (
book Book
unmarshalError error
)
unmarshalError = xml.Unmarshal(data, &book)
if unmarshalError != nil {
panic(fmt.Sprintf("%v", unmarshalError))
}
var (
copiesCount = d.getAvailable(book.Isbn)
sizeError *DogeLibrarySizeError
)
if copiesCount >= 4 {
sizeError = &DogeLibrarySizeError{isbn: book.Isbn}
} else {
d.addBook(book)
}
return copiesCount, sizeError
}
func NewLibrary(librarians int) Library {
var d = new(DogeLibrary)
d.books = make(map[string]*BookItem)
d.librarians = librarians
d.sem = make(chan struct{}, d.librarians)
for i := 0; i < d.librarians; i++ {
d.sem <- struct{}{}
}
return d
}
func (d *DogeLibrary) getAvailable(isbn string) int {
if d.exists(isbn) {
var bookItem = d.books[isbn]
return bookItem.count
} else {
return 0
}
}
func (d *DogeLibrary) getRegistered(isbn string) int {
if d.exists(isbn) {
var bookItem = d.books[isbn]
return bookItem.registered
} else {
return 0
}
}
func (d *DogeLibrary) exists(isbn string) bool {
var _, exists = d.books[isbn]
return exists
}
func (d *DogeLibrary) addBook(b Book) bool {
if d.exists(b.Isbn) {
var bookItem = d.books[b.Isbn]
if bookItem.registered+1 > 4 {
return false
} else {
bookItem.count++
bookItem.registered++
}
} else {
d.books[b.Isbn] = &BookItem{book: &b, count: 1, registered: 1}
}
return true
}
func (d *DogeLibrary) removeBook(isbn string) (*Book, bool) {
if d.exists(isbn) {
var bookItem = d.books[isbn]
bookItem.count--
return bookItem.book, true
} else {
return nil, false
}
}
type ErrorUnknownBook struct {
message string
}
func (e *ErrorUnknownBook) Error() string {
return e.message
}
func (d *DogeLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
<-d.sem
var libraryRequestChannel = make(chan LibraryRequest)
var libraryResponseChannel = make(chan LibraryResponse, 1)
go func() {
for request := range libraryRequestChannel {
var requestType = request.GetType()
var isbn = request.GetISBN()
var response = new(DogeLibraryResponse)
d.mutex.Lock()
if d.exists(isbn) {
response.registered = d.getRegistered(isbn)
response.available = d.getAvailable(isbn)
response.error = nil
} else {
response.registered = 0
response.available = 0
response.error = &ErrorUnknownBook{message: "Непозната книга " + isbn}
}
if requestType == 1 {
var book, _ = d.removeBook(isbn)
response.book = book
} else if requestType == 2 {
//~ d.returnBook(isbn)
response.book = nil
} else if requestType == 3 {
//
}
d.mutex.Unlock()
libraryResponseChannel <- response
}
d.sem <- struct{}{}
}()
return libraryRequestChannel, libraryResponseChannel
}
type DogeLibraryResponse struct {
registered int
available int
book *Book
error error
}
func (d *DogeLibraryResponse) GetBook() (fmt.Stringer, error) {
return d.book, d.error
}
func (d *DogeLibraryResponse) GetAvailability() (available int, registered int) {
return d.available, d.registered
}
-func Dump(d *DogeLibrary) {
- for _, book := range d.books {
- fmt.Println(book)
- }
-}
-func main() {
- var json = []byte(`{
- "isbn": "0954540018",
- "title": "Who Said the Race is Over?",
- "author": {
- "first_name": "Anno",
- "last_name": "Birkin"
- },
- "genre": "poetry",
- "pages": 80,
- "ratings": [5, 4, 4, 5, 3]
- }`)
-
- var xml = []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>
- `)
-
- var lib = NewLibrary(16)
-
- lib.AddBookJSON(json)
- lib.AddBookXML(xml)
-
- Dump(lib.(*DogeLibrary))
-}