/* * [USPostageRates.java] * * Summary: Probe US post office to find the latest postage rates to post at http://mindprod.com/jgloss/postage.html. * * Copyright: (c) 2014-2017 Roedy Green, Canadian Mind Products, http://mindprod.com * * Licence: This software may be copied and used freely for any purpose but military. * http://mindprod.com/contact/nonmil.html * * Requires: JDK 1.8+ * * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/ * * Version History: * 1.0 2014-04-06 initial release * 1.1 2015-02-05 make date of probe track today's date. * New style probe. Tighten finder so will ignore the $400 entries. * N O L O N G E R W O R K S. now 2 pages of HTTPS: * 1.2 2016-06-22 Use downloaded files rather than web calculator. */ package com.mindprod.repair; import com.mindprod.common18.BigDate; import com.mindprod.common18.EIO; import com.mindprod.common18.ST; import com.mindprod.csv.CSVReader; import com.mindprod.fastcat.FastCat; import com.mindprod.filetransfer.Download; import java.io.File; import java.io.IOException; import java.text.DecimalFormat; import static java.lang.System.*; /** * Probe US post office to find the latest postage rates to post at http://mindprod.com/jgloss/postage.html. * Trigger with E:\com\mindprod\repair\GrabPostageRates.exe * * @author Roedy Green, Canadian Mind Products * @version 1.2 2016-06-22 Use downloaded files rather than web calculator. * @see CanadaPostageRates * @since 2014-04-06 */ class USPostageRates { /** * format for display and input of sale amount */ private static final DecimalFormat PRICEFORMAT = new DecimalFormat( "#,##0.00" ); private static final double[] prices = new double[ 12 ]; /** * cost of one basic US stamp, used for computing ratios */ private static double usBaseRate; private static int lineCounter; private static void downloadFiles() { out.println( "Downloading rate files..." ); if ( !Download.downloadOneFile( "https://www.usps.com/business/prices/m-fcm-eddm-retail.csv", "C:/temp/domestic.csv", false ) ) { err.println( "Unable to download US domestic rates." ); System.exit( 2 ); } if ( !Download.downloadOneFile( "https://www.usps.com/business/prices/m-fcmi-letters.csv", "C:/temp/international.csv", false ) ) { err.println( "Unable to download US international rates." ); System.exit( 2 ); } } private static void extractPrices() { try { CSVReader domestic = new CSVReader( EIO.getBufferedReader( new File( "C:/temp/domestic.csv" ), 32 * 1024, EIO.UTF8 ) ); for ( int i = 0; i < 5; i++ ) { domestic.skipToNextLine(); } domestic.skip( 1 ); prices[ 0 ] = domestic.getDouble(); usBaseRate = prices[ 0 ]; domestic.skipToNextLine(); domestic.skip( 1 ); prices[ 1 ] = domestic.getDouble(); domestic.skipToNextLine(); domestic.skip( 1 ); prices[ 2 ] = domestic.getDouble(); domestic.skipToNextLine(); domestic.skip( 1 ); prices[ 3 ] = domestic.getDouble(); domestic.close(); CSVReader international = new CSVReader( EIO.getBufferedReader( new File( "C:/temp/international.csv" ), 32 * 1024, EIO.UTF8 ) ); for ( int i = 0; i < 5; i++ ) { international.skipToNextLine(); } // Canada is group 1, Britain in group 3 international.skip( 1 ); prices[ 4 ] = international.getDouble(); international.skip( 1 ); prices[ 8 ] = international.getDouble(); international.skipToNextLine(); international.skip( 1 ); prices[ 5 ] = international.getDouble(); international.skip( 1 ); prices[ 9 ] = international.getDouble(); international.skipToNextLine(); international.skip( 1 ); prices[ 6 ] = international.getDouble(); international.skip( 1 ); prices[ 10 ] = international.getDouble(); international.skipToNextLine(); international.skip( 1 ); prices[ 7 ] = international.getDouble(); international.skip( 1 ); prices[ 11 ] = international.getDouble(); international.close(); } catch ( IOException e ) { err.println( "USPS file format has changed." ); System.exit( 2 ); } } /** * main method, probes all the variants of mail from the USA * * @return html text to list the prices and descriptions */ static String generateAllUSPrices() { downloadFiles(); extractPrices(); final String prelude1 = " \n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + ""; final String postlude = "\n" + "\n" + "\n" + "
American Postage Rates
American Postage\n" + "Rates
Cost $USDRatioTypeWeight
  Others 
"; final FastCat sb = new FastCat( 20 ); sb.append( prelude1, prelude2, prelude3 ); sb.append( generateOneUSTableLine( "light letter within the USA", 0, 1 /* low/high weight */, prices[ 0 ] ) ); sb.append( generateOneUSTableLine( "midweight letter within the USA", 1, 2, prices[ 1 ] ) ); sb.append( generateOneUSTableLine( "overweight letter within the USA", 2, 3, prices[ 2 ] ) ); sb.append( generateOneUSTableLine( "heavy letter within the USA", 3, 3.5, prices[ 3 ] ) ); // find out cost of US letters to Canada sb.append( generateOneUSTableLine( "light letter to Canada", 0, 1 /* low/high weight */, prices[ 4 ] ) ); sb.append( generateOneUSTableLine( "midweight letter to Canada", 1, 2, prices[ 5 ] ) ); sb.append( generateOneUSTableLine( "overweight letter to Canada", 2, 3, prices[ 6 ] ) ); sb.append( generateOneUSTableLine( "heavy letter to Canada", 3, 3.5, prices[ 7 ] ) ); // find out to US letters to Britain sb.append( generateOneUSTableLine( "light International letter. Rate varies by country. \n" + "England (group 3) shown", 0, 1 /* low/high weight */, prices[ 8 ] ) ); sb.append( generateOneUSTableLine( "midweight International letter. Rate varies by country. \n" + "England shown", 1, 2, prices[ 9 ] ) ); sb.append( generateOneUSTableLine( "overweight International letter. Rate varies by country. \n" + "England shown", 2, 3, prices[ 10 ] ) ); sb.append( generateOneUSTableLine( "heavy International letter. Rate varies by country. \n" + "England shown", 3, 3.5, prices[ 11 ] ) ); sb.append( postlude ); return sb.toSeparatedList( '\n' ); } /** * @param desc description e.g. light letter with the USA * @param fromOz low bound on weight * @param toOz high bound on weight * @param price without lead $ * * @return HTML text */ private static String generateOneUSTableLine( final String desc, final double fromOz, final double toOz, final double price ) { // group lines by fours, alternating light/dark backgrounds final String css = ( lineCounter++ / 4 % 2 == 0 ) ? "stripe1" : "stripe2"; final FastCat sb = new FastCat( 17 ); sb.append( "" ); sb.append( "$", PRICEFORMAT.format( price ), "" ); sb.append( "", PRICEFORMAT.format( price / usBaseRate ), "" ); sb.append( "", desc, "" ); sb.append( "", tidyFormat( fromOz ), " to ", tidyFormat( toOz ), " ounces" ); return sb.toString(); } private static String tidyFormat( double d ) { final String s = Double.toString( d ); return ST.chopTrailingString( s, ".0" ); } public static void main( String[] args ) throws IOException { out.println( generateAllUSPrices() ); } }