public boolean prepNextSong() { mp.reset(); if (currentPlaylist.size() > 0) { currentTrack = currentPlaylist.get(globalTrackNo++); MySongManager.rebuildStats(this, currentTrack.getLocal_id()); try { mp.setDataSource(currentTrack.getPath()); mp.prepare(); } catch (IOException e) { e.printStackTrace(); return false; } int i = Math.max(currentPlaylist.size() - 5, globalTrackNo); if (currentPlaylist.size() - 5 <= globalTrackNo) { // TODO async currentPlaylist.addAll(generateNewTracks(sessionType)); } return true; } else { return false; } }
private void checkIfRegisterAsSkip() { if (currentTrack != null) { long millis = System.currentTimeMillis() - mStartTime; accumulatedPlaytimeForThisTrack += millis; if (accumulatedPlaytimeForThisTrack > currentTrack.getDuration() / 2) { // dun consider as skip, just "next" createTrackStats(currentTrack.getLocal_id(), TrackStats.SONG_HALF_PLAYED); } else { // its a skip, the guy dun like this song1 createTrackStats(currentTrack.getLocal_id(), TrackStats.SONG_SKIPPED); } } }
public void showNotification() { if (currentTrack != null) { mNotificationBuilder = new Notification.Builder(this) .setSmallIcon(android.R.drawable.sym_def_app_icon) .setContentTitle(currentTrack.getTitle()) .setContentText(currentTrack.getArtist()) .setContentIntent(activityIntent) .addAction(android.R.drawable.ic_media_play, "PlayPause", playPausePendingIntent) .addAction(android.R.drawable.ic_media_next, "Next", nextPendingIntent) .addAction(0, "Dismiss", dismissPendingIntent); mNotification = mNotificationBuilder.build(); mNotification.flags = Notification.FLAG_ONGOING_EVENT; mNotificationManager.notify(NOTIFICATION_ID, mNotification); } }
private List<Track> getUnderratedPlaylist(List<Track> tempTrackList) { Log.d(TAG, "getUnderratedPlaylist()"); List<Track> tempList = new ArrayList<Track>(); /** * referring to how many times does a song need to be played/selected before it is not a rookie * TODO XZ: in future, this should be a relative number such as top played song is at 100 * completeCount hence an underrated song would be, say maxCount * 0.4? */ int rookieThreshold = 10; if (!tempTrackList.isEmpty()) { Collections.shuffle(tempTrackList); for (Track t : tempTrackList) { int completedCount = t.getCompletedCount(); int skippedCount = t.getSkippedCount(); int selectedCount = t.getSelectedCount(); int likedCount = t.getLikedCount(); int dislikedCount = t.getDislikedCount(); if (completedCount + selectedCount < rookieThreshold) { if (selectedCount > 2) { if (skippedCount <= completedCount) { tempList.add(t); } } else { if (completedCount > 2) { tempList.add(t); } else { if (likedCount > dislikedCount) { tempList.add(t); } } } } if (tempList.size() == 10) { break; } } } Log.d(TAG, "tempList.size():" + tempList.size()); return tempList; }
public static void updateLibrary(Context context, boolean rebuildStats) { Log.d(TAG, "updateLibrary() start"); Realm realm = Realm.getInstance(Migration.getConfig(context)); realm.beginTransaction(); RealmResults<Track> res = realm.where(Track.class).findAll(); for (int x = 0; x < res.size(); x++) { res.get(x).setIsAvailable(false); } realm.commitTransaction(); String where = MediaStore.Audio.Media.IS_MUSIC + " = 1"; String[] selectionArgs = null; String orderBy = MediaStore.Audio.Media.DEFAULT_SORT_ORDER; ContentResolver contentResolver = context.getContentResolver(); Cursor[] cursors = new Cursor[2]; cursors[0] = contentResolver.query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, TRACK_COLUMNS, where, selectionArgs, orderBy); cursors[1] = contentResolver.query( MediaStore.Audio.Media.INTERNAL_CONTENT_URI, TRACK_COLUMNS, where, selectionArgs, orderBy); Cursor cursor = new MergeCursor(cursors); int idColumn = cursor.getColumnIndex(MediaStore.Audio.Media._ID); int displayNameColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME); int titleColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE); int titleKeyColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TITLE_KEY); int durationColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DURATION); int trackColumn = cursor.getColumnIndex(MediaStore.Audio.Media.TRACK); int artistColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST); // int dateAddedColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DATE_ADDED); int dataColumn = cursor.getColumnIndex(MediaStore.Audio.Media.DATA); int albumColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM); int albumIdColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID); int albumKeyColumn = cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_KEY); realm.beginTransaction(); while (cursor.moveToNext()) { int minimumDurationToConsiderAsSong = 61500; Track track = null; String local_id = Track.getLocalId( cursor.getString(titleColumn), cursor.getString(artistColumn), cursor.getString(albumColumn)); Track res2 = realm.where(Track.class).equalTo("local_id", local_id).findFirst(); if (res2 != null) { if (cursor.getInt(durationColumn) < minimumDurationToConsiderAsSong) { res2.removeFromRealm(); } else { track = res2; track.setIsAvailable(true); if (!track.isHidden()) { if (rebuildStats) { rebuildStats(context, track.getLocal_id()); } } } } else { if (cursor.getInt(durationColumn) > minimumDurationToConsiderAsSong) { // Log.d(TAG, "hi6 - means its a new record"); // Log.d(TAG, "cursor.getString(titleColumn): " + // cursor.getString(titleColumn)); // Log.d(TAG, "cursor.getString(artistColumn): " + // cursor.getString(artistColumn)); // Log.d(TAG, "cursor.getString(albumColumn): " + // cursor.getString(albumColumn)); track = new Track( cursor.getString(titleColumn), cursor.getString(artistColumn), cursor.getString(albumColumn), cursor.getString(dataColumn)); track.setId(cursor.getLong(idColumn)); track.setDisplayName(cursor.getString(displayNameColumn)); track.setTitleKey(cursor.getString(titleKeyColumn)); track.setDuration(cursor.getInt(durationColumn)); track.setTrackNo(cursor.getInt(trackColumn)); track.setAlbumId(cursor.getString(albumIdColumn)); track.setAlbumKey(cursor.getString(albumKeyColumn)); track = realm.copyToRealm(track); } } if (track != null) { track.setPath(cursor.getString(dataColumn)); } } realm.commitTransaction(); cursor.close(); Log.d(TAG, "updateLibrary() end"); }
public static void rebuildStats(Context context, String localId) { Realm realm = Realm.getInstance(Migration.getConfig(context)); RealmResults<TrackStats> statsRes = realm.where(TrackStats.class).equalTo("local_id", localId).findAll(); if (!statsRes.isEmpty()) { /* Log.d(TAG, "hi5"); Log.d(TAG, "=================="); Log.d(TAG, "track.getTitle(): " + track.getTitle()); Log.d(TAG, "track.getCompletedCount(): " + track.getCompletedCount()); Log.d(TAG, "track.getSkippedCount(): " + track.getSkippedCount()); Log.d(TAG, "track.getLikedCount(): " + track.getLikedCount()); Log.d(TAG, "track.getDislikedCount(): " + track.getDislikedCount()); res.where().equalTo("type", TrackStats.SONG_SELECTED) //TODO not implemented yet */ int completedCount = 0; int skippedCount = 0; int likedCount = 0; int dislikedCount = 0; int halfPlayedCount = 0; int selectedCount = 0; for (TrackStats ts : statsRes) { switch (ts.getType()) { case TrackStats.SONG_COMPLETED: completedCount++; break; case TrackStats.SONG_HALF_PLAYED: halfPlayedCount++; break; case TrackStats.SONG_SELECTED: selectedCount++; break; case TrackStats.SONG_SKIPPED: skippedCount++; break; case TrackStats.SONG_LIKED: likedCount++; break; case TrackStats.SONG_DISLIKED: dislikedCount++; break; } } Track track = realm.where(Track.class).equalTo("local_id", localId).findFirst(); realm.beginTransaction(); track.setCompletedCount(completedCount); track.setHalfPlayedCount(halfPlayedCount); track.setSelectedCount(selectedCount); track.setSkippedCount(skippedCount); track.setLikedCount(likedCount); track.setDislikedCount(dislikedCount); track.setStatsUpdatedAt(DateTime.now(Calendar.getInstance().getTimeZone()).toString()); realm.commitTransaction(); } }
private List<Track> getGeneralPlaylist(List<Track> tempTrackList) { List<Track> tempList = new ArrayList<Track>(); if (tempTrackList != null) { Collections.sort( tempTrackList, new Comparator<Track>() { @Override public int compare(Track left, Track right) { return (left.getCompletedCount() + left.getSkippedCount()) - (right.getCompletedCount() + right.getSkippedCount()); } }); Iterator<Track> iter = tempTrackList.iterator(); while (iter.hasNext()) { Track newTrack = iter.next(); if (newTrack.getSkippedCount() + newTrack.getCompletedCount() > 3) { break; } if (Math.random() > 0.2) { tempList.add(newTrack); iter.remove(); if (tempTrackList.size() > 3) { break; } } } Collections.shuffle(tempTrackList); for (Track t : tempTrackList) { // Log.d(TAG, "t.getTitle(): " + t.getTitle()); int completedCount = t.getCompletedCount(); int skippedCount = t.getSkippedCount(); // res.where().equalTo("type", TrackStats.SONG_SELECTED) //TODO not implemented yet int likedCount = t.getLikedCount(); int dislikedCount = t.getDislikedCount(); /** * TODO need to make the ratio more representative of the respective counts i.e. if i * completed the song once, it should only give like 0.6 but if i completed the song 100 * times, it should give like 0.9? */ int comMinusSkip = completedCount - skippedCount; double cmsRatio = 0; if (comMinusSkip > 0) { cmsRatio = 0.9; } else { if (comMinusSkip == 0) { cmsRatio = 0.5; } else { cmsRatio = 0.1; } } // TODO similarly as above, this algo needs rework in future int likeMinusDislike = likedCount - dislikedCount; double lmdRatio = 0; if (likeMinusDislike > 0) { lmdRatio = 0.9; } else { if (likeMinusDislike == 0) { lmdRatio = 0.5; } else { lmdRatio = 0.1; } } // XZ: it should add up to 100 in total final double chanceContributionWeightage = 50; final double completedVsSkippedContributionWeightage = 20; final double likeDislikeContributionWeightage = 30; double chanceContribution = chanceContributionWeightage * Math.random(); double completedVsSkippedContribution = completedVsSkippedContributionWeightage * cmsRatio; double likeDislikeContribution = likeDislikeContributionWeightage * lmdRatio; // double selectedContribution = 20; //TODO *WIP* // double freshnessContribution = 20; //TODO *WIP* double points = chanceContribution + completedVsSkippedContribution + likeDislikeContribution; if (points > PASSING_GRADE) { tempList.add(t); } if (tempList.size() == 10) { break; } } } return tempList; }