Решение на Concurrent Tasks от Стефани Стоянова

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

Към профила на Стефани Стоянова

Резултати

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

Код

package main
import (
"encoding/json"
"encoding/xml"
"fmt"
)
type Library interface {
// Добавя книга от json
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Aко са повече от 4 - връща грешка
AddBookJSON(data []byte) (int, error)
// Добавя книга от xml
// Oтговаря с общия брой копия в библиотеката (не само наличните).
// Ако са повече от 4 - връщаме грешка
AddBookXML(data []byte) (int, error)
// Ангажира свободен "библиотекар" да ни обработва заявките.
// Библиотекарите са фиксиран брой - подават се като параметър на NewLibrary
// Блокира ако всички библиотекари са заети.
// Връщат се два канала:
// първият е само за писане - по него ще изпращаме заявките
// вторият е само за четене - по него ще получаваме отговорите.
// Ако затворим канала със заявките - освобождаваме библиотекаря.
Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
}
type LibraryRequest interface {
// Тип на заявката:
// 1 - Borrow book
// 2 - Return book
// 3 - Get availability information about book
GetType() int
// Връща isbn на книгата, за която се отнася Request-a
GetISBN() string
}
type LibraryResponse interface {
// Ако книгата съществува/налична е - обект имплементиращ fmt.Stringer (повече информация по-долу)
// Aко книгата не съществува първият резултат е nil.
// Връща се и подобаващa грешка (виж по-долу) - ако такава е възникнала.
// Когато се е резултат на заявка от тип 2 (Return book) - не е нужно да я закачаме към отговора.
GetBook() (fmt.Stringer, error)
// available - Колко наличности от книгата имаме останали след изпълнението на заявката.
// Тоест, ако сме имали 3 копия от Х и това е отговор на Borrow заявка - тук ще има 2.
// registered - Колко копия от тази книга има регистрирани в библиотеката (макс 4).
GetAvailability() (available int, registered int)
}
type MyRequest struct {
reqType int
isbn string
}
func (req MyRequest) GetType() int {
return req.reqType
}
func (req MyRequest) GetISBN() string {
return req.isbn
}
type MyResponse struct {
book Book
availability int
registered int
error string
}
func (response MyResponse) GetBook() (fmt.Stringer, error) {
if response.error != "" {
return nil, errorString{response.error}
}
return response.book, nil
}
func (book Book) String() string {
return "[" + book.Isbn + "] " + book.Title + " от " + book.Author.FirstName + " " + book.Author.LastName
}
func (response MyResponse) GetAvailability() (available int, registered int) {
return response.availability, response.registered
}
// Връща "отворена" библиотека
func NewLibrary(librarians int) Library {
return &MyLibrary{
allLibrarians: librarians,
busyLibrarians: 0,
books: []Book{},
bookAvailable: map[string]int{},
bookRegistered: map[string]int{},
}
}
type Author struct {
FirstName string `json:"first_name" xml:"first_name"`
LastName string `json:"last_name" xml:"last_name"`
}
type Book struct {
Isbn string `json:"isbn" xml:"isbn,attr"`
Author Author `json:"author" xml:"author"`
Title string `json:"title" xml:"title"`
Ratings []int `json:"ratings" xml:"ratings>rating"`
}
type MyLibrary struct {
allLibrarians int
busyLibrarians int
books []Book
bookAvailable map[string]int
bookRegistered map[string]int
}
func (library *MyLibrary) AddBookJSON(data []byte) (int, error) {
var book Book
json.Unmarshal(data, &book)
val, ok := library.bookRegistered[book.Isbn]
if !ok {
library.books = append(library.books, book)
} else if val >= 4 {
return val, errorString{"Има 4 копия на книга <" + book.Isbn + ">"}
}
library.bookRegistered[book.Isbn]++
library.bookAvailable[book.Isbn]++
return library.bookRegistered[book.Isbn], nil
}
func (library *MyLibrary) AddBookXML(data []byte) (int, error) {
var book Book
xml.Unmarshal(data, &book)
val, ok := library.bookRegistered[book.Isbn]
if !ok {
library.books = append(library.books, book)
} else if val >= 4 {
return val, errorString{"Има 4 копия на книга " + book.Isbn}
}
library.bookRegistered[book.Isbn]++
library.bookAvailable[book.Isbn]++
return library.bookRegistered[book.Isbn], nil
}
type errorString struct {
errorMsg string
}
func (e errorString) Error() string {
return e.errorMsg
}
func (library *MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
if library.allLibrarians-library.busyLibrarians >= 0 {
//blokira
} else {
library.busyLibrarians++
}
in := make(chan LibraryRequest)
out := make(chan LibraryResponse)
go func() {
for req := range in {
if req.GetType() == 1 { //borrow
resp := MyResponse{
availability: library.bookAvailable[req.GetISBN()],
registered: library.bookRegistered[req.GetISBN()],
error: "",
}
if resp.registered == 0 {
resp.error = "Непозната книга " + req.GetISBN()
} else if resp.availability <= 0 {
resp.error = "Няма наличност на книга " + req.GetISBN()
} else {
for _, book := range library.books {
if book.Isbn == req.GetISBN() {
resp.book = book
break
}
library.bookAvailable[req.GetISBN()]--
resp.availability--
}
}
out <- resp
} else if req.GetType() == 2 { //return
resp := MyResponse{
availability: library.bookAvailable[req.GetISBN()],
registered: library.bookRegistered[req.GetISBN()],
error: "",
}
if resp.registered == 0 {
resp.error = "Непозната книга " + req.GetISBN()
} else if resp.registered-resp.availability <= 0 {
resp.error = "Всички копия са налични " + req.GetISBN()
} else {
for _, book := range library.books {
if book.Isbn == req.GetISBN() {
resp.book = book
break
}
library.bookAvailable[req.GetISBN()]++
resp.availability++
}
}
out <- resp
} else if req.GetType() == 3 {
resp := MyResponse{
availability: library.bookAvailable[req.GetISBN()],
registered: library.bookRegistered[req.GetISBN()],
error: "",
}
if resp.registered == 0 {
resp.error = "Непозната книга " + req.GetISBN()
} else {
for _, book := range library.books {
if book.Isbn == req.GetISBN() {
resp.book = book
break
}
}
}
out <- resp
}
}
}()
return in, out
}

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

PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.003s
--- FAIL: TestAddBookJSON (0.00s)
	solution_test.go:82: [solution_test.go:119] Expected:
		Има 4 копия на книга 0954540018
		Got:
		<nil>
		Context: Error when adding a book for 5th time
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1noag5l	0.004s
PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.004s
PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.004s
PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.003s
--- FAIL: TestTakeBookRequest (0.00s)
	solution_test.go:82: [solution_test.go:244] Expected:
		3
		Got:
		4
		Context:  available books left...
	solution_test.go:82: [solution_test.go:244] Expected:
		2
		Got:
		4
		Context:  available books left...
	solution_test.go:82: [solution_test.go:244] Expected:
		1
		Got:
		4
		Context:  available books left...
	solution_test.go:82: [solution_test.go:244] Expected:
		0
		Got:
		4
		Context:  available books left...
	solution_test.go:255: Expected error but got nil
FAIL
exit status 1
FAIL	_/tmp/d20151207-5667-1noag5l	0.003s
PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.003s
PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.004s
PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.004s
PASS
ok  	_/tmp/d20151207-5667-1noag5l	0.003s

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

Стефани обнови решението на 05.12.2015 02:02 (преди над 2 години)

+package main
+
+import (
+ "encoding/json"
+ "encoding/xml"
+ "fmt"
+)
+
+type Library interface {
+
+ // Добавя книга от json
+ // Oтговаря с общия брой копия в библиотеката (не само наличните).
+ // Aко са повече от 4 - връща грешка
+ AddBookJSON(data []byte) (int, error)
+
+ // Добавя книга от xml
+ // Oтговаря с общия брой копия в библиотеката (не само наличните).
+ // Ако са повече от 4 - връщаме грешка
+ AddBookXML(data []byte) (int, error)
+
+ // Ангажира свободен "библиотекар" да ни обработва заявките.
+ // Библиотекарите са фиксиран брой - подават се като параметър на NewLibrary
+ // Блокира ако всички библиотекари са заети.
+ // Връщат се два канала:
+ // първият е само за писане - по него ще изпращаме заявките
+ // вторият е само за четене - по него ще получаваме отговорите.
+ // Ако затворим канала със заявките - освобождаваме библиотекаря.
+ Hello() (chan<- LibraryRequest, <-chan LibraryResponse)
+}
+
+type LibraryRequest interface {
+ // Тип на заявката:
+ // 1 - Borrow book
+ // 2 - Return book
+ // 3 - Get availability information about book
+ GetType() int
+
+ // Връща isbn на книгата, за която се отнася Request-a
+ GetISBN() string
+}
+
+type LibraryResponse interface {
+ // Ако книгата съществува/налична е - обект имплементиращ fmt.Stringer (повече информация по-долу)
+ // Aко книгата не съществува първият резултат е nil.
+ // Връща се и подобаващa грешка (виж по-долу) - ако такава е възникнала.
+ // Когато се е резултат на заявка от тип 2 (Return book) - не е нужно да я закачаме към отговора.
+ GetBook() (fmt.Stringer, error)
+
+ // available - Колко наличности от книгата имаме останали след изпълнението на заявката.
+ // Тоест, ако сме имали 3 копия от Х и това е отговор на Borrow заявка - тук ще има 2.
+ // registered - Колко копия от тази книга има регистрирани в библиотеката (макс 4).
+ GetAvailability() (available int, registered int)
+}
+
+type MyRequest struct {
+ reqType int
+ isbn string
+}
+
+func (req MyRequest) GetType() int {
+ return req.reqType
+}
+
+func (req MyRequest) GetISBN() string {
+ return req.isbn
+}
+
+type MyResponse struct {
+ book Book
+ availability int
+ registered int
+ error string
+}
+
+func (response MyResponse) GetBook() (fmt.Stringer, error) {
+ if response.error != "" {
+ return nil, errorString{response.error}
+ }
+ return response.book, nil
+}
+
+func (book Book) String() string {
+ return "[" + book.Isbn + "] " + book.Title + " от " + book.Author.FirstName + " " + book.Author.LastName
+}
+
+func (response MyResponse) GetAvailability() (available int, registered int) {
+ return response.availability, response.registered
+}
+
+// Връща "отворена" библиотека
+func NewLibrary(librarians int) Library {
+ return &MyLibrary{
+ allLibrarians: librarians,
+ busyLibrarians: 0,
+ books: []Book{},
+ bookAvailable: map[string]int{},
+ bookRegistered: map[string]int{},
+ }
+}
+
+type Author struct {
+ FirstName string `json:"first_name" xml:"first_name"`
+ LastName string `json:"last_name" xml:"last_name"`
+}
+
+type Book struct {
+ Isbn string `json:"isbn" xml:"isbn,attr"`
+ Author Author `json:"author" xml:"author"`
+ Title string `json:"title" xml:"title"`
+ Ratings []int `json:"ratings" xml:"ratings>rating"`
+}
+
+type MyLibrary struct {
+ allLibrarians int
+ busyLibrarians int
+ books []Book
+ bookAvailable map[string]int
+ bookRegistered map[string]int
+}
+
+func (library *MyLibrary) AddBookJSON(data []byte) (int, error) {
+ var book Book
+ json.Unmarshal(data, &book)
+ val, ok := library.bookRegistered[book.Isbn]
+ if !ok {
+ library.books = append(library.books, book)
+ } else if val >= 4 {
+ return val, errorString{"Има 4 копия на книга <" + book.Isbn + ">"}
+ }
+
+ library.bookRegistered[book.Isbn]++
+ library.bookAvailable[book.Isbn]++
+ return library.bookRegistered[book.Isbn], nil
+}
+
+func (library *MyLibrary) AddBookXML(data []byte) (int, error) {
+ var book Book
+ xml.Unmarshal(data, &book)
+ val, ok := library.bookRegistered[book.Isbn]
+ if !ok {
+ library.books = append(library.books, book)
+ } else if val >= 4 {
+ return val, errorString{"Има 4 копия на книга " + book.Isbn}
+ }
+
+ library.bookRegistered[book.Isbn]++
+ library.bookAvailable[book.Isbn]++
+ return library.bookRegistered[book.Isbn], nil
+}
+
+type errorString struct {
+ errorMsg string
+}
+
+func (e errorString) Error() string {
+ return e.errorMsg
+}
+
+func (library *MyLibrary) Hello() (chan<- LibraryRequest, <-chan LibraryResponse) {
+ if library.allLibrarians-library.busyLibrarians >= 0 {
+ //blokira
+ } else {
+ library.busyLibrarians++
+ }
+ in := make(chan LibraryRequest)
+ out := make(chan LibraryResponse)
+ go func() {
+ for req := range in {
+ if req.GetType() == 1 { //borrow
+ resp := MyResponse{
+
+ availability: library.bookAvailable[req.GetISBN()],
+ registered: library.bookRegistered[req.GetISBN()],
+ error: "",
+ }
+
+ if resp.registered == 0 {
+ resp.error = "Непозната книга " + req.GetISBN()
+ } else if resp.availability <= 0 {
+ resp.error = "Няма наличност на книга " + req.GetISBN()
+ } else {
+ for _, book := range library.books {
+ if book.Isbn == req.GetISBN() {
+ resp.book = book
+ break
+ }
+ library.bookAvailable[req.GetISBN()]--
+ resp.availability--
+ }
+ }
+
+ out <- resp
+
+ } else if req.GetType() == 2 { //return
+
+ resp := MyResponse{
+
+ availability: library.bookAvailable[req.GetISBN()],
+ registered: library.bookRegistered[req.GetISBN()],
+ error: "",
+ }
+
+ if resp.registered == 0 {
+ resp.error = "Непозната книга " + req.GetISBN()
+ } else if resp.registered-resp.availability <= 0 {
+ resp.error = "Всички копия са налични " + req.GetISBN()
+ } else {
+ for _, book := range library.books {
+ if book.Isbn == req.GetISBN() {
+ resp.book = book
+ break
+ }
+ library.bookAvailable[req.GetISBN()]++
+ resp.availability++
+ }
+ }
+
+ out <- resp
+
+ } else if req.GetType() == 3 {
+ resp := MyResponse{
+
+ availability: library.bookAvailable[req.GetISBN()],
+ registered: library.bookRegistered[req.GetISBN()],
+ error: "",
+ }
+
+ if resp.registered == 0 {
+ resp.error = "Непозната книга " + req.GetISBN()
+ } else {
+ for _, book := range library.books {
+ if book.Isbn == req.GetISBN() {
+ resp.book = book
+ break
+ }
+ }
+ }
+
+ out <- resp
+ }
+ }
+ }()
+
+ return in, out
+}