Skip to content
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

intern hiring. #171

Open
wants to merge 22 commits into
base: intern_task
Choose a base branch
from
Open
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
137 changes: 119 additions & 18 deletions Application.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,54 @@
## Application
### There are 4 resources:

There are 5 resources:
- Users
- Principal
- Students
- Teachers
- Assignments

4 Users (2 students and 2 teachers) have already been created for you in the db fixture
5 Users (1 Principal, 2 students and 2 teachers) have already been created for you in the db fixture

## User Actions:
- A principal can view all the teachers
- A principal can view all the assignments submitted and/or graded by teachers.
- A principal can re-grade the assignments already graded by the teacher.
- A student can create and edit a draft assignment
- A student can list all his created assignments
- A student can submit a draft assignment to a teacher
- A teacher can list all assignments submitted to him
- A teacher can grade an assignment submitted to him

## Challenge

Please fork the repository into your account and continue the development in your fork.

Your tasks
- Add missing APIs mentioned here and get the automated tests to pass
- Add tests for grading API
- Please be aware that intentional bugs have been incorporated into the application, leading to test failures. Kindly address and rectify these issues as part of the assignment.
- All tests should pass
- Get the test coverage to 94% or above
- There are certain SQL tests present inside `tests/SQL/`. You have to write SQL in following files:
- count_grade_A_assignments_by_teacher_with_max_grading.sql
- number_of_graded_assignments_for_each_student.sql
- Optionally, Dockerize your application by creating a Dockerfile and a docker-compose.yml file, providing clear documentation on building and running the application with Docker, to stand out in your submission

***Once you are done with your task, please use [this form](https://forms.gle/TbpVhYojG84cyUD77) to complete your submission.***

You will hear back within 48 hours from us via email.


## Available APIs

### Auth
- header: "X-Principal"
- value: {"user_id":1, "student_id":1}

For APIs to work you need a principal header to establish identity and context

### GET /student/assignments
#### List all assignments created by a student

List all assignments created by a student
```
headers:
X-Principal: {"user_id":1, "student_id":1}
Expand Down Expand Up @@ -55,7 +81,8 @@ response:
```

### POST /student/assignments
#### Create an assignment

Create an assignment
```
headers:
X-Principal: {"user_id":2, "student_id":2}
Expand All @@ -81,7 +108,8 @@ response:
```

### POST /student/assignments
#### Edit an assignment

Edit an assignment
```
headers:
X-Principal: {"user_id":2, "student_id":2}
Expand All @@ -108,7 +136,8 @@ response:
```

### POST /student/assignments/submit
#### Submit an assignment

Submit an assignment
```
headers:
X-Principal: {"user_id":1, "student_id":1}
Expand All @@ -132,17 +161,11 @@ response:
"updated_at": "2021-09-17T03:17:20.147349"
}
}
```

## Missing APIs
### Auth
- header: "X-Principal"
- value: {"user_id":3, "teacher_id":1}

For APIs to work you need a principal header to establish identity and context

```
### GET /teacher/assignments
#### List all assignments submitted to this teacher

List all assignments submitted to this teacher
```
headers:
X-Principal: {"user_id":3, "teacher_id":1}
Expand All @@ -165,7 +188,8 @@ response:
```

### POST /teacher/assignments/grade
#### Grade an assignment

Grade an assignment
```
headers:
X-Principal: {"user_id":3, "teacher_id":1}
Expand All @@ -189,4 +213,81 @@ response:
"updated_at": "2021-09-17T03:20:42.896947"
}
}
```
```

## Missing APIs

You'll need to implement these APIs

### GET /principal/assignments

List all submitted and graded assignments
```
headers:
X-Principal: {"user_id":5, "principal_id":1}

response:
{
"data": [
{
"content": "ESSAY T1",
"created_at": "2021-09-17T03:14:01.580126",
"grade": null,
"id": 1,
"state": "SUBMITTED",
"student_id": 1,
"teacher_id": 1,
"updated_at": "2021-09-17T03:14:01.584644"
}
]
}
```

### GET /principal/teachers

List all the teachers
```
headers:
X-Principal: {"user_id":5, "principal_id":1}


response:
{
"data": [
{
"created_at": "2024-01-08T07:58:53.131970",
"id": 1,
"updated_at": "2024-01-08T07:58:53.131972",
"user_id": 3
}
]
}
```

### POST /principal/assignments/grade

Grade or re-grade an assignment
```
headers:
X-Principal: {"user_id":5, "principal_id":1}

payload:
{
"id": 1,
"grade": "A"
}

response:
{
"data": {
"content": "ESSAY T1",
"created_at": "2021-09-17T03:14:01.580126",
"grade": "A",
"id": 1,
"state": "GRADED",
"student_id": 1,
"teacher_id": 1,
"updated_at": "2021-09-17T03:20:42.896947"
}
}
```
27 changes: 9 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

## Who is this for?

This challenge is meant for candidates who wish to work / intern at Fyle and work with our engineering teams.

If it is for internship, you should be able to commit to at least 3 months.
This challenge is meant for candidates who wish to intern at Fyle and work with our engineering team. You should be able to commit to at least 6 months of dedicated time for internship.

## Why work at Fyle?

Expand All @@ -15,49 +13,42 @@ We are an extremely transparent organization. Check out our [careers page](https

## Challenge outline

This is a web application designed in a context of a single classroom.
Described [here](./Application.md)

### Your tasks
1. Add missing APIs mentioned [here](./Application.md#Missing-APIs) and get the automated tests to pass
2. Add a test for grading API
3. Get the test coverage to 94% or above
**You are allowed to use any online/AI tool such as ChatGPT, Gemini, etc. to complete the challenge. However, we expect you to fully understand the code and logic involved.**

## Submission
This challenge involves writing a backend service for a classroom. The challenge is described in detail [here](./Application.md)

Once you are done with your task, please use [this form](https://forms.gle/fZex7LDo6kj1Syg7A) to complete your submission.

## What happens next?

You will hear back within 48 hours from us via email. We may request for some changes based on reviewing your code.

Subsequently, we will schedule a phone interview with a Fyle Engineer.
You will hear back within 48 hours from us via email.

If that goes well, we'll make an offer.

---

## Installation

1. Fork this repository to your github account
2. Clone the forked repository and proceed with steps mentioned below

### Install requirements

```
virtualenv env --python=python3.8
source env/bin/activate
pip install -r requirements.txt
```
### Reset DB

```
export FLASK_APP=core/server.py
rm core/store.sqlite3
flask db upgrade -d core/migrations/
```
### Start Server

```
bash run.sh
```
### Run Tests

```
pytest -vvv -s tests/

Expand Down
1 change: 1 addition & 0 deletions core/apis/assignments/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .student import student_assignments_resources
from .teacher import teacher_assignments_resources
Empty file.
15 changes: 14 additions & 1 deletion core/apis/assignments/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Meta:
unknown = EXCLUDE

id = auto_field(required=False, allow_none=True)
content = auto_field(required=True)
content = auto_field()
created_at = auto_field(dump_only=True)
updated_at = auto_field(dump_only=True)
teacher_id = auto_field(dump_only=True)
Expand All @@ -36,3 +36,16 @@ class Meta:
def initiate_class(self, data_dict, many, partial):
# pylint: disable=unused-argument,no-self-use
return GeneralObject(**data_dict)


class AssignmentGradeSchema(Schema):
class Meta:
unknown = EXCLUDE

id = fields.Integer(required=True, allow_none=False)
grade = EnumField(GradeEnum, required=True, allow_none=False)

@post_load
def initiate_class(self, data_dict, many, partial):
# pylint: disable=unused-argument,no-self-use
return GeneralObject(**data_dict)
8 changes: 4 additions & 4 deletions core/apis/assignments/student.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


@student_assignments_resources.route('/assignments', methods=['GET'], strict_slashes=False)
@decorators.auth_principal
@decorators.authenticate_principal
def list_assignments(p):
"""Returns list of assignments"""
students_assignments = Assignment.get_assignments_by_student(p.student_id)
Expand All @@ -19,7 +19,7 @@ def list_assignments(p):

@student_assignments_resources.route('/assignments', methods=['POST'], strict_slashes=False)
@decorators.accept_payload
@decorators.auth_principal
@decorators.authenticate_principal
def upsert_assignment(p, incoming_payload):
"""Create or Edit an assignment"""
assignment = AssignmentSchema().load(incoming_payload)
Expand All @@ -33,15 +33,15 @@ def upsert_assignment(p, incoming_payload):

@student_assignments_resources.route('/assignments/submit', methods=['POST'], strict_slashes=False)
@decorators.accept_payload
@decorators.auth_principal
@decorators.authenticate_principal
def submit_assignment(p, incoming_payload):
"""Submit an assignment"""
submit_assignment_payload = AssignmentSubmitSchema().load(incoming_payload)

submitted_assignment = Assignment.submit(
_id=submit_assignment_payload.id,
teacher_id=submit_assignment_payload.teacher_id,
principal=p
auth_principal=p
)
db.session.commit()
submitted_assignment_dump = AssignmentSchema().dump(submitted_assignment)
Expand Down
34 changes: 34 additions & 0 deletions core/apis/assignments/teacher.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from flask import Blueprint
from core import db
from core.apis import decorators
from core.apis.responses import APIResponse
from core.models.assignments import Assignment

from .schema import AssignmentSchema, AssignmentGradeSchema
teacher_assignments_resources = Blueprint('teacher_assignments_resources', __name__)


@teacher_assignments_resources.route('/assignments', methods=['GET'], strict_slashes=False)
@decorators.authenticate_principal
def list_assignments(p):
"""Returns list of assignments"""
teachers_assignments = Assignment.get_assignments_by_teacher()
teachers_assignments_dump = AssignmentSchema().dump(teachers_assignments, many=True)
return APIResponse.respond(data=teachers_assignments_dump)


@teacher_assignments_resources.route('/assignments/grade', methods=['POST'], strict_slashes=False)
@decorators.accept_payload
@decorators.authenticate_principal
def grade_assignment(p, incoming_payload):
"""Grade an assignment"""
grade_assignment_payload = AssignmentGradeSchema().load(incoming_payload)

graded_assignment = Assignment.mark_grade(
_id=grade_assignment_payload.id,
grade=grade_assignment_payload.grade,
auth_principal=p
)
db.session.commit()
graded_assignment_dump = AssignmentSchema().dump(graded_assignment)
return APIResponse.respond(data=graded_assignment_dump)
Loading