diff --git a/app/src/main/java/com/totsp/crossword/Accessor.java b/app/src/main/java/com/totsp/crossword/Accessor.java index 7986d8b3..39ff9d99 100755 --- a/app/src/main/java/com/totsp/crossword/Accessor.java +++ b/app/src/main/java/com/totsp/crossword/Accessor.java @@ -1,48 +1,8 @@ package com.totsp.crossword; -import java.text.SimpleDateFormat; import java.util.Comparator; public interface Accessor extends Comparator { - Accessor DATE_ASC = new Accessor() { - @SuppressWarnings("SimpleDateFormat") - public String getLabel(FileHandle o) { - SimpleDateFormat df = new SimpleDateFormat("EEEEEEEEE MMM dd, yyyy"); - - return df.format(o.getDate()); - } - - public int compare(FileHandle object1, FileHandle object2) { - return object1.getDate() - .compareTo(object2.getDate()); - } - }; - - Accessor DATE_DESC = new Accessor() { - @SuppressWarnings("SimpleDateFormat") - public String getLabel(FileHandle o) { - SimpleDateFormat df = new SimpleDateFormat("EEEEEEEEE MMM dd, yyyy"); - - return df.format(o.getDate()); - } - - public int compare(FileHandle object1, FileHandle object2) { - return object2.getDate() - .compareTo(object1.getDate()); - } - }; - - Accessor SOURCE = new Accessor() { - public String getLabel(FileHandle o) { - return o.getSource(); - } - - public int compare(FileHandle object1, FileHandle object2) { - return object1.getSource() - .compareTo(object2.getSource()); - } - }; - String getLabel(FileHandle o); } diff --git a/app/src/main/java/com/totsp/crossword/Accessors.java b/app/src/main/java/com/totsp/crossword/Accessors.java new file mode 100644 index 00000000..e50936c6 --- /dev/null +++ b/app/src/main/java/com/totsp/crossword/Accessors.java @@ -0,0 +1,72 @@ +package com.totsp.crossword; + +import java.text.SimpleDateFormat; + +final public class Accessors { + private Accessors() {} + + static Accessor DATE_ASC = new Accessor() { + public String getLabel(FileHandle o) { + return getDateLabel(o); + } + + public int compare(FileHandle object1, FileHandle object2) { + int dateComparison = compareDate(object1, object2); + + if (dateComparison == 0) { + return compareSource(object1, object2); + } + + return dateComparison; + } + }; + + static Accessor DATE_DESC = new Accessor() { + public String getLabel(FileHandle o) { + return getDateLabel(o); + } + + public int compare(FileHandle object1, FileHandle object2) { + int dateComparison = compareDate(object2, object1); + + if (dateComparison == 0) { + return compareSource(object1, object2); + } + + return dateComparison; + } + }; + + static Accessor SOURCE = new Accessor() { + public String getLabel(FileHandle o) { + return o.getSource(); + } + + public int compare(FileHandle object1, FileHandle object2) { + int sourceComparison = compareSource(object1, object2); + + if (sourceComparison == 0) { + return compareDate(object2, object1); + } + + return sourceComparison; + } + }; + + @SuppressWarnings("SimpleDateFormat") + private static String getDateLabel(FileHandle o) { + SimpleDateFormat df = new SimpleDateFormat("EEEEEEEEE MMM dd, yyyy"); + + return df.format(o.getDate()); + } + + private static int compareDate(FileHandle object1, FileHandle object2) { + return object1.getDate() + .compareTo(object2.getDate()); + } + + private static int compareSource(FileHandle object1, FileHandle object2) { + return object1.getSource() + .compareTo(object2.getSource()); + } +} diff --git a/app/src/main/java/com/totsp/crossword/BrowseActivity.java b/app/src/main/java/com/totsp/crossword/BrowseActivity.java index cb368db2..af34021e 100755 --- a/app/src/main/java/com/totsp/crossword/BrowseActivity.java +++ b/app/src/main/java/com/totsp/crossword/BrowseActivity.java @@ -71,7 +71,7 @@ public class BrowseActivity extends ShortyzActivity implements RecyclerItemClick private static final int REQUEST_WRITE_STORAGE = 1002; private static final long DAY = 24L * 60L * 60L * 1000L; private static final Logger LOGGER = Logger.getLogger(BrowseActivity.class.getCanonicalName()); - private Accessor accessor = Accessor.DATE_DESC; + private Accessor accessor = Accessors.DATE_DESC; private SeparatedRecyclerViewAdapter currentAdapter = null; private Dialog downloadDialog; private File archiveFolder = new File(Environment.getExternalStorageDirectory(), "crosswords/archive"); @@ -291,21 +291,21 @@ public boolean onOptionsItemSelected(MenuItem item) { this.startActivity(i); } else if (item.getTitle() .equals("By Source")) { - this.accessor = Accessor.SOURCE; + this.accessor = Accessors.SOURCE; prefs.edit() .putInt("sort", 2) .apply(); this.render(); } else if (item.getTitle() .equals("By Date (Ascending)")) { - this.accessor = Accessor.DATE_ASC; + this.accessor = Accessors.DATE_ASC; prefs.edit() .putInt("sort", 1) .apply(); this.render(); } else if (item.getTitle() .equals("By Date (Descending)")) { - this.accessor = Accessor.DATE_DESC; + this.accessor = Accessors.DATE_DESC; prefs.edit() .putInt("sort", 0) .apply(); @@ -391,17 +391,17 @@ public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { switch (prefs.getInt("sort", 0)) { case 2: - this.accessor = Accessor.SOURCE; + this.accessor = Accessors.SOURCE; break; case 1: - this.accessor = Accessor.DATE_ASC; + this.accessor = Accessors.DATE_ASC; break; default: - this.accessor = Accessor.DATE_DESC; + this.accessor = Accessors.DATE_DESC; } @@ -986,7 +986,7 @@ public void onBindViewHolder(FileViewHolder holder, int position) { date.setText(df.format(handle.getDate())); - if (accessor == Accessor.SOURCE) { + if (accessor == Accessors.SOURCE) { date.setVisibility(View.VISIBLE); } else { date.setVisibility(View.GONE); diff --git a/app/src/main/java/com/totsp/crossword/net/Downloaders.java b/app/src/main/java/com/totsp/crossword/net/Downloaders.java index a9886839..43b30351 100755 --- a/app/src/main/java/com/totsp/crossword/net/Downloaders.java +++ b/app/src/main/java/com/totsp/crossword/net/Downloaders.java @@ -105,19 +105,19 @@ public Downloaders(SharedPreferences prefs, } if (prefs.getBoolean("downloadJoseph", true)) { - downloaders.add(new KFSDownloader("joseph", "Joseph Crosswords", - "Thomas Joseph", Downloader.DATE_NO_SUNDAY)); + downloaders.add(new KFSDownloader("Joseph", "Joseph Crosswords", + Downloader.DATE_NO_SUNDAY)); } if (prefs.getBoolean("downloadSheffer", true)) { - downloaders.add(new KFSDownloader("sheffer", "Sheffer Crosswords", - "Eugene Sheffer", Downloader.DATE_NO_SUNDAY)); + downloaders.add(new KFSDownloader("Sheffer", "Sheffer Crosswords", + Downloader.DATE_NO_SUNDAY)); } -// if (prefs.getBoolean("downloadPremier", true)) { -// downloaders.add(new KFSDownloader("premier", "Premier Crosswords", -// "Frank Longo", Downloader.DATE_SUNDAY)); -// } + if (prefs.getBoolean("downloadPremier", true)) { + downloaders.add(new KFSDownloader("Premier", "Premier Crosswords", + Downloader.DATE_SUNDAY)); + } if (prefs.getBoolean("downloadNewsday", true)) { downloaders.add(new BrainsOnlyDownloader( diff --git a/app/src/main/java/com/totsp/crossword/net/KFSDownloader.java b/app/src/main/java/com/totsp/crossword/net/KFSDownloader.java index 176feb98..6f6cc57f 100755 --- a/app/src/main/java/com/totsp/crossword/net/KFSDownloader.java +++ b/app/src/main/java/com/totsp/crossword/net/KFSDownloader.java @@ -1,42 +1,25 @@ package com.totsp.crossword.net; -import java.io.DataOutputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.text.DateFormat; -import java.text.NumberFormat; +import java.text.SimpleDateFormat; import java.util.Date; -import java.util.logging.Level; - -import com.totsp.crossword.io.KingFeaturesPlaintextIO; -import com.totsp.crossword.versions.DefaultUtil; - /** * King Features Syndicate Puzzles - * URL: http://[puzzle].king-online.com/clues/YYYYMMDD.txt + * URL: http://puzzles.kingdigital.com/jpz/YYYYMMDD.jpz * premier = Sunday * joseph = Monday-Saturday * sheffer = Monday-Saturday */ -public class KFSDownloader extends AbstractDownloader { - DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM); - NumberFormat nf = NumberFormat.getInstance(); - private String author; +public class KFSDownloader extends AbstractJPZDownloader { + SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd"); private String fullName; private int[] days; - public KFSDownloader(String shortName, String fullName, String author, int[] days) { - super("http://puzzles.kingdigital.com/javacontent/clues/"+shortName+"/", DOWNLOAD_DIR, fullName); + public KFSDownloader(String shortName, String fullName, int[] days) { + super("http://puzzles.kingdigital.com/jpz/"+shortName+"/", DOWNLOAD_DIR, fullName); this.fullName = fullName; - this.author = author; this.days = days; - nf.setMinimumIntegerDigits(2); - nf.setMaximumFractionDigits(0); } public int[] getDownloadDates() { @@ -48,47 +31,11 @@ public String getName() { } public File download(Date date) { - File downloadTo = new File(this.downloadDirectory, this.createFileName(date)); - - if (downloadTo.exists()) { - return null; - } - - File plainText = downloadToTempFile(this.getName(), date); - - if (plainText == null) { - return null; - } - - String copyright = "\u00a9 " + (date.getYear() + 1900) + " King Features Syndicate."; - - try { - InputStream is = new FileInputStream(plainText); - DataOutputStream os = new DataOutputStream(new FileOutputStream(downloadTo)); - boolean retVal = KingFeaturesPlaintextIO.convertKFPuzzle(is, os, fullName + ", " + df.format(date), author, - copyright, date); - os.close(); - is.close(); - plainText.delete(); - - if (!retVal) { - LOG.log(Level.SEVERE, "Unable to convert KFS puzzle into Across Lite format."); - downloadTo.delete(); - downloadTo = null; - } - } catch (Exception ioe) { - LOG.log(Level.SEVERE, "Exception converting KFS puzzle into Across Lite format.", ioe); - downloadTo.delete(); - downloadTo = null; - } - - return downloadTo; + return download(date, this.createUrlSuffix(date), EMPTY_MAP); } @Override protected String createUrlSuffix(Date date) { - return (date.getYear() + 1900) + nf.format(date.getMonth() + 1) + nf.format(date.getDate()) + ".txt"; + return df.format(date) + ".jpz"; } - - } diff --git a/app/src/main/java/com/totsp/crossword/view/recycler/SeparatedRecyclerViewAdapter.java b/app/src/main/java/com/totsp/crossword/view/recycler/SeparatedRecyclerViewAdapter.java index fd712d47..454f160c 100755 --- a/app/src/main/java/com/totsp/crossword/view/recycler/SeparatedRecyclerViewAdapter.java +++ b/app/src/main/java/com/totsp/crossword/view/recycler/SeparatedRecyclerViewAdapter.java @@ -26,21 +26,25 @@ public SeparatedRecyclerViewAdapter(int textViewId) { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { if(viewType == HEADER){ + // For headers, we can create a simple text holder. TextView view = (TextView) LayoutInflater.from(viewGroup.getContext()) .inflate(textViewId, viewGroup, false); return new SimpleTextViewHolder(view); } else { - RecyclerView.ViewHolder result = null; - while(result == null){ - for(RecyclerView.Adapter sectionAdapter : sections.values()){ - try { - result = sectionAdapter.onCreateViewHolder(viewGroup, viewType); - } catch(Exception e){ - e.printStackTrace(); - } + // For puzzle views, any sectionAdapter can be used to create the view holder, so find + // the first one that gives us a result. + for(RecyclerView.Adapter sectionAdapter : sections.values()){ + RecyclerView.ViewHolder result = null; + try { + result = sectionAdapter.onCreateViewHolder(viewGroup, viewType); + } catch(Exception e){ + e.printStackTrace(); + } + if (result != null) { + return result; } } - return result; + return null; } } diff --git a/puzlib/src/main/java/com/totsp/crossword/io/UclickXMLIO.java b/puzlib/src/main/java/com/totsp/crossword/io/UclickXMLIO.java index 17034027..b25fda69 100755 --- a/puzlib/src/main/java/com/totsp/crossword/io/UclickXMLIO.java +++ b/puzlib/src/main/java/com/totsp/crossword/io/UclickXMLIO.java @@ -69,23 +69,15 @@ public void startElement(String nsURI, String strippedName, if (clueNum > maxClueNum) { maxClueNum = clueNum; } - try { - acrossNumToClueMap.put(clueNum, URLDecoder.decode(attributes.getValue("c"), CHARSET_NAME)); - } catch (UnsupportedEncodingException e) { - acrossNumToClueMap.put(clueNum, attributes.getValue("c")); - } + acrossNumToClueMap.put(clueNum, tryDecode(attributes.getValue("c"))); } else if (inDown) { int clueNum = Integer.parseInt(attributes.getValue("cn")); if (clueNum > maxClueNum) { maxClueNum = clueNum; } - try { - downNumToClueMap.put(clueNum, URLDecoder.decode(attributes.getValue("c"), CHARSET_NAME)); - } catch (UnsupportedEncodingException e) { - downNumToClueMap.put(clueNum, attributes.getValue("c")); - } + downNumToClueMap.put(clueNum, tryDecode(attributes.getValue("c"))); } else if (name.equalsIgnoreCase("title")) { - puz.setTitle(attributes.getValue("v")); + puz.setTitle(tryDecode(attributes.getValue("v"))); } else if (name.equalsIgnoreCase("author")) { puz.setAuthor(attributes.getValue("v")); } else if (name.equalsIgnoreCase("width")) { @@ -112,6 +104,14 @@ public void startElement(String nsURI, String strippedName, inDown = true; } } + + private static String tryDecode(String s) { + try { + return URLDecoder.decode(s, CHARSET_NAME); + } catch (UnsupportedEncodingException e) { + return s; + } + } @Override public void endElement(String nsURI, String strippedName, diff --git a/puzlib/src/main/java/com/totsp/crossword/puz/Puzzle.java b/puzlib/src/main/java/com/totsp/crossword/puz/Puzzle.java index 94558fb9..5f326cb3 100755 --- a/puzlib/src/main/java/com/totsp/crossword/puz/Puzzle.java +++ b/puzlib/src/main/java/com/totsp/crossword/puz/Puzzle.java @@ -102,15 +102,15 @@ public void setBoxes(Box[][] boxes) { if (!somethingAbove(boxes, row, col)) { if (somethingBelow(boxes, row, col)) { boxes[row][col].setDown(true); + tickedClue = true; } - tickedClue = true; } if (!somethingLeftOf(boxes, row, col)) { if (somethingRightOf(boxes, row, col)) { boxes[row][col].setAcross(true); + tickedClue = true; } - tickedClue = true; } if (tickedClue) { @@ -582,4 +582,4 @@ public String toString() { return "Puzzle " + boxes.length + " x " + boxes[0].length + " " + this.title; } -} \ No newline at end of file +}