-
Notifications
You must be signed in to change notification settings - Fork 56
Add API specs for Controllers #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Pull Request Test Coverage Report for Build 492
💛 - Coveralls |
|
Missions looks good so far, thanks for the quick PR! For modularity of fetching data, will there be a GET request for individual missions implemented later on? |
|
Yea, I'm thinking of giving less information in the missions listing, and then y'all can request more information about specific mission later on. Which fields do you think is necessary for the missions index listing? |
|
We are thinking of segregating it into two kinds:
The former would then allow us to fetch the minimal information for all of the missions quickly, while the latter would be fast because we're fetching detailed data for a singular mission. |
|
Yup, I got that, I'm just wondering which fields do you require for displaying information in the missions page? (e.g. You don't need question, but I'm not sure which other fields you need or don't need) I think this is better so as to minimise the data sent. You can then get these additional informations when you request detailed data for a singular mission. |
|
@indocomsoft We've come up with a mock of the data types that we would be displaying for assessments...the data is more or less similar to the model I saw in the swagger, barring a few instances of renaming. Also, we try to make a distinction between the different assessment types so as to conveniently fetch data according to the category later on and be more verbose https://gist.github.com/remo5000/cd6923c6fa004442bbc7c633718966fc |
| Mission: | ||
| swagger_schema do | ||
| properties do | ||
| order(:integer, "The order of showing the missions", required: true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to keep you in the know, we'll probably sort by due date or mission ID on the frontend (perhaps providing a toggle for the user). Still, no harm having this field here for back compatibility with mission data, but just to let you know.
|
I think Submission and GradingInfo look good. Just to clarify, for GradingInfo:
As for Grading, I have this relationship in mind:
Any thoughts @ningyuansg @indocomsoft @sreycodes ? |
To be honest, the API structure that I made were rather display-centric so it doesn't quite correspond one-to-one to the backend models & relationships. In case you're interested, here's the entity-relationship diagram of the |
|
@indocomsoft that looks good, I think the only modification when adding Grading would be shifting the As for how to structure it, I think we should come up with structures that are easy to represent and modify. The API can then provide an ad-hoc structure using a combination of the simpler internal models. e.g the display while one is grading will take information from that particular I second removing |
|
@remo5000 not sure what you mean by "shifting the Yup, that's what I'm thinking. In such case, there's no need to create a separate table since the data needed have been contained in the models & contexts to be merged from the As for removing I will try to finish up my API spec for students submitting answers and graders giving comments and XP points by today so you and @ningyuansg can review the API tomorrow. If everything is okay, the frontend team can then write the necessary API hooks and the backend team can start implementing the controllers. |
|
Alright, this is pretty much done. Let me know what you think @remo5000 @ningyuansg |
|
@indocomsoft By moving the |
|
@remo5000 Ok, I see what you mean now. I guess for now we are still gonna have a What do you think? @tuesmiddt @sreycodes |
| swagger_path :questions do | ||
| get("/missions/{missionId}/questions") | ||
|
|
||
| summary("Get questions contained inside a mission. Response is either `mcq` or `programming`") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that the response can contain (exclusive) either of the two? Right now the structure appears to be two arrays, one for programming and the other for mcq
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, it's exclusive. Cos the swagger library we're using is still on OpenAPI 2.0 which doesn't allow oneOf 😞
| swagger_schema do | ||
| properties do | ||
| questionId(:integer, "question id", required: true) | ||
| content(:string, "the question content", required: true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this provided in Markdown? Or is it just the content/prompt of the question? @indocomsoft
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's just the prompt of the question, but we can store markdown, sure since it's just a string -- that depends on the frontend team decision
| end | ||
|
|
||
| swagger_path :questions do | ||
| get("/missions/{missionId}/questions") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need an API call for each question. Rather, the questions for a particular assessment can be provided with the API call for that assessment as an array. This helps us bind the right actions to the onClicks for next, prev, and submit (and when to render these buttons) of the workspace.
i.e. the mission model can supply us with questions as an array property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like one query to /missions/{missionId}/questions returns all the questions. However, you would then need to hit the /answer/{type}/id endpoint once per question to get the user's previous submission. Since we need to be able to refresh questions individually, I'm thinking maybe an alternative is to have /answer/{type}?id={id1}?id={id2} return a JSON of
{
id1: {
type: "mcq",
answer: 4
},
id2: {
type: "programming",
answer: "console.log('hello world!');"
},
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, though I'd prefer to not have to specify what type of question (MCQ or programming) in the query string.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You shouldn't need to specify the question type in the query. I guess it's not even necessary to include the type in the response. You would then need to check against the locally stored collection of questions to determine question type (and thus how to interpret the value).
Alternatively, for simplicity, we can represent MCQ answers as a string (specifically a character). So something like:
{
id1: "d", // or "4"
id2: "console.log('hello world!');"
}
We can then also unify MCQ/programming submission apis into say GET|POST /question/answer?id={id1} (must validate only 1 id is supplied for POST) that returns an optional correctness response.
@indocomsoft Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tuesmiddt Yeah, sorry the /answer/* endpoints were my very early plans -- we should be able to unify the 2 types.
As for MCQ answer, I was thinking to maybe tag each MCQ choice associated with an MCQ question with a pseudo-id that will be used to identify them uniquely (combination of questionId + choice pseudo-id). Doesn't sound very nice to me -- let me know if any of you have any suggestion. @remo5000 @sreycodes @rrtheonlyone
@ningyuansg would you then rather have the questions themselves embedded in the get("/missions/{missionId}") endpoint? That way we can just merge the two.
| mission_pdf(:string, "The URL to the mission pdf") | ||
| end | ||
| end, | ||
| Questions: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have a field in questions that is either 'MCQ' or 'Programming', or something to that effect? On our end, it's safer to check the string value of this property rather than something like if (question.choices === undefined).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. So the json will be either
{
"type": "mcq",
"mcq": [
{ "questionId": 1,
"content": "test",
"choices": [{"content": "a", "hint": "asd"}]}]
}
]
}or
{
"type": "programming",
"programming": [
{ "questionId": 2,
"content": "kjnfb",
"solution_template": "sjdfkb",
"library": { "chapter": 1, "globals": [], "externals": [], "files": [] }
}
]
}Sounds good?
| @@ -0,0 +1,190 @@ | |||
| defmodule CadetWeb.MissionsController do | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do these missions include paths, contests, and sidequests? In that case, can we rename this as Assessments?
lib/cadet_web/router.ex
Outdated
| post("/programming", ProgrammingAnswerController, :submit) | ||
| get("/mcq/:id", MCQAnswerController, :show) | ||
| post("/mcq", MCQAnswerController, :submit) | ||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I understand it, question IDs are only unique within a mission, so this needs a mission ID somewhere.
Also, can we have one path for all questions, no matter the type (programming or mcq)? In that case, you could nest this under the current /missions path as the POST and GET at /missions/{missionId}/{questionId}.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question IDs should be unique across all but anyway this AnswerController needs a rework to unify the two kinds of questions anyway.
|
@indocomsoft My bad, could have communicated my idea better. Is it possible to change the |
| post("/auth/logout", AuthController, :logout) | ||
| end | ||
|
|
||
| # Authenticated Pages |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a path to get user information, such as username and (later on) progress on the story. Perhaps a /user path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we will probably need a full users controller. I can see the need to implement more features as we go along (notification preferences, display picture, whatnot)
| properties do | ||
| questionId(:integer, "The question id", required: true) | ||
|
|
||
| submitted(:boolean, "Whether this is the final answer", default: false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need a submitted flag or can we just take the most recent submission as final?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need it cos students might wanna save them as "draft" -- once submitted, it's locked from being edited and the TA can start grading
| response(401, "Unauthorised") | ||
| end | ||
|
|
||
| swagger_path :open do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this
|
Updated to reflect results of yesterday's discussion. I renamed the submit endpoint to
|
|
@ningyuansg @remo5000 The objects in the array returned by the |
| end, | ||
| Assessment: | ||
| swagger_schema do | ||
| properties do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add type here just to standardise with the frontend data structure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't add this cos AssessmentCategory was in a different colour in the .ts schema. Need to get my eyes checked
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lmao at least the commit message isn't I'm blind
| post("/assessments/question/{questionId}/submit") | ||
|
|
||
| summary("Submit an answer to a question") | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should add description("For MCQ, answer contains choice_id. For programming question, this is a string containing the code.") or sth to that effect
|
LGTM |
| solution(:integer, "Solution to a mcq question if it belongs to path assessment") | ||
|
|
||
| answer( | ||
| :string_or_integer, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@indocomsoft I was looking at the Grading specs and saw this. An issue with swagger perhaps?

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I think questionType and questionId should be changed to snake_case. I use camelCase for Typescript so that's probably where it got mixed in
* Add ProgrammingSubmissionController API spec * API docs for both MCQ and Programming Submission * Reorganise files * Add missions controller index API Spec * Rename submission to answer and add :show method * Add more missions controller spec * Added changes so far * Add :show to GradingController and various fixups * Fix Library according to #43 * Complete GradingController api spec * Unify marks and comments * Amend assessments controller * Remove missions controller * Minor fix * I'm blind * Update Answer controller spec * Add answer controller test file * Update grading controller spec * Rename answers controller file * Change submit method to POST * Split Assessment swagger model into two models * Minor changes to add missing description/field

Fixes #40 #39 #43