Documentation
¶
Index ¶
- Constants
- Variables
- type Answer
- type Assignment
- type Commit
- func (commit *Commit) ComputeSignature(secret, problemTypeSignature, problemSignature, daycareHost string, ...) string
- func (commit *Commit) DumpTranscript(w io.Writer) error
- func (commit *Commit) FilterIncoming(whitelist map[string]bool)
- func (commit *Commit) Normalize(now time.Time, whitelist map[string]bool) error
- type CommitBundle
- type Course
- type DaycareRequest
- type DaycareResponse
- type EventMessage
- type Problem
- type ProblemBundle
- type ProblemSet
- type ProblemSetBundle
- type ProblemSetProblem
- type ProblemStep
- type ProblemType
- type ProblemTypeAction
- type Question
- type QuestionPatch
- type Quiz
- type QuizPatch
- type ReportCard
- func (elt *ReportCard) AddFailedResult(name, details, context string) *ReportCardResult
- func (elt *ReportCard) AddPassedResult(name, details string) *ReportCardResult
- func (elt *ReportCard) AddTime(duration time.Duration)
- func (elt *ReportCard) ComputeScore() float64
- func (elt *ReportCard) Failf(note string, params ...interface{})
- func (elt *ReportCard) LogAndFailf(note string, params ...interface{})
- type ReportCardResult
- type Response
- type User
- type Version
Constants ¶
const ( TranscriptEventCountLimit = 500 TranscriptDataLimit = 1e5 OpenCommitTimeout = 6 * time.Hour SignedCommitTimeout = 15 * time.Minute CookieName = "codegrinder" )
const MaxDaycareRequestAge = 15 * time.Minute
MaxDaycareRequestAge is the maximum age of a daycare-signed commit to be saved. Any commit older than this will be rejected.
const MaxDetailsLen = 50e3
Variables ¶
var BeginningOfTime = time.Date(2016, 1, 1, 0, 0, 0, 0, time.UTC)
var CurrentVersion = Version{ Version: "2.6.4", GrindVersionRequired: "2.6.4", GrindVersionRecommended: "2.6.4", ThonnyVersionRecommended: "2.6.16", ThonnyVersionRequired: "2.6.16", }
var ProblemStepDirectoryWhitelist = map[string]bool{ "inputs": true, "outputs": true, "doc": true, }
problem files in these directories do not have line endings cleaned up
Functions ¶
This section is empty.
Types ¶
type Assignment ¶
type Assignment struct { ID int64 `json:"id" meddler:"id,pk"` CourseID int64 `json:"courseID" meddler:"course_id"` ProblemSetID int64 `json:"problemSetID" meddler:"problem_set_id,zeroisnull"` UserID int64 `json:"userID" meddler:"user_id"` Roles string `json:"roles" meddler:"roles"` Instructor bool `json:"instructor" meddler:"instructor"` RawScores map[string][]float64 `json:"rawScores" meddler:"raw_scores,json"` Score float64 `json:"score" meddler:"score,zeroisnull"` GradeID string `json:"-" meddler:"grade_id,zeroisnull"` LtiID string `json:"-" meddler:"lti_id"` CanvasTitle string `json:"canvasTitle" meddler:"canvas_title"` CanvasID int64 `json:"canvasID" meddler:"canvas_id"` CanvasAPIDomain string `json:"-" meddler:"canvas_api_domain"` OutcomeURL string `json:"-" meddler:"outcome_url"` OutcomeExtURL string `json:"-" meddler:"outcome_ext_url"` OutcomeExtAccepted string `json:"-" meddler:"outcome_ext_accepted"` FinishedURL string `json:"-" meddler:"finished_url"` ConsumerKey string `json:"consumerKey" meddler:"consumer_key"` UnlockAt *time.Time `json:"unlockAt" meddler:"unlock_at,localtime"` DueAt *time.Time `json:"dueAt" meddler:"due_at,localtime"` LockAt *time.Time `json:"lockAt" meddler:"lock_at,localtime"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
Assignment represents a single instance of a problem set for a student in a course. Many commits (attempts to solve a step of a problem in the set) are linked to an assignment.
func (*Assignment) ComputeScore ¶
func (*Assignment) IsInstructorRole ¶
func (asst *Assignment) IsInstructorRole() bool
isInstructorRole returns true if the given LTI Roles field indicates this user is an instructor for a specific course.
func (*Assignment) SetMinorScore ¶
func (assignment *Assignment) SetMinorScore(major string, minor int, score float64)
type Commit ¶
type Commit struct { ID int64 `json:"id" meddler:"id,pk"` AssignmentID int64 `json:"assignmentID" meddler:"assignment_id"` ProblemID int64 `json:"problemID" meddler:"problem_id"` Step int64 `json:"step" meddler:"step"` // note: one-based Action string `json:"action" meddler:"action,zeroisnull"` Note string `json:"note" meddler:"note,zeroisnull"` Files map[string][]byte `json:"files" meddler:"files,json"` Transcript []*EventMessage `json:"transcript,omitempty" meddler:"transcript,json"` ReportCard *ReportCard `json:"reportCard" meddler:"report_card,json"` Score float64 `json:"score" meddler:"score,zeroisnull"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
Commit defines an attempt at solving one step of a Problem.
func (*Commit) ComputeSignature ¶
func (*Commit) FilterIncoming ¶
filter out files in subdirectories/not on whitelist, and clean up line endings
type CommitBundle ¶
type CommitBundle struct { ProblemType *ProblemType `json:"problemType"` ProblemTypeSignature string `json:"problemTypeSignature,omitempty"` Problem *Problem `json:"problem"` ProblemSteps []*ProblemStep `json:"problemSteps"` ProblemSignature string `json:"problemSignature,omitempty"` Action string `json:"action"` Hostname string `json:"hostname,omitempty"` UserID int64 `json:"userID"` Commit *Commit `json:"commit"` CommitSignature string `json:"commitSignature,omitempty"` }
type Course ¶
type Course struct { ID int64 `json:"id" meddler:"id,pk"` Name string `json:"name" meddler:"name"` Label string `json:"label" meddler:"lti_label"` LtiID string `json:"ltiID" meddler:"lti_id"` CanvasID int64 `json:"canvasID" meddler:"canvas_id"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
Course represents a single instance of a course as defined by LTI.
type DaycareRequest ¶
type DaycareRequest struct { CommitBundle *CommitBundle `json:"commitBundle,omitempty"` Stdin []byte `json:"stdin,omitempty"` CloseStdin bool `json:"closeStdin,omitempty"` }
DaycareRequest represents a single request from a client to the daycare. These objects are streamed across a websockets connection.
type DaycareResponse ¶
type DaycareResponse struct { CommitBundle *CommitBundle `json:"commitBundle,omitempty"` Event *EventMessage `json:"event,omitempty"` Error string `json:"error,omitempty"` }
DaycareResponse represents a single response from the daycare back to a client. These objects are streamed across a websockets connection.
type EventMessage ¶
type EventMessage struct { Time time.Time `json:"time"` Event string `json:"event"` ExecCommand []string `json:"execCommand,omitempty"` ExitStatus int `json:"exitStatus,omitempty"` StreamData []byte `json:"streamData,omitempty"` Error string `json:"error,omitempty"` ReportCard *ReportCard `json:"reportCard,omitempty"` Files map[string][]byte `json:"files,omitempty"` }
EventMessage follows one of these forms:
exec ExecCommand exit ExitStatus stdin StreamData stdout StreamData stderr StreamData stdinclosed error Error reportcard ReportCard files Files
func (*EventMessage) Dump ¶
func (e *EventMessage) Dump() string
func (*EventMessage) String ¶
func (e *EventMessage) String() string
type Problem ¶
type Problem struct { ID int64 `json:"id" meddler:"id,pk"` Unique string `json:"unique" meddler:"unique_id"` Note string `json:"note" meddler:"note"` Tags []string `json:"tags" meddler:"tags,json"` Options []string `json:"options" meddler:"options,json"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
func (*Problem) ComputeSignature ¶
func (problem *Problem) ComputeSignature(secret string, steps []*ProblemStep) string
type ProblemBundle ¶
type ProblemBundle struct { ProblemTypes map[string]*ProblemType `json:"problemTypes"` ProblemTypeSignatures map[string]string `json:"problemTypeSignatures,omitempty"` Problem *Problem `json:"problem"` ProblemSteps []*ProblemStep `json:"problemSteps"` ProblemSignature string `json:"problemSignature,omitempty"` Hostname string `json:"hostname"` UserID int64 `json:"userID"` Commits []*Commit `json:"commits"` CommitSignatures []string `json:"commitSignatures,omitempty"` }
type ProblemSet ¶
type ProblemSet struct { ID int64 `json:"id" meddler:"id,pk"` Unique string `json:"unique" meddler:"unique_id"` Note string `json:"note" meddler:"note"` Tags []string `json:"tags" meddler:"tags,json"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
type ProblemSetBundle ¶
type ProblemSetBundle struct { ProblemSet *ProblemSet `json:"problemSet"` ProblemSetProblems []*ProblemSetProblem `json:"problemSetProblems"` }
type ProblemSetProblem ¶
type ProblemStep ¶
type ProblemStep struct { ProblemID int64 `json:"problemID" meddler:"problem_id"` Step int64 `json:"step" meddler:"step"` // note: one-based ProblemType string `json:"problemType" meddler:"problem_type"` Note string `json:"note" meddler:"note"` Instructions string `json:"instructions" meddler:"instructions"` Weight float64 `json:"weight" meddler:"weight"` Files map[string][]byte `json:"files" meddler:"files,json"` Whitelist map[string]bool `json:"whitelist" meddler:"whitelist,json"` Solution map[string][]byte `json:"solution,omitempty" meddler:"solution,json"` }
ProblemStep represents a single step of a problem. Anything in the root directory of Files is added to the working directory, possibly overwriting existing content. The subdirectory contents of Files replace all subdirectory contents in the problem from earlier steps.
func (*ProblemStep) BuildInstructions ¶
func (step *ProblemStep) BuildInstructions() (string, error)
buildInstructions builds the instructions for a problem step as a single html document. Markdown is processed and images are inlined.
type ProblemType ¶
type ProblemType struct { Name string `json:"name" meddler:"name"` Image string `json:"image" meddler:"image"` Files map[string][]byte `json:"files,omitempty" meddler:"-"` Actions map[string]*ProblemTypeAction `json:"actions" meddler:"-"` }
ProblemType defines one type of problem.
func (*ProblemType) ComputeSignature ¶
func (problemType *ProblemType) ComputeSignature(secret string) string
type ProblemTypeAction ¶
type ProblemTypeAction struct { ProblemType string `json:"problemType" meddler:"problem_type"` Action string `json:"action,omitempty" meddler:"action"` Command string `json:"command,omitempty" meddler:"command"` Parser string `json:"parser,omitempty" meddler:"parser,zeroisnull"` Message string `json:"message,omitempty" meddler:"message"` Interactive bool `json:"interactive,omitempty" meddler:"interactive"` MaxCPU int64 `json:"maxCPU" meddler:"max_cpu"` MaxSession int64 `json:"maxSession" meddler:"max_session"` MaxTimeout int64 `json:"maxTimeout" meddler:"max_timeout"` MaxFD int64 `json:"maxFD" meddler:"max_fd"` MaxFileSize int64 `json:"maxFileSize" meddler:"max_file_size"` MaxMemory int64 `json:"maxMemory" meddler:"max_memory"` MaxThreads int64 `json:"maxThreads" meddler:"max_threads"` }
ProblemTypeAction defines the labels, parser, interactivity, and handler for a single problem type action.
type Question ¶
type Question struct { ID int64 `json:"id" meddler:"id,pk"` QuizID int64 `json:"quizID" meddler:"quiz_id"` Number int64 `json:"number" meddler:"question_number"` // note: 1-based Note string `json:"note" meddler:"note"` Weight float64 `json:"weight" meddler:"weight"` PointsForAttempt float64 `json:"pointsForAttempt" meddler:"points_for_attempt"` IsMultipleChoice bool `json:"isMultipleChoice" meddler:"is_multiple_choice"` Answers []Answer `json:"answers" meddler:"answers,json"` ClosedAt *time.Time `json:"closedAt" meddler:"closed_at,localtime"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
Question represents a single interactive quiz question.
func (*Question) HideAnswersUnlessClosed ¶
func (question *Question) HideAnswersUnlessClosed()
type QuestionPatch ¶
type Quiz ¶
type Quiz struct { ID int64 `json:"id" meddler:"id,pk"` AssignmentID int64 `json:"assignmentID" meddler:"assignment_id"` // creator LtiID string `json:"-" meddler:"lti_id"` Note string `json:"note" meddler:"note"` Weight float64 `json:"weight" meddler:"weight"` ParticipationThreshold float64 `json:"participationThreshold" meddler:"participation_threshold"` ParticipationPercent float64 `json:"participationPercent" meddler:"participation_percent"` IsGraded bool `json:"isGraded" meddler:"is_graded"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
Quiz represents a single session of interactive student quizzes, usually from a single class period.
type ReportCard ¶
type ReportCard struct { Passed bool `json:"passed"` Note string `json:"note"` Duration time.Duration `json:"duration"` Results []*ReportCardResult `json:"results"` }
ReportCard gives the results of a graded run
func NewReportCard ¶
func NewReportCard() *ReportCard
func (*ReportCard) AddFailedResult ¶
func (elt *ReportCard) AddFailedResult(name, details, context string) *ReportCardResult
func (*ReportCard) AddPassedResult ¶
func (elt *ReportCard) AddPassedResult(name, details string) *ReportCardResult
func (*ReportCard) AddTime ¶
func (elt *ReportCard) AddTime(duration time.Duration)
func (*ReportCard) ComputeScore ¶
func (elt *ReportCard) ComputeScore() float64
func (*ReportCard) Failf ¶
func (elt *ReportCard) Failf(note string, params ...interface{})
func (*ReportCard) LogAndFailf ¶
func (elt *ReportCard) LogAndFailf(note string, params ...interface{})
type ReportCardResult ¶
type ReportCardResult struct { Name string `json:"name"` Outcome string `json:"outcome"` Details string `json:"details,omitempty"` Context string `json:"context,omitempty"` }
ReportCardResult Outcomes:
passed failed error skipped
Details: a multi-line message that should
be displayed in a monospace font
Context:
path/to/file.py:line#
type Response ¶
type Response struct { ID int64 `json:"id" meddler:"id,pk"` AssignmentID int64 `json:"assignmentID" meddler:"assignment_id"` QuestionID int64 `json:"questionID" meddler:"question_id"` Response string `json:"response" meddler:"response"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` }
Response represents a student response to a single question.
type User ¶
type User struct { ID int64 `json:"id" meddler:"id,pk"` Name string `json:"name" meddler:"name"` Email string `json:"email" meddler:"email"` LtiID string `json:"ltiID" meddler:"lti_id"` ImageURL string `json:"imageURL" meddler:"lti_image_url"` CanvasLogin string `json:"canvasLogin" meddler:"canvas_login"` CanvasID int64 `json:"canvasID" meddler:"canvas_id"` Author bool `json:"author" meddler:"author"` Admin bool `json:"admin" meddler:"admin"` CreatedAt time.Time `json:"createdAt" meddler:"created_at,localtime"` UpdatedAt time.Time `json:"updatedAt" meddler:"updated_at,localtime"` LastSignedInAt time.Time `json:"lastSignedInAt" meddler:"last_signed_in_at,localtime"` }
User represents a single user as defined by LTI.
type Version ¶
type Version struct { Version string `json:"version"` GrindVersionRequired string `json:"grindVersionRequired"` GrindVersionRecommended string `json:"grindVersionRecommended"` ThonnyVersionRequired string `json:"thonnyVersionRequired"` ThonnyVersionRecommended string `json:"thonnyVersionRecommended"` }