From 914e6674572997b88a3444489af49c0268319e83 Mon Sep 17 00:00:00 2001 From: ramonaharrison Date: Thu, 21 May 2015 19:06:46 -0400 Subject: [PATCH 1/2] finished --- ScientificCalculator | 1 + 1 file changed, 1 insertion(+) create mode 160000 ScientificCalculator diff --git a/ScientificCalculator b/ScientificCalculator new file mode 160000 index 0000000..b8551f5 --- /dev/null +++ b/ScientificCalculator @@ -0,0 +1 @@ +Subproject commit b8551f5dbec64d4582e081e5e056c86b4d39d28b From f1211ecd8cb4b373ab30b04309498136cfd89ffb Mon Sep 17 00:00:00 2001 From: ramonaharrison Date: Thu, 21 May 2015 19:07:56 -0400 Subject: [PATCH 2/2] ... --- .DS_Store | Bin 0 -> 6148 bytes ScientificCalculator | 1 - ScientificCalculator.iml | 19 + app/.gitignore | 1 + app/app.iml | 94 +++ app/build.gradle | 26 + app/libs/JbcParser.jar | Bin 0 -> 39610 bytes app/proguard-rules.pro | 17 + .../scientificcalculator/ApplicationTest.java | 13 + app/src/main/AndroidManifest.xml | 27 + .../scientificcalculator/Calculate.java | 270 ++++++++ .../scientificcalculator/GraphActivity.java | 127 ++++ .../scientificcalculator/GraphView.java | 183 ++++++ .../scientificcalculator/MainActivity.java | 592 ++++++++++++++++++ app/src/main/res/drawable/calculator_bar.xml | 17 + .../main/res/layout-land/activity_main.xml | 447 +++++++++++++ app/src/main/res/layout/activity_graph.xml | 110 ++++ app/src/main/res/layout/activity_main.xml | 241 +++++++ app/src/main/res/menu/menu_graph.xml | 11 + app/src/main/res/menu/menu_main.xml | 11 + app/src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3418 bytes app/src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2206 bytes app/src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4842 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 7718 bytes app/src/main/res/values-v21/styles.xml | 9 + app/src/main/res/values-w820dp/dimens.xml | 6 + app/src/main/res/values/attrs.xml | 2 + app/src/main/res/values/dimens.xml | 5 + app/src/main/res/values/strings.xml | 7 + app/src/main/res/values/styles.xml | 9 + build.gradle | 19 + build/intermediates/dex-cache/cache.xml | 40 ++ build/intermediates/model_data.bin | Bin 0 -> 85381 bytes gradle.properties | 18 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 49896 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 +++++ gradlew.bat | 90 +++ local.properties | 10 + settings.gradle | 1 + 40 files changed, 2592 insertions(+), 1 deletion(-) create mode 100644 .DS_Store delete mode 160000 ScientificCalculator create mode 100644 ScientificCalculator.iml create mode 100644 app/.gitignore create mode 100644 app/app.iml create mode 100644 app/build.gradle create mode 100644 app/libs/JbcParser.jar create mode 100644 app/proguard-rules.pro create mode 100644 app/src/androidTest/java/nyc/c4q/ramonaharrison/scientificcalculator/ApplicationTest.java create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/Calculate.java create mode 100644 app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphActivity.java create mode 100644 app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphView.java create mode 100644 app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/MainActivity.java create mode 100644 app/src/main/res/drawable/calculator_bar.xml create mode 100644 app/src/main/res/layout-land/activity_main.xml create mode 100644 app/src/main/res/layout/activity_graph.xml create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 app/src/main/res/menu/menu_graph.xml create mode 100644 app/src/main/res/menu/menu_main.xml create mode 100644 app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 app/src/main/res/values-v21/styles.xml create mode 100644 app/src/main/res/values-w820dp/dimens.xml create mode 100644 app/src/main/res/values/attrs.xml create mode 100644 app/src/main/res/values/dimens.xml create mode 100644 app/src/main/res/values/strings.xml create mode 100644 app/src/main/res/values/styles.xml create mode 100644 build.gradle create mode 100644 build/intermediates/dex-cache/cache.xml create mode 100644 build/intermediates/model_data.bin create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 local.properties create mode 100644 settings.gradle diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 + + + + + + + + + + + + + + + + + diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..22541f3 --- /dev/null +++ b/app/app.iml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..da28d23 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,26 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 22 + buildToolsVersion "22.0.1" + + defaultConfig { + applicationId "nyc.c4q.ramonaharrison.scientificcalculator" + minSdkVersion 15 + targetSdkVersion 22 + versionCode 1 + versionName "1.0" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'com.android.support:appcompat-v7:22.1.1' + compile files('libs/JbcParser.jar') +} diff --git a/app/libs/JbcParser.jar b/app/libs/JbcParser.jar new file mode 100644 index 0000000000000000000000000000000000000000..ff1e40fc87f13af6c09038a83926750cb3d387b7 GIT binary patch literal 39610 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 zTesting Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..80640ef --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/Calculate.java b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/Calculate.java new file mode 100644 index 0000000..554495a --- /dev/null +++ b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/Calculate.java @@ -0,0 +1,270 @@ +package nyc.c4q.ramonaharrison.scientificcalculator; + +import com.bestcode.mathparser.IMathParser; +import com.bestcode.mathparser.MathParserFactory; + +import java.util.ArrayList; + +public class Calculate +{ + public static void main(String[] args) + { +// String inputExpression = "4! + 3!"; +// System.out.println(calculate(inputExpression, false)); + + } + + public static ArrayList findFactorialEnds(String parseExpression) { + ArrayList factorialEnds = new ArrayList(); + int start = 0; + int facEnd = 0; + while (facEnd != -1) { + facEnd = parseExpression.indexOf('!', start); + if (facEnd > 0) { + factorialEnds.add(facEnd); + start = facEnd + 1; + + } + } + return factorialEnds; + } + + public static ArrayList findFactorialStarts(String parseExpression, ArrayList factorialEnds) { + + ArrayList factorials = new ArrayList(); + + for (int exclamation : factorialEnds) { + String stringFactorial = ""; + for (int i = exclamation; i >= 0; i--) { + char c = parseExpression.charAt(i); + if (c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9' || c == '0' || c == '.' || c == 'E' || c == '!') { + stringFactorial = c + stringFactorial; + } else { + factorials.add(stringFactorial); + break; + } + if (i == 0) { + factorials.add(stringFactorial); + } + } + + } + return factorials; + } + + public static ArrayList parseFactorials(ArrayList factorials){ + + ArrayList parsedFacs = new ArrayList(); + + for (String fac: factorials){ + + int factorial = Integer.valueOf(fac.substring(0, fac.length() - 1)); + int n = 1; + + while(factorial != 1) { + n *= factorial; + factorial--; + } + parsedFacs.add(String.valueOf(n)); + } + return parsedFacs; + } + public static String calculate(String inputExpression, boolean degrees) { + + String parseExpression = ""; + + // Makes most string expressions readable by the parser. + if(!inputExpression.equals("")) { + + parseExpression = inputExpression.replaceAll("%", "*.01"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("e", "2.71828182846"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("√\\(", "SQRT("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("π", "PI"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("0p", "0*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("0\\(", "0*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("0a", "0*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("0l", "0*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("0s", "0*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("0c", "0*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("0t", "0*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("1p", "1*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("1\\(", "1*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("1a", "1*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("1l", "1*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("1s", "1*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("1c", "1*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("1t", "1*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("2p", "2*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("2\\(", "2*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("2a", "2*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("2l", "2*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("2s", "2*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("2c", "2*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("2t", "2*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("3p", "3*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("3\\(", "3*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("3a", "3*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("3l", "3*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("3s", "3*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("3c", "3*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("3t", "3*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("4p", "4*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("4\\(", "4*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("4a", "4*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("4l", "4*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("4s", "4*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("4c", "4*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("4t", "4*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("5p", "5*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("5\\(", "5*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("5a", "5*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("5l", "5*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("5s", "5*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("5c", "5*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("5t", "5*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("6p", "6*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("6\\(", "6*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("6a", "6*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("6l", "6*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("6s", "6*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("6c", "6*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("6t", "6*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("7p", "7*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("7\\(", "7*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("7a", "7*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("7l", "7*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("7s", "7*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("7c", "7*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("7t", "7*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("8p", "8*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("8\\(", "8*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("8a", "8*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("8l", "8*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("8s", "8*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("8c", "8*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("8t", "8*t"); + inputExpression = parseExpression; + + parseExpression = inputExpression.replaceAll("9p", "9*p"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("9\\(", "9*("); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("9a", "9*a"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("9l", "9*l"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("9s", "9*s"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("9c", "9*c"); + inputExpression = parseExpression; + parseExpression = inputExpression.replaceAll("9t", "9*t"); + inputExpression = parseExpression; + + + ArrayList facEnds = findFactorialEnds(parseExpression); + ArrayList facs = findFactorialStarts(parseExpression, facEnds); + ArrayList parsedFacs = parseFactorials(facs); + for (String fac: facs) { + System.out.println(fac); + } + + for (int i = 0; i <= facs.size()-1; i++){ + parseExpression = inputExpression.replaceAll(facs.get(i), parsedFacs.get(i)); + inputExpression = parseExpression; + } + } + + String result = ""; + try{ + IMathParser parser = MathParserFactory.create(); + Double resultDouble = 0.0; + + parser.setExpression(parseExpression); + + resultDouble = parser.getValue(); + + result = resultDouble.toString(); + + System.out.println(result); + }catch(Exception ex){ + System.out.println(ex.getMessage()); + } + + return result; + } +} \ No newline at end of file diff --git a/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphActivity.java b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphActivity.java new file mode 100644 index 0000000..178f90b --- /dev/null +++ b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphActivity.java @@ -0,0 +1,127 @@ +package nyc.c4q.ramonaharrison.scientificcalculator; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.view.Display; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.Toast; + +import java.util.HashMap; + + +public class GraphActivity extends ActionBarActivity { + + private GraphView graph; + private EditText inputEquation; + private EditText inputMin; + private EditText inputMax; + private Button graphIt; + private HashMap coordinates; + private String equation; + private Float min; + private Float max; + private static Display display; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + + //TODO save instance state + + super.onCreate(savedInstanceState); + display = getWindowManager().getDefaultDisplay(); + setContentView(R.layout.activity_graph); + + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayShowTitleEnabled(false); + actionBar.show(); + } + + graph = (GraphView) findViewById(R.id.graph); + inputEquation = (EditText) findViewById(R.id.input_equation); + inputMin = (EditText) findViewById(R.id.input_min); + inputMax = (EditText) findViewById(R.id.input_max); + graphIt = (Button) findViewById(R.id.graph_it); + + + graphIt.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + equation = inputEquation.getText().toString(); + min = Float.valueOf(inputMin.getText().toString()); + max = Float.valueOf(inputMax.getText().toString()); + coordinates = new HashMap<>(); + + for (float x = min; x <= max; x++) { + float y = findY(equation, x); + coordinates.put(x, y); + } + + graph.setValues(coordinates, min, max); + graph.drawGraph(); + + } + }); + + } + + public float findY(String equation, float x) { + Float y = Float.valueOf(0); + String xEquation = equation.replaceAll("[x]", "" + x);; + String yString= Calculate.calculate(xEquation, false); + if (isValue(yString)) { + y = Float.valueOf(yString); + } else { + Toast.makeText(getApplicationContext(), "Invalid equation!", Toast.LENGTH_SHORT).show(); + // TODO: get toast out of loop + } + return y; + } + + public boolean isValue(String result) { + for (int i = 0; i < result.length(); i++) { + // checks for only numeric values in result + char c = result.charAt(i); + if ((c < 45 || c > 57) && c != 69) { + return false; + } + } + + return true; + } + + public static int getWidth() { + return display.getWidth(); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_graph, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + switch (item.getItemId()) { + case R.id.action_calculator: + Intent calcIntent = new Intent(this, MainActivity.class); + this.startActivity(calcIntent); + return true; + case R.id.action_graph: + return true; + default: + return super.onOptionsItemSelected(item); + } + } +} diff --git a/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphView.java b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphView.java new file mode 100644 index 0000000..720a9a8 --- /dev/null +++ b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/GraphView.java @@ -0,0 +1,183 @@ +package nyc.c4q.ramonaharrison.scientificcalculator; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import java.util.Collections; +import java.util.HashMap; + +/** + * Created by mona on 5/17/15. + */ +public class GraphView extends View { + + private Path drawPath, textPath, gridPath; + private Paint drawPaint, canvasPaint, gridPaint, canvasGridPaint, textPaint, boxPaint; + private Canvas drawCanvas; + private Bitmap canvasBitmap; + private HashMap coordinates; + private Float min, max; + private int width, height, center; + private float yMax; + private float yMin; + + private float scaleX; + private float scaleY; + + private float centerX; + private float centerY; + + + + public GraphView(Context context, AttributeSet attrs){ + super(context, attrs); + } + + public void setValues(HashMap coord, Float mn, Float mx) { + coordinates = coord; + min = mn; + max = mx; + } + + public void drawGraph() { + invalidate(); + } + + public void setupGrid(Canvas canvas, int width) { + textPaint = new Paint(); + textPaint.setStyle(Paint.Style.FILL_AND_STROKE); + textPaint.setAntiAlias(true); + textPaint.setColor(Color.WHITE); + textPaint.setTextSize(48); + textPath = new Path(); + + boxPaint = new Paint(); + boxPaint.setStyle(Paint.Style.FILL); + boxPaint.setAntiAlias(true); + boxPaint.setAlpha(125); + boxPaint.setColor(Color.CYAN); + + gridPath = new Path(); + gridPaint = new Paint(); + gridPaint.setAlpha(125); + gridPaint.setAntiAlias(true); + gridPaint.setStrokeWidth(5); + gridPaint.setStyle(Paint.Style.STROKE); + gridPaint.setStrokeJoin(Paint.Join.BEVEL); + gridPaint.setStrokeCap(Paint.Cap.SQUARE); + canvasGridPaint = new Paint(Paint.DITHER_FLAG); + canvas.drawBitmap(canvasBitmap, 0, 0, canvasGridPaint); + + gridPaint.setColor(Color.LTGRAY); + gridPath.moveTo(width/2, 0); + gridPath.lineTo(width/2, width); + canvas.drawPath(gridPath, gridPaint); + gridPath.moveTo(0, width/2); + gridPath.lineTo(width, width/2); + canvas.drawPath(gridPath, gridPaint); + } + + + @Override + protected void onSizeChanged(int w, int h, int xw, int xh) { + super.onSizeChanged(w, h, xw, xh); + width = GraphActivity.getWidth() - 100; + height = width; + center = width/2; + canvasBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + drawCanvas = new Canvas(canvasBitmap); + setupGrid(drawCanvas, width); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // check for null inputs + if (min == null) { + min = Float.valueOf(0); + } + if (max == null) { + max = Float.valueOf(0); + } + if (coordinates == null) { + coordinates = new HashMap(); + coordinates.put(min, max); + } + + drawPath = new Path(); + drawPaint = new Paint(); + drawPaint.setAlpha(125); + drawPaint.setAntiAlias(true); + drawPaint.setStrokeWidth(5); + drawPaint.setStyle(Paint.Style.STROKE); + drawPaint.setStrokeJoin(Paint.Join.MITER); + drawPaint.setStrokeCap(Paint.Cap.BUTT); + canvasPaint = new Paint(Paint.DITHER_FLAG); + canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint); + + yMax = Collections.max(coordinates.values()); + yMin = Collections.min(coordinates.values()); + scaleX = width / (max - min); + scaleY = height / (yMax - yMin); + centerX = (max - min)/2; + centerY = (yMax - yMin)/2; + + // draw a graph of the equation + drawPaint.setColor(Color.BLACK); + for (float x = min; x < max; x++) { + float thisX = (centerX + x) * scaleX; + float thisY = height - (centerY + coordinates.get(x)) * scaleY; + float nextX = (centerX + (x + 1)) * scaleX; + float nextY = height - (centerY + coordinates.get(x + 1)) * scaleY; + drawPath.moveTo(thisX, thisY); + drawPath.lineTo(nextX, nextY); + canvas.drawPath(drawPath, drawPaint); + } + + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + float touchX = event.getX(); + float touchY = event.getY(); + float thisx = (touchX - center) / scaleX; + float thisy = 0 - ((touchY - center) / scaleY); + + String pos = "X = " + String.format("%.1f", thisx) + ", Y = " + String.format("%.1f", thisy); + + float textStart = center - (pos.length() * 12); + float textEnd = center + (pos.length() * 12); + textPath.moveTo(textStart, height - 30); + textPath.lineTo(textEnd, height - 30); + + Rect rect = new Rect((int)textStart - 30, height - 100, (int)textEnd + 30, height); + RectF rectF = new RectF(rect); + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + drawCanvas.drawRoundRect(rectF, 15, 15, boxPaint); + drawCanvas.drawTextOnPath(pos, textPath, 0, 0, textPaint); + break; + case MotionEvent.ACTION_MOVE: + drawCanvas.drawRoundRect(rectF, 15, 15, boxPaint); + drawCanvas.drawTextOnPath(pos, textPath, 0, 0, textPaint); + break; + case MotionEvent.ACTION_UP: + break; + default: + return false; + } + invalidate(); + return true; + } +} diff --git a/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/MainActivity.java b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/MainActivity.java new file mode 100644 index 0000000..d5e8dda --- /dev/null +++ b/app/src/main/java/nyc/c4q/ramonaharrison/scientificcalculator/MainActivity.java @@ -0,0 +1,592 @@ +package nyc.c4q.ramonaharrison.scientificcalculator; + +import android.content.Intent; +import android.content.res.Configuration; +import android.graphics.Color; +import android.os.Bundle; +import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarActivity; +import android.text.SpannableString; +import android.text.style.ForegroundColorSpan; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.Random; + + +public class MainActivity extends ActionBarActivity { + private TextView calculatorBar; + private TextView cacheBar; + private Button sin; + private Button cos; + private Button tan; + private Button ln; + private Button log; + private Button sqrt; + private Button ansb; + private Button rad; + private Button deg; + private Button ceac; + private Random random; + + + private boolean isDeg; + private boolean isInv; + private String equation; + private String cache; + private String result; + private String display; + private String ans; + private String closeParens; + private int ce; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + random = new Random(); + calculatorBar = (TextView) findViewById(R.id.calculator_bar); + cacheBar = (TextView) findViewById(R.id.cache); + sin = (Button) findViewById(R.id.sin); + cos = (Button) findViewById(R.id.cos); + tan = (Button) findViewById(R.id.tan); + ln = (Button) findViewById(R.id.ln); + log = (Button) findViewById(R.id.log); + sqrt = (Button) findViewById(R.id.sqrt); + ansb = (Button) findViewById(R.id.ans); + ceac = (Button) findViewById(R.id.ce); + ce = 0; + + if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) + { + // code to do for Portrait Mode + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayShowTitleEnabled(false); + actionBar.show(); + } + } else { + // code to do for Landscape Mode + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.hide(); + } + } + + + + if (savedInstanceState == null) { + setDeg(false); + setInv(false); + setEquation(""); + setCache(""); + setResult(""); + setDisplay("0"); + setAns("0"); + setCloseParens(""); + } else { + setDeg(savedInstanceState.getBoolean("isDeg")); + setInv(savedInstanceState.getBoolean("isInv")); + setEquation(savedInstanceState.getString("equation")); + setCache(savedInstanceState.getString("cache")); + setResult(savedInstanceState.getString("result")); + setDisplay(savedInstanceState.getString("display")); + setAns(savedInstanceState.getString("ans")); + setCloseParens(savedInstanceState.getString("closeParens")); + } + + setRadDegMode(); + displayText(); + cacheBar.setText(cache); + + } + + @Override + public void onSaveInstanceState(Bundle savedInstanceState) { + super.onSaveInstanceState(savedInstanceState); + savedInstanceState.putBoolean("isDeg", isDeg); + savedInstanceState.putBoolean("isInv", isInv); + savedInstanceState.putString("equation", equation); + savedInstanceState.putString("cache", cache); + savedInstanceState.putString("result", result); + savedInstanceState.putString("display", display); + savedInstanceState.putString("ans", ans); + savedInstanceState.putString("closeParens", closeParens); + } + + public void setRadDegMode() { + rad = (Button) findViewById(R.id.rad); + deg = (Button) findViewById(R.id.deg); + if (rad != null && deg != null) { + if (isDeg) { + deg.setBackgroundColor(Color.CYAN); + deg.setTextColor(Color.WHITE); + rad.setBackgroundColor(Color.LTGRAY); + rad.setTextColor(Color.GRAY); + } else { + deg.setBackgroundColor(Color.LTGRAY); + deg.setTextColor(Color.GRAY); + rad.setBackgroundColor(Color.CYAN); + rad.setTextColor(Color.WHITE); + } + } + } + + public void type(View view) { + // input button pressed + Button button = (Button) view; + digitInsertMultiply(); + equation += button.getText().toString(); + setDisplay(pad(equation)); + displayText(); + } + + public void typeSpecial(String special) { + // input button pressed + equation += special; + setDisplay(pad(equation)); + displayText(); + } + + public void ac(View view) { + // AC button pressed + setEquation(""); + setCache(""); + setResult(""); + setDisplay("0"); + setAns("0"); + setCloseParens(""); + + displayText(); + cacheBar.setText(cache); + } + + public void ce(View view) { + ce += 1; + if (ce == 4) { + ceac.setText("AC"); + } + if (equation.length() == 0 || ce == 5) { + setEquation(""); + setCache(""); + setResult(""); + setDisplay("0"); + setAns("0"); + setCloseParens(""); + ceac.setText("CE"); + ce = 0; + } else { + if (equation.charAt(equation.length() - 1) == '(') { + if (closeParens.length() > 0) { + closeParens = closeParens.substring(1); + } + } else if (equation.charAt(equation.length() - 1) == ')') { + closeParens += ')'; + } + setEquation(equation.substring(0, equation.length() - 1)); + setDisplay(pad(equation)); + } + + displayText(); + cacheBar.setText(cache); + } + + public void displayText() { + SpannableString displayText = new SpannableString(display + closeParens); + displayText.setSpan(new ForegroundColorSpan(Color.GRAY), displayText.length() - closeParens.length(), displayText.length(), 0); + calculatorBar.setText(displayText, TextView.BufferType.SPANNABLE); + } + + public String pad(String equation) { + String paddedEquation = ""; + for (int i = 0; i < equation.length(); i++) { + char c = equation.charAt(i); + if (c == '+' || c == '-') { + paddedEquation += " " + c + " "; + } else if (c == '*') { + paddedEquation += " × "; + } else if (c == '/') { + paddedEquation += " ÷ "; + } else { + paddedEquation += "" + c; + } + } + + return paddedEquation; + } + + public void equals(View view) { + + addCloseParens(); + insertZero(); + ce = 0; + cache = display + " = "; + cacheBar.setText(cache); + + if (isDeg) { + System.out.println("Degrees mode"); + String equationToRad = parseTrigonometicExpressions(equation); + System.out.println(equationToRad); + result = Calculate.calculate(equationToRad, isDeg); + } else { + System.out.println("Radians mode"); + result = Calculate.calculate(equation, isDeg); + } + + if (isNumeric(result)) { + ans = result; + display = result; + equation = result; + } else { + display = "Error"; + Toast.makeText(getApplicationContext(), result, Toast.LENGTH_SHORT).show(); + } + + displayText(); + + } + + public static String parseTrigonometicExpressions(String equation) { + String[] trigExpressions = {"sin(", "cos(", "tan("}; + for (int i = 0; i < trigExpressions.length; i++) { + int index = -1; + do { + index = equation.indexOf(trigExpressions[i], index + 1); + if (index != -1) { + String trigValue = equation.substring(index, equation.indexOf(')', index) + 1); + String newValue = trigExpressions[i] + toRadians(extractNumber(trigValue)) + ")"; + equation = equation.replace(trigValue, newValue); + } + } while (index != -1); + } + return equation; + } + + public static double extractNumber(String expression) { + + return Double.valueOf(expression.replaceAll("[^0-9.E-]", "")); + + } + + public static double toRadians(double degrees) { + return degrees * (Math.PI/180); + } + + public boolean isNumeric(String result) { + for (int i = 0; i < result.length(); i++) { + char c = result.charAt(i); + if ((c < 45 || c > 57) && c != 69) { + return false; + } + } + return true; + } + + public void addCloseParens() { + equation += closeParens; + display += closeParens; + closeParens = ""; + } + + + + + // This section contains onClick functions for the calculator buttons + + public void openParen(View view) { + closeParens += ")"; + insertMultiply(); + typeSpecial("("); + } + + public void closeParen(View view) { + if (equation.contains("(")) { + if (closeParens.length() > 0) { + closeParens = closeParens.substring(1); + } + insertZero(); + typeSpecial(")"); + } + } + + public void add(View view) { + insertZero(); + typeSpecial("+"); + } + + public void subtract(View view) { + typeSpecial("-"); + } + + public void divide(View view) { + insertZero(); + typeSpecial("/"); + } + + public void multiply(View view) { + insertZero(); + typeSpecial("*"); + } + + public void point(View view) { + insertZero(); + if (equation.charAt(equation.length() - 1) != '.') { + typeSpecial("."); + } + } + + public void insertMultiply() { + if (0 < equation.length()) { + char last = equation.charAt(equation.length() - 1); + if ((47 < last && last < 58) || last == ')' || last == 's' || last == 'π' || last == 'e' || last == '%') { // assume multiplication if the last item in the equation is a digit, close paren, or 'Ans' + typeSpecial("*"); + } + } + } + + public void digitInsertMultiply() { + if (0 < equation.length()) { + char last = equation.charAt(equation.length() - 1); + if (last == ')' || last == 's' || last == 'π' || last == 'e' || last == '%') { // assume multiplication if the last item in the equation is a digit, close paren, or 'Ans' + typeSpecial("*"); + } + } + } + + public void insertZero() { + if (equation.length() == 0) { + typeSpecial("0"); + } else { + char last = equation.charAt(equation.length() - 1); + if (last == '+' || last == '-' || last == '*' || last == '/' || last == '(') { + typeSpecial("0"); + } + } + } + + public void rad(View view) { + setDeg(false); + setRadDegMode(); + } + + public void deg(View view) { + setDeg(true); + setRadDegMode(); + } + + public void factorial(View view) { + insertZero(); + typeSpecial("!"); + } + + public void inv(View view) { + if (!isInv) { + isInv = true; + sin.setText("asin"); + cos.setText("acos"); + tan.setText("atan"); + ln.setText("eⁿ"); + log.setText("10ⁿ"); + sqrt.setText("x²"); + ansb.setText("Rnd"); + } else { + isInv = false; + sin.setText("sin"); + cos.setText("cos"); + tan.setText("tan"); + ln.setText("ln"); + log.setText("log"); + sqrt.setText("√"); + ansb.setText("Ans"); + } + } + + public void sin(View view) { + closeParens += ")"; + insertMultiply(); + if (!isInv) { + typeSpecial("sin("); + } else { + typeSpecial("asin("); + } + } + + public void ln(View view) { + closeParens += ")"; + insertMultiply(); + if (!isInv) { + typeSpecial("ln("); + } else { + typeSpecial("e^("); + } + } + + public void pi(View view) { + insertMultiply(); + typeSpecial("π"); + } + + public void cos(View view) { + insertMultiply(); + closeParens += ")"; + if (!isInv) { + typeSpecial("cos("); + } else { + typeSpecial("acos("); + } + } + + public void log(View view) { + insertMultiply(); + closeParens += ")"; + if (!isInv) { + typeSpecial("log("); + } else { + typeSpecial("10^("); + } + } + + public void e(View view) { + insertMultiply(); + typeSpecial("e"); + } + + public void tan(View view) { + insertMultiply(); + closeParens += ")"; + if (!isInv) { + typeSpecial("tan("); + } else { + typeSpecial("atan("); + } + } + + public void sqrt(View view) { + if (!isInv) { + insertMultiply(); + closeParens += ")"; + typeSpecial("√("); + } else { + insertZero(); + closeParens += ")"; + typeSpecial("^(2"); + } + } + + public void percent(View view) { + insertZero(); + typeSpecial("%"); + } + + public void ans(View view) { + insertMultiply(); + if (!isInv) { + typeSpecial(ans); + } else { + typeSpecial("" + String.format("%.2f", random.nextFloat() * 100.0f)); + } + } + + public void exp(View view) { + typeSpecial("E"); + } + + public void toThe(View view) { + closeParens += ")"; + insertZero(); + typeSpecial("^("); + } + + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + + // Handle presses on the action bar items + switch (item.getItemId()) { + case R.id.action_calculator: + return true; + case R.id.action_graph: + Intent graphIntent = new Intent(this, GraphActivity.class); + this.startActivity(graphIntent); + return true; + default: + return super.onOptionsItemSelected(item); + } + + } + + public void setDeg(boolean deg) { + this.isDeg = deg; + } + + public String getEquation() { + return equation; + } + + public void setEquation(String equation) { + this.equation = equation; + } + + public String getCache() { + return cache; + } + + public void setCache(String cache) { + this.cache = cache; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public String getDisplay() { + return display; + } + + public void setDisplay(String display) { + this.display = display; + } + + public String getAns() { + return ans; + } + + public void setAns(String ans) { + this.ans = ans; + } + + + public boolean getInv() { + return isInv; + } + + public void setInv(boolean inv) { + this.isInv = inv; + } + + public String getCloseParens() { + return closeParens; + } + + public void setCloseParens(String closeParens) { + this.closeParens = closeParens; + } +} diff --git a/app/src/main/res/drawable/calculator_bar.xml b/app/src/main/res/drawable/calculator_bar.xml new file mode 100644 index 0000000..58d8226 --- /dev/null +++ b/app/src/main/res/drawable/calculator_bar.xml @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml new file mode 100644 index 0000000..e0ba4db --- /dev/null +++ b/app/src/main/res/layout-land/activity_main.xml @@ -0,0 +1,447 @@ + + + + + + + + + + + + + + + +