import java.io.*;

/**
 * Free Rocket Simulation Program, version 0.0.0.6, published 10.12.2008
 *
 * Copyright (C) 2003 Aapo Puhakka, http://aapo.iki.fi
 *
 * This program is distributed under the terms of the GNU General Public License (GPL).
 *
 * The GNU General Public License may be obtained from http://www.gnu.org.
 *
 * The author may be contacted for other licenses.
 */
public class Simulation {

  // Variables that depend on rocket 

  /** Motor's type. */
  private String sMotorType;

  /** Motor's index in motor-table. */
  private int iMotorIndex;

  /**
   * Descriptions of motors.
   * 0: Code
   * 1: Description
   */
  private static String[][] sMotors = 
  // Code   Description
  {
    {"SF_A","Sachsen-Feuerwerk A8-3"},
    {"SF_B","Sachsen-Feuerwerk B4-4"},
    {"SF_C","Sachsen-Feuerwerk C6-3"},
    {"SF_D","Sachsen-Feuerwerk D7-3"},
    {"AT_D","Aerotech D24-7T (18 mm, reusable)"},
    {"HT440-076-J115","Hypertek 440cc, orifice: 076, fuel: J115"},
    {"HT440-098-J170","Hypertek 440cc, orifice: 098, fuel: J170"},
    {"HT440-125-J250","Hypertek 440cc, orifice: 125, fuel: J250"},
    {"HT1685-125-L350","Hypertek 1685cc, orifice: 125, fuel: L350"},
    {"HT2800-172-L540","Hypertek 2800cc, orifice: 172, fuel: L540"}
  };

  /** 
   * Properties of motors.
   * 0: Full motor mass.
   * 1: Empty motor mass.
   * 2: Delay time.
   */
  private static double[][] dMotors = 
  // Full Mass   Empty Mass Ejection time 
  {
    { 0.015,      0.009,     3.6},
    { 0.017,      0.009,     5.2},
    { 0.023,      0.009,     4.85},
    { 0.044,      0.020,     4.53},
    { 0.031,      0.022,     7.9},
    { 1.2822,     0.8663,  999},
    { 1.2822,     0.8747,  999},
    { 1.2925,     0.8879,  999},
    { 3.903,      2.301,   999},
    { 5.656,      3.097,   999}
  };
  // Full Mass and Empty Mass was measured from real motors.
  // Ejection time is from manufacturers specifications.
  // Hypertek: Data from www.thrustcurve.org

  /**
   * Thrust of Sachsen-Feuerwerk A8-3.
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private static double[][] dThrust_SF_A8_3 =
  {
    { 0,     0 },
    { 0.25, 12.2 },
    { 0.3,   7 },
    { 0.42,  4.4 },
    { 0.55,  0 }
  };

  /**
   * Thrust of Sachsen-Feuerwerk B4-4.
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private static double[][] dThrust_SF_B4_4 =
  {
    { 0,     0 },
    { 0.25, 11.6 },
    { 0.3,   5.4 },
    { 0.55,  3.5 },
    { 1.2,   3.5 },
    { 1.3,   0 }
  };

  /**
   * Thrust of Sachsen-Feuerwerk C6-3.
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private static double[][] dThrust_SF_C6_3 =
  {
    { 0,     0 },
    { 0.2,  11.6 },
    { 0.25, 11.6 },
    { 0.32,  5.2 },
    { 0.5,   3.6 },
    { 1.1,   3 },
    { 1.8,   3.7 },
    { 1.85,  0 }
  };

  /**
   * Thrust of Sachsen-Feuerwerk D7-3.
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private static double[][] dThrust_SF_D7_3 =
  {
    { 0,      0 },
    { 0.32,  18.5 },
    { 0.38,  20.5 },
    { 0.42,  20.5 },
    { 0.5,   12.5 },
    { 0.6,   10.5 },
    { 0.9,    7.93 },
    { 1.34,   8.3 },
    { 1.5,    0 }
  };

  /**
   * Thrust of Aerotech D24-7T.
   * Measured from graph from D24-7T package.
   */
  private static double[][] dThrust_AT_D24_7 =
  {
    { 0,      0 },
    { 0.02,  38 },
    { 0.06,  33 },
    { 0.7,   19 },
    { 0.76,   6 },
    { 0.9,    0 }
  };

  /**
   * Thrust of Hypertek 440-076-J115.
   * Data from www.thrustcurve.org.
   */
  private static double[][] dThrust_HT_440_076_J115 =
  {
    { 0.00,     0.00 },
    { 0.02,    93.74 },
    { 0.07,   246.84 },
    { 0.12,   251.05 },
    { 0.17,   252.39 },
    { 0.22,   236.20 },
    { 0.27,   234.59 },
    { 0.32,   233.95 },
    { 0.37,   229.65 },
    { 0.42,   229.59 },
    { 0.47,   228.23 },
    { 0.52,   230.86 },
    { 0.57,   227.21 },
    { 0.62,   227.30 },
    { 0.67,   220.65 },
    { 0.72,   206.48 },
    { 0.77,   186.00 },
    { 0.82,   173.77 },
    { 0.87,   167.82 },
    { 0.92,   163.53 },
    { 0.97,   160.41 },
    { 1.02,   161.42 },
    { 1.07,   158.24 },
    { 1.12,   158.92 },
    { 1.17,   158.58 },
    { 1.22,   158.51 },
    { 1.27,   159.90 },
    { 1.32,   160.67 },
    { 1.36,   162.65 },
    { 1.41,   161.43 },
    { 1.46,   162.43 },
    { 1.51,   163.57 },
    { 1.56,   158.73 },
    { 1.61,   159.00 },
    { 1.66,   157.55 },
    { 1.71,   159.00 },
    { 1.76,   157.04 },
    { 1.81,   156.79 },
    { 1.86,   155.35 },
    { 1.91,   155.33 },
    { 1.96,   152.75 },
    { 2.01,   150.85 },
    { 2.06,   151.25 },
    { 2.11,   150.65 },
    { 2.16,   148.72 },
    { 2.21,   147.67 },
    { 2.26,   146.91 },
    { 2.31,   148.72 },
    { 2.36,   144.71 },
    { 2.41,   144.06 },
    { 2.46,   142.64 },
    { 2.51,   141.33 },
    { 2.56,   141.96 },
    { 2.61,   139.34 },
    { 2.66,   140.19 },
    { 2.71,   139.76 },
    { 2.76,   136.15 },
    { 2.81,   134.57 },
    { 2.86,   133.60 },
    { 2.91,   131.02 },
    { 2.96,   130.57 },
    { 3.01,   131.12 },
    { 3.06,   128.75 },
    { 3.10,   125.38 },
    { 3.15,   125.67 },
    { 3.20,   125.43 },
    { 3.25,   123.70 },
    { 3.30,   120.00 },
    { 3.35,   120.26 },
    { 3.40,   116.87 },
    { 3.45,   118.79 },
    { 3.50,   116.17 },
    { 3.55,   115.46 },
    { 3.60,   108.70 },
    { 3.65,    96.45 },
    { 3.70,    94.23 },
    { 3.75,    95.50 },
    { 3.80,    78.18 },
    { 3.85,    73.10 },
    { 3.90,    66.94 },
    { 3.95,    61.82 },
    { 4.00,    57.79 },
    { 4.05,    53.88 },
    { 4.10,    50.49 },
    { 4.15,    48.50 },
    { 4.20,    46.16 },
    { 4.25,    44.60 },
    { 4.30,    43.48 },
    { 4.35,    42.65 },
    { 4.40,    41.38 },
    { 4.45,    40.64 },
    { 4.50,    39.80 },
    { 4.54,    39.22 },
    { 4.59,    38.39 },
    { 4.64,    37.55 },
    { 4.69,    36.76 },
    { 4.74,    35.05 },
    { 4.79,    34.73 },
    { 4.84,    33.51 },
    { 4.89,    32.76 },
    { 4.94,    31.95 },
    { 4.99,    31.04 },
    { 5.04,    30.03 },
    { 5.09,    29.17 },
    { 5.14,    28.18 },
    { 5.19,    27.11 },
    { 5.24,    26.40 },
    { 5.29,    25.22 },
    { 5.34,    24.68 },
    { 5.39,    23.55 },
    { 5.44,    22.89 },
    { 5.49,    22.03 },
    { 5.54,    21.13 },
    { 5.59,    20.49 },
    { 5.64,    19.58 },
    { 5.69,    18.94 },
    { 5.74,    18.27 },
    { 5.79,    17.33 },
    { 5.84,    16.77 },
    { 5.89,    16.09 },
    { 5.94,    15.52 },
    { 5.99,    14.89 },
    { 6.04,    13.77 },
    { 6.09,    12.92 },
    { 6.14,    12.16 },
    { 6.19,    11.72 },
    { 6.24,    11.07 },
    { 6.28,    10.68 },
    { 6.33,     9.70 },
    { 6.38,     9.65 },
    { 6.43,     9.27 },
    { 6.48,     8.65 },
    { 6.53,     8.15 },
    { 6.7,      0 }
  };

  /**
   * Thrust of Hypertek 440-098-J170.
   * Data from www.thrustcurve.org.
   */
  private static double[][] dThrust_HT_440_098_J170 =
  {
    { 0.00,     0.00 },
    { 0.02,   207.99 },
    { 0.07,   344.69 },
    { 0.12,   353.39 },
    { 0.17,   361.30 },
    { 0.22,   352.49 },
    { 0.27,   351.97 },
    { 0.32,   349.60 },
    { 0.37,   348.47 },
    { 0.42,   337.44 },
    { 0.47,   311.65 },
    { 0.52,   287.99 },
    { 0.57,   270.47 },
    { 0.62,   258.68 },
    { 0.67,   253.12 },
    { 0.72,   245.63 },
    { 0.77,   237.79 },
    { 0.82,   236.03 },
    { 0.87,   235.13 },
    { 0.92,   232.44 },
    { 0.97,   234.87 },
    { 1.02,   236.52 },
    { 1.07,   233.91 },
    { 1.12,   234.52 },
    { 1.17,   233.46 },
    { 1.22,   230.57 },
    { 1.27,   227.73 },
    { 1.32,   226.98 },
    { 1.37,   224.84 },
    { 1.42,   219.89 },
    { 1.47,   221.86 },
    { 1.52,   220.05 },
    { 1.57,   218.89 },
    { 1.62,   216.90 },
    { 1.67,   214.87 },
    { 1.71,   211.85 },
    { 1.76,   209.45 },
    { 1.81,   210.31 },
    { 1.86,   204.85 },
    { 1.91,   207.41 },
    { 1.96,   202.88 },
    { 2.01,   203.71 },
    { 2.06,   197.80 },
    { 2.11,   200.99 },
    { 2.16,   196.65 },
    { 2.21,   194.56 },
    { 2.26,   194.29 },
    { 2.31,   191.62 },
    { 2.36,   192.26 },
    { 2.41,   186.74 },
    { 2.46,   183.95 },
    { 2.51,   180.78 },
    { 2.56,   178.17 },
    { 2.61,   164.35 },
    { 2.66,   150.02 },
    { 2.71,   131.74 },
    { 2.76,   111.51 },
    { 2.81,    92.86 },
    { 2.86,    85.93 },
    { 2.91,    80.42 },
    { 2.96,    77.42 },
    { 3.01,    73.15 },
    { 3.06,    71.92 },
    { 3.11,    71.30 },
    { 3.16,    71.07 },
    { 3.21,    68.59 },
    { 3.26,    65.84 },
    { 3.31,    61.74 },
    { 3.36,    60.06 },
    { 3.41,    56.30 },
    { 3.46,    54.13 },
    { 3.51,    51.47 },
    { 3.56,    49.92 },
    { 3.61,    46.59 },
    { 3.66,    44.87 },
    { 3.71,    42.10 },
    { 3.76,    39.90 },
    { 3.80,    37.81 },
    { 3.85,    35.52 },
    { 3.90,    33.09 },
    { 3.95,    30.93 },
    { 4.00,    28.97 },
    { 4.05,    27.12 },
    { 4.10,    25.37 },
    { 4.15,    23.08 },
    { 4.20,    21.92 },
    { 4.25,    19.85 },
    { 4.30,    18.65 },
    { 4.35,    16.77 },
    { 4.40,    16.18 },
    { 4.45,    14.49 },
    { 4.50,    13.53 },
    { 4.55,    12.26 },
    { 4.60,    11.09 },
    { 4.65,    10.66 },
    { 4.8,      0 },
  };

  /**
   * Thrust of Hypertek 440-125-J250.
   * Data from www.thrustcurve.org.
   */
  private static double[][] dThrust_HT_440_125_J250 =
  {
    { 0.00,     0.00 },
    { 0.02,   302.14 },
    { 0.07,   472.67 },
    { 0.12,   475.62 },
    { 0.17,   454.77 },
    { 0.22,   445.61 },
    { 0.27,   427.99 },
    { 0.32,   419.97 },
    { 0.37,   407.33 },
    { 0.42,   392.23 },
    { 0.47,   379.10 },
    { 0.52,   372.74 },
    { 0.57,   361.22 },
    { 0.61,   355.11 },
    { 0.66,   347.85 },
    { 0.71,   343.69 },
    { 0.76,   339.75 },
    { 0.81,   336.99 },
    { 0.86,   338.97 },
    { 0.91,   330.72 },
    { 0.96,   331.94 },
    { 1.01,   323.78 },
    { 1.06,   324.02 },
    { 1.11,   318.21 },
    { 1.16,   314.24 },
    { 1.21,   310.96 },
    { 1.26,   305.56 },
    { 1.31,   306.49 },
    { 1.36,   310.75 },
    { 1.40,   303.22 },
    { 1.45,   294.77 },
    { 1.50,   289.93 },
    { 1.55,   285.35 },
    { 1.60,   290.98 },
    { 1.65,   277.54 },
    { 1.70,   275.34 },
    { 1.75,   264.38 },
    { 1.80,   247.32 },
    { 1.85,   221.93 },
    { 1.90,   194.60 },
    { 1.95,   166.73 },
    { 2.00,   147.62 },
    { 2.04,   136.07 },
    { 2.09,   129.30 },
    { 2.14,   125.74 },
    { 2.19,   124.98 },
    { 2.24,   117.98 },
    { 2.29,   111.29 },
    { 2.34,   102.86 },
    { 2.39,    93.91 },
    { 2.44,    85.95 },
    { 2.49,    78.25 },
    { 2.54,    70.86 },
    { 2.59,    64.20 },
    { 2.64,    57.50 },
    { 2.69,    51.90 },
    { 2.74,    46.63 },
    { 2.79,    41.18 },
    { 2.83,    36.97 },
    { 2.88,    32.38 },
    { 2.93,    28.67 },
    { 2.98,    25.28 },
    { 3.03,    21.99 },
    { 3.08,    18.41 },
    { 3.13,    15.42 },
    { 3.18,    14.33 },
    { 3.23,    12.51 },
    { 3.3,      0 }
  };

  /**
   * Thrust of Hypertek 1685-125-L350.
   * Data from www.thrustcurve.org.
   */
  private static double[][] dThrust_HT_1685_125_L350 =
  {
    { 0.00, 0.00 },
    { 0.02, 429.97 },
    { 0.07, 688.01 },
    { 0.12, 638.15 },
    { 0.17, 610.81 },
    { 0.22, 596.74 },
    { 0.27, 609.02 },
    { 0.32, 553.14 },
    { 0.37, 610.85 },
    { 0.42, 573.00 },
    { 0.47, 521.32 },
    { 0.52, 569.74 },
    { 0.57, 669.66 },
    { 0.62, 658.43 },
    { 0.67, 629.37 },
    { 0.72, 576.14 },
    { 0.77, 560.09 },
    { 0.82, 534.79 },
    { 0.87, 475.14 },
    { 0.92, 468.41 },
    { 0.97, 457.82 },
    { 1.02, 456.92 },
    { 1.07, 449.77 },
    { 1.12, 440.10 },
    { 1.17, 437.00 },
    { 1.22, 434.36 },
    { 1.27, 431.44 },
    { 1.32, 430.41 },
    { 1.37, 421.83 },
    { 1.42, 418.67 },
    { 1.47, 417.48 },
    { 1.52, 418.20 },
    { 1.57, 410.75 },
    { 1.62, 409.05 },
    { 1.67, 406.34 },
    { 1.72, 404.91 },
    { 1.77, 409.29 },
    { 1.82, 401.63 },
    { 1.87, 397.52 },
    { 1.92, 397.78 },
    { 1.97, 397.64 },
    { 2.02, 394.49 },
    { 2.07, 394.98 },
    { 2.12, 391.51 },
    { 2.17, 393.08 },
    { 2.22, 396.69 },
    { 2.27, 393.29 },
    { 2.32, 388.38 },
    { 2.36, 388.96 },
    { 2.41, 393.33 },
    { 2.46, 400.22 },
    { 2.51, 395.21 },
    { 2.56, 389.98 },
    { 2.61, 396.75 },
    { 2.66, 398.03 },
    { 2.71, 399.13 },
    { 2.76, 401.88 },
    { 2.81, 408.00 },
    { 2.86, 401.97 },
    { 2.91, 410.13 },
    { 2.96, 409.21 },
    { 3.01, 475.31 },
    { 3.06, 518.78 },
    { 3.11, 516.82 },
    { 3.16, 518.47 },
    { 3.21, 518.41 },
    { 3.26, 517.93 },
    { 3.31, 515.87 },
    { 3.36, 513.04 },
    { 3.41, 514.32 },
    { 3.46, 511.39 },
    { 3.51, 512.67 },
    { 3.56, 507.62 },
    { 3.61, 506.40 },
    { 3.66, 504.62 },
    { 3.71, 500.97 },
    { 3.76, 497.07 },
    { 3.81, 497.86 },
    { 3.86, 493.56 },
    { 3.91, 486.66 },
    { 3.96, 419.02 },
    { 4.01, 398.30 },
    { 4.06, 411.88 },
    { 4.11, 399.67 },
    { 4.16, 386.11 },
    { 4.21, 383.12 },
    { 4.26, 391.39 },
    { 4.31, 391.25 },
    { 4.36, 389.27 },
    { 4.41, 387.82 },
    { 4.46, 382.60 },
    { 4.51, 401.95 },
    { 4.56, 478.96 },
    { 4.61, 470.91 },
    { 4.66, 467.54 },
    { 4.71, 463.76 },
    { 4.76, 460.74 },
    { 4.81, 456.96 },
    { 4.86, 457.52 },
    { 4.91, 450.77 },
    { 4.96, 451.49 },
    { 5.01, 450.23 },
    { 5.06, 449.95 },
    { 5.11, 447.00 },
    { 5.16, 444.07 },
    { 5.21, 443.57 },
    { 5.26, 444.51 },
    { 5.30, 439.56 },
    { 5.35, 440.97 },
    { 5.40, 439.29 },
    { 5.45, 438.06 },
    { 5.50, 437.47 },
    { 5.55, 435.10 },
    { 5.60, 430.58 },
    { 5.65, 429.22 },
    { 5.70, 426.95 },
    { 5.75, 423.42 },
    { 5.80, 425.28 },
    { 5.85, 421.39 },
    { 5.90, 363.88 },
    { 5.95, 347.04 },
    { 6.00, 340.96 },
    { 6.05, 321.94 },
    { 6.10, 309.93 },
    { 6.15, 290.79 },
    { 6.20, 273.36 },
    { 6.25, 249.13 },
    { 6.30, 220.86 },
    { 6.35, 196.18 },
    { 6.40, 178.80 },
    { 6.45, 167.77 },
    { 6.50, 159.17 },
    { 6.55, 154.15 },
    { 6.60, 149.58 },
    { 6.65, 144.87 },
    { 6.70, 140.47 },
    { 6.75, 135.78 },
    { 6.80, 132.00 },
    { 6.85, 128.79 },
    { 6.90, 124.57 },
    { 6.95, 120.83 },
    { 7.00, 117.21 },
    { 7.05, 113.77 },
    { 7.10, 111.03 },
    { 7.15, 107.79 },
    { 7.20, 104.70 },
    { 7.25, 101.36 },
    { 7.30, 98.31 },
    { 7.35, 95.08 },
    { 7.40, 92.02 },
    { 7.45, 89.30 },
    { 7.50, 85.97 },
    { 7.55, 83.32 },
    { 7.60, 80.85 },
    { 7.65, 78.58 },
    { 7.70, 76.46 },
    { 7.74, 73.40 },
    { 7.79, 70.82 },
    { 7.84, 69.06 },
    { 7.89, 67.05 },
    { 7.94, 64.09 },
    { 7.99, 61.85 },
    { 8.04, 59.80 },
    { 8.09, 57.39 },
    { 8.14, 55.40 },
    { 8.19, 52.85 },
    { 8.24, 51.06 },
    { 8.29, 49.19 },
    { 8.34, 47.22 },
    { 8.39, 45.50 },
    { 8.44, 43.64 },
    { 8.49, 41.59 },
    { 8.54, 39.89 },
    { 8.59, 37.77 },
    { 8.64, 36.39 },
    { 8.69, 34.99 },
    { 8.74, 33.61 },
    { 8.79, 32.02 },
    { 8.84, 30.93 },
    { 8.89, 29.38 },
    { 8.94, 28.22 },
    { 8.99, 27.38 },
    { 9.04, 26.08 },
    { 9.09, 24.54 },
    { 9.14, 23.95 },
    { 9.19, 23.05 },
    { 9.24, 22.61 },
    { 9.29, 21.52 },
    { 9.34, 20.51 },
    { 9.39, 19.75 },
    { 9.44, 18.63 }
  };

  /**
   * Thrust of Hypertek 2800-172-L540.
   * Data from www.thrustcurve.org.
   */
  private static double[][] dThrust_HT_2800_172_L540 =
  {
    { 0.00, 0.00 },
    { 0.02, 585.16 },
    { 0.07, 737.02 },
    { 0.12, 748.29 },
    { 0.17, 726.17 },
    { 0.22, 689.81 },
    { 0.27, 659.76 },
    { 0.32, 655.86 },
    { 0.37, 677.53 },
    { 0.42, 671.04 },
    { 0.47, 673.00 },
    { 0.52, 658.46 },
    { 0.57, 668.70 },
    { 0.62, 665.93 },
    { 0.67, 664.30 },
    { 0.72, 653.30 },
    { 0.77, 641.91 },
    { 0.82, 637.74 },
    { 0.87, 632.20 },
    { 0.92, 650.64 },
    { 0.97, 660.63 },
    { 1.02, 616.30 },
    { 1.07, 625.04 },
    { 1.12, 627.55 },
    { 1.17, 627.29 },
    { 1.22, 630.32 },
    { 1.27, 626.12 },
    { 1.32, 618.49 },
    { 1.37, 643.42 },
    { 1.42, 631.04 },
    { 1.47, 661.43 },
    { 1.52, 659.74 },
    { 1.57, 641.84 },
    { 1.62, 662.17 },
    { 1.67, 640.08 },
    { 1.72, 634.49 },
    { 1.77, 675.74 },
    { 1.82, 666.92 },
    { 1.87, 648.82 },
    { 1.92, 705.17 },
    { 1.97, 629.05 },
    { 2.02, 613.80 },
    { 2.07, 745.21 },
    { 2.12, 709.33 },
    { 2.17, 752.96 },
    { 2.22, 748.63 },
    { 2.27, 733.69 },
    { 2.32, 648.25 },
    { 2.37, 736.34 },
    { 2.42, 724.96 },
    { 2.47, 722.82 },
    { 2.52, 674.96 },
    { 2.57, 712.97 },
    { 2.62, 657.27 },
    { 2.67, 697.09 },
    { 2.72, 737.19 },
    { 2.77, 789.53 },
    { 2.82, 785.41 },
    { 2.87, 790.73 },
    { 2.92, 787.61 },
    { 2.97, 785.37 },
    { 3.02, 781.46 },
    { 3.07, 797.46 },
    { 3.12, 797.20 },
    { 3.17, 808.30 },
    { 3.22, 724.41 },
    { 3.27, 667.54 },
    { 3.32, 813.79 },
    { 3.37, 812.01 },
    { 3.42, 788.63 },
    { 3.47, 777.74 },
    { 3.52, 802.37 },
    { 3.57, 803.79 },
    { 3.62, 760.39 },
    { 3.67, 722.21 },
    { 3.72, 798.19 },
    { 3.77, 805.05 },
    { 3.82, 794.47 },
    { 3.87, 803.06 },
    { 3.92, 788.76 },
    { 3.97, 753.85 },
    { 4.02, 687.60 },
    { 4.07, 655.31 },
    { 4.12, 640.70 },
    { 4.17, 675.74 },
    { 4.22, 620.74 },
    { 4.27, 712.13 },
    { 4.32, 775.64 },
    { 4.37, 766.63 },
    { 4.42, 711.91 },
    { 4.47, 730.90 },
    { 4.52, 627.89 },
    { 4.57, 609.05 },
    { 4.62, 640.05 },
    { 4.67, 724.28 },
    { 4.72, 757.87 },
    { 4.77, 705.83 },
    { 4.82, 711.72 },
    { 4.87, 727.36 },
    { 4.92, 616.00 },
    { 4.97, 702.92 },
    { 5.02, 632.29 },
    { 5.07, 709.30 },
    { 5.12, 670.88 },
    { 5.17, 575.21 },
    { 5.22, 675.99 },
    { 5.27, 637.02 },
    { 5.32, 651.22 },
    { 5.37, 558.24 },
    { 5.42, 549.05 },
    { 5.47, 635.33 },
    { 5.52, 592.53 },
    { 5.57, 618.32 },
    { 5.62, 663.52 },
    { 5.67, 568.41 },
    { 5.72, 664.51 },
    { 5.77, 593.61 },
    { 5.82, 542.32 },
    { 5.87, 553.18 },
    { 5.92, 535.76 },
    { 5.97, 574.86 },
    { 6.02, 502.36 },
    { 6.07, 518.02 },
    { 6.12, 557.71 },
    { 6.17, 575.18 },
    { 6.22, 487.75 },
    { 6.27, 430.89 },
    { 6.32, 385.36 },
    { 6.37, 326.63 },
    { 6.42, 289.14 },
    { 6.47, 273.30 },
    { 6.52, 264.36 },
    { 6.57, 256.01 },
    { 6.62, 248.24 },
    { 6.67, 240.85 },
    { 6.72, 233.66 },
    { 6.77, 225.74 },
    { 6.82, 218.90 },
    { 6.87, 211.29 },
    { 6.92, 205.25 },
    { 6.97, 197.84 },
    { 7.02, 191.15 },
    { 7.07, 184.12 },
    { 7.12, 177.41 },
    { 7.17, 171.33 },
    { 7.22, 166.11 },
    { 7.27, 160.21 },
    { 7.32, 154.92 },
    { 7.37, 150.34 },
    { 7.42, 145.07 },
    { 7.47, 139.87 },
    { 7.52, 135.19 },
    { 7.57, 131.03 },
    { 7.62, 126.24 },
    { 7.67, 122.15 },
    { 7.72, 118.10 },
    { 7.77, 113.53 },
    { 7.82, 109.90 },
    { 7.87, 105.33 },
    { 7.92, 101.69 },
    { 7.97, 98.20 },
    { 8.02, 94.22 },
    { 8.07, 90.65 },
    { 8.12, 86.76 },
    { 8.17, 83.75 },
    { 8.22, 80.25 },
    { 8.27, 77.07 },
    { 8.32, 73.51 },
    { 8.37, 70.24 },
    { 8.42, 67.25 },
    { 8.47, 64.26 },
    { 8.52, 61.55 },
    { 8.57, 58.42 },
    { 8.62, 55.42 },
    { 8.67, 52.78 },
    { 8.72, 49.83 },
    { 8.77, 47.07 },
    { 8.82, 45.13 },
    { 8.87, 42.89 },
    { 8.92, 40.38 },
    { 8.97, 38.52 },
    { 9.02, 36.23 },
    { 9.07, 34.30 },
    { 9.12, 32.27 },
    { 9.17, 29.70 },
    { 9.22, 26.98 },
    { 9.27, 25.36 },
    { 9.32, 23.48 },
    { 9.37, 21.72 },
    { 9.42, 18.89 },
    { 9.47, 17.64 },
    { 9.52, 16.54 },
    { 9.57, 14.44 }
  };

  /**
   * Set the motor's type.
   */
  public void setMotorType( String p_sMotorType ) {
    sMotorType = p_sMotorType;
    iMotorIndex = -1;

    for (int i = 0; i < sMotors.length; i++) {
      if (sMotors[i][0].equals( sMotorType )) {
	iMotorIndex = i;
	break;
      }
    }

    if (iMotorIndex == -1) {
      System.err.println("Invalid sMotorType: "+sMotorType);
      System.err.println("Possibilities are:");
      for (int i = 0; i < sMotors.length; i++)
	System.err.println(" "+sMotors[i][0]+"\t"+sMotors[i][1]);
      System.exit(-1);
    }
  }

  /** Motor's ejection time: burn + delay (parachute ejection time)*/
  private double dEjectionTime;

  /** Rocket's mass with full motor */
  private double dFullMass;

  /** Rocket's mass with empty motor */
  private double dEmptyMotorMass;

  /** Rocket's mass without motor */
  private double dNoMotorMass;

  /**
   * Set rocket's mass without motor. Kilograms.
   */
  public void setNoMotorMass( double p_dNoMotorMass ) {
    dNoMotorMass = p_dNoMotorMass;
  }

  /** Rocket's drag coefficient */
  private double dDragCoefficient;

  /**
   * Set rocket's drag coefficient. Unitless.
   */
  public void setDragCoefficient( double p_dDragCoefficient ) {
    dDragCoefficient = p_dDragCoefficient;
  }

  /** Rocket's tubes largest diameter */
  private double dDiameter;

  /**
   * Set the diameter of rocket's tube. Meters.
   */
  public void setDiameter( double p_dDiameter ) {
    dDiameter = p_dDiameter;

    double dRadius = dDiameter/2;
    dFrontalArea = 3.142 * dRadius * dRadius;
  }

  /** Rocket's frontal area */
  private double dFrontalArea;

  // Variables that are independent of the rocket 

  /** Simulation step, seconds. */
  private double dDeltaTime;

  /** Gravity of planet */
  private double dGravity;

  /**
   * Constructor.
   */
  public Simulation() { 
    super();

    sMotorType = null;
    iMotorIndex = -1;
    dFullMass = 0;
    dEmptyMotorMass = 0;
    dNoMotorMass = 0;
    dDragCoefficient = 0;
    dDiameter = 0;

    // Defaults for rocket independent variables
    dDeltaTime = 0.001;
    dGravity = 9.81;
  }

  // ---------------- c a l c T h r u s t ------------------
  /**
   * Motor's thrust during particular moment.
   */
  private double calcThrust( double dTime ) {

    double[][] dMatrix = null;

    if (iMotorIndex == 0) dMatrix = dThrust_SF_A8_3;
    else if (iMotorIndex == 1) dMatrix = dThrust_SF_B4_4;
    else if (iMotorIndex == 2) dMatrix = dThrust_SF_C6_3;
    else if (iMotorIndex == 3) dMatrix = dThrust_SF_D7_3;
    else if (iMotorIndex == 4) dMatrix = dThrust_AT_D24_7;
    else if (iMotorIndex == 5) dMatrix = dThrust_HT_440_076_J115;
    else if (iMotorIndex == 6) dMatrix = dThrust_HT_440_098_J170;
    else if (iMotorIndex == 7) dMatrix = dThrust_HT_440_125_J250;
    else if (iMotorIndex == 8) dMatrix = dThrust_HT_1685_125_L350;
    else if (iMotorIndex == 9) dMatrix = dThrust_HT_2800_172_L540;

    if (dMatrix == null)
      return 0;

    if (dTime < dMatrix[ 0 ][ 0 ] || dTime > dMatrix[ dMatrix.length - 1 ][ 0 ])
      return 0;

    for (int i = 1; i < dMatrix.length; i++) {
      if (dTime < dMatrix[ i ][ 0 ])
	return calcLinearInterval( dMatrix[ i - 1 ][ 0 ], dMatrix[ i ][ 0 ],
				   dMatrix[ i - 1 ][ 1 ], dMatrix[ i ][ 1 ], dTime );
    }

    return 0;

    // old style
    /*
    switch (iMotorIndex) {
    case 0: return calcSachsen_A8_3( dTime );
    case 1: return calcSachsen_B4_4( dTime );
    case 2: return calcSachsen_C6_3( dTime );
    case 3: return calcSachsen_D7_3( dTime );
    case 4: return calcAerotech_D24_7( dTime );
    }
    return 0;
    */
  }

  // --------------- c a l c L i n e a r I n t e r v a l --------------
  /**
   * Calculates variable during linear interval;
   */
  private double calcLinearInterval( double dTimeStart, double dTimeEnd, double dVariableStart, double dVariableEnd, double dTime) {
    double dVariableBase;
    double dVariableMaxDifference;
    double dIntervalLength = dTimeEnd - dTimeStart;

    dTime = dTime - dTimeStart;
    if (dVariableEnd > dVariableStart) {
      dVariableMaxDifference = dVariableEnd - dVariableStart;
      dVariableBase = dVariableEnd - dVariableMaxDifference;
    }
    else {
      dTime = dIntervalLength - dTime;
      dVariableMaxDifference = dVariableStart - dVariableEnd;
      dVariableBase = dVariableStart - dVariableMaxDifference;
    }

    return dVariableBase + dVariableMaxDifference * dTime / dIntervalLength;
  }

  // --------------- c a l c S a c h s e n _ A 8 _ 3 ----------
  /**
   * Thrust is approximated with following equations:
   * 0 - 0.25 s    : 0 - 12,2 N
   * 0.25 - 0.3 s  : 12,2 - 7 N
   * 0.3 - 0.42 s  : 7 - 4,4 N
   * 0.42 - 0.55 s : 4,4 - 0 N
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private double calcSachsen_A8_3( double dTime ) {
    if (dTime < 0 || dTime > 0.55) return 0;
    if (dTime < 0.25) return calcLinearInterval( 0, 0.25, 0, 12.2, dTime );
    if (dTime < 0.3) return calcLinearInterval( 0.25, 0.3, 12.2, 7, dTime );
    if (dTime < 0.42) return calcLinearInterval( 0.3, 0.42, 7, 4.4, dTime );
    return calcLinearInterval( 0.42, 0.55, 4.4, 0, dTime );
  }

  // --------------- c a l c S a c h s e n _ B 4 _ 4 ----------
  /**
   * Thrust is approximated with following equations:
   * 0 - 0.25 s   : 0 - 11,6 N
   * 0.25 - 0.3 s : 11,6 - 5,4 N
   * 0.3 - 0.55 s : 5,4 - 3,5 N
   * 0.55 - 1,2 s : 3,5 - 3,5 N
   * 1,2 - 1,3 s  : 3,5 - 0 N
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private double calcSachsen_B4_4( double dTime ) {
    if (dTime < 0 || dTime > 1.3) return 0;
    if (dTime < 0.25) return calcLinearInterval( 0, 0.25, 0, 11.6, dTime );
    if (dTime < 0.3) return calcLinearInterval( 0.25, 0.3, 11.6, 5.4, dTime );
    if (dTime < 0.55) return calcLinearInterval( 0.3, 0.55, 5.4, 3.5, dTime );
    if (dTime < 1.2) return 3.5;
    return calcLinearInterval( 1.2, 1.3, 3.5, 0, dTime );
  }

  // --------------- c a l c S a c h s e n _ C 6 _ 3 ----------
  /**
   * Thrust is approximated with following equations:
   * 0 - 0.2 s     : 0 - 11,6 N
   * 0.2 - 0.25 s  : 11,6 N
   * 0.25 - 0.32 s : 11,6 - 5,2 N
   * 0.32 - 0.5 s  : 5,2 - 3.6 N
   * 0.5 - 1.1 s   : 3.6 - 3.0 N
   * 1.1 - 1.8 s   : 3.0 - 3.7 N
   * 1.8 - 1.85 s  : 3.7 - 0 N
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private double calcSachsen_C6_3( double dTime ) {
    if (dTime < 0 || dTime > 1.85) return 0;
    if (dTime < 0.2) return calcLinearInterval( 0, 0.2, 0, 11.6, dTime );
    if (dTime < 0.25) return 11.6;
    if (dTime < 0.32) return calcLinearInterval( 0.25, 0.32, 11.6, 5.2, dTime );
    if (dTime < 0.5) return calcLinearInterval( 0.32, 0.5, 5.2, 3.6, dTime );
    if (dTime < 1.1) return calcLinearInterval( 0.5, 1.1, 3.6, 3, dTime );
    if (dTime < 1.8) return calcLinearInterval( 1.1, 1.8, 3.0, 3.7, dTime );
    return calcLinearInterval( 1.8, 1.85, 3.7, 0, dTime );
  }

  // --------------- c a l c S a c h s e n _ D 7 _ 3 ----------
  /**
   * Thrust is approximated with following equations:
   * 0 - 0.32 s    : 0 - 18.5 N
   * 0.32 - 0.38 s : 18.5 - 20.5 N
   * 0.38 - 0.42 s : 20.5 N
   * 0.42 - 0.5 s  : 20.5 - 12.5 N
   * 0.5 - 0.6 s   : 12.5 - 10.5 N
   * 0.6 - 0.9 s   : 10.5 - 7.9 N
   * 0.9 - 1.34 s  : 7.9 - 8.3 N
   * 1.34 - 1.5 s  : 8.3 - 0 N
   * Measured from graph from http://www.raketenmodellbautechnik.de/produkte/Motoren/
   */
  private double calcSachsen_D7_3( double dTime ) {
    if (dTime < 0 || dTime > 1.5) return 0;
    if (dTime < 0.32) return calcLinearInterval( 0, 0.32, 0, 18.5, dTime );
    if (dTime < 0.38) return calcLinearInterval( 0.32, 0.38, 18.5, 20.5, dTime );
    if (dTime < 0.42) return 20.5;
    if (dTime < 0.5) return calcLinearInterval( 0.42, 0.5, 20.5, 12.5, dTime );
    if (dTime < 0.6) return calcLinearInterval( 0.5, 0.6, 12.5, 10.5, dTime );
    if (dTime < 0.9) return calcLinearInterval( 0.6, 0.9, 10.5, 7.9, dTime );
    if (dTime < 1.34) return calcLinearInterval( 0.9, 1.34, 7.9, 8.3, dTime );
    return calcLinearInterval( 1.34, 1.5, 8.3, 0, dTime );
  }

  // --------------- c a l c A e r o t e c h _ D 2 4 _ 7 ----------
  /**
   * Thrust is approximated with following equations:
   * 0 - 0.02 s    : 0 - 38 N
   * 0.02 - 0.06 s : 38 - 33 N
   * 0.06 - 0.70 s : 33 - 19 N
   * 0.70 - 0.76 s : 19 - 6 N
   * 0.76 - 0.90 s : 6 - 0 N
   * Measured from graph from D24-7T package.
   */
  private double calcAerotech_D24_7( double dTime ) {
    if (dTime < 0 || dTime > 0.90) return 0;
    if (dTime < 0.02) return calcLinearInterval( 0, 0.02, 0, 38, dTime );
    if (dTime < 0.06) return calcLinearInterval( 0.02, 0.06, 38, 33, dTime );
    if (dTime < 0.70) return calcLinearInterval( 0.06, 0.70, 33, 19, dTime );
    if (dTime < 0.76) return calcLinearInterval( 0.70, 0.76, 19, 6, dTime );
    return calcLinearInterval( 0.76, 0.90, 6, 0, dTime );
  }

  // ---------------- c a l c M a s s ------------------
  /**
   * Rocket's mass during particular moment.
   * Mass is approximated with linear equation when motor is functioning.
   */
  private double calcMass( double dTime ) {
    if (dTime > dEjectionTime)
      return dEmptyMotorMass;

    return calcLinearInterval( 0, dEjectionTime, dFullMass, dEmptyMotorMass, dTime );
  }

  // ---------------- c a l c A i r D e n s i t y ----------------
  /**
   * Air density in particular altitude.
   * Air density is approximated with following equations:
   *  km   density kb/m^3
   *    0  1.2250
   *    1  1.1117
   *    3  0.90912
   *    5  0.76312
   *   10  0.41351
   *   25  0.040084
   *   50  0.0010269
   *   75  0.000034861
   *  100  5.604 E -7
   *  130  8.152 E -9
   *  160  1.233 E -9
   *  200  2.541 E -10
   *  300  1.916 E -11
   *  400  2.803 E -12
   *  600  2.137 E -13
   * 1000  3.561 E -15
   * (100 km is considered as zero below)
   * Data is from Sutton, Biblarz: Rocket Propulsion Elements: Appendix 2
   * Which is called 'U.S. Standard Atmosphere'
   */
  private double calcAirDensity( double dAltitude ) {
    if (dAltitude < 1000) return calcLinearInterval( 0, 1000, 1.225, 1.1117, dAltitude);
    if (dAltitude < 3000) return calcLinearInterval( 1000, 3000, 1.1117, 0.90912, dAltitude );
    if (dAltitude < 5000) return calcLinearInterval( 3000, 5000, 0.90912, 0.76312, dAltitude );
    if (dAltitude < 10000) return calcLinearInterval( 5000, 10000, 0.76312, 0.41351, dAltitude );
    if (dAltitude < 25000) return calcLinearInterval( 10000, 25000, 0.41351, 0.040084, dAltitude );
    if (dAltitude < 50000) return calcLinearInterval( 25000, 50000, 0.040084, 0.0010269, dAltitude );
    if (dAltitude < 75000) return calcLinearInterval( 50000, 75000, 0.0010269, 0.000034861, dAltitude );
    if (dAltitude < 100000) return calcLinearInterval( 75000, 100000, 0.000034861, 0, dAltitude );
    return 0;
  }

  // ---------------- c a l c D r a g ------------
  /**
   * Calculates drag caused by air.
   */
  private double calcDrag( double dAirDensity, double dVelocity ) {
    double dResult = 0.5 * dAirDensity * dVelocity * dVelocity * dDragCoefficient * dFrontalArea;
    if (dVelocity < 0)
      dResult = -dResult;
    return dResult;
  }

  // ---------------- c a l c A c c e l e r a t i o n ----------------
  /**
   * Calculates rocket's acceleration.
   */
  private double calcAcceleration( double dThrust, double dDrag, double dMass ) {
    return (dThrust - dDrag) / dMass - dGravity;
  }

  // ---------------- c a l c V e l o c i t y ----------------
  /**
   * Calculates rocket's velocity.
   */
  private double calcVelocity( double dPrevVelocity, double dAcceleration ) {
    return dPrevVelocity + dAcceleration * dDeltaTime;
  }
  
  // ---------------- c a l c A l t i t u d e ----------------
  /**
   * Calculates rocket's altitude.
   */
  private double calcAltitude( double dPrevAltitude, double dPrevVelocity, double dAcceleration ) {
    double dResult = dPrevAltitude + dPrevVelocity * dDeltaTime + 0.5 * dAcceleration * dDeltaTime * dDeltaTime;
    if (dResult < 0)
      dResult = 0;
    return dResult;
  }

  // ------------ r o u n d 2 D e s i m ------------------
  /**
   * Rounds double to certain amount of decimals.
   */
  public static double round2Desim( double dToRound, int iDesim ) {
    long lCoeff = Math.round( Math.pow( 10, iDesim ) );

    return (double)Math.round( dToRound * lCoeff ) / lCoeff;
  }

  // ------------------ r u n -----------------
  /**
   * Main simulation loop.
   */
  public void run( String sFile ) throws IOException {
    System.out.println();
    String sError = "";
    if (iMotorIndex == -1) sError += "sMotorType ";
    if (dNoMotorMass == 0) sError += "dNoMotorMass ";
    if (dDragCoefficient == 0) sError += "dDragCoefficient ";
    if (dDiameter == 0) sError += "Diameter ";
    if (sError.length() > 0) {
      System.err.println("Undefined "+sError);
      System.exit(-1);
    }

    System.out.println("Parameters given:");
    System.out.println("Motor type\t"+sMotors[ iMotorIndex ][0]+" "+sMotors[ iMotorIndex ][ 1 ]);
    System.out.println("Mass without motor\t"+round2Desim( dNoMotorMass, 3 )+" kg");
    System.out.println("Drag coefficient\t"+round2Desim( dDragCoefficient, 2 ));
    System.out.println("Tube diameter\t"+round2Desim( dDiameter, 4 )+" m");
    if (sFile == null)
      System.out.println("No simulation-step file.");
    else
      System.out.println("File to print simulation steps: "+sFile);
    System.out.println();

    dFullMass = dNoMotorMass + dMotors[ iMotorIndex ][0];
    dEmptyMotorMass = dNoMotorMass + dMotors[ iMotorIndex ][1];
    dEjectionTime = dMotors[ iMotorIndex ][2];

    System.out.println("Derived from motor type:");
    System.out.println("Mass with full motor\t"+round2Desim( dFullMass, 3 )+" kg");
    System.out.println("Mass with empty motor\t"+round2Desim( dEmptyMotorMass, 3 )+" kg");
    System.out.println("Time of ejection\t"+round2Desim( dEjectionTime, 2 )+" s");
    System.out.println();

    double dTime = 0;
    double dThrust;
    double dMass;
    double dAirDensity;
    double dDrag;
    double dAcceleration;
    double dPrevVelocity = 0;
    double dVelocity;
    double dPrevAltitude = 0;
    double dAltitude;

    double dMaxThrust = 0;
    double dAvgThrustSum = 0;
    int iAvgThrustCount = 0;
    double dTotalImpulse = 0;
    double dMaxDrag = 0;
    double dMinDrag = 0;
    double dMaxAcceleration = 0;
    double dMinAcceleration = 0;
    double dMaxVelocity = 0;
    double dMinVelocity = 0;
    double dMaxAltitude = 0;
    double dDelayAltitude = 0;

    double dBurnoutTime = 0;
    double dMaxAltitudeTime = 0;

    int iLoopNro = 0;
    int iMaxLoops = (int)(10 * 60 / dDeltaTime);

    FileOutputStream fos = null;
    String sDelimiter = "\t";
    if (sFile != null) {
      fos = new FileOutputStream(sFile);
      fos.write( ("iLoopNro"+sDelimiter+"dTime"+sDelimiter+"dThrust"+sDelimiter+"dMass"+sDelimiter
		  +"dAirDensity"+sDelimiter+"dDrag"+sDelimiter+"dAcceleration"+sDelimiter
		  +"dVelocity"+sDelimiter+"dAltitude\n").getBytes() );
    }

    System.out.print("Simulating");

    while (iLoopNro < iMaxLoops && (dPrevAltitude > 0 || dTime < 2)) {
      
      dThrust = calcThrust( dTime );

      dMass = calcMass( dTime );

      dAirDensity = calcAirDensity( dPrevAltitude );

      dDrag = calcDrag( dAirDensity, dPrevVelocity );

      dAcceleration = calcAcceleration( dThrust, dDrag, dMass );

      dVelocity = calcVelocity( dPrevVelocity, dAcceleration );

      dAltitude = calcAltitude( dPrevAltitude, dPrevVelocity, dAcceleration );

      if (dAltitude <= 0) {
	dVelocity = 0;
	dAltitude = 0;
      }

      if (fos != null)
	fos.write( (iLoopNro+sDelimiter + round2Desim( dTime, 3 )+sDelimiter + round2Desim( dThrust, 2)+sDelimiter
		    +round2Desim( dMass, 4 )+sDelimiter + round2Desim( dAirDensity, 3 )+sDelimiter
		    +round2Desim( dDrag, 2 )+sDelimiter + round2Desim( dAcceleration, 2 )+sDelimiter
		    +round2Desim( dVelocity, 2 )+sDelimiter + round2Desim( dAltitude, 2 )+"\n").getBytes());

      if (iLoopNro % 100 == 0)
	System.out.print(".");

      if (dThrust > dMaxThrust)	dMaxThrust = dThrust;
      if (dThrust > 0) {
	dAvgThrustSum += dThrust;
	dTotalImpulse += dThrust * dDeltaTime;
	iAvgThrustCount++;
      }

      if (dDrag > dMaxDrag) dMaxDrag = dDrag;
      if (dDrag < dMinDrag) dMinDrag = dDrag;
      if (dAcceleration > dMaxAcceleration) dMaxAcceleration = dAcceleration;
      if (dAcceleration < dMinAcceleration) dMinAcceleration = dAcceleration;
      if (dVelocity > dMaxVelocity) dMaxVelocity = dVelocity;
      if (dVelocity < dMinVelocity) dMinVelocity = dVelocity;
      if (dAltitude > dMaxAltitude)
	dMaxAltitude = dAltitude;
      if (dTime < dEjectionTime)
	dDelayAltitude = dAltitude;

      if (dThrust == 0 && dBurnoutTime == 0 && iLoopNro > 10) dBurnoutTime = dTime;
      if (dAltitude > dPrevAltitude && dAltitude > 0) dMaxAltitudeTime = dTime;

      dPrevVelocity = dVelocity;
      dPrevAltitude = dAltitude;

      dTime += dDeltaTime;
      iLoopNro++;
    }
    System.out.println("done.");

    if (fos != null) {
      fos.close();
      fos = null;
    }

    System.out.println();
    System.out.println("Results:");
    System.out.println("Loops\t"+iLoopNro);
    System.out.println("Max thrust\t"+round2Desim( dMaxThrust, 1 )+" N");
    System.out.println("Avg thrust\t"+round2Desim( dAvgThrustSum/iAvgThrustCount, 1 )+" N");
    System.out.println("Total impulse\t"+round2Desim( dTotalImpulse, 1 )+" N");
    System.out.println("Max drag\t"+round2Desim( dMaxDrag,1 )+" N");
    System.out.println("Min drag\t"+round2Desim( dMinDrag,1 )+" N (without ejection)");
    System.out.println("Max acceleration\t"+Math.round( dMaxAcceleration )
		       +" m/s^2 == "+round2Desim(dMaxAcceleration/dGravity, 1)+" g");
    System.out.println("Min acceleration\t"+Math.round( dMinAcceleration )
		       +" m/s^2 == "+round2Desim(dMinAcceleration/dGravity, 1)+" g");
    System.out.println("Max velocity\t"+Math.round( dMaxVelocity )+" m/s");
    System.out.println("Min velocity\t"+Math.round( dMinVelocity )+" m/s (without ejection)");
    System.out.println("Max altitude\t"+Math.round( dMaxAltitude )+" m (without ejection)");
    System.out.println("Altitude at ejection\t"+Math.round( dDelayAltitude )+" m");
    System.out.println("Time of burnout\t"+round2Desim( dBurnoutTime, 2 )+" s");
    System.out.println("Time of max altitude\t"+round2Desim( dMaxAltitudeTime, 2 )+" s (without ejection)");
    System.out.println("Flight time\t"+round2Desim( dTime, 2 )+" s (without ejection)");
    System.out.println();
  }

  // ------------------ m a i n -------------------
  public static void main( String[] sArgs ) {
    System.out.println();
    System.out.println("Free Rocket Simulation Program, version 0.0.0.6, published 10.12.2008");
    System.out.println("Copyright (C) 2003-2008 Aapo Puhakka, http://www.iki.fi/~aapo/");
    System.out.println("This program is distributed under the terms of the GNU General Public License (GPL).");
    System.out.println();

    Simulation sim = new Simulation();
    if (sArgs.length < 4) {
      System.out.println("Usage: Simulation <motor> <m> <Cd> <d> <file>");
      System.out.println("Where:");
      String sTmp = " motor:\tType of motor: ";
      for (int i = 0; i < sMotors.length; i++) {
	sTmp += sMotors[i][0];
	if (i < sMotors.length-2)
	  sTmp += ", ";
	else if (i == sMotors.length-2)
	  sTmp += " or ";
      }
      System.out.println( sTmp );
      System.out.println(" m:\tRocket's mass without a motor (kg)");
      System.out.println(" Cd:\tRocket's drag coefficient");
      System.out.println(" d:\tDiameter or rocket's tube (m)");
      System.out.println(" file:\tFile to print simulation steps. Optional.");
      System.out.println();
      System.out.println("For example:");
      System.out.println("Simulation SF_C 0.032 0.8 0.02");
      System.out.println();
    }
    else {
      sim.setMotorType( sArgs[0] );
      sim.setNoMotorMass( Double.parseDouble( sArgs[1] ) );
      sim.setDragCoefficient( Double.parseDouble( sArgs[2] ) );
      sim.setDiameter( Double.parseDouble( sArgs[3] ) );
      try {
	if (sArgs.length == 4)
	  sim.run( null );
	else
	  sim.run( sArgs[4] );
      } catch (IOException e) {
	e.printStackTrace();
	System.err.println(e.getClass().getName()+" "+e.getMessage());
      }
    }
  }

}
