// Version 0.1.4 - 26 apr 1998 import java.awt.*; import java.lang.*; import java.util.*; import java.applet.*; public class STApplet extends Applet { static String defaultText = "len 25.5\"\n" + "\n" + "E .012\" PL\n" + "B, .016\" PL\n" + "G, .024\" PB\n" + "D, .032\" PB\n" + "A,, .042\" PB\n" + "E,, .053\" PB\n" + "total\n" + "\n" + "E 23# PL\n" + "B, 23# PL\n" + "G, 30# PB\n" + "D, 30# PB\n" + "A,, 30# PB\n" + "E,, 26# PB\n" ; TextArea textArea1 = new TextArea( defaultText ); Button calculate = new Button(); GridBagLayout gridBagLayout1 = new GridBagLayout(); Checkbox metricCheckbox = new Checkbox(); Checkbox verboseCheckbox = new Checkbox(); public STApplet() { } //Component initialization public void init() { this.setLayout(gridBagLayout1); textArea1.setFont(new Font("Courier", 0, 11)); calculate.setLabel("Calculate"); metricCheckbox.setLabel("Metric"); verboseCheckbox.setLabel("Verbose"); gridBagLayout1.setConstraints(metricCheckbox, new GridBagConstraintsX(0, 0, 1, 1, .5, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); this.add(metricCheckbox); gridBagLayout1.setConstraints(verboseCheckbox, new GridBagConstraintsX(1, 0, 1, 1, .5, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); this.add(verboseCheckbox); gridBagLayout1.setConstraints(calculate, new GridBagConstraintsX(2, 0, 2, 1, 1.0, 0.0 ,GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); this.add(calculate); gridBagLayout1.setConstraints(textArea1, new GridBagConstraintsX(0, 1, 4, 1, 1.0, 1.0 ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); this.add(textArea1); show(); } static String sep = " == "; String strip( String ss ) { int ndx = ss.lastIndexOf( sep ); if ( ndx >= 0 ) { return ss.substring( 0, ndx ); } else { return ss; } } public boolean action( Event evt, Object what ) { //--- recalculate on all actions doCalculate(); return true; } public boolean keyDown( Event event, int key ) { if ( key == '\n' && (event.modifiers & Event.SHIFT_MASK) != 0 ) { doCalculate(); return true; } return false; } void doCalculate() { double len = 25.5 * 2.54; boolean metric = metricCheckbox.getState(); boolean verbose = verboseCheckbox.getState(); double totalTension = 0.; StringBuffer out = new StringBuffer(); StringTokenizer lines = new StringTokenizer( textArea1.getText(), "\n", true ); while ( lines.hasMoreTokens() ) { String line = lines.nextToken(); if ( line.charAt( 0 ) == '\n' ) { out.append( line ); continue; } line = strip( line ); StringTokenizer words = new StringTokenizer( line ); String ww = words.nextToken(); if ( ww.endsWith( ":" ) ) { ww = ww.substring( 1, ww.length() - 1 ); } if ( ww.equalsIgnoreCase( "len" ) || ww.equalsIgnoreCase( "length" ) ) { try { out.append( line ); len = parseLength( words, metric ); double rlen = Math.round( ( metric ? len : len / 2.54 ) * 100 ) / 100.; if ( verbose ) { out.append( sep + rlen + ( metric ? "cm" : "\"" ) ); } } catch ( Exception ee ) { out.append( line + sep + "bad length: " + ee ); } continue; } if ( ww.equalsIgnoreCase( "total" ) ) { out.append( line + sep + ( Math.round( totalTension * 100 ) / 100. ) + ( metric ? "kg" : "#" ) ); totalTension = 0.; continue; } if ( ww.equalsIgnoreCase( "totalX2" ) ) { out.append( line + sep + ( Math.round( totalTension * 2 * 100 ) / 100. ) + ( metric ? "kg" : "#" ) ); totalTension = 0.; continue; } else { int note; double tension = 0.; double gauge = 0.; boolean doTension = true; double[][] weights; try { note = parseNote( ww ); } catch ( Exception ee ) { out.append( line ); continue; } try { ww = words.nextToken(); if ( ww.endsWith( "." ) ) { ww = ww.substring( 0, ww.length() - 1 ); } if ( ww.endsWith( "s" ) ) { ww = ww.substring( 0, ww.length() - 1 ); } doTension = ! ( ww.endsWith( "#" ) || ww.endsWith( "lb" ) || ww.endsWith( "kg" ) ); if ( doTension ) { gauge = parseGauge( ww, metric ); if ( gauge < .004 ) { out.append( line + sep + "guage too small: " + (Math.round(gauge*10000)/10000.) + "\"" ); continue; } } else { tension = parseTension( ww, metric ); } } catch ( Exception ee ) { out.append( line + sep + "bad " + ( doTension ? "gauge" : "tension" ) + ": " + ee ); continue; } try { ww = words.nextToken(); if ( ww.equalsIgnoreCase( "pl" ) || ww.equalsIgnoreCase( "p" ) ) { weights = PL; } else if ( ww.equalsIgnoreCase( "pb" ) || ww.equalsIgnoreCase( "b" ) || ww.equalsIgnoreCase( "w" ) ) { weights = PB; } else if ( ww.equalsIgnoreCase( "xs" ) || ww.equalsIgnoreCase( "s" ) ) { weights = XS; } else if ( ww.equalsIgnoreCase( "nw" ) || ww.equalsIgnoreCase( "n" ) ) { weights = NW; } else if ( ww.equalsIgnoreCase( "hr" ) || ww.equalsIgnoreCase( "h" ) ) { weights = HR; } else { throw ( new IllegalArgumentException() ); } } catch ( Exception ee ) { out.append( line + sep + "bad string type: " + ee ); continue; } double fq = 440. * Math.pow( Math.pow(2.,1./12.), note ); if ( doTension ) { double wt = getWeight( gauge, weights ); tension = ( 4 * fq * fq * len * (len * wt) ) / 980621.; if ( ! metric ) { tension *= 2.2047; } totalTension += tension; tension = Math.round( tension * 100 ) / 100.; fq = Math.round( fq * 10 ) / 10.; wt = Math.round( wt * 10000 ) / 10000.; out.append( line + sep + tension + ( metric ? "kg" : "#" ) ); if ( verbose ) { out.append( " ( " + wt + "gm/cm " + fq + "hz )" ); } } else { double wt = ( tension * 980621. ) / ( 4 * fq * fq * len * len ); gauge = getGauge( wt, weights ); if ( metric ) { gauge *= 25.4; } gauge = Math.round( gauge * 10000 ) / 10000.; fq = Math.round( fq * 10 ) / 10.; wt = Math.round( wt * 10000 ) / 10000.; out.append( line + sep + gauge + ( metric ? "mm" : "\"" ) ); if ( verbose ) { out.append( " ( " + wt + "gm/cm " + fq + "hz )" ); } } } } textArea1.replaceText( out.toString(), 0, textArea1.getText().length() ); } static double getWeight( double gauge, double[][] weights ) { return getGaugeOrWeight( gauge, weights, 0, 1 ) /(2.2046/1000)/2.54; } static double getGauge( double weight, double[][] weights ) { return getGaugeOrWeight( weight*(2.2046/1000)*2.54, weights, 1, 0 ); } static double getGaugeOrWeight( double value, double[][] weights, int inndx, int outndx ) { int ll = weights.length; int ii; for ( ii = 0; ii < ll; ++ii ) { if ( value < weights[ ii ][ inndx ] ) { break; } } double wt; if ( ii == ll ) { wt = weights[ ll - 3 ][ outndx ] + ( (weights[ ll - 1 ][ outndx ] - weights[ ll - 3 ][ outndx ]) * (value - weights[ ll - 3 ][ inndx ]) / (weights[ ll - 1 ][ inndx ] - weights[ ll - 3 ][ inndx ]) ); } else if ( ii == 0 ) { wt = weights[ 0 ][ outndx ] + ( (weights[ 2 ][ outndx ] - weights[ 0 ][ outndx ]) * (value - weights[ 0 ][ inndx ]) / (weights[ 2 ][ inndx ] - weights[ 0 ][ inndx ]) ); } else { wt = weights[ ii - 1 ][ outndx ] + ( (weights[ ii ][ outndx ] - weights[ ii - 1 ][ outndx ]) * (value - weights[ ii - 1 ][ inndx ]) / (weights[ ii ][ inndx ] - weights[ ii - 1 ][ inndx ]) ); } return wt; } static double parseGauge( String ww, boolean metric ) { int ii; for ( ii = 0; ii < ww.length(); ++ii ) { char cc = ww.charAt( ii ); if ( cc != '.' && ! Character.isDigit( cc ) ) { break; } } double dd = new Double( ww.substring( 0, ii ) ).doubleValue(); if ( ii < ww.length() ) { ww = ww.substring( ii ); if ( ww.equals( "\"" ) ) {} else if ( ww.equals( "cm" ) ) { dd /= 2.54; } else if ( ww.equals( "mm" ) ) { dd /= 25.4; } else { throw new IllegalArgumentException(); } } else { if ( metric ) dd /= 25.4; } return dd; } static double parseTension( String ww, boolean metric ) { int ii; for ( ii = 0; ii < ww.length(); ++ii ) { char cc = ww.charAt( ii ); if ( cc != '.' && ! Character.isDigit( cc ) ) { break; } } double dd = new Double( ww.substring( 0, ii ) ).doubleValue(); if ( ii < ww.length() ) { ww = ww.substring( ii ); if ( ww.equals( "#" ) ) { dd /= 2.2047; } else if ( ww.equals( "lb" ) ) { dd /= 2.2047; } else if ( ww.equals( "kg" ) ) {; } else { throw new IllegalArgumentException(); } } else { if ( ! metric ) dd /= 2.2047; } return dd; } int parseNote( String ww ) { int accidental = 0; if ( ww.charAt( 0 ) == '_' ) { accidental = -1; ww = ww.substring( 1 ); } else if ( ww.charAt( 0 ) == '^' ) { accidental = 1; ww = ww.substring( 1 ); } int note = "C D EF G A Bc d ef g a b".indexOf( ww.charAt( 0 ) ); if ( note == -1 ) { throw new IllegalArgumentException(); } ww = ww.substring( 1 ); if ( ww.length() > 0 ) { if ( Character.isDigit( ww.charAt( 0 ) ) ) { if ( note >= 12 ) { note -= 12; } note += 12 * ( Character.digit( ww.charAt( 0 ), 10 ) - 4 ); ww = ww.substring( 1 ); } else { while ( ww.length() > 0 && ww.charAt( 0 ) == ',' ) { note -= 12; ww = ww.substring( 1 ); } while ( ww.length() > 0 && ww.charAt( 0 ) == '\'' ) { note += 12; ww = ww.substring( 1 ); } } } if ( ww.length() > 0 ) { if ( ww.charAt( 0 ) == 'b' ) { accidental = -1; ww = ww.substring( 1 ); } else if ( ww.charAt( 0 ) == '#' ) { accidental = 1; ww = ww.substring( 1 ); } } if ( ww.length() > 0 ) { throw new IllegalArgumentException(); } note += accidental; note -= 9; // A440 is base return note; } static double parseLength( StringTokenizer words, boolean metric ) { String ww = words.nextToken(); int ii; for ( ii = 0; ii < ww.length(); ++ii ) { char cc = ww.charAt( ii ); if ( cc != '.' && ! Character.isDigit( cc ) ) { break; } } double dd = new Double( ww.substring( 0, ii ) ).doubleValue(); if ( ii < ww.length() ) { ww = ww.substring( ii ); } else if ( words.hasMoreTokens() ) { ww = words.nextToken(); } else { if ( ! metric ) dd *= 2.54; return dd; } if ( ww.equals( "\"" ) ) { dd *= 2.54; } else if ( ww.equals( "cm" ) ) {} else if ( ww.equals( "mm" ) ) { dd /= 10.; } else { throw new IllegalArgumentException(); } return dd; } double[][] PL = { { .007 , .00001085 }, { .008 , .00001418 }, { .0085 , .00001601 }, { .009 , .00001794 }, { .0095 , .00001999 }, { .010 , .00002215 }, { .0105 , .00002442 }, { .011 , .00002680 }, { .0115 , .00002930 }, { .012 , .00003190 }, { .013 , .00003744 }, { .0135 , .00004037 }, { .014 , .00004342 }, { .015 , .00004984 }, { .016 , .00005671 }, { .017 , .00006402 }, { .018 , .00007177 }, { .019 , .00007997 }, { .020 , .00008861 }, { .022 , .00010722 }, { .024 , .00012760 }, { .026 , .00014975 } }; double[][] PB = { { .020 , .00008106 }, { .021 , .00008944 }, { .022 , .00009876 }, { .023 , .00010801 }, { .024 , .00011682 }, { .025 , .00012686 }, { .026 , .00013640 }, { .027 , .00014834 }, { .029 , .00017381 }, { .030 , .00018660 }, { .032 , .00021018 }, { .034 , .00023887 }, { .035 , .00025365 }, { .036 , .00026824 }, { .039 , .00031124 }, { .042 , .00036722 }, { .045 , .00041751 }, { .047 , .00045289 }, { .049 , .00049151 }, { .052 , .00055223 }, { .053 , .00056962 }, { .056 , .00063477 }, { .059 , .00070535 } }; double[][] XS = { { .018 , .00006153 }, { .020 , .00007396 }, { .021 , .00008195 }, { .022 , .00009089 }, { .024 , .00010742 }, { .026 , .00012533 }, { .028 , .00014471 }, { .030 , .00017002 }, { .032 , .00019052 }, { .034 , .00021229 }, { .036 , .00023535 }, { .038 , .00025969 }, { .040 , .00028995 }, { .042 , .00031685 }, { .046 , .00037449 }, { .048 , .00040523 }, { .050 , .00043726 }, { .052 , .00047056 }, { .054 , .00052667 }, { .056 , .00056317 }, { .070 , .00087444 } }; double[][] NW = { { .017 , .00005524 }, { .018 , .00006215 }, { .019 , .00006947 }, { .020 , .00007495 }, { .021 , .00008293 }, { .022 , .00009184 }, { .024 , .00010857 }, { .026 , .00012671 }, { .028 , .00014666 }, { .030 , .00017236 }, { .032 , .00019347 }, { .034 , .00021590 }, { .036 , .00023964 }, { .038 , .00026471 }, { .039 , .00027932 }, { .042 , .00032279 }, { .044 , .00035182 }, { .046 , .00038216 }, { .048 , .00041382 }, { .049 , .00043014 }, { .052 , .00048109 }, { .056 , .00057598 }, { .059 , .00064191 }, { .060 , .00066542 }, { .062 , .00070697 }, { .064 , .00074984 }, { .066 , .00079889 }, { .068 , .00084614 }, { .070 , .00089304 }, { .072 , .00094124 }, { .074 , .00098869 }, { .080 , .00115011 }, }; double[][] HR = { { .022 , .00011271 }, { .024 , .00013139 }, { .026 , .00015224 }, { .030 , .00019916 }, { .032 , .00022329 }, { .036 , .00027556 }, { .039 , .00032045 }, { .042 , .00036404 }, { .046 , .00043534 }, { .052 , .00054432 }, { .056 , .00062758 } }; } class GridBagConstraintsX extends GridBagConstraints { public GridBagConstraintsX(int gridx, int gridy, int gridwidth, int gridheight, double weightx, double weighty, int anchor, int fill, Insets insets, int ipadx, int ipady) { this.gridx = gridx; this.gridy = gridy; this.gridwidth = gridwidth; this.gridheight = gridheight; this.fill = fill; this.ipadx = ipadx; this.ipady = ipady; this.insets = insets; this.anchor = anchor; this.weightx = weightx; this.weighty = weighty; } }