def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('batch_id', type=int) parser.add_argument('batch_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('branches', type=comma_separated_ints_type) parser.add_argument('query', type=str) parser.add_argument('offset', type=int, default=0) parser.add_argument('limit', type=int, default=20) args = parser.parse_args() if args['branches'] is not None: args['branches'] = map(str, args['branches']) if args['batch_id'] is not None: batch = Batch.get(args['batch_id']) if args['batch_type'] is not None and batch.type != args['batch_type']: return {'students': []} if args['target_year'] is not None and batch.target_year != args['target_year']: return {'students': []} if args['target_exam'] is not None and batch.target_exam != args['target_exam']: return {'students': []} student_ids = [sb.student_id for sb in StudentBatches.query.filter(StudentBatches.batch_id == batch.id, StudentBatches.left_at == None).all()] else: batches = {b.id: b for b in Batch.get_filtered(type=args['batch_type'], target_year=args['target_year'], target_exam=args['target_exam'], institute_id=kwargs['user'].id, branches=args['branches'])} student_ids = list({sb.student_id for sb in StudentBatches.query.filter(StudentBatches.batch_id.in_(batches.keys()), StudentBatches.left_at == None).all()}) # for pagination if args['query'] is not None: students = Student.query.filter(Student.id.in_(student_ids), Student.name.ilike('%' + args['query'] + '%')).all() total = len(students) student_ids = [s.id for s in students][args['offset']:args['offset']+args['limit']] else: total = len(student_ids) student_ids = sorted(student_ids)[args['offset']:args['offset']+args['limit']] students = Student.query.filter(Student.id.in_(student_ids)).all() student_batches = {} # get all students whose id is present `student_ids` and have not left the batch and all their batches too for sb in StudentBatches.query.filter(StudentBatches.student_id.in_(student_ids), StudentBatches.left_at == None).all(): if sb.student_id not in student_batches: student_batches[sb.student_id] = [sb.batch_id] else: student_batches[sb.student_id].append(sb.batch_id) # need to make one more batch query because i need all the batches that any student in the result set is part of batches = {b.id: b for b in Batch.get_filtered(include_ids=list(itertools.chain(*student_batches.values())))} for student in students: student.batches = [{'id': b_id, 'name': batches[b_id].name} for b_id in student_batches.get(student.id, [])] return {'students': students, 'total': total}
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}
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}
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}
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}
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('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, required=True) 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.create(name=args['name'], email=args['email'], password=md5(args['password']).hexdigest(), mobile_no=args['mobile_no'], city=args['city'], area=args['area'], pin=args['pin'], school=args['school'], ntse_score=args['ntse_score'], roll_no=args['roll_no'], father_name=args['father_name'], father_mobile_no=args['father_mobile_no'], father_email=args['father_email'], registered_from='institute') 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 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}
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 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}
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}
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}
def get(self, *args, **kwargs): batch = BatchModel.get(kwargs['id']) return {'batch': batch}
def get(self, *args, **kwargs): parser = reqparse.RequestParser() parser.add_argument('target_exams', type=comma_separated_ints_type) parser.add_argument('batches', type=comma_separated_ints_type) args = parser.parse_args() # if batches are provided if args['batches'] is not None: batch_ids = args['batches'] # if batches are not provided but target exams are provided elif args['target_exams'] is not None: target_exams = map(str, args['target_exams']) batch_ids = [b.id for b in Batch.query.filter(Batch.target_exam.in_(target_exams), Batch.status == 1, Batch.institute_id == kwargs['user'].id).all()] # if no filters are used then get all batches for this institute else: batch_ids = [b.id for b in Batch.get_filtered(institute_id=kwargs['user'].id)] students = {} for sb in StudentBatches.query.filter(StudentBatches.batch_id.in_(batch_ids)).all(): student_id = sb.student_id batch_id = sb.batch_id if student_id not in students: students[student_id] = {} if batch_id not in students[student_id]: # not using dictionary for `joined_at` and `left_at` on purpose, saving memory students[student_id][batch_id] = (sb.joined_at, sb.left_at) # current_students, past_students = [], [] # for student in students: # (current_students, past_students)[student['left_at'] is not None].append(student) # Get all mock tests that were pushed to the batches with id in `batch_ids` pushed_mock_tests = PushedMockTest.query.filter(PushedMockTest.batch_id.in_(batch_ids)).all() exprs = [AttemptedMockTest.pushed_mock_test_id.in_([p.id for p in pushed_mock_tests])] # if len(current_students) > 0: # exprs.append(AttemptedMockTest.student_id.in_([s['id'] for s in current_students])) # if len(past_students) > 0: # for student in past_students: # exprs.append(or_(AttemptedMockTest.student_id == student['id'], AttemptedMockTest.attempted_at < student['left_at'])) attempted_mock_tests = AttemptedMockTest.query.filter(*exprs).all() mock_test_ids = list({a.mock_test_id for a in attempted_mock_tests}) mock_tests = {m.id: m for m in MockTest.query.filter(MockTest.id.in_(mock_test_ids)).all()} question_ids = set() for mock_test in mock_tests.values(): subjects = json.loads(mock_test.question_ids) for sid, data in subjects.items(): question_ids.update(set(data['q_ids'])) question_difficulty = {q.id: q.difficulty for q in Question.query.with_entities(Question.id, Question.difficulty).filter(Question.id.in_(list(question_ids)))} exam_weights = app.config['TARGET_EXAM_WEIGHT'] performance = {} topics = {} attempted_test_count = {} for amt in attempted_mock_tests: mock_test = mock_tests[amt.mock_test_id] d = [] subjects = json.loads(mock_test.question_ids) analysis = json.loads(amt.analysis) for sid, data in subjects.items(): for q_id in data['q_ids']: d.append(int(question_difficulty[q_id])) average_difficulty = sum(d)/float(len(d)) p = (amt.score/analysis['maximum_marks'])*exam_weights[mock_tests[amt.mock_test_id].target_exam] * average_difficulty if amt.student_id in performance: performance[amt.student_id][amt.id] = p else: performance[amt.student_id] = { amt.id: p } attempted_test_count[amt.student_id] = attempted_test_count.get(amt.student_id, 0) + 1 # this set is used for keeping track of those topic ids whose subject id not known yet new_topic_ids = set() for topic_id, data in analysis['topics'].items(): topic_id = int(topic_id) total = len(data['not_attempted']) + len(data['correct']) + len(data['incorrect']) correct = len(data['correct']) if topic_id in topics: topics[topic_id]['total'] += total topics[topic_id]['correct'] += correct else: # topic has not been seen yet new_topic_ids.add(topic_id) topics[topic_id] = { 'total': total, 'correct': correct } for sid, data in analysis['subjects'].items(): sid = int(sid) subject_topic_ids = set(data['topic_ids']) # topic ids of the current subject whose subject id was not known found_topic_ids = subject_topic_ids.intersection(new_topic_ids) for tid in found_topic_ids: topics[tid]['subject_id'] = sid new_topic_ids = new_topic_ids - found_topic_ids student_count = len(performance) top_student_count = int(student_count*(app.config['TOP_PERFORMERS_PERCENTAGE']/100)) top_student_count = top_student_count if top_student_count > app.config['TOP_PERFORMERS_MIN_COUNT'] else app.config['TOP_PERFORMERS_MIN_COUNT'] bottom_student_count = int(student_count*(app.config['BOTTOM_PERFORMERS_PERCENTAGE']/100)) bottom_student_count = bottom_student_count if bottom_student_count > app.config['BOTTOM_PERFORMERS_MIN_COUNT'] else app.config['BOTTOM_PERFORMERS_MIN_COUNT'] top_students = {} bottom_students = {} for student_id, data in performance.items(): score = sum(data.values())/float(len(data.values())) if len(top_students) < top_student_count: top_students[student_id] = score else: min_score = min(top_students.values()) if score > min_score: k = None for i, s in top_students.items(): if s == min_score: k = i break if k is not None: del top_students[k] top_students[student_id] = score if len(bottom_students) < bottom_student_count: bottom_students[student_id] = score else: max_score = max(bottom_students.values()) if score < max_score: k = None for i, s in bottom_students.items(): if s == max_score: k = i break if k is not None: del bottom_students[k] bottom_students[student_id] = score # Students that appear both in top students and bottom students should be removed from bottom students for student_id in top_students: if student_id in bottom_students: del bottom_students[student_id] top_topic_count = app.config['TOP_TOPICS_COUNT'] bottom_topic_count = app.config['BOTTOM_TOPICS_COUNT'] top_topics = {} bottom_topics = {} top_topics_by_subjects = {} bottom_topics_by_subjects = {} subject_ids = set() for topic_id, data in topics.items(): accuracy = (data['correct']*100.0)/data['total'] if data['total'] > 0 else 0 subject_id = data['subject_id'] subject_ids.add(subject_id) # Overall top topics # if number of top_topics found yet is less than required top topics then add topic to top_topics if len(top_topics) < top_topic_count: top_topics[topic_id] = accuracy # if number of top_topics found yet is more than or equal to required top_topics else: min_acc = min(top_topics.values()) # if accuracy of current topic is more than minimum accuracy of any topic in top_topics if accuracy > min_acc: k = None # in the next loop the topic_id with minimum accuracy is found for i, s in top_topics.items(): if s == min_acc: k = i break # remove the topic_id with minimum accuracy del top_topics[k] # add current topic to top_topics top_topics[topic_id] = accuracy # Subject wise top topics if subject_id not in top_topics_by_subjects or len(top_topics_by_subjects[subject_id]) < top_topic_count: if subject_id not in top_topics_by_subjects: top_topics_by_subjects[subject_id] = {} top_topics_by_subjects[subject_id][topic_id] = accuracy else: min_acc = min(top_topics_by_subjects[subject_id].values()) if accuracy > min_acc: k = None for i, s in top_topics_by_subjects[subject_id].items(): if s == min_acc: k = i break del top_topics_by_subjects[subject_id][k] top_topics_by_subjects[subject_id][topic_id] = accuracy # Overall bottom topics # if number of bottom_topics found yet is less than required bottom topics then add topic to bottom_topics if len(bottom_topics) < bottom_topic_count: bottom_topics[topic_id] = accuracy # if number of bottom_topics found yet is more than or equal to required bottom_topics else: max_acc = max(bottom_topics.values()) # if accuracy of current topic is less than maximum accuracy of any topic in bottom_topics if accuracy < max_acc: k = None # in the next loop the topic_id with maximum accuracy is found for i, s in bottom_topics.items(): if s == max_acc: k = i break # remove the topic_id with maximum accuracy del bottom_topics[k] # add current topic to bottom_topics bottom_topics[topic_id] = accuracy # Subject wise bottom topics if subject_id not in bottom_topics_by_subjects or len(bottom_topics_by_subjects[subject_id]) < bottom_topic_count: if subject_id not in bottom_topics_by_subjects: bottom_topics_by_subjects[subject_id] = {} bottom_topics_by_subjects[subject_id][topic_id] = accuracy else: max_acc = max(bottom_topics_by_subjects[subject_id].values()) if accuracy < max_acc: k = None for i, s in bottom_topics_by_subjects[subject_id].items(): if s == max_acc: k = i break del bottom_topics_by_subjects[subject_id][k] bottom_topics_by_subjects[subject_id][topic_id] = accuracy # Topics that appear both in top topics and bottom topics should be removed from bottom topics for topic_id in top_topics: if topic_id in bottom_topics: del bottom_topics[topic_id] # Topics that appear both in top topics for a subject and bottom topics of the same subject should be removed # from bottom topics of that subject for subject_id in top_topics_by_subjects: if subject_id in bottom_topics_by_subjects: for topic_id in top_topics_by_subjects[subject_id]: if topic_id in bottom_topics_by_subjects[subject_id]: del bottom_topics_by_subjects[subject_id][topic_id] student_objs = {s.id: s for s in Student.query.filter(Student.id.in_(top_students.keys()+bottom_students.keys()))} top_students_list = [] bottom_students_list = [] # Calculating attendance for top_students for student_id in top_students: total_pushed = 0 seen_mock_test_ids = set() for batch_id, dates in students[student_id].items(): # if current student if dates[1] is None: for pmt in pushed_mock_tests: # if mock test was pushed to this batch if pmt.batch_id == batch_id: if pmt.mock_test_id in seen_mock_test_ids: continue total_pushed += 1 seen_mock_test_ids.add(pmt.mock_test_id) # if past student else: for pmt in pushed_mock_tests: # if mock test was pushed to this batch before this student left the batch if pmt.batch_id == batch_id and dates[0] < pmt.pushed_at < dates[1]: if pmt.mock_test_id in seen_mock_test_ids: continue total_pushed += 1 seen_mock_test_ids.add(pmt.mock_test_id) student = { 'id': student_id, 'attendance': (attempted_test_count[student_id]*100.0)/total_pushed if total_pushed > 0 else 0, 'name': student_objs[student_id].name, 'score': top_students[student_id] } top_students_list.append(student) # Calculating attendance for bottom_students for student_id in bottom_students: total_pushed = 0 for batch_id, dates in students[student_id].items(): # if current student if dates[1] is None: for pmt in pushed_mock_tests: # if mock test was pushed to this batch if pmt.batch_id == batch_id: total_pushed += 1 # if past student else: for pmt in pushed_mock_tests: # if mock test was pushed to this batch before this student left the batch if pmt.batch_id == batch_id and dates[0] < pmt.pushed_at < dates[1]: total_pushed += 1 student = { 'id': student_id, 'attendance': (attempted_test_count[student_id]*100.0)/total_pushed if total_pushed > 0 else 0, 'name': student_objs[student_id].name, 'score': bottom_students[student_id] } bottom_students_list.append(student) required_topic_ids = set() for d in top_topics_by_subjects.values(): required_topic_ids.update(set(d.keys())) for d in bottom_topics_by_subjects.values(): required_topic_ids.update(set(d.keys())) node_objs = {n.id: n for n in Ontology.query.filter(or_(Ontology.id.in_(top_topics.keys()+bottom_topics.keys()), Ontology.id.in_(list(subject_ids)), Ontology.id.in_(list(required_topic_ids))))} top_topics_list = [] bottom_topics_list = [] for topic_id, accuracy in top_topics.items(): topic_id = int(topic_id) subject_id = node_objs[topic_id].parent_path[0] subject_name = node_objs[subject_id].name topic = { 'id': topic_id, 'name': node_objs[topic_id].name, 'accuracy': accuracy, 'subject_id': subject_id, 'subject_name': subject_name } top_topics_list.append(topic) for topic_id, accuracy in bottom_topics.items(): topic_id = int(topic_id) subject_id = node_objs[topic_id].parent_path[0] subject_name = node_objs[subject_id].name topic = { 'id': topic_id, 'name': node_objs[topic_id].name, 'accuracy': accuracy, 'subject_id': subject_id, 'subject_name': subject_name } bottom_topics_list.append(topic) for subject_id, data in top_topics_by_subjects.items(): subject_name = node_objs[subject_id].name topics_list = tuple(data.items()) top_topics_by_subjects[subject_id] = [{ 'id': tpl[0], 'name': node_objs[tpl[0]].name, 'accuracy': tpl[1], 'subject_id': subject_id, 'subject_name': subject_name } for tpl in topics_list] for subject_id, data in bottom_topics_by_subjects.items(): subject_name = node_objs[subject_id].name topics_list = tuple(data.items()) bottom_topics_by_subjects[subject_id] = [{ 'id': tpl[0], 'name': node_objs[tpl[0]].name, 'accuracy': tpl[1], 'subject_id': subject_id, 'subject_name': subject_name } for tpl in topics_list] return { 'top_students': top_students_list, 'bottom_students': bottom_students_list, 'top_topics': top_topics_list, 'bottom_topics': bottom_topics_list, 'top_topics_by_subjects': top_topics_by_subjects, 'bottom_topics_by_subjects': bottom_topics_by_subjects }
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}
email = student_details['email'], password = md5(student_details['password']).hexdigest(), mobile_no = student_details['mobile_no'], city = student_details['city'], area = student_details['area'], # pin = student_details['pin'], school = student_details['school'], # ntse_score = student_details['ntse_score'], roll_no = student_details['roll_no'], father_name = student_details['father_name'], father_mobile_no = student_details['father_mobile_no'], # father_email = student_details['father_email'], registered_from = student_details['registered_from'], target_year = int(student_details['target_year']) ) student.branches = [i for i in student_details['branches'].split(',')] student.target_exams = [int(i) for i in student_details['target_exams'].split(',')] batch_obj = all_batches[student_details['batch']] student_batch = StudentBatches(batch_id=batch_obj['id'], student_id=student.id, joined_at=datetime.datetime.utcnow()) db.session.add(student_batch) db.session.commit() _students = get_data_from_csv('/Users/rishabh/Downloads/student_data.csv') students = [student for student in _students] institute = Institute.get(4) batches = Batch.get_filtered(institute_id=institute.id) batches = {batch.name: batch.__dict__ for batch in batches} # for student in students: # create_student(student, batches)
def get_cumulative_analysis(student_id, institute_id=None): # get mock tests by student which have completed if institute_id is not None: batches = Batch.get_filtered(institute_id=institute_id) pushed_mock_tests = PushedMockTest.query.filter( PushedMockTest.batch_id.in_([b.id for b in batches])) attempted_mock_tests = AttemptedMockTest.query.filter( AttemptedMockTest.student_id == student_id, AttemptedMockTest.score != None, AttemptedMockTest.pushed_mock_test_id.in_( [p.id for p in pushed_mock_tests])).all() else: attempted_mock_tests = AttemptedMockTest.query.filter( AttemptedMockTest.student_id == student_id, AttemptedMockTest.score != None).all() mock_test_ids = [amt.mock_test_id for amt in attempted_mock_tests] mock_tests = MockTest.query.filter( MockTest.id.in_(mock_test_ids)).all() question_ids = set() overall_correct_q_ids = set() overall_incorrect_q_ids = set() overall_not_attempted_q_ids = set() total_ideal_time = 0 total_taken_time = 0 for amt in attempted_mock_tests: analysis = json.loads(amt.analysis) subjects = analysis['subjects'] for sid in subjects: overall_correct_q_ids.update(set(subjects[sid]['correct'])) overall_incorrect_q_ids.update(set(subjects[sid]['incorrect'])) overall_not_attempted_q_ids.update( set(subjects[sid]['not_attempted'])) question_ids.update(overall_correct_q_ids) question_ids.update(overall_incorrect_q_ids) question_ids.update(overall_not_attempted_q_ids) questions = { q.id: q for q in Question.get_filtertered_list( include_question_ids=list(question_ids))['questions'] } overall_attempted_count = len(overall_incorrect_q_ids) + len( overall_correct_q_ids) accuracy = round( len(overall_correct_q_ids) * 100.0 / overall_attempted_count, 2) if overall_attempted_count > 0 else 0.0 for amt in attempted_mock_tests: answers = json.loads(amt.answers) for q_id, answer in answers.items(): q_id = int(q_id) # if attempted question if len(answer['options']) != 0 and q_id in questions: total_ideal_time += questions[q_id].average_time total_taken_time += answer['time'] overall_speed = total_ideal_time - total_taken_time return { 'attempted_mock_tests': attempted_mock_tests, 'mock_tests': mock_tests, 'questions': questions.values(), 'accuracy': accuracy, 'speed': overall_speed }