This repository has been archived by the owner on Dec 3, 2021. It is now read-only.
/
lessons.go
executable file
路122 lines (97 loc) 路 3.5 KB
/
lessons.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package api
import (
"context"
"errors"
copier "github.com/jinzhu/copier"
ot "github.com/opentracing/opentracing-go"
"github.com/opentracing/opentracing-go/ext"
log "github.com/opentracing/opentracing-go/log"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
pb "github.com/nre-learning/antidote-core/api/exp/generated"
models "github.com/nre-learning/antidote-core/db/models"
)
// ListLessons returns a list of Lessons present in the data store
func (s *AntidoteAPI) ListLessons(ctx context.Context, filter *pb.LessonFilter) (*pb.Lessons, error) {
span := ot.StartSpan("api_lesson_list", ext.SpanKindRPCClient)
defer span.Finish()
lessons := []*pb.Lesson{}
dbLessons, err := s.Db.ListLessons(span.Context())
if err != nil {
span.LogFields(log.Error(err))
ext.Error.Set(span, true)
return nil, errors.New("Error retrieving lessons")
}
for _, l := range dbLessons {
lessons = append(lessons, lessonDBToAPI(l))
}
return &pb.Lessons{
Lessons: lessons,
}, nil
}
// GetAllLessonPrereqs examines the entire tree of depedencies that a given lesson might have, and returns
// it as a flattened, de-duplicated list. Used for the advisor's learning path tool in antidote-web
func (s *AntidoteAPI) GetAllLessonPrereqs(ctx context.Context, lessonSlug *pb.LessonSlug) (*pb.LessonPrereqs, error) {
span := ot.StartSpan("api_lesson_getprereqs", ext.SpanKindRPCClient)
defer span.Finish()
// Preload the requested lesson ID so we can strip it before returning
pr := s.getPrereqs(span, lessonSlug.Slug, []string{lessonSlug.Slug})
return &pb.LessonPrereqs{
// Remove first item from slice - this is the lesson being requested
Prereqs: pr[1:],
}, nil
}
func (s *AntidoteAPI) getPrereqs(span ot.Span, lessonSlug string, currentPrereqs []string) []string {
// Return if lesson slug doesn't exist
lesson, err := s.Db.GetLesson(span.Context(), lessonSlug)
if err != nil {
return currentPrereqs
}
// Add this lessonSlug to prereqs if doesn't already exist
if !isAlreadyInSlice(lessonSlug, currentPrereqs) {
currentPrereqs = append(currentPrereqs, lessonSlug)
}
// Return if lesson doesn't have prerequisites
if len(lesson.Prereqs) == 0 {
return currentPrereqs
}
// Call recursion for lesson IDs that need it
for i := range lesson.Prereqs {
prereqSlug := lesson.Prereqs[i]
currentPrereqs = s.getPrereqs(span, prereqSlug, currentPrereqs)
}
return currentPrereqs
}
func isAlreadyInSlice(lessonSlug string, currentPrereqs []string) bool {
for i := range currentPrereqs {
if currentPrereqs[i] == lessonSlug {
return true
}
}
return false
}
// GetLesson retrieves a single Lesson from the data store by Slug
func (s *AntidoteAPI) GetLesson(ctx context.Context, lessonSlug *pb.LessonSlug) (*pb.Lesson, error) {
span := ot.StartSpan("api_lesson_get", ext.SpanKindRPCClient)
defer span.Finish()
dbLesson, err := s.Db.GetLesson(span.Context(), lessonSlug.Slug)
if err != nil {
return nil, status.Error(codes.NotFound, err.Error())
}
lesson := lessonDBToAPI(dbLesson)
return lesson, nil
}
// lessonDBToAPI translates a single Lesson from the `db` package models into the
// api package's equivalent
func lessonDBToAPI(dbLesson models.Lesson) *pb.Lesson {
lessonAPI := &pb.Lesson{}
copier.Copy(&lessonAPI, dbLesson)
return lessonAPI
}
// lessonAPIToDB translates a single Lesson from the `api` package models into the
// `db` package's equivalent
func lessonAPIToDB(pbLesson *pb.Lesson) *models.Lesson {
lessonDB := &models.Lesson{}
copier.Copy(&lessonDB, pbLesson)
return lessonDB
}