Пример #1
0
    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))
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
    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
        )
Пример #5
0
    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,
                },
            ]
        }
Пример #6
0
    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,
                },
            ]
        }
Пример #7
0
    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)
Пример #8
0
    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]}}
Пример #9
0
    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]}}
Пример #10
0
    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)
Пример #11
0
    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))
Пример #12
0
    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}]
        }
Пример #13
0
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)]
Пример #14
0
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)]
Пример #15
0
    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]
            }
        }
Пример #16
0
    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)
Пример #17
0
    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)
Пример #18
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)
Пример #19
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)
Пример #20
0
 def get(self):
     number = self.request_int('num', len(Exercise.get_all_use_cache()))
     self.render_json(self.number_facts_for_geckboard_text(number))
Пример #21
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, _, _,
         user_exercise_graph) in izip(list_students, student_email_pairs,
                                      emails_escapejsed, user_exercise_graphs):

        student_email = student.email

        for (exercise, (_, _, _)) 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 graph_dict["reviewing"]:
                    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,
                    'profile_root': student.profile_root,
                    '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 (_, 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]

    exercise_data = {}

    for (student, _, _, user_exercise_graph) in izip(list_students,
                                                     student_email_pairs,
                                                     emails_escapejsed,
                                                     user_exercise_graphs):
        student_email = student.email

        for (exercise, (_, _, _)) 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 graph_dict["reviewing"]:
                    status = "Herzien"
                else:
                    status = "Gehaald"
                    if not graph_dict["explicitly_proficient"]:
                        status = ("Gehaald")

            elif graph_dict["struggling"]:
                status = "Moeite"
            elif graph_dict["total_done"] > 0:
                status = "Gestart"

            if student_email not in exercise_data:
                exercise_data[student_email] = {
                    'email': student.email,
                    'nickname': student.nickname,
                    'profile_root': student.profile_root,
                    '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 (_, 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)
    }
Пример #23
0
 def get(self):
     number = self.request_int("num", len(Exercise.get_all_use_cache()))
     self.render_json(self.number_facts_for_geckboard_text(number))