def request_to_parameters(self, criticize_type, track, request_parameters): if criticize_type != TrackCriticizeType.Parameter and not track: raise Exception("Target track is None") parameters = [] if criticize_type == TrackCriticizeType.Parameter: if "bpm" in request_parameters: parameters.append(Parameter("bpm", request_parameters["bpm"])) elif criticize_type == TrackCriticizeType.Pattern: criticize = CriticizePattern(pattern=request_parameters["pattern"]) direction = criticize.get_direction() parameters.append(Parameter("pattern", criticize.pattern)) for c in criticize.get_targets(): parameters.append(Parameter(c.name, vector_utils.to_value(getattr(track, c.name)), direction)) elif criticize_type == TrackCriticizeType.Like: for c in self.__get_criticizables(): parameters.append(Parameter(c, vector_utils.to_value(getattr(track, c)))) if "q" in request_parameters and request_parameters["q"]: parameters.append(Parameter("q", request_parameters["q"])) if Parameter.first_or_default("genre", parameters) and not Parameter.first_or_default("genre_score", parameters): genre = Parameter.first_or_default("genre", parameters) if Track.genre_to_score(genre): g_score = Track.genre_to_score(genre) parameters.append(Parameter("genre_score", g_score)) return parameters
def __get_track(cls, track_id, tracks): if not track_id: Exception("Track id is not defined") track = None track = next(iter(filter(lambda t: t.id == track_id, tracks)), None) if track is None: track = Track.find_by_id(track_id) return track
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_default_conditions(cls): default_condition = {} base_date = datetime.now() - timedelta(days=730) default_condition["created_at"] = {"from": base_date.strftime("%Y-%m-%d %H:%M:%S")} random_score = random.uniform(-1, 1) random_genres = Track.score_to_genres(random_score, 1) default_condition["genres"] = ",".join(random_genres) default_condition["filter"] = "streamable" return default_condition
def parameters_to_conditions(self, parameters): default_condition = self.get_default_conditions() c_dict = {} is_condition_set = False for key in self.__get_conditionables(): p = Parameter.first_or_default(key, parameters) if p is not None and p.value is not None: is_condition_set = True if key == "bpm": value = int(p.value) if p.direction == CriticizeDirection.Up: c_dict[key] = {"from": self.adjust_parameter(key, value, True)} elif p.direction == CriticizeDirection.Down: c_dict[key] = {"to": self.adjust_parameter(key, value, False)} else: c_dict[key] = {"from": self.adjust_parameter(key, value, False), "to": self.adjust_parameter(key, value, True)} elif key == "genre_score": if p.direction == CriticizeDirection.Around: c_dict[key] = p.value else: c_dict[key] = self.adjust_parameter(key, p.value, p.direction == CriticizeDirection.Up) elif key == "created_at": value = self.adjust_parameter(key, p.value, p.direction == CriticizeDirection.Up) c_dict[key] = {"from": value.strftime("%Y-%m-%d %H:%M:%S")} else: c_dict[key] = p.value if "genre_score" in c_dict: genre = Track.score_to_genre(c_dict["genre_score"]) c_dict["genres"] = genre c_dict.pop("genre_score") elif "genre" in c_dict: c_dict["genres"] = c_dict["genre"] if "genre" in c_dict: c_dict.pop("genre") if is_condition_set: c_dict["filter"] = default_condition["filter"] else: c_dict = default_condition return c_dict
def get_criticize_pattern(cls, request): if request.method == "POST": posted = json.loads(request.body.decode("utf-8")) track_id = posted["track_id"] tracks = cls.__get_session_tracks(request) track = cls.__get_track(track_id, tracks) evaluator = Track.make_evaluator() criticize_patterns = evaluator.make_pattern(tracks, track) questions = TrackCriticizePattern.patterns_to_questions(criticize_patterns, track, tracks) serialized_question = json.dumps(questions) return HttpResponse(serialized_question, content_type="application/json") else: raise Exception("You have to use POST method when access the get_criticize_pattern.")
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_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