/* * [Coal.java] * * Summary: How long will US coal last given a rate of growth in consumption. * * Copyright: (c) 2009-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 2009-11-29 initial version */ package com.mindprod.coal; import com.mindprod.common18.CMPAboutJBox; import com.mindprod.common18.Common18; import com.mindprod.common18.FontFactory; import com.mindprod.common18.HybridJ; import com.mindprod.common18.JEButton; import com.mindprod.common18.VersionCheck; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JSpinner; import javax.swing.JTextArea; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.Color; import java.awt.Container; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.text.DecimalFormat; /** * How long will US coal last given a rate of growth in consumption. * * @author Roedy Green, Canadian Mind Products * @version 1.0 2009-11-29 initial version * @since 2009-11-29 */ public final class Coal extends JApplet { /** * height of Applet box in pixels. Does not include surrounding frame. */ private static final int APPLET_HEIGHT = 162; /** * Width of Applet box in pixels. */ private static final int APPLET_WIDTH = 664; private static final int FIRST_COPYRIGHT_YEAR = 2009; /** * undisplayed copyright notice */ private static final String EMBEDDED_COPYRIGHT = "Copyright: (c) 2009-2017 Roedy Green, Canadian Mind Products, http://mindprod.com"; private static final String RELEASE_DATE = "2009-11-29"; private static final String TITLE_STRING = "Coal Extinction Calculator"; /** * embedded version string. */ private static final String VERSION_STRING = "1.0"; /** * background colour for window. */ private static final Color BACKGROUND_FOR_APP = new Color( 0xeeeeee/* grey */ ); /** * background where for data entry where user enters a value. */ private static final Color BACKGROUND_FOR_EDITABLE = Color.WHITE; /** * for instruction on how to use program */ private static final Color BACKGROUND_FOR_INSTRUCTIONS = Color.WHITE; /** * for final result */ private static final Color BACKGROUND_FOR_RESULT = Color.WHITE; /** * foreground colour for window text */ private static final Color FOREGROUND_FOR_APP = Color.BLACK; /** * data entry text field colour */ private static final Color FOREGROUND_FOR_ENTER = Color.BLACK; /** * for instruction on how to use program */ private static final Color FOREGROUND_FOR_INSTRUCTIONS = new Color( 0x008000 ); /** * for final result */ private static final Color FOREGROUND_FOR_RESULT = Color.BLACK; /** * for titles */ private static final Color FOREGROUND_FOR_TITLE = new Color( 0xdc143c ); /** * format for display and input of sale amount */ private static final DecimalFormat PERCENT_FORMAT = new DecimalFormat( "#0.0" ); /** * format for display and input of sale amount */ private static final DecimalFormat YEARS_FORMAT = new DecimalFormat( "###,##0.0" ); /** * for spinner */ private static final Font FONT_FOR_EDITABLE_FIELDS; /** * for for titles and About buttons */ private static final Font FONT_FOR_INSTRUCTIONS; /** * for final result */ private static final Font FONT_FOR_RESULTS; /** * for for titles and About buttons */ private static final Font FONT_FOR_TITLE; static { FONT_FOR_EDITABLE_FIELDS = FontFactory.build( "Monospaced", Font.BOLD, 15 ); FONT_FOR_INSTRUCTIONS = FontFactory.build( "Dialog", Font.PLAIN, 15 ); FONT_FOR_RESULTS = FontFactory.build( "Dialog", Font.PLAIN, 15 ); FONT_FOR_TITLE = FontFactory.build( "Dialog", Font.BOLD, 16 ); } /** * about */ private JButton about; /** * label for annualConsumptionGrowthPercent */ private JLabel annualConsumptionGrowthPercentLabel; /** * title of applet */ private JLabel title; /** * annual growth in consumption as a percent */ private JSpinner annualConsumptionGrowthPercent; /** * first line of result as a sentence. */ private JTextArea result; /** * formats output of annualConsumptionGrowthPercent. */ private SpinnerNumberModel annualConsumptionGrowthPercentNumberModel; /** * constructor */ public Coal() { } /** * compute how many years are left before US coal runs out, given a presumed rate of growth in consumption */ private void compute() { final double percent = annualConsumptionGrowthPercentNumberModel.getNumber().doubleValue(); // historic 2.86, // pop 3% final double rate = percent / 100; // +ve mean growing, -ve means shrinking // data for US coal annual energy review 1991, US Dept of energy final double reserve = 273E9; /** short tons reserve of extractable coal in USA, http://www.clean-energy.us/facts/coal.htm*/ final double extraction = 986E6 / .86; /** tons per yer in USA in 2001 */ // formula from http://climatechange.flinders.edu.au/various%20attachments/Bartlett%20-%20NRR%5B1%5D.pdf // Math.log1P is more accurate that adding one to the argument. final double extinctionYears = 1. / rate * Math.log1p( rate * reserve / extraction ); if ( rate > 0 ) { result.setText( "If coal consumption grows at " + PERCENT_FORMAT.format( percent ) + "% per annum, coal in the USA will run out in " + YEARS_FORMAT.format( extinctionYears ) + " years." ); } else if ( rate < 0 ) { if ( Double.isNaN( extinctionYears ) ) { result.setText( "If coal consumption shrinks at " + PERCENT_FORMAT.format( -percent ) + "% per annum, coal in the USA would not run out." ); } else { result.setText( "If coal consumption shrinks at " + PERCENT_FORMAT.format( -percent ) + "% per annum, coal in the USA will run out in " + YEARS_FORMAT.format( extinctionYears ) + " years." ); } } else { result.setText( "If annual coal consumption does not change, the USA will run out of coal in " + YEARS_FORMAT.format( reserve / extraction ) + " years." ); } } /** * create gui components */ private void createComponents() { title = new JLabel( TITLE_STRING + " " + VERSION_STRING ); title.setFont( FONT_FOR_TITLE ); title.setForeground( FOREGROUND_FOR_TITLE ); // leave background app background about = new JEButton( "About" ); about.setToolTipText( "About " + TITLE_STRING + " " + VERSION_STRING ); annualConsumptionGrowthPercentLabel = new JLabel( "Select assumed annual growth rate percentage in coal consumption.", JLabel.RIGHT ); annualConsumptionGrowthPercentLabel.setFont( FONT_FOR_INSTRUCTIONS ); annualConsumptionGrowthPercentLabel.setBackground( BACKGROUND_FOR_INSTRUCTIONS ); annualConsumptionGrowthPercentLabel.setForeground( FOREGROUND_FOR_INSTRUCTIONS ); annualConsumptionGrowthPercent = new JSpinner(); annualConsumptionGrowthPercent.setFont( FONT_FOR_EDITABLE_FIELDS ); annualConsumptionGrowthPercent.setBackground( BACKGROUND_FOR_EDITABLE ); annualConsumptionGrowthPercent.setForeground( FOREGROUND_FOR_ENTER ); annualConsumptionGrowthPercent.setValue( 2.9d ); // bounds on spinner annualConsumptionGrowthPercentNumberModel = new SpinnerNumberModel( /* initial value */ 2.9d, /* min */ -0.5d, /* max */ +25.0d, /* step */ 0.1d ); annualConsumptionGrowthPercent.setModel( annualConsumptionGrowthPercentNumberModel ); result = new JTextArea( 2, 40 ); result.setEditable( false ); // provide some space around the inside result.setMargin( new Insets( 4, 4, 4, 4 ) ); // automatically wrap lines result.setLineWrap( true ); result.setWrapStyleWord( true ); result.setFont( FONT_FOR_RESULTS ); result.setBackground( BACKGROUND_FOR_RESULT ); result.setForeground( FOREGROUND_FOR_RESULT ); } /** * hook up the listeners */ private void hookListeners() { // engage the listeners about.addActionListener( new ActionListener() { public void actionPerformed( ActionEvent e ) { // open about box frame new CMPAboutJBox( TITLE_STRING, VERSION_STRING, "Calculates how long coal will last presuming", "different rates of growth in demand.", "freeware", RELEASE_DATE, FIRST_COPYRIGHT_YEAR, "Roedy Green", "COAL", "1.8" ); } } ); annualConsumptionGrowthPercentNumberModel.addChangeListener( new ChangeListener() { /** * } * spinner changed value * @param e event from spinner */ public void stateChanged( ChangeEvent e ) { compute(); } // end actionPerformed } ); // don't also need annualConsumptionGrowthPercent.addChangeListener } /** * layout the components * * @param contentPane where to add components */ private void layoutGridBag( Container contentPane ) { // basic layout: // 0-----0------------------------------------ 1------- // 0 -----------TITLE------------------------ -----about // 1 --consumption % ---------------------- consumption // 2 -- result-----------------------------------------. // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( title, new GridBagConstraints( 0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets( 10, 10, 0, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( about, new GridBagConstraints( 1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 10, 5, 5, 10 ), 10, 2 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( annualConsumptionGrowthPercentLabel, new GridBagConstraints( 0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 0, 10, 5, 5 ), 0, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( annualConsumptionGrowthPercent, new GridBagConstraints( 1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets( 0, 5, 5, 10 ), 20, 0 ) ); // x y w h wtx wty anchor fill T L B R padx pady contentPane.add( result, new GridBagConstraints( 0, 3, 2, 1, 1.0, 1.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets( 5, 10, 10, 10 ), 0, 0 ) ); } /** * Allow this Applet to run as as application as well. * * @param args command line arguments ignored. */ public static void main( String args[] ) { HybridJ.fireup( new Coal(), TITLE_STRING + " " + VERSION_STRING, APPLET_WIDTH, APPLET_HEIGHT ); } // end main /** * Called by the browser or Applet viewer to inform * this Applet that it is being reclaimed and that it should destroy * any resources that it has allocated. */ @Override public void destroy() { about = null; annualConsumptionGrowthPercent = null; annualConsumptionGrowthPercentLabel = null; annualConsumptionGrowthPercentNumberModel = null; result = null; title = null; } /** * Called by the browser or Applet viewer to inform * this Applet that it has been loaded into the system. */ @Override public void init() { if ( !VersionCheck.isJavaVersionOK( 1, 8, 0, this ) ) { return; } Common18.setLaf(); Container contentPane = this.getContentPane(); contentPane.setBackground( BACKGROUND_FOR_APP ); contentPane.setForeground( FOREGROUND_FOR_APP ); contentPane.setLayout( new GridBagLayout() ); createComponents(); layoutGridBag( contentPane ); hookListeners(); compute(); this.validate(); this.setVisible( true ); } // end init }