diff options
Diffstat (limited to 'app/src/main/java')
-rw-r--r-- | app/src/main/java/org/rssin/android/FilterActivity.java | 95 | ||||
-rwxr-xr-x | app/src/main/java/org/rssin/neurons/FeedSorter.java | 13 | ||||
-rwxr-xr-x | app/src/main/java/org/rssin/neurons/Feedback.java | 3 | ||||
-rwxr-xr-x[-rw-r--r--] | app/src/main/java/org/rssin/rss/FeedItem.java | 64 | ||||
-rwxr-xr-x | app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java | 14 | ||||
-rwxr-xr-x | app/src/main/java/org/rssin/rssin/UnifiedFilterLoader.java | 84 |
6 files changed, 225 insertions, 48 deletions
diff --git a/app/src/main/java/org/rssin/android/FilterActivity.java b/app/src/main/java/org/rssin/android/FilterActivity.java index b1be925..6c827d1 100644 --- a/app/src/main/java/org/rssin/android/FilterActivity.java +++ b/app/src/main/java/org/rssin/android/FilterActivity.java @@ -5,6 +5,8 @@ import android.content.Context; import android.content.Intent; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.text.Html; import android.view.LayoutInflater; import android.view.Menu; @@ -31,10 +33,17 @@ public class FilterActivity extends ActionBarActivity { private FiltersList filtersList; private Filter filter; + private RecyclerView mRecyclerView; + private RecyclerView.Adapter mAdapter; + private RecyclerView.LayoutManager mLayoutManager; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_filter); + mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view); + mLayoutManager = new LinearLayoutManager(this); + mRecyclerView.setLayoutManager(mLayoutManager); try { filtersList = FiltersList.getInstance(this); @@ -52,13 +61,14 @@ public class FilterActivity extends ActionBarActivity { setTitle(filter.getTitle()); final Activity activity = this; - final ListView itemsListView = (ListView) findViewById(R.id.filter_items_list); FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(filter); loaderAndSorter.getFilteredFeedItems(new VolleyFetcher(this), new FallibleListener<List<FeedItem>, VolleyError>() { @Override public void onReceive(List<FeedItem> data) { - FeedItemAdapter feedItemAdapter = new FeedItemAdapter(activity, R.layout.item_feeditem, data); - itemsListView.setAdapter(feedItemAdapter); + + FeedItemAdapter feedItemAdapter = new FeedItemAdapter(data); + mRecyclerView.setAdapter(feedItemAdapter); + mRecyclerView.setHasFixedSize(true); } @Override @@ -101,49 +111,72 @@ public class FilterActivity extends ActionBarActivity { /** * Custom ArrayAdapter to display Keywords */ - private static class FeedItemAdapter extends ArrayAdapter<FeedItem> { - Context context; - int layoutResourceId; + private static class FeedItemAdapter extends RecyclerView.Adapter<FeedItemAdapter.KeywordHolder> { List<FeedItem> feedItems; - public FeedItemAdapter(Context context, int resource, List<FeedItem> objects) { - super(context, resource, objects); - this.context = context; - layoutResourceId = resource; + public FeedItemAdapter(List<FeedItem> objects) { feedItems = objects; } - @Override - public View getView(int position, View convertView, ViewGroup parent) { - View row = convertView; - KeywordHolder holder = null; - - if (row == null) { - LayoutInflater inflater = ((Activity) context).getLayoutInflater(); - row = inflater.inflate(layoutResourceId, parent, false); +// @Override +// public View getView(int position, View convertView, ViewGroup parent) { +// View row = convertView; +// KeywordHolder holder = null; +// +// if (row == null) { +// LayoutInflater inflater = ((Activity) context).getLayoutInflater(); +// row = inflater.inflate(layoutResourceId, parent, false); +// +// holder = new KeywordHolder(); +// holder.title = (TextView) row.findViewById(R.id.feeditem_title); +// holder.summary = (TextView) row.findViewById(R.id.feeditem_summary); +// +// row.setTag(holder); +// } else { +// holder = (KeywordHolder) row.getTag(); +// } +// +// FeedItem feedItem = feedItems.get(position); +// holder.title.setText(feedItem.getTitle()); +// holder.summary.setText(Html.fromHtml(feedItem.getDescription())); +// +// return row; +// } - holder = new KeywordHolder(); - holder.title = (TextView) row.findViewById(R.id.feeditem_title); - holder.summary = (TextView) row.findViewById(R.id.feeditem_summary); - - row.setTag(holder); - } else { - holder = (KeywordHolder) row.getTag(); - } + @Override + public KeywordHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View itemView = LayoutInflater. + from(parent.getContext()). + inflate(R.layout.item_feeditem, parent, false); + return new KeywordHolder(itemView); + } - FeedItem feedItem = feedItems.get(position); - holder.title.setText(feedItem.getTitle()); - holder.summary.setText(Html.fromHtml(feedItem.getDescription())); + @Override + public void onBindViewHolder(KeywordHolder holder, int position) { + FeedItem item = feedItems.get(position); + holder.title.setText(item.getTitle()); + holder.summary.setText(item.getDescription()); + } - return row; + @Override + public int getItemCount() { + return feedItems.size(); } /** * TextViews holder */ - private static class KeywordHolder { + static class KeywordHolder extends RecyclerView.ViewHolder { TextView title; TextView summary; + + public KeywordHolder(View itemView) { + super(itemView); + title = (TextView) itemView.findViewById(R.id.feeditem_title); + summary = (TextView) itemView.findViewById(R.id.feeditem_summary); + } } + + } } diff --git a/app/src/main/java/org/rssin/neurons/FeedSorter.java b/app/src/main/java/org/rssin/neurons/FeedSorter.java index 910057f..fe1e998 100755 --- a/app/src/main/java/org/rssin/neurons/FeedSorter.java +++ b/app/src/main/java/org/rssin/neurons/FeedSorter.java @@ -33,7 +33,7 @@ public class FeedSorter implements Storable { private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
stream.writeObject(nn);
- stream.writeObject(trainingCases);
+ SerializationTools.writeList(trainingCases, stream);
SerializationTools.writeArray(isNthMonthInput, stream);
SerializationTools.writeArray(isNthWeekDayInput, stream);
stream.writeInt(isMorning);
@@ -48,7 +48,7 @@ public class FeedSorter implements Storable { private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
nn = (MultiNeuralNetwork) stream.readObject();
- trainingCases = (List<TrainingCase>) stream.readObject();
+ trainingCases = SerializationTools.readList(stream);
isNthMonthInput = SerializationTools.readArrayInt(stream);
isNthWeekDayInput = SerializationTools.readArrayInt(stream);
isMorning = stream.readInt();
@@ -183,22 +183,17 @@ public class FeedSorter implements Storable { */
public List<FeedItem> sortItems(List<FeedItem> items) {
final int SECONDS_IN_DAY = 24 * 60 * 60;
-
final List<FeedItem> newItems = new ArrayList<>(items);
- final Hashtable<FeedItem, Long> predictions = new Hashtable<>();
for (FeedItem item : newItems) {
PredictionInterface prediction = getPrediction(item);
- predictions.put(item, (long) (prediction.getOutput() * SECONDS_IN_DAY));
+ item.setScore((long) (item.getPubDate().getTime() / 1000 + prediction.getOutput() * SECONDS_IN_DAY));
}
Collections.sort(newItems, new Comparator<FeedItem>() {
@Override
public int compare(FeedItem lhs, FeedItem rhs) {
- long lhsScore = lhs.getPubDate().getTime() / 1000 + predictions.get(lhs);
- long rhsScore = rhs.getPubDate().getTime() / 1000 + predictions.get(rhs);
-
- return (int) Math.signum(rhsScore - lhsScore);
+ return (int) Math.signum(rhs.getScore() - lhs.getScore());
}
});
diff --git a/app/src/main/java/org/rssin/neurons/Feedback.java b/app/src/main/java/org/rssin/neurons/Feedback.java index fe59b1b..59d3246 100755 --- a/app/src/main/java/org/rssin/neurons/Feedback.java +++ b/app/src/main/java/org/rssin/neurons/Feedback.java @@ -2,13 +2,14 @@ package org.rssin.neurons; /**
* @author Jos.
+ * Feedback for the Neural Network.
*/
public enum Feedback {
Like(1.0d), Dislike(-1.0d);
private final double expectedOutput;
- private Feedback(double expectedOutput) {
+ Feedback(double expectedOutput) {
this.expectedOutput = expectedOutput;
}
diff --git a/app/src/main/java/org/rssin/rss/FeedItem.java b/app/src/main/java/org/rssin/rss/FeedItem.java index bb074cd..f7805d8 100644..100755 --- a/app/src/main/java/org/rssin/rss/FeedItem.java +++ b/app/src/main/java/org/rssin/rss/FeedItem.java @@ -15,11 +15,11 @@ public class FeedItem { private String description; private String link; private String author; - private List<String> category = new LinkedList<>(); private String comments; private String enclosure; private String source; - private boolean isRead; + private List<String> category = new LinkedList<>(); + private transient long score = -1; public FeedItem(String guid, Date pubDate, String title, String description, String link, String author, List<String> category, String comments, String enclosure, String source) @@ -123,11 +123,63 @@ public class FeedItem { return title + "\n" + description + " - " + author; } - public boolean isRead() { - return isRead; + @Override + public int hashCode() { + int hash = 17; + + if(guid != null) + { + hash = hash * 23 + guid.hashCode(); + } + + if(link != null) + { + hash = hash * 23 + link.hashCode(); + } + + if(title != null) + { + hash = hash * 23 + title.hashCode(); + } + + if(pubDate != null) + { + hash = hash * 23 + pubDate.hashCode(); + } + + return hash; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof FeedItem)) + return false; + + if (obj == this) + return true; + + FeedItem other = (FeedItem) obj; + return (guid == null && other.guid == null) || (guid != null && guid.equals(other.guid)) + && (pubDate == null && other.pubDate == null) || (pubDate != null && pubDate.equals(other.pubDate)) + && (title == null && other.title == null) || (title != null && title.equals(other.title)) + && (description == null && other.description == null) || (description != null && description.equals(other.description)) + && (link == null && other.link == null) || (link != null && link.equals(other.link)) + && (author == null && other.author == null) || (author != null && author.equals(other.author)) + && (comments == null && other.comments == null) || (comments != null && comments.equals(other.comments)) + && (enclosure == null && other.enclosure == null) || (enclosure != null && enclosure.equals(other.enclosure)) + && (source == null && other.source == null) || (source != null && source.equals(other.source)); + } + + public long getScore() { + if(score == -1) + { + throw new UnsupportedOperationException("score not set"); + } + + return score; } - public void setIsRead(boolean isRead) { - this.isRead = isRead; + public void setScore(long score) { + this.score = score; } } diff --git a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java index 2ec3cfd..e1fbbab 100755 --- a/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java +++ b/app/src/main/java/org/rssin/rssin/FeedLoaderAndSorter.java @@ -85,10 +85,22 @@ public class FeedLoaderAndSorter { {
for(Keyword keyword : filter.getKeywords())
{
- if(contains(item.getTitle(), keyword.getKeyword()))
+ String word = keyword.getKeyword();
+ if(contains(item.getTitle(), word)
+ || contains(item.getAuthor(), word))
{
return true;
}
+
+
+
+ for(String category : item.getCategory())
+ {
+ if(contains(category, word))
+ {
+ return true;
+ }
+ }
}
return filter.getKeywords().size() == 0;
diff --git a/app/src/main/java/org/rssin/rssin/UnifiedFilterLoader.java b/app/src/main/java/org/rssin/rssin/UnifiedFilterLoader.java new file mode 100755 index 0000000..9740380 --- /dev/null +++ b/app/src/main/java/org/rssin/rssin/UnifiedFilterLoader.java @@ -0,0 +1,84 @@ +package org.rssin.rssin;
+
+import org.rssin.http.Fetcher;
+import org.rssin.listener.Listener;
+import org.rssin.listener.RealtimeListener;
+import org.rssin.rss.FeedItem;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+
+/**
+ * @author Jos.
+ * This class merges the FeedItems from multiple Filters together into one list of FeedItems.
+ */
+public class UnifiedFilterLoader {
+
+ private List<Filter> filters;
+ public UnifiedFilterLoader(List<Filter> filters)
+ {
+ this.filters = filters;
+ }
+
+ /**
+ * Loads the feed(s), filters it, sorts it, and returns the result.
+ * @param fetcher HTTP Fetcher
+ * @param listener Listener for when the fetcher finishes
+ */
+ public void getFilteredFeedItems(Fetcher fetcher, final Listener<List<FeedItem>> listener) {
+ // HashSet to make sure that there are no duplicates when merging multiple filters, since different filters
+ // may contain the same feed.
+ final HashSet<FeedItem> resultingItems = new HashSet<>();
+ final Counter counter = new Counter(filters.size());
+
+ for (Filter filter : filters) {
+ // Load the sorted FeedItems from the filters, and combine them.
+ FeedLoaderAndSorter loaderAndSorter = new FeedLoaderAndSorter(filter);
+ loaderAndSorter.getFilteredFeedItems(fetcher, new Listener<List<FeedItem>>() {
+ @Override
+ public void onReceive(List<FeedItem> data) {
+ resultingItems.addAll(data);
+
+ if (counter.decr().isZero() || listener.getClass() == RealtimeListener.class) {
+ ArrayList<FeedItem> newItems = new ArrayList<FeedItem>(resultingItems);
+
+ // Do another sort to make sure the items are still in the correct order.
+ // this uses the score set by the FeedSorter class, which is called
+ // in the Filter class. The Unified inbox does not have a separate network.
+ Collections.sort(newItems, new Comparator<FeedItem>() {
+ @Override
+ public int compare(FeedItem lhs, FeedItem rhs) {
+ return (int) Math.signum(rhs.getScore() - lhs.getScore());
+ }
+ });
+
+ listener.onReceive(newItems);
+ if (counter.decr().isZero() && listener.getClass() == RealtimeListener.class) {
+ ((RealtimeListener) listener).finish();
+ }
+ }
+ }
+ });
+ }
+ }
+
+ private static class Counter {
+ int count;
+
+ Counter (int initial) {
+ count = initial;
+ }
+
+ public Counter decr() {
+ count--;
+ return this;
+ }
+
+ public boolean isZero() {
+ return count == 0;
+ }
+ }
+}
|