<s> """<STR_LIT>""" <EOL> import ast <EOL> from core import jobs <EOL> from core . domain import exp_services <EOL> from core . domain import recommendations_services <EOL> from core . domain import rights_manager <EOL> from core . platform import models <EOL> ( exp_models , recommendations_models , ) = models . Registry . import_models ( [ <EOL> models . NAMES . exploration , models . NAMES . recommendations ] ) <EOL> MAX_RECOMMENDATIONS = <NUM_LIT:10> <EOL> SIMILARITY_SCORE_THRESHOLD = <NUM_LIT> <EOL> class ExplorationRecommendationsRealtimeModel ( <EOL> jobs . BaseRealtimeDatastoreClassForContinuousComputations ) : <EOL> pass <EOL> class ExplorationRecommendationsAggregator ( <EOL> jobs . BaseContinuousComputationManager ) : <EOL> """<STR_LIT>""" <EOL> @ classmethod <EOL> def get_event_types_listened_to ( cls ) : <EOL> return [ ] <EOL> @ classmethod <EOL> def _get_realtime_datastore_class ( cls ) : <EOL> return ExplorationRecommendationsRealtimeModel <EOL> @ classmethod <EOL> def _get_batch_job_manager_class ( cls ) : <EOL> return ExplorationRecommendationsMRJobManager <EOL> @ classmethod <EOL> def _handle_incoming_event ( cls , active_realtime_layer , event_type , * args ) : <EOL> pass <EOL> class ExplorationRecommendationsMRJobManager ( <EOL> jobs . BaseMapReduceJobManagerForContinuousComputations ) : <EOL> """<STR_LIT>""" <EOL> @ classmethod <EOL> def _get_continuous_computation_class ( cls ) : <EOL> return ExplorationRecommendationsAggregator <EOL> @ classmethod <EOL> def entity_classes_to_map_over ( cls ) : <EOL> return [ exp_models . ExpSummaryModel ] <EOL> @ staticmethod <EOL> def map ( item ) : <EOL> if item . status == rights_manager . ACTIVITY_STATUS_PRIVATE : <EOL> return <EOL> exp_summary_id = item . id <EOL> exp_summaries_dict = ( <EOL> exp_services . get_non_private_exploration_summaries ( ) ) <EOL> if exp_summary_id not in exp_summaries_dict : <EOL> return <EOL> reference_exp_summary = exp_summaries_dict [ exp_summary_id ] <EOL> exp_summaries_items = exp_summaries_dict . iteritems ( ) <EOL> for compared_exp_id , compared_exp_summary in exp_summaries_items : <EOL> if compared_exp_id != exp_summary_id : <EOL> similarity_score = ( <EOL> recommendations_services . get_item_similarity ( <EOL> reference_exp_summary . category , <EOL> reference_exp_summary . language_code , <EOL> reference_exp_summary . owner_ids , <EOL> compared_exp_summary . category , <EOL> compared_exp_summary . language_code , <EOL> compared_exp_summary . exploration_model_last_updated , <EOL> compared_exp_summary . owner_ids , <EOL> compared_exp_summary . status ) ) <EOL> if similarity_score >= SIMILARITY_SCORE_THRESHOLD : <EOL> yield ( exp_summary_id , { <EOL> '<STR_LIT>' : similarity_score , <EOL> '<STR_LIT>' : compared_exp_id <EOL> } ) <EOL> @ staticmethod <EOL> def reduce ( key , stringified_values ) : <EOL> other_exploration_similarities = sorted ( <EOL> [ ast . literal_eval ( v ) for v in stringified_values ] , <EOL> reverse = True , <EOL> key = lambda x : x [ '<STR_LIT>' ] ) <EOL> recommended_exploration_ids = [ <EOL> item [ '<STR_LIT>' ] <EOL> for item in other_exploration_similarities [ : MAX_RECOMMENDATIONS ] ] <EOL> recommendations_services . set_recommendations ( <EOL> key , recommended_exploration_ids ) </s>
