def add_rating(user, gid): """Take the DJ spot (if it is available).""" group = g.store.get(Group, gid) if group is None: raise helpers.BadRequest(errors.INVALID_GROUP, "group does not exist") try: artist = request.form['artist'] title = request.form['title'] rating = max(1, min(5, int(request.form['rating']))) except KeyError: raise helpers.BadRequest(errors.MISSING_FIELD, "missing artist, title or rating") except ValueError: raise helpers.BadRequest(errors.INVALID_RATING, "rating is invalid") if user.group != group: raise helpers.Unauthorized("you are not in this group") track = g.store.find(Track, (Track.artist == artist) & (Track.title == title)).one() if track is None: raise helpers.BadRequest(errors.INVALID_TRACK, "track not found") # Add a group event. event = GroupEvent(group, user, events.RATING) event.payload = { 'artist': track.artist, 'title': track.title, 'rating': rating, } g.store.add(event) # Add a library entry. set_rating(user, track.artist, track.title, rating) return helpers.success()
def set_master(user, gid): """Take the DJ spot (if it is available).""" group = g.store.get(Group, gid) if group is None: raise helpers.BadRequest(errors.INVALID_GROUP, "group does not exist") try: uid = int(request.form['uid']) except (KeyError, ValueError): raise helpers.BadRequest(errors.MISSING_FIELD, "cannot parse uid") if user.id != uid or user.group != group: raise helpers.Unauthorized("user not self or not in group") if group.master != None and group.master != user: raise helpers.Unauthorized("someone else is already here") group.master = user event = GroupEvent(group, user, events.MASTER, None) g.store.add(event) return helpers.success()
def leave_master(user, gid): """Leave the DJ spot.""" group = g.store.get(Group, gid) if group is None: raise helpers.BadRequest(errors.INVALID_GROUP, "group does not exist") if group.master != None and group.master != user: raise helpers.Unauthorized("you are not the master") group.master = None return helpers.success()
def get_tracks(master, gid): """Get the next tracks.""" group = g.store.get(Group, gid) if group is None: raise helpers.BadRequest(errors.INVALID_GROUP, "group does not exist") if group.master != master: raise helpers.Unauthorized("you are not the DJ") # Get all the tracks in the master's library that haven't been played. played_filter = get_played_filter(group) remaining = filter( played_filter, g.store.find(LibEntry, (LibEntry.user == master) & (LibEntry.is_valid == True) & (LibEntry.is_local == True))) if len(remaining) == 0: raise helpers.NotFound(errors.TRACKS_DEPLETED, 'no more tracks to play') # Partition tracks based on whether we can embed them in the latent space. with_feats = list() points = list() no_feats = list() for entry in remaining: point = predict.get_point(entry.track) if point is not None: with_feats.append(entry) points.append(point) else: no_feats.append(entry) # For the users that can be modelled: predict their ratings. models = filter(lambda model: model.is_nontrivial(), [predict.Model(user) for user in group.users]) if models is not None: ratings = [model.score(points) for model in models] agg = predict.aggregate(ratings) else: # Not a single user can be modelled! just order the songs randomly. agg = range(len(with_feats)) random.shuffle(agg) # Construct the playlist, decreasing order of scores. playlist = [ entry for entry, score in sorted( zip(with_feats, agg), key=itemgetter(1), reverse=True) ] # Randomize songs for which we don't have features. random.shuffle(no_feats) playlist.extend(no_feats) # Craft the JSON response. tracks = list() for entry in playlist[:MAX_TRACKS]: tracks.append({ 'artist': entry.track.artist, 'title': entry.track.title, 'local_id': entry.local_id, }) return jsonify(playlist_id=get_playlist_id(group), tracks=tracks)
def skip_track(user, gid): """Skip the track that is currently being played.""" group = g.store.get(Group, gid) if group is None: raise helpers.BadRequest(errors.INVALID_GROUP, "group does not exist") if group.master != user: raise helpers.Unauthorized("you are not the master") results = g.store.find(GroupEvent, (GroupEvent.event_type == events.PLAY) & (GroupEvent.group == group)) play_event = results.order_by(Desc(GroupEvent.created)).first() if play_event is None: raise helpers.BadRequest(errors.NO_CURRENT_TRACK, "no track to skip") payload = { 'artist': play_event.payload.get('artist'), 'title': play_event.payload.get('title'), 'master': { 'uid': user.id, 'nickname': user.nickname }, } event = GroupEvent(group, user, events.SKIP, payload) g.store.add(event) return helpers.success()
def play_track(user, gid): """Register the track that is currently playing.""" group = g.store.get(Group, gid) if group is None: raise helpers.BadRequest(errors.INVALID_GROUP, "group does not exist") if group.master != user: raise helpers.Unauthorized("you are not the master") try: artist = request.form['artist'] title = request.form['title'] except KeyError: raise helpers.BadRequest(errors.MISSING_FIELD, "missing artist and / or title") track = g.store.find(Track, (Track.artist == artist) & (Track.title == title)).one() if track is None: raise helpers.BadRequest(errors.INVALID_TRACK, "track not found") payload = { 'artist': track.artist, 'title': track.title, 'master': { 'uid': user.id, 'nickname': user.nickname }, } payload['stats'] = list() # TODO Something better than random scores :) for resident in group.users: payload['stats'].append({ 'uid': resident.id, 'nickname': resident.nickname, 'score': int(random.random() * 100), 'predicted': True #if random.random() > 0.2 else False }) event = GroupEvent(group, user, events.PLAY, payload) g.store.add(event) return helpers.success()