0
0
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:
Tim Rae 2016-01-28 13:58:25 +09:00
commit c0759d1dc5
9 changed files with 2035 additions and 5 deletions

View File

@ -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

View File

@ -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);

View 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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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 ForsythEdwards 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>

View File

@ -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">

View File

@ -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>