示例#1
0
def get_criteria_in_course():
    data_format = get_criteria()
    data_format.update({
        'course_id': fields.Integer(attribute=lambda x: x.course_assoc.courses_id),
        'active': fields.Boolean(attribute=lambda x: x.course_assoc.active),
        'in_question': fields.Boolean(attribute=lambda x: x.course_assoc.in_question)
    })
    return data_format
class InternList(AuthorizedResource):
    intern_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'email': fields.String,
        'joined_at': fields.DateTime,
        'last_activity': fields.DateTime,
        'type': fields.Integer
    }

    get_response = {
        'error':
        fields.Boolean(default=False),
        'interns':
        fields.List(
            fields.Nested({
                'intern': fields.Nested(intern_obj),
                'reported_questions': fields.Integer,
                'questions_categorized': fields.Integer,
                'questions_approved': fields.Integer,
                'text_solutions_submitted': fields.Integer,
                'text_solutions_approved': fields.Integer,
                'video_solutions_submitted': fields.Integer,
                'video_solutions_approved': fields.Integer,
            })),
        'total':
        fields.Integer
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'intern': fields.Nested(intern_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit',
                            type=int,
                            default=app.config['INTERN_LIST_LIMIT'])
        args = parser.parse_args()
        interns, total = Intern.get_list(args['page'], args['limit'])
        return {'interns': interns, 'total': total}

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str, required=True)
        args = parser.parse_args()

        intern = Intern.create(name=args['name'],
                               email=args['email'],
                               password=md5(args['password']).hexdigest())
        welcome_admin_email_task.delay(args)
        return {'intern': intern}
示例#3
0
class Teacher(AuthorizedResource):

    get_response = {
        'error':
        fields.Boolean(default=False),
        'teacher':
        fields.Nested({
            'teacher': fields.Nested(TeacherList.teacher_obj),
            'questions_categorized': fields.Integer,
            'questions_approved': fields.Integer,
            'text_solutions_submitted': fields.Integer,
            'text_solutions_approved': fields.Integer,
            'video_solutions_submitted': fields.Integer,
            'video_solutions_approved': fields.Integer,
            'reported_resolved': fields.Integer
        })
    }

    put_response = {
        'error': fields.Boolean(default=False),
        'teacher': fields.Nested(TeacherList.teacher_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        teacher = TeacherModel.get(kwargs['id'])
        return {'teacher': teacher}

    @marshal_with(put_response)
    def put(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str)
        parser.add_argument('subject_expert', type=str, required=True)
        parser.add_argument('specialization', type=str, required=True)
        parser.add_argument('qualification', type=str, required=True)
        args = parser.parse_args()

        teacher = TeacherModel.get(kwargs['id'])

        teacher.name = args['name']
        teacher.email = args['email']
        teacher.subject_expert = args['subject_expert']
        teacher.specialization = args['specialization']
        teacher.qualification = args['qualification']

        if args['password'] is not None:
            teacher.password = md5(args['password']).hexdigest()

        try:
            db.session.commit()
        except IntegrityError:
            db.session.rollback()
            raise EmailAlreadyRegistered

        return {'teacher': teacher}
示例#4
0
class Intern(AuthorizedResource):

    get_response = {
        'error':
        fields.Boolean(default=False),
        'intern':
        fields.Nested({
            'intern': fields.Nested(InternList.intern_obj),
            'reported_questions': fields.Integer,
            'questions_categorized': fields.Integer,
            'questions_approved': fields.Integer,
            'text_solutions_submitted': fields.Integer,
            'text_solutions_approved': fields.Integer,
            'video_solutions_submitted': fields.Integer,
            'video_solutions_approved': fields.Integer,
        })
    }

    put_response = {
        'error': fields.Boolean(default=False),
        'intern': fields.Nested(InternList.intern_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        intern = InternModel.get(kwargs['id'])
        return {'intern': intern}

    @marshal_with(put_response)
    def put(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str)
        args = parser.parse_args()

        intern = InternModel.query.get(kwargs['id'])
        if intern is None:
            raise InvalidInternId

        intern.name = args['name']
        intern.email = args['email']

        if args['password'] is not None:
            intern.password = md5(args['password']).hexdigest()

        try:
            db.session.commit()
        except IntegrityError:
            raise EmailAlreadyRegistered

        return {'intern': intern}

    def delete(self, id):
        return {'error': False}
class Institute(AuthorizedResource):

    response = {
        'error': fields.Boolean(default=False),
        'institute': fields.Nested(InstituteList.institute_obj)
    }

    @marshal_with(response)
    def get(self, *args, **kwargs):
        institute = InstituteModel.get(kwargs['id'])
        return {'institute': institute}

    @marshal_with(response)
    def put(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str)
        parser.add_argument('location', type=str, required=True)
        parser.add_argument('username', type=str, required=True)
        parser.add_argument('mobile_no', type=str, required=True)
        parser.add_argument('logo', type=str)
        args = parser.parse_args()

        institute = InstituteModel.get(kwargs['id'])
        institute.name = args['name']
        institute.email = args['email']
        institute.location = args['location']
        institute.username = args['username']
        institute.mobile_no = args['mobile_no']

        if args['password'] is not None:
            institute.password = md5(args['password']).hexdigest()

        if args['logo'] is not None:
            s3 = S3()
            mimetype, image_data = parse_base64_string(args['logo'])
            mimetype_parts = mimetype.split('/')
            if len(mimetype_parts) > 1 and mimetype_parts[-1] in app.config[
                    'ACCEPTED_IMAGE_EXTENSIONS']:
                # if mimetype has an extension and the extension is in the accepted list then proceed with the upload
                content_type = mimetype_parts[-1]
                url = s3.upload(image_data, content_type)
                institute.logo_url = url
            else:
                raise UnAcceptableFileType

        try:
            db.session.commit()
        except IntegrityError as e:
            db.session.rollback()
            if 'email' in e.message:
                raise EmailAlreadyRegistered
            if 'username' in e.message:
                raise UsernameAlreadyRegistered
            if 'mobile_no' in e.message:
                raise MobileNoAlreadyRegistered
            raise e

        return {'institute': institute}
示例#6
0
class Student(AuthorizedResource):
    student_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'target_year': fields.Integer,
        'institute': fields.Integer,
        'type': fields.Integer,
        'mobile_no': fields.String,
        'email': fields.String,
        'plan_id': fields.Integer,
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'student': fields.Nested(student_obj)
    }

    @marshal_with(get_response)
    def get(self, id):
        student = {}
        return {'student': student}

    def put(self, id):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str)
        parser.add_argument('mobile_no', type=str, required=True)
        parser.add_argument('target_year', type=int, required=True)
        parser.add_argument('institute', type=int, required=True)
        parser.add_argument('plan_id', type=int)
        parser.add_argument('type', type=int, required=True)
        args = parser.parse_args()
        return {'id': 12}
示例#7
0
class DataOperatorList(AuthorizedResource):
    operator_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'email': fields.String,
        'joined_at': fields.DateTime,
        'last_activity': fields.DateTime,
        'type': fields.Integer
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'data_operators': fields.List(fields.Nested({
            'data_operator': fields.Nested(operator_obj),
            'questions_added': fields.Integer,
            'text_solutions_added': fields.Integer,
            'video_solutions_added': fields.Integer
        })),
        'total': fields.Integer
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'data_operator': fields.Nested(operator_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit', type=int, default=app.config['DATA_OPERATOR_LIST_LIMIT'])
        args = parser.parse_args()

        rows, total = DataOperator.get_list(args['page'], args['limit'])
        return {'data_operators': rows, 'total': total}

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str, required=True)
        args = parser.parse_args()

        data_operator = DataOperator.create(name=args['name'], email=args['email'], password=md5(args['password']).hexdigest())
        welcome_admin_email_task.delay(args)
        return {'data_operator': data_operator}
示例#8
0
class InstituteMockTest(AuthorizedResource):
    response = {
        'error': fields.Boolean(default=False),
        'mock_test': fields.Nested(InstituteMockTestList.mock_test_obj),
        'questions': fields.List(fields.Nested(QuestionList.question_obj))
    }

    @marshal_with(response)
    def get(self, *args, **kwargs):
        mock_test = MockTest.query.get(kwargs['id'])
        if mock_test is None:
            raise InvalidMockTestId
        pushed_batch_ids = [
            p.batch_id for p in PushedMockTest.query.filter(
                PushedMockTest.mock_test_id == mock_test.id).all()
        ]
        batches = Batch.get_filtered(include_ids=pushed_batch_ids,
                                     institute_id=kwargs['user'].id)
        mock_test.batches_pushed_to = [{
            'id': b.id,
            'name': b.name,
            'class': b.clazz
        } for b in batches]
        question_ids = []
        for sid, data in json.loads(mock_test.question_ids).items():
            question_ids.extend(data['q_ids'])
        questions = Question.get_filtertered_list(
            include_question_ids=question_ids)['questions']
        return {'mock_test': mock_test, 'questions': questions}

    @marshal_with(response)
    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('batch_ids',
                            type=comma_separated_ints_type,
                            required=True)
        args = parser.parse_args()
        mock_test = MockTest.query.get(kwargs['id'])
        if mock_test is None:
            raise InvalidMockTestId
        batches = {
            b.id: b
            for b in Batch.get_filtered(institute_id=kwargs['user'].id)
        }
        new_batch_ids = args['batch_ids'][:]
        for p in PushedMockTest.query.filter(
                PushedMockTest.mock_test_id == mock_test.id,
                PushedMockTest.batch_id.in_(batches.keys())).all():
            if p.batch_id in args['batch_ids']:
                new_batch_ids.remove(p.batch_id)

        for batch_id in new_batch_ids:
            p = PushedMockTest(mock_test_id=mock_test.id,
                               batch_id=batch_id,
                               pushed_at=datetime.datetime.utcnow())
            db.session.add(p)
        db.session.commit()
        return {'error': False}
class StudentMockTestQuestions(AuthorizedResource):
    get_response = {
        'error':
        fields.Boolean(default=False),
        'mock_test':
        fields.Nested(MockTestList.mock_test_obj),
        'subjects':
        fields.List(
            fields.Nested({
                'questions':
                fields.List(fields.Nested(QuestionList.question_obj)),
                'subject_id':
                fields.Integer,
                'order':
                fields.Integer,
                'q_ids':
                fields.List(fields.Integer)
            }))
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('mock_test_id', type=int, required=True)
        args = parser.parse_args()
        mock_test_id = args['mock_test_id']
        mock_test = MockTest.query.get(mock_test_id)
        if mock_test is None:
            raise InvalidMockTestId
        question_data = json.loads(mock_test.question_ids)
        question_ids = []
        for subject_id, data in question_data.items():
            data['subject_id'] = subject_id
            question_ids.extend(data['q_ids'])

        sorted_question_data = sorted(question_data.values(),
                                      key=lambda d: d['order'])
        questions = Question.get_filtertered_list(
            include_question_ids=question_ids)['questions']
        """
        for question in questions:
            print '--options--'
            print question.correct_options
            print '---$$$---'
            question.correct_options = None
            question.option_reasons = None
            question.text_solution = None
            question.video_solution_url = None
            question.similar_question_ids = None
            question.average_time = None
        """

        questions = {q.id: q for q in questions}
        for subject in sorted_question_data:
            subject['questions'] = map(lambda q_id: questions[q_id],
                                       subject['q_ids'])
        return {'mock_test': mock_test, 'subjects': sorted_question_data}
class ReportedQuestionList(AuthorizedResource):
    report_obj = {
        'question': fields.Nested(QuestionList.question_obj),
        'report_id': fields.Integer
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'reports': fields.List(fields.Nested(report_obj)),
        'total': fields.Integer
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('categorized', type=int, default=1)

        # the next field will contain comma separated ontology node ids
        parser.add_argument('ontology', type=comma_separated_ints_type)

        parser.add_argument('nature',
                            type=str,
                            choices=app.config['QUESTION_NATURE'].keys())
        parser.add_argument('type',
                            type=str,
                            choices=app.config['QUESTION_TYPE'].keys())
        parser.add_argument('difficulty',
                            type=str,
                            choices=app.config['QUESTION_DIFFICULTY_LEVEL'])
        parser.add_argument('average_time',
                            type=str,
                            choices=map(int,
                                        app.config['QUESTION_AVERAGE_TIME']))
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit',
                            type=int,
                            default=app.config['REPORTED_QUESTION_LIST_LIMIT'])
        args = parser.parse_args()
        reports, total = ReportedQuestion.get(args['nature'], args['type'],
                                              args['difficulty'],
                                              args['average_time'],
                                              args['ontology'], args['page'],
                                              args['limit'])
        return {'reports': reports, 'total': total}

    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('question_id', type=int, required=True)
        args = parser.parse_args()
        report = ReportedQuestion.create(kwargs['user_type'].id,
                                         kwargs['user'].id,
                                         args['question_id'])
        return {'report_id': report.id}
class InstituteStudentAnalysis(AuthorizedResource):
    class JSObject(fields.Raw):
        def format(self, value):
            return json.loads(value)

    attempted_mock_test_obj = {
        'id': fields.Integer,
        'pushed_mock_test_id': fields.Integer,
        'mock_test_id': fields.Integer,
        'score': fields.Float,
        'answers': JSObject,
        'analysis': JSObject,
        'attempted_at': fields.String
    }

    attempted_mock_test = deepcopy(
        AttemptedMockTestList.attempted_mock_test_obj)
    attempted_mock_test['pdf_report_url'] = fields.String

    response = {
        'error': fields.Boolean(default=False),
        'attempted_mock_tests':
        fields.List(fields.Nested(attempted_mock_test_obj)),
        'mock_tests': fields.List(fields.Nested(MockTestList.mock_test_obj)),
        'questions': fields.List(fields.Nested(QuestionList.question_obj)),
        'accuracy': fields.Float,
        'speed': fields.Float,
        'attempted_mock_test': fields.Nested(attempted_mock_test),
        'mock_test': fields.Nested(MockTestList.mock_test_obj),
    }

    @marshal_with(response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('student_id', type=int, required=True)
        parser.add_argument('attempted_mock_test_id', type=int)
        args = parser.parse_args()
        # if no attempted mock test id provided return cumulative analysis
        if args['attempted_mock_test_id'] is None:
            return AttemptedMockTestList.get_cumulative_analysis(
                args['student_id'], kwargs['user'].id)
        else:
            return AttemptedMockTest.get_analysis(
                args['attempted_mock_test_id'])
class QuestionsFileUpload(AuthorizedResource):

    post_response = {
        'error': fields.Boolean(default=False),
        'archive_s3_key': fields.String
    }
    
    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        
        parse = reqparse.RequestParser()
        parse.add_argument('file', type=str, required=True)
        args = parse.parse_args()

        # create a file object of the image
        mimetype, file_data = parse_base64_string(args['file'])
        archive_file = StringIO(file_data)

        print 'yahan pahuncha 1'

        # upload the file to s3 with a unique uuid
        key_name = str(uuid.uuid4()) + '.zip'
        conn = S3Connection(app.config['S3_ACCESS_KEY'], app.config['S3_SECRET'])
        bucket = conn.get_bucket(app.config['S3_UPLOAD_SET_ARCHIVES_BUCKET'])
        archive_s3 = Key(bucket)
        archive_s3.key = key_name
        archive_s3.content_type = 'application/zip'
        archive_s3.set_contents_from_string(archive_file.getvalue())
        archive_s3.set_acl('public-read')

        print 'yahan pahuncha 2'

        # close the StringIO object
        archive_file.close()

        print 'yahan pahuncha 3'
        
        # return the name of the S3 key
        return {'archive_s3_key': archive_s3.key}
示例#13
0
class Question(AuthorizedResource):
    @staticmethod
    def is_categorization_same(question, params):
        if question.nature == params['nature'] and question.type == params['type'] and question.difficulty == params['difficulty'] and \
                                        question.average_time == params['average_time']:
            if question.ontology[-1] == params['ontology_id']:
                return True
        return False

    response = {
        'error': fields.Boolean(default=False),
        'question': fields.Nested(QuestionList.question_obj)
    }

    @marshal_with(response)
    def get(self, *args, **kwargs):
        return {'question': QuestionModel.get(kwargs['id'])}

    @marshal_with(response)
    def put(self, *args, **kwargs):
        parser = reqparse.RequestParser()

        # the next field will be present when a comprehension question is updated
        parser.add_argument('comprehension_text', type=unicode)

        # the next field will be present when a comprehension question is updated
        parser.add_argument('comprehension_id', type=int)

        parser.add_argument('ontology_id', type=int)
        parser.add_argument('nature', type=str)
        parser.add_argument('type', type=str)
        parser.add_argument('difficulty', type=str)
        parser.add_argument('average_time', type=int)
        parser.add_argument('content', type=unicode, required=True)
        parser.add_argument('options', type=options_json_type, required=True)
        parser.add_argument('text_solution', type=unicode)
        parser.add_argument('video_solution_url', type=str)
        parser.add_argument('text_solution_by', type=user_json_type)
        parser.add_argument('video_solution_by', type=user_json_type)
        parser.add_argument('proof_read_categorization',
                            type=int,
                            choices=[0, 1])
        parser.add_argument('proof_read_text_solution',
                            type=int,
                            choices=[0, 1])
        parser.add_argument('proof_read_video_solution',
                            type=int,
                            choices=[0, 1])
        parser.add_argument('error_reported', type=str, choices=['0', '1'])
        args = parser.parse_args()

        question = QuestionModel.get(kwargs['id'])
        if question is None:
            raise InvalidQuestionId

        comprehension = None
        if args['comprehension_id'] is not None:
            # comprehension_id is present, just update the comprehension content if its present in request
            if args['comprehension_text'] is not None:
                comprehension = Comprehension.update(
                    args['comprehension_id'], args['comprehension_text'])
        else:
            # comprehension_id is not present, create the comprehension object if comprehension content is present in request
            if args['comprehension_text'] is not None:
                comprehension = Comprehension.create(
                    args['comprehension_text'])
        comprehension_id = comprehension.id if comprehension is not None else (
            args['comprehension_id']
            if args['comprehension_id'] is not None else None)

        status = question.status

        # if complete categorization submitted
        if QuestionList.is_categorization_complete(args):
            ontology_obj = Ontology.query.get(args['ontology_id'])
            # question was uncategorized
            if status['categorized'] == '0':
                # set categorization flag
                status['categorized'] = '1'
                status['proof_read_categorization'] = '1'
                # delete any previous category submission
                # CategorySubmission.query.filter_by(question_id=question.id).delete()
                # create a category submission that will be sent for proof reading
                CategorySubmission.create(kwargs['user_type'].id,
                                          kwargs['user'].id,
                                          question.id,
                                          ontology=ontology_obj.absolute_path,
                                          type=args['type'],
                                          nature=args['nature'],
                                          difficulty=args['difficulty'],
                                          average_time=args['average_time'])

            # question was categorized
            else:
                # if edited from proof_read_categorization
                if args['proof_read_categorization'] == 1:
                    # set proof_read_categorization flag
                    status['proof_read_categorization'] = '1'
                    # if categorization has changed
                    if not self.is_categorization_same(question, args):
                        # reject any previous accepted category submissions and delete their approvals
                        prev_submissions = CategorySubmission.query.filter(
                            CategorySubmission.question_id == question.id,
                            CategorySubmission.status == 'accepted').all()
                        for s in prev_submissions:
                            s.status = 'rejected'
                            CategoryApproval.query.filter_by(
                                submission_id=s.id).delete()
                        # create a new accepted category submission
                        cs = CategorySubmission.create(
                            kwargs['user_type'].id,
                            kwargs['user'].id,
                            question.id,
                            ontology=ontology_obj.absolute_path,
                            type=args['type'],
                            nature=args['nature'],
                            difficulty=args['difficulty'],
                            average_time=args['average_time'],
                            status='accepted')
                    else:
                        # get the category submission for this question which has neither been accepted nor rejected
                        cs = CategorySubmission.query.filter(
                            CategorySubmission.question_id == question.id,
                            CategorySubmission.status == None).first()

                    # create category submission approval
                    CategoryApproval.create(cs.id, kwargs['user_type'].id,
                                            kwargs['user'].id)

                # edited from anywhere except proof_read_categorization
                else:
                    # if categorization has changed
                    if not self.is_categorization_same(question, args):
                        # delete any previous category submission and its corresponding approvals
                        CategorySubmission.query.filter_by(
                            question_id=question.id).delete()
                        CategorySubmission.create(
                            kwargs['user_type'].id,
                            kwargs['user'].id,
                            question.id,
                            ontology=ontology_obj.absolute_path,
                            type=args['type'],
                            nature=args['nature'],
                            difficulty=args['difficulty'],
                            average_time=args['average_time'])

                        # if question was already proof read categorized, then reset proof_read_categorization
                        status['proof_read_categorization'] = '1'
                        #if status['proof_read_categorization'] == '1':
                        #    status['proof_read_categorization'] = '0'

        # if incomplete categorization submitted
        else:
            status['categorized'] = '0'
            status['proof_read_categorization'] = '0'
            status['finalized'] = '0'
            # delete any previous category submission and its corresponding approvals
            CategorySubmission.query.filter_by(
                question_id=question.id).delete()

        text_solution_submitted_by_type, text_solution_submitted_by_id, text_solution_added_by_type, text_solution_added_by_id = [
            None
        ] * 4

        # if text solution is submitted
        if args['text_solution'] is not None:
            text_solution_submitted_by_type = args['text_solution_by']['type']
            text_solution_submitted_by_id = args['text_solution_by']['id']
            text_solution_added_by_type = kwargs['user_type'].id
            text_solution_added_by_id = kwargs['user'].id

            # question had no text solution
            if status['text_solution_added'] == '0':
                status['text_solution_added'] = '1'
                status['proof_read_text_solutions'] = '1'
                # delete any previous text solution submission and its corresponding approvals
                #SolutionSubmission.query.filter(SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'text').delete()
                # create a new text solution submission
                SolutionSubmission.create(text_solution_submitted_by_type,
                                          text_solution_submitted_by_id,
                                          question.id, 'text',
                                          args['text_solution'])
            # question had text solution
            else:
                # if came from proof_read_text_solution
                if args['proof_read_text_solution'] == 1:
                    status['text_solution_added'] = '1'
                    status['proof_read_text_solution'] = '1'
                    # if text solution changed
                    if QuestionModel.parse_content(
                            args['text_solution']) != question.text_solution:
                        # reject any previous accepted text solution submissions and delete their corresponding approvals
                        prev_submissions = SolutionSubmission.query.filter(
                            SolutionSubmission.question_id == question.id,
                            SolutionSubmission.solution_type == 'text',
                            SolutionSubmission.status == 'accepted').all()
                        for s in prev_submissions:
                            s.status = 'rejected'
                            SolutionApproval.query.filter_by(
                                submission_id=s.id).delete()
                        # create a new text solution submission
                        ss = SolutionSubmission.create(
                            text_solution_submitted_by_type,
                            text_solution_submitted_by_id,
                            question.id,
                            'text',
                            args['text_solution'],
                            status='accepted')
                    else:
                        # get the text solution submission for this question which has neither been accepted nor rejected
                        ss = SolutionSubmission.query.filter(
                            SolutionSubmission.question_id == question.id,
                            SolutionSubmission.solution_type == 'text',
                            SolutionSubmission.status == None).first()

                    # create category submission approval
                    SolutionApproval.create(ss.id, kwargs['user_type'].id,
                                            kwargs['user'].id)

                # edited from anywhere except proof_read_categorization
                else:
                    # if text solution changed
                    if QuestionModel.parse_content(
                            args['text_solution']) != question.text_solution:
                        # delete any previous text solution submission and its corresponding approvals
                        SolutionSubmission.query.filter(
                            SolutionSubmission.question_id == question.id,
                            SolutionSubmission.solution_type ==
                            'text').delete()
                        # create a new text solution submission
                        SolutionSubmission.create(
                            text_solution_submitted_by_type,
                            text_solution_submitted_by_id, question.id, 'text',
                            args['text_solution'])

                        # if text solution was already proof read , then reset proof_read_text_solution
                        status['proof_read_text_solution'] = '1'
                        print 'Here here here here!!!'
                        #if status['proof_read_text_solution'] == '1':
                        #    status['proof_read_text_solution'] = '0'

        # if no text solution submitted
        else:
            status['text_solution_added'] = '0'
            status['proof_read_text_solution'] = '0'
            status['finalized'] = '0'
            # delete any previous text solution submission and its corresponding approvals
            SolutionSubmission.query.filter(
                SolutionSubmission.question_id == question.id,
                SolutionSubmission.solution_type == 'text').delete()

        video_solution_submitted_by_type, video_solution_submitted_by_id, video_solution_added_by_type, video_solution_added_by_id = [
            None
        ] * 4

        # if video solution is submitted
        if args['video_solution_url'] is not None:
            video_solution_submitted_by_type = args['video_solution_by'][
                'type']
            video_solution_submitted_by_id = args['video_solution_by']['id']
            video_solution_added_by_type = kwargs['user_type'].id
            video_solution_added_by_id = kwargs['user'].id

            # question had no video solution
            if status['video_solution_added'] == '0':
                status['video_solution_added'] = '1'
                # delete any previous video solution submission and its corresponding approvals
                #SolutionSubmission.query.filter(SolutionSubmission.question_id == question.id, SolutionSubmission.solution_type == 'video').delete()
                # create a new solution submission
                SolutionSubmission.create(video_solution_submitted_by_type,
                                          video_solution_submitted_by_id,
                                          question.id, 'video',
                                          args['video_solution_url'])

            # question had video solution
            else:
                # if came from proof_read_video_solution
                if args['proof_read_video_solution']:
                    status['video_solution_added'] = '1'
                    status['proof_read_video_solution'] = '1'
                    # if video solution changed
                    if args['video_solution_url'] != question.video_solution_url:
                        # reject any previous accepted text solution submissions and delete their corresponding approvals
                        prev_submissions = SolutionSubmission.query.filter(
                            SolutionSubmission.question_id == question.id,
                            SolutionSubmission.solution_type == 'video',
                            SolutionSubmission.status == 'accepted').all()
                        for s in prev_submissions:
                            s.status = 'rejected'
                            SolutionApproval.query.filter_by(
                                submission_id=s.id).delete()
                        # create a new text solution submission
                        ss = SolutionSubmission.create(
                            video_solution_submitted_by_type,
                            video_solution_submitted_by_id,
                            question.id,
                            'video',
                            args['video_solution_url'],
                            status='accepted')
                    else:
                        # get the video solution submission for this question which has neither been accepted nor rejected
                        ss = SolutionSubmission.query.filter(
                            SolutionSubmission.question_id == question.id,
                            SolutionSubmission.solution_type == 'video',
                            SolutionSubmission.status == None).first()
                    # create category submission approval
                    SolutionApproval.create(ss.id, kwargs['user_type'].id,
                                            kwargs['user'].id)

                # edited from anywhere except proof_read_categorization
                else:
                    # if video solution changed
                    if args['video_solution_url'] != question.video_solution_url:
                        # delete any previous video solution submission and its corresponding approvals
                        SolutionSubmission.query.filter(
                            SolutionSubmission.question_id == question.id,
                            SolutionSubmission.solution_type ==
                            'video').delete()
                        # create a new video solution submission
                        SolutionSubmission.create(
                            video_solution_submitted_by_type,
                            video_solution_submitted_by_id, question.id,
                            'video', args['video_solution_url'])

                        # if text solution was already proof read , then reset proof_read_text_solution
                        if status['proof_read_video_solution'] == '1':
                            status['proof_read_video_solution'] = '0'

        # if no video solution submitted
        else:
            status['video_solution_added'] = '0'
            status['video_read_text_solution'] = '0'
            status['finalized'] = '0'
            # delete any previous video solution submission and its corresponding approvals
            SolutionSubmission.query.filter(
                SolutionSubmission.question_id == question.id,
                SolutionSubmission.solution_type == 'video').delete()

        if args['error_reported'] is not None:
            status['error_reported'] = args['error_reported']

        if '0' not in (status['proof_read_categorization'],
                       status['proof_read_text_solution'],
                       status['proof_read_video_solution'],
                       status['error_reported']):
            # question has been proof read in all 3 respects so its finalized
            status['finalized'] = '1'

        question.update(args['content'],
                        status,
                        comprehension_id=comprehension_id,
                        ontology_id=args['ontology_id'],
                        average_time=args['average_time'],
                        nature=args['nature'],
                        type=args['type'],
                        difficulty=args['difficulty'],
                        text_solution=args['text_solution'],
                        video_solution_url=args['video_solution_url'],
                        text_solution_by_type=text_solution_added_by_type,
                        text_solution_by_id=text_solution_added_by_id,
                        video_solution_by_type=video_solution_added_by_type,
                        video_solution_by_id=video_solution_added_by_id,
                        **args['options'])

        if args['error_reported'] is not None and args['error_reported'] == '0':
            report = ReportedQuestion.query.filter(
                ReportedQuestion.question_id == question.id,
                ReportedQuestion.is_resolved == False).first()
            report.is_resolved = True
            report.resolved_by_type = kwargs['user_type'].id
            report.resolved_by_id = kwargs['user'].id
            report.resolved_at = datetime.datetime.utcnow()

        db.session.commit()
        return {'question': question, 'error': False}
示例#14
0
instance_fields = {
    'id': fields.String,
    'name': fields.String,
    'provisioned_at': fields.DateTime,
    'lifetime_left': fields.Integer,
    'maximum_lifetime': fields.Integer,
    'runtime': fields.Float,
    'state': fields.String,
    'to_be_deleted': fields.Boolean,
    'error_msg': fields.String,
    'username': fields.String,
    'user_id': fields.String,
    'blueprint': fields.String,
    'blueprint_id': fields.String,
    'cost_multiplier': fields.Float(default=1.0),
    'can_update_connectivity': fields.Boolean(default=False),
    'instance_data': fields.Raw,
    'public_ip': fields.String,
    'client_ip': fields.String(default='not set'),
    'logs': fields.Raw,
}

instance_log_fields = {
    'id': fields.String,
    'instance_id': fields.String,
    'log_type': fields.String,
    'log_level': fields.String,
    'timestamp': fields.Float,
    'message': fields.String
}
class StudentList(AuthorizedResource):
    student_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'email': fields.String,
        'target_year': fields.Integer,
        'institute': fields.Integer,
        'type': fields.Integer,
        'mobile_no': fields.String,
        'city': fields.String,
        'branches': fields.List(fields.String),
        'target_exams': fields.List(fields.String),
        'father_name': fields.String,
        'father_mobile_no': fields.String,
        'payment_plan_id': fields.String,
        'registered_from': fields.String
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'students': fields.List(fields.Nested(student_obj)),
        'total': fields.Integer
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'student': fields.Nested(student_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('type', type=int, default=0)
        parser.add_argument('institute', type=int, default=0)
        parser.add_argument('target_year', type=int, default=0)
        parser.add_argument('status', type=int, default=0)
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit', type=int, default=app.config['STUDENT_LIST_LIMIT'])
        args = parser.parse_args()
        students, total = Student.get_list(args['page'], args['limit'])
        return {'students': students, 'total': total}

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str, required=True)
        parser.add_argument('mobile_no', type=str, required=True)
        parser.add_argument('target_year', type=int, required=True)
        parser.add_argument('city', type=str)
        parser.add_argument('area', type=str)
        parser.add_argument('branches', type=comma_separated_ints_type, required=True)
        parser.add_argument('target_exams', type=comma_separated_ints_type, required=True)
        parser.add_argument('father_name', type=str)
        parser.add_argument('father_mobile_no', type=str)
        args = parser.parse_args()

        student = Student.create(name=args['name'], email=args['email'], password=md5(args['password']).hexdigest(), mobile_no=args['mobile_no'],
                                 target_year=args['target_year'], city=args['city'], area=args['area'], branches=args['branches'],
                                 target_exams=args['target_exams'], father_name=args['father_name'],
                                 father_mobile_no=args['father_mobile_no'])
        return {'student': student}
示例#16
0
    "arrival_date_time":
    DateTime(attribute="end_date_time"),
    "base_arrival_date_time":
    DateTime(attribute="base_end_date_time"),
    "co2_emission":
    Co2Emission(),
}

cost = {
    'value': fields.String(),
    'currency': fields.String(),
}

fare = {
    'total': NonNullNested(cost),
    'found': fields.Boolean(),
    'links': FareLinks(attribute="ticket_id")
}

journey = {
    'duration': fields.Integer(),
    'nb_transfers': fields.Integer(),
    'departure_date_time': DateTime(),
    'arrival_date_time': DateTime(),
    'requested_date_time': DateTime(),
    'sections': NonNullList(NonNullNested(section)),
    'from': PbField(place, attribute='origin'),
    'to': PbField(place, attribute='destination'),
    'type': fields.String(),
    'fare': NonNullNested(fare),
    'tags': fields.List(fields.String),
示例#17
0
# AttentionValue helpers
class ParseAttentionValue(object):
    @staticmethod
    def parse(data):
        av = data['attentionvalue']
        sti = av['sti'] if 'sti' in av else None
        lti = av['lti'] if 'lti' in av else None
        vlti = av['vlti'] if 'vlti' in av else None

        return sti, lti, vlti


av_fields = {
    'sti': fields.Integer(attribute='sti'),
    'lti': fields.Integer(attribute='lti'),
    'vlti': fields.Boolean(attribute='vlti')
}


# Atom helpers
class FormatHandleValue(fields.Raw):
    def format(self, value):
        return value.value()


class FormatHandleList(fields.Raw):
    def format(self, values):
        return [elem.h.value() for elem in values]


class AtomListResponse(object):
示例#18
0
    'count': fields.Integer,
}
book_fields = {
    'id': fields.Integer,
    'isbn': fields.String,
    'title': fields.String,
    'subtitle': fields.String,
    'authors': fields.String,
    'translator': fields.String,
    'bookValue': fields.String,
    'thumbnail': fields.String,
    'publishedDate': fields.String,
    'collateral_value': fields.Integer,
    'numbers': fields.Integer,
    'hidden': fields.Boolean,
    'can_borrow': fields.Boolean(attribute=lambda x: x.can_borrow()),
    'can_borrow_number': fields.Integer(attribute=lambda x: x.can_borrow_number()),
    'tags': fields.List(fields.Nested(tag_fields), attribute=lambda x: x.tags),
    'uri': fields.String(attribute=lambda x: url_for('api.book', book_id=x.id, _external=True)),
}
book_list = {
    'items': fields.List(fields.Nested(book_fields)),
    'next': fields.String,
    'prev': fields.String,
    'total': fields.Integer,
    'pages_count': fields.Integer,
    'current_page': fields.Integer,
    'per_page': fields.Integer,
}
library_fields = {
    'id': fields.Integer,
示例#19
0
            response.append({"type": "note", "id": uris.note})

        for value in display_info.notes:
            response.append({
                "type": 'notes',
                "id": value.uri,
                'value': value.note,
                'internal': True
            })
        return response


instance_status = {
    "data_version": fields.Integer(),
    "end_production_date": fields.String(),
    "is_connected_to_rabbitmq": fields.Boolean(),
    "last_load_at": fields.String(),
    "last_rt_data_loaded": fields.String(),
    "last_load_status": fields.Boolean(),
    "kraken_version": fields.String(attribute="navitia_version"),
    "nb_threads": fields.Integer(),
    "publication_date": fields.String(),
    "start_production_date": fields.String(),
    "status": fields.String(),
}

instance_parameters = {
    'scenario': fields.Raw(attribute='_scenario_name'),
    'journey_order': fields.Raw,
    'max_walking_duration_to_pt': fields.Raw,
    'max_bike_duration_to_pt': fields.Raw,
示例#20
0
class BatchList(AuthorizedResource):
    @classmethod
    def batch_timings(cls, data):
        """
        Validate batch timing format. It should be ``h1:m1-h2:m2``

        :param data:
        :return:
        """
        timings = data.split('-')
        if len(timings) != 2:
            raise ValueError('Timing format incorrect')
        for timing in timings:
            try:
                hour, minute = timing.split(':')
            except Exception:
                raise ValueError('Timing format incorrect')
            try:
                hour, minute = int(hour), int(minute)
            except Exception:
                raise ValueError('Hour and minute should be integer')
            if not (0 <= hour <= 23 and 0 <= minute <= 59):
                raise ValueError('Out of range values for hour and minute')
        return data

    batch_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'on_weekdays': fields.Boolean,
        'on_weekends': fields.Boolean,
        'clazz': fields.String,
        'target_year': fields.Integer,
        'target_exam': fields.String,
        'type': fields.String,
        'other': fields.String,
        'batch_timings': fields.String,
        'institute_id': fields.Integer,
        'status': fields.Integer
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'batches': fields.List(fields.Nested(batch_obj))
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'batch': fields.Nested(batch_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('days', type=str, choices=['weekdays', 'weekends'])
        parser.add_argument('type',
                            type=str,
                            choices=app.config['BATCH_TYPE'].keys())
        parser.add_argument('target_year', type=int)
        parser.add_argument('target_exam',
                            type=str,
                            choices=app.config['TARGET_EXAMS'].keys())
        parser.add_argument('branch',
                            type=str,
                            choices=app.config['BATCH_FIELD'].keys())
        parser.add_argument('status', type=int, default=-1)
        args = parser.parse_args()

        if args['branch'] is not None:
            args['branches'] = [
                args['branch'],
            ]
        args.pop('branch', None)

        batches = Batch.get_filtered(institute_id=kwargs['user'].id, **args)
        return {'batches': batches}

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('on_weekdays',
                            type=int,
                            required=True,
                            choices=[0, 1])
        parser.add_argument('on_weekends',
                            type=int,
                            required=True,
                            choices=[0, 1])
        parser.add_argument('clazz', type=str, choices=['11', '12'])
        parser.add_argument('target_year', type=int, required=True)
        parser.add_argument('target_exam',
                            type=str,
                            required=True,
                            choices=app.config['TARGET_EXAMS'].keys())
        parser.add_argument('type',
                            type=str,
                            required=True,
                            choices=app.config['BATCH_TYPE'].keys())
        parser.add_argument('other', type=str)
        parser.add_argument('batch_timings', type=self.__class__.batch_timings)
        args = parser.parse_args()

        batch = Batch.create(name=args['name'],
                             on_weekdays=bool(args['on_weekdays']),
                             on_weekends=bool(args['on_weekends']),
                             clazz=args['clazz'],
                             target_year=args['target_year'],
                             target_exam=args['target_exam'],
                             type=args['type'],
                             other=args['other'],
                             batch_timings=args['batch_timings'],
                             institute_id=kwargs['user'].id)
        return {'batch': batch}
class AttemptedMockTest(AuthorizedResource):
    class JSObject(fields.Raw):
        def format(self, value):
            return json.loads(value)

    attempted_mock_test = deepcopy(
        AttemptedMockTestList.attempted_mock_test_obj)
    attempted_mock_test['pdf_report_url'] = fields.String

    get_response = {
        'error': fields.Boolean(default=False),
        'attempted_mock_test': fields.Nested(attempted_mock_test),
        'mock_test': fields.Nested(MockTestList.mock_test_obj),
        'questions': fields.List(fields.Nested(QuestionList.question_obj)),
    }

    @classmethod
    def get_percentile(cls, attempted_mock_test):
        # attempted mock test with same `mock_test_id`
        similar_tests = AttemptedMockTestModel.query.filter(
            AttemptedMockTestModel.mock_test_id ==
            attempted_mock_test.mock_test_id).all()
        if len(similar_tests) > 0:
            similar_test_scores = [test.score for test in similar_tests]
            sorted_scores = sorted(similar_test_scores)
            scores_more, scores_less = filter(
                lambda s: s > attempted_mock_test.score,
                sorted_scores), filter(lambda s: s < attempted_mock_test.score,
                                       sorted_scores)
            if len(scores_more) == 0 and len(scores_less) == 0:
                return 0.0
            else:
                return len(scores_less) * 100.0 / len(sorted_scores)

    @classmethod
    def get_rank_and_college(cls, attempted_mock_test, mock_test):
        past_exams = PastExamResult.query.filter_by(
            exam=mock_test.target_exam).order_by(PastExamResult.year.desc())
        if past_exams is not None:
            last_exam = past_exams.first()
            if last_exam is not None:
                last_exam_data = json.loads(last_exam.data)
                #attempted_mock_test.analysis['last_year_cutoff'] = last_exam_data['cutoff']
                marks_ranks = [[
                    map(int, marks_range.split('~')),
                    map(int, rank_range.split('~'))
                ] for marks_range, rank_range in
                               last_exam_data['marks_rank'].items()]
                obtained_marks_range = None
                closest_obtained_marks_range = None
                for item in marks_ranks:
                    marks_low = item[0][0]
                    marks_high = item[0][1]
                    if marks_low <= attempted_mock_test.score <= marks_high:
                        obtained_marks_range = [[marks_low, marks_high],
                                                item[1]]
                        break
                    else:
                        if closest_obtained_marks_range is None:
                            closest_obtained_marks_range = [[
                                marks_low, marks_high
                            ], item[1]]
                        else:
                            if abs(attempted_mock_test.score -
                                   closest_obtained_marks_range[0][0]) > abs(
                                       attempted_mock_test.score - marks_low):
                                closest_obtained_marks_range = [[
                                    marks_low, marks_high
                                ], item[1]]
                if obtained_marks_range is None:
                    obtained_marks_range = closest_obtained_marks_range
                obtained_marks_range[1].reverse()
                expected_rank = '%s-%s' % (obtained_marks_range[1][0],
                                           obtained_marks_range[1][1])

                ranks_colleges = [[map(int, rank_range.split('~')), colleges]
                                  for rank_range, colleges in
                                  last_exam_data['rank_college'].items()]
                ranks_colleges = sorted(ranks_colleges,
                                        key=lambda x: int(x[0][0]))
                obtained_rank_range = None
                closest_obtained_rank_range = None
                for item in ranks_colleges:
                    rank_low = item[0][0]
                    rank_high = item[0][1]
                    if rank_low <= obtained_marks_range[1][
                            0] and obtained_marks_range[1][1] <= rank_high:
                        obtained_rank_range = [[rank_low, rank_high], item[1]]
                        break
                    else:
                        if obtained_marks_range[1][0] <= rank_high:
                            if closest_obtained_rank_range is None:
                                closest_obtained_rank_range = [[
                                    rank_low, rank_high
                                ], item[1]]
                            else:
                                if rank_low <= obtained_marks_range[1][
                                        0] and obtained_marks_range[1][
                                            1] > rank_high:
                                    if (obtained_marks_range[1][0] - rank_low
                                        ) > (
                                            obtained_marks_range[1][0] -
                                            closest_obtained_rank_range[0][0]):
                                        closest_obtained_rank_range = [[
                                            rank_low, rank_high
                                        ], item[1]]
                                if rank_low > obtained_marks_range[1][
                                        0] and obtained_marks_range[1][
                                            1] <= rank_high:
                                    if (rank_high - obtained_marks_range[1][1]
                                        ) > (
                                            obtained_marks_range[1][1] -
                                            closest_obtained_rank_range[0][1]):
                                        closest_obtained_rank_range = [[
                                            rank_low, rank_high
                                        ], item[1]]

                if obtained_rank_range is None and closest_obtained_rank_range is not None:
                    obtained_rank_range = closest_obtained_rank_range
                if obtained_rank_range is None and closest_obtained_rank_range is None:
                    obtained_rank_range = [[], ['No colleges expected']]
                expected_colleges = obtained_rank_range[1]
                return expected_rank, expected_colleges

    @staticmethod
    def get_analysis(attempted_mock_test_id):
        attempted_mock_test = AttemptedMockTestModel.query.get(
            attempted_mock_test_id)
        if attempted_mock_test is None:
            raise InvalidAttemptedMockTestId
        mock_test = MockTest.query.get(attempted_mock_test.mock_test_id)
        if mock_test is None:
            raise InvalidMockTestId

        if attempted_mock_test.answers is None:
            return {'error': True, 'message': 'No answers yet'}

        attempted_mock_test.analysis = json.loads(attempted_mock_test.analysis)

        attempted_mock_test.analysis[
            'percentile'] = AttemptedMockTest.get_percentile(
                attempted_mock_test)

        attempted_mock_test.analysis['cutoff'] = mock_test.cutoff
        rank_colleges = AttemptedMockTest.get_rank_and_college(
            attempted_mock_test, mock_test)
        if rank_colleges is not None:
            attempted_mock_test.analysis[
                'expected_rank'], attempted_mock_test.analysis[
                    'expected_colleges'] = rank_colleges

        attempted_mock_test.analysis = json.dumps(attempted_mock_test.analysis)

        question_data = json.loads(mock_test.question_ids)
        question_ids = []
        for subject_id, data in question_data.items():
            data['subject_id'] = subject_id
            question_ids.extend(data['q_ids'])
        questions = Question.get_filtertered_list(
            include_question_ids=question_ids)['questions']

        return {
            'attempted_mock_test': attempted_mock_test,
            'mock_test': mock_test,
            'questions': questions
        }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        attempted_mock_test_id = kwargs['id']
        return self.get_analysis(attempted_mock_test_id)
class QuestionUploadSetList(AuthorizedResource):

    mock_test_obj = {
        'name': fields.String
    }

    upload_set_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'errors_exist': fields.Boolean,
        'mock_test_id': fields.Integer,
        'mock_test': fields.Nested(mock_test_obj),
        'questions_added': fields.Boolean,
    }

    get_response = {
        'total': fields.Integer,
        'error': fields.Boolean(default=False),
        'upload_sets': fields.List(fields.Nested(upload_set_obj)),
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'upload_set': fields.Nested(upload_set_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        
        parser = reqparse.RequestParser()
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit', type=int, default=app.config['UPLOAD_SET_LIST_LIMIT'])
        args = parser.parse_args()

        # get a list of all the upload sets in the DB (without the questions)
        upload_set_pag_obj = QuestionUploadSet.query.filter().order_by(QuestionUploadSet.created_at.desc()).paginate(args['page'], args['limit'])
        upload_sets = upload_set_pag_obj.items
        total = upload_set_pag_obj.total

        # return a list of tests
        return {'upload_sets': upload_sets, 'total': total}

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        
        parse = reqparse.RequestParser()
        parse.add_argument('name', type=str, required=True)
        parse.add_argument('archive_key', type=str, required=True)
        parse.add_argument('mock_test_id', type=str, required=True)
        args = parse.parse_args()

        parse_upload_set_async.delay(args['name'], args['archive_key'], args['mock_test_id'])

        print 'this is done'

        return 'this is good shit'

        #print 'Checking S3 key'

        # check if the s3 key exists
        conn = S3Connection(app.config['S3_ACCESS_KEY'], app.config['S3_SECRET'])
        bucket = conn.get_bucket(app.config['S3_UPLOAD_SET_ARCHIVES_BUCKET'])
        archive_s3 = bucket.get_key(args['archive_key'])
        if not archive_s3:
            raise ArchiveS3KeyDoesNotExist

        #print 'S3 key checked'


        #print 'Checking mock test'

        # check if the mock test is open and has no questions
        mock_test_id = args['mock_test_id']
        mock_test = MockTest.query.get(mock_test_id)
        if not mock_test:
            raise InvalidMockTestId
        if not mock_test.question_ids is None:
            raise QuestionUploadSetMockSetNotEmpty

        #print 'Mock test checked'

        #print 'Getting contents from S3'

        # parse the paper and store it in json
        archive = StringIO()
        archive_s3.get_contents_to_file(archive)

        #print 'Contents from S3 got'
        
        #print 'parsing questions'
        parsed_questions = parse_paper(archive)
        #print 'questions parsed'

        # check the parsed questions for any `overall` errors. if there are then don't proceed
        if parsed_questions['is_overall_error']:
            error_message = '\n'.join([ exc.message for exc in parsed_questions['overall_errors'] ])
            raise OverallQuestionParsingError(error_message)

        # check if any errors exist or not
        errors = False
        try:
            check_if_errors_exist_in_parsed_questions(parsed_questions)
        except Exception as e:
            errors = True

        # store the parsed questions in the DB
        upload_set = QuestionUploadSet.create(
            name=args['name'],
            errors_exist=errors,
            mock_test_id=mock_test.id,
            parsed_questions=ExceptionJSONEncoder().encode(parsed_questions['questions']),
            parsed_comprehensions=ExceptionJSONEncoder().encode(parsed_questions['comprehensions'])
        )

        return {'upload_set': upload_set}
class QuestionList(AuthorizedResource):
    @staticmethod
    def is_categorization_complete(params):
        if None not in (params['nature'], params['type'], params['difficulty'],
                        params['average_time']):
            # All required attributes present
            if params['ontology_id'] is not None and Ontology.is_leaf_node(
                    params['ontology_id']):
                # Ontology is complete since leaf node. So consider it categorized
                return True
        return False

    question_obj = {
        'id':
        fields.Integer,
        'status':
        fields.Nested({
            'categorized': fields.String,
            'proof_read_categorization': fields.String,
            'text_solution_added': fields.String,
            'video_solution_added': fields.String,
            'proof_read_text_solution': fields.String,
            'proof_read_video_solution': fields.String,
            'finalized': fields.String,
            'error_reported': fields.String
        }),
        'content':
        fields.String,
        'ontology':
        fields.List(fields.Integer),
        'type':
        fields.String,
        'difficulty':
        fields.String,
        'nature':
        fields.String,
        'average_time':
        fields.String,
        'text_solution':
        fields.String,
        'video_solution_url':
        fields.String,
        'text_solution_by_type':
        fields.Integer(default=None),
        'text_solution_by_id':
        fields.Integer(default=None),
        'video_solution_by_type':
        fields.Integer(default=None),
        'video_solution_by_id':
        fields.Integer(default=None),
        'all_options':
        fields.List(fields.String),
        'correct_options':
        fields.List(fields.Integer),
        'option_reasons':
        fields.List(fields.String),
        'comprehension':
        fields.Nested({
            'id': fields.Integer(default=None),
            'content': fields.String
        }),
        'similar_question_ids':
        fields.List(fields.Integer),
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'questions': fields.List(fields.Nested(question_obj)),
        'total': fields.Integer
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'question': fields.Nested(question_obj)
    }

    common_parser = reqparse.RequestParser()
    common_parser.add_argument('nature',
                               type=str,
                               choices=app.config['QUESTION_NATURE'].keys())
    common_parser.add_argument('type',
                               type=str,
                               choices=app.config['QUESTION_TYPE'].keys())
    common_parser.add_argument('difficulty',
                               type=str,
                               choices=app.config['QUESTION_DIFFICULTY_LEVEL'])
    common_parser.add_argument('average_time',
                               type=int,
                               choices=map(
                                   int, app.config['QUESTION_AVERAGE_TIME']))

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = self.common_parser.copy()
        parser.add_argument('categorized', type=str, choices=['0', '1'])
        parser.add_argument('proof_read_categorization',
                            type=str,
                            choices=['0', '1'])
        parser.add_argument('proof_read_text_solution',
                            type=str,
                            choices=['0', '1'])
        parser.add_argument('proof_read_video_solution',
                            type=str,
                            choices=['0', '1'])
        parser.add_argument('finalized', type=str, choices=['0', '1'])
        parser.add_argument('error_reported', type=str, choices=['0', '1'])

        # this contains comma separated ontology node ids
        parser.add_argument('ontology', type=comma_separated_ints_type)

        parser.add_argument('ontology_id', type=int)

        parser.add_argument('is_comprehension', type=int, choices=[0, 1])
        parser.add_argument('text_solution_added', type=int, choices=[0, 1])
        parser.add_argument('video_solution_added', type=int, choices=[0, 1])
        parser.add_argument('exclude_question_ids',
                            type=comma_separated_ints_type)
        parser.add_argument('include_question_ids',
                            type=comma_separated_ints_type)
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit',
                            type=int,
                            default=app.config['QUESTION_BANK_LIST_LIMIT'])
        args = parser.parse_args()

        if args['ontology_id'] is not None and args['ontology'] is None:
            ontology_obj = Ontology.query.get(args['ontology_id'])
            if ontology_obj is not None:
                args['ontology'] = ontology_obj.absolute_path

        return Question.get_filtertered_list(
            nature=args['nature'],
            type=args['type'],
            difficulty=args['difficulty'],
            average_time=args['average_time'],
            categorized=args['categorized'],
            proof_read_categorization=args['proof_read_categorization'],
            proof_read_text_solution=args['proof_read_text_solution'],
            proof_read_video_solution=args['proof_read_video_solution'],
            finalized=args['finalized'],
            error_reported=args['error_reported'],
            text_solution_added=args['text_solution_added'],
            video_solution_added=args['video_solution_added'],
            ontology=args['ontology'],
            is_comprehension=args['is_comprehension'],
            exclude_question_ids=args['exclude_question_ids'],
            include_question_ids=args['include_question_ids'],
            page=args['page'],
            limit=args['limit'])

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        parser = self.common_parser.copy()
        # the next field will be present when the first question of a comprehension is added
        parser.add_argument('comprehension_text', type=unicode)

        # the next field will be present when question of an already created comprehension is added
        parser.add_argument('comprehension_id', type=int)

        parser.add_argument('ontology_id', type=int)
        parser.add_argument('content', type=unicode, required=True)
        parser.add_argument('options', type=options_json_type, required=True)
        parser.add_argument('text_solution', type=unicode)
        parser.add_argument('video_solution_url', type=str)
        parser.add_argument('text_solution_by', type=user_json_type)
        parser.add_argument('video_solution_by', type=user_json_type)
        args = parser.parse_args()

        comprehension = None
        if args['comprehension_id'] is not None:
            # comprehension_id is present, just update the comprehension content if its present in request
            if args['comprehension_text'] is not None:
                comprehension = Comprehension.update(
                    args['comprehension_id'], args['comprehension_text'])
        else:
            # comprehension_id is not present, create the comprehension object if comprehension content if its present in request
            if args['comprehension_text'] is not None:
                comprehension = Comprehension.create(
                    args['comprehension_text'])
        comprehension_id = comprehension.id if comprehension is not None else (
            args['comprehension_id']
            if args['comprehension_id'] is not None else None)

        status = {
            # keeping string values of 0 and 1 because postgres hstore needs keys and values as text
            'categorized':
            '0',
            'proof_read_categorization':
            '0',
            'text_solution_added':
            '1' if args['text_solution'] is not None else '0',
            'video_solution_added':
            '1' if args['video_solution_url'] is not None else '0',
            'proof_read_text_solution':
            '0',
            'proof_read_video_solution':
            '0',
            'finalized':
            '0',
            'error_reported':
            '0'
        }

        # If question is categorized
        if self.is_categorization_complete(args):
            status['categorized'] = '1'
            status['proof_read_categorization'] = '1'

        text_solution_submitted_by_type, text_solution_submitted_by_id, text_solution_added_by_type, text_solution_added_by_id = [
            None
        ] * 4
        if args['text_solution'] is not None:
            status['text_solution_added'] = '1'
            status['proof_read_text_solution'] = '1'
            text_solution_submitted_by_type = args['text_solution_by']['type']
            text_solution_submitted_by_id = args['text_solution_by']['id']
            text_solution_added_by_type = kwargs['user_type'].id
            text_solution_added_by_id = kwargs['user'].id

        video_solution_submitted_by_type, video_solution_submitted_by_id, video_solution_added_by_type, video_solution_added_by_id = [
            None
        ] * 4
        if args['video_solution_url'] is not None:
            status['video_solution_added'] = '1'
            status['proof_read_video_solution'] = '1'
            video_solution_submitted_by_type = args['video_solution_by'][
                'type']
            video_solution_submitted_by_id = args['video_solution_by']['id']
            video_solution_added_by_type = kwargs['user_type'].id
            video_solution_added_by_id = kwargs['user'].id

        question = Question.create(
            content=args['content'],
            status=status,
            comprehension_id=comprehension_id,
            ontology_id=args['ontology_id'],
            average_time=args['average_time'],
            nature=args['nature'],
            type=args['type'],
            difficulty=args['difficulty'],
            text_solution=args['text_solution'],
            video_solution_url=args['video_solution_url'],
            text_solution_by_type=text_solution_added_by_type
            if args['text_solution_by'] is not None else None,
            text_solution_by_id=text_solution_added_by_id
            if args['text_solution_by'] is not None else None,
            video_solution_by_type=video_solution_added_by_type
            if args['video_solution_by'] is not None else None,
            video_solution_by_id=video_solution_added_by_id
            if args['video_solution_by'] is not None else None,
            created_by_type=kwargs['user_type'].id,
            created_by_id=kwargs['user'].id,
            **args['options'])

        if status['categorized'] == '1':
            # Question is categorized. Submit it for approval
            ontology_obj = Ontology.query.get(args['ontology_id'])

            # Do a category submission so it can be verified by teacher
            CategorySubmission.create(kwargs['user_type'].id,
                                      kwargs['user'].id,
                                      question.id,
                                      ontology=ontology_obj.absolute_path,
                                      type=args['type'],
                                      nature=args['nature'],
                                      difficulty=args['difficulty'],
                                      average_time=args['average_time'])

        if args['text_solution'] is not None:
            # Text solution is provided. Do a solution submission so it can be verified by teacher
            SolutionSubmission.create(text_solution_submitted_by_type,
                                      text_solution_submitted_by_id,
                                      question.id, 'text',
                                      args['text_solution'])

        if args['video_solution_url'] is not None:
            # Video solution is provided. Do a solution submission so it can be verified by teacher
            SolutionSubmission.create(video_solution_submitted_by_type,
                                      video_solution_submitted_by_id,
                                      question.id, 'video',
                                      args['video_solution_url'])

        return {
            'comprehension_id': comprehension_id,
            'question': question,
            'error': False
        }
class InstituteStudent(AuthorizedResource):

    student_obj = deepcopy(InstituteStudentList.student_obj)
    student_obj['mock_tests'] = fields.List(
        fields.Nested({
            'id': fields.Integer,
            'name': fields.String,
            'attempted': fields.Boolean
        }))

    response = {
        'error': fields.Boolean(default=False),
        'student': fields.Nested(student_obj),
    }

    @marshal_with(response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('profile', type=int, choices=[0, 1], default=0)
        args = parser.parse_args()
        student = Student.get(kwargs['id'])
        batch_ids = [
            sb.batch_id for sb in StudentBatches.query.filter(
                StudentBatches.student_id == student.id, StudentBatches.left_at
                == None).all()
        ]
        batches = Batch.get_filtered(include_ids=batch_ids,
                                     institute_id=kwargs['user'].id)
        student.batches = [{'id': b.id, 'name': b.name} for b in batches]
        if args['profile'] == 1:
            pushed_mock_test_ids = {
                p.id: p.mock_test_id
                for p in PushedMockTest.query.filter(
                    PushedMockTest.batch_id.in_([b.id
                                                 for b in batches])).all()
            }
            mock_tests = {
                m.id: m
                for m in MockTest.query.filter(
                    MockTest.id.in_(pushed_mock_test_ids.values()))
            }
            amts = AttemptedMockTest.query.filter(
                AttemptedMockTest.student_id == student.id,
                AttemptedMockTest.pushed_mock_test_id.in_(
                    pushed_mock_test_ids.keys())).all()
            attempted_mock_test_ids = {amt.mock_test_id for amt in amts}
            student.mock_tests = []
            seen_mock_test_ids = set()
            for pushed_id, mock_test_id in pushed_mock_test_ids.items():
                mt = {
                    'id': mock_test_id,
                    'name': mock_tests[mock_test_id].name,
                    'attempted': False
                }
                for amt in amts:
                    if pushed_id == amt.pushed_mock_test_id:
                        mt['attempted'] = True
                        break

                # if current mock test is not attempted
                if mt['attempted'] is False:
                    # a similar attempted mock test exists then dont push this entry into the result
                    if mock_test_id in attempted_mock_test_ids:
                        continue
                    # if similar mock test has already been pushed into the result
                    if mock_test_id in seen_mock_test_ids:
                        continue
                student.mock_tests.append(mt)
                seen_mock_test_ids.add(mock_test_id)
        return {'student': student}

    @marshal_with(response)
    def put(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('password', type=str)
        parser.add_argument('mobile_no', type=str, required=True)
        parser.add_argument('city', type=str)
        parser.add_argument('area', type=str)
        parser.add_argument('pin', type=str)
        parser.add_argument('school', type=str)
        parser.add_argument('ntse_score', type=float)
        parser.add_argument('roll_no', type=str)
        parser.add_argument('father_name', type=str)
        parser.add_argument('father_mobile_no', type=str)
        parser.add_argument('father_email', type=str)
        parser.add_argument('batch_ids',
                            type=comma_separated_ints_type,
                            required=True)
        args = parser.parse_args()
        student = Student.get(kwargs['id'])
        if args['password'] is not None:
            student.password = md5(args['password']).hexdigest()
        student.name = args['name']
        student.mobile_no = args['mobile_no']
        student.city = args['city']
        student.area = args['area']
        student.pin = args['pin']
        student.school = args['school']
        student.ntse_score = args['ntse_score']
        student.roll_no = args['roll_no']
        student.father_name = args['father_name']
        student.father_mobile_no = args['father_mobile_no']
        student.father_email = args['father_email']
        unow = datetime.datetime.utcnow()

        # new batches that the student may join. ids from this will be removed in a loop later
        new_batch_ids = args['batch_ids'][:]

        for sb in StudentBatches.query.filter(
                StudentBatches.student_id == student.id).all():
            # if any old batch_id not in newly supplied batch ids then student will leave that batch
            if sb.batch_id not in args['batch_ids']:
                sb.left_at = unow
            # old batch_id also in newly supplied batch ids so remove this batch_id from new_batch_ids
            else:
                new_batch_ids.remove(sb.batch_id)
                # if student rejoining
                if sb.left_at is not None:
                    sb.left_at = None

        target_exams = set()
        target_year = None
        batches = Batch.get_filtered(include_ids=args['batch_ids'])
        engineering_exams = {'1', '2', '3'}
        medical_exams = {'4', '5'}
        for batch in batches:
            if batch.target_exam in engineering_exams:
                target_exams.update(engineering_exams)
            if batch.target_exam in medical_exams:
                target_exams.update(medical_exams)
            if target_year is None or target_year > batch.target_year:
                target_year = batch.target_year
            # if a new batch id encountered
            if batch.id in new_batch_ids:
                sb = StudentBatches(batch_id=batch.id,
                                    student_id=student.id,
                                    joined_at=datetime.datetime.utcnow())
                db.session.add(sb)

        branches = []
        if len(target_exams.intersection(engineering_exams)) > 0:
            branches.append('1')
        if len(target_exams.intersection(medical_exams)) > 0:
            branches.append('2')

        student.target_year = target_year
        student.target_exams = list(target_exams)
        student.branches = branches
        db.session.commit()
        student.batches = [{'id': b.id, 'name': b.name} for b in batches]
        return {'student': student}
示例#25
0
class Batch(AuthorizedResource):

    response = {
        'error': fields.Boolean(default=False),
        'batch': fields.Nested(BatchList.batch_obj),
    }

    @marshal_with(response)
    def get(self, *args, **kwargs):
        batch = BatchModel.get(kwargs['id'])
        return {'batch': batch}

    @marshal_with(response)
    def put(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('on_weekdays',
                            type=int,
                            required=True,
                            choices=[0, 1])
        parser.add_argument('on_weekends',
                            type=int,
                            required=True,
                            choices=[0, 1])
        parser.add_argument('clazz', type=str, choices=['11', '12'])
        parser.add_argument('target_year', type=int, required=True)
        parser.add_argument('target_exam',
                            type=str,
                            required=True,
                            choices=app.config['TARGET_EXAMS'].keys())
        parser.add_argument('type',
                            type=str,
                            required=True,
                            choices=app.config['BATCH_TYPE'].keys())
        parser.add_argument('other', type=str)
        parser.add_argument('batch_timings', type=BatchList.batch_timings)
        parser.add_argument('status', type=int)
        args = parser.parse_args()

        batch = BatchModel.get(kwargs['id'])
        if args['status'] is not None and args['status'] == 1:
            batch.status = 1
        else:
            batch.on_weekdays = bool(args['on_weekdays'])
            batch.on_weekends = bool(args['on_weekends'])
            if args['clazz'] is not None:
                batch.clazz = args['clazz']
            batch.target_year = args['target_year']
            batch.target_exam = args['target_exam']
            batch.type = args['type']
            if args['other'] is not None:
                batch.other = args['other']
            if args['batch_timings'] is not None:
                batch.batch_timings = args['batch_timings']

        db.session.commit()

        return {'batch': batch}

    def delete(self, *args, **kwargs):
        sbs = StudentBatches.query.filter(
            StudentBatches.batch_id == kwargs['id'],
            StudentBatches.left_at == None).count()
        if sbs > 0:
            raise BatchNotEmpty
        batch = BatchModel.get(kwargs['id'])
        batch.status = 0
        db.session.commit()
        return {'error': False}
class SimilarQuestions(AuthorizedResource):

    get_response = {
        'error': fields.Boolean(default=False),
        'questions': fields.List(fields.Nested(QuestionList.question_obj)),
        'total': fields.Integer
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        """
        Get questions questions not similar to the given question id

        :param args:
        :param kwargs:
        :return:
        """
        parser = reqparse.RequestParser()
        parser.add_argument('nature',
                            type=str,
                            choices=app.config['QUESTION_NATURE'].keys())
        parser.add_argument('type',
                            type=str,
                            choices=app.config['QUESTION_TYPE'].keys())
        parser.add_argument('difficulty',
                            type=str,
                            choices=app.config['QUESTION_DIFFICULTY_LEVEL'])
        parser.add_argument('average_time',
                            type=int,
                            choices=map(int,
                                        app.config['QUESTION_AVERAGE_TIME']))

        # this contains comma separated ontology node ids
        parser.add_argument('ontology', type=comma_separated_ints_type)

        parser.add_argument('question_id', type=int)

        parser.add_argument('offset', type=int, default=0)

        args = parser.parse_args()

        if args['question_id'] is None:
            exprs = [
                Question.is_similarity_marked == False,
                Question.status['categorized'] == '1'
            ]
            if args['nature'] is not None:
                exprs.append(Question.nature == args['nature'])
            if args['type'] is not None:
                exprs.append(Question.type == args['type'])
            if args['difficulty'] is not None:
                exprs.append(Question.difficulty == args['difficulty'])
            if args['average_time'] is not None:
                exprs.append(Question.average_time == args['average_time'])
            if args['ontology'] is not None:
                exprs.append(Question.ontology == args['ontology'])

            question = Question.query.filter(*exprs).offset(
                args['offset']).first()
            if question is None:
                return {'questions': [], 'total': 0}
            else:
                other_questions = Question.get_filtertered_list(
                    nature=args['nature'],
                    type=args['type'],
                    difficulty=args['difficulty'],
                    average_time=args['average_time'],
                    ontology=args['ontology'],
                    categorized='1',
                    exclude_question_ids=[
                        question.id,
                    ])

                if other_questions['total'] == 0:
                    skip = args['offset'] + 1
                    while question is not None:
                        question = Question.query.filter(
                            *exprs).offset(skip).first()
                        if question is None:
                            return {'questions': [], 'total': 0}
                        other_questions = Question.get_filtertered_list(
                            nature=args['nature'],
                            type=args['type'],
                            difficulty=args['difficulty'],
                            average_time=args['average_time'],
                            ontology=args['ontology'],
                            categorized='1',
                            exclude_question_ids=[
                                question.id,
                            ])
                        if other_questions['total'] > 0:
                            break
                        skip += 1

                return {
                    'questions': [question] + other_questions['questions'],
                    'total': other_questions['total'] + 1
                }
        else:
            question_id = args['question_id']
            question = Question.get(question_id)

            other_questions = Question.get_filtertered_list(
                ontology=question.ontology,
                categorized='1',
                exclude_question_ids=[
                    question.id,
                ])

            return {
                'questions': [question] + other_questions['questions'],
                'total': other_questions['total'] + 1
            }

    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('question_id', type=int, required=True)

        # this contains comma separated question ids
        parser.add_argument('similar_question_ids', type=str)

        args = parser.parse_args()

        lst = map(lambda x: x.strip(), args['similar_question_ids'].split(','))
        if '' in lst:
            similar_question_ids = []
        else:
            similar_question_ids = map(int, lst)

        question = Question.query.get(args['question_id'])
        question.is_similarity_marked = True
        question.similar_question_ids = similar_question_ids
        similar_questions = Question.query.filter(
            Question.id.in_(similar_question_ids),
            or_(Question.similar_question_ids == None,
                Question.similar_question_ids.any(question.id))).all()
        for q in similar_questions:
            if q.similar_question_ids is None:
                q.similar_question_ids = [question.id]
            else:
                q.similar_question_ids.append(question.id)
        db.session.commit()
        return {'error': False}
class InstituteMockTestList(AuthorizedResource):
    class JSObject(fields.Raw):
        def format(self, value):
            return json.loads(value)

    mock_test_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'description': fields.String,
        'syllabus': fields.String,
        'difficulty': fields.String,
        'target_exam': fields.String,
        'for_institutes': fields.Integer,
        'is_locked': fields.Integer,
        'question_ids': JSObject,
        'type': fields.String,
        'type_id': fields.Integer,
        'prerequisite_id': fields.Integer(default=None),
        'duration': fields.Integer,
        'cutoff': fields.Float,
        'batches_pushed_to': fields.List(fields.Nested({
            'id': fields.Integer,
            'name': fields.String,
            'class': fields.String
        }))
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'mock_tests': fields.List(fields.Nested(mock_test_obj)),
        'total': fields.Integer
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('difficulty', type=str, choices=app.config['MOCK_TEST_DIFFICULTY_LEVEL'].keys())
        parser.add_argument('batches_pushed_to', type=comma_separated_ints_type)
        parser.add_argument('offset', type=int, default=0)
        parser.add_argument('limit', type=int, default=20)
        args = parser.parse_args()
        total = 0
        if args['batches_pushed_to'] is not None:
            pushed_mock_test_ids = {}
            for p in PushedMockTest.query.filter(PushedMockTest.batch_id.in_(args['batches_pushed_to'])).all():
                if p.mock_test_id not in pushed_mock_test_ids:
                    pushed_mock_test_ids[p.mock_test_id] = [p.batch_id]
                else:
                    pushed_mock_test_ids[p.mock_test_id].append(p.batch_id)
            exprs = []
            exprs.append(MockTest.id.in_(pushed_mock_test_ids.keys()))
            if args['difficulty'] is not None:
                exprs.append(MockTest.difficulty == args['difficulty'])
            mock_tests = MockTest.query.filter(*exprs).offset(args['offset']).limit(args['limit'])
            total = MockTest.query.filter(*exprs).count()
            batches = {b.id: b for b in Batch.get_filtered(include_ids=args['batches_pushed_to'])}
        else:
            exprs = []
            exprs.append(MockTest.for_institutes == True)
            exprs.append(MockTest.is_locked == True)
            if args['difficulty'] is not None:
                exprs.append(MockTest.difficulty == args['difficulty'])
            mock_tests = MockTest.query.filter(*exprs).offset(args['offset']).limit(args['limit'])
            batches = {b.id: b for b in Batch.get_filtered(institute_id=kwargs['user'].id)}
            total = MockTest.query.filter(*exprs).count()
            pushed_mock_test_ids = {}
            for p in PushedMockTest.query.filter(PushedMockTest.mock_test_id.in_([m.id for m in mock_tests]),
                                                 PushedMockTest.batch_id.in_(batches.keys())).all():
                if p.mock_test_id not in pushed_mock_test_ids:
                    pushed_mock_test_ids[p.mock_test_id] = [p.batch_id]
                else:
                    pushed_mock_test_ids[p.mock_test_id].append(p.batch_id)
        res = []
        for mock_test in mock_tests:
            mock_test.batches_pushed_to = [{'id': b_id, 'name': batches[b_id].name, 'class': batches[b_id].clazz} for
                                           b_id in pushed_mock_test_ids.get(mock_test.id, [])]
            res.append(mock_test)

        return {'mock_tests': res, 'total': total}
class InstituteList(AuthorizedResource):
    institute_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'email': fields.String,
        'username': fields.String,
        'location': fields.String,
        'mobile_no': fields.String,
        'logo_url': fields.String,
        'joined_at': fields.DateTime,
        'last_activity': fields.DateTime,
        'type': fields.Integer
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'institutes': fields.List(fields.Nested(institute_obj)),
        'total': fields.Integer
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'institute': fields.Nested(institute_obj)
    }

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit',
                            type=int,
                            default=app.config['INSTITUTE_LIST_LIMIT'])
        args = parser.parse_args()
        institutes, total = Institute.get_list(args['page'], args['limit'])
        return {'institutes': institutes, 'total': total}

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('email', type=str, required=True)
        parser.add_argument('password', type=str, required=True)
        parser.add_argument('location', type=str, required=True)
        parser.add_argument('username', type=str, required=True)
        parser.add_argument('mobile_no', type=str, required=True)
        parser.add_argument('logo', type=str)
        args = parser.parse_args()

        if args['logo'] is not None:
            s3 = S3()
            mimetype, image_data = parse_base64_string(args['logo'])
            mimetype_parts = mimetype.split('/')
            if len(mimetype_parts) > 1 and mimetype_parts[-1] in app.config[
                    'ACCEPTED_IMAGE_EXTENSIONS']:
                # if mimetype has an extension and the extension is in the accepted list then proceed with the upload
                content_type = mimetype_parts[-1]
                url = s3.upload(image_data, content_type)
            else:
                raise UnAcceptableFileType
        else:
            url = None

        institute = Institute.create(name=args['name'],
                                     email=args['email'],
                                     password=md5(
                                         args['password']).hexdigest(),
                                     username=args['username'],
                                     location=args['location'],
                                     mobile_no=args['mobile_no'],
                                     logo_url=url)

        return {'institute': institute}
示例#29
0
        for value in display_info.notes:
            response.append({
                "type": 'notes',
                # Note: type should be 'note' but for retrocompatibility, we can't change it
                "rel": 'notes',
                "id": value.uri,
                'value': value.note,
                'internal': True
            })
        return response


instance_status = {
    "data_version": fields.Integer(),
    "end_production_date": fields.String(),
    "is_connected_to_rabbitmq": fields.Boolean(),
    "last_load_at": fields.String(),
    "last_rt_data_loaded": fields.String(),
    "last_load_status": fields.Boolean(),
    "kraken_version": fields.String(attribute="navitia_version"),
    "nb_threads": fields.Integer(),
    "publication_date": fields.String(),
    "start_production_date": fields.String(),
    "status": fields.String(),
    "is_open_data": fields.Boolean(),
    "is_realtime_loaded": fields.Boolean(),
    "realtime_proxies": fields.Raw(),
}

instance_parameters = {
    'scenario': fields.Raw(attribute='_scenario_name'),
示例#30
0
class MockTestList(AuthorizedResource):

    class Qids(fields.Raw):
        def format(self, value):
            return json.loads(value)

    mock_test_obj = {
        'id': fields.Integer,
        'name': fields.String,
        'description': fields.String,
        'syllabus': fields.String,
        'difficulty': fields.Integer,
        'target_exam': fields.Integer,
        'for_institutes': fields.Integer,
        'is_locked': fields.Integer,
        'question_ids': Qids,
        'type': fields.String,
        'type_id': fields.Integer,
        'prerequisite_id': fields.Integer(default=None),
        'duration': fields.Integer,
        'cutoff': fields.Float
    }

    get_response = {
        'error': fields.Boolean(default=False),
        'mock_tests': fields.List(fields.Nested(mock_test_obj)),
        'total': fields.Integer
    }

    post_response = {
        'error': fields.Boolean(default=False),
        'mock_test': fields.Nested(mock_test_obj)
    }

    @classmethod
    def date_json_type(cls, data):
        """
        Parse the string date and output the datetime.date object.
        """

        try:
            print data
            date = datetime.datetime.strptime(data, "%Y-%m-%d").date()
            return date
        except Exception as e:
            raise ValueError("Date is not given in the proper format.")

    @classmethod
    def question_ids_json_type(cls, data):
        """
        Parse the question ids json
        Questions are supplied in the format {
            <parent_id1>: {
            "order": 2, "q_ids": [q_id1, q_id2]
            },
            <parent_id2>: {
            "order": 1, "q_ids": [q_id4, q_id5]
            }
        }

        :param data:
        :return:
        """
        try:
            parsed_data = json.loads(data)
            if not isinstance(parsed_data, dict):
                raise ValueError('question_ids should be in the form of object')
            for subject_id, d in parsed_data.items():
                if 'order' not in d or not isinstance(d['order'], int):
                    raise ValueError('order should be present for subject and should be integer')
                if 'q_ids' not in d:
                    raise ValueError('q_ids should be present for subject and should be a non empty array')

            return data

        except Exception as e:
            raise ValueError("question_ids should be json")

    @marshal_with(get_response)
    def get(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('difficulty', type=str, choices=app.config['MOCK_TEST_DIFFICULTY_LEVEL'].keys())
        parser.add_argument('target_exam', type=str, choices=app.config['TARGET_EXAMS'].keys())
        parser.add_argument('is_locked', type=int, choices=[0,1])
        parser.add_argument('for_institutes', type=int, choices=[0,1])
        parser.add_argument('page', type=int, default=1)
        parser.add_argument('limit', type=int, default=app.config['MOCK_TEST_LIST_LIMIT'])
        args = parser.parse_args()

        exprs = []
        if args['difficulty'] is not None:
            exprs.append(MockTest.difficulty == args['difficulty'])
        if args['target_exam'] is not None:
            exprs.append(MockTest.target_exam == args['target_exam'])
        if args['is_locked'] is not None:
            exprs.append(MockTest.is_locked == (args['is_locked'] == 1))
        if args['for_institutes'] is not None:
            exprs.append(MockTest.for_institutes == (args['for_institutes'] == 1))

        mock_test_pag_obj = MockTest.query.filter(*exprs).order_by(MockTest.created_at.desc()).paginate(args['page'], args['limit'])
        mock_tests = mock_test_pag_obj.items
        total = mock_test_pag_obj.total
        return {'mock_tests': mock_tests, 'total': total}

    @marshal_with(post_response)
    def post(self, *args, **kwargs):
        parser = reqparse.RequestParser()
        parser.add_argument('name', type=str, required=True)
        parser.add_argument('difficulty', type=str, required=True, choices=app.config['MOCK_TEST_DIFFICULTY_LEVEL'].keys())
        parser.add_argument('description', type=unicode)
        parser.add_argument('syllabus', type=unicode)
        parser.add_argument('target_exam', type=str, required=True, choices=app.config['TARGET_EXAMS'].keys())
        parser.add_argument('for_institutes', type=int, required=True, choices=[0, 1])
        parser.add_argument('type', type=str, required=True, choices=app.config['MOCK_TEST_TYPES'].keys())
        parser.add_argument('type_id', type=int)
        parser.add_argument('prerequisite_id', type=int)
        parser.add_argument('duration', type=int, required=True)
        parser.add_argument('cutoff', type=float, required=True)
        parser.add_argument('date_closed', type=bool, required=True)
        parser.add_argument('opening_date', type=self.__class__.date_json_type)

        # comma separated question ids
        parser.add_argument('question_ids', type=self.__class__.question_ids_json_type)
        args = parser.parse_args()

        for k,v in args.items():
            print "{0}: {1}".format(k, v)

        params = {
            "name": args['name'],
            "difficulty": args['difficulty'], 
            "description": args['description'], 
            "syllabus": args['syllabus'],
            "target_exam": args['target_exam'], 
            "for_institutes": args['for_institutes']==1,
            "question_ids": args['question_ids'],
            "type": args['type'],
            "type_id": args['type_id'],
            "prerequisite_id": args['prerequisite_id'],
            "duration": args['duration'],
            "cutoff": args['cutoff'],
            "created_by_type": kwargs['user_type'].id,
            "created_by_id": kwargs['user'].id,
            "date_closed": args['date_closed'],
            "opening_date": args.get('opening_date')
        }

        mock_test = MockTest.create(**params)
        return {'mock_test': mock_test}