diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..13038a1 Binary files /dev/null and b/.DS_Store differ diff --git a/LunaCalculator/.gitignore b/LunaCalculator/.gitignore new file mode 100644 index 0000000..9c4de58 --- /dev/null +++ b/LunaCalculator/.gitignore @@ -0,0 +1,7 @@ +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures diff --git a/LunaCalculator/.idea/.name b/LunaCalculator/.idea/.name new file mode 100644 index 0000000..edc2841 --- /dev/null +++ b/LunaCalculator/.idea/.name @@ -0,0 +1 @@ +LunaCalculator \ No newline at end of file diff --git a/LunaCalculator/.idea/compiler.xml b/LunaCalculator/.idea/compiler.xml new file mode 100644 index 0000000..217af47 --- /dev/null +++ b/LunaCalculator/.idea/compiler.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/LunaCalculator/.idea/copyright/profiles_settings.xml b/LunaCalculator/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/LunaCalculator/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/LunaCalculator/.idea/encodings.xml b/LunaCalculator/.idea/encodings.xml new file mode 100644 index 0000000..e206d70 --- /dev/null +++ b/LunaCalculator/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/LunaCalculator/.idea/gradle.xml b/LunaCalculator/.idea/gradle.xml new file mode 100644 index 0000000..736c7b5 --- /dev/null +++ b/LunaCalculator/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/LunaCalculator/.idea/misc.xml b/LunaCalculator/.idea/misc.xml new file mode 100644 index 0000000..17bff38 --- /dev/null +++ b/LunaCalculator/.idea/misc.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/LunaCalculator/.idea/modules.xml b/LunaCalculator/.idea/modules.xml new file mode 100644 index 0000000..888f4d7 --- /dev/null +++ b/LunaCalculator/.idea/modules.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/LunaCalculator/.idea/scopes/scope_settings.xml b/LunaCalculator/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..922003b --- /dev/null +++ b/LunaCalculator/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/LunaCalculator/.idea/vcs.xml b/LunaCalculator/.idea/vcs.xml new file mode 100644 index 0000000..def6a6a --- /dev/null +++ b/LunaCalculator/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/LunaCalculator/LunaCalculator.iml b/LunaCalculator/LunaCalculator.iml new file mode 100644 index 0000000..007f1e4 --- /dev/null +++ b/LunaCalculator/LunaCalculator.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/LunaCalculator/README.md b/LunaCalculator/README.md new file mode 100644 index 0000000..9d1efd2 --- /dev/null +++ b/LunaCalculator/README.md @@ -0,0 +1,121 @@ +# Luna Calculator + +#### 1. Awesome Error Handling + +#### 2. Auto Closing + +#### 3. Try 50 + 30% + +#### 4. + + + + + + + + + + +#### Project Date + +May 5th, 2015 ~ May 21st, 2015 (16 days) + +#### Members + +Luke Lee, Anna Li + +#### Specification + +Basic calculator (Vertical) + +1. +, -, *, / +2. AC, DEL, (), ANS, ^ + +Scientific calculator (Horizental) + +1. sin, cos, tan +2. log, ln +3. + +Additional Features + +1. + +#### Log + +May 11th : EvalEx library applied, error prevention (double operation) + + +#### Check points + +Step 0 : Set up the GitHub working environment (completed) + +Step 1 : create the layout of basic calculator (one activity, vertical, no fragment) + +Step 1.1 : create all the buttons + +Step 1.2 : create the TextView to display the input + +Step 1.3 : if you click button "1", it prints "1" to TextView(input screen). + +Step 1.4 : apply Step 1.3 to button "1", button "2", button "3". + +Step 1.5 : now you see the duplicate codes. find a better way to handle this and apply Step 1.3 to all buttons. + +1. create the layout of basic calculator (one activity, no fragment) +2. implementing the functionality in java. +3. adding scientific calculator +4. error handling +5. adding bonus features +6. user testing +7. + +#### +error handling + +multiple operators prevention : 3++ + +auto closing : sin(30 + +#### Things to do + +saving history + +saving entire history + send email + +radian/degree + +textview overlapping fixing + +graphing + +wolfram + +unit conversion + +font + +setting theme + +funny error messages + +secret music + +store, x y + +#### Things are done + + +% + +factorial 0.45! + +() complete + +negative + +optimize coding + + + diff --git a/LunaCalculator/app/.gitignore b/LunaCalculator/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/LunaCalculator/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/LunaCalculator/app/app.iml b/LunaCalculator/app/app.iml new file mode 100644 index 0000000..914a45b --- /dev/null +++ b/LunaCalculator/app/app.iml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LunaCalculator/app/build.gradle b/LunaCalculator/app/build.gradle new file mode 100644 index 0000000..e3b7d65 --- /dev/null +++ b/LunaCalculator/app/build.gradle @@ -0,0 +1,28 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 22 + buildToolsVersion "22.0.1" + + defaultConfig { + applicationId "lukesterlee.c4q.nyc.lunacalculator" + minSdkVersion 17 + 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 'com.android.support:support-v4:22.1.1' + compile 'com.android.support:recyclerview-v7:22.1.1' + compile 'com.getbase:floatingactionbutton:1.9.0' +} diff --git a/LunaCalculator/app/proguard-rules.pro b/LunaCalculator/app/proguard-rules.pro new file mode 100644 index 0000000..118511c --- /dev/null +++ b/LunaCalculator/app/proguard-rules.pro @@ -0,0 +1,17 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /Users/Willee/Library/Android/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/LunaCalculator/app/src/androidTest/java/lukesterlee/c4q/nyc/lunacalculator/ApplicationTest.java b/LunaCalculator/app/src/androidTest/java/lukesterlee/c4q/nyc/lunacalculator/ApplicationTest.java new file mode 100644 index 0000000..2dadef9 --- /dev/null +++ b/LunaCalculator/app/src/androidTest/java/lukesterlee/c4q/nyc/lunacalculator/ApplicationTest.java @@ -0,0 +1,13 @@ +package lukesterlee.c4q.nyc.lunacalculator; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/LunaCalculator/app/src/main/AndroidManifest.xml b/LunaCalculator/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..5deb3b2 --- /dev/null +++ b/LunaCalculator/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + diff --git a/LunaCalculator/app/src/main/java/lukesterlee/c4q/nyc/lunacalculator/ButtonClickListener.java b/LunaCalculator/app/src/main/java/lukesterlee/c4q/nyc/lunacalculator/ButtonClickListener.java new file mode 100644 index 0000000..c7d3fef --- /dev/null +++ b/LunaCalculator/app/src/main/java/lukesterlee/c4q/nyc/lunacalculator/ButtonClickListener.java @@ -0,0 +1,1074 @@ +package lukesterlee.c4q.nyc.lunacalculator; + +import android.content.Context; +import android.graphics.Color; +import android.media.MediaPlayer; +import android.view.View; +import android.widget.Button; +import android.widget.TextView; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Random; +import java.util.Stack; + +/** + * Created by Luke on 5/11/2015. + */ + +public class ButtonClickListener implements View.OnClickListener { + + + HashMap error; + + Context activity; + + MediaPlayer m1; + MediaPlayer m2; + MediaPlayer m3; + MediaPlayer m4; + + final String errorMessage1 = "seriously, bro?"; + final String errorMessage2 = "come on~"; + final String errorMessage3 = "u r embarrassing urself"; + final String errorMessage4 = "hell no"; + + GraphCallbacks mFragment; + + + + TextView panelHistory; + TextView panel; + + String print; + String ans; + String randomMessage; + String formula; + + lastInputType lastCode; + int open; + int close; + + boolean is2ndOn; + boolean isRadian; + boolean isEvalon; + boolean isEvalAnsOn; + + Button sin; + Button cos; + Button tan; + Button deg; + Button rad; + Button buttonAns; + Button exp; + Button buttonPercentage; + Button equal; + + + Stack expression; + Stack display; + String history; + + public ButtonClickListener(TextView panel, TextView panelHistory, GraphCallbacks mFragment, String ans, Context activity) { + + this.activity = activity; + + expression = new Stack(); + display = new Stack(); + history = ""; + + this.mFragment = mFragment; + + this.panel = panel; + this.panelHistory = panelHistory; + + randomMessage = ""; + formula = ""; + print = ""; + this.ans = ans; + ans = "0"; + open = 0; + close = 0; + + + is2ndOn = false; + isRadian = false; + isEvalon = false; + isEvalAnsOn = false; + + error = new HashMap(); + + } + + @Override + public void onClick(View view) { + Button button = (Button) view; + switch (button.getId()) { + case R.id.button0 : + handleNumbers("0"); + break; + case R.id.button1 : + handleNumbers("1"); + break; + case R.id.button2 : + handleNumbers("2"); + break; + case R.id.button3 : + handleNumbers("3"); + break; + case R.id.button4 : + handleNumbers("4"); + break; + case R.id.button5 : + handleNumbers("5"); + break; + case R.id.button6 : + handleNumbers("6"); + break; + case R.id.button7 : + handleNumbers("7"); + break; + case R.id.button8 : + handleNumbers("8"); + break; + case R.id.button9 : + handleNumbers("9"); + break; + + case R.id.buttonAdd : + handleOperators("+"); + break; + case R.id.buttonMinus : + handleOperators("-"); + break; + case R.id.buttonMultiple : + handleOperators("*"); + break; + case R.id.buttonDivided : + handleOperators("/"); + break; + + case R.id.buttonDot : + handleDot(); + break; + + case R.id.buttonNega : + handleNegative(); + break; + case R.id.buttonParenthesis : + handleParenthesis(); + break; + + case R.id.buttonPercentage : + if (isEvalon) { + handleEval(); + + + } else { + handlePercentage(); + } + + break; + + + case R.id.buttonFactorial : + handleFactorial(); + break; + + case R.id.buttonSin : + if (is2ndOn) { + if (isRadian) { + handleFunction("asinrad(", "asin(", true); + + } else { + handleFunction("asin(", "asin(", true); + } + } + else { + if (isRadian) { + handleFunction("sinrad(", "sin(", true); + + } else { + handleFunction("sin(", "sin(", true); + } + } + break; + case R.id.buttonCos : + if (is2ndOn) { + if (isRadian) { + handleFunction("acosrad(", "acos(", true); + + } else { + handleFunction("acos(", "acos(", true); + } + } + else { + if (isRadian) { + handleFunction("cosrad(", "cos(", true); + + } else { + handleFunction("cos(", "cos(", true); + } + } + break; + case R.id.buttonTan : + if (is2ndOn) { + if (isRadian) { + handleFunction("atanrad(", "atan(", true); + + } else { + handleFunction("atan(", "atan(", true); + } + } + else { + if (isRadian) { + handleFunction("tanrad(", "tan(", true); + + } else { + handleFunction("tan(", "tan(", true); + } + } + break; + case R.id.buttonLn : + handleFunction("log(", "ln(", true); + break; + case R.id.buttonLog : + handleFunction("log10(", "Log(", true); + break; + + case R.id.buttonPi : + handleFunction("PI", "π", false); + break; + case R.id.buttonE : + handleFunction("e", "e", false); + break; + + case R.id.button2nd : + if (is2ndOn) { + is2ndOn = false; + sin.setText("sin"); + cos.setText("cos"); + tan.setText("tan"); + sin.setBackgroundResource(R.drawable.button_lightgray); + cos.setBackgroundResource(R.drawable.button_lightgray); + tan.setBackgroundResource(R.drawable.button_lightgray); + sin.setTextColor(Color.parseColor("#000000")); + cos.setTextColor(Color.parseColor("#000000")); + tan.setTextColor(Color.parseColor("#000000")); + + buttonAns.setText("Ans"); + buttonAns.setBackgroundResource(R.drawable.button_lightgray); + buttonAns.setTextColor(Color.parseColor("#000000")); + + + + + } else { + is2ndOn = true; + sin.setText("asin"); + cos.setText("acos"); + tan.setText("atan"); + sin.setBackgroundResource(R.drawable.button_green2); + cos.setBackgroundResource(R.drawable.button_green2); + tan.setBackgroundResource(R.drawable.button_green2); + sin.setTextColor(Color.parseColor("#FFFFFF")); + cos.setTextColor(Color.parseColor("#FFFFFF")); + tan.setTextColor(Color.parseColor("#FFFFFF")); + buttonAns.setText("x"); + buttonAns.setBackgroundResource(R.drawable.button_green2); + buttonAns.setTextColor(Color.parseColor("#FFFFFF")); + + + } + break; + + case R.id.buttonDegree : + isRadian = false; + deg.setBackgroundResource(R.drawable.button_green2); + deg.setTextColor(Color.parseColor("#FFFFFF")); + rad.setBackgroundResource(R.drawable.button_gray); + rad.setTextColor(Color.parseColor("#D7D7D7")); + break; + case R.id.buttonRadian : + isRadian = true; + rad.setBackgroundResource(R.drawable.button_green2); + rad.setTextColor(Color.parseColor("#FFFFFF")); + deg.setBackgroundResource(R.drawable.button_gray); + deg.setTextColor(Color.parseColor("#D7D7D7")); + break; + + case R.id.buttonAns : + if (is2ndOn) { + handleFunction("x", "x", false); + buttonPercentage.setBackgroundResource(R.drawable.button_red); + buttonPercentage.setTextColor(Color.parseColor("#FFFFFF")); + buttonPercentage.setText("EVAL"); + isEvalon = true; + equal.setBackgroundResource(R.drawable.button_red); + equal.setText("DRAW"); + + } else { + handleAns(); + } + + break; + + case R.id.buttonDEL : + handleDel(); + break; + case R.id.buttonAC : + handleAC(); + break; + + case R.id.buttonRoot : + handleFunction("sqrt(", "√(", true); + break; + + + case R.id.buttonExp : + + handleExp(); + break; + + case R.id.buttonEqual : + + try { + handleEqual(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + break; + + } + print = stackToString(display); + panel.setText(print); + } + + private enum lastInputType { + EMPTY, + DIGIT, + DOT, + OPERATOR, + LPARENT, + RPARENT, + CONSTANT_UNARY, + EXP, + ERROR + } + + public String stackToString(Stack stack) { + String print = ""; + Object[] objects = stack.toArray(); + for (Object object : objects) { + print += object.toString(); + } + return print; + } + + public lastInputType lastDetection() { + if (display.empty()) { + return lastInputType.EMPTY; + } + String last = display.peek(); + if (Character.isDigit(last.charAt(0))) { + return lastInputType.DIGIT; + } else if (last.length() > 1 && last.startsWith("-")) { + return lastInputType.DIGIT; + } else if (last.equals(".")) { + return lastInputType.DOT; + } else if (last.equals("+") || last.equals("-") || last.equals("*") || last.equals("/")) { + return lastInputType.OPERATOR; + } else if (last.endsWith("(")) { + return lastInputType.LPARENT; + } else if (last.equals(")")) { + return lastInputType.RPARENT; + } else if (last.equals("e") || last.equals("π") || last.equals("!") || last.equals("%") || last.equals("x")) { + return lastInputType.CONSTANT_UNARY; + } else if (last.equals("^")) { + return lastInputType.EXP; + } else if (last.equals(randomMessage)) { + display.clear(); + return lastInputType.EMPTY; + } + return lastInputType.ERROR; + } + + public void add(String input) { + expression.add(input); + display.add(input); + } + + public void add(String first, String second) { + add(first); + add(second); + } + + public void add(String first, String second, String third) { + add(first, second); + add(third); + } + + public void delete() { + expression.pop(); + display.pop(); + } + + public void concatenate(String number) { + String newNumber = expression.pop() + number; + expression.push(newNumber); + display.pop(); + display.push(newNumber); + } + + public void handleNumbers(String number) { + lastCode = lastDetection(); + switch (lastCode) { + case DIGIT: + if (!expression.empty()) + concatenate(number); + else { + display.clear(); + add(number); + } + break; + case RPARENT: case CONSTANT_UNARY: + add("*", number); + break; + default: + add(number); + } + } + + public void handleOperators(String operator) { + lastCode = lastDetection(); + switch (lastCode) { + case EMPTY: + expression.push(ans); + display.push("Ans"); + add(operator); + break; + case DIGIT: + if (expression.empty()) + expression.push(display.peek()); + add(operator); + break; + case OPERATOR: + delete(); + add(operator); + break; + case RPARENT: case CONSTANT_UNARY: + add(operator); + break; + } + } + + public void handleAC() { + expression.clear(); + display.clear(); + print = ""; + panel.setText(""); + ans = ""; + panelHistory.setText(""); + open = 0; + close = 0; + + + if (buttonPercentage != null) { + buttonPercentage.setBackgroundResource(R.drawable.button_lightgray); + buttonPercentage.setTextColor(Color.parseColor("#000000")); + buttonPercentage.setText("%"); + equal.setBackgroundResource(R.drawable.button_green2); + equal.setText("="); + } + + + isEvalon = false; + isEvalAnsOn = false; + } + + public void handleDel() { + lastCode = lastDetection(); + switch (lastCode) { + case DIGIT: + if (expression.empty()) + expression.push(display.peek()); + String delNumber = expression.pop(); + display.pop(); + if(delNumber.length() != 1) { + delNumber = delNumber.substring(0, delNumber.length()-1); + expression.push(delNumber); + display.push(delNumber); + } + break; + case DOT: case OPERATOR: case CONSTANT_UNARY: case EXP: + delete(); + break; + case LPARENT: + delete(); + open--; + break; + case RPARENT: + delete(); + close--; + break; + } + } + + public void handleDot() { + lastCode = lastDetection(); + switch (lastCode) { + case DIGIT: + if (expression.empty()) { + display.pop(); + add("0", "."); + } else + add("."); + break; + case OPERATOR: case LPARENT: case EMPTY: case EXP: + add("0", "."); + break; + case RPARENT: case CONSTANT_UNARY: + add("*", "0", "."); + break; + } + } + + public void handleFunction(String symbol, String symbolDisplay, boolean isParenthesis) { + lastCode = lastDetection(); + switch (lastCode) { + case DIGIT: + if (expression.empty()) { + expression.push(display.pop()); + } + expression.push("*"); + display.push("Ans"); + display.push("*"); + expression.push(symbol); + display.push(symbolDisplay); + if (isParenthesis) + open++; + break; + case OPERATOR: case LPARENT: case EXP: case EMPTY: + expression.push(symbol); + display.push(symbolDisplay); + if (isParenthesis) + open++; + break; + case RPARENT: case CONSTANT_UNARY: + add("*"); + expression.push(symbol); + display.push(symbolDisplay); + if (isParenthesis) + open++; + break; + } + } + + public void handleExp() { + lastCode = lastDetection(); + switch (lastCode) { + case EMPTY: + expression.push(ans); + display.push("Ans"); + add("^"); + break; + case DIGIT: + if (expression.empty()) + expression.push(display.peek()); + add("^"); + break; + case RPARENT: case CONSTANT_UNARY: + add("^"); + break; + } + } + + public void handlePercentage() { + + String last; + String secondToLast; + String thirdToLast; + + lastCode = lastDetection(); + switch (lastCode) { + case EMPTY: + expression.push("0"); + display.push("0%"); + break; + case DIGIT: + if (expression.empty()) { + expression.push(display.peek()); + expression.push("*"); + expression.push("0"); + expression.push("."); + expression.push("01"); + } + else if (expression.size() >= 3) { + last = expression.pop(); + secondToLast = expression.pop(); + thirdToLast = expression.pop(); + + if (Character.isDigit(thirdToLast.charAt(0)) && secondToLast.equals("+")) { + expression.push(thirdToLast + "*(1+" + last + "*0.01)"); + + } else if (Character.isDigit(thirdToLast.charAt(0)) && secondToLast.equals("-")) { + expression.push(thirdToLast + "*(1-" + last + "*0.01)"); + } else if (Character.isDigit(thirdToLast.charAt(0)) && secondToLast.equals("*")) { + expression.push(thirdToLast + "*" + last + "*0.01"); + } else if (Character.isDigit(thirdToLast.charAt(0)) && secondToLast.equals("/")) { + expression.push(thirdToLast + "/" + "(" + last + "*0.01)"); + } + } else { + expression.push("*"); + expression.push("0"); + expression.push("."); + expression.push("01"); + + } + display.push("%"); + + break; + case RPARENT: case CONSTANT_UNARY: + expression.push("*"); + expression.push("0"); + expression.push("."); + expression.push("01"); + display.push("%"); + break; + } + } + + public void handleParenthesis() { + lastCode = lastDetection(); + switch (lastCode) { + case DIGIT: + if (expression.empty()) { + display.clear(); + add("("); + open++; + } else if (open > close) { + add(")"); + close++; + } else { + add("*", "("); + open++; + } + break; + case OPERATOR: case LPARENT: case EMPTY: + add("("); + open++; + break; + case RPARENT: + if (open == close) { + add("*", "("); + open++; + } else if (open > close) { + add(")"); + close++; + } + break; + case CONSTANT_UNARY: + if (open > close) + add(")"); + else + add("*", "("); + close++; + break; + case EXP: + add("("); + open++; + break; + } + } + + public void insertBeforeLast() { + String last = expression.pop(); + display.pop(); + add("-", last); + } + + public void insertPlusBeforeLast() { + String last = expression.pop(); + display.pop(); + add("+", last); + } + + + public void insertBeforeThirdToLast() { + String last = expression.pop(); + String secondToLast = expression.pop(); + String thirdToLast = expression.pop(); + display.pop(); + display.pop(); + display.pop(); + add("-"); + add(thirdToLast, secondToLast, last); + } + + public void replaceBeforeLast() { + String last = expression.pop(); + String secondToLast = expression.pop(); + display.pop(); + display.pop(); + if (secondToLast.equals("+")) { + add("-", last); + } else if (secondToLast.equals("-")) { + add("+", last); + } + } + + public void replaceBeforeThirdToLast() { + String last = expression.pop(); + String secondToLast = expression.pop(); + String thirdToLast = expression.pop(); + String fourthToLast = expression.pop(); + display.pop(); + display.pop(); + display.pop(); + display.pop(); + if (fourthToLast.equals("+")) { + add("-"); + } else if (fourthToLast.equals("-")) { + add("+"); + } + add(thirdToLast, secondToLast, last); + } + + public void handleNegative() { + String last; + String secondLast; + String thirdLast; + lastCode = lastDetection(); + + switch (lastCode) { + case DIGIT: + if (expression.empty()) { + expression.push(display.peek()); + } + int size = expression.size(); + switch (size) { + + case 1 : + if (expression.peek().contains("-")) { + last = expression.pop().substring(1); + expression.push(last); + display.pop(); + display.push(last); + insertPlusBeforeLast(); + } else { + insertBeforeLast(); + } + + break; + case 2 : + last = expression.pop(); + secondLast = expression.peek(); + expression.push(secondLast); + expression.push(last); + if (secondLast.equals("-")) { + replaceBeforeLast(); + } else if (secondLast.equals("(")) { + insertBeforeLast(); + } + break; + case 3: + last = expression.pop(); + secondLast = expression.pop(); + expression.push(secondLast); + expression.push(last); + if (secondLast.equals(".")) { + insertBeforeThirdToLast(); + } else { + replaceBeforeLast(); + } + break; + default: + last = expression.pop(); + secondLast = expression.pop(); + expression.push(secondLast); + expression.push(last); + if (secondLast.equals(".")) { + replaceBeforeThirdToLast(); + } else { + replaceBeforeLast(); + } + + } + + break; + case DOT: + last = expression.pop(); + secondLast = expression.pop(); + display.pop(); + display.pop(); + add("-", secondLast, last); + break; + case OPERATOR: case EXP: + add("(", "-"); + open++; + break; + case LPARENT: case EMPTY: + add("-"); + break; + case RPARENT: case CONSTANT_UNARY: + add("*", "(", "-"); + open++; + break; + } + } + + public long factorial(long number) { + if (number == 1 || number == 0) + return 1; + return factorial(number-1) * number; + } + + public void handleFactorial() { + String last; + String secondToLast; + lastCode = lastDetection(); + switch (lastCode) { + case EMPTY: +// expression.push(Long.toString(factorial(Long.parseLong(ans)))); +// display.push("Ans"); +// display.push("!"); + break; + case DIGIT: + // handle the case of 0.45 + if (expression.empty()) { + expression.push(display.peek()); + } + int size = expression.size(); + if (size == 1) { + last = expression.pop(); + display.pop(); + expression.push(Long.toString(factorial(Long.parseLong(last)))); + display.push(last + "!"); + } else { + last = expression.pop(); + secondToLast = expression.pop(); + if (secondToLast.equals(".")) { + expression.push(secondToLast); + expression.push(last); + } else { + expression.push(secondToLast); + display.pop(); + expression.push(Long.toString(factorial(Long.parseLong(last)))); + display.push(last + "!"); + } + } + break; + case RPARENT: + break; + case CONSTANT_UNARY: + break; + } + } + + public void handleAns() { + lastCode = lastDetection(); + switch (lastCode) { + case DIGIT: + if (expression.empty()) + expression.push(ans); + add("*"); + expression.push(ans); + display.push("Ans"); + break; + case RPARENT: case CONSTANT_UNARY: + add("*"); + expression.push(ans); + display.push("Ans"); + break; + default: + expression.push(ans); + display.push("Ans"); + } + } + + public void handleEqual() throws FileNotFoundException { + + lastCode = lastDetection(); + + // it the user didn't put anything, or end with operators, equal button is disabled. + if (!expression.empty() && lastCode != lastInputType.OPERATOR) { + + if (isEvalAnsOn) { + + getEvalAnswer(formula, expression.pop()); + } else { + // test if the user misses parenthesis. + while (open > close) { + expression.push(")"); + display.push(")"); + close++; + } + // if the test is passed + formula = stackToString(expression); + if (formula.contains("x")) { + handleGraph(); + } else { + submit(formula); + } + + + + } + + + + } + + } + + public void getEvalAnswer(String input, String x) { + Expression express = new Expression(input); + try { + BigDecimal answer = express.with("x", x).eval(); + + String result = answer.toPlainString(); + ans = result; + history = input + " = " + result; + display.clear(); + expression.clear(); + open = 0; + close = 0; + display.push(ans); + isEvalon = false; + isEvalAnsOn = false; + if (panelHistory != null) { + panelHistory.setText(history); + } + } catch(Exception e) { + expression.clear(); + display.clear(); + randomMessage = "can't evaluate"; + display.push(randomMessage); + } + } + + public void submit(String inputExpression) throws FileNotFoundException { + Expression express = new Expression(inputExpression); + try { + BigDecimal answer = express.eval(); + + // this is for sin(0), sin(180), cos(90), tan(180) because java Math.sin sucks. +// BigDecimal sinCheck = new Expression(inputExpression + "< 0.00000000000001").eval(); +// if (sinCheck.toPlainString().equals("1")) { +// answer = new BigDecimal("0"); +// } + if (answer.toPlainString().startsWith("0.00000000000000")) { + answer = new BigDecimal("0"); + } + + ans = answer.toPlainString(); + history = stackToString(display) + " = " + ans; + display.clear(); + expression.clear(); + open = 0; + close = 0; + display.push(ans); + if (panelHistory != null) { + panelHistory.setText(history); + } + } catch(Exception e) { + handleAC(); + // print error here + randomErrorPlay(); + + + } + } + + + public void randomErrorPlay() { + ArrayList lines = new ArrayList(); + lines.add(errorMessage1); + lines.add(errorMessage2); + lines.add(errorMessage3); + lines.add(errorMessage4); + Random random = new Random(); + int index = random.nextInt(lines.size()); + + randomMessage = lines.get(index); + + error = new HashMap(); + + m1 = MediaPlayer.create(activity, R.raw.seriously); + m2 = MediaPlayer.create(activity, R.raw.come_on); + m3 = MediaPlayer.create(activity, R.raw.embarrassing); + m4 = MediaPlayer.create(activity, R.raw.hell_no); + + error.put(errorMessage1, m1); + error.put(errorMessage2, m2); + error.put(errorMessage3, m3); + error.put(errorMessage4, m4); + + display.push(randomMessage); + + MediaPlayer current = null; + current = error.get(randomMessage); + current.start(); + + } + + public String randomErrorMessage() throws FileNotFoundException { + ArrayList lines = new ArrayList(); + lines.add(errorMessage1); + lines.add(errorMessage2); + lines.add(errorMessage3); + lines.add(errorMessage4); + Random random = new Random(); + int index = random.nextInt(lines.size()); + return lines.get(index); + } + + public void handleEval() { + + buttonPercentage.setBackgroundResource(R.drawable.button_lightgray); + buttonPercentage.setTextColor(Color.parseColor("#000000")); + buttonPercentage.setText("%"); + + equal.setBackgroundResource(R.drawable.button_green2); + equal.setText("="); + + isEvalAnsOn = true; + isEvalon = false; + + panelHistory.setText("Enter x's value"); + display.clear(); + formula = stackToString(expression); + expression.clear(); + open = 0; + close = 0; + + } + + public void handleGraph() { + + expression.clear(); + display.clear(); + open = 0; + close = 0; + print = formula; + if (panelHistory != null) { + panelHistory.setText("y = " + print); + } + mFragment.graphButtonClicked(formula,10, 30); + } + + public void set2nd(Button sin, Button cos, Button tan, Button deg, Button rad, Button buttonAns, Button exp, Button buttonPercentage, Button equal) { + this.sin = sin; + this.cos = cos; + this.tan = tan; + this.deg = deg; + this.rad = rad; + this.buttonAns = buttonAns; + this.exp = exp; + this.buttonPercentage = buttonPercentage; + this.equal = equal; + } +} diff --git a/LunaCalculator/app/src/main/java/lukesterlee/c4q/nyc/lunacalculator/CalculatorFragment.java b/LunaCalculator/app/src/main/java/lukesterlee/c4q/nyc/lunacalculator/CalculatorFragment.java new file mode 100644 index 0000000..0908d3c --- /dev/null +++ b/LunaCalculator/app/src/main/java/lukesterlee/c4q/nyc/lunacalculator/CalculatorFragment.java @@ -0,0 +1,151 @@ +package lukesterlee.c4q.nyc.lunacalculator; + +import android.app.Activity; +import android.app.Fragment; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import java.util.ArrayList; + + +/** + * Created by Luke on 5/19/2015. + */ +public class CalculatorFragment extends Fragment implements GraphCallbacks{ + + + + TextView history; + TextView panel; + ArrayList