def can_cross_empty_bridge(self): bridge_name = "balrog" filter_type = "all-users" bridge = GandalfBridge.get_or_insert(bridge_name) return gandalf(bridge_name)
def get(self): if not gandalf.gandalf("new_faster_search"): self.get_old() return query = self.request.get('page_search_query') template_values = {'page_search_query': query} query = query.strip() if len(query) < search.SEARCH_PHRASE_MIN_LENGTH: if len(query) > 0: template_values.update({ 'query_too_short': search.SEARCH_PHRASE_MIN_LENGTH }) self.render_jinja2_template("searchresults_new.html", template_values) return searched_phrases = [] url = "http://search-rpc.khanacademy.org/solr/select/?q=%s&start=0&rows=1000&indent=on&wt=json&fl=*%%20score" % urllib.quote(query) try: logging.info("Fetching: %s" % url) # Allow responses to be cached for an hour response = urlfetch.fetch(url = url, deadline=25, headers = {'Cache-Control' : 'max-age=3600'}) response_object = json.loads(response.content) except Exception, e: logging.error("Failed to fetch search results from search-rpc! Error: %s" % str(e)) template_values.update({ 'server_timout': True }) self.render_jinja2_template("searchresults_new.html", template_values) return
def get(self): self.render_jinja2_template( 'about/about_the_site.html', { "selected_id": "the-site", "approx_vid_count": Video.approx_count(), "gandalf_production_test": gandalf("production_test"), })
def add_global_template_values(self, template_values): template_values['App'] = App template_values['None'] = None if not template_values.has_key('user_data'): user_data = UserData.current() template_values['user_data'] = user_data user_data = template_values['user_data'] template_values['username'] = user_data.nickname if user_data else "" template_values[ 'viewer_profile_root'] = user_data.profile_root if user_data else "/profile/nouser" template_values['points'] = user_data.points if user_data else 0 template_values[ 'logged_in'] = not user_data.is_phantom if user_data else False template_values['http_host'] = os.environ["HTTP_HOST"] # Always insert a post-login request before our continue url template_values['continue'] = util.create_post_login_url( template_values.get('continue') or self.request.uri) template_values['login_url'] = ( '%s&direct=1' % util.create_login_url(template_values['continue'])) template_values['logout_url'] = util.create_logout_url( self.request.uri) template_values['is_mobile'] = False template_values['is_mobile_capable'] = False template_values['is_ipad'] = False if self.is_mobile_capable(): template_values['is_mobile_capable'] = True template_values['is_ipad'] = self.is_ipad() if 'is_mobile_allowed' in template_values and template_values[ 'is_mobile_allowed']: template_values['is_mobile'] = self.is_mobile() # overridable hide_analytics querystring that defaults to true in dev # mode but false for prod. hide_analytics = self.request_bool("hide_analytics", App.is_dev_server) template_values['hide_analytics'] = hide_analytics # client-side error logging template_values['include_errorception'] = gandalf('errorception') if user_data: goals = GoalList.get_current_goals(user_data) goals_data = [g.get_visible_data() for g in goals] if goals_data: template_values['global_goals'] = jsonify(goals_data) app_host = self.request.host.split(":")[0] if app_host[0].isdigit(): app_host = app_host.partition(".")[2] template_values['webengage_id'] = App.webengage_id.get( app_host, app_host) if App.webengage_id else "" return template_values
def can_cross_all_users_blacklist(self): bridge_name = "balrog" filter_type = "all-users" bridge = GandalfBridge.get_or_insert(bridge_name) GandalfFilter(bridge=bridge, filter_type=filter_type, whitelist=False).put() return gandalf(bridge_name)
def add_global_template_values(self, template_values): template_values["App"] = App template_values["None"] = None if not template_values.has_key("user_data"): user_data = UserData.current() template_values["user_data"] = user_data user_data = template_values["user_data"] email = user_data.email if user_data else "" template_values["username"] = user_data.nickname if user_data else "" template_values["user_email"] = email if not is_facebook_user_id(email) else "" template_values["viewer_profile_root"] = user_data.profile_root if user_data else "/profile/nouser" template_values["points"] = user_data.points if user_data else 0 template_values["logged_in"] = not user_data.is_phantom if user_data else False template_values["http_host"] = os.environ["HTTP_HOST"] # Always insert a post-login request before our continue url template_values["continue"] = util.create_post_login_url(template_values.get("continue") or self.request.uri) template_values["login_url"] = "%s&direct=1" % util.create_login_url(template_values["continue"]) template_values["logout_url"] = util.create_logout_url(self.request.uri) template_values["is_mobile"] = False template_values["is_mobile_capable"] = False template_values["is_ipad"] = False if self.is_mobile_capable(): template_values["is_mobile_capable"] = True template_values["is_ipad"] = self.is_ipad() if "is_mobile_allowed" in template_values and template_values["is_mobile_allowed"]: template_values["is_mobile"] = self.is_mobile() # overridable hide_analytics querystring that defaults to true in dev # mode but false for prod. hide_analytics = self.request_bool("hide_analytics", App.is_dev_server) template_values["hide_analytics"] = hide_analytics # client-side error logging template_values["include_errorception"] = gandalf("errorception") if user_data: goals = GoalList.get_current_goals(user_data) goals_data = [g.get_visible_data() for g in goals] if goals_data: template_values["global_goals"] = jsonify(goals_data) app_host = self.request.host.split(":")[0] if app_host[0].isdigit(): app_host = app_host.partition(".")[2] template_values["webengage_id"] = App.webengage_id.get(app_host, app_host) if App.webengage_id else "" return template_values
def can_cross_all_users_outside_percentage(self): bridge_name = "balrog" filter_type = "all-users" bridge = GandalfBridge.get_or_insert(bridge_name) filter = GandalfFilter(bridge=bridge, filter_type=filter_type, whitelist=True) filter.put() identity_percentage = BridgeFilter._identity_percentage(filter.key()) filter.percentage = identity_percentage filter.put() return gandalf(bridge_name)
def get(self, exid=None): # TODO(david): Is there some webapp2 magic that will allow me not to # repeat this URL string in main.py? review_mode = self.request.path == "/review" and ( ab_test('Review Mode UI', conversion_name=ViewExercise._review_conversion_names, conversion_type=ViewExercise._review_conversion_types)) if not exid and not review_mode: self.redirect("/exercise/%s" % self.request_string("exid", default="addition_1")) return user_data = models.UserData.current() or models.UserData.pre_phantom() user_exercise_graph = models.UserExerciseGraph.get(user_data) if review_mode: # Take the first review exercise if available exid = (user_exercise_graph.review_exercise_names() or user_exercise_graph.proficient_exercise_names() or ["addition_1"])[0] reviews_left_count = user_exercise_graph.reviews_left_count() exercise = models.Exercise.get_by_name(exid) if not exercise: raise MissingExerciseException("Missing exercise w/ exid '%s'" % exid) user_exercise = user_data.get_or_insert_exercise(exercise) # Cache these so we don't have to worry about future lookups user_exercise.exercise_model = exercise user_exercise._user_data = user_data user_exercise._user_exercise_graph = user_exercise_graph user_exercise.summative = exercise.summative # Temporarily work around in-app memory caching bug exercise.user_exercise = None problem_number = self.request_int('problem_number', default=(user_exercise.total_done + 1)) user_data_student = self.request_student_user_data(legacy=True) or user_data if user_data_student.key_email != user_data.key_email and not user_data_student.is_visible_to(user_data): user_data_student = user_data viewing_other = user_data_student.key_email != user_data.key_email # Can't view your own problems ahead of schedule if not viewing_other and problem_number > user_exercise.total_done + 1: problem_number = user_exercise.total_done + 1 # When viewing another student's problem or a problem out-of-order, show read-only view read_only = viewing_other or problem_number != (user_exercise.total_done + 1) exercise_template_html = exercise_template() exercise_body_html, exercise_inline_script, exercise_inline_style, data_require, sha1 = exercise_contents(exercise) user_exercise.exercise_model.sha1 = sha1 user_exercise.exercise_model.related_videos = map(lambda exercise_video: exercise_video.video, user_exercise.exercise_model.related_videos_fetch()) for video in user_exercise.exercise_model.related_videos: video.id = video.key().id() renderable = True if read_only: # Override current problem number and user being inspected # so proper exercise content will be generated user_exercise.total_done = problem_number - 1 user_exercise.user = user_data_student.user user_exercise.read_only = True if not self.request_bool("renderable", True): # We cannot render old problems that were created in the v1 exercise framework. renderable = False query = models.ProblemLog.all() query.filter("user = "******"exercise = ", exid) # adding this ordering to ensure that query is served by an existing index. # could be ok if we remove this query.order('time_done') problem_logs = query.fetch(500) problem_log = None for p in problem_logs: if p.problem_number == problem_number: problem_log = p break user_activity = [] previous_time = 0 if not problem_log or not hasattr(problem_log, "hint_after_attempt_list"): renderable = False else: # Don't include incomplete information problem_log.hint_after_attempt_list = filter(lambda x: x != -1, problem_log.hint_after_attempt_list) while len(problem_log.hint_after_attempt_list) and problem_log.hint_after_attempt_list[0] == 0: user_activity.append([ "hint-activity", "0", max(0, problem_log.hint_time_taken_list[0] - previous_time) ]) previous_time = problem_log.hint_time_taken_list[0] problem_log.hint_after_attempt_list.pop(0) problem_log.hint_time_taken_list.pop(0) # For each attempt, add it to the list and then add any hints # that came after it for i in range(0, len(problem_log.attempts)): user_activity.append([ "correct-activity" if problem_log.correct else "incorrect-activity", unicode(problem_log.attempts[i] if problem_log.attempts[i] else 0), max(0, problem_log.time_taken_attempts[i] - previous_time) ]) previous_time = 0 # Here i is 0-indexed but problems are numbered starting at 1 while (len(problem_log.hint_after_attempt_list) and problem_log.hint_after_attempt_list[0] == i + 1): user_activity.append([ "hint-activity", "0", max(0, problem_log.hint_time_taken_list[0] - previous_time) ]) previous_time = problem_log.hint_time_taken_list[0] # easiest to just pop these instead of maintaining # another index into this list problem_log.hint_after_attempt_list.pop(0) problem_log.hint_time_taken_list.pop(0) user_exercise.user_activity = user_activity if problem_log.count_hints is not None: user_exercise.count_hints = problem_log.count_hints user_exercise.current = problem_log.sha1 == sha1 is_webos = self.is_webos() browser_disabled = is_webos or self.is_older_ie() renderable = renderable and not browser_disabled url_pattern = "/exercise/%s?student_email=%s&problem_number=%d" user_exercise.previous_problem_url = url_pattern % \ (exid, user_data_student.key_email, problem_number - 1) user_exercise.next_problem_url = url_pattern % \ (exid, user_data_student.key_email, problem_number + 1) user_exercise_json = jsonify.jsonify(user_exercise) template_values = { 'exercise': exercise, 'user_exercise_json': user_exercise_json, 'exercise_body_html': exercise_body_html, 'exercise_template_html': exercise_template_html, 'exercise_inline_script': exercise_inline_script, 'exercise_inline_style': exercise_inline_style, 'data_require': data_require, 'read_only': read_only, 'selected_nav_link': 'practice', 'browser_disabled': browser_disabled, 'is_webos': is_webos, 'renderable': renderable, 'issue_labels': ('Component-Code,Exercise-%s,Problem-%s' % (exid, problem_number)), 'alternate_hints_treatment': ab_test('Hints or Show Solution Dec 10', ViewExercise._hints_ab_test_alternatives, ViewExercise._hints_conversion_names, ViewExercise._hints_conversion_types, 'Hints or Show Solution Nov 5'), 'reviews_left_count': reviews_left_count if review_mode else "null", 'include_errorception': gandalf("errorception"), } self.render_jinja2_template("exercise_template.html", template_values)
def get(self): self.render_jinja2_template('about/about_the_site.html', { "selected_id": "the-site", "approx_vid_count": Video.approx_count(), "gandalf_production_test": gandalf("production_test"), })
def add_global_template_values(self, template_values): template_values['App'] = App template_values['None'] = None if not template_values.has_key('user_data'): user_data = user_models.UserData.current() template_values['user_data'] = user_data user_data = template_values['user_data'] template_values['username'] = user_data.nickname if user_data else "" template_values['viewer_profile_root'] = user_data.profile_root if user_data else "/profile/nouser/" template_values['points'] = user_data.points if user_data else 0 template_values['logged_in'] = not user_data.is_phantom if user_data else False template_values['http_host'] = os.environ["HTTP_HOST"] # Always insert a post-login request before our continue url template_values['continue'] = util.create_post_login_url(template_values.get('continue') or self.request.uri) template_values['login_url'] = ('%s&direct=1' % util.create_login_url(template_values['continue'])) template_values['logout_url'] = util.create_logout_url(self.request.uri) template_values['is_mobile'] = False template_values['is_mobile_capable'] = False template_values['is_ipad'] = False if self.is_mobile_capable(): template_values['is_mobile_capable'] = True template_values['is_ipad'] = self.is_ipad() if 'is_mobile_allowed' in template_values and template_values['is_mobile_allowed']: template_values['is_mobile'] = self.is_mobile() # overridable hide_analytics querystring that defaults to true in dev # mode but false for prod. hide_analytics = self.request_bool("hide_analytics", App.is_dev_server) template_values['hide_analytics'] = hide_analytics # client-side error logging template_values['include_errorception'] = gandalf('errorception') # Analytics template_values['mixpanel_enabled'] = gandalf('mixpanel_enabled') if False: # Enable for testing only template_values['mixpanel_test'] = "70acc4fce4511b89477ac005639cfee1" template_values['mixpanel_enabled'] = True template_values['hide_analytics'] = False if template_values['mixpanel_enabled']: template_values['mixpanel_id'] = gae_bingo.identity.identity() if not template_values['hide_analytics']: superprops_list = user_models.UserData.get_analytics_properties(user_data) # Create a superprops dict for MixPanel with a version number # Bump the version number if changes are made to the client-side analytics # code and we want to be able to filter by version. template_values['mixpanel_superprops'] = dict(superprops_list) # Copy over first 4 per-user properties for GA (5th is reserved for Bingo) template_values['ga_custom_vars'] = superprops_list[0:4] if user_data: user_goals = goals.models.GoalList.get_current_goals(user_data) goals_data = [g.get_visible_data() for g in user_goals] if goals_data: template_values['global_goals'] = jsonify(goals_data) # Disable topic browser in the header on mobile devices template_values['watch_topic_browser_enabled'] = not self.is_mobile_capable() template_values['show_topic_pages'] = True return template_values
def add_global_template_values(self, template_values): template_values['App'] = App template_values['None'] = None if not template_values.has_key('user_data'): user_data = user_models.UserData.current() template_values['user_data'] = user_data user_data = template_values['user_data'] template_values['username'] = user_data.nickname if user_data else "" template_values['viewer_profile_root'] = user_data.profile_root if user_data else "/profile/nouser/" template_values['points'] = user_data.points if user_data else 0 template_values['logged_in'] = not user_data.is_phantom if user_data else False template_values['http_host'] = os.environ["HTTP_HOST"] # Always insert a post-login request before our continue url template_values['continue'] = util.create_post_login_url(template_values.get('continue') or self.request.uri) template_values['login_url'] = ('%s&direct=1' % util.create_login_url(template_values['continue'])) template_values['logout_url'] = util.create_logout_url(self.request.uri) template_values['is_mobile'] = False template_values['is_mobile_capable'] = False template_values['is_ipad'] = False if self.is_mobile_capable(): template_values['is_mobile_capable'] = True template_values['is_ipad'] = self.is_ipad() if 'is_mobile_allowed' in template_values and template_values['is_mobile_allowed']: template_values['is_mobile'] = self.is_mobile() # overridable hide_analytics querystring that defaults to true in dev # mode but false for prod. hide_analytics = self.request_bool("hide_analytics", App.is_dev_server) template_values['hide_analytics'] = hide_analytics # client-side error logging template_values['include_errorception'] = gandalf('errorception') # Analytics template_values['mixpanel_enabled'] = gandalf('mixpanel_enabled') if False: # Enable for testing only template_values['mixpanel_test'] = "70acc4fce4511b89477ac005639cfee1" template_values['mixpanel_enabled'] = True template_values['hide_analytics'] = False if template_values['mixpanel_enabled']: template_values['mixpanel_id'] = gae_bingo.identity.identity() if not template_values['hide_analytics']: superprops_list = user_models.UserData.get_analytics_properties(user_data) # Create a superprops dict for MixPanel with a version number # Bump the version number if changes are made to the client-side analytics # code and we want to be able to filter by version. template_values['mixpanel_superprops'] = dict(superprops_list) # Copy over first 4 per-user properties for GA (5th is reserved for Bingo) template_values['ga_custom_vars'] = superprops_list[0:4] if user_data: user_goals = goals.models.GoalList.get_current_goals(user_data) goals_data = [g.get_visible_data() for g in user_goals] if goals_data: template_values['global_goals'] = jsonify(goals_data) # Disable topic browser in the header on mobile devices template_values['watch_topic_browser_enabled'] = not self.is_mobile_capable() # Begin topic pages A/B test if template_values['mixpanel_enabled']: show_topic_pages = ab_test("Show topic pages", ["show", "hide"], ["topic_pages_view_page", "topic_pages_started_video", "topic_pages_completed_video"]) analytics_bingo = {"name": "Bingo: Topic pages", "value": show_topic_pages} template_values['analytics_bingo'] = analytics_bingo else: show_topic_pages = "hide" template_values['show_topic_pages'] = (show_topic_pages == "show") # End topic pages A/B test return template_values
def can_cross_empty_bridge(self): bridge_name = "balrog" GandalfBridge.get_or_insert(bridge_name) return gandalf(bridge_name)
def get(self, exid=None): # TODO(david): Is there some webapp2 magic that will allow me not to # repeat this URL string in main.py? review_mode = self.request.path == "/review" and (ab_test( 'Review Mode UI', conversion_name=ViewExercise._review_conversion_names, conversion_type=ViewExercise._review_conversion_types)) if not exid and not review_mode: self.redirect("/exercise/%s" % self.request_string("exid", default="addition_1")) return user_data = models.UserData.current() or models.UserData.pre_phantom() user_exercise_graph = models.UserExerciseGraph.get(user_data) if review_mode: # Take the first review exercise if available exid = (user_exercise_graph.review_exercise_names() or user_exercise_graph.proficient_exercise_names() or ["addition_1"])[0] reviews_left_count = user_exercise_graph.reviews_left_count() exercise = models.Exercise.get_by_name(exid) if not exercise: raise MissingExerciseException("Missing exercise w/ exid '%s'" % exid) user_exercise = user_data.get_or_insert_exercise(exercise) # Cache these so we don't have to worry about future lookups user_exercise.exercise_model = exercise user_exercise._user_data = user_data user_exercise._user_exercise_graph = user_exercise_graph user_exercise.summative = exercise.summative # Temporarily work around in-app memory caching bug exercise.user_exercise = None problem_number = self.request_int('problem_number', default=(user_exercise.total_done + 1)) user_data_student = self.request_student_user_data( legacy=True) or user_data if user_data_student.key_email != user_data.key_email and not user_data_student.is_visible_to( user_data): user_data_student = user_data viewing_other = user_data_student.key_email != user_data.key_email # Can't view your own problems ahead of schedule if not viewing_other and problem_number > user_exercise.total_done + 1: problem_number = user_exercise.total_done + 1 # When viewing another student's problem or a problem out-of-order, show read-only view read_only = viewing_other or problem_number != ( user_exercise.total_done + 1) # [Multilingual] ML_language = ( ':' in exid) and exid.split(':')[0] or 'en' # Default to english ML_exercise = (':' in exid) and exid.split(':')[1] or exid exercise_template_html = exercise_template(ML_language) exercise_template_html = exercise_template_html.decode('utf-8') exercise_body_html, exercise_inline_script, exercise_inline_style, data_require, sha1 = exercise_contents( ML_exercise, ML_language) user_exercise.exercise_model.sha1 = sha1 user_exercise.exercise_model.related_videos = map( lambda exercise_video: exercise_video.video, user_exercise.exercise_model.related_videos_fetch()) for video in user_exercise.exercise_model.related_videos: video.id = video.key().id() renderable = True if read_only: # Override current problem number and user being inspected # so proper exercise content will be generated user_exercise.total_done = problem_number - 1 user_exercise.user = user_data_student.user user_exercise.read_only = True if not self.request_bool("renderable", True): # We cannot render old problems that were created in the v1 exercise framework. renderable = False query = models.ProblemLog.all() query.filter("user = "******"exercise = ", exid) # adding this ordering to ensure that query is served by an existing index. # could be ok if we remove this query.order('time_done') problem_logs = query.fetch(500) problem_log = None for p in problem_logs: if p.problem_number == problem_number: problem_log = p break user_activity = [] previous_time = 0 if not problem_log or not hasattr(problem_log, "hint_after_attempt_list"): renderable = False else: # Don't include incomplete information problem_log.hint_after_attempt_list = filter( lambda x: x != -1, problem_log.hint_after_attempt_list) while len(problem_log.hint_after_attempt_list ) and problem_log.hint_after_attempt_list[0] == 0: user_activity.append([ "hint-activity", "0", max( 0, problem_log.hint_time_taken_list[0] - previous_time) ]) previous_time = problem_log.hint_time_taken_list[0] problem_log.hint_after_attempt_list.pop(0) problem_log.hint_time_taken_list.pop(0) # For each attempt, add it to the list and then add any hints # that came after it for i in range(0, len(problem_log.attempts)): user_activity.append([ "correct-activity" if problem_log.correct else "incorrect-activity", unicode(problem_log.attempts[i] if problem_log. attempts[i] else 0), max(0, problem_log.time_taken_attempts[i] - previous_time) ]) previous_time = 0 # Here i is 0-indexed but problems are numbered starting at 1 while (len(problem_log.hint_after_attempt_list) and problem_log.hint_after_attempt_list[0] == i + 1): user_activity.append([ "hint-activity", "0", max( 0, problem_log.hint_time_taken_list[0] - previous_time) ]) previous_time = problem_log.hint_time_taken_list[0] # easiest to just pop these instead of maintaining # another index into this list problem_log.hint_after_attempt_list.pop(0) problem_log.hint_time_taken_list.pop(0) user_exercise.user_activity = user_activity if problem_log.count_hints is not None: user_exercise.count_hints = problem_log.count_hints user_exercise.current = problem_log.sha1 == sha1 is_webos = self.is_webos() browser_disabled = is_webos or self.is_older_ie() renderable = renderable and not browser_disabled url_pattern = "/exercise/%s?student_email=%s&problem_number=%d" user_exercise.previous_problem_url = url_pattern % \ (exid, user_data_student.key_email, problem_number - 1) user_exercise.next_problem_url = url_pattern % \ (exid, user_data_student.key_email, problem_number + 1) user_exercise_json = jsonify.jsonify(user_exercise) template_values = { 'exercise': exercise, 'user_exercise_json': user_exercise_json, 'exercise_body_html': exercise_body_html, 'exercise_template_html': exercise_template_html, 'exercise_inline_script': exercise_inline_script, 'exercise_inline_style': exercise_inline_style, 'data_require': data_require, 'read_only': read_only, 'selected_nav_link': 'practice', 'browser_disabled': browser_disabled, 'is_webos': is_webos, 'renderable': renderable, 'issue_labels': ('Component-Code,Exercise-%s,Problem-%s' % (exid, problem_number)), 'alternate_hints_treatment': ab_test('Hints or Show Solution Dec 10', ViewExercise._hints_ab_test_alternatives, ViewExercise._hints_conversion_names, ViewExercise._hints_conversion_types, 'Hints or Show Solution Nov 5'), 'reviews_left_count': reviews_left_count if review_mode else "null", 'include_errorception': gandalf("errorception"), } self.render_jinja2_template("exercise_template.html", template_values)