mirror of
https://github.com/ankidroid/Anki-Android.git
synced 2024-09-20 12:02:16 +02:00
Merge pull request #4070 from rvanprehn/develop
Make forecast statistic predictive
This commit is contained in:
commit
c0759d1dc5
@ -48,6 +48,7 @@ import android.view.WindowManager.BadTokenException;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.ichi2.libanki.hooks.AdvancedStatistics;
|
||||
import com.ichi2.themes.Themes;
|
||||
import com.ichi2.ui.AppCompatPreferenceActivity;
|
||||
import com.ichi2.ui.SeekBarPreference;
|
||||
@ -182,6 +183,7 @@ public class Preferences extends AppCompatPreferenceActivity implements Preferen
|
||||
// in from preferences screen), so we need to update it here.
|
||||
updatePreference(prefs, "syncAccount", this);
|
||||
updatePreference(prefs, "custom_sync_server_link", this);
|
||||
updatePreference(prefs, "advanced_statistics_link", this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,6 +295,16 @@ public class Preferences extends AppCompatPreferenceActivity implements Preferen
|
||||
return true;
|
||||
}
|
||||
});
|
||||
// Advanced statistics option
|
||||
Preference advancedStatisticsPreference = screen.findPreference("advanced_statistics_link");
|
||||
advancedStatisticsPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Intent i = CompatHelper.getCompat().getPreferenceSubscreenIntent(Preferences.this,
|
||||
"com.ichi2.anki.prefs.advanced_statistics");
|
||||
startActivity(i);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
// Force full sync option
|
||||
Preference fullSyncPreference = screen.findPreference("force_full_sync");
|
||||
fullSyncPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||
@ -311,6 +323,10 @@ public class Preferences extends AppCompatPreferenceActivity implements Preferen
|
||||
getSupportActionBar().setTitle(R.string.custom_sync_server_title);
|
||||
listener.addPreferencesFromResource(R.xml.preferences_custom_sync_server);
|
||||
break;
|
||||
case "com.ichi2.anki.prefs.advanced_statistics":
|
||||
getSupportActionBar().setTitle(R.string.advanced_statistics_title);
|
||||
listener.addPreferencesFromResource(R.xml.preferences_advanced_statistics);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -428,6 +444,13 @@ public class Preferences extends AppCompatPreferenceActivity implements Preferen
|
||||
HebrewFixFilter.uninstall(Hooks.getInstance(getApplicationContext()));
|
||||
}
|
||||
break;
|
||||
case "advanced_statistics_enabled":
|
||||
if (((CheckBoxPreference) pref).isChecked()) {
|
||||
AdvancedStatistics.install(Hooks.getInstance(getApplicationContext()));
|
||||
} else {
|
||||
AdvancedStatistics.uninstall(Hooks.getInstance(getApplicationContext()));
|
||||
}
|
||||
break;
|
||||
case "showProgress":
|
||||
getCol().getConf().put("dueCounts", ((CheckBoxPreference) pref).isChecked());
|
||||
getCol().setMod();
|
||||
@ -538,6 +561,13 @@ public class Preferences extends AppCompatPreferenceActivity implements Preferen
|
||||
} else {
|
||||
pref.setSummary(AnkiDroidApp.getSharedPrefs(this).getString("syncBaseUrl", ""));
|
||||
}
|
||||
}
|
||||
else if (pref.getKey().equals("advanced_statistics_link")) {
|
||||
if (!AnkiDroidApp.getSharedPrefs(this).getBoolean("advanced_statistics_enabled", false)) {
|
||||
pref.setSummary(R.string.disabled);
|
||||
} else {
|
||||
pref.setSummary(R.string.enabled);
|
||||
}
|
||||
}
|
||||
// Get value text
|
||||
String value;
|
||||
@ -731,6 +761,7 @@ public class Preferences extends AppCompatPreferenceActivity implements Preferen
|
||||
// in from preferences screen), so we need to update it here.
|
||||
((Preferences) getActivity()).updatePreference(prefs, "syncAccount", this);
|
||||
((Preferences) getActivity()).updatePreference(prefs, "custom_sync_server_link", this);
|
||||
((Preferences) getActivity()).updatePreference(prefs, "advanced_statistics_link", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +66,7 @@ public class ChartBuilder {
|
||||
Stats stats = new Stats(mCollectionData, mIsWholeCollection);
|
||||
switch (mChartType){
|
||||
case FORECAST:
|
||||
stats.calculateDue(mType);
|
||||
stats.calculateDue(mChartView.getContext(), mType);
|
||||
break;
|
||||
case REVIEW_COUNT:
|
||||
stats.calculateDone(mType, true);
|
||||
|
187
AnkiDroid/src/main/java/com/ichi2/anki/stats/StatsMetaInfo.java
Normal file
187
AnkiDroid/src/main/java/com/ichi2/anki/stats/StatsMetaInfo.java
Normal file
@ -0,0 +1,187 @@
|
||||
/****************************************************************************************
|
||||
* Copyright (c) 2016 Jeffrey van Prehn <jvanprehn@gmail.com> *
|
||||
* *
|
||||
* 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. *
|
||||
* *
|
||||
* This program 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 *
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
****************************************************************************************/
|
||||
|
||||
package com.ichi2.anki.stats;
|
||||
|
||||
/**
|
||||
* Interface between Stats.java and AdvancedStatistics.java
|
||||
*/
|
||||
public class StatsMetaInfo {
|
||||
boolean mDynamicAxis = false;
|
||||
boolean mHasColoredCumulative = false;
|
||||
int mType;
|
||||
int mTitle;
|
||||
boolean mBackwards;
|
||||
int[] mValueLabels;
|
||||
int[] mColors;
|
||||
int[] mAxisTitles;
|
||||
int mMaxCards = 0;
|
||||
int mMaxElements = 0;
|
||||
double mFirstElement = 0;
|
||||
double mLastElement = 0;
|
||||
int mZeroIndex = 0;
|
||||
double[][] mCumulative = null;
|
||||
double mMcount;
|
||||
|
||||
double[][] mSeriesList;
|
||||
|
||||
boolean statsCalculated;
|
||||
boolean dataAvailable;
|
||||
|
||||
public boolean isStatsCalculated() {
|
||||
return statsCalculated;
|
||||
}
|
||||
|
||||
public void setStatsCalculated(boolean statsCalculated) {
|
||||
this.statsCalculated = statsCalculated;
|
||||
}
|
||||
|
||||
public double[][] getmSeriesList() {
|
||||
return mSeriesList;
|
||||
}
|
||||
|
||||
public void setmSeriesList(double[][] mSeriesList) {
|
||||
this.mSeriesList = mSeriesList;
|
||||
}
|
||||
|
||||
public boolean isDataAvailable() {
|
||||
return dataAvailable;
|
||||
}
|
||||
|
||||
public void setDataAvailable(boolean dataAvailable) {
|
||||
this.dataAvailable = dataAvailable;
|
||||
}
|
||||
|
||||
public boolean ismDynamicAxis() {
|
||||
return mDynamicAxis;
|
||||
}
|
||||
|
||||
public void setmDynamicAxis(boolean mDynamicAxis) {
|
||||
this.mDynamicAxis = mDynamicAxis;
|
||||
}
|
||||
|
||||
public boolean ismHasColoredCumulative() {
|
||||
return mHasColoredCumulative;
|
||||
}
|
||||
|
||||
public void setmHasColoredCumulative(boolean mHasColoredCumulative) {
|
||||
this.mHasColoredCumulative = mHasColoredCumulative;
|
||||
}
|
||||
|
||||
public int getmType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
public void setmType(int mType) {
|
||||
this.mType = mType;
|
||||
}
|
||||
|
||||
public int getmTitle() {
|
||||
return mTitle;
|
||||
}
|
||||
|
||||
public void setmTitle(int mTitle) {
|
||||
this.mTitle = mTitle;
|
||||
}
|
||||
|
||||
public boolean ismBackwards() {
|
||||
return mBackwards;
|
||||
}
|
||||
|
||||
public void setmBackwards(boolean mBackwards) {
|
||||
this.mBackwards = mBackwards;
|
||||
}
|
||||
|
||||
public int[] getmValueLabels() {
|
||||
return mValueLabels;
|
||||
}
|
||||
|
||||
public void setmValueLabels(int[] mValueLabels) {
|
||||
this.mValueLabels = mValueLabels;
|
||||
}
|
||||
|
||||
public int[] getmColors() {
|
||||
return mColors;
|
||||
}
|
||||
|
||||
public void setmColors(int[] mColors) {
|
||||
this.mColors = mColors;
|
||||
}
|
||||
|
||||
public int[] getmAxisTitles() {
|
||||
return mAxisTitles;
|
||||
}
|
||||
|
||||
public void setmAxisTitles(int[] mAxisTitles) {
|
||||
this.mAxisTitles = mAxisTitles;
|
||||
}
|
||||
|
||||
public int getmMaxCards() {
|
||||
return mMaxCards;
|
||||
}
|
||||
|
||||
public void setmMaxCards(int mMaxCards) {
|
||||
this.mMaxCards = mMaxCards;
|
||||
}
|
||||
|
||||
public int getmMaxElements() {
|
||||
return mMaxElements;
|
||||
}
|
||||
|
||||
public void setmMaxElements(int mMaxElements) {
|
||||
this.mMaxElements = mMaxElements;
|
||||
}
|
||||
|
||||
public double getmFirstElement() {
|
||||
return mFirstElement;
|
||||
}
|
||||
|
||||
public void setmFirstElement(double mFirstElement) {
|
||||
this.mFirstElement = mFirstElement;
|
||||
}
|
||||
|
||||
public double getmLastElement() {
|
||||
return mLastElement;
|
||||
}
|
||||
|
||||
public void setmLastElement(double mLastElement) {
|
||||
this.mLastElement = mLastElement;
|
||||
}
|
||||
|
||||
public int getmZeroIndex() {
|
||||
return mZeroIndex;
|
||||
}
|
||||
|
||||
public void setmZeroIndex(int mZeroIndex) {
|
||||
this.mZeroIndex = mZeroIndex;
|
||||
}
|
||||
|
||||
public double[][] getmCumulative() {
|
||||
return mCumulative;
|
||||
}
|
||||
|
||||
public void setmCumulative(double[][] mCumulative) {
|
||||
this.mCumulative = mCumulative;
|
||||
}
|
||||
|
||||
public double getmMcount() {
|
||||
return mMcount;
|
||||
}
|
||||
|
||||
public void setmMcount(double mMcount) {
|
||||
this.mMcount = mMcount;
|
||||
}
|
||||
}
|
@ -22,11 +22,12 @@ import android.database.Cursor;
|
||||
|
||||
import com.ichi2.anki.AnkiDroidApp;
|
||||
import com.ichi2.anki.R;
|
||||
import com.ichi2.anki.stats.StatsMetaInfo;
|
||||
import com.ichi2.libanki.hooks.Hooks;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
import timber.log.Timber;
|
||||
@ -78,7 +79,6 @@ public class Stats {
|
||||
sCurrentInstance = this;
|
||||
}
|
||||
|
||||
|
||||
public static Stats currentStats() {
|
||||
return sCurrentInstance;
|
||||
}
|
||||
@ -171,11 +171,46 @@ public class Stats {
|
||||
|
||||
return new int[]{cards, thetime, failed, lrn, rev, relrn, filt, mcnt, msum};
|
||||
}
|
||||
|
||||
public boolean calculateDue(Context context, int type) {
|
||||
|
||||
// Not in libanki
|
||||
StatsMetaInfo metaInfo = new StatsMetaInfo();
|
||||
|
||||
metaInfo = (StatsMetaInfo) Hooks.getInstance(context).runFilter("advancedStatistics", metaInfo, type, context, _limit());
|
||||
|
||||
if(metaInfo.isStatsCalculated()) {
|
||||
|
||||
mDynamicAxis = metaInfo.ismDynamicAxis();
|
||||
mHasColoredCumulative = metaInfo.ismHasColoredCumulative();
|
||||
mType = metaInfo.getmType();
|
||||
mTitle = metaInfo.getmTitle();
|
||||
mBackwards = metaInfo.ismBackwards();
|
||||
mValueLabels = metaInfo.getmValueLabels();
|
||||
mColors = metaInfo.getmColors();
|
||||
mAxisTitles = metaInfo.getmAxisTitles();
|
||||
mMaxCards = metaInfo.getmMaxCards();
|
||||
mMaxElements = metaInfo.getmMaxElements();
|
||||
mFirstElement = metaInfo.getmFirstElement();
|
||||
mLastElement = metaInfo.getmLastElement();
|
||||
mZeroIndex = metaInfo.getmZeroIndex();
|
||||
mCumulative = metaInfo.getmCumulative();
|
||||
mMcount = metaInfo.getmMcount();
|
||||
|
||||
mSeriesList = metaInfo.getmSeriesList();
|
||||
|
||||
return metaInfo.isDataAvailable();
|
||||
}
|
||||
else {
|
||||
return calculateDue(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Due and cumulative due
|
||||
* ***********************************************************************************************
|
||||
*/
|
||||
public boolean calculateDue(int type) {
|
||||
private boolean calculateDue(int type) {
|
||||
mHasColoredCumulative = false;
|
||||
mType = type;
|
||||
mDynamicAxis = true;
|
||||
@ -290,7 +325,6 @@ public class Stats {
|
||||
return dues.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
/* only needed for studyoptions small chart */
|
||||
public static double[][] getSmallDueStats(Collection col) {
|
||||
ArrayList<int[]> dues = new ArrayList<int[]>();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -58,6 +58,9 @@ public class Hooks {
|
||||
if (prefs.getBoolean("convertFenText", false)) {
|
||||
ChessFilter.install(this);
|
||||
}
|
||||
if (prefs.getBoolean("advanced_statistics_enabled", false)) {
|
||||
AdvancedStatistics.install(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
--><resources>
|
||||
<!-- generic strings -->
|
||||
<string name="disabled">Disabled</string>
|
||||
<string name="enabled">Enabled</string>
|
||||
<!-- preferences.xml categories-->
|
||||
<string name="pref_cat_general">AnkiDroid</string>
|
||||
<string name="pref_cat_general_summ">General settings</string>
|
||||
@ -140,6 +141,13 @@
|
||||
<string name="convert_fen_text_summ">Draw chessboard from Forsyth–Edwards Notation. The notation must be enclosed in [fen][/fen] tags.</string>
|
||||
<string name="enable_api_title">Enable AnkiDroid API</string>
|
||||
<string name="enable_api_summary">Let other apps connect to AnkiDroid and read / write data without your intervention</string>
|
||||
<!-- Advanced statistics settings -->
|
||||
<string name="advanced_statistics_title">Advanced statistics</string>
|
||||
<string name="enable_advanced_statistics_title">Enable advanced statistics</string>
|
||||
<string name="enable_advanced_statistics_summ">Display forecast statistics based on a computation or simulation of future reviews (enabled) or on the future reviews already scheduled (disabled).</string>
|
||||
<string name="advanced_forecast_stats_compute_n_days_title">Compute first n days, simulate remainder</string>
|
||||
<string name="advanced_forecast_stats_compute_precision_title">Precision of computation</string>
|
||||
<string name="advanced_forecast_stats_mc_n_iterations_title">Number of iterations of the simulation</string>
|
||||
<!-- Custom sync server settings -->
|
||||
<string name="custom_sync_server_title">Custom sync server</string>
|
||||
<string name="custom_sync_server_enable_title">Use custom sync server</string>
|
||||
|
@ -128,8 +128,12 @@
|
||||
android:key="double_scrolling"
|
||||
android:summary="@string/double_scrolling_gap_summ"
|
||||
android:title="@string/double_scrolling_gap" />
|
||||
<Preference
|
||||
android:key="advanced_statistics_link"
|
||||
android:title="@string/advanced_statistics_title"/>
|
||||
</PreferenceCategory>
|
||||
|
||||
|
||||
<Preference
|
||||
android:key="about_dialog_preference"
|
||||
android:title="@string/about_title">
|
||||
|
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
|
||||
<!-- Advanced Statistics Preferences -->
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://arbitrary.app.namespace/com.ichi2.anki">
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="advanced_statistics_enabled"
|
||||
android:summary="@string/enable_advanced_statistics_summ"
|
||||
android:title="@string/enable_advanced_statistics_title"/>
|
||||
<com.ichi2.ui.SeekBarPreference
|
||||
android:defaultValue="0"
|
||||
android:dependency="advanced_statistics_enabled"
|
||||
android:key="advanced_forecast_stats_compute_n_days"
|
||||
android:max="30"
|
||||
android:summary="@string/preference_summary_literal"
|
||||
android:title="@string/advanced_forecast_stats_compute_n_days_title"
|
||||
app:interval="1"
|
||||
app:min="0" />
|
||||
<com.ichi2.ui.SeekBarPreference
|
||||
android:defaultValue="90"
|
||||
android:dependency="advanced_statistics_enabled"
|
||||
android:key="advanced_forecast_stats_compute_precision"
|
||||
android:max="99"
|
||||
android:summary="@string/preference_summary_percentage"
|
||||
android:text=" %"
|
||||
android:title="@string/advanced_forecast_stats_compute_precision_title"
|
||||
app:interval="1"
|
||||
app:min="0" />
|
||||
<com.ichi2.ui.SeekBarPreference
|
||||
android:defaultValue="1"
|
||||
android:dependency="advanced_statistics_enabled"
|
||||
android:key="advanced_forecast_stats_mc_n_iterations"
|
||||
android:max="20"
|
||||
android:summary="@string/preference_summary_literal"
|
||||
android:title="@string/advanced_forecast_stats_mc_n_iterations_title"
|
||||
app:interval="1"
|
||||
app:min="1" />
|
||||
</PreferenceScreen>
|
Loading…
Reference in New Issue
Block a user