def register(self, args): # TBD: we record UNKNOWN for testing only. # In deployment we should ignore registering requests from UNKNOWN # (and not even send them from the page) try: user_id = context.c.user.user_id if context.c.user else "UNKNOWN" except: user_id = "UNKNOWN" pass if args["response_type"] == ResponseOperation.toStr(ResponseOperation.SUBMIT) or \ args["response_type"] == ResponseOperation.toStr(ResponseOperation.SKIP): # Record answer to the database correct = 0 incorrect = 0 questions = "" if "q_id" in args.keys() and "now" in args.keys(): if "l_id" not in args.keys( ) or not args["l_id"] or args["l_id"] is None: l_id = "" else: l_id = args["l_id"] if "language" not in args.keys( ) or not args["language"] or args["language"] is None: language = "" else: language = args["language"] # for key, v in args.items(): # value = v # if key[0:5] == "q_res": # questions = questions + key + "=" + value + "," # if value == "true": # correct = correct + 1 # else: # incorrect = incorrect + 1 questions = "" if 'detailed' in args.keys(): for k, v in args['detailed'].items(): if v == "true": correct = correct + 1 else: incorrect = incorrect + 1 questions = str(args['detailed']) values = "" if 'values' in args.keys(): values = str(args['values']) shown_solution = False if "shown_solutions" in args.keys() and type( args["shown_solutions"]) == bool: shown_solution = args["shown_solutions"] hist = context.c.session.get("history") if (len(hist) > 0 and (hist[-1]["correct"] == 0 or correct > hist[-1]["correct"])) and not shown_solution: hist[-1]["correct"] = correct hist[-1]["incorrect"] = incorrect context.c.session.set("history", hist) # We register temporary stats for anonymous users that are stored with the cookie if (user_id == "UNKNOWN" or user_id == "local:UNKNOWN") and \ context.c.session.get("last_q_year") and context.c.session.get("last_q_theme") and \ context.c.session.get("last_q_subtheme") and context.c.session.get("difficulty"): year = context.c.session.get("last_q_year") theme = context.c.session.get("last_q_theme") subtheme = context.c.session.get("last_q_subtheme") difficulty = context.c.session.get("difficulty") anon_stats = context.c.session.get("anon_stats") if not anon_stats: anon_stats = {} context.c.session.set("anon_stats", anon_stats) add_anon_stats(self, anon_stats, args["q_id"], \ PageLanguage.fromStr(language), \ year, theme, subtheme, difficulty, correct, incorrect) response = { "user_id": user_id, "question_id": args["q_id"], "list_id": l_id, "year": context.c.session.get("last_q_year") if context.c.session.get("last_q_year") else "", "theme": context.c.session.get("last_q_theme") if context.c.session.get("last_q_theme") else "", "subtheme": context.c.session.get("last_q_subtheme") if context.c.session.get("last_q_subtheme") else "", "topic": context.c.session.get("last_q_topic") if context.c.session.get("last_q_topic") else "", "period": context.c.session.get("period") if context.c.session.get("period") else "", "difficulty": context.c.session.get("difficulty") if context.c.session.get("difficulty") else "", "language": language, "test_id": args["test_id"], "test_order": args["test_order"], "response_type": args["response_type"], "attempt": args["attempt"], "shown_solutions": args["shown_solutions"], "time": args["start"], "duration": int(args["now"]) - int(args["start"]), "correct": correct, "incorrect": incorrect, "questions": questions, "values": values } # logging.debug("Register results: user_id={}, q_id={}, l_id={}, lang={}, response_type={}, " + # "attempt={}, start={}, duration={}, correct={}, incorrect={}, questions=\"{}\"".format( # str(user_id), str(args["q_id"]), str(l_id), # str(language), str(args["response_type"]), str(args["attempt"]), # str(args["start"]), str(int(args["now"]) - int(args["start"])), # str(correct), str(incorrect), str(questions))) try: self.app_data.storage.record_response(response) except Exception as err: logging.error( "Error submitting record response: {}\n{}".format( err, helpers.get_stack_trace())) # Also register responses to LogAnalytics for better visibility log_json = { "user": user_id, "q_id": args["q_id"], "l_id": l_id, "year": context.c.session.get("last_q_year") if context.c.session.get("last_q_year") else "", "theme": context.c.session.get("last_q_theme") if context.c.session.get("last_q_theme") else "", "subtheme": context.c.session.get("last_q_subtheme") if context.c.session.get("last_q_subtheme") else "", "topic": context.c.session.get("last_q_topic") if context.c.session.get("last_q_topic") else "", "period": context.c.session.get("period") if context.c.session.get("period") else "", "difficulty": context.c.session.get("difficulty") if context.c.session.get("difficulty") else "", "language": language, "response_type": args["response_type"], "attempt": args["attempt"], "shown_solutions": args["shown_solutions"], "time": args["start"], "duration": int(args["now"]) - int(args["start"]), "correct": correct, "incorrect": incorrect } self.app_data.log_json("Register", log_json) else: logging.error( "Register operation with incomplete parameters: {}\n{}". format(args, helpers.get_stack_trace())) else: # This is often hit by crawlers, so ignore logging.debug("Unknown register operation: {}".format( args["response_type"])) return "ABC"
def main(self, req, headers, timers, args): logging.debug("\n\nMAIN ARGS: {}\n\n".format(args)) if headers is None or req is None: # Cherrypy - ignore cookies # Special ops to register a user reported error # DEBUG: This is only for testing and may not implement the full feedback functionality if "op" in args.keys() and args["op"] == PageOperation.toStr( PageOperation.FEEDBACK): return self.feedback(args) self.page_params.parse(args, legacy=True) return Design.main(self) # No caching headers.set_no_store() if args["root"] == "edit": # Old style EDIT page with parameter passing in GET URL # DEBUG: these two special ops are for testing and are not fully functional in edit mode # Special ops to register results if "op" in args.keys() and args["op"] == PageOperation.toStr( PageOperation.REGISTER): return self.register(args) # Special ops to register a user reported error elif "op" in args.keys() and args["op"] == PageOperation.toStr( PageOperation.FEEDBACK): return self.feedback(args) self.page_params.parse_edit(in_args=args) # self.page_params.print_params() return Design.main(self) with context.new_context(req, headers): context.c.timers = timers with self.sessiondb.init_session(req, headers) as session: context.c.session = session context.c.user = self.userdb.get_user(session.user_id()) # Debug if False: session.print() # Special ops to register results if "op" in args.keys() and args["op"] == PageOperation.toStr( PageOperation.REGISTER): return self.register(args) # Special ops to register a user reported error elif "op" in args.keys() and args["op"] == PageOperation.toStr( PageOperation.FEEDBACK): return self.feedback(args) else: self.page_params.set_url(req.get_url()) # DEBUG (log.debug level required for the below to work) # print("\n\nPRE PARSING:\n") # #print("\n\nARGS: \n{}\n".format(json.dumps(args, indent=2))) # print("\n\nARGS: \n{}\n".format(args)) # session.print() # # Parameters stored in a session, # # only updates passed in URL self.page_params.parse(in_args=args, session=session) if self.page_params.get_param("language"): #print("\n\n**** DIRECT: ", self.page_params.get_param("language")) self.userdb.update_selected_language( self.page_params.get_param("language").value) elif context.c.user and context.c.user.selected_language: self.page_params.set_param( "language", PageLanguage.fromStr( context.c.user.selected_language)) #print("\n\n**** FROM DB: ", self.page_params.get_param("language")) else: self.page_params.set_param( "language", PageLanguage.get_default(req.get_preferred_lang())) #print("\n\n**** DEFAULT: ", self.page_params.get_param("language")) # DEBUG (log.debug level required for the below to work) # print("\n\nPOST PARSING:\n") # self.page_params.print_params() # session.print() logging.debug("=== New /main request, op = {}".format( self.page_params.get_param('op'))) if False: self.page_params.print_params() logging.info( "\n\n === New request: op={} - " "q_id={}, l_id={}, language={}, " "init_code={}, iter_code={}, text={}.\n\n".format( PageOperation.toStr( self.page_params.get_param("op")), self.page_params.get_param("q_id"), self.page_params.get_param("l_id"), PageLanguage.toStr( self.page_params.get_param("language")), self.page_params.get_param("init_code"), self.page_params.get_param("iter_code"), self.page_params.get_param("text"), )) log_json = {"url": req.get_url()} if context.c.user and context.c.user.user_id: log_json["user"] = context.c.user.user_id if self.page_params.get_param("op"): log_json["op"] = PageOperation.toStr( self.page_params.get_param("op")) if self.page_params.get_param("q_id"): log_json["q_id"] = self.page_params.get_param("q_id") if self.page_params.get_param("l_id"): log_json["l_id"] = self.page_params.get_param("l_id") if self.page_params.get_param("language"): log_json["language"] = PageLanguage.toStr( self.page_params.get_param("language")) if self.page_params.get_param("year"): log_json["year"] = self.page_params.get_param("year") if self.page_params.get_param("theme"): log_json["theme"] = self.page_params.get_param("theme") if self.page_params.get_param("subtheme"): log_json["subtheme"] = self.page_params.get_param( "subtheme") if self.page_params.get_param("topic"): log_json["topic"] = self.page_params.get_param("topic") if context.c.session.get("period"): log_json["period"] = context.c.session.get("period") if context.c.session.get("difficulty"): log_json["difficulty"] = context.c.session.get( "difficulty") if self.page_params.get_param("skipped"): log_json["skipped"] = self.page_params.get_param( "skipped") # HTTP header log_json["accepted_lang"] = req.get_header( 'Accept-Language') log_json["preferred_lang"] = req.get_preferred_lang() log_json["remote_addr"] = req.get_header('Remote-Addr') log_json["user_agent"] = req.get_header('User-Agent') self.app_data.log_json("Access", log_json) with context.c.timers.new_section("design.main"): return Design.main(self)