def get_json_response(self): # Currently accepts: { "buckets", "all", "newest" } to_show = self.request_string('show', 'buckets') past_days = self.request_int('past_days', 7) refresh_secs = self.request_int('rsecs', 30) today = dt.date.today() # We don't use App Engine Query filters so as to avoid adding entries to index.yaml days = [ today - dt.timedelta(days=i) for i in range(0, past_days) ] if to_show == 'all': exercise_names = [ex.name for ex in Exercise.get_all_use_cache()] return self.exercise_over_time_for_highcharts(exercise_names, days, 'All Exercises', showLegend=True) if to_show == 'newest': exercises = Exercise.get_all_use_cache() exercises.sort(key=lambda ex: ex.creation_date, reverse=True) exercise_names = [ex.name for ex in exercises] num_newest = self.request_int('newest', 5) exid = exercise_names[get_bucket_cursor(refresh_secs, num_newest)] title = 'Newest Exercises - %s' % Exercise.to_display_name(exid) return self.exercise_over_time_for_highcharts([exid], days, title, showLegend=True) num_buckets = self.request_int('buckets', NUM_BUCKETS) bucket_index = self.request_int('ix', 0) bucket_size = get_bucket_size(num_buckets, bucket_index) bucket_cursor = get_bucket_cursor(refresh_secs, bucket_size) exercise_names = exercises_in_bucket(num_buckets, bucket_index) exid = exercise_names[bucket_cursor] return self.exercise_over_time_for_highcharts([exid], days, Exercise.to_display_name(exid))
def get_use_cache(self): params = self.get_request_params() # Get the maximum so we know how the data label circles should be scaled most_new_users = 1 ex_stat_dict = {} for ex in Exercise.get_all_use_cache(): stat = ExerciseStatistic.get_by_date(ex.name, params['interested_day']) ex_stat_dict[ex.name] = stat if stat: most_new_users = max(most_new_users, stat.num_new_users()) data_points = [] min_y, max_y = -1, 1 for ex in Exercise.get_all_use_cache(): stat = ex_stat_dict[ex.name] y, x = -int(ex.h_position), int(ex.v_position) min_y, max_y = min(y, min_y), max(y, max_y) # Set the area of the circle proportional to the data value radius = 1 if stat: radius = math.sqrt( float(stat.num_new_users()) / most_new_users) * MAX_POINT_RADIUS point = { 'x': x, 'y': y, 'name': ex.display_name, 'marker': { 'radius': max(radius, 1) }, } data_points.append(point) context = { 'title': 'Exercises map - First attempts', 'series': { 'name': 'First attempts', 'data_values': json.dumps(data_points), }, 'minYValue': min_y - 1, 'maxYValue': max_y + 1, } return self.render_jinja2_template_to_string( 'exercisestats/highcharts_scatter_map.json', context)
def get_use_cache(self): params = self.get_request_params() # Get the maximum so we know how the data label circles should be scaled most_new_users = 1 ex_stat_dict = {} for ex in Exercise.get_all_use_cache(): stat = ExerciseStatistic.get_by_date(ex.name, params['interested_day']) ex_stat_dict[ex.name] = stat if stat: most_new_users = max(most_new_users, stat.num_new_users()) data_points = [] min_y, max_y = -1, 1 for ex in Exercise.get_all_use_cache(): stat = ex_stat_dict[ex.name] y, x = -int(ex.h_position), int(ex.v_position) min_y, max_y = min(y, min_y), max(y, max_y) # Set the area of the circle proportional to the data value radius = 1 if stat: radius = math.sqrt(float(stat.num_new_users()) / most_new_users) * MAX_POINT_RADIUS point = { 'x': x, 'y': y, 'name': ex.display_name, 'marker': { 'radius': max(radius, 1) }, } data_points.append(point) context = { 'title': 'Exercises map - First attempts', 'series': { 'name': 'First attempts', 'data_values': json.dumps(data_points), }, 'minYValue': min_y - 1, 'maxYValue': max_y + 1, } return self.render_jinja2_template_to_string( 'exercisestats/highcharts_scatter_map.json', context)
def exercise_counter_for_geckoboard_rag(): exercises = Exercise.get_all_use_cache() exercises.sort(key=lambda ex: ex.creation_date, reverse=True) last_exercise = exercises[0] num_exercises = len(exercises) last_exercise_author = last_exercise.author.nickname( ) if last_exercise.author else 'random person' text = "Thanks %s for %s!" % (last_exercise_author, last_exercise.display_name) return { 'item': [ { 'value': None, 'text': '', }, { 'value': None, 'text': '', }, { 'value': num_exercises, 'text': text, }, ] }
def exercise_counter_for_geckoboard_rag(): exercises = Exercise.get_all_use_cache() exercises.sort(key=lambda ex: ex.creation_date, reverse=True) last_exercise = exercises[0] num_exercises = len(exercises) last_exercise_author = last_exercise.author.nickname() if last_exercise.author else 'random person' text = "Thanks %s for %s!" % (last_exercise_author, last_exercise.display_name) return { 'item': [ { 'value': None, 'text': '', }, { 'value': None, 'text': '', }, { 'value': num_exercises, 'text': text, }, ] }
def exercise_title_dicts(): return [{ "title": exercise.display_name, "key": str(exercise.key()), "relative_url": exercise.relative_url, "id": exercise.name, } for exercise in Exercise.get_all_use_cache() if not exercise.summative]
def exercise_progress_graph_context(user_data_student): if not user_data_student: return {} user = user_data_student.user exercise_data = {} exercises = Exercise.get_all_use_cache() user_exercises = UserExercise.get_for_user_use_cache(user) dict_user_exercises = {} for user_exercise in user_exercises: dict_user_exercises[user_exercise.exercise] = user_exercise for exercise in exercises: chart_link ="" status = "" color = "transparent" exercise_display = Exercise.to_display_name(exercise.name) ex_link = "/exercises?exid="+exercise.name hover = "<b>%s</b><br/><em><nobr>Status: %s</nobr></em><br/><em>Streak: %s</em><br/><em>Problems attempted: %s</em>" % ( exercise_display, "Not Started", 0, 0) chart_link = "/profile/graph/exerciseproblems?student_email=%s&exercise_name=%s" % (user.email(), exercise.name) user_exercise = dict_user_exercises[exercise.name] if dict_user_exercises.has_key(exercise.name) else None if user_data_student.is_proficient_at(exercise.name): status = "Proficient" color = "proficient" if not user_data_student.is_explicitly_proficient_at(exercise.name): status = "Proficient (due to proficiency in a more advanced module)" elif user_exercise is not None and UserExercise.is_struggling_with(user_exercise, exercise): status = "Struggling" color = "struggling" elif user_exercise is not None and user_exercise.total_done > 0: status = "Started" color = "started" if len(status) > 0: hover = "<b>%s</b><br/><em><nobr>Status: %s</nobr></em><br/><em>Streak: %s</em><br/><em>Problems attempted: %s</em>" % (exercise_display, status, user_exercise.streak if user_exercise is not None else 0, user_exercise.total_done if user_exercise is not None else 0) exercise_data[exercise.name] = { "short_name": exercise.short_name(), "chart_link": chart_link, "ex_link": ex_link, "hover": hover, "color": color } return { 'exercises': exercises, 'exercise_data': exercise_data, }
def exercise_progress_graph_context(user_data_student): if not user_data_student: return {} exercise_data = {} exercises = Exercise.get_all_use_cache() user_exercise_graph = UserExerciseGraph.get(user_data_student) review_exercise_names = user_exercise_graph.review_exercise_names() for exercise in exercises: chart_link ="" status = "" color = "transparent" exercise_display = Exercise.to_display_name(exercise.name) hover = "<b>%s</b><br/><em><nobr>Status: %s</nobr></em><br/><em>Progress: %s</em><br/><em>Problems attempted: %s</em>" % ( exercise_display, "Not Started", '0%', 0) chart_link = "/profile/graph/exerciseproblems?student_email=%s&exercise_name=%s" % (user_data_student.email, exercise.name) graph_dict = user_exercise_graph.graph_dict(exercise.name) if graph_dict["proficient"]: if exercise.name in review_exercise_names: status = "Review" color = "review light" else: status = "Proficient" color = "proficient" if not graph_dict["explicitly_proficient"]: status = "Proficient (due to proficiency in a more advanced module)" elif graph_dict["struggling"]: status = "Struggling" color = "struggling" elif graph_dict["total_done"] > 0: status = "Started" color = "started" if len(status) > 0: hover = "<b>%s</b><br/><em><nobr>Status: %s</nobr></em><br/><em>Progress: %s</em><br/><em>Problems attempted: %s</em>" % (exercise_display, status, UserExercise.to_progress_display(graph_dict["progress"]), graph_dict["total_done"]) exercise_data[exercise.name] = { "short_name": exercise.short_name(), "chart_link": chart_link, "ex_link": exercise.relative_url, "hover": hover, "color": color } return { 'exercises': exercises, 'exercise_data': exercise_data, }
def get(self): date_to_set = self.request_date('date', "%Y/%m/%d") exercises = Exercise.get_all_use_cache() updated = [] for ex in exercises: ex.creation_date = date_to_set updated.append(ex) db.put(updated)
def get_ip_addresses_for_geckoboard_map(date): ip_addresses = [] for ex in Exercise.get_all_use_cache(): stat = ExerciseStatistic.get_by_date(ex.name, date) if stat: ip_addresses += stat.histogram.get('ip_addresses', []) return {'points': {'point': [{'ip': addr} for addr in ip_addresses]}}
def get_json_response(self): # Currently accepts: { "buckets", "all", "newest" } to_show = self.request_string('show', 'buckets') past_days = self.request_int('past_days', 7) refresh_secs = self.request_int('rsecs', 30) today = dt.date.today() # We don't use App Engine Query filters so as to avoid adding entries to index.yaml days = [today - dt.timedelta(days=i) for i in range(0, past_days)] if to_show == 'all': exercise_names = [ex.name for ex in Exercise.get_all_use_cache()] return self.exercise_over_time_for_highcharts(exercise_names, days, 'All Exercises', showLegend=True) if to_show == 'newest': exercises = Exercise.get_all_use_cache() exercises.sort(key=lambda ex: ex.creation_date, reverse=True) exercise_names = [ex.name for ex in exercises] num_newest = self.request_int('newest', 5) exid = exercise_names[get_bucket_cursor(refresh_secs, num_newest)] title = 'Newest Exercises - %s' % Exercise.to_display_name(exid) return self.exercise_over_time_for_highcharts([exid], days, title, showLegend=True) num_buckets = self.request_int('buckets', NUM_BUCKETS) bucket_index = self.request_int('ix', 0) bucket_size = get_bucket_size(num_buckets, bucket_index) bucket_cursor = get_bucket_cursor(refresh_secs, bucket_size) exercise_names = exercises_in_bucket(num_buckets, bucket_index) exid = exercise_names[bucket_cursor] return self.exercise_over_time_for_highcharts( [exid], days, Exercise.to_display_name(exid))
def exercises_in_bucket(num_buckets, bucket_index): exercise_names = [ex.name for ex in Exercise.get_all_use_cache()] exercise_names.sort() # These calculations evenly distribute exercises among buckets, with excess # going to the first few buckets. # In particular, max_capacity(buckets) - min_capacity(buckets) <= 1. num_exercises = len(exercise_names) min_bucket_size = num_exercises / num_buckets bucket_rem = num_exercises % num_buckets first = bucket_index * min_bucket_size + min(bucket_rem, bucket_index) return exercise_names[ first : first + get_bucket_size(num_buckets, bucket_index) ]
def get_ip_addresses_for_geckoboard_map(date): ip_addresses = [] for ex in Exercise.get_all_use_cache(): stat = ExerciseStatistic.get_by_date(ex.name, date) if stat: ip_addresses += stat.histogram.get('ip_addresses', []) return { 'points': { 'point': [{'ip': addr} for addr in ip_addresses] } }
def exercises_in_bucket(num_buckets, bucket_index): exercise_names = [ex.name for ex in Exercise.get_all_use_cache()] exercise_names.sort() # These calculations evenly distribute exercises among buckets, with excess # going to the first few buckets. # In particular, max_capacity(buckets) - min_capacity(buckets) <= 1. num_exercises = len(exercise_names) min_bucket_size = num_exercises / num_buckets bucket_rem = num_exercises % num_buckets first = bucket_index * min_bucket_size + min(bucket_rem, bucket_index) return exercise_names[first:first + get_bucket_size(num_buckets, bucket_index)]
def get_histogram_spline_for_highcharts(self, earliest_dt=dt.datetime.min): histogram = {} for ex in Exercise.get_all_use_cache(): if ex.creation_date: creation_day = dt.datetime.combine(ex.creation_date, dt.time()) timestamp = to_unix_secs(creation_day) * 1000 histogram[timestamp] = histogram.get(timestamp, 0) + 1 total_exercises = {} prev_value = 0 for day, value in sorted(histogram.items()): prev_value = total_exercises[day] = prev_value + value # Only retain recent dates earliest_unix = to_unix_secs(earliest_dt) * 1000 histogram = [[k, v] for k, v in histogram.items() if k >= earliest_unix] total_exercises = [[k, v] for k, v in total_exercises.items() if k >= earliest_unix] context = { 'series': [{ 'name': 'Histogram (created per day)', 'type': 'column', 'data_values': json.dumps(histogram), 'axis': 0, }, { 'name': 'Total exercises', 'type': 'spline', 'data_values': json.dumps(total_exercises), 'axis': 1, }], # Let highcharts determine the scales for now. 'axes': [ { 'max': 'null' }, { 'max': 'null' }, ], } return self.render_jinja2_template_to_string( 'exercisestats/highcharts_exercises_created_histogram.json', context)
def add_related_exercises(videos): logging.info("%s videos", len(videos)) exercises = {e.key():e for e in Exercise.get_all_use_cache()} relations = {} logging.info("%s exercises", len(exercises)) for exvid in ExerciseVideo.all().run(): ex = exercises.get(exvid.key_for_exercise()) if ex: relations.setdefault(exvid.key_for_video(),[]).append(ex) for exs in relations.itervalues(): exs.sort(key=lambda e: (e.v_position, e.h_position)) logging.info("%s related videos", len(relations)) for vid in videos: exs = relations.get(vid.key()) or [] vid.cached_related_exercises = exs
def add_related_exercises(videos): logging.info("%s videos", len(videos)) exercises = {e.key(): e for e in Exercise.get_all_use_cache()} relations = {} logging.info("%s exercises", len(exercises)) for exvid in ExerciseVideo.all().run(): ex = exercises.get(exvid.key_for_exercise()) if ex: relations.setdefault(exvid.key_for_video(), []).append(ex) for exs in relations.itervalues(): exs.sort(key=lambda e: (e.v_position, e.h_position)) logging.info("%s related videos", len(relations)) for vid in videos: exs = relations.get(vid.key()) or [] vid.cached_related_exercises = exs
def get_histogram_spline_for_highcharts(self, earliest_dt=dt.datetime.min): histogram = {} for ex in Exercise.get_all_use_cache(): if ex.creation_date: creation_day = dt.datetime.combine(ex.creation_date, dt.time()) timestamp = to_unix_secs(creation_day) * 1000 histogram[timestamp] = histogram.get(timestamp, 0) + 1 total_exercises = {} prev_value = 0 for day, value in sorted(histogram.items()): prev_value = total_exercises[day] = prev_value + value # Only retain recent dates earliest_unix = to_unix_secs(earliest_dt) * 1000 histogram = [[k,v] for k,v in histogram.items() if k >= earliest_unix] total_exercises = [[k,v] for k,v in total_exercises.items() if k >= earliest_unix] context = { 'series': [ { 'name': 'Histogram (created per day)', 'type': 'column', 'data_values': json.dumps(histogram), 'axis': 0, }, { 'name': 'Total exercises', 'type': 'spline', 'data_values': json.dumps(total_exercises), 'axis': 1, } ], # Let highcharts determine the scales for now. 'axes': [ { 'max': 'null' }, { 'max': 'null' }, ], } return self.render_jinja2_template_to_string( 'exercisestats/highcharts_exercises_created_histogram.json', context)
def get_content_data(): topics = {str(t.key()):(idx, t) for idx, t in enumerate(Topic.get_visible_topics())} topic_names = {} def get_topics_of(item): def g(): if not item.topic_string_keys: return seen = set() for tk in item.topic_string_keys: try: idx, topic = topics[tk] except KeyError: continue for depth, tk2 in enumerate(topic.ancestor_keys[:-1][::-1]): try: idx2, topic2 = topics[str(tk2)] except KeyError: continue if idx2 in seen: continue seen.add(idx2) topic_names[idx2] = topic2.title # use depth for sorting by topic level yield depth, idx2 return [idx for _, idx in sorted(g())] videos = {video.key().id(): dict( key_id=video.key().id(), name=video.readable_id, display_name=video.title, topics=get_topics_of(video) ) for video in Video.get_all()} exercises = {exercise.name: dict( name=exercise.name, display_name=exercise.display_name, topics=get_topics_of(exercise), ) for exercise in Exercise.get_all_use_cache()} return topic_names, videos, exercises
def class_progress_report_graph_context(user_data, list_students): if not user_data: return {} list_students = sorted(list_students, key=lambda student: student.nickname) student_email_pairs = [ (escape(s.email), (s.nickname[:14] + '...') if len(s.nickname) > 17 else s.nickname) for s in list_students ] emails_escapejsed = [escapejs(s.email) for s in list_students] exercises_all = Exercise.get_all_use_cache() user_exercise_graphs = UserExerciseGraph.get(list_students) exercises_found = [] for exercise in exercises_all: for user_exercise_graph in user_exercise_graphs: graph_dict = user_exercise_graph.graph_dict(exercise.name) if graph_dict and graph_dict["total_done"]: exercises_found.append(exercise) break exercise_names = [(e.name, e.display_name, escapejs(e.name)) for e in exercises_found] exercise_list = [{ 'name': e.name, 'display_name': e.display_name } for e in exercises_found] videos_all = Video.get_all() all_video_progress = dict( zip(list_students, get_video_progress_for_students(list_students))) videos_found = reduce(set.union, all_video_progress.itervalues(), set()) videos_found = [ video for video in videos_all if video.key().id() in videos_found ] video_list = [{ 'name': v.readable_id, 'display_name': v.title } for v in videos_found] progress_data = {} for (student, student_email_pair, escapejsed_student_email, user_exercise_graph) in izip(list_students, student_email_pairs, emails_escapejsed, user_exercise_graphs): student_email = student.email student_review_exercise_names = user_exercise_graph.review_exercise_names( ) progress_data[student_email] = student_data = { 'email': student.email, 'nickname': student.nickname, 'profile_root': student.profile_root, 'exercises': [], 'videos': [], } for (exercise, (_, exercise_display, exercise_name_js)) in izip(exercises_found, exercise_names): exercise_name = exercise.name graph_dict = user_exercise_graph.graph_dict(exercise_name) status = "" status_name = "" if graph_dict["proficient"]: if exercise_name in student_review_exercise_names: status_name = "review" else: if not graph_dict["explicitly_proficient"]: status_name = "proficient_implicit" else: status_name = "proficient" elif graph_dict["struggling"]: status_name = "struggling" elif graph_dict["total_done"] > 0: status_name = "started" status = STATUSES[status_name] if status: student_data['exercises'].append({ "status": status, "status_name": status_name, "progress": graph_dict["progress"], "total_done": graph_dict["total_done"], "last_done": graph_dict["last_done"] if graph_dict["last_done"] and graph_dict["last_done"].year > 1 else '', "last_done_ago": timesince_ago(graph_dict["last_done"]) if graph_dict["last_done"] and graph_dict["last_done"].year > 1 else '' }) else: student_data['exercises'].append({ "name": exercise_name, "status": status, }) video_progress = all_video_progress[student] for video in videos_found: status_name = video_progress.get(video.key().id(), "") status = STATUSES[status_name] student_data['videos'].append({ "name": video.title, "status": status, "status_name": status_name, }) student_row_data = [data for key, data in progress_data.iteritems()] return { 'exercise_names': exercise_list, 'video_names': video_list, 'progress_data': student_row_data, 'coach_email': user_data.email, 'c_points': reduce(lambda a, b: a + b, map(lambda s: s.points, list_students), 0) }
def class_progress_report_graph_context(user_data, list_students): if not user_data: return {} list_students = sorted(list_students, key=lambda student: student.nickname) student_email_pairs = [(escape(s.email), (s.nickname[:14] + '...') if len(s.nickname) > 17 else s.nickname) for s in list_students] emails_escapejsed = [escapejs(s.email) for s in list_students] exercises_all = Exercise.get_all_use_cache() user_exercise_graphs = UserExerciseGraph.get(list_students) exercises_found = [] for exercise in exercises_all: for user_exercise_graph in user_exercise_graphs: graph_dict = user_exercise_graph.graph_dict(exercise.name) if graph_dict and graph_dict["total_done"]: exercises_found.append(exercise) break exercise_names = [(e.name, e.display_name, escapejs(e.name)) for e in exercises_found] exercise_list = [{'name': e.name, 'display_name': e.display_name} for e in exercises_found] exercise_data = {} for (student, student_email_pair, escapejsed_student_email, user_exercise_graph) in izip(list_students, student_email_pairs, emails_escapejsed, user_exercise_graphs): student_email = student.email student_review_exercise_names = user_exercise_graph.review_exercise_names() for (exercise, (_, exercise_display, exercise_name_js)) in izip(exercises_found, exercise_names): exercise_name = exercise.name graph_dict = user_exercise_graph.graph_dict(exercise_name) status = "" if graph_dict["proficient"]: if exercise_name in student_review_exercise_names: status = "Review" else: status = "Proficient" if not graph_dict["explicitly_proficient"]: status = "Proficient (due to proficiency in a more advanced module)" elif graph_dict["struggling"]: status = "Struggling" elif graph_dict["total_done"] > 0: status = "Started" if student_email not in exercise_data: exercise_data[student_email] = { 'email': student.email, 'nickname': student.nickname, 'exercises': [] } if len(status) > 0: exercise_data[student_email]['exercises'].append({ "status": status, "progress": graph_dict["progress"], "total_done": graph_dict["total_done"], "last_done": graph_dict["last_done"] if graph_dict["last_done"] and graph_dict["last_done"].year > 1 else '', "last_done_ago": timesince_ago(graph_dict["last_done"]) if graph_dict["last_done"] and graph_dict["last_done"].year > 1 else '' }) else: exercise_data[student_email]['exercises'].append({ "name": exercise_name, "status": status, }) student_row_data = [data for key, data in exercise_data.iteritems()] return { 'exercise_names': exercise_list, 'exercise_data': student_row_data, 'coach_email': user_data.email, 'c_points': reduce(lambda a, b: a + b, map(lambda s: s.points, list_students), 0) }
def class_progress_report_graph_context(user_data, list_students): if not user_data: return {} list_students = sorted(list_students, key=lambda student: student.nickname) student_email_pairs = [(escape(s.email), (s.nickname[:14] + '...') if len(s.nickname) > 17 else s.nickname) for s in list_students] emails_escapejsed = [escapejs(s.email) for s in list_students] exercises_all = Exercise.get_all_use_cache() user_exercise_graphs = UserExerciseGraph.get(list_students) exercises_found = [] for exercise in exercises_all: for user_exercise_graph in user_exercise_graphs: graph_dict = user_exercise_graph.graph_dict(exercise.name) if graph_dict and graph_dict["total_done"]: exercises_found.append(exercise) break exercise_names = [(e.name, e.display_name, escapejs(e.name)) for e in exercises_found] exercise_list = [{'name': e.name, 'display_name': e.display_name} for e in exercises_found] videos_all = Video.get_all() all_video_progress = dict(zip(list_students, get_video_progress_for_students(list_students))) videos_found = reduce(set.union, all_video_progress.itervalues(), set()) videos_found = [video for video in videos_all if video.key().id() in videos_found] video_list = [{'name': v.readable_id, 'display_name': v.title} for v in videos_found] progress_data = {} for (student, student_email_pair, escapejsed_student_email, user_exercise_graph) in izip(list_students, student_email_pairs, emails_escapejsed, user_exercise_graphs): student_email = student.email student_review_exercise_names = user_exercise_graph.review_exercise_names() progress_data[student_email] = student_data = { 'email': student.email, 'nickname': student.nickname, 'profile_root': student.profile_root, 'exercises': [], 'videos': [], } for (exercise, (_, exercise_display, exercise_name_js)) in izip(exercises_found, exercise_names): exercise_name = exercise.name graph_dict = user_exercise_graph.graph_dict(exercise_name) status = "" status_name = "" if graph_dict["proficient"]: if exercise_name in student_review_exercise_names: status_name = "review" else: if not graph_dict["explicitly_proficient"]: status_name = "proficient_implicit" else: status_name = "proficient" elif graph_dict["struggling"]: status_name = "struggling" elif graph_dict["total_done"] > 0: status_name = "started" status = STATUSES[status_name] if status: student_data['exercises'].append({ "status": status, "status_name": status_name, "progress": graph_dict["progress"], "total_done": graph_dict["total_done"], "last_done": graph_dict["last_done"] if graph_dict["last_done"] and graph_dict["last_done"].year > 1 else '', "last_done_ago": timesince_ago(graph_dict["last_done"]) if graph_dict["last_done"] and graph_dict["last_done"].year > 1 else '' }) else: student_data['exercises'].append({ "name": exercise_name, "status": status, }) video_progress = all_video_progress[student] for video in videos_found: status_name = video_progress.get(video.key().id(), "") status = STATUSES[status_name] student_data['videos'].append({ "name": video.title, "status": status, "status_name": status_name, }) student_row_data = [data for key, data in progress_data.iteritems()] return { 'exercise_names': exercise_list, 'video_names': video_list, 'progress_data': student_row_data, 'coach_email': user_data.email, 'c_points': reduce(lambda a, b: a + b, map(lambda s: s.points, list_students), 0) }
def get_bucket_size(num_buckets, bucket_index): num_exercises = len(Exercise.get_all_use_cache()) bucket_rem = num_exercises % num_buckets return (num_exercises / num_buckets) + (1 if bucket_index < bucket_rem else 0)
def exercise_progress_graph_context(user_data_student): if not user_data_student: return {} exercise_data = {} exercises = Exercise.get_all_use_cache() user_exercise_graph = UserExerciseGraph.get(user_data_student) review_exercise_names = user_exercise_graph.review_exercise_names() for exercise in exercises: chart_link = "" status = "" color = "transparent" exercise_display = Exercise.to_display_name(exercise.name) hover = "<b>%s</b><br/><em><nobr>Status: %s</nobr></em><br/><em>Progress: %s</em><br/><em>Problems attempted: %s</em>" % ( exercise_display, "Not Started", '0%', 0) chart_link = "/profile/graph/exerciseproblems?student_email=%s&exercise_name=%s" % ( user_data_student.email, exercise.name) graph_dict = user_exercise_graph.graph_dict(exercise.name) if graph_dict["proficient"]: if exercise.name in review_exercise_names: status = "Review" color = "review light" else: status = "Proficient" color = "proficient" if not graph_dict["explicitly_proficient"]: status = "Proficient (due to proficiency in a more advanced module)" elif graph_dict["struggling"]: status = "Struggling" color = "struggling" elif graph_dict["total_done"] > 0: status = "Started" color = "started" if len(status) > 0: hover = "<b>%s</b><br/><em><nobr>Status: %s</nobr></em><br/><em>Progress: %s</em><br/><em>Problems attempted: %s</em>" % ( exercise_display, status, UserExercise.to_progress_display( graph_dict["progress"]), graph_dict["total_done"]) exercise_data[exercise.name] = { "short_name": exercise.short_name(), "chart_link": chart_link, "ex_link": exercise.relative_url, "hover": hover, "color": color } return { 'exercises': exercises, 'exercise_data': exercise_data, }
def get(self): number = self.request_int('num', len(Exercise.get_all_use_cache())) self.render_json(self.number_facts_for_geckboard_text(number))