def recommends(cls, request): tracks = [] pa = ParameterAdapter() limit = 10 # todo:get limit by parameter response = [] # get request parameters request_body = None if request.method == "GET": request_body = list(request.GET.dict().keys())[0] else: request_body = request.body.decode("utf-8") posted = json.loads(request_body) posted_parameters = {} if not "parameters" in posted else posted["parameters"] # process by methods if request.method == "GET": # initialize when get SessionManager.set_session(request, SessionManager.CRITICIZE_SESSION, []) SessionManager.set_session(request, SessionManager.TRACK_SESSION, []) parameters = pa.request_to_parameters(TrackCriticizeType.Parameter, None, posted_parameters) tracks = cls.get_scored_tracks(parameters, None, []) else: track_id = posted["track_id"] criticize_type = TrackCriticizeType(posted["criticize_type"]) track = cls.__get_track(track_id, tracks) tracks = cls.__get_session_tracks(request) # get from session parameters = pa.request_to_parameters(criticize_type, track, posted_parameters) history = cls.__get_session_history(request) # merge history and make parameter parameters = ParameterAdapter.merge_parameters(history + [parameters]) if criticize_type == TrackCriticizeType.Like: tracks = cls.get_favorite_tracks(parameters, track, tracks) else: tracks = cls.get_scored_tracks(parameters, track, tracks) if len(tracks) > 0: # to dictionary serialized_evaluated = [{"score": s.score, "item": s.item.to_dict(), "score_detail": s.score_detail} for s in tracks] # store to session SessionManager.set_session(request, SessionManager.TRACK_SESSION, [s["item"] for s in serialized_evaluated]) SessionManager.add_session(request, SessionManager.CRITICIZE_SESSION, [p.to_dict() for p in parameters]) if limit > 0: serialized_evaluated = serialized_evaluated[:limit] response = serialized_evaluated return HttpResponse(json.dumps(response), content_type="application/json")
def test_criticize_by_parameter(self): pa = ParameterAdapter() selected_track = random.sample(self.tracks, 1)[0] # by parameter criticize_type = TrackCriticizeType.Parameter post_parameters = {"bpm": "123"} # dummy bpm value parameters = pa.request_to_parameters(criticize_type, selected_track, post_parameters) print(map(lambda p: p.__str__(), parameters)) scored = RecommendApi.get_scored_tracks(parameters, selected_track, self.tracks) print("tracks: {0}".format(len(scored))) self.print_tracks(map(lambda s: s.item, scored[:10]))
def test_criticize_by_pattern(self): pa = ParameterAdapter() selected_track = random.sample(self.tracks, 1)[0] # by parameter criticize_type = TrackCriticizeType.Pattern evaluator = Track.make_evaluator() criticize_patterns = evaluator.make_pattern(self.tracks, selected_track) pattern = random.sample(criticize_patterns, 1)[0] post_parameters = {"pattern": pattern.pattern} parameters = pa.request_to_parameters(criticize_type, selected_track, post_parameters) print(map(lambda p: p.__str__(), parameters)) scored = RecommendApi.get_scored_tracks(parameters, selected_track, self.tracks) print("tracks: {0}".format(len(scored))) self.print_tracks(map(lambda s: s.item, scored[:10]))
def get_scored_tracks(cls, parameters, track, initial_tracks): tracks = [] trial_count = 0 finder = Track() base_track = track pa = ParameterAdapter() conditions = pa.parameters_to_conditions(parameters) while trial_count < RecommendApi.TRACK_TRIAL_LIMIT and len(tracks) <= RecommendApi.TRACK_COUNT_BASE: try: # get tracks by criticizes if len(tracks) > 0: conditions["offset"] = len(tracks) if trial_count == 0: tracks += initial_tracks new_tracks = finder.find(conditions) tracks += list(filter(lambda t: t.id not in [t.id for t in tracks], new_tracks)) # filter by inputed parameters if track: tracks = list(filter(lambda t: pa.filter_by_parameters(parameters, track, t), tracks)) except HTTPError as ex: pass trial_count += 1 sleep(0.5) scored = tracks if len(tracks) > 0: if track is None: base_track = tracks[0] evaluator = Track.make_evaluator(TrackCriticizePattern) scored = evaluator.calc_score(tracks, base_track) scored = scored[:RecommendApi.TRACK_COUNT_BASE] return scored
def get_favorite_tracks(cls, parameters, track, initial_tracks): if track is None: Exception("If getting favorite, you have to set track parameter") tracks = [] favoriters = [] trial_count = 0 pa = ParameterAdapter() user_evaluator = User.make_evaluator() while trial_count < RecommendApi.TRACK_TRIAL_LIMIT and len(tracks) <= RecommendApi.TRACK_COUNT_BASE: try: # get tracks by criticizes if trial_count == 0: favoriters = track.get_favoriters() if len(favoriters) > 0: favoriters = user_evaluator.calc_score(favoriters, favoriters[0]) else: break if len(favoriters) > trial_count: new_tracks = favoriters[trial_count].item.get_favorites() tracks += list(filter(lambda t: t.id not in [t.id for t in tracks], new_tracks)) tracks = list(filter(lambda t: pa.filter_by_parameters(parameters, track, t), tracks)) except HTTPError as ex: pass trial_count += 1 sleep(0.5) scored = [] if len(tracks) > 0: evaluator = Track.make_evaluator(TrackCriticizePattern) scored = evaluator.calc_score(tracks, track) else: scored = cls.get_scored_tracks(parameters, track, tracks) scored = scored[:RecommendApi.TRACK_COUNT_BASE] return scored