From 6e4dac4f333e02e624c5b7a1d579c2c7b2888d89 Mon Sep 17 00:00:00 2001 From: Size43 Date: Wed, 10 Jun 2015 11:08:28 +0200 Subject: Removed hardcoded strings & only one TrainingCase is stored per Article. --- .../java/org/rssin/android/ArticleActivity.java | 4 +- .../org/rssin/android/NavigationDrawerAdapter.java | 59 +++------------------- .../main/java/org/rssin/neurons/FeedSorter.java | 8 ++- .../main/java/org/rssin/neurons/TrainingCase.java | 11 ++-- .../org/rssin/rssin/SortedFeedItemContainer.java | 9 +++- app/src/main/res/values/strings.xml | 5 ++ 6 files changed, 35 insertions(+), 61 deletions(-) diff --git a/app/src/main/java/org/rssin/android/ArticleActivity.java b/app/src/main/java/org/rssin/android/ArticleActivity.java index f5c0631..2512949 100755 --- a/app/src/main/java/org/rssin/android/ArticleActivity.java +++ b/app/src/main/java/org/rssin/android/ArticleActivity.java @@ -77,12 +77,12 @@ public class ArticleActivity extends ActionBarActivity { //noinspection SimplifiableIfStatement if (id == R.id.article_action_dislike) { - Toast.makeText(this, "Feedback saved.", Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.article_feedback_saved), Toast.LENGTH_SHORT).show(); container.feedback(this, Dislike); return true; } else if(id == R.id.article_action_like) { - Toast.makeText(this, "Feedback saved.", Toast.LENGTH_SHORT).show(); + Toast.makeText(this, getString(R.string.article_feedback_saved), Toast.LENGTH_SHORT).show(); container.feedback(this, Like); return true; } else if(id == R.id.article_action_share) diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java b/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java index 90ce041..2a24342 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java @@ -33,23 +33,22 @@ class NavigationDrawerAdapter implements ListAdapter { public void updateMenu(Context context) throws IOException { menuItems.clear(); - menuItems.add(new MenuSection("START")); - menuItems.add(new MenuUnifiedInbox()); - menuItems.add(new ManageFiltersSection("FILTERS (EDIT)")); + menuItems.add(new MenuSection(context.getString(R.string.navigation_drawer_start))); + menuItems.add(new MenuUnifiedInbox(context)); + menuItems.add(new ManageFiltersSection(context.getString(R.string.navigation_drawer_edit_filters))); for(Filter f : FiltersList.getInstance(context).getFilters()) { menuItems.add(new MenuFilterItem(f)); } - menuItems.add(new ManageFeedsSection("FEEDS (EDIT)")); + menuItems.add(new ManageFeedsSection(context.getString(R.string.navigation_drawer_edit_feeds))); for(Feed f : FeedsList.getInstance(context).getFeeds()) { menuItems.add(new MenuFeedItem(f)); } - for(DataSetObserver observer : observers) { observer.onChanged(); @@ -181,57 +180,11 @@ class NavigationDrawerAdapter implements ListAdapter { } } - class FilterListMenuItem extends MenuItem - { - public FilterListMenuItem() - { - super("Manage filters..."); - } - - @Override - public int getItemViewType() { - return ITEM_VIEW_TYPE_NORMAL; - } - - @Override - public Fragment getFragment() { - return NavigationDrawerManageFiltersFragment.newInstance(); - } - - @Override - public int getPreferredMenuId() { - return R.menu.menu_filters; - } - } - - class FeedListMenuItem extends MenuItem - { - public FeedListMenuItem() - { - super("Manage feeds..."); - } - - @Override - public int getItemViewType() { - return ITEM_VIEW_TYPE_NORMAL; - } - - @Override - public Fragment getFragment() { - return NavigationDrawerManageFeedsFragment.newInstance(); - } - - @Override - public int getPreferredMenuId() { - return R.menu.menu_feeds; - } - } - class MenuUnifiedInbox extends MenuItem { - public MenuUnifiedInbox() + public MenuUnifiedInbox(Context context) { - super("All feeds"); + super(context.getString(R.string.navigation_drawer_all_feeds)); } @Override diff --git a/app/src/main/java/org/rssin/neurons/FeedSorter.java b/app/src/main/java/org/rssin/neurons/FeedSorter.java index 4a8fe7e..8887b99 100755 --- a/app/src/main/java/org/rssin/neurons/FeedSorter.java +++ b/app/src/main/java/org/rssin/neurons/FeedSorter.java @@ -151,17 +151,21 @@ public class FeedSorter implements Storable { * @param feedback The feedback. Like will move these types of items up in the list, * dislike will move them down. */ - public void feedback(FeedItem item, Feedback feedback) { + public TrainingCase feedback(FeedItem item, Feedback feedback) { + TrainingCase trainingCase; Log.d("FeedSorter", "Collected feedback: " + feedback.toString()); PredictionInterface prediction = getPrediction(item); prediction.learn(feedback.toExpectedOutput()); - trainingCases.add(new TrainingCase(prediction.getInputs(), feedback)); + trainingCase = new TrainingCase(prediction.getInputs(), feedback); + trainingCases.add(trainingCase); final int MAX_TRAINING_HISTORY = 250; while (trainingCases.size() > MAX_TRAINING_HISTORY) { trainingCases.remove(0); } + + return trainingCase; } /** diff --git a/app/src/main/java/org/rssin/neurons/TrainingCase.java b/app/src/main/java/org/rssin/neurons/TrainingCase.java index 69f72cb..5c6172c 100755 --- a/app/src/main/java/org/rssin/neurons/TrainingCase.java +++ b/app/src/main/java/org/rssin/neurons/TrainingCase.java @@ -5,21 +5,26 @@ import java.io.Serializable; /** * @author Jos. */ -class TrainingCase implements Serializable { +public class TrainingCase implements Serializable { private static final long serialVersionUID = 0; private final double[] inputs; - private final Feedback feedback; + private Feedback feedback; public TrainingCase(double[] inputs, Feedback feedback) { this.inputs = inputs; this.feedback = feedback; } - public double[] getInputs() { + double[] getInputs() { return inputs; } public Feedback getFeedback() { return feedback; } + + public void setFeedback(Feedback feedback) + { + this.feedback = feedback; + } } diff --git a/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java b/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java index 2a69bfa..f96382a 100755 --- a/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java +++ b/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java @@ -6,6 +6,7 @@ import org.rssin.android.FeedSorterProvider; import org.rssin.android.FiltersList; import org.rssin.neurons.FeedSorter; import org.rssin.neurons.Feedback; +import org.rssin.neurons.TrainingCase; import org.rssin.rss.FeedItem; import java.io.Serializable; @@ -16,6 +17,7 @@ import java.io.Serializable; public class SortedFeedItemContainer implements Comparable, Serializable { private FeedItem feeditem; private long score; + private TrainingCase trainingCase; public SortedFeedItemContainer(FeedItem feeditem) { @@ -38,7 +40,12 @@ public class SortedFeedItemContainer implements ComparableUnknown author Published on: + All feeds + START + FILTERS (EDIT) + FEEDS (EDIT) + Feedback saved. -- cgit v1.2.3 From 9b5d0b1b08ae0656b832cfa49eb08d14718a0db7 Mon Sep 17 00:00:00 2001 From: zkwip Date: Wed, 10 Jun 2015 11:38:21 +0200 Subject: cleared up summary package --- .../main/java/org/rssin/summaries/BablukiAPI.java | 31 +- app/src/main/java/org/rssin/summaries/Special.java | 63 -- app/src/main/java/org/rssin/summaries/Stemmer.java | 874 --------------------- .../main/java/org/rssin/summaries/Stopword.java | 71 -- .../main/java/org/rssin/summaries/SummaryAPI.java | 368 --------- .../main/java/org/rssin/summaries/TxtStatic.java | 33 - app/src/main/java/org/rssin/summaries/tester.java | 53 -- 7 files changed, 7 insertions(+), 1486 deletions(-) delete mode 100644 app/src/main/java/org/rssin/summaries/Special.java delete mode 100644 app/src/main/java/org/rssin/summaries/Stemmer.java delete mode 100644 app/src/main/java/org/rssin/summaries/Stopword.java delete mode 100644 app/src/main/java/org/rssin/summaries/SummaryAPI.java delete mode 100644 app/src/main/java/org/rssin/summaries/TxtStatic.java delete mode 100644 app/src/main/java/org/rssin/summaries/tester.java diff --git a/app/src/main/java/org/rssin/summaries/BablukiAPI.java b/app/src/main/java/org/rssin/summaries/BablukiAPI.java index 417a807..2617262 100644 --- a/app/src/main/java/org/rssin/summaries/BablukiAPI.java +++ b/app/src/main/java/org/rssin/summaries/BablukiAPI.java @@ -27,7 +27,7 @@ public class BablukiAPI implements SummaryAPIInterface{ private boolean stripHtml; /** - * + * constructor */ public BablukiAPI() { @@ -76,16 +76,11 @@ public class BablukiAPI implements SummaryAPIInterface{ */ private String getSumText(String content, String title) { - if (content.isEmpty()) - android.util.Log.d("No text to summarize", title); - SentenceScore[] ranks = getSentenceRanks(content); - String[] paragraphs = splitIntoParagraphs(content); - - - //choose sentences + String[] paragraphs = splitIntoParagraphs(content); + //choose sentences ArrayList sents = new ArrayList(); for(String p: paragraphs) @@ -99,8 +94,7 @@ public class BablukiAPI implements SummaryAPIInterface{ int senc = sents.size(); - //reduce if neccesairy - + //shorten the summary if needed ArrayList sents_bu = (ArrayList)sents.clone(); while((lm == LengthMode.LINES || lm == LengthMode.BOTH) && sents.size() > maxlines) { @@ -110,8 +104,7 @@ public class BablukiAPI implements SummaryAPIInterface{ while((lm == LengthMode.CHARACTERS || lm == LengthMode.BOTH) && getTotalSize(sents, sep) > maxchars) removeLeastSentences(sents, ranks); - //output the sentences. - + //output the sentences. String o = ""; for(String p: sents) @@ -124,16 +117,9 @@ public class BablukiAPI implements SummaryAPIInterface{ } if (o.isEmpty()) { - if (senc == 0) - android.util.Log.d("Empty summary", "No sentences could be found: " + title); - else if (sents.size() == 0) - android.util.Log.d("Empty summary", "None of the found sentences fits the summary limit: " + title); - else - android.util.Log.d("Empty summary", "all sentences are empty: " + title); return title; } return o; - } /** @@ -187,7 +173,6 @@ public class BablukiAPI implements SummaryAPIInterface{ } } return index; - } private void removeLeastSentences(ArrayList sentences, SentenceScore[] ranks) @@ -234,8 +219,7 @@ public class BablukiAPI implements SummaryAPIInterface{ } ss[i] = s; } - return ss; - + return ss; } private String[] splitIntoParagraphs(String content) @@ -365,6 +349,5 @@ public class BablukiAPI implements SummaryAPIInterface{ @Override public void setMaxLines(int lines) { maxlines = lines; - } - + } } diff --git a/app/src/main/java/org/rssin/summaries/Special.java b/app/src/main/java/org/rssin/summaries/Special.java deleted file mode 100644 index b367ee5..0000000 --- a/app/src/main/java/org/rssin/summaries/Special.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.rssin.summaries; - -import java.io.*; -import java.util.StringTokenizer; - -/** - * - * @author jbernards - */ -public class Special { - - char spch[]; - - /** - * constructor. - */ - public Special() { - spch = new TxtStatic().getSpecial(); - } - - /** - * devides the sentence into different words. - * - * @param sen the sentence string - * @return the first letter of each word. - */ - public char[] getTokens(String sen) { - - String[] sp = sen.split(" "); - char[] words = new char[sp.length]; - for(int i = 0; i < sp.length; i++) - { - words[i] = sp[i].charAt(0); - } - - return words; - } - - /** - * removes special words for a give sentence - * - * @param sen sentence - * @return sentences with the words removed. - */ - public String remove(String sen) { - String dsen = sen; - - for (int j = 0; j < spch.length; j++) { - - char csh[] = dsen.toCharArray(); - dsen = ""; - for (int i = 0; i < csh.length; i++) { - if (csh[i] != spch[j]) { - dsen = dsen + csh[i]; - } - } - - } - - return dsen; - } - -} diff --git a/app/src/main/java/org/rssin/summaries/Stemmer.java b/app/src/main/java/org/rssin/summaries/Stemmer.java deleted file mode 100644 index 54a64fb..0000000 --- a/app/src/main/java/org/rssin/summaries/Stemmer.java +++ /dev/null @@ -1,874 +0,0 @@ -package org.rssin.summaries; - -import java.util.*; - -/** - * - * @author jbernards - */ -public class Stemmer { - - private static boolean m_CompMode = false; - private static HashMap m_l11 = null; - private static HashMap m_l10 = null; - private static HashMap m_l9 = null; - private static HashMap m_l8 = null; - private static HashMap m_l7 = null; - private static HashMap m_l6 = null; - private static HashMap m_l5 = null; - private static HashMap m_l4 = null; - private static HashMap m_l3 = null; - private static HashMap m_l2 = null; - private static HashMap m_l1 = null; - - static { - - m_l11 = new HashMap(); - m_l11.put("alistically", "B"); - m_l11.put("arizability", "A"); - m_l11.put("izationally", "B"); - m_l10 = new HashMap(); - m_l10.put("antialness", "A"); - m_l10.put("arisations", "A"); - m_l10.put("arizations", "A"); - m_l10.put("entialness", "A"); - m_l9 = new HashMap(); - m_l9.put("allically", "C"); - m_l9.put("antaneous", "A"); - m_l9.put("antiality", "A"); - m_l9.put("arisation", "A"); - m_l9.put("arization", "A"); - m_l9.put("ationally", "B"); - m_l9.put("ativeness", "A"); - m_l9.put("eableness", "E"); - m_l9.put("entations", "A"); - m_l9.put("entiality", "A"); - m_l9.put("entialize", "A"); - m_l9.put("entiation", "A"); - m_l9.put("ionalness", "A"); - m_l9.put("istically", "A"); - m_l9.put("itousness", "A"); - m_l9.put("izability", "A"); - m_l9.put("izational", "A"); - m_l8 = new HashMap(); - m_l8.put("ableness", "A"); - m_l8.put("arizable", "A"); - m_l8.put("entation", "A"); - m_l8.put("entially", "A"); - m_l8.put("eousness", "A"); - m_l8.put("ibleness", "A"); - m_l8.put("icalness", "A"); - m_l8.put("ionalism", "A"); - m_l8.put("ionality", "A"); - m_l8.put("ionalize", "A"); - m_l8.put("iousness", "A"); - m_l8.put("izations", "A"); - m_l8.put("lessness", "A"); - m_l7 = new HashMap(); - m_l7.put("ability", "A"); - m_l7.put("aically", "A"); - m_l7.put("alistic", "B"); - m_l7.put("alities", "A"); - m_l7.put("ariness", "E"); - m_l7.put("aristic", "A"); - m_l7.put("arizing", "A"); - m_l7.put("ateness", "A"); - m_l7.put("atingly", "A"); - m_l7.put("ational", "B"); - m_l7.put("atively", "A"); - m_l7.put("ativism", "A"); - m_l7.put("elihood", "E"); - m_l7.put("encible", "A"); - m_l7.put("entally", "A"); - m_l7.put("entials", "A"); - m_l7.put("entiate", "A"); - m_l7.put("entness", "A"); - m_l7.put("fulness", "A"); - m_l7.put("ibility", "A"); - m_l7.put("icalism", "A"); - m_l7.put("icalist", "A"); - m_l7.put("icality", "A"); - m_l7.put("icalize", "A"); - m_l7.put("ication", "G"); - m_l7.put("icianry", "A"); - m_l7.put("ination", "A"); - m_l7.put("ingness", "A"); - m_l7.put("ionally", "A"); - m_l7.put("isation", "A"); - m_l7.put("ishness", "A"); - m_l7.put("istical", "A"); - m_l7.put("iteness", "A"); - m_l7.put("iveness", "A"); - m_l7.put("ivistic", "A"); - m_l7.put("ivities", "A"); - m_l7.put("ization", "F"); - m_l7.put("izement", "A"); - m_l7.put("oidally", "A"); - m_l7.put("ousness", "A"); - m_l6 = new HashMap(); - m_l6.put("aceous", "A"); - m_l6.put("acious", "B"); - m_l6.put("action", "G"); - m_l6.put("alness", "A"); - m_l6.put("ancial", "A"); - m_l6.put("ancies", "A"); - m_l6.put("ancing", "B"); - m_l6.put("ariser", "A"); - m_l6.put("arized", "A"); - m_l6.put("arizer", "A"); - m_l6.put("atable", "A"); - m_l6.put("ations", "B"); - m_l6.put("atives", "A"); - m_l6.put("eature", "Z"); - m_l6.put("efully", "A"); - m_l6.put("encies", "A"); - m_l6.put("encing", "A"); - m_l6.put("ential", "A"); - m_l6.put("enting", "C"); - m_l6.put("entist", "A"); - m_l6.put("eously", "A"); - m_l6.put("ialist", "A"); - m_l6.put("iality", "A"); - m_l6.put("ialize", "A"); - m_l6.put("ically", "A"); - m_l6.put("icance", "A"); - m_l6.put("icians", "A"); - m_l6.put("icists", "A"); - m_l6.put("ifully", "A"); - m_l6.put("ionals", "A"); - m_l6.put("ionate", "D"); - m_l6.put("ioning", "A"); - m_l6.put("ionist", "A"); - m_l6.put("iously", "A"); - m_l6.put("istics", "A"); - m_l6.put("izable", "E"); - m_l6.put("lessly", "A"); - m_l6.put("nesses", "A"); - m_l6.put("oidism", "A"); - m_l5 = new HashMap(); - m_l5.put("acies", "A"); - m_l5.put("acity", "A"); - m_l5.put("aging", "B"); - m_l5.put("aical", "A"); - if (!m_CompMode) { - m_l5.put("alist", "A"); - } - m_l5.put("alism", "B"); - m_l5.put("ality", "A"); - m_l5.put("alize", "A"); - m_l5.put("allic", "b"); - m_l5.put("anced", "B"); - m_l5.put("ances", "B"); - m_l5.put("antic", "C"); - m_l5.put("arial", "A"); - m_l5.put("aries", "A"); - m_l5.put("arily", "A"); - m_l5.put("arity", "B"); - m_l5.put("arize", "A"); - m_l5.put("aroid", "A"); - m_l5.put("ately", "A"); - m_l5.put("ating", "I"); - m_l5.put("ation", "B"); - m_l5.put("ative", "A"); - m_l5.put("ators", "A"); - m_l5.put("atory", "A"); - m_l5.put("ature", "E"); - m_l5.put("early", "Y"); - m_l5.put("ehood", "A"); - m_l5.put("eless", "A"); - if (!m_CompMode) { - m_l5.put("elily", "A"); - } else { - m_l5.put("elity", "A"); - } - m_l5.put("ement", "A"); - m_l5.put("enced", "A"); - m_l5.put("ences", "A"); - m_l5.put("eness", "E"); - m_l5.put("ening", "E"); - m_l5.put("ental", "A"); - m_l5.put("ented", "C"); - m_l5.put("ently", "A"); - m_l5.put("fully", "A"); - m_l5.put("ially", "A"); - m_l5.put("icant", "A"); - m_l5.put("ician", "A"); - m_l5.put("icide", "A"); - m_l5.put("icism", "A"); - m_l5.put("icist", "A"); - m_l5.put("icity", "A"); - m_l5.put("idine", "I"); - m_l5.put("iedly", "A"); - m_l5.put("ihood", "A"); - m_l5.put("inate", "A"); - m_l5.put("iness", "A"); - m_l5.put("ingly", "B"); - m_l5.put("inism", "J"); - m_l5.put("inity", "c"); - m_l5.put("ional", "A"); - m_l5.put("ioned", "A"); - m_l5.put("ished", "A"); - m_l5.put("istic", "A"); - m_l5.put("ities", "A"); - m_l5.put("itous", "A"); - m_l5.put("ively", "A"); - m_l5.put("ivity", "A"); - m_l5.put("izers", "F"); - m_l5.put("izing", "F"); - m_l5.put("oidal", "A"); - m_l5.put("oides", "A"); - m_l5.put("otide", "A"); - m_l5.put("ously", "A"); - m_l4 = new HashMap(); - m_l4.put("able", "A"); - m_l4.put("ably", "A"); - m_l4.put("ages", "B"); - m_l4.put("ally", "B"); - m_l4.put("ance", "B"); - m_l4.put("ancy", "B"); - m_l4.put("ants", "B"); - m_l4.put("aric", "A"); - m_l4.put("arly", "K"); - m_l4.put("ated", "I"); - m_l4.put("ates", "A"); - m_l4.put("atic", "B"); - m_l4.put("ator", "A"); - m_l4.put("ealy", "Y"); - m_l4.put("edly", "E"); - m_l4.put("eful", "A"); - m_l4.put("eity", "A"); - m_l4.put("ence", "A"); - m_l4.put("ency", "A"); - m_l4.put("ened", "E"); - m_l4.put("enly", "E"); - m_l4.put("eous", "A"); - m_l4.put("hood", "A"); - m_l4.put("ials", "A"); - m_l4.put("ians", "A"); - m_l4.put("ible", "A"); - m_l4.put("ibly", "A"); - m_l4.put("ical", "A"); - m_l4.put("ides", "L"); - m_l4.put("iers", "A"); - m_l4.put("iful", "A"); - m_l4.put("ines", "M"); - m_l4.put("ings", "N"); - m_l4.put("ions", "B"); - m_l4.put("ious", "A"); - m_l4.put("isms", "B"); - m_l4.put("ists", "A"); - m_l4.put("itic", "H"); - m_l4.put("ized", "F"); - m_l4.put("izer", "F"); - m_l4.put("less", "A"); - m_l4.put("lily", "A"); - m_l4.put("ness", "A"); - m_l4.put("ogen", "A"); - m_l4.put("ward", "A"); - m_l4.put("wise", "A"); - m_l4.put("ying", "B"); - m_l4.put("yish", "A"); - m_l3 = new HashMap(); - m_l3.put("acy", "A"); - m_l3.put("age", "B"); - m_l3.put("aic", "A"); - m_l3.put("als", "b"); - m_l3.put("ant", "B"); - m_l3.put("ars", "O"); - m_l3.put("ary", "F"); - m_l3.put("ata", "A"); - m_l3.put("ate", "A"); - m_l3.put("eal", "Y"); - m_l3.put("ear", "Y"); - m_l3.put("ely", "E"); - m_l3.put("ene", "E"); - m_l3.put("ent", "C"); - m_l3.put("ery", "E"); - m_l3.put("ese", "A"); - m_l3.put("ful", "A"); - m_l3.put("ial", "A"); - m_l3.put("ian", "A"); - m_l3.put("ics", "A"); - m_l3.put("ide", "L"); - m_l3.put("ied", "A"); - m_l3.put("ier", "A"); - m_l3.put("ies", "P"); - m_l3.put("ily", "A"); - m_l3.put("ine", "M"); - m_l3.put("ing", "N"); - m_l3.put("ion", "Q"); - m_l3.put("ish", "C"); - m_l3.put("ism", "B"); - m_l3.put("ist", "A"); - m_l3.put("ite", "a"); - m_l3.put("ity", "A"); - m_l3.put("ium", "A"); - m_l3.put("ive", "A"); - m_l3.put("ize", "F"); - m_l3.put("oid", "A"); - m_l3.put("one", "R"); - m_l3.put("ous", "A"); - m_l2 = new HashMap(); - m_l2.put("ae", "A"); - m_l2.put("al", "b"); - m_l2.put("ar", "X"); - m_l2.put("as", "B"); - m_l2.put("ed", "E"); - m_l2.put("en", "F"); - m_l2.put("es", "E"); - m_l2.put("ia", "A"); - m_l2.put("ic", "A"); - m_l2.put("is", "A"); - m_l2.put("ly", "B"); - m_l2.put("on", "S"); - m_l2.put("or", "T"); - m_l2.put("um", "U"); - m_l2.put("us", "V"); - m_l2.put("yl", "R"); - m_l2.put("s\'", "A"); - m_l2.put("\'s", "A"); - m_l1 = new HashMap(); - m_l1.put("a", "A"); - m_l1.put("e", "A"); - m_l1.put("i", "A"); - m_l1.put("o", "A"); - m_l1.put("s", "W"); - m_l1.put("y", "B"); - } - - private String removeEnding(String word) { - - int length = word.length(); - int el = 11; - - while (el > 0) { - if (length - el > 1) { - String ending = word.substring(length - el); - String conditionCode = null; - switch (el) { - case 11: - conditionCode = (String) m_l11.get(ending); - break; - case 10: - conditionCode = (String) m_l10.get(ending); - break; - case 9: - conditionCode = (String) m_l9.get(ending); - break; - case 8: - conditionCode = (String) m_l8.get(ending); - break; - case 7: - conditionCode = (String) m_l7.get(ending); - break; - case 6: - conditionCode = (String) m_l6.get(ending); - break; - case 5: - conditionCode = (String) m_l5.get(ending); - break; - case 4: - conditionCode = (String) m_l4.get(ending); - break; - case 3: - conditionCode = (String) m_l3.get(ending); - break; - case 2: - conditionCode = (String) m_l2.get(ending); - break; - case 1: - conditionCode = (String) m_l1.get(ending); - break; - default: - } - if (conditionCode != null) { - switch (conditionCode.charAt(0)) { - case 'A': - return word.substring(0, length - el); - case 'B': - if (length - el > 2) { - return word.substring(0, length - el); - } - break; - case 'C': - if (length - el > 3) { - return word.substring(0, length - el); - } - break; - case 'D': - if (length - el > 4) { - return word.substring(0, length - el); - } - break; - case 'E': - if (word.charAt(length - el - 1) != 'e') { - return word.substring(0, length - el); - } - break; - case 'F': - if ((length - el > 2) - && (word.charAt(length - el - 1) != 'e')) { - return word.substring(0, length - el); - } - break; - case 'G': - if ((length - el > 2) - && (word.charAt(length - el - 1) == 'f')) { - return word.substring(0, length - el); - } - break; - case 'H': - if ((word.charAt(length - el - 1) == 't') - || ((word.charAt(length - el - 1) == 'l') - && (word.charAt(length - el - 2) == 'l'))) { - return word.substring(0, length - el); - } - break; - case 'I': - if ((word.charAt(length - el - 1) != 'o') - && (word.charAt(length - el - 1) != 'e')) { - return word.substring(0, length - el); - } - break; - case 'J': - if ((word.charAt(length - el - 1) != 'a') - && (word.charAt(length - el - 1) != 'e')) { - return word.substring(0, length - el); - } - break; - case 'K': - if ((length - el > 2) - && ((word.charAt(length - el - 1) == 'l') - || (word.charAt(length - el - 1) == 'i') - || ((word.charAt(length - el - 1) == 'e') - && (word.charAt(length - el - 3) == 'u')))) { - return word.substring(0, length - el); - } - break; - case 'L': - if ((word.charAt(length - el - 1) != 'u') - && (word.charAt(length - el - 1) != 'x') - && ((word.charAt(length - el - 1) != 's') - || (word.charAt(length - el - 2) == 'o'))) { - return word.substring(0, length - el); - } - break; - case 'M': - if ((word.charAt(length - el - 1) != 'a') - && (word.charAt(length - el - 1) != 'c') - && (word.charAt(length - el - 1) != 'e') - && (word.charAt(length - el - 1) != 'm')) { - return word.substring(0, length - el); - } - break; - case 'N': - if ((length - el > 3) - || ((length - el == 3) - && ((word.charAt(length - el - 3) != 's')))) { - return word.substring(0, length - el); - } - break; - case 'O': - if ((word.charAt(length - el - 1) == 'l') - || (word.charAt(length - el - 1) == 'i')) { - return word.substring(0, length - el); - } - break; - case 'P': - if (word.charAt(length - el - 1) != 'c') { - return word.substring(0, length - el); - } - break; - case 'Q': - if ((length - el > 2) - && (word.charAt(length - el - 1) != 'l') - && (word.charAt(length - el - 1) != 'n')) { - return word.substring(0, length - el); - } - break; - case 'R': - if ((word.charAt(length - el - 1) == 'n') - || (word.charAt(length - el - 1) == 'r')) { - return word.substring(0, length - el); - } - break; - case 'S': - if (((word.charAt(length - el - 1) == 'r') - && (word.charAt(length - el - 2) == 'd')) - || ((word.charAt(length - el - 1) == 't') - && (word.charAt(length - el - 2) != 't'))) { - return word.substring(0, length - el); - } - break; - case 'T': - if ((word.charAt(length - el - 1) == 's') - || ((word.charAt(length - el - 1) == 't') - && (word.charAt(length - el - 2) != 'o'))) { - return word.substring(0, length - el); - } - break; - case 'U': - if ((word.charAt(length - el - 1) == 'l') - || (word.charAt(length - el - 1) == 'm') - || (word.charAt(length - el - 1) == 'n') - || (word.charAt(length - el - 1) == 'r')) { - return word.substring(0, length - el); - } - break; - case 'V': - if (word.charAt(length - el - 1) == 'c') { - return word.substring(0, length - el); - } - break; - case 'W': - if ((word.charAt(length - el - 1) != 's') - && (word.charAt(length - el - 1) != 'u')) { - return word.substring(0, length - el); - } - break; - case 'X': - if ((word.charAt(length - el - 1) == 'l') - || (word.charAt(length - el - 1) == 'i') - || ((length - el > 2) - && (word.charAt(length - el - 1) == 'e') - && (word.charAt(length - el - 3) == 'u'))) { - return word.substring(0, length - el); - } - break; - case 'Y': - if ((word.charAt(length - el - 1) == 'n') - && (word.charAt(length - el - 2) == 'i')) { - return word.substring(0, length - el); - } - break; - case 'Z': - if (word.charAt(length - el - 1) != 'f') { - return word.substring(0, length - el); - } - break; - case 'a': - if ((word.charAt(length - el - 1) == 'd') - || (word.charAt(length - el - 1) == 'f') - || (((word.charAt(length - el - 1) == 'h') - && (word.charAt(length - el - 2) == 'p'))) - || (((word.charAt(length - el - 1) == 'h') - && (word.charAt(length - el - 2) == 't'))) - || (word.charAt(length - el - 1) == 'l') - || (((word.charAt(length - el - 1) == 'r') - && (word.charAt(length - el - 2) == 'e'))) - || (((word.charAt(length - el - 1) == 'r') - && (word.charAt(length - el - 2) == 'o'))) - || (((word.charAt(length - el - 1) == 's') - && (word.charAt(length - el - 2) == 'e'))) - || (word.charAt(length - el - 1) == 't')) { - return word.substring(0, length - el); - } - break; - case 'b': - if (m_CompMode) { - if (((length - el == 3) - && (!((word.charAt(length - el - 1) == 't') - && (word.charAt(length - el - 2) == 'e') - && (word.charAt(length - el - 3) == 'm')))) - || ((length - el > 3) - && (!((word.charAt(length - el - 1) == 't') - && (word.charAt(length - el - 2) == 's') - && (word.charAt(length - el - 3) == 'y') - && (word.charAt(length - el - 4) == 'r'))))) { - return word.substring(0, length - el); - } - } else { - if ((length - el > 2) - && (!((word.charAt(length - el - 1) == 't') - && (word.charAt(length - el - 2) == 'e') - && (word.charAt(length - el - 3) == 'm'))) - && ((length - el < 4) - || (!((word.charAt(length - el - 1) == 't') - && (word.charAt(length - el - 2) == 's') - && (word.charAt(length - el - 3) == 'y') - && (word.charAt(length - el - 4) == 'r'))))) { - return word.substring(0, length - el); - } - } - break; - case 'c': - if (word.charAt(length - el - 1) == 'l') { - return word.substring(0, length - el); - } - break; - default: - throw new IllegalArgumentException("Fatal error."); - } - } - } - el--; - } - return word; - } - - private String recodeEnding(String word) { - - int lastPos = word.length() - 1; - - // Rule 1 - if (word.endsWith("bb") - || word.endsWith("dd") - || word.endsWith("gg") - || word.endsWith("ll") - || word.endsWith("mm") - || word.endsWith("nn") - || word.endsWith("pp") - || word.endsWith("rr") - || word.endsWith("ss") - || word.endsWith("tt")) { - word = word.substring(0, lastPos); - lastPos--; - } - - // Rule 2 - if (word.endsWith("iev")) { - word = word.substring(0, lastPos - 2).concat("ief"); - } - - // Rule 3 - if (word.endsWith("uct")) { - word = word.substring(0, lastPos - 2).concat("uc"); - lastPos--; - } - - // Rule 4 - if (word.endsWith("umpt")) { - word = word.substring(0, lastPos - 3).concat("um"); - lastPos -= 2; - } - - // Rule 5 - if (word.endsWith("rpt")) { - word = word.substring(0, lastPos - 2).concat("rb"); - lastPos--; - } - - // Rule 6 - if (word.endsWith("urs")) { - word = word.substring(0, lastPos - 2).concat("ur"); - lastPos--; - } - - // Rule 7 - if (word.endsWith("istr")) { - word = word.substring(0, lastPos - 3).concat("ister"); - lastPos++; - } - - // Rule 7a - if (word.endsWith("metr")) { - word = word.substring(0, lastPos - 3).concat("meter"); - lastPos++; - } - - // Rule 8 - if (word.endsWith("olv")) { - word = word.substring(0, lastPos - 2).concat("olut"); - lastPos++; - } - - // Rule 9 - if (word.endsWith("ul")) { - if ((lastPos - 2 < 0) - || ((word.charAt(lastPos - 2) != 'a') - && (word.charAt(lastPos - 2) != 'i') - && (word.charAt(lastPos - 2) != 'o'))) { - word = word.substring(0, lastPos - 1).concat("l"); - lastPos--; - } - } - - // Rule 10 - if (word.endsWith("bex")) { - word = word.substring(0, lastPos - 2).concat("bic"); - } - - // Rule 11 - if (word.endsWith("dex")) { - word = word.substring(0, lastPos - 2).concat("dic"); - } - - // Rule 12 - if (word.endsWith("pex")) { - word = word.substring(0, lastPos - 2).concat("pic"); - } - - // Rule 13 - if (word.endsWith("tex")) { - word = word.substring(0, lastPos - 2).concat("tic"); - } - - // Rule 14 - if (word.endsWith("ax")) { - word = word.substring(0, lastPos - 1).concat("ac"); - } - - // Rule 15 - if (word.endsWith("ex")) { - word = word.substring(0, lastPos - 1).concat("ec"); - } - - // Rule 16 - if (word.endsWith("ix")) { - word = word.substring(0, lastPos - 1).concat("ic"); - } - - // Rule 17 - if (word.endsWith("lux")) { - word = word.substring(0, lastPos - 2).concat("luc"); - } - - // Rule 18 - if (word.endsWith("uad")) { - word = word.substring(0, lastPos - 2).concat("uas"); - } - - // Rule 19 - if (word.endsWith("vad")) { - word = word.substring(0, lastPos - 2).concat("vas"); - } - - // Rule 20 - if (word.endsWith("cid")) { - word = word.substring(0, lastPos - 2).concat("cis"); - } - - // Rule 21 - if (word.endsWith("lid")) { - word = word.substring(0, lastPos - 2).concat("lis"); - } - - // Rule 22 - if (word.endsWith("erid")) { - word = word.substring(0, lastPos - 3).concat("eris"); - } - - // Rule 23 - if (word.endsWith("pand")) { - word = word.substring(0, lastPos - 3).concat("pans"); - } - - // Rule 24 - if (word.endsWith("end")) { - if ((lastPos - 3 < 0) - || (word.charAt(lastPos - 3) != 's')) { - word = word.substring(0, lastPos - 2).concat("ens"); - } - } - - // Rule 25 - if (word.endsWith("ond")) { - word = word.substring(0, lastPos - 2).concat("ons"); - } - - // Rule 26 - if (word.endsWith("lud")) { - word = word.substring(0, lastPos - 2).concat("lus"); - } - - // Rule 27 - if (word.endsWith("rud")) { - word = word.substring(0, lastPos - 2).concat("rus"); - } - - // Rule 28 - if (word.endsWith("her")) { - if ((lastPos - 3 < 0) - || ((word.charAt(lastPos - 3) != 'p') - && (word.charAt(lastPos - 3) != 't'))) { - word = word.substring(0, lastPos - 2).concat("hes"); - } - } - - // Rule 29 - if (word.endsWith("mit")) { - word = word.substring(0, lastPos - 2).concat("mis"); - } - - // Rule 30 - if (word.endsWith("end")) { - if ((lastPos - 3 < 0) - || (word.charAt(lastPos - 3) != 'm')) { - word = word.substring(0, lastPos - 2).concat("ens"); - } - } - - // Rule 31 - if (word.endsWith("ert")) { - word = word.substring(0, lastPos - 2).concat("ers"); - } - - // Rule 32 - if (word.endsWith("et")) { - if ((lastPos - 2 < 0) - || (word.charAt(lastPos - 2) != 'n')) { - word = word.substring(0, lastPos - 1).concat("es"); - } - } - - // Rule 33 - if (word.endsWith("yt")) { - word = word.substring(0, lastPos - 1).concat("ys"); - } - - // Rule 34 - if (word.endsWith("yz")) { - word = word.substring(0, lastPos - 1).concat("ys"); - } - - return word; - } - - /** - * - * @param word - * @return - */ - public String stem(String word) { - - if (word.length() > 2) { - return recodeEnding(removeEnding(word.toLowerCase())); - } else { - return word.toLowerCase(); - } - } - - /** - * - * @param str - * @return - */ - public String stemString(String str) { - - StringBuffer result = new StringBuffer(); - int start = -1; - for (int j = 0; j < str.length(); j++) { - char c = str.charAt(j); - if (Character.isLetterOrDigit(c)) { - if (start == -1) { - start = j; - } - } else if (c == '\'') { - if (start == -1) { - result.append(c); - } - } else { - if (start != -1) { - result.append(stem(str.substring(start, j))); - start = -1; - } - result.append(c); - } - } - if (start != -1) { - result.append(stem(str.substring(start, str.length()))); - } - return result.toString(); - } - -} diff --git a/app/src/main/java/org/rssin/summaries/Stopword.java b/app/src/main/java/org/rssin/summaries/Stopword.java deleted file mode 100644 index e43d3bd..0000000 --- a/app/src/main/java/org/rssin/summaries/Stopword.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.rssin.summaries; - -import java.io.*; -import java.util.StringTokenizer; - -/** - * - * @author jbernards - */ -public class Stopword { - - String stwd[]; - - /** - * - */ - public Stopword() { - stwd = new TxtStatic().getStopWords(); - } - - /** - * - * @param word - * @return - */ - public boolean isStopword(String word) { - boolean flag = false; - for (int i = 0; i < stwd.length; i++) { - if (stwd[i].equalsIgnoreCase(word)) { - flag = true; - break; - } - } - return flag; - } - - /** - * - * @param sen - * @return - */ - public String[] getTokens(String sen) { - int sz = 0, cnt = 0; - String words[] = null; - StringTokenizer stk = new StringTokenizer(sen); - sz = stk.countTokens(); - words = new String[sz]; - while (stk.hasMoreTokens()) { - words[cnt] = new String(stk.nextToken()); - cnt++; - } - return words; - } - - /** - * - * @param sen - * @return - */ - public String remove(String sen) { - String dsen = ""; - String words[] = getTokens(sen); - for (int j = 0; j < words.length; j++) { - if (!isStopword(words[j])) { - dsen = dsen + words[j] + " "; - } - } - return dsen; - } - -} diff --git a/app/src/main/java/org/rssin/summaries/SummaryAPI.java b/app/src/main/java/org/rssin/summaries/SummaryAPI.java deleted file mode 100644 index 780e613..0000000 --- a/app/src/main/java/org/rssin/summaries/SummaryAPI.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.rssin.summaries; - -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Set; -import org.rssin.rss.FeedItem; - -/** - * Summary API van AST - * - * @author Joep - */ -public class SummaryAPI implements SummaryAPIInterface { - - LengthMode lm; - int maxchars, maxlines; - - /** - * get a Summary object from a feedItem, using the settings specified. - * - * @param f FeedItem containing the text to summarize. - * @return The summary - */ - @Override - public Summary getSummary(FeedItem f) { - //todo - String desc = f.getDescription(); - String t = getSumText(desc); - Summary s = new Summary(t); - - return s; - } - - @Override - public void setHtmlStrip(boolean b) - { - //meh - } - - /** - * Constructor - */ - public SummaryAPI() { - lm = LengthMode.NOLIMIT; - maxchars = Integer.MAX_VALUE; - maxlines = Integer.MAX_VALUE; - } - - /** - * Generates get a Summary object from a String, using the settings - * specified. - * - * @param desc the text to summarize - * @return The summary. - */ - @Override - public Summary getSummaryFromText(String desc) { - String t = getSumText(desc); - - Summary s = new Summary(t); - - return s; - } - - /** - * gets the summary string from a text string, using the settings specified. - * - * @param desc string to summarize - * @return the summary text. - */ - public String getSumText(String desc) { - Hashtable hs = new Hashtable(); - ArrayList zinnen = getSentences(desc); - - //remove stopwords - Stopword stop = new Stopword(); - Special specl = new Special(); - for (int i = 0; i < zinnen.size(); i++) { - SentenceItem sl = (SentenceItem) zinnen.get(i); - sl.setSRSentence(specl.remove(sl.getRawSentence())); - sl.setSRSentence(stop.remove(sl.getSRSentence())); - } - - //unique words - for (int i = 0; i < zinnen.size(); i++) { - SentenceItem sl = (SentenceItem) zinnen.get(i); - String sen = sl.getSRSentence(); - - int wordcount = 0; - String[] words = sen.split(" "); - - for (String tok : words) { - - tok = tok.trim(); - - wordcount++; - - if (!hs.containsKey(tok) && tok.length() >= 3) { - addword(tok, i, wordcount, hs); - } else if (hs.containsKey(tok)) { - upword(tok, i, wordcount, hs); - } - } - } - - //stemming - stemming(hs); - - //significant - Enumeration key = hs.keys(); - while (key.hasMoreElements()) { - delword(key.nextElement(), hs); - } - - //getWeight - key = hs.keys(); - while (key.hasMoreElements()) { - setWeight(key.nextElement(), hs, zinnen); - } - - //ranking + return :P - ranking(zinnen, hs); - - return chooseSentence(zinnen); - } - - private String chooseSentence(ArrayList zinnen) { - String output = ""; - int lines = zinnen.size(); - SentenceItem[] z = zinnen.toArray(new SentenceItem[0]); - if (lm == LengthMode.LINES || lm == LengthMode.BOTH) { - lines = Math.min(zinnen.size(), maxlines); - z = new SentenceItem[lines]; - for (int i = 0; i < zinnen.size(); i++) { - boolean placed = false; - int j = 0; - while (j < lines && !placed) { - if (z[j] == null) { - z[j] = zinnen.get(i); - placed = true; - } - j++; - } - j--; - - while (!placed && j >= 0) { - if (z[j].getWeight() > zinnen.get(i).getWeight()) { - z[j] = zinnen.get(i); - placed = true; - } - j--; - } - } - } - - if (lm == LengthMode.CHARACTERS || lm == LengthMode.BOTH) { - //todo - } - - for(SentenceItem zin : z) - { - output += zin.getRawSentence(); - } - - return output; - } - - private void setWeight(Object tok, Hashtable hs, ArrayList zinnen) { - double wg = 0.0; - WordItem wl = (WordItem) hs.get(tok); - double scnt = (double) zinnen.size(); - double tf = wl.getcount(); - double df = wl.sentensecount(); - wg = tf * Math.log10(scnt / df); - wl.addWeight(wg); - } - - /** - * - * @param zinnen - * @param hs - * @return - */ - public String ranking(ArrayList zinnen, Hashtable hs) { - SentenceItem sl = null; - double max = 0.0; - int mi = 0; - - for (int i = 0; i < zinnen.size(); i++) { - sl = zinnen.get(i); - String sen = sl.getSRSentence(); - Enumeration key = hs.keys(); - while (key.hasMoreElements()) { - String str = (String) key.nextElement(); - if (sen.indexOf(str) != -1) { - WordItem wl = (WordItem) hs.get(str); - sl.addWeight(wl.getWeight()); - } - } - } - - for (int i = 0; i < zinnen.size(); i++) { - sl = (SentenceItem) zinnen.get(i); - if (sl.getWeight() > max) { - max = sl.getWeight(); - mi = i; - } - } - - String str1 = sl.getRawSentence(); - sl = zinnen.get(mi); - - return str1; - } - - private void delword(Object tok, Hashtable hs) { - WordItem wl = (WordItem) hs.remove(tok); - if (wl.getcount() > 3) { - hs.put(tok, wl); - } - } - - private void stemword(String w1, String w2, Hashtable hs) { - if (!hs.containsKey(w2) || !hs.containsKey(w1)) { - // System.out.print("return:"); - return; - } - WordItem wl1 = (WordItem) hs.remove(w1); - WordItem wl2 = (WordItem) hs.remove(w2); - - ArrayList wp = wl2.getwordpos(); - ArrayList sp = wl2.getsentensepos(); - - for (int i = 0; i < wp.size(); i++) { - String wp2 = (String) wp.get(i); - String sp2 = (String) sp.get(i); - wl1.incrcount(Integer.parseInt(wp2), Integer.parseInt(sp2)); - } - - hs.put(w1, wl1); - } - - private double difpos(String str1, String str2) { - int sz = Math.min(str1.length(), str2.length()); - int mz = Math.max(str1.length(), str2.length()); - - double dp = mz; - double sm = 0; - - for (int i = 0; i < mz; i++) { - if (str1.charAt(i) != str2.charAt(i)) { - dp = i + 1; - break; - } else { - sm++; - } - } - return (sm * (dp / sz)); - } - - private void stemming(Hashtable hs) { - int sz = hs.size(); - - double wdis[][] = new double[sz][sz]; - - Set s1 = hs.keySet(); - - Object obj[] = s1.toArray(); - - for (int i = 0; i < sz; i++) { - String str1 = (String) obj[i]; - for (int j = 0; j < sz; j++) { - String str2 = (String) obj[j]; - if (i != j) { - wdis[i][j] = difpos(str1, str2); - } - } - } - - for (int i = 0; i < sz; i++) { - String str1 = (String) obj[i]; - for (int j = 0; j < sz; j++) { - String str2 = (String) obj[j]; - if (i != j && wdis[i][j] >= 3.0) { - stemword(str1, str2, hs); - } - } - } - } - - private void addword(String tok, int sp, int wp, Hashtable hs) { - WordItem wl = new WordItem(tok); - wl.incrcount(sp + 1, wp); - hs.put(tok, wl); - } - - private void upword(String tok, int sp, int wp, Hashtable hs) { - WordItem wl = (WordItem) hs.remove(tok); - wl.incrcount(sp + 1, wp); - hs.put(tok, wl); - } - - private ArrayList getSentences(String doc) { - ArrayList als = new ArrayList(); - - int fs1 = 0; - int fs2 = 0; - int nx = 0; - - while (nx < (doc.length() - 1)) { - nx = doc.indexOf(".", fs2); - if (nx == -1) { - break; - } else if (nx == doc.lastIndexOf(".")) { - String str = (doc.substring(fs1, nx + 1)).toLowerCase(); - als.add(new SentenceItem(str)); - fs2 = nx + 1; - fs1 = fs2; - break; - } else if (doc.charAt(nx + 1) == ' ' || doc.charAt(nx + 1) == '\r' || doc.charAt(nx + 1) == '\n') { - String str = (doc.substring(fs1, nx + 1).toLowerCase()).trim(); - als.add(new SentenceItem(str)); - fs2 = nx + 1; - fs1 = fs2; - } else { - fs2 = nx + 1; - } - } - - return als; - } - - /** - * set the lengthmode -_- - * - * @param l Mode to use. - */ - @Override - public void setLengthMode(LengthMode l) { - lm = l; - } - - /** - * set the maximum number of characters of the summary text. - * - * @param chars integer value of the amount. - */ - @Override - public void setMaxChars(int chars) { - maxchars = chars; - } - - /** - * set the maximum number of sentences of the summary text. - * - * @param lines integer value of the amount. - */ - @Override - public void setMaxLines(int lines) { - maxlines = lines; - } -} diff --git a/app/src/main/java/org/rssin/summaries/TxtStatic.java b/app/src/main/java/org/rssin/summaries/TxtStatic.java deleted file mode 100644 index e31bf8b..0000000 --- a/app/src/main/java/org/rssin/summaries/TxtStatic.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.rssin.summaries; - -/** - * - * @author Joep - */ -public class TxtStatic { - - private final String[] stopwords = {"a", "about", "above", "across", "after", "afterwards", "again", "against", "all", "almost", "alone", "along", "already", "also", "although", "always", "am", "among", "amongst", "amoungst", "amount", "an", "and", "another", "any", "anyhow", "anyone", "anything", "anyway", "anywhere", "are", "around", "as", "at", "back", "be", "became", "because", "become", "becomes", "becoming", "been", "before", "beforehand", "behind", "being", "below", "beside", "besides", "between", "beyond", "bill", "both", "bottom", "but", "by", "by", "call", "can", "common", "cannot", "cant", "co", "computer", "con", "could", "couldnt", "cry", "de", "describe", "detail", "do", "does", "done", "down", "due", "during", "each", "eg", "eight", "either", "eleven", "else", "elsewhere", "empty", "enough", "etc", "even", "ever", "every", "everyone", "everything", "everywhere", "except", "few", "fifteen", "fify", "fill", "find", "fire", "first", "five", "for", "former", "formerly", "forty", "found", "four", "from", "front", "full", "further", "get", "give", "go", "had", "has", "hasnt", "have", "he", "hence", "her", "here", "hereafter", "hereby", "herein", "hereupon", "hers", "herself", "him", "himself", "his", "how", "however", "hundred", "i", "ie", "if", "in", "inc", "indeed", "interest", "into", "is", "it", "its", "itself", "keep", "last", "latter", "latterly", "least", "less", "ltd", "made", "many", "may", "me", "meanwhile", "might", "mill", "mine", "more", "moreover", "most", "mostly", "move", "much", "must", "my", "myself", "name", "namely", "neither", "never", "nevertheless", "next", "nine", "no", "nobody", "none", "noone", "nor", "not", "nothing", "now", "nowhere", "of", "off", "often", "on", "once", "one", "only", "onto", "or", "other", "others", "otherwise", "our", "ours", "ourselves", "out", "over", "own", "part", "per", "perhaps", "please", "put", "rather", "re", "same", "see", "seem", "seemed", "seeming", "seems", "serious", "several", "she", "should", "show", "side", "since", "sincere", "six", "sixty", "so", "some", "somehow", "someone", "something", "sometime", "sometimes", "somewhere", "still", "such", "system", "take", "ten", "than", "that", "the", "their", "them", "themselves", "then", "thence", "there", "thereafter", "thereby", "therefore", "therein", "thereupon", "these", "they", "thick", "thin", "third", "this", "those", "though", "three", "through", "throughout", "thru", "thus", "to", "together", "too", "top", "toward", "towards", "twelve", "twenty", "two", "un", "under", "until", "up", "upon", "us", "usually", "usual", "very", "via", "was", "we", "well", "were", "what", "whatever", "when", "whence", "whenever", "where", "whereafter", "whereas", "whereby", "whereinwhereupon", "wherever", "whether", "which", "while", "whither", "who", "whoever", "whole", "whom", "whose", "why", "will", "with", "within", "without", "would", "yet", "you", "your", "yours", "yourself", "yourselves", "don't", "won't", "can't", "didn't", "it's", "is'nt", "aren't", "wasn't", "haven't", "hasn't", "hadn't", "you've", "it'hv", "you'd", "you're", "hasn't", "we�ll", "you�re", "we're", "we've"}; - - private final char[] special = {'"', ',', ';', '!', '&', '/', '$', ':', '|', '%', ')', '(', '[', ']', '�', '�', '\'', '.', ' ', '\n'}; - - /** - * - * @return - */ - public String[] getStopWords() { - return stopwords; - } - - /** - * - * @return - */ - public char[] getSpecial() { - return special; - } -} diff --git a/app/src/main/java/org/rssin/summaries/tester.java b/app/src/main/java/org/rssin/summaries/tester.java deleted file mode 100644 index c795c78..0000000 --- a/app/src/main/java/org/rssin/summaries/tester.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package org.rssin.summaries; - -import java.net.URL; -import java.util.Calendar; -import java.util.Scanner; -import org.rssin.rss.FeedItem; - -/** - * - * @author jbernards - */ -public class tester { - - /** - * @param args the command line arguments - */ - public static void main(String[] args) { - Scanner scanner = new Scanner(System.in); - - System.out.println("Voer een tekst in"); - String t = ""; - String s = ""; - - do { - t += s + "\n"; - s = scanner.nextLine(); - } while (!s.contains("#")); - - System.out.println("Tekst geaccepteerd."); - - SummaryAPIInterface sumo = new BablukiAPI(); - sumo.setLengthMode(LengthMode.LINES); - sumo.setMaxLines(2); - - System.out.println("Sumo ingesteld."); - - Summary su = sumo.getSummaryFromText(t); - String k = su.getText(); - - //k = k.trim(); - - System.out.println(k); - - System.out.println(k.length()); - System.out.println(t.length()); - } - -} -- cgit v1.2.3 From b8b188a42d39cc95013686a71459a792bf5bfa86 Mon Sep 17 00:00:00 2001 From: Size43 Date: Wed, 10 Jun 2015 11:39:50 +0200 Subject: Added comments to rssin.neurons.* --- .../main/java/org/rssin/neurons/FeedSorter.java | 22 ++++++++++++++ .../java/org/rssin/neurons/MultiNeuralNetwork.java | 21 +++++++++++++ .../neurons/MultiNeuralNetworkPrediction.java | 11 +++++++ .../main/java/org/rssin/neurons/NeuralNetwork.java | 34 +++++++++++++++++++++- .../org/rssin/neurons/NeuralNetworkPrediction.java | 14 +++++++++ app/src/main/java/org/rssin/neurons/Neuron.java | 18 ++++++++++++ .../org/rssin/neurons/PredictionInterface.java | 14 ++++++++- .../java/org/rssin/neurons/SentenceSplitter.java | 3 +- .../main/java/org/rssin/neurons/TrainingCase.java | 10 +++++++ .../java/org/rssin/rssin/FeedLoaderAndSorter.java | 12 ++++---- 10 files changed, 149 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/rssin/neurons/FeedSorter.java b/app/src/main/java/org/rssin/neurons/FeedSorter.java index 8887b99..660c546 100755 --- a/app/src/main/java/org/rssin/neurons/FeedSorter.java +++ b/app/src/main/java/org/rssin/neurons/FeedSorter.java @@ -19,6 +19,7 @@ import java.util.TimeZone; /** * @author Jos. + * Sorts lists of feeds based on the output of a neural network, using date/time + title + author + category as inputs. */ public class FeedSorter implements Storable { private static final long serialVersionUID = 0; @@ -64,6 +65,9 @@ public class FeedSorter implements Storable { authorInputs = (Hashtable) stream.readObject(); } + /** + * Initializes a new FeedSorter, and creates the basic inputs for the Neural network.4 + */ public FeedSorter() { biasInput = nn.addInput(); for (int i = 0; i < 12; i++) { @@ -80,6 +84,11 @@ public class FeedSorter implements Storable { isNight = nn.addInput(); } + /** + * Returns a prediction for the provided FeedItem. + * @param item The item to predict the interest of the user of. + * @return The prediction. + */ private PredictionInterface getPrediction(FeedItem item) { List words = splitter.splitSentence(item.getTitle()); @@ -123,18 +132,31 @@ public class FeedSorter implements Storable { return nn.computeOutput(inputs); } + /** + * @return a new array, the same size as the number of inputs, initialized to -1. + */ private double[] newArrayInitializedToNegativeOne() { double[] inputs = new double[nn.getInputCount()]; Arrays.fill(inputs, 0, inputs.length, -1); return inputs; } + /** + * Adds new inputs to the Neural Network + * @param words The string identifiers of the inputs. + * @param map The map of string identifiers to input IDs. This map is modified. + */ private void addNewInputs(Iterable words, Hashtable map) { for (String word : words) { addNewInput(word, map); } } + /** + * Adds a single new input to the neural network. + * @param word The string identifier. + * @param map The map op string identifiers to input IDs. This map is modified. + */ private void addNewInput(String word, Hashtable map) { if (word != null) { word = word.toLowerCase(); diff --git a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java index ece53a8..b53588b 100755 --- a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java +++ b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java @@ -21,6 +21,11 @@ class MultiNeuralNetwork implements Serializable { networks = SerializationTools.readArray(stream, NeuralNetwork.class); } + /** + * Creates a new instance of the MultiNeuralNetwork + * @param numNetworks The number of underlying networks. + * @param numHiddenNodes The number of hidden nodes each network has. + */ public MultiNeuralNetwork(int numNetworks, int numHiddenNodes) { networks = new NeuralNetwork[numNetworks]; for (int i = 0; i < networks.length; i++) { @@ -28,15 +33,26 @@ class MultiNeuralNetwork implements Serializable { } } + /** + * Calls addInput() on all NeuralNetworks. + * @return the new input ID. + */ public int addInput() { int id = 0; for (NeuralNetwork network : networks) { id = network.addInput(); } + // Unless a neural network's addInput() is called individually, which should be impossible + // because the list of networks is private, all IDs returned by network.addInput() are the same. return id; } + /** + * Returns a prediction from the Neural Networks based on the inputs. + * @param inputs The list of double inputs. + * @return The prediction. + */ public PredictionInterface computeOutput(double[] inputs) { PredictionInterface[] predictions = new PredictionInterface[networks.length]; for (int i = 0; i < predictions.length; i++) { @@ -46,7 +62,12 @@ class MultiNeuralNetwork implements Serializable { return new MultiNeuralNetworkPrediction(predictions); } + /** + * Returns the number of inputs in the neural network. + * @return + */ public int getInputCount() { + // All neural networks will have the same number of inputs. See addInput(). return networks[0].getInputCount(); } } diff --git a/app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java b/app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java index f618749..c03cab3 100755 --- a/app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java +++ b/app/src/main/java/org/rssin/neurons/MultiNeuralNetworkPrediction.java @@ -2,6 +2,7 @@ package org.rssin.neurons; /** * @author Jos. + * A prediction that bases its result on the average of multiple other predictions. */ class MultiNeuralNetworkPrediction implements PredictionInterface { private final PredictionInterface[] predictions; @@ -14,6 +15,9 @@ class MultiNeuralNetworkPrediction implements PredictionInterface { this.predictions = predictions; } + /** + * @return the prediction, as a value in [-1, 1]. + */ public double getOutput() { double average = 0; for (PredictionInterface prediction : predictions) { @@ -23,12 +27,19 @@ class MultiNeuralNetworkPrediction implements PredictionInterface { return average / (double) predictions.length; } + /** + * Provides the neural networks with feedback. + * @param expectedOutput The expected output for the input values (getInputs()). + */ public void learn(double expectedOutput) { for (PredictionInterface prediction : predictions) { prediction.learn(expectedOutput); } } + /** + * @return The inputs provided to the neural network. + */ public double[] getInputs() { return predictions[0].getInputs(); } diff --git a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java index c990be9..446e13a 100755 --- a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java +++ b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java @@ -9,6 +9,7 @@ import java.io.Serializable; /** * @author Jos. + * A 'simple' implementation of a neural network with one hidden layer. */ class NeuralNetwork implements Serializable { private static final long serialVersionUID = 0; @@ -25,6 +26,10 @@ class NeuralNetwork implements Serializable { outputNode = (Neuron) stream.readObject(); } + /** + * Creates a new instance of the neural network. + * @param numHiddenNodes The number of hidden nodes in the neural network. + */ NeuralNetwork(int numHiddenNodes) { if (numHiddenNodes < 1) { throw new IllegalArgumentException("numHiddenNodes must be > 0"); @@ -39,6 +44,9 @@ class NeuralNetwork implements Serializable { outputNode = new Neuron(numHiddenNodes + 1); } + /** + * @return the new input ID. + */ @SuppressLint("Assert") int addInput() { assert hiddenNodes.length > 0; @@ -51,6 +59,11 @@ class NeuralNetwork implements Serializable { return result; } + /** + * Calculcates the output of the neural network for the given input values. + * @param inputs The inputs for the neural network. + * @return The output of the neural network. + */ PredictionInterface computeOutput(double[] inputs) { double[] intermediateValues = new double[outputNode.getWeightCount()]; @@ -74,8 +87,12 @@ class NeuralNetwork implements Serializable { return new NeuralNetworkPrediction(this, inputs, intermediateValues, HyperTan(result)); } + /** + * Train the neural network + * @param p The original prediction + * @param expectedOutput The expected output of the prediction. + */ void learn(NeuralNetworkPrediction p, double expectedOutput) { - //TODO: See if adding momentum helps avoid local minimum double actualOutput = p.getOutput(); double[] intermediateValues = p.getIntermediateValues(); double[] inputs = p.getInputs(); @@ -97,6 +114,13 @@ class NeuralNetwork implements Serializable { updateWeights(intermediateValues, inputs, hiddenGradients, outputGradient); } + /** + * Method to update the weights of the nodes. + * @param intermediateValues The intermediate values generated by the hidden nodes + * @param inputs The input values + * @param hiddenGradients The hidden gradients, calculated in learn(). + * @param outputGradient The output gradients, calculated in learn(). + */ private void updateWeights(double[] intermediateValues, double[] inputs, double[] hiddenGradients, double outputGradient) { final double learningRate = 0.2; @@ -119,12 +143,20 @@ class NeuralNetwork implements Serializable { } } + /** + * HyperTan that returns -1 or 1 when the value is smaller than -10 or bigger than 10, respectively. + * @param x The input + * @return The result of HyperTan. + */ private static double HyperTan(double x) { if (x < -10.0) return -1.0; else if (x > 10.0) return 1.0; else return Math.tanh(x); } + /** + * @return The number of inputs for this neural network. + */ int getInputCount() { return hiddenNodes[0].getWeightCount(); } diff --git a/app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java b/app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java index 169caee..40dca02 100755 --- a/app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java +++ b/app/src/main/java/org/rssin/neurons/NeuralNetworkPrediction.java @@ -2,6 +2,7 @@ package org.rssin.neurons; /** * @author Jos. + * A prediction made by the neural network. */ class NeuralNetworkPrediction implements PredictionInterface { private final double[] inputs; @@ -16,18 +17,31 @@ class NeuralNetworkPrediction implements PredictionInterface { this.nn = nn; } + /** + * @return The inputs that resulted in this prediction. + */ public double[] getInputs() { return inputs; } + /** + * @return The intermediate values that resulted in the output, as calculated by NeuralNetwork.computeOutput. + */ public double[] getIntermediateValues() { return intermediateValues; } + /** + * @return The output of the neural network. + */ public double getOutput() { return output; } + /** + * Provides feedback to the neural network. + * @param expectedOutput The expected output for the input values. + */ public void learn(double expectedOutput) { nn.learn(this, expectedOutput); } diff --git a/app/src/main/java/org/rssin/neurons/Neuron.java b/app/src/main/java/org/rssin/neurons/Neuron.java index 203a450..760ea77 100755 --- a/app/src/main/java/org/rssin/neurons/Neuron.java +++ b/app/src/main/java/org/rssin/neurons/Neuron.java @@ -10,6 +10,7 @@ import java.util.Random; /** * @author Jos. + * A class that contains the weights for a single neuron in the neural network. */ class Neuron implements Serializable { private static final long serialVersionUID = 0; @@ -35,6 +36,10 @@ class Neuron implements Serializable { } } + /** + * Adds a weight to the neuron. + * @return The index of the weight. + */ public int addWeight() { // Initial values range from -.5 to .5. The exact value does not matter, // as long as they aren't all 0. @@ -42,14 +47,27 @@ class Neuron implements Serializable { return weights.size() - 1; } + /** + * Returns the value of a weight + * @param i The weight index + * @return The value of the weight + */ public double getWeight(int i) { return weights.get(i); } + /** + * Modifies a weight, by adding delta to its value + * @param i The weight index + * @param delta The amount the value will change. + */ public void adjustWeight(int i, double delta) { weights.set(i, weights.get(i) + delta); } + /** + * @return the number of weights in this neuron. + */ public int getWeightCount() { return weights.size(); } diff --git a/app/src/main/java/org/rssin/neurons/PredictionInterface.java b/app/src/main/java/org/rssin/neurons/PredictionInterface.java index ff46992..891707a 100755 --- a/app/src/main/java/org/rssin/neurons/PredictionInterface.java +++ b/app/src/main/java/org/rssin/neurons/PredictionInterface.java @@ -2,11 +2,23 @@ package org.rssin.neurons; /** * @author Jos. + * Interface for predictions generated by either NeuralNetwork or MultiNeuralNetwork. */ -interface PredictionInterface { +interface PredictionInterface +{ + /** + * @return The output of the neural network. + */ double getOutput(); + /** + * Provides feedback to the neural network. + * @param expectedOutput The expected output for this prediction. + */ void learn(double expectedOutput); + /** + * @return The inputs that were given to the neural network. + */ double[] getInputs(); } diff --git a/app/src/main/java/org/rssin/neurons/SentenceSplitter.java b/app/src/main/java/org/rssin/neurons/SentenceSplitter.java index 29e34bc..002071e 100755 --- a/app/src/main/java/org/rssin/neurons/SentenceSplitter.java +++ b/app/src/main/java/org/rssin/neurons/SentenceSplitter.java @@ -12,7 +12,8 @@ import java.util.regex.Pattern; public class SentenceSplitter implements Serializable { private static final long serialVersionUID = 0; - private final Pattern wordMatch = Pattern.compile("[\\w-]+");//For unicode support, add the Pattern.UNICODE_CHARACTER_CLASS flag. Works only in Java 7+. + //For unicode support, add the Pattern.UNICODE_CHARACTER_CLASS flag. Works only in Java 7+, currently not supported on Android. + private final Pattern wordMatch = Pattern.compile("[\\w-]+"); public SentenceSplitter() { } diff --git a/app/src/main/java/org/rssin/neurons/TrainingCase.java b/app/src/main/java/org/rssin/neurons/TrainingCase.java index 5c6172c..d1fee3a 100755 --- a/app/src/main/java/org/rssin/neurons/TrainingCase.java +++ b/app/src/main/java/org/rssin/neurons/TrainingCase.java @@ -4,6 +4,7 @@ import java.io.Serializable; /** * @author Jos. + * A training case for the FeedSorter. */ public class TrainingCase implements Serializable { private static final long serialVersionUID = 0; @@ -15,14 +16,23 @@ public class TrainingCase implements Serializable { this.feedback = feedback; } + /** + * @return The inputs that were given to the neural network. + */ double[] getInputs() { return inputs; } + /** + * @return The expected prediction + */ public Feedback getFeedback() { return feedback; } + /** + * @param feedback The new expected prediction. + */ public void setFeedback(Feedback feedback) { this.feedback = feedback; diff --git a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java index a317a27..524ac46 100755 --- a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java +++ b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java @@ -16,11 +16,15 @@ import java.util.List; /** * Created by Jos on 20-5-2015. - * @todo javadoc + * A class that loads & sorts FeedItems from a list of Feeds. */ public class FeedLoaderAndSorter { private final List feeds; + /** + * Creates a new FeedLoaderAndSorter that can load FeedItems the list of feeds. + * @param feeds The list of Feeds to load FeedItems from. + */ public FeedLoaderAndSorter(List feeds) { this.feeds = feeds; } @@ -81,10 +85,4 @@ public class FeedLoaderAndSorter { return count == 0; } } - - private static boolean contains(String haystack, String needle) { - return haystack != null - && needle != null - && haystack.toLowerCase().contains(needle.toLowerCase()); - } } -- cgit v1.2.3 From fef7df0f36e8871a6e2bd36030d5b68a85e91f0e Mon Sep 17 00:00:00 2001 From: Size43 Date: Wed, 10 Jun 2015 11:53:29 +0200 Subject: Fixed all hardcoded strings --- README.md | 2 -- app/src/main/java/org/rssin/android/FeedSorterTrainer.java | 3 ++- app/src/main/java/org/rssin/android/FeedsActivity.java | 4 ++-- app/src/main/java/org/rssin/android/FilterSettingsActivity.java | 4 ++-- app/src/main/java/org/rssin/android/HomeScreenActivity.java | 2 +- .../java/org/rssin/android/NavigationDrawerManageFeedsFragment.java | 4 ++-- .../java/org/rssin/android/NavigationDrawerManageFiltersFragment.java | 4 ++-- app/src/main/res/values/strings.xml | 4 ++++ 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 7cd6f2c..5afc936 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,6 @@ Copyright © 2015 Randy Wanga, Jos Craaijo, Joep Bernards, Camil Staps. All (see also the @todo markings throughout the source code) ## High priority -* Walk through all java to check for hardcoded strings -* Don't train both like and dislike * Test deleting feeds * Test settings button * Make "start" not clickable diff --git a/app/src/main/java/org/rssin/android/FeedSorterTrainer.java b/app/src/main/java/org/rssin/android/FeedSorterTrainer.java index 1f88a3e..987ed45 100755 --- a/app/src/main/java/org/rssin/android/FeedSorterTrainer.java +++ b/app/src/main/java/org/rssin/android/FeedSorterTrainer.java @@ -14,8 +14,8 @@ public class FeedSorterTrainer implements Runnable { @Override public void run() { + Log.d("FeedSorterTrainer", "Training starting..."); for (int i = 0; i < 50; i++) { - Log.d("FeedSorterTrainer", "Training: round " + i); sorterProvider.getFeedSorter().train(); try { Thread.sleep(10); @@ -24,6 +24,7 @@ public class FeedSorterTrainer implements Runnable { } } + Log.d("FeedSorterTrainer", "Training stopping..."); sorterProvider.save(); } } diff --git a/app/src/main/java/org/rssin/android/FeedsActivity.java b/app/src/main/java/org/rssin/android/FeedsActivity.java index 4a69af9..32f256a 100755 --- a/app/src/main/java/org/rssin/android/FeedsActivity.java +++ b/app/src/main/java/org/rssin/android/FeedsActivity.java @@ -105,8 +105,8 @@ public class FeedsActivity extends ActionBarActivity { AlertDialog.Builder alert = new AlertDialog.Builder(this); - alert.setTitle("Add feed"); - alert.setMessage("URL:"); + alert.setTitle(getString(R.string.feeds_activity_add_feed)); + alert.setMessage(getString(R.string.feeds_activity_url)); final EditText input = new EditText(this); input.setFocusable(true); diff --git a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java index 931a86c..3041859 100755 --- a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java +++ b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java @@ -182,8 +182,8 @@ public class FilterSettingsActivity extends ActionBarActivity { AlertDialog.Builder alert = new AlertDialog.Builder(this); - alert.setTitle("Title"); - alert.setMessage("New title:"); + alert.setTitle(getString(R.string.filter_settings_title)); + alert.setMessage(getString(R.string.filter_settings_new_title)); final EditText input = new EditText(this); input.setText(filter.getTitle()); diff --git a/app/src/main/java/org/rssin/android/HomeScreenActivity.java b/app/src/main/java/org/rssin/android/HomeScreenActivity.java index 378ac18..f33411b 100755 --- a/app/src/main/java/org/rssin/android/HomeScreenActivity.java +++ b/app/src/main/java/org/rssin/android/HomeScreenActivity.java @@ -41,7 +41,7 @@ public class HomeScreenActivity extends ActionBarActivity implements NavigationD fragmentManager.beginTransaction() .replace(R.id.container, currentFragment = initialFragment) .commit(); - mTitle = "All feeds"; + mTitle = getString(R.string.navigation_drawer_all_feeds); } private Fragment currentFragment; diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java index c768a3b..e239588 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java @@ -119,8 +119,8 @@ public class NavigationDrawerManageFeedsFragment extends Fragment { AlertDialog.Builder alert = new AlertDialog.Builder(context); - alert.setTitle("Add feed"); - alert.setMessage("URL:"); + alert.setTitle(getString(R.string.feeds_activity_add_feed)); + alert.setMessage(getString(R.string.feeds_activity_url)); final EditText input = new EditText(context); input.setFocusable(true); diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerManageFiltersFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerManageFiltersFragment.java index 405d7be..42be75f 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerManageFiltersFragment.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerManageFiltersFragment.java @@ -115,8 +115,8 @@ public class NavigationDrawerManageFiltersFragment extends Fragment { AlertDialog.Builder alert = new AlertDialog.Builder(rootView.getContext()); - alert.setTitle("Add filter"); - alert.setMessage("Title:"); + alert.setTitle(getString(R.string.filters_action_add)); + alert.setMessage(getString(R.string.filter_settings_title)); final EditText input = new EditText(rootView.getContext()); input.setFocusable(true); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3b3a884..591a878 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -70,4 +70,8 @@ FILTERS (EDIT) FEEDS (EDIT) Feedback saved. + Add feed + URL: + Title + New title: -- cgit v1.2.3 From 3617197cf2b010ce59691e4a263ce5f7e2c18b25 Mon Sep 17 00:00:00 2001 From: Size43 Date: Wed, 10 Jun 2015 12:19:22 +0200 Subject: Added icons, changed filter title edittext to singleline, fixed feed settings crash --- README.md | 2 -- app/src/main/java/org/rssin/android/FeedsActivity.java | 2 +- .../java/org/rssin/android/FilterSettingsActivity.java | 1 + .../java/org/rssin/android/NavigationDrawerAdapter.java | 5 +++-- .../main/res/drawable-hdpi/ic_action_action_delete.png | Bin 0 -> 239 bytes .../main/res/drawable-hdpi/ic_action_action_settings.png | Bin 0 -> 654 bytes .../res/drawable-hdpi/ic_action_editor_border_color.png | Bin 0 -> 410 bytes .../main/res/drawable-mdpi/ic_action_action_delete.png | Bin 0 -> 190 bytes .../main/res/drawable-mdpi/ic_action_action_settings.png | Bin 0 -> 399 bytes .../res/drawable-mdpi/ic_action_editor_border_color.png | Bin 0 -> 262 bytes .../main/res/drawable-xhdpi/ic_action_action_delete.png | Bin 0 -> 306 bytes .../res/drawable-xhdpi/ic_action_action_settings.png | Bin 0 -> 903 bytes .../res/drawable-xhdpi/ic_action_editor_border_color.png | Bin 0 -> 489 bytes .../main/res/drawable-xxhdpi/ic_action_action_delete.png | Bin 0 -> 444 bytes .../res/drawable-xxhdpi/ic_action_action_settings.png | Bin 0 -> 1289 bytes .../drawable-xxhdpi/ic_action_editor_border_color.png | Bin 0 -> 678 bytes .../res/drawable-xxxhdpi/ic_action_action_delete.png | Bin 0 -> 659 bytes .../res/drawable-xxxhdpi/ic_action_action_settings.png | Bin 0 -> 2029 bytes .../drawable-xxxhdpi/ic_action_editor_border_color.png | Bin 0 -> 940 bytes app/src/main/res/menu/global.xml | 2 +- app/src/main/res/menu/home_screen.xml | 2 +- app/src/main/res/menu/menu_article.xml | 2 +- app/src/main/res/menu/menu_filter.xml | 2 +- app/src/main/res/menu/menu_filter_settings.xml | 6 ++++-- app/src/main/res/menu/menu_unified_inbox.xml | 11 ----------- app/src/main/res/values/strings.xml | 1 + 26 files changed, 14 insertions(+), 22 deletions(-) create mode 100755 app/src/main/res/drawable-hdpi/ic_action_action_delete.png create mode 100755 app/src/main/res/drawable-hdpi/ic_action_action_settings.png create mode 100755 app/src/main/res/drawable-hdpi/ic_action_editor_border_color.png create mode 100755 app/src/main/res/drawable-mdpi/ic_action_action_delete.png create mode 100755 app/src/main/res/drawable-mdpi/ic_action_action_settings.png create mode 100755 app/src/main/res/drawable-mdpi/ic_action_editor_border_color.png create mode 100755 app/src/main/res/drawable-xhdpi/ic_action_action_delete.png create mode 100755 app/src/main/res/drawable-xhdpi/ic_action_action_settings.png create mode 100755 app/src/main/res/drawable-xhdpi/ic_action_editor_border_color.png create mode 100755 app/src/main/res/drawable-xxhdpi/ic_action_action_delete.png create mode 100755 app/src/main/res/drawable-xxhdpi/ic_action_action_settings.png create mode 100755 app/src/main/res/drawable-xxhdpi/ic_action_editor_border_color.png create mode 100755 app/src/main/res/drawable-xxxhdpi/ic_action_action_delete.png create mode 100755 app/src/main/res/drawable-xxxhdpi/ic_action_action_settings.png create mode 100755 app/src/main/res/drawable-xxxhdpi/ic_action_editor_border_color.png mode change 100644 => 100755 app/src/main/res/menu/menu_filter_settings.xml delete mode 100644 app/src/main/res/menu/menu_unified_inbox.xml diff --git a/README.md b/README.md index 5afc936..c6fc667 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,6 @@ Copyright © 2015 Randy Wanga, Jos Craaijo, Joep Bernards, Camil Staps. All ## High priority * Test deleting feeds -* Test settings button -* Make "start" not clickable * Titles & alignment "edit" ## Normal priority diff --git a/app/src/main/java/org/rssin/android/FeedsActivity.java b/app/src/main/java/org/rssin/android/FeedsActivity.java index 32f256a..87edab0 100755 --- a/app/src/main/java/org/rssin/android/FeedsActivity.java +++ b/app/src/main/java/org/rssin/android/FeedsActivity.java @@ -45,7 +45,7 @@ public class FeedsActivity extends ActionBarActivity { Intent intent = getIntent(); String ac = intent.getAction(); - if (ac.equals(Intent.ACTION_VIEW)) { + if (ac != null && ac.equals(Intent.ACTION_VIEW)) { //open with startUri = intent.getData().toString(); openAddDialog(); diff --git a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java index 3041859..a38c7bc 100755 --- a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java +++ b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java @@ -187,6 +187,7 @@ public class FilterSettingsActivity extends ActionBarActivity { final EditText input = new EditText(this); input.setText(filter.getTitle()); + input.setSingleLine(true); input.setFocusable(true); input.requestFocus(); diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java b/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java index 2a24342..8f0a068 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java @@ -57,12 +57,13 @@ class NavigationDrawerAdapter implements ListAdapter { @Override public boolean areAllItemsEnabled() { - return true; + return false; } @Override public boolean isEnabled(int position) { - return true; + // Position 0 is always "Start" + return position != 0; } private List observers = new ArrayList<>(); diff --git a/app/src/main/res/drawable-hdpi/ic_action_action_delete.png b/app/src/main/res/drawable-hdpi/ic_action_action_delete.png new file mode 100755 index 0000000..9449c35 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_action_delete.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_action_settings.png b/app/src/main/res/drawable-hdpi/ic_action_action_settings.png new file mode 100755 index 0000000..116e9a0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_action_settings.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_action_editor_border_color.png b/app/src/main/res/drawable-hdpi/ic_action_editor_border_color.png new file mode 100755 index 0000000..b044320 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_action_editor_border_color.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_action_delete.png b/app/src/main/res/drawable-mdpi/ic_action_action_delete.png new file mode 100755 index 0000000..eb03dce Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_action_delete.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_action_settings.png b/app/src/main/res/drawable-mdpi/ic_action_action_settings.png new file mode 100755 index 0000000..1a8017b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_action_settings.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_action_editor_border_color.png b/app/src/main/res/drawable-mdpi/ic_action_editor_border_color.png new file mode 100755 index 0000000..6216372 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_action_editor_border_color.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_action_delete.png b/app/src/main/res/drawable-xhdpi/ic_action_action_delete.png new file mode 100755 index 0000000..a0b397e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_action_delete.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_action_settings.png b/app/src/main/res/drawable-xhdpi/ic_action_action_settings.png new file mode 100755 index 0000000..b764d9c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_action_settings.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_action_editor_border_color.png b/app/src/main/res/drawable-xhdpi/ic_action_editor_border_color.png new file mode 100755 index 0000000..a754a2d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_action_editor_border_color.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_action_delete.png b/app/src/main/res/drawable-xxhdpi/ic_action_action_delete.png new file mode 100755 index 0000000..c1fbf46 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_action_delete.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_action_settings.png b/app/src/main/res/drawable-xxhdpi/ic_action_action_settings.png new file mode 100755 index 0000000..a68f6f9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_action_settings.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_action_editor_border_color.png b/app/src/main/res/drawable-xxhdpi/ic_action_editor_border_color.png new file mode 100755 index 0000000..ef5e602 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_action_editor_border_color.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_action_delete.png b/app/src/main/res/drawable-xxxhdpi/ic_action_action_delete.png new file mode 100755 index 0000000..d152354 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_action_delete.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_action_settings.png b/app/src/main/res/drawable-xxxhdpi/ic_action_action_settings.png new file mode 100755 index 0000000..f18ff96 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_action_settings.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_action_editor_border_color.png b/app/src/main/res/drawable-xxxhdpi/ic_action_editor_border_color.png new file mode 100755 index 0000000..a57ae9b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_action_editor_border_color.png differ diff --git a/app/src/main/res/menu/global.xml b/app/src/main/res/menu/global.xml index 86959a3..c4ae1a3 100755 --- a/app/src/main/res/menu/global.xml +++ b/app/src/main/res/menu/global.xml @@ -1,5 +1,5 @@ + android:orderInCategory="100" app:showAsAction="ifRoom" android:icon="@drawable/ic_action_action_settings" /> \ No newline at end of file diff --git a/app/src/main/res/menu/home_screen.xml b/app/src/main/res/menu/home_screen.xml index a894d92..bf901df 100755 --- a/app/src/main/res/menu/home_screen.xml +++ b/app/src/main/res/menu/home_screen.xml @@ -3,5 +3,5 @@ xmlns:tools="http://schemas.android.com/tools" tools:context="org.rssin.android.HomeScreenActivity"> + android:orderInCategory="100" app:showAsAction="ifRoom" android:icon="@drawable/ic_action_action_settings" /> diff --git a/app/src/main/res/menu/menu_article.xml b/app/src/main/res/menu/menu_article.xml index 064831b..80ef7a7 100755 --- a/app/src/main/res/menu/menu_article.xml +++ b/app/src/main/res/menu/menu_article.xml @@ -19,7 +19,7 @@ diff --git a/app/src/main/res/menu/menu_filter.xml b/app/src/main/res/menu/menu_filter.xml index 86cfe5d..5822314 100755 --- a/app/src/main/res/menu/menu_filter.xml +++ b/app/src/main/res/menu/menu_filter.xml @@ -2,5 +2,5 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context="org.rssin.android.HomeScreenActivity"> + android:orderInCategory="100" app:showAsAction="ifRoom" android:icon="@drawable/ic_action_action_settings" /> diff --git a/app/src/main/res/menu/menu_filter_settings.xml b/app/src/main/res/menu/menu_filter_settings.xml old mode 100644 new mode 100755 index 655ee84..a914ad8 --- a/app/src/main/res/menu/menu_filter_settings.xml +++ b/app/src/main/res/menu/menu_filter_settings.xml @@ -8,11 +8,13 @@ + app:showAsAction="ifRoom" + android:icon="@drawable/ic_action_editor_border_color"/> + app:showAsAction="ifRoom" + android:icon="@drawable/ic_action_action_delete"/> diff --git a/app/src/main/res/menu/menu_unified_inbox.xml b/app/src/main/res/menu/menu_unified_inbox.xml deleted file mode 100644 index 021ceb5..0000000 --- a/app/src/main/res/menu/menu_unified_inbox.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 591a878..df130b3 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -74,4 +74,5 @@ URL: Title New title: + Share -- cgit v1.2.3 From ed6446af455fe0749fabd0b39f1e2c1b25623e06 Mon Sep 17 00:00:00 2001 From: Size43 Date: Wed, 10 Jun 2015 13:00:11 +0200 Subject: Aligned (EDIT) to the right --- README.md | 3 +-- .../org/rssin/android/NavigationDrawerAdapter.java | 24 ++++++++++++++-------- .../res/layout/separator_navigation_drawer.xml | 16 +++++++++++++-- app/src/main/res/values/strings.xml | 5 +++-- 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index c6fc667..b31a843 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,12 @@ Copyright © 2015 Randy Wanga, Jos Craaijo, Joep Bernards, Camil Staps. All (see also the @todo markings throughout the source code) ## High priority -* Test deleting feeds -* Titles & alignment "edit" ## Normal priority * Background sync & notifications * Add tutorial (e.g.: at first startup, walk user through creating first filter) * Swipe left & right for (dis)like +* Extract feed title from feed ## Low priority * Readability plugin to view whole article diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java b/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java index 8f0a068..973f7ab 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerAdapter.java @@ -33,16 +33,16 @@ class NavigationDrawerAdapter implements ListAdapter { public void updateMenu(Context context) throws IOException { menuItems.clear(); - menuItems.add(new MenuSection(context.getString(R.string.navigation_drawer_start))); + menuItems.add(new MenuSection(context.getString(R.string.navigation_drawer_start), "")); menuItems.add(new MenuUnifiedInbox(context)); - menuItems.add(new ManageFiltersSection(context.getString(R.string.navigation_drawer_edit_filters))); + menuItems.add(new ManageFiltersSection(context.getString(R.string.navigation_drawer_edit_filters), context.getString(R.string.navigation_drawer_edit_text))); for(Filter f : FiltersList.getInstance(context).getFilters()) { menuItems.add(new MenuFilterItem(f)); } - menuItems.add(new ManageFeedsSection(context.getString(R.string.navigation_drawer_edit_feeds))); + menuItems.add(new ManageFeedsSection(context.getString(R.string.navigation_drawer_edit_feeds), context.getString(R.string.navigation_drawer_edit_text))); for(Feed f : FeedsList.getInstance(context).getFeeds()) { @@ -117,6 +117,7 @@ class NavigationDrawerAdapter implements ListAdapter { if (type == ITEM_VIEW_TYPE_SEPARATOR) { final MenuSection section = (MenuSection) getItem(position); ((TextView) convertView.findViewById(R.id.separator_navigation_drawer_text)).setText(section.getText()); + ((TextView) convertView.findViewById(R.id.separator_navigation_drawer_edit)).setText(section.getRightText()); } else { final MenuItem video = (MenuItem) getItem(position); ((TextView) convertView.findViewById(R.id.item_navigation_drawer_text)).setText(video.getText()); @@ -261,22 +262,29 @@ class NavigationDrawerAdapter implements ListAdapter { class MenuSection extends MenuItem { - public MenuSection(String text) + private String rightText; + + public MenuSection(String text, String rightText) { super(text); + this.rightText = rightText; } @Override public int getItemViewType() { return ITEM_VIEW_TYPE_SEPARATOR; } + + public String getRightText() { + return rightText; + } } class ManageFiltersSection extends MenuSection { - public ManageFiltersSection(String text) + public ManageFiltersSection(String text, String rightText) { - super(text); + super(text, rightText); } @Override @@ -292,9 +300,9 @@ class NavigationDrawerAdapter implements ListAdapter { class ManageFeedsSection extends MenuSection { - public ManageFeedsSection(String text) + public ManageFeedsSection(String text, String rightText) { - super(text); + super(text, rightText); } @Override diff --git a/app/src/main/res/layout/separator_navigation_drawer.xml b/app/src/main/res/layout/separator_navigation_drawer.xml index 81a9d0a..a3031a0 100755 --- a/app/src/main/res/layout/separator_navigation_drawer.xml +++ b/app/src/main/res/layout/separator_navigation_drawer.xml @@ -10,7 +10,7 @@ android:layout_marginTop="0dp" android:background="#252525" > - - + + + All feeds START - FILTERS (EDIT) - FEEDS (EDIT) + FILTERS + FEEDS Feedback saved. Add feed URL: Title New title: Share + (EDIT) -- cgit v1.2.3 From 797d7a62c782e4cc141c0c434047dd3fa2fdeff5 Mon Sep 17 00:00:00 2001 From: Camil Staps Date: Wed, 10 Jun 2015 13:13:35 +0200 Subject: IT WORKS --- .../java/org/rssin/android/FeedSorterProvider.java | 13 +++-- .../java/org/rssin/android/FeedSorterTrainer.java | 1 + app/src/main/java/org/rssin/android/FeedsList.java | 26 ++++++++- .../main/java/org/rssin/android/FiltersList.java | 2 +- .../org/rssin/android/InternalStorageProvider.java | 33 ++++++----- .../android/NavigationDrawerAllFeedsFragment.java | 25 ++++---- .../android/NavigationDrawerFeedFragment.java | 21 ++++--- .../android/NavigationDrawerFilterFragment.java | 22 +++++--- .../android/SharedPreferencesStorageProvider.java | 13 ----- .../main/java/org/rssin/android/VolleyFetcher.java | 14 ++++- .../java/org/rssin/listener/RealtimeListener.java | 2 +- .../main/java/org/rssin/neurons/FeedSorter.java | 42 ++------------ .../java/org/rssin/neurons/MultiNeuralNetwork.java | 8 --- .../main/java/org/rssin/neurons/NeuralNetwork.java | 10 ---- app/src/main/java/org/rssin/neurons/Neuron.java | 9 --- .../java/org/rssin/rssin/FeedLoaderAndSorter.java | 61 ++++++++++++++++---- .../org/rssin/rssin/SortedFeedItemContainer.java | 14 ++--- app/src/main/res/values/feeds.xml | 66 ---------------------- 18 files changed, 171 insertions(+), 211 deletions(-) diff --git a/app/src/main/java/org/rssin/android/FeedSorterProvider.java b/app/src/main/java/org/rssin/android/FeedSorterProvider.java index 0f0748d..fcdeca2 100755 --- a/app/src/main/java/org/rssin/android/FeedSorterProvider.java +++ b/app/src/main/java/org/rssin/android/FeedSorterProvider.java @@ -15,11 +15,11 @@ public class FeedSorterProvider { private static FeedSorterProvider instance; private FeedSorter sorter = null; private final String storageKey = "FeedSorter"; - private InternalStorageProvider storageProvider; + private final StorageProvider storageProvider; private FeedSorterProvider(Context context) { - storageProvider = InternalStorageProvider.getInstance(context); + storageProvider = SharedPreferencesStorageProvider.getInstance(context); } public synchronized static FeedSorterProvider getInstance() @@ -43,8 +43,9 @@ public class FeedSorterProvider { { try { sorter = (FeedSorter) storageProvider.fetch(storageKey, FeedSorter.class); - } catch (IOException e) { + } catch (Exception e) { sorter = new FeedSorter(); + Log.v("FST", "Saving new empty sorterProvider", e); this.save(); } } @@ -52,7 +53,7 @@ public class FeedSorterProvider { return sorter; } - public synchronized void save() + public void save() { FeedSorterStorer storer = new FeedSorterStorer(storageKey, storageProvider, sorter); new Thread(storer).start(); @@ -72,7 +73,9 @@ public class FeedSorterProvider { @Override public void run() { try { - storageProvider.store(storageKey, feedSorter); + synchronized (feedSorter) { + storageProvider.store(storageKey, feedSorter); + } } catch (Exception e) { Log.e("Filter", "Failed to store FeedSorter", e); } diff --git a/app/src/main/java/org/rssin/android/FeedSorterTrainer.java b/app/src/main/java/org/rssin/android/FeedSorterTrainer.java index 1f88a3e..9704fc7 100755 --- a/app/src/main/java/org/rssin/android/FeedSorterTrainer.java +++ b/app/src/main/java/org/rssin/android/FeedSorterTrainer.java @@ -24,6 +24,7 @@ public class FeedSorterTrainer implements Runnable { } } + Log.v("FST", "Saving sorterProvider"); sorterProvider.save(); } } diff --git a/app/src/main/java/org/rssin/android/FeedsList.java b/app/src/main/java/org/rssin/android/FeedsList.java index 72a56d1..1036ad3 100644 --- a/app/src/main/java/org/rssin/android/FeedsList.java +++ b/app/src/main/java/org/rssin/android/FeedsList.java @@ -1,8 +1,11 @@ package org.rssin.android; import android.content.Context; +import android.preference.PreferenceManager; +import android.util.Log; import org.rssin.rssin.Feed; +import org.rssin.rssin.R; import java.io.IOException; import java.util.Collections; @@ -16,18 +19,39 @@ class FeedsList { private static FeedsList instance; - private final List feeds; + private List feeds; private final DefaultStorageProvider storageProvider; + public static final boolean USE_DEFAULT_LIST = true; + /** * Fetch from storage provider * @param context needed to get the storageprovider * @throws IOException if data is corrupted, and deserializing fails */ + @SuppressWarnings("all") protected FeedsList(Context context) throws IOException { storageProvider = DefaultStorageProvider.getInstance(context); feeds = storageProvider.allFeeds(); sort(); + + if (USE_DEFAULT_LIST && + feeds.isEmpty() && + !PreferenceManager.getDefaultSharedPreferences(context).getBoolean("firstload", false)) { + String[] feedsList = context.getResources().getStringArray(R.array.default_feeds); + for (String url : feedsList) { + try { + Feed f = new Feed(url); + f.store(storageProvider); + } catch (Exception e) { + Log.w("SPSP", "Couldn't add " + url, e); + } + } + PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean("firstload", true).apply(); + + feeds = storageProvider.allFeeds(); + sort(); + } } public static FeedsList getInstance(Context context) throws IOException { diff --git a/app/src/main/java/org/rssin/android/FiltersList.java b/app/src/main/java/org/rssin/android/FiltersList.java index 6b53186..b555e5e 100755 --- a/app/src/main/java/org/rssin/android/FiltersList.java +++ b/app/src/main/java/org/rssin/android/FiltersList.java @@ -12,7 +12,7 @@ import java.util.List; * A list of filters that can be saved using the DefaultStorageProvider * @author Camil Staps */ -public class FiltersList { +class FiltersList { private static FiltersList instance; diff --git a/app/src/main/java/org/rssin/android/InternalStorageProvider.java b/app/src/main/java/org/rssin/android/InternalStorageProvider.java index c5a7bc1..b6787b4 100644 --- a/app/src/main/java/org/rssin/android/InternalStorageProvider.java +++ b/app/src/main/java/org/rssin/android/InternalStorageProvider.java @@ -1,6 +1,7 @@ package org.rssin.android; import android.content.Context; +import android.util.Log; import org.rssin.neurons.FeedSorter; import org.rssin.rssin.Filter; @@ -8,6 +9,7 @@ import org.rssin.storage.FilterStorageProvider; import org.rssin.storage.Storable; import org.rssin.storage.StorageProvider; +import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -21,14 +23,15 @@ import java.util.List; * A way to store data in internal storage * @author Camil Staps */ -class InternalStorageProvider implements StorageProvider, FilterStorageProvider { +class InternalStorageProvider implements StorageProvider, FilterStorageProvider { protected static final String PREFIX = "storage_", PREFIX_FILTER = "f_", PREFIX_FEEDSORTER = "fs_"; private static InternalStorageProvider instance; private final Context context; - private InternalStorageProvider(Context context) { + // @todo redo singleton + public InternalStorageProvider(Context context) { this.context = context; } @@ -43,7 +46,7 @@ class InternalStorageProvider implements StorageProvider, Filt } @Override - public synchronized void store(String key, Storable element) throws FileNotFoundException, IOException { + public synchronized void store(String key, FeedSorter element) throws FileNotFoundException, IOException { FileOutputStream fos = context.openFileOutput(getFilename(key, element), Context.MODE_PRIVATE); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(element); @@ -52,7 +55,7 @@ class InternalStorageProvider implements StorageProvider, Filt } @Override - public Storable fetch(String key, Class className) throws ClassCastException, FileNotFoundException, IOException { + public FeedSorter fetch(String key, Class className) throws ClassCastException, FileNotFoundException, IOException { return fetchFromFilename(getFilename(key, className)); } @@ -61,11 +64,11 @@ class InternalStorageProvider implements StorageProvider, Filt throw new UnsupportedOperationException("Not implemented yet."); } - public Storable fetchFromFilename(String fileName) throws ClassCastException, FileNotFoundException, IOException { + public FeedSorter fetchFromFilename(String fileName) throws ClassCastException, FileNotFoundException, IOException { FileInputStream fis = context.openFileInput(fileName); ObjectInputStream ois = new ObjectInputStream(fis); try { - return (Storable) ois.readObject(); + return (FeedSorter) ois.readObject(); } catch (ClassNotFoundException e) { return null; } @@ -114,11 +117,11 @@ class InternalStorageProvider implements StorageProvider, Filt @Override public List allFilters() { List filters = new ArrayList<>(); - for (String fileName : context.fileList()) { - try { - filters.add((Filter) fetchFromFilename(fileName)); - } catch (ClassCastException | IOException e) {} - } +// for (String fileName : context.fileList()) { +// try { +// filters.add((Filter) fetchFromFilename(fileName)); +// } catch (ClassCastException | IOException e) {} +// } return filters; } @@ -129,11 +132,11 @@ class InternalStorageProvider implements StorageProvider, Filt @Override public Filter getFilter(String key) { - try { - return (Filter) fetch(key, Filter.class); - } catch (ClassCastException | IOException e) { +// try { +// return (Filter) fetch(key, Filter.class); +// } catch (ClassCastException | IOException e) { return null; - } +// } } @Override diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java index b7a0d73..e32b7e6 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerAllFeedsFragment.java @@ -10,13 +10,12 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import com.android.volley.VolleyError; - -import org.rssin.listener.FallibleListener; +import org.rssin.listener.RealtimeListener; import org.rssin.rssin.FeedLoaderAndSorter; import org.rssin.rssin.R; import org.rssin.rssin.SortedFeedItemContainer; +import java.util.ArrayList; import java.util.List; /** @@ -42,24 +41,30 @@ public class NavigationDrawerAllFeedsFragment extends Fragment { RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context); mRecyclerView.setLayoutManager(mLayoutManager); + final FeedItemAdapter feedItemAdapter = new FeedItemAdapter(new ArrayList()); + mRecyclerView.setAdapter(feedItemAdapter); + mRecyclerView.setHasFixedSize(true); + /** - * @todo Load feeds in separate thread so that the UI is immediately available - * * @todo Now, feed items are only returned after *all* feeds have been loaded. With many * filters that may take a while, so it would be preferable to return intermediate * results. We could do this for example with {@link org.rssin.listener.RealtimeListener} */ FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(FeedsList.getInstance().getFeeds()); - loaderAndSorter.getFilteredFeedItems(context, new VolleyFetcher(context), new FallibleListener, VolleyError>() { + loaderAndSorter.getFilteredFeedItems(context, VolleyFetcher.getInstance(context), new RealtimeListener, Object>() { + @Override + public void finish() { + // @todo finish + } + @Override public void onReceive(List data) { - FeedItemAdapter feedItemAdapter = new FeedItemAdapter(data); - mRecyclerView.setAdapter(feedItemAdapter); - mRecyclerView.setHasFixedSize(true); + feedItemAdapter.feedItems = data; + feedItemAdapter.notifyDataSetChanged(); } @Override - public void onError(VolleyError error) { + public void onError(Object error) { Frontend.error(context, R.string.error_net_load); } }); diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java index 0f33aca..66b808b 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerFeedFragment.java @@ -13,6 +13,7 @@ import android.view.ViewGroup; import com.android.volley.VolleyError; import org.rssin.listener.FallibleListener; +import org.rssin.listener.RealtimeListener; import org.rssin.rssin.Feed; import org.rssin.rssin.FeedLoaderAndSorter; import org.rssin.rssin.R; @@ -67,24 +68,30 @@ public class NavigationDrawerFeedFragment extends Fragment { List singleFeedList = new ArrayList(); singleFeedList.add(feed); + final FeedItemAdapter feedItemAdapter = new FeedItemAdapter(new ArrayList()); + mRecyclerView.setAdapter(feedItemAdapter); + mRecyclerView.setHasFixedSize(true); + /** - * @todo Load feeds in separate thread so that the UI is immediately available - * * @todo Now, feed items are only returned after *all* feeds have been loaded. With many * filters that may take a while, so it would be preferable to return intermediate * results. We could do this for example with {@link org.rssin.listener.RealtimeListener} */ FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(singleFeedList); - loaderAndSorter.getFilteredFeedItems(context, new VolleyFetcher(context), new FallibleListener, VolleyError>() { + loaderAndSorter.getFilteredFeedItems(context, VolleyFetcher.getInstance(context), new RealtimeListener, Object>() { + @Override + public void finish() { + // @todo finish + } + @Override public void onReceive(List data) { - FeedItemAdapter feedItemAdapter = new FeedItemAdapter(data); - mRecyclerView.setAdapter(feedItemAdapter); - mRecyclerView.setHasFixedSize(true); + feedItemAdapter.feedItems = data; + feedItemAdapter.notifyDataSetChanged(); } @Override - public void onError(VolleyError error) { + public void onError(Object error) { Frontend.error(context, R.string.error_net_load); } }); diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java index 74be14a..ececd81 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerFilterFragment.java @@ -13,12 +13,14 @@ import android.view.ViewGroup; import com.android.volley.VolleyError; import org.rssin.listener.FallibleListener; +import org.rssin.listener.RealtimeListener; import org.rssin.rssin.FeedLoaderAndSorter; import org.rssin.rssin.Filter; import org.rssin.rssin.R; import org.rssin.rssin.SortedFeedItemContainer; import java.io.IOException; +import java.util.ArrayList; import java.util.List; /** @@ -66,24 +68,30 @@ public class NavigationDrawerFilterFragment extends Fragment { filter.ensureFeeds(DefaultStorageProvider.getInstance(context)); + final FeedItemAdapter feedItemAdapter = new FeedItemAdapter(new ArrayList()); + mRecyclerView.setAdapter(feedItemAdapter); + mRecyclerView.setHasFixedSize(true); + /** - * @todo Load feeds in separate thread so that the UI is immediately available - * * @todo Now, feed items are only returned after *all* feeds have been loaded. With many * filters that may take a while, so it would be preferable to return intermediate * results. We could do this for example with {@link org.rssin.listener.RealtimeListener} */ FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(filter.getFeeds()); - loaderAndSorter.getFilteredFeedItems(context, new VolleyFetcher(context), new FallibleListener, VolleyError>() { + loaderAndSorter.getFilteredFeedItems(context, VolleyFetcher.getInstance(context), new RealtimeListener, Object>() { + @Override + public void finish() { + // @todo finish + } + @Override public void onReceive(List data) { - FeedItemAdapter feedItemAdapter = new FeedItemAdapter(data); - mRecyclerView.setAdapter(feedItemAdapter); - mRecyclerView.setHasFixedSize(true); + feedItemAdapter.feedItems = data; + feedItemAdapter.notifyDataSetChanged(); } @Override - public void onError(VolleyError error) { + public void onError(Object error) { Frontend.error(context, R.string.error_net_load); } }); diff --git a/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java b/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java index dbfcc9a..ffcf0e1 100755 --- a/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java +++ b/app/src/main/java/org/rssin/android/SharedPreferencesStorageProvider.java @@ -168,19 +168,6 @@ class SharedPreferencesStorageProvider implements StorageProvider, FilterStorage @Override public List allFeeds() { Set names = context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).getStringSet("feeds", new HashSet()); - if (names.isEmpty() && !context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).getBoolean("firstload", false)) { - String[] feedsList = context.getResources().getStringArray(R.array.default_feeds); - /*for (String url : feedsList) { - try { - Feed f = new Feed(url); - f.store(this); - } catch (Exception e) { - Log.w("SPSP", "Couldn't add " + url, e); - } - }*/ - context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).edit().putBoolean("firstload", true).apply(); - names = context.getSharedPreferences(ADMIN_PREF_KEY, Context.MODE_PRIVATE).getStringSet("feeds", new HashSet()); - } List feeds = new ArrayList<>(); for (String name : names) { Feed feed = getFeed(name); diff --git a/app/src/main/java/org/rssin/android/VolleyFetcher.java b/app/src/main/java/org/rssin/android/VolleyFetcher.java index af6895e..9aa7c03 100644 --- a/app/src/main/java/org/rssin/android/VolleyFetcher.java +++ b/app/src/main/java/org/rssin/android/VolleyFetcher.java @@ -19,14 +19,22 @@ import org.rssin.listener.Listener; */ class VolleyFetcher implements Fetcher { - private final Context context; + private static VolleyFetcher instance; + private final RequestQueue requestQueue; - public VolleyFetcher(Context context) { - this.context = context; + private VolleyFetcher(Context context) { requestQueue = Volley.newRequestQueue(context); } + public static VolleyFetcher getInstance(Context context) { + if (instance == null) { + instance = new VolleyFetcher(context); + } + + return instance; + } + @Override public void fetch(Request request) { fetch(request, null); diff --git a/app/src/main/java/org/rssin/listener/RealtimeListener.java b/app/src/main/java/org/rssin/listener/RealtimeListener.java index 4a2ac3e..cb63b33 100644 --- a/app/src/main/java/org/rssin/listener/RealtimeListener.java +++ b/app/src/main/java/org/rssin/listener/RealtimeListener.java @@ -4,6 +4,6 @@ package org.rssin.listener; * The RealtimeListener lets you call onReceive() multiple times. * When all data has been sent, call finish(). */ -public interface RealtimeListener extends Listener { +public interface RealtimeListener extends FallibleListener { void finish(); } diff --git a/app/src/main/java/org/rssin/neurons/FeedSorter.java b/app/src/main/java/org/rssin/neurons/FeedSorter.java index 0af57ae..d2605f1 100755 --- a/app/src/main/java/org/rssin/neurons/FeedSorter.java +++ b/app/src/main/java/org/rssin/neurons/FeedSorter.java @@ -24,7 +24,7 @@ public class FeedSorter implements Storable { private static final long serialVersionUID = 0; private final SentenceSplitter splitter = new SentenceSplitter(); - private MultiNeuralNetwork nn = new MultiNeuralNetwork(25, 50); + private MultiNeuralNetwork nn = new MultiNeuralNetwork(10, 50); private List trainingCases = new ArrayList<>(); private int[] isNthMonthInput = new int[12]; @@ -34,36 +34,6 @@ public class FeedSorter implements Storable { private Hashtable wordInputs = new Hashtable<>(); private Hashtable authorInputs = new Hashtable<>(); - private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException { - stream.writeObject(nn); - SerializationTools.writeList(trainingCases, stream); - SerializationTools.writeArray(isNthMonthInput, stream); - SerializationTools.writeArray(isNthWeekDayInput, stream); - stream.writeInt(isMorning); - stream.writeInt(isAfternoon); - stream.writeInt(isEvening); - stream.writeInt(isNight); - stream.writeInt(biasInput); - stream.writeObject(categoryInputs); - stream.writeObject(wordInputs); - stream.writeObject(authorInputs); - } - - private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { - nn = (MultiNeuralNetwork) stream.readObject(); - trainingCases = SerializationTools.readList(stream); - isNthMonthInput = SerializationTools.readArrayInt(stream); - isNthWeekDayInput = SerializationTools.readArrayInt(stream); - isMorning = stream.readInt(); - isAfternoon = stream.readInt(); - isEvening = stream.readInt(); - isNight = stream.readInt(); - biasInput = stream.readInt(); - categoryInputs = (Hashtable) stream.readObject(); - wordInputs = (Hashtable) stream.readObject(); - authorInputs = (Hashtable) stream.readObject(); - } - public FeedSorter() { biasInput = nn.addInput(); for (int i = 0; i < 12; i++) { @@ -189,16 +159,16 @@ public class FeedSorter implements Storable { * @param items The list of items. * @return A new, sorted, list of items. */ - public List sortItems(List items) { + public synchronized void sortItems(List items) { final int SECONDS_IN_DAY = 24 * 60 * 60; for (SortedFeedItemContainer item : items) { - PredictionInterface prediction = getPrediction(item.getFeeditem()); - item.setScore((long) (item.getFeeditem().getPubDate().getTime() / 1000 + prediction.getOutput() * SECONDS_IN_DAY)); + if (!item.hasScore()) { + PredictionInterface prediction = getPrediction(item.getFeeditem()); + item.setScore((long) (item.getFeeditem().getPubDate().getTime() / 1000 + prediction.getOutput() * SECONDS_IN_DAY)); + } } Collections.sort(items); - - return items; } } diff --git a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java index 9ba40e0..420f43d 100755 --- a/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java +++ b/app/src/main/java/org/rssin/neurons/MultiNeuralNetwork.java @@ -13,14 +13,6 @@ class MultiNeuralNetwork implements Serializable { private static final long serialVersionUID = 0; private NeuralNetwork[] networks; - private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException { - SerializationTools.writeArray(networks, stream); - } - - private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { - networks = SerializationTools.readArray(stream, NeuralNetwork.class); - } - public MultiNeuralNetwork(int numNetworks, int numHiddenNodes) { networks = new NeuralNetwork[numNetworks]; for (int i = 0; i < networks.length; i++) { diff --git a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java index 972f9de..e050145 100755 --- a/app/src/main/java/org/rssin/neurons/NeuralNetwork.java +++ b/app/src/main/java/org/rssin/neurons/NeuralNetwork.java @@ -15,16 +15,6 @@ class NeuralNetwork implements Serializable { private Neuron[] hiddenNodes; private Neuron outputNode; - private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException { - SerializationTools.writeArray(hiddenNodes, stream); - stream.writeObject(outputNode); - } - - private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { - hiddenNodes = SerializationTools.readArray(stream, Neuron.class); - outputNode = (Neuron) stream.readObject(); - } - NeuralNetwork(int numHiddenNodes) { if (numHiddenNodes < 1) { throw new IllegalArgumentException("numHiddenNodes must be > 0"); diff --git a/app/src/main/java/org/rssin/neurons/Neuron.java b/app/src/main/java/org/rssin/neurons/Neuron.java index da0e4ca..e29e218 100755 --- a/app/src/main/java/org/rssin/neurons/Neuron.java +++ b/app/src/main/java/org/rssin/neurons/Neuron.java @@ -17,15 +17,6 @@ class Neuron implements Serializable { private List weights = new ArrayList<>(); - private synchronized void writeObject(java.io.ObjectOutputStream stream) throws IOException { - SerializationTools.writeList(weights, stream); - } - - private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { - weights = SerializationTools.readList(stream); - } - - public Neuron() { } diff --git a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java index a317a27..5e9a05a 100755 --- a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java +++ b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java @@ -30,25 +30,68 @@ public class FeedLoaderAndSorter { * @param fetcher HTTP Fetcher * @param listener Listener for when the fetcher finishes */ - public void getFilteredFeedItems(Context context, Fetcher fetcher, final Listener> listener) - { + public void getFilteredFeedItems( + Context context, + Fetcher fetcher, + final RealtimeListener, Object> listener) { final List resultingItems = new ArrayList<>(); final Counter counter = new Counter(feeds.size()); final FeedSorter sorter = FeedSorterProvider.getInstance(context).getFeedSorter(); for (Feed feed : feeds) { + Loader loader = new Loader( + feed, + fetcher, + listener, + resultingItems, + counter, + sorter + ); + Thread thread = new Thread(loader); + thread.start(); + } + } + + private static class Loader implements Runnable { + + final private Feed feed; + final private Fetcher fetcher; + final private RealtimeListener,Object> listener; + final private List resultingItems; + final private Counter counter; + final private FeedSorter feedSorter; + + public Loader( + Feed feed, + Fetcher fetcher, + RealtimeListener,Object> listener, + List resultingItems, + Counter counter, + FeedSorter feedSorter) { + this.feed = feed; + this.fetcher = fetcher; + this.listener = listener; + this.resultingItems = resultingItems; + this.counter = counter; + this.feedSorter = feedSorter; + } + + @Override + public void run() { final FeedLoader loader = new FeedLoader(feed.getURL()); loader.fetchXML(fetcher, new FallibleListener() { @Override public void onReceive(Object data) { - for (FeedItem item : loader.getFeed().getPosts()) { - resultingItems.add(new SortedFeedItemContainer(item)); + List feedItems = loader.getFeed().getPosts(); + synchronized (resultingItems) { + for (FeedItem item : feedItems) { + resultingItems.add(new SortedFeedItemContainer(item)); + } + feedSorter.sortItems(resultingItems); } - List sorted = sorter.sortItems(resultingItems); - if (counter.decr().isZero() || listener.getClass() == RealtimeListener.class) { - listener.onReceive(sorted); + listener.onReceive(resultingItems); if (counter.decr().isZero() && listener.getClass() == RealtimeListener.class) { ((RealtimeListener) listener).finish(); } @@ -57,9 +100,7 @@ public class FeedLoaderAndSorter { @Override public void onError(Object error) { - try { - ((FallibleListener) listener).onError(error); - } catch (ClassCastException e) {} + listener.onError(error); } }); } diff --git a/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java b/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java index 2a69bfa..384f43c 100755 --- a/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java +++ b/app/src/main/java/org/rssin/rssin/SortedFeedItemContainer.java @@ -3,8 +3,6 @@ package org.rssin.rssin; import android.content.Context; import org.rssin.android.FeedSorterProvider; -import org.rssin.android.FiltersList; -import org.rssin.neurons.FeedSorter; import org.rssin.neurons.Feedback; import org.rssin.rss.FeedItem; @@ -15,24 +13,22 @@ import java.io.Serializable; */ public class SortedFeedItemContainer implements Comparable, Serializable { private FeedItem feeditem; - private long score; + private long score = -1; public SortedFeedItemContainer(FeedItem feeditem) { this.feeditem = feeditem; - this.setScore(-1); } public FeedItem getFeeditem() { return feeditem; } - public long getScore() { - if(score == -1) - { - throw new UnsupportedOperationException("score not set"); - } + public boolean hasScore() { + return score != 0; + } + public long getScore() { return score; } diff --git a/app/src/main/res/values/feeds.xml b/app/src/main/res/values/feeds.xml index e4ae386..384739b 100644 --- a/app/src/main/res/values/feeds.xml +++ b/app/src/main/res/values/feeds.xml @@ -1,86 +1,20 @@ - http://feeds.bbci.co.uk/news/business/rss.xml - http://feeds.bbci.co.uk/news/entertainment_and_arts/rss.xml - http://feeds.bbci.co.uk/news/health/rss.xml http://feeds.bbci.co.uk/news/politics/rss.xml http://feeds.bbci.co.uk/news/science_and_environment/rss.xml http://feeds.bbci.co.uk/news/technology/rss.xml - http://feeds.bbci.co.uk/news/uk/rss.xml http://feeds.bbci.co.uk/news/world/rss.xml http://feeds.bbci.co.uk/sport/0/rss.xml - http://feeds.foxnews.com/foxnews/internal/travel/mixed - http://feeds.foxnews.com/foxnews/opinion http://feeds.foxnews.com/foxnews/politics http://feeds.foxnews.com/foxnews/science - http://feeds.foxnews.com/foxnews/section/lifestyle http://feeds.foxnews.com/foxnews/sports http://feeds.foxnews.com/foxnews/tech - http://feeds.mashable.com/mashable/business - http://feeds.mashable.com/mashable/entertainment - http://feeds.mashable.com/mashable/socialmedia - http://feeds.mashable.com/mashable/tech - http://feeds.reuters.com/news/artsculture - http://feeds.reuters.com/news/economy - http://feeds.reuters.com/news/reutersmedia - http://feeds.reuters.com/news/wealth - http://feeds.reuters.com/reuters/businessNews - http://feeds.reuters.com/reuters/entertainment http://feeds.reuters.com/reuters/environment http://feeds.reuters.com/reuters/financialsNews - http://feeds.reuters.com/reuters/healthNews - http://feeds.reuters.com/reuters/hotStocksNews - http://feeds.reuters.com/reuters/lifestyle - http://feeds.reuters.com/reuters/oddlyEnoughNews - http://feeds.reuters.com/Reuters/PoliticsNews - http://feeds.reuters.com/reuters/scienceNews - http://feeds.reuters.com/reuters/sportsNews - http://feeds.reuters.com/reuters/technologyNews - http://feeds.reuters.com/reuters/technologysectorNews - http://feeds.reuters.com/reuters/UShealthcareNews http://feeds.reuters.com/reuters/worldNews - http://rss.cnn.com/rss/edition_entertainment.rss - http://rss.cnn.com/rss/edition_space.rss - http://rss.cnn.com/rss/edition_sport.rss - http://rss.cnn.com/rss/edition_technology.rss - http://rss.cnn.com/rss/money_news_international.rss - http://rss.cnn.com/rss/si_topstories.rss - http://rss.nytimes.com/services/xml/rss/nyt/Books.xml - http://rss.nytimes.com/services/xml/rss/nyt/Business.xml - http://rss.nytimes.com/services/xml/rss/nyt/Dance.xml - http://rss.nytimes.com/services/xml/rss/nyt/Economy.xml http://rss.nytimes.com/services/xml/rss/nyt/Environment.xml - http://rss.nytimes.com/services/xml/rss/nyt/FashionandStyle.xml - http://rss.nytimes.com/services/xml/rss/nyt/MediaandAdvertising.xml - http://rss.nytimes.com/services/xml/rss/nyt/Movies.xml http://rss.nytimes.com/services/xml/rss/nyt/Music.xml - http://rss.nytimes.com/services/xml/rss/nyt/Science.xml - http://rss.nytimes.com/services/xml/rss/nyt/Sports.xml - http://rss.nytimes.com/services/xml/rss/nyt/Technology.xml http://rss.nytimes.com/services/xml/rss/nyt/Travel.xml - http://www.cnet.com/rss/news/ - http://www.dailymail.co.uk/health/index.rss - http://www.dailymail.co.uk/money/index.rss - http://www.dailymail.co.uk/sciencetech/index.rss - http://www.dailymail.co.uk/sport/index.rss - http://www.dailymail.co.uk/tvshowbiz/index.rss - http://www.thesundaily.my/rss/business - http://www.thesundaily.my/rss/lifestyle/food - http://www.thesundaily.my/rss/lifestyle/health - http://www.thesundaily.my/rss/lifestyle/tech - http://www.thesundaily.my/rss/lifestyle/travel - http://www.thesundaily.my/rss/media-marketing - http://www.thesundaily.my/rss/opinion - http://www.thesundaily.my/rss/showbiz - http://www.thesundaily.my/rss/sports - http://www.thesundaily.my/rss/style - http://www.washingtontimes.com/rss/headlines/culture/autos/ - http://www.washingtontimes.com/rss/headlines/culture/entertainment/ - http://www.washingtontimes.com/rss/headlines/culture/health/ - http://www.washingtontimes.com/rss/headlines/culture/travel/ - http://www.washingtontimes.com/rss/headlines/news/politics/ - http://www.washingtontimes.com/rss/headlines/opinion/ - http://www.washingtontimes.com/rss/headlines/sports/ \ No newline at end of file -- cgit v1.2.3 From 7d0ebf14c5972f4b3191cfe8ae769c6cbd7d1ea6 Mon Sep 17 00:00:00 2001 From: Size43 Date: Wed, 10 Jun 2015 13:31:56 +0200 Subject: Feed titles from RSS feeds --- README.md | 2 +- .../main/java/org/rssin/android/FeedsActivity.java | 15 ++++++- .../org/rssin/android/FilterSettingsActivity.java | 15 ++++++- .../NavigationDrawerManageFeedsFragment.java | 12 +++++- app/src/main/java/org/rssin/rssin/Feed.java | 47 ++++++++++++++++------ 5 files changed, 74 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index b31a843..8b7689c 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,12 @@ Copyright © 2015 Randy Wanga, Jos Craaijo, Joep Bernards, Camil Staps. All (see also the @todo markings throughout the source code) ## High priority +* Hamburger menu does not highlight selected item ## Normal priority * Background sync & notifications * Add tutorial (e.g.: at first startup, walk user through creating first filter) * Swipe left & right for (dis)like -* Extract feed title from feed ## Low priority * Readability plugin to view whole article diff --git a/app/src/main/java/org/rssin/android/FeedsActivity.java b/app/src/main/java/org/rssin/android/FeedsActivity.java index 87edab0..37e8434 100755 --- a/app/src/main/java/org/rssin/android/FeedsActivity.java +++ b/app/src/main/java/org/rssin/android/FeedsActivity.java @@ -20,6 +20,7 @@ import android.widget.EditText; import android.widget.ListView; import android.widget.TextView; +import org.rssin.listener.FallibleListener; import org.rssin.rssin.Feed; import org.rssin.rssin.R; @@ -115,13 +116,25 @@ public class FeedsActivity extends ActionBarActivity { input.setMaxLines(1); input.requestFocus(); + final Context context = feedsView.getContext(); + AlertDialog dialog = alert .setView(input) .setPositiveButton(getResources().getString(R.string.button_apply), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { String value = input.getText().toString(); try { - Feed f = new Feed(value); + Feed f = new Feed(value, context, new VolleyFetcher(context), new FallibleListener() { + @Override + public void onError(Object error) { + + } + + @Override + public void onReceive(String data) { + feedAdapter.notifyDataSetChanged(); + } + }); f.store(DefaultStorageProvider.getInstance(getBaseContext())); feedsList.getFeeds().add(f); feedAdapter.notifyDataSetChanged(); diff --git a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java index a38c7bc..670c986 100755 --- a/app/src/main/java/org/rssin/android/FilterSettingsActivity.java +++ b/app/src/main/java/org/rssin/android/FilterSettingsActivity.java @@ -25,6 +25,7 @@ import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; +import org.rssin.listener.FallibleListener; import org.rssin.rssin.Feed; import org.rssin.rssin.Filter; import org.rssin.rssin.R; @@ -99,6 +100,8 @@ public class FilterSettingsActivity extends ActionBarActivity { } }); + final Context context = feedsListView.getContext(); + /** * @todo Allow users to enter links without scheme (http:// ...) */ @@ -109,7 +112,17 @@ public class FilterSettingsActivity extends ActionBarActivity { String value = editText.getText().toString(); try { URL url = new URL(value); - Feed feed = new Feed(url); + Feed feed = new Feed(url, context, new VolleyFetcher(context), new FallibleListener() { + @Override + public void onError(Object error) { + + } + + @Override + public void onReceive(String data) { + feedAdapter.notifyDataSetChanged(); + } + }); try { feed.store(DefaultStorageProvider.getInstance()); FeedsList.getInstance().getFeeds().add(feed); diff --git a/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java b/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java index e239588..bc2b710 100755 --- a/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java +++ b/app/src/main/java/org/rssin/android/NavigationDrawerManageFeedsFragment.java @@ -134,7 +134,17 @@ public class NavigationDrawerManageFeedsFragment extends Fragment { public void onClick(DialogInterface dialog, int whichButton) { String value = input.getText().toString(); try { - Feed f = new Feed(value); + Feed f = new Feed(value, context, new VolleyFetcher(context), new FallibleListener() { + @Override + public void onError(Object error) { + + } + + @Override + public void onReceive(String data) { + feedAdapter.notifyDataSetChanged(); + } + }); f.store(DefaultStorageProvider.getInstance(context)); feedsList.getFeeds().add(f); feedAdapter.notifyDataSetChanged(); diff --git a/app/src/main/java/org/rssin/rssin/Feed.java b/app/src/main/java/org/rssin/rssin/Feed.java index ae8b5f2..d108017 100755 --- a/app/src/main/java/org/rssin/rssin/Feed.java +++ b/app/src/main/java/org/rssin/rssin/Feed.java @@ -1,9 +1,13 @@ package org.rssin.rssin; +import android.content.Context; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; +import org.rssin.http.Fetcher; +import org.rssin.listener.FallibleListener; +import org.rssin.rss.FeedLoader; import org.rssin.serialization.Jsonable; import org.rssin.storage.FeedStorageProvider; import org.rssin.storage.Storable; @@ -34,14 +38,13 @@ public class Feed implements Storable, Comparable, Jsonable { */ private Object storageKey; - public Feed(URL url) { + public Feed(URL url, Context context, Fetcher fetcher, FallibleListener titleHasChanged) { this.url = url; - setTitleFromURL(); + setTitleFromURL(context, fetcher, titleHasChanged); } - public Feed(String url) throws MalformedURLException { - this.url = new URL(url); - setTitleFromURL(); + public Feed(String url, Context context, Fetcher fetcher, FallibleListener titleHasChanged) throws MalformedURLException { + this(new URL(url), context, fetcher, titleHasChanged); } public Feed(URL url, String title) { @@ -90,15 +93,33 @@ public class Feed implements Storable, Comparable, Jsonable { * Cleverly make up a title based on the URL * @todo make it really really clever */ - public void setTitleFromURL() { - String title = url.getHost(); - String url = this.url.toString(); - if (url.lastIndexOf('/') < url.lastIndexOf('.') && url.lastIndexOf('/') != -1) { - title += " " + url.substring(url.lastIndexOf('/') + 1, url.lastIndexOf('.')); - } else if (url.lastIndexOf('/') != -1) { - title += " " + url.substring(url.lastIndexOf('/') + 1); + public void setTitleFromURL(Context context, Fetcher fetcher, final FallibleListener titlehasChanged) { + String newTitle = url.getHost(); + String strUrl = url.toString(); + if (strUrl.lastIndexOf('/') < strUrl.lastIndexOf('.') && strUrl.lastIndexOf('/') != -1) { + newTitle += " " + strUrl.substring(strUrl.lastIndexOf('/') + 1, strUrl.lastIndexOf('.')); + } else if (strUrl.lastIndexOf('/') != -1) { + newTitle += " " + strUrl.substring(strUrl.lastIndexOf('/') + 1); } - this.title = title; + + title = newTitle; + + final FeedLoader loader = new FeedLoader(url); + loader.fetchXML(fetcher, new FallibleListener() { + @Override + public void onError(Object error) { + // Keep title the same, based on the URL + if(titlehasChanged != null){ + titlehasChanged.onError(error); + } + } + + @Override + public void onReceive(Object data) { + title = loader.getFeed().getTitle(); + titlehasChanged.onReceive(title); + } + }); } @Override -- cgit v1.2.3