Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions db/migrations/202606261000_practice_test_studysets.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- migrate:up
CREATE TABLE practice_test_studysets (
practice_test_id uuid NOT NULL REFERENCES practice_tests(id) ON DELETE CASCADE,
studyset_id uuid NOT NULL REFERENCES studysets(id) ON DELETE CASCADE,
PRIMARY KEY (practice_test_id, studyset_id)
);

CREATE INDEX idx_pts_studyset_id ON practice_test_studysets(studyset_id);

GRANT SELECT, INSERT, UPDATE, DELETE ON practice_test_studysets TO quizfreely_api;

-- Populate existing data
INSERT INTO practice_test_studysets (practice_test_id, studyset_id)
SELECT DISTINCT mapping.practice_test_id, t.studyset_id
FROM (
SELECT practice_test_id, term_id FROM practice_test_question_terms
UNION
SELECT practice_test_id, term_id FROM practice_test_distractor_terms
) mapping
JOIN terms t ON mapping.term_id = t.id;

-- migrate:down
DROP TABLE practice_test_studysets;
38 changes: 12 additions & 26 deletions graph/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,23 +533,18 @@ func (dr *dataReader) getPracticeTestsByStudysetIDs(ctx context.Context, studyse
ctx,
dr.db,
&dbPracticeTests,
`SELECT DISTINCT ON (input.og_order, pt.id)
`SELECT
pt.id,
to_char(pt.timestamp, 'YYYY-MM-DD"T"HH24:MI:SS.MSTZH:TZM') as timestamp,
pt.questions_correct,
pt.questions_total,
pt.questions,
input.studyset_id
FROM unnest($1::uuid[]) WITH ORDINALITY AS input(studyset_id, og_order)
JOIN (
SELECT practice_test_id, term_id FROM practice_test_question_terms
UNION
SELECT practice_test_id, term_id FROM practice_test_distractor_terms
) mapping ON TRUE
JOIN terms t ON mapping.term_id = t.id AND t.studyset_id = input.studyset_id
JOIN practice_tests pt ON pt.id = mapping.practice_test_id
JOIN practice_test_studysets pts ON pts.studyset_id = input.studyset_id
JOIN practice_tests pt ON pt.id = pts.practice_test_id
WHERE pt.user_id = $2
ORDER BY input.og_order ASC, pt.id, pt.timestamp DESC`,
ORDER BY input.og_order ASC, pt.timestamp DESC`,
studysetIDs,
authedUser.ID,
)
Expand Down Expand Up @@ -689,6 +684,7 @@ JOIN (
) mapping ON mapping.term_id = input.term_id
JOIN practice_tests pt ON pt.id = mapping.practice_test_id
WHERE pt.user_id = $2
GROUP BY input.term_id, input.og_order, pt.id
ORDER BY input.og_order ASC, pt.timestamp DESC`,
termIDs,
authedUser.ID,
Expand All @@ -700,23 +696,13 @@ ORDER BY input.og_order ASC, pt.timestamp DESC`,
grouped := make(map[string][]*model.PracticeTest)
for _, pt := range dbPracticeTests {
if pt.ID != nil && pt.TermID != nil {
// Avoid duplicates if same term is both question and distractor in same test
exists := false
for _, existing := range grouped[*pt.TermID] {
if *existing.ID == *pt.ID {
exists = true
break
}
}
if !exists {
grouped[*pt.TermID] = append(grouped[*pt.TermID], &model.PracticeTest{
ID: pt.ID,
Timestamp: pt.Timestamp,
QuestionsCorrect: pt.QuestionsCorrect,
QuestionsTotal: pt.QuestionsTotal,
Questions: pt.Questions,
})
}
grouped[*pt.TermID] = append(grouped[*pt.TermID], &model.PracticeTest{
ID: pt.ID,
Timestamp: pt.Timestamp,
QuestionsCorrect: pt.QuestionsCorrect,
QuestionsTotal: pt.QuestionsTotal,
Questions: pt.Questions,
})
}
}

Expand Down
158 changes: 156 additions & 2 deletions graph/resolver/mutation.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 1 addition & 9 deletions graph/resolver/query.resolvers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/practice_test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,5 @@ func TestPracticeTestLifecycle(t *testing.T) {
resp, _ = http.DefaultClient.Do(req)
var privateResult map[string]interface{}
json.NewDecoder(resp.Body).Decode(&privateResult)
require.Nil(t, privateResult["errors"], "user2 should be able to record PT even for terms in private sets as per user instructions")
require.NotNil(t, privateResult["errors"], "user2 should NOT be able to record PT for user1's private set")
}
Loading