Add statistics #274

This commit is contained in:
tom79 2019-08-26 17:47:00 +02:00
parent 19d3779a6d
commit 59259f0faf
10 changed files with 307 additions and 60 deletions

View File

@ -62,15 +62,18 @@ import java.util.List;
import java.util.Map;
import app.fedilab.android.R;
import app.fedilab.android.asynctasks.RetrieveNotificationStatsAsyncTask;
import app.fedilab.android.asynctasks.RetrieveNotificationsCacheAsyncTask;
import app.fedilab.android.client.APIResponse;
import app.fedilab.android.client.Entities.Account;
import app.fedilab.android.client.Entities.Notification;
import app.fedilab.android.client.Entities.Statistics;
import app.fedilab.android.client.Entities.StatisticsNotification;
import app.fedilab.android.drawers.NotificationsListAdapter;
import app.fedilab.android.helper.FilterNotifications;
import app.fedilab.android.helper.Helper;
import app.fedilab.android.interfaces.OnRetrieveCacheNotificationsInterface;
import app.fedilab.android.interfaces.OnRetrieveNotificationStatsInterface;
import app.fedilab.android.interfaces.OnRetrieveStatsInterface;
import app.fedilab.android.services.BackupNotificationInDataBaseService;
import app.fedilab.android.sqlite.AccountDAO;
@ -84,7 +87,7 @@ import es.dmoral.toasty.Toasty;
* Show owner's notifications
*/
public class OwnerNotificationActivity extends BaseActivity implements OnRetrieveStatsInterface, OnRetrieveCacheNotificationsInterface {
public class OwnerNotificationActivity extends BaseActivity implements OnRetrieveCacheNotificationsInterface, OnRetrieveNotificationStatsInterface {
private ImageView pp_actionBar;
@ -102,7 +105,7 @@ public class OwnerNotificationActivity extends BaseActivity implements OnRetrie
private FilterNotifications filterNotifications;
private Date dateIni, dateEnd;
private View statsDialogView;
private Statistics statistics;
private StatisticsNotification statistics;
@Override
@ -319,7 +322,7 @@ public class OwnerNotificationActivity extends BaseActivity implements OnRetrie
});
dialogBuilder.create().show();
if( statistics == null) {
new RetrieveNotificationsCacheAsyncTask(getApplicationContext(), null, null, OwnerNotificationActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
new RetrieveNotificationStatsAsyncTask(getApplicationContext(), OwnerNotificationActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}else{
displayStats();
}
@ -354,6 +357,10 @@ public class OwnerNotificationActivity extends BaseActivity implements OnRetrie
settings_time_from = dialogView.findViewById(R.id.settings_time_from);
settings_time_to = dialogView.findViewById(R.id.settings_time_to);
settings_time_from.setText(dateInitString);
settings_time_to.setText(dateEndString);
final CheckBox filter_boosts = dialogView.findViewById(R.id.filter_boosts);
final CheckBox filter_fav = dialogView.findViewById(R.id.filter_fav);
final CheckBox filter_mention = dialogView.findViewById(R.id.filter_mention);
@ -366,7 +373,6 @@ public class OwnerNotificationActivity extends BaseActivity implements OnRetrie
filter_follow.setChecked(filterNotifications.isFollow());
filter_poll.setChecked(filterNotifications.isPoll());
final Spinner filter_boost = dialogView.findViewById(R.id.filter_boost);
Calendar c = Calendar.getInstance();
@ -453,33 +459,23 @@ public class OwnerNotificationActivity extends BaseActivity implements OnRetrie
.unregisterReceiver(backupFinishedReceiver);
}
@Override
public void onStats(Statistics statistics) {
this.statistics = statistics;
displayStats();
}
private void displayStats(){
if( statsDialogView != null){
ScrollView stats_container = statsDialogView.findViewById(R.id.stats_container);
RelativeLayout loader = statsDialogView.findViewById(R.id.loader);
TextView total_statuses = statsDialogView.findViewById(R.id.total_statuses);
TextView total_notifications = statsDialogView.findViewById(R.id.total_notifications);
TextView number_boosts = statsDialogView.findViewById(R.id.number_boosts);
TextView number_replies = statsDialogView.findViewById(R.id.number_replies);
TextView number_statuses = statsDialogView.findViewById(R.id.number_statuses);
TextView number_with_media = statsDialogView.findViewById(R.id.number_with_media);
TextView number_with_cw = statsDialogView.findViewById(R.id.number_with_cw);
TextView number_with_sensitive_media = statsDialogView.findViewById(R.id.number_with_sensitive_media);
TextView v_public = statsDialogView.findViewById(R.id.v_public);
TextView v_unlisted = statsDialogView.findViewById(R.id.v_unlisted);
TextView v_private = statsDialogView.findViewById(R.id.v_private);
TextView v_direct = statsDialogView.findViewById(R.id.v_direct);
TextView number_favourites = statsDialogView.findViewById(R.id.number_favourites);
TextView number_mentions = statsDialogView.findViewById(R.id.number_mentions);
TextView number_follows = statsDialogView.findViewById(R.id.number_follows);
TextView number_polls = statsDialogView.findViewById(R.id.number_polls);
TextView frequency = statsDialogView.findViewById(R.id.frequency);
TextView last_toot_date = statsDialogView.findViewById(R.id.last_toot_date);
TextView first_toot_date = statsDialogView.findViewById(R.id.first_toot_date);
TextView tags = statsDialogView.findViewById(R.id.tags);
ImageButton charts = statsDialogView.findViewById(R.id.charts);
charts.setOnClickListener(w ->{
@ -487,38 +483,19 @@ public class OwnerNotificationActivity extends BaseActivity implements OnRetrie
startActivity(intent);
});
total_statuses.setText(String.valueOf(statistics.getTotal_statuses()));
number_boosts.setText(String.valueOf(statistics.getNumber_boosts()));
number_replies.setText(String.valueOf(statistics.getNumber_replies()));
number_statuses.setText(String.valueOf(statistics.getNumber_status()));
number_with_media.setText(String.valueOf(statistics.getNumber_with_media()));
number_with_cw.setText(String.valueOf(statistics.getNumber_with_cw()));
number_with_sensitive_media.setText(String.valueOf(statistics.getNumber_with_sensitive_media()));
v_public.setText(String.valueOf(statistics.getV_public()));
v_unlisted.setText(String.valueOf(statistics.getV_unlisted()));
v_private.setText(String.valueOf(statistics.getV_private()));
v_direct.setText(String.valueOf(statistics.getV_direct()));
total_notifications.setText(String.valueOf(statistics.getTotal_notification()));
number_boosts.setText(String.valueOf(statistics.getNumber_reblog()));
number_favourites.setText(String.valueOf(statistics.getNumber_favourite()));
number_mentions.setText(String.valueOf(statistics.getNumber_mentions()));
number_follows.setText(String.valueOf(statistics.getNumber_follow()));
number_polls.setText(String.valueOf(statistics.getNumber_poll()));
first_toot_date.setText(Helper.dateToString(statistics.getFirstTootDate()));
last_toot_date.setText(Helper.dateToString(statistics.getLastTootDate()));
DecimalFormat df = new DecimalFormat("#.##");
frequency.setText(getString(R.string.toot_per_day, df.format(statistics.getFrequency())));
frequency.setText(getString(R.string.notification_per_day, df.format(statistics.getFrequency())));
if( statistics.getTagsTrend() != null && statistics.getTagsTrend().size() > 0 ){
Iterator it = statistics.getTagsTrend() .entrySet().iterator();
StringBuilder text = new StringBuilder();
int i = 1;
while (it.hasNext() && i <= 10) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
text.append(i).append(" - ").append(pair.getKey()).append("").append(pair.getValue()).append("\r\n");
i++;
}
tags.setText(text.toString());
}else{
tags.setText(getString(R.string.no_tags));
}
stats_container.setVisibility(View.VISIBLE);
loader.setVisibility(View.GONE);
@ -570,4 +547,10 @@ public class OwnerNotificationActivity extends BaseActivity implements OnRetrie
swipeRefreshLayout.setRefreshing(false);
firstLoad = false;
}
@Override
public void onStats(StatisticsNotification statistics) {
this.statistics = statistics;
displayStats();
}
}

View File

@ -0,0 +1,61 @@
/* Copyright 2019 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
package app.fedilab.android.asynctasks;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.AsyncTask;
import java.lang.ref.WeakReference;
import app.fedilab.android.client.Entities.StatisticsNotification;
import app.fedilab.android.interfaces.OnRetrieveNotificationStatsInterface;
import app.fedilab.android.sqlite.NotificationCacheDAO;
import app.fedilab.android.sqlite.Sqlite;
/**
* Created by Thomas on 26/08/2019.
* Retrieves notification stats for an account
*/
public class RetrieveNotificationStatsAsyncTask extends AsyncTask<Void, Void, Void> {
private OnRetrieveNotificationStatsInterface listener;
private WeakReference<Context> contextReference;
private StatisticsNotification statistics;
public RetrieveNotificationStatsAsyncTask(Context context, OnRetrieveNotificationStatsInterface onRetrieveNotificationStatsInterface){
this.contextReference = new WeakReference<>(context);
this.listener = onRetrieveNotificationStatsInterface;
}
@Override
protected Void doInBackground(Void... params) {
SQLiteDatabase db = Sqlite.getInstance(contextReference.get(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
statistics = new NotificationCacheDAO(contextReference.get(), db).getStat();
return null;
}
@Override
protected void onPostExecute(Void result) {
listener.onStats(statistics);
}
}

View File

@ -0,0 +1,104 @@
package app.fedilab.android.client.Entities;
/* Copyright 2019 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
import java.util.Date;
public class StatisticsNotification {
private int total_notification = 0;
private int number_reblog = 0;
private int number_favourite = 0;
private int number_mentions = 0;
private int number_follow = 0;
private int number_poll = 0;
private Date firstTootDate;
private Date lastTootDate;
private float frequency;
public int getTotal_notification() {
return total_notification;
}
public void setTotal_notification(int total_notification) {
this.total_notification = total_notification;
}
public int getNumber_reblog() {
return number_reblog;
}
public void setNumber_reblog(int number_reblog) {
this.number_reblog = number_reblog;
}
public int getNumber_favourite() {
return number_favourite;
}
public void setNumber_favourite(int number_favourite) {
this.number_favourite = number_favourite;
}
public int getNumber_mentions() {
return number_mentions;
}
public void setNumber_mentions(int number_mentions) {
this.number_mentions = number_mentions;
}
public int getNumber_follow() {
return number_follow;
}
public void setNumber_follow(int number_follow) {
this.number_follow = number_follow;
}
public int getNumber_poll() {
return number_poll;
}
public void setNumber_poll(int number_poll) {
this.number_poll = number_poll;
}
public Date getFirstTootDate() {
return firstTootDate;
}
public void setFirstTootDate(Date firstTootDate) {
this.firstTootDate = firstTootDate;
}
public Date getLastTootDate() {
return lastTootDate;
}
public void setLastTootDate(Date lastTootDate) {
this.lastTootDate = lastTootDate;
}
public float getFrequency() {
return frequency;
}
public void setFrequency(float frequency) {
this.frequency = frequency;
}
}

View File

@ -0,0 +1,25 @@
/* Copyright 2019 Thomas Schneider
*
* This file is a part of Fedilab
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* Fedilab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
* see <http://www.gnu.org/licenses>. */
package app.fedilab.android.interfaces;
import app.fedilab.android.client.Entities.StatisticsNotification;
/**
* Created by Thomas on 26/08/2019.
* Interface when retrieving notification stats
*/
public interface OnRetrieveNotificationStatsInterface {
void onStats(StatisticsNotification statistics);
}

View File

@ -116,7 +116,6 @@ public class BackupNotificationInDataBaseService extends IntentService {
SQLiteDatabase db = Sqlite.getInstance(BackupNotificationInDataBaseService.this, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
Account account = new AccountDAO(getApplicationContext(), db).getUniqAccount(userId, instance);
API api = new API(getApplicationContext(), account.getInstance(), account.getToken());
//new NotificationCacheDAO(getApplicationContext(), db).removeAll();
try {
//Starts from the last recorded ID
String lastId = new NotificationCacheDAO(BackupNotificationInDataBaseService.this, db).getLastNotificationIDCache(userId, instance);
@ -137,14 +136,14 @@ public class BackupNotificationInDataBaseService extends IntentService {
new NotificationCacheDAO(BackupNotificationInDataBaseService.this, db).insertNotification(tmpNotification, userId, instance);
backupNotifications.add(tmpNotification);
}
SystemClock.sleep(1000);
SystemClock.sleep(500);
}while (max_id != null && canContinue);
if(backupNotifications.size() > 0){
Intent backupIntent = new Intent(Helper.INTENT_BACKUP_FINISH);
LocalBroadcastManager.getInstance(this).sendBroadcast(backupIntent);
}
message = getString(R.string.data_backup_success, String.valueOf(backupNotifications.size()));
message = getString(R.string.data_backup_notification_success, String.valueOf(backupNotifications.size()));
Intent mainActivity = new Intent(BackupNotificationInDataBaseService.this, MainActivity.class);
mainActivity.putExtra(Helper.INTENT_ACTION, Helper.BACKUP_NOTIFICATION_INTENT);
String title = getString(R.string.data_backup_toots, account.getAcct());

View File

@ -135,7 +135,7 @@ public class BackupStatusInDataBaseService extends IntentService {
new StatusCacheDAO(BackupStatusInDataBaseService.this, db).insertStatus(StatusCacheDAO.ARCHIVE_CACHE, tmpStatus, userId, instance);
backupStatus.add(tmpStatus);
}
SystemClock.sleep(1000);
SystemClock.sleep(500);
}while (max_id != null && canContinue);
if(backupStatus.size() > 0){

View File

@ -119,7 +119,7 @@ public class BackupStatusService extends IntentService {
List<Status> statuses = apiResponse.getStatuses();
if (statuses.size() > 0)
backupStatus.addAll(statuses);
SystemClock.sleep(1000);
SystemClock.sleep(500);
}while (max_id != null);
String fileName = account.getAcct()+"@"+account.getInstance()+ Helper.dateFileToString(getApplicationContext(), new Date())+".csv";

View File

@ -21,20 +21,14 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import app.fedilab.android.client.Entities.Charts;
import app.fedilab.android.client.Entities.Notification;
import app.fedilab.android.client.Entities.Statistics;
import app.fedilab.android.client.Entities.StatisticsNotification;
import app.fedilab.android.client.Entities.Status;
import app.fedilab.android.client.Entities.Tag;
import app.fedilab.android.helper.FilterNotifications;
import app.fedilab.android.helper.FilterToots;
import app.fedilab.android.helper.Helper;
@ -399,6 +393,85 @@ public class NotificationCacheDAO {
public StatisticsNotification getStat(){
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(context);
StatisticsNotification statistics = new StatisticsNotification();
//Count All
Cursor mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_NOTIFICATION_CACHE
+ " where " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"'"
, null);
mCount.moveToFirst();
statistics.setTotal_notification(mCount.getInt(0));
mCount.close();
//Count boosts
mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_NOTIFICATION_CACHE
+ " where " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND "
+ Sqlite.COL_TYPE + " = 'reblog'"
, null);
mCount.moveToFirst();
statistics.setNumber_reblog(mCount.getInt(0));
mCount.close();
//Count favorites
mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_NOTIFICATION_CACHE
+ " where " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND "
+ Sqlite.COL_TYPE + " = 'favourite'"
, null);
mCount.moveToFirst();
statistics.setNumber_favourite(mCount.getInt(0));
mCount.close();
//Count mentions
mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_NOTIFICATION_CACHE
+ " where " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND "
+ Sqlite.COL_TYPE + " = 'mention'"
, null);
mCount.moveToFirst();
statistics.setNumber_mentions(mCount.getInt(0));
mCount.close();
//Count follows
mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_NOTIFICATION_CACHE
+ " where " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND "
+ Sqlite.COL_TYPE + " = 'follow'"
, null);
mCount.moveToFirst();
statistics.setNumber_follow(mCount.getInt(0));
mCount.close();
//Count polls
mCount = db.rawQuery("select count(*) from " + Sqlite.TABLE_NOTIFICATION_CACHE
+ " where " + Sqlite.COL_USER_ID + " = '" + userId + "' AND " + Sqlite.COL_INSTANCE + " = '" + instance +"' AND "
+ Sqlite.COL_TYPE + " = 'poll'"
, null);
mCount.moveToFirst();
statistics.setNumber_poll(mCount.getInt(0));
mCount.close();
statistics.setFirstTootDate(getSmallerDate());
statistics.setLastTootDate(getGreaterDate());
long days = 1;
if( statistics.getLastTootDate() != null && statistics.getFirstTootDate() != null) {
long diff = statistics.getLastTootDate().getTime() - statistics.getFirstTootDate().getTime();
days = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
}
statistics.setFrequency((float)statistics.getTotal_notification()/days);
return statistics;
}
/***
* Method to hydrate notification from database
* @param c Cursor

View File

@ -169,7 +169,7 @@
<TextView
android:layout_weight="1"
android:textAlignment="textEnd"
android:id="@+id/total_statuses"
android:id="@+id/total_notifications"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>

View File

@ -454,6 +454,7 @@
<string name="data_backup_toots">Backup toots for %1$s</string>
<string name="data_backup_notifications">Backup notifications for %1$s</string>
<string name="data_backup_success">%1$s new toots have been imported</string>
<string name="data_backup_notification_success">%1$s new notifications have been imported</string>
<string-array name="filter_select">
<item>No</item>
<item>Only</item>
@ -1143,6 +1144,7 @@
<string name="last_toot_date">Last status date</string>
<string name="frequency">Frequency</string>
<string name="toot_per_day">%s statuses per day</string>
<string name="notification_per_day">%s notifications per day</string>
<string name="date_range">Date range</string>
<string name="action_groups">Groups</string>
<string name="no_messages">No groups!</string>