/* * [PrepKansas.java] * * Summary: One shot program to process tax data for Kansas. Generates code for AmericanTax.java table. * * Copyright: (c) 2010-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 2010-12-13 initial version */ package com.mindprod.americantax; import com.mindprod.common18.ST; import com.mindprod.csv.CSVReader; import java.io.IOException; import java.util.HashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import static java.lang.System.*; /** * One shot program to process tax data for Kansas. Generates code for AmericanTax.java table. *

* Generates code for AmericanTax.java table. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2010-12-13 initial version * @since 2010-12-13 */ public final class PrepKansas extends PrepStateBase { /** * find out what county a city is in */ private final HashMap lookupCityToCounty = new HashMap<>( 1000 ); private final Pattern FIND_COUNTY = Pattern.compile( "(?i)\\(([\\p{Alpha}]+) county\\)", Pattern.CASE_INSENSITIVE ); private final String[] countiesByCountyNumber = new String[ 100 ]; private final double[] lookupCountyTax = new double[ 100 ]; /** * enclosing county for this city records for lookup */ private String enclosingCounty; /** * Constructor */ private PrepKansas() { super( "KS", "kansas", 6.3, true /* hast kansascounties.csv */, true /* has kansascities.csv */, true /* files include state rate */, false /* convert to book case */, 1000 /* est # cites */ ); } /** * abbreviate the city so we can look it up. * * @param city long city name * * @return short city name */ private String getShortCity( final String city ) { String shortCity; if ( city.startsWith( "St. " ) ) { final int place = city.indexOf( '(' ); if ( place < 0 ) { shortCity = city; } else { shortCity = city.substring( 0, place ).trim(); } } else { shortCity = ST.firstWord( city ); } return shortCity; } /* * home: http://www.ksrevenue.org/salesratechanges.html * download http://www.ksrevenue.org/pdf/pub1700413.xls kansas.xls * // name will change * counties and cities interleaved in Excel format. * and save as E:\com\mindprod\americantax\kansascities.csv * # city/county rate * "Abbyville", 7.300 * "Abilene", 8.150 * "Admire", 7.800 * "Agenda", 8.300 * "Willard (Shawnee county)", 8.200 * "Willard (Wabaunsee county)", 8.550 * * counties in kansas: http://www.kansascounties.org/index.aspx?NID=7 * list of cities in Kanas with county http://en.wikipedia.org/wiki/List_of_cities_in_Kansas as table. (complete?) * http://www.ksrevenue.org/pdf/StateLocalSalesRates.pdf (city rate without country assoc) * download http://www.ksrevenue.org/pdf/110localratios.pdf kansaslookup.pdf lets you figure out which county * each city is in * save as kansascounties.csv * Allen county * Bassett * Elsmore * Gas * Humboldt * Iola * La Harpe * Mildred * Moran * Savonburg * Anderson county * Colony * Manually create entries for * Coffey,LeRoy,0.000 * Reno, "Salt Mine Museum-1",1.750 * Reno,"Salt Mine Museum-2",1.000 * Wabaunsee,"Maple Hill Travel Store CID",3.500 */ /** * Default method to read and prepare one county record. * You must read, and add SalesTaxItem to salesTaxItems, and skipToNewLine * * @param c open CSV reader. * * @throws java.io.IOException if cannot read file */ void prepareCity( final CSVReader c ) throws IOException { final String item = c.get(); if ( item.endsWith( " county" ) ) { // was a country record final String county = ST.chopTrailingString( item, " county" ); final double percent = c.getDouble() - stateTax; // strip state tax salesTaxItems.add( new SalesTaxItem( county, "", percent ) ); } else { // was a city record String city = item; final double percent = c.getDouble() - stateTax; // strip state tax, includes county tax // the county may already be encoded as (iiii county) String county; final Matcher m = FIND_COUNTY.matcher( city ); // Matchers are used both for matching and finding. if ( m.find() ) { county = m.group( 1 ); // prune off the county from the city. int place = city.indexOf( '(' ); city = city.substring( 0, place ); } else { county = lookupCityToCounty.get( getShortCity( city ) ); if ( county == null ) { // can't find county for city. county = "unknown"; err.println( "can't find county for city: " + city ); } } salesTaxItems.add( new SalesTaxItem( county, city, percent ) ); } c.skipToNextLine(); } /** * files don't have mechanism to get county from city, so you must build an aux table * Default method to read and prepare one county record. * You must read, and add SalesTaxItem to salesTaxItems, and skipToNewLine * This fix contains no tax info, just city to county association. * * @param c open CSV reader. * * @throws IOException if cannot read file */ void prepareCounty( final CSVReader c ) throws IOException { String item = c.get(); if ( item.endsWith( "county" ) ) { enclosingCounty = ST.chopTrailingString( item, " county" ).intern(); } else { lookupCityToCounty.put( getShortCity( item ), enclosingCounty ); } c.skipToNextLine(); } public static void main( String[] args ) throws IOException { new PrepKansas().prepare(); } }