diff --git a/client/client.go b/client/client.go
index afd856e..574a3e4 100644
--- a/client/client.go
+++ b/client/client.go
@@ -2,11 +2,6 @@ package client
import "git.andreafazzi.eu/andrea/probo/models"
-type Response struct {
- Status string `json:"status"`
- Content interface{} `json:"content"`
-}
-
type Question struct {
Text string `json:"text"`
}
@@ -21,18 +16,23 @@ type Quiz struct {
Answers []*Answer `json:"answers"`
}
+type BaseResponse struct {
+ Status string `json:"status"`
+ Message string `json:"message"`
+}
+
type ReadAllQuizResponse struct {
- Status string `json:"status"`
+ BaseResponse
Content []*models.Quiz `json:"content"`
}
type CreateQuizResponse struct {
- Status string `json:"status"`
+ BaseResponse
Content *models.Quiz `json:"content"`
}
type UpdateQuizResponse struct {
- Status string `json:"status"`
+ BaseResponse
Content *models.Quiz `json:"content"`
}
@@ -44,11 +44,6 @@ type CreateAnswerRequest struct {
*Answer
}
-type CreateQuizRequest struct {
- *Quiz
-}
-
-type UpdateQuizRequest struct {
- ID string
+type CreateUpdateQuizRequest struct {
*Quiz
}
diff --git a/main.go b/main.go
index b5822dc..877cd18 100644
--- a/main.go
+++ b/main.go
@@ -15,8 +15,8 @@ const port = "3000"
func main() {
logger.SetLevel(logger.DebugLevel)
- server := NewQuizHubCollectorServer(
- memory.NewMemoryQuizHubCollectorStore(
+ server := NewProboCollectorServer(
+ memory.NewMemoryProboCollectorStore(
sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn),
),
)
diff --git a/misc/logseq/src/index.ts b/misc/logseq/src/index.ts
index 7a437d5..5c0a394 100644
--- a/misc/logseq/src/index.ts
+++ b/misc/logseq/src/index.ts
@@ -55,17 +55,21 @@ const main = () => {
const proboId = `probo_${id}`;
logseq.provideModel({
- async postQuiz() {
- const parentBlock = await logseq.Editor.getBlock(payload.uuid, { includeChildren: true });
- const quizzes = parentBlock.children.map((child: BlockEntity) => {
- const question = { text: child.content }
- const answers = child.children.map((answer: BlockEntity, i: number) => {
+ async createOrUpdateQuiz() {
+ const parentBlock = await logseq.Editor.getBlock(payload.uuid, { includeChildren: true });
+ const answers = child.children.map((answer: BlockEntity, i: number) => {
return { text: answer.content, correct: (i == 0) ? true : false }
})
+
+ const quiz = {
+ question: {text: parentBlock.children[0].content },
+ answers: answers
+ }
+ const question = { text: child.content }
return { question: question, answers: answers, uuid: child.uuid }
});
quizzes.forEach(async (quiz, i) => {
- const res = await fetch(endpoint, { method: 'POST', body: JSON.stringify(quiz) })
+ const res = await fetch(endpoint+'/create', { method: 'POST', body: JSON.stringify(quiz) })
const data = await res.json();
const block = await logseq.Editor.getBlock(quiz.uuid)
await logseq.Editor.upsertBlockProperty(parentBlock.uuid, `probo-quiz-uuid`, data.content.ID)
@@ -93,7 +97,7 @@ const main = () => {
key: `${proboId}`,
slot,
reset: true,
- template: ``,
+ template: ``,
});
});
diff --git a/server.go b/server.go
index 19b6462..ff276bc 100644
--- a/server.go
+++ b/server.go
@@ -12,84 +12,115 @@ import (
"github.com/julienschmidt/httprouter"
)
-const jsonContentType = "application/json"
-
-type QuizHubCollectorServer struct {
- store store.QuizHubCollectorStore
+type ProboCollectorServer struct {
+ store store.ProboCollectorStore
http.Handler
}
-func NewQuizHubCollectorServer(store store.QuizHubCollectorStore) *QuizHubCollectorServer {
- ps := new(QuizHubCollectorServer)
+func NewProboCollectorServer(store store.ProboCollectorStore) *ProboCollectorServer {
+ ps := new(ProboCollectorServer)
ps.store = store
router := httprouter.New()
router.GET("/quizzes", httprouter.Handle(ps.readAllQuizzesHandler))
router.POST("/quizzes/create", httprouter.Handle(ps.createQuizHandler))
- router.POST("/quizzes/:id/update", httprouter.Handle(ps.updateQuizHandler))
- // router.Handle("/quizzes", logger.WithLogging(http.HandlerFunc(ps.testHandler)))
+ router.PUT("/quizzes/update/:id", httprouter.Handle(ps.updateQuizHandler))
- ps.Handler = logger.WithLogging(router)
+ ps.Handler = logger.WithLogging(ps.jsonHeaderMiddleware(router))
return ps
}
-func (ps *QuizHubCollectorServer) readAllQuizzesHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
- w.Header().Set("content-type", jsonContentType)
- json.NewEncoder(w).Encode(ps.readAllQuizzes(w, r))
+func (ps *ProboCollectorServer) jsonHeaderMiddleware(next http.Handler) http.Handler {
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("Content-Type", "application/json")
+ next.ServeHTTP(w, r)
+ })
}
-func (ps *QuizHubCollectorServer) createQuizHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
- response := new(client.Response)
+func (ps *ProboCollectorServer) readAllQuizzesHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
+ response := new(client.ReadAllQuizResponse)
+
+ quizzes, err := ps.readAllQuiz(w, r)
+ if err != nil {
+ response = &client.ReadAllQuizResponse{
+ BaseResponse: client.BaseResponse{Status: "error", Message: err.Error()},
+ Content: nil,
+ }
+ } else {
+ response = &client.ReadAllQuizResponse{
+ BaseResponse: client.BaseResponse{Status: "success", Message: ""},
+ Content: quizzes,
+ }
+ }
+
+ w.WriteHeader(http.StatusOK)
+ json.NewEncoder(w).Encode(response)
+}
+
+func (ps *ProboCollectorServer) createQuizHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
+ response := new(client.CreateQuizResponse)
quiz, err := ps.createQuiz(w, r)
if err != nil {
- response = &client.Response{Status: "error", Content: err.Error()}
+ response = &client.CreateQuizResponse{
+ BaseResponse: client.BaseResponse{Status: "error", Message: err.Error()},
+ Content: nil,
+ }
}
- response = &client.Response{Status: "success", Content: quiz}
+ response = &client.CreateQuizResponse{
+ BaseResponse: client.BaseResponse{Status: "success", Message: ""},
+ Content: quiz,
+ }
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(response)
}
-func (ps *QuizHubCollectorServer) updateQuizHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
- response := new(client.Response)
+func (ps *ProboCollectorServer) updateQuizHandler(w http.ResponseWriter, r *http.Request, params httprouter.Params) {
+ response := new(client.UpdateQuizResponse)
quiz, err := ps.updateQuiz(w, r, params.ByName("id"))
if err != nil {
- response = &client.Response{Status: "error", Content: err.Error()}
+ response = &client.UpdateQuizResponse{
+ BaseResponse: client.BaseResponse{Status: "error", Message: err.Error()},
+ Content: nil,
+ }
+ } else {
+ response = &client.UpdateQuizResponse{
+ BaseResponse: client.BaseResponse{Status: "success", Message: ""},
+ Content: quiz,
+ }
}
- response = &client.Response{Status: "success", Content: quiz}
-
w.WriteHeader(http.StatusAccepted)
json.NewEncoder(w).Encode(response)
}
-func (ps *QuizHubCollectorServer) readAllQuizzes(w http.ResponseWriter, r *http.Request) *client.Response {
- tests, err := ps.store.ReadAllQuizzes()
+func (ps *ProboCollectorServer) readAllQuiz(w http.ResponseWriter, r *http.Request) ([]*models.Quiz, error) {
+ quizzes, err := ps.store.ReadAllQuizzes()
if err != nil {
- return &client.Response{Status: "error", Content: err.Error()}
+ return nil, err
}
- return &client.Response{Status: "success", Content: tests}
+ return quizzes, nil
}
-func (ps *QuizHubCollectorServer) updateQuiz(w http.ResponseWriter, r *http.Request, id string) (*models.Quiz, error) {
+func (ps *ProboCollectorServer) updateQuiz(w http.ResponseWriter, r *http.Request, id string) (*models.Quiz, error) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
- updateQuizReq := new(client.UpdateQuizRequest)
+ updateQuizReq := new(client.CreateUpdateQuizRequest)
err = json.Unmarshal(body, &updateQuizReq)
if err != nil {
return nil, err
}
- updatedQuiz, err := ps.store.UpdateQuiz(updateQuizReq)
+ updatedQuiz, err := ps.store.UpdateQuiz(updateQuizReq, id)
if err != nil {
return nil, err
}
@@ -97,13 +128,13 @@ func (ps *QuizHubCollectorServer) updateQuiz(w http.ResponseWriter, r *http.Requ
return updatedQuiz, nil
}
-func (ps *QuizHubCollectorServer) createQuiz(w http.ResponseWriter, r *http.Request) (*models.Quiz, error) {
+func (ps *ProboCollectorServer) createQuiz(w http.ResponseWriter, r *http.Request) (*models.Quiz, error) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
- createQuizReq := new(client.CreateQuizRequest)
+ createQuizReq := new(client.CreateUpdateQuizRequest)
err = json.Unmarshal(body, &createQuizReq)
if err != nil {
diff --git a/server_integration_test.go b/server_integration_test.go
index db2f63f..c8dee7c 100644
--- a/server_integration_test.go
+++ b/server_integration_test.go
@@ -2,6 +2,7 @@ package main
import (
"encoding/json"
+ "fmt"
"net/http"
"net/http/httptest"
"reflect"
@@ -18,8 +19,8 @@ type integrationTestSuite struct {
}
func (t *integrationTestSuite) TestQuizCreateAndReadAll() {
- server := NewQuizHubCollectorServer(
- memory.NewMemoryQuizHubCollectorStore(
+ server := NewProboCollectorServer(
+ memory.NewMemoryProboCollectorStore(
sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn),
),
)
@@ -60,9 +61,70 @@ func (t *integrationTestSuite) TestQuizCreateAndReadAll() {
}
}
+func (t *integrationTestSuite) TestQuizCreateAndUpdate() {
+ server := NewProboCollectorServer(
+ memory.NewMemoryProboCollectorStore(
+ sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn),
+ ),
+ )
+
+ // POST a new question using a JSON payload
+
+ payload := `
+{
+ "question": {"text": "Question 1"},
+ "answers": [
+ {"text": "Text of the answer 1", "correct": true},
+ {"text": "Text of the answer 2"},
+ {"text": "Text of the answer 3"},
+ {"text": "Text of the answer 4"}
+ ]
+}
+`
+ createQuizResponse, err := t.createQuiz(server, payload)
+ t.True(err == nil, "Response should be decoded properly")
+
+ if !t.Failed() {
+ payload = `
+{
+ "question": {"text": "Updated Question 1"},
+ "answers": [
+ {"text": "Text of the answer 1"},
+ {"text": "Text of the answer 2"},
+ {"text": "Text of the answer 3", "correct": true},
+ {"text": "Text of the answer 4"}
+ ]
+}
+
+`
+ updateQuizResponse, err := t.updateQuiz(server, payload, createQuizResponse.Content.ID)
+ t.True(err == nil, "Response should be decoded properly")
+
+ if !t.Failed() {
+ t.Equal("Updated Question 1", updateQuizResponse.Content.Question.Text)
+ t.Equal("Text of the answer 3", updateQuizResponse.Content.Correct.Text)
+ }
+
+ }
+}
+
+func (t *integrationTestSuite) TestUpdateNotExistentQuiz() {
+ server := NewProboCollectorServer(
+ memory.NewMemoryProboCollectorStore(
+ sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn),
+ ),
+ )
+
+ payload := ""
+ r, err := t.updateQuiz(server, payload, "1234")
+
+ t.True(err == nil, fmt.Sprintf("The operation should not return an error: %v", err))
+ t.Equal("error", r.Status)
+}
+
func (t *integrationTestSuite) TestCatchDuplicateQuiz() {
- server := NewQuizHubCollectorServer(
- memory.NewMemoryQuizHubCollectorStore(
+ server := NewProboCollectorServer(
+ memory.NewMemoryProboCollectorStore(
sha256.NewDefault256Hasher(sha256.DefaultSHA256HashingFn),
),
)
@@ -82,7 +144,7 @@ func (t *integrationTestSuite) TestCatchDuplicateQuiz() {
`
quiz1, err := t.createQuiz(server, payload)
- t.True(err == nil)
+ t.True(err == nil, fmt.Sprintf("Create quiz should not raise an error: %v", err))
quiz2, err := t.createQuiz(server, payload)
@@ -90,8 +152,8 @@ func (t *integrationTestSuite) TestCatchDuplicateQuiz() {
t.True(reflect.DeepEqual(quiz1, quiz2), "Quizzes shold be exactly the same")
}
-func (t *integrationTestSuite) createQuiz(server *QuizHubCollectorServer, payload string) (*client.CreateQuizResponse, error) {
- request, _ := http.NewRequest(http.MethodPost, "/quizzes", strings.NewReader(payload))
+func (t *integrationTestSuite) createQuiz(server *ProboCollectorServer, payload string) (*client.CreateQuizResponse, error) {
+ request, _ := http.NewRequest(http.MethodPost, "/quizzes/create", strings.NewReader(payload))
response := httptest.NewRecorder()
server.ServeHTTP(response, request)
@@ -106,7 +168,23 @@ func (t *integrationTestSuite) createQuiz(server *QuizHubCollectorServer, payloa
return decodedResponse, err
}
-func (t *integrationTestSuite) readAllQuiz(server *QuizHubCollectorServer) (*client.ReadAllQuizResponse, error) {
+func (t *integrationTestSuite) updateQuiz(server *ProboCollectorServer, payload string, id string) (*client.UpdateQuizResponse, error) {
+ request, _ := http.NewRequest(http.MethodPut, "/quizzes/update/"+id, strings.NewReader(payload))
+ response := httptest.NewRecorder()
+
+ server.ServeHTTP(response, request)
+
+ decodedResponse := new(client.UpdateQuizResponse)
+
+ err := json.Unmarshal(response.Body.Bytes(), decodedResponse)
+ if err != nil {
+ return decodedResponse, err
+ }
+
+ return decodedResponse, err
+}
+
+func (t *integrationTestSuite) readAllQuiz(server *ProboCollectorServer) (*client.ReadAllQuizResponse, error) {
request, _ := http.NewRequest(http.MethodGet, "/quizzes", nil)
response := httptest.NewRecorder()
diff --git a/server_test.go b/server_test.go
index 87186fe..af9663d 100644
--- a/server_test.go
+++ b/server_test.go
@@ -24,10 +24,16 @@ type StubTestHubCollectorStore struct {
tests []*models.Quiz
}
-func (store *StubTestHubCollectorStore) CreateQuiz(test *client.CreateQuizRequest) (*models.Quiz, error) {
+func (store *StubTestHubCollectorStore) CreateQuiz(test *client.CreateUpdateQuizRequest) (*models.Quiz, error) {
return nil, nil
}
+func (store *StubTestHubCollectorStore) UpdateQuiz(quiz *client.CreateUpdateQuizRequest, id string) (*models.Quiz, error) {
+ store.tests[0].Question.Text = quiz.Question.Text
+
+ return store.tests[0], nil
+}
+
func (store *StubTestHubCollectorStore) ReadAllQuizzes() ([]*models.Quiz, error) {
return store.tests, nil
}
@@ -44,9 +50,9 @@ func (t *testSuite) BeforeAll() {
logger.SetLevel(logger.Disabled)
}
-func (t *testSuite) TestGETQuestions() {
+func (t *testSuite) TestReadAllQuizzes() {
expectedResult := &client.ReadAllQuizResponse{
- Status: "success",
+ BaseResponse: client.BaseResponse{Status: "success"},
Content: []*models.Quiz{
{
Question: &models.Question{ID: "1", Text: "Question 1"},
@@ -62,7 +68,7 @@ func (t *testSuite) TestGETQuestions() {
},
}}
- server := NewQuizHubCollectorServer(store)
+ server := NewProboCollectorServer(store)
request, _ := http.NewRequest(http.MethodGet, "/quizzes", nil)
response := httptest.NewRecorder()
@@ -71,7 +77,7 @@ func (t *testSuite) TestGETQuestions() {
result := getResponse(response.Body)
- t.True(result.Status == expectedResult.Status)
+ t.Equal("application/json", response.Header().Get("Content-Type"))
t.True(testsAreEqual(result, expectedResult))
t.Equal(http.StatusOK, response.Code)
@@ -79,9 +85,9 @@ func (t *testSuite) TestGETQuestions() {
func (t *testSuite) TestUpdateQuiz() {
expectedResponse := &client.UpdateQuizResponse{
- Status: "success",
+ BaseResponse: client.BaseResponse{Status: "success"},
Content: &models.Quiz{
- Question: &models.Question{ID: "1", Text: "Question 1"},
+ Question: &models.Question{ID: "1", Text: "Updated Question 1"},
Answers: []*models.Answer{{}, {}, {}},
},
}
@@ -93,11 +99,11 @@ func (t *testSuite) TestUpdateQuiz() {
},
}}
- server := NewQuizHubCollectorServer(store)
+ server := NewProboCollectorServer(store)
payload := `
{
- "question": {"text": "Update Question 1"},
+ "question": {"text": "Updated Question 1"},
"answers": [
{"text": "Text of the answer 1", "correct": true},
{"text": "Text of the answer 2"},
@@ -106,7 +112,7 @@ func (t *testSuite) TestUpdateQuiz() {
]
}
`
- request, _ := http.NewRequest(http.MethodPut, "/quizzes/1/update", strings.NewReader(payload))
+ request, _ := http.NewRequest(http.MethodPut, "/quizzes/update/1", strings.NewReader(payload))
response := httptest.NewRecorder()
server.ServeHTTP(response, request)
@@ -118,14 +124,15 @@ func (t *testSuite) TestUpdateQuiz() {
if !t.Failed() {
t.True(result.Status == expectedResponse.Status)
t.True(reflect.DeepEqual(result, expectedResponse))
- t.Equal(http.StatusOK, response.Code)
+ t.Equal("application/json", response.Header().Get("Content-Type"))
+ t.Equal(http.StatusAccepted, response.Code)
}
}
func getResponse(body io.Reader) (response *client.ReadAllQuizResponse) {
err := json.NewDecoder(body).Decode(&response)
if err != nil {
- panic(fmt.Errorf("Unable to parse response from server %q into slice of Test, '%v'", body, err))
+ panic(fmt.Errorf("Unable to parse response from server %q: %v", body, err))
}
return
diff --git a/store/memory/memory.go b/store/memory/memory.go
index fe67ed8..7235490 100644
--- a/store/memory/memory.go
+++ b/store/memory/memory.go
@@ -1,6 +1,7 @@
package memory
import (
+ "fmt"
"sync"
"git.andreafazzi.eu/andrea/probo/client"
@@ -9,32 +10,46 @@ import (
"github.com/google/uuid"
)
-type MemoryQuizHubCollectorStore struct {
- questions map[string]*models.Question
- answers map[string]*models.Answer
- quizzes map[string]*models.Quiz
+type MemoryProboCollectorStore struct {
+ quizzes map[string]*models.Quiz
- questionAnswer map[string][]string
- testQuestion map[string]uint
+ questionsHashes map[string]*models.Question
+ answersHashes map[string]*models.Answer
+ quizzesHashes map[string]*models.Quiz
+
+ hasher hasher.Hasher
// A mutex is used to synchronize read/write access to the map
lock sync.RWMutex
-
- hasher hasher.Hasher
}
-func NewMemoryQuizHubCollectorStore(hasher hasher.Hasher) *MemoryQuizHubCollectorStore {
- s := new(MemoryQuizHubCollectorStore)
+func NewMemoryProboCollectorStore(hasher hasher.Hasher) *MemoryProboCollectorStore {
+ s := new(MemoryProboCollectorStore)
s.hasher = hasher
- s.questions = make(map[string]*models.Question)
- s.answers = make(map[string]*models.Answer)
+
+ s.questionsHashes = make(map[string]*models.Question)
+ s.answersHashes = make(map[string]*models.Answer)
+ s.quizzesHashes = make(map[string]*models.Quiz)
+
s.quizzes = make(map[string]*models.Quiz)
return s
}
-func (s *MemoryQuizHubCollectorStore) readQuiz(id string) *models.Quiz {
+func (s *MemoryProboCollectorStore) getQuizFromHash(hash string) *models.Quiz {
+ s.lock.RLock()
+ defer s.lock.RUnlock()
+
+ quiz, ok := s.quizzesHashes[hash]
+ if ok {
+ return quiz
+ }
+
+ return nil
+}
+
+func (s *MemoryProboCollectorStore) getQuizFromID(id string) *models.Quiz {
s.lock.RLock()
defer s.lock.RUnlock()
@@ -46,11 +61,11 @@ func (s *MemoryQuizHubCollectorStore) readQuiz(id string) *models.Quiz {
return nil
}
-func (s *MemoryQuizHubCollectorStore) readQuestion(id string) *models.Question {
+func (s *MemoryProboCollectorStore) getQuestionFromHash(hash string) *models.Question {
s.lock.RLock()
defer s.lock.RUnlock()
- question, ok := s.questions[id]
+ question, ok := s.questionsHashes[hash]
if ok {
return question
}
@@ -58,11 +73,11 @@ func (s *MemoryQuizHubCollectorStore) readQuestion(id string) *models.Question {
return nil
}
-func (s *MemoryQuizHubCollectorStore) readAnswer(id string) *models.Answer {
+func (s *MemoryProboCollectorStore) getAnswerFromHash(hash string) *models.Answer {
s.lock.RLock()
defer s.lock.RUnlock()
- answer, ok := s.answers[id]
+ answer, ok := s.answersHashes[hash]
if ok {
return answer
}
@@ -70,122 +85,96 @@ func (s *MemoryQuizHubCollectorStore) readAnswer(id string) *models.Answer {
return nil
}
-func (s *MemoryQuizHubCollectorStore) createQuiz(id string, hash string, quiz *models.Quiz) *models.Quiz {
+func (s *MemoryProboCollectorStore) createQuizFromHash(id string, hash string, quiz *models.Quiz) *models.Quiz {
s.lock.Lock()
defer s.lock.Unlock()
quiz.ID = id
- s.quizzes[hash] = quiz
+
+ s.quizzesHashes[hash] = quiz
+ s.quizzes[id] = quiz
return quiz
}
-func (s *MemoryQuizHubCollectorStore) createQuestion(id string, question *models.Question) *models.Question {
+func (s *MemoryProboCollectorStore) createQuestionFromHash(hash string, question *models.Question) *models.Question {
s.lock.Lock()
defer s.lock.Unlock()
- s.questions[id] = question
+ s.questionsHashes[hash] = question
return question
}
-func (s *MemoryQuizHubCollectorStore) createAnswer(id string, answer *models.Answer) *models.Answer {
+func (s *MemoryProboCollectorStore) createAnswerFromHash(hash string, answer *models.Answer) *models.Answer {
s.lock.Lock()
defer s.lock.Unlock()
- s.answers[id] = answer
+ s.answersHashes[hash] = answer
return answer
}
-func (s *MemoryQuizHubCollectorStore) ReadAllQuizzes() ([]*models.Quiz, error) {
+func (s *MemoryProboCollectorStore) ReadAllQuizzes() ([]*models.Quiz, error) {
result := make([]*models.Quiz, 0)
- for id, _ := range s.quizzes {
- result = append(result, s.readQuiz(id))
+ for hash := range s.quizzesHashes {
+ result = append(result, s.getQuizFromHash(hash))
}
return result, nil
}
-func (s *MemoryQuizHubCollectorStore) CreateQuiz(r *client.CreateQuizRequest) (*models.Quiz, error) {
+func (s *MemoryProboCollectorStore) createOrUpdateQuiz(r *client.CreateUpdateQuizRequest, id string) (*models.Quiz, error) {
hashes := s.hasher.QuizHashes(r.Quiz)
-
- quizID := uuid.New().String()
quizHash := hashes[len(hashes)-1]
- quiz := s.readQuiz(quizHash)
+ quiz := s.getQuizFromHash(quizHash)
if quiz != nil { // Quiz is already present in the store
return quiz, nil
}
- quiz = new(models.Quiz)
+ if id != "" {
+ quiz = s.getQuizFromID(id)
+ if quiz == nil { // Quiz is already present in the store
+ return nil, fmt.Errorf("Quiz ID %v doesn't exist in the store!", id)
+ }
+ } else {
+ id = uuid.New().String()
+ quiz = new(models.Quiz)
+ }
questionHash := hashes[0]
- q := s.readQuestion(questionHash)
+ q := s.getQuestionFromHash(questionHash)
if q == nil { // if the question is not in the store then we should add it
- q = s.createQuestion(questionHash, &models.Question{
+ q = s.createQuestionFromHash(questionHash, &models.Question{
ID: uuid.New().String(),
- Text: r.Question.Text,
+ Text: r.Quiz.Question.Text,
})
}
// Populate Question field
quiz.Question = q
- for i, answer := range r.Answers {
+ for i, answer := range r.Quiz.Answers {
answerHash := hashes[i+1]
- a := s.readAnswer(answerHash)
+ a := s.getAnswerFromHash(answerHash)
if a == nil { // if the answer is not in the store add it
- a = s.createAnswer(answerHash, &models.Answer{
+ a = s.createAnswerFromHash(answerHash, &models.Answer{
ID: uuid.New().String(),
Text: answer.Text,
})
- if answer.Correct {
- quiz.Correct = a // s.readAnswer(answerID)
- }
+ }
+ if answer.Correct {
+ quiz.Correct = a // s.readAnswer(answerID)
}
quiz.Answers = append(quiz.Answers, a)
}
- return s.createQuiz(quizID, quizHash, quiz), nil
+ return s.createQuizFromHash(id, quizHash, quiz), nil
}
-func (s *MemoryQuizHubCollectorStore) UpdateQuiz(r *client.UpdateQuizRequest) (*models.Quiz, error) {
- hashes := s.hasher.QuizHashes(r.Quiz)
-
- quizID := uuid.New().String()
- quizHash := hashes[len(hashes)-1]
-
- quiz := s.readQuiz(quizHash)
- if quiz != nil { // Quiz is already present in the store
- return quiz, nil
- }
-
- quiz = new(models.Quiz)
-
- questionHash := hashes[0]
- q := s.readQuestion(questionHash)
- if q == nil { // if the question is not in the store then we should add it
- q = s.createQuestion(questionHash, &models.Question{
- ID: uuid.New().String(),
- Text: r.Question.Text,
- })
- }
-
- // Populate Question field
- quiz.Question = q
- for i, answer := range r.Answers {
- answerHash := hashes[i+1]
- a := s.readAnswer(answerHash)
- if a == nil { // if the answer is not in the store add it
- a = s.createAnswer(answerHash, &models.Answer{
- ID: uuid.New().String(),
- Text: answer.Text,
- })
- if answer.Correct {
- quiz.Correct = a // s.readAnswer(answerID)
- }
- }
- quiz.Answers = append(quiz.Answers, a)
- }
-
- return s.createQuiz(quizID, quizHash, quiz), nil
+func (s *MemoryProboCollectorStore) CreateQuiz(r *client.CreateUpdateQuizRequest) (*models.Quiz, error) {
+ return s.createOrUpdateQuiz(r, "")
+}
+
+func (s *MemoryProboCollectorStore) UpdateQuiz(r *client.CreateUpdateQuizRequest, id string) (*models.Quiz, error) {
+ return s.createOrUpdateQuiz(r, id)
}
diff --git a/store/store.go b/store/store.go
index 941138f..a76e9c7 100644
--- a/store/store.go
+++ b/store/store.go
@@ -5,8 +5,9 @@ import (
"git.andreafazzi.eu/andrea/probo/models"
)
-type QuizHubCollectorStore interface {
+type ProboCollectorStore interface {
ReadAllQuizzes() ([]*models.Quiz, error)
- CreateQuiz(r *client.CreateQuizRequest) (*models.Quiz, error)
- UpdateQuiz(r *client.UpdateQuizRequest) (*models.Quiz, error)
+
+ CreateQuiz(r *client.CreateUpdateQuizRequest) (*models.Quiz, error)
+ UpdateQuiz(r *client.CreateUpdateQuizRequest, id string) (*models.Quiz, error)
}
diff --git a/tests/hurl/create_new_quiz.hurl b/tests/hurl/create_new_quiz.hurl
index 1f9cf67..71c50a0 100644
--- a/tests/hurl/create_new_quiz.hurl
+++ b/tests/hurl/create_new_quiz.hurl
@@ -1,4 +1,4 @@
-POST http://localhost:3000/quizzes
+POST http://localhost:3000/quizzes/create
{
"question": {"text": "Text of Question 1"},
"answers": [