Conversation
| calculator.pressNumericKey(NumericKeys.ONE); | ||
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("2.718281828459045"); |
There was a problem hiding this comment.
we should probably round these in the model, maybe 2-3 decimal points?
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) |
There was a problem hiding this comment.
should we implement these before merging? otherwise maybe remove the TODOs
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
it seems like we only have one case where only one operand is needed (EXP). maybe we just use an "else" here?
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
I don't like leaving assertions in code outside of tests - if we need to throw a meaningful error here, let's do that.
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this._buffer = this.popNumber().toString(); | ||
| if ( | ||
| this._operatorStack[this._operatorStack.length - 1] === |
There was a problem hiding this comment.
repeated conditional from above, maybe refactor out?
| MINUS = "-", | ||
| MULT = "*", | ||
| DIV = "/", | ||
| EXP = "exp", |
There was a problem hiding this comment.
is there a different symbol we can use to keep pattern? (1 char)
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
What if there were more than 2 numbers?
| this._operatorStack[this._operatorStack.length - 1] === OperatorKeys.EXP | ||
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); |
| case ActionKeys.EQUALS: { | ||
| this.pushNumber(); | ||
| this.pushBuffer(); | ||
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { |
There was a problem hiding this comment.
Doesn't seem to account for large number of operands in a larger expression, including several exps
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
| calculator.pressNumericKey(NumericKeys.ONE); | ||
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("2.718281828459045"); |
There was a problem hiding this comment.
do we want to use .toEqual(string) when checking the value of floats? Could we use .toBeCloseTo instead?
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| if ( | ||
| this._operatorStack.length > 0 && |
There was a problem hiding this comment.
Lack of comments on the functionality of the new feature.
| MINUS = "-", | ||
| MULT = "*", | ||
| DIV = "/", | ||
| EXP = "exp", |
There was a problem hiding this comment.
No need for the last comment, will give an error
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Should test with all operators, missing "-" and "/"
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
Can be a double = operator instead
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
What is the point of this comment?
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
Don't need to be asserting this value, can check for it previously to maintain good style
| calculator.pressNumericKey(NumericKeys.ONE); | ||
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("2.718281828459045"); |
There was a problem hiding this comment.
All of the tests should round to a specific value, these toEqual functions can have roundoff error
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
Leave TODOs out of the production branch
| } | ||
|
|
||
| private pushNumber(): void { | ||
| private pushBuffer(): void { |
There was a problem hiding this comment.
If the pushNumber would be changed to a buffer pusher, change the functionality to actually get each value instead of keeping just the number
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
There was a problem hiding this comment.
Don't need to log "doing exp" or "...it's" for every calculation that is made
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Add additional tests for more edge cases, such as exp(0) to ensure functionality is working correctly
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| if ( | ||
| this._operatorStack.length > 0 && |
There was a problem hiding this comment.
won't need to check that the length > 0 if the value at the length -1 is EXP
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
There was a problem hiding this comment.
can you remove the console.log() statements on line 48 and 50
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here | ||
| this.setState(State.ENTERING_SECOND_OPERAND); |
There was a problem hiding this comment.
Is it possible to remove this from this pull request.
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
can you remove this check from this pr.
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) |
There was a problem hiding this comment.
can you include these within the pull request
kelvinx24
left a comment
There was a problem hiding this comment.
Some implementation and architectural issues are present. Architectural issues extend further than this PR itself. The code needs to be finished, cleaned up, and all test cases must be written out. The existing tests look good.
There was a problem hiding this comment.
The user may want to execute operations within the exp function i.e. exp(2 * 2). Therefore, we should aim to support this action by requiring the user to enter parentheses to start and end the function.
There was a problem hiding this comment.
Write out all tests and run them before attempting to push please. We need to make sure all cases are covered and problems are detected early. The tests you have in TODO looks great for covering those other cases.
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
Unsure what this test will / suppose to be. Please let me know, or implement it like you have for some of the other tests!
| } | ||
|
|
||
| private pushNumber(): void { | ||
| private pushBuffer(): void { |
There was a problem hiding this comment.
Method name change here is unnecessary I think. The method pushes a number to the field _numberStack, so the original name, "pushNumber", makes more sense. Nothing is being pushed to buffer.
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| const result: number = Math.exp(num); |
There was a problem hiding this comment.
Not necessarily broken; however, the evaluation should be done when the equal sign is inputted. The implementation for evaluating this new function can be added to the compute() method.
| this.pushBuffer(); | ||
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this._buffer = this.popNumber().toString(); | ||
| if ( |
There was a problem hiding this comment.
It is not necessarily to detect for only the exp function. This can cause issues later if more functions need to be implemented besides exp. I think reverting is the way to go here.
| public pressOperatorKey(key: OperatorKeys): void { | ||
| this.pushNumber(); | ||
| this.pushBuffer(); | ||
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { |
There was a problem hiding this comment.
Using an enumeration to represent operands / operations limit the number of operations possible for the user. Th e user will not be able to input an expression with more than 3 operations with the current implementation. I recommend removing state. This issue extends further than this PR itself.
| console.log("...it's", result); | ||
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { |
There was a problem hiding this comment.
As noted below, that means this if statement will also not be necessary
There was a problem hiding this comment.
Please include more comments in the code regarding the new process. I suggest including comments for each state in the pressOperatorKey() method. Additionally, please do not attempt to push unfinished code, and comment out or delete console logs.
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
yumio7
left a comment
There was a problem hiding this comment.
please finish those tests you put under TODO and ensure there isnt a fatal flaw in exponent handling, otherwise lgtm
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
| // I do not understand what is going on here | ||
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { |
There was a problem hiding this comment.
couldn't this be an else instead of an else if?
| @@ -23,7 +23,7 @@ export class CalculatorModel implements ICalculatorModel { | |||
| this._buffer += key; | |||
There was a problem hiding this comment.
This code is very difficult to read because of the way the indentation and the brackets are done.
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Some aspects of these tests could be separated so that there is less repetition.
stephanie-xu
left a comment
There was a problem hiding this comment.
Overall functionality looks ok but needs some more tests and resolving the comment stating you were confused
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
what does the last to-do mean? Are you testing for exponent functionality or addition?
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
the code here is saying: if the first operator isn't the exp key, then skip to the second operator
is this your intended functionality, if you didn't understand what was happening?
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
Do not push comments of this variety, instead ask a programming lead.
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
||
| it("should display e**1 with `exp(1)`", (): void => { |
There was a problem hiding this comment.
Calculator does not support "e", either implement e as a constant value or change your tests.
| expect(displayValue).toEqual("2.718281828459045"); | ||
| }); | ||
|
|
||
| it("should display e**4 with `exp(4)`", (): void => { |
There was a problem hiding this comment.
It might be helpful to leave comments above tests describing their purpose.
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
In the future, add comments if this variety in a code review or pull request instead of in the code itself.
kyle12803
left a comment
There was a problem hiding this comment.
Please provide a more descriptive summary of your changes.
| // I do not understand what is going on here | ||
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { |
There was a problem hiding this comment.
Consider adding a comment for why we do not check for the OperatorKeys.EXP operator here.
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); | ||
| const result: number = Math.exp(num); | ||
| console.log("...it's", result); |
There was a problem hiding this comment.
This logic could potentially be abstracted into its own method for computing the logic as it is the same as lines 119 to 121.
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
If this is not supported then we should handle it gracefully in the logic and add test cases to ensure it is handled.
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
reginarabkina
left a comment
There was a problem hiding this comment.
Leaving general comments regarding code format
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
It would be helpful to have some more insight on what you are testing by leaving some comments before the test. For example, you can say that you are specifically testing for e^1. At first glance, it is easy to miss the "e", so some may assume you are just testing 1 as the exponent!
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
There was a problem hiding this comment.
For clarity purposes, when a user will review the logs, it would be helpful to see 'exp' written out in its entirety (e.g., 'exponent').
| this.pushBuffer(); | ||
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| if ( |
There was a problem hiding this comment.
It would be helpful to distinguish the different cases this function is cycling through, by using comments denoting what the if-statement is checking.
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) |
There was a problem hiding this comment.
Do you expect other people to do your job for you?
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this._buffer = this.popNumber().toString(); | ||
| if ( | ||
| this._operatorStack[this._operatorStack.length - 1] === |
There was a problem hiding this comment.
This code is so hard to read. Have I not asked you enough to cleanup your code?
| MINUS = "-", | ||
| MULT = "*", | ||
| DIV = "/", | ||
| EXP = "exp", |
There was a problem hiding this comment.
It makes more sense for the exponential operator key to be "^".
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Include a comment explaining the mathematical expectation (e^1 ≈ 2.718) to improve readability for future readers.
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("2.718281828459045"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
brief comment explaining the expected result (e^4 ≈ 54.598) would improve clarity.
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("54.598150033144236"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Ensure that the calculator is handling operator precedence correctly, especially when mixing operations like exp and +.
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
Make sure to cover edge cases like exp(-1) or exp(0) in future tests.
|
|
||
| public pressOperatorKey(key: OperatorKeys): void { | ||
| this.pushNumber(); | ||
| this.pushBuffer(); |
There was a problem hiding this comment.
Consider adding validation for parseFloat to handle potential edge cases like non-numeric values or multiple decimals.
MichaelGadhia
left a comment
There was a problem hiding this comment.
Great work and fine tuning should make this very useful!
| } | ||
|
|
||
| private pushNumber(): void { | ||
| private pushBuffer(): void { |
There was a problem hiding this comment.
This is a better name that clarifies the use of the function! Could popNumber() be changed to popBuffer() to match?
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| if ( | ||
| this._operatorStack.length > 0 && | ||
| this._operatorStack[this._operatorStack.length - 1] === OperatorKeys.EXP |
There was a problem hiding this comment.
The evaluation might want to wait until EQUALS is pressed, rather than taking the value immediately if the previous key was EXP.
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here | ||
| this.setState(State.ENTERING_SECOND_OPERAND); |
There was a problem hiding this comment.
The exp function takes one operand and should evaluate it after EQUALS is pressed, so these two states for operands might not work here. After pressing EXP the code should then accept one operand entered after it to then evaluate.
| this.pushBuffer(); | ||
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this._buffer = this.popNumber().toString(); | ||
| if ( |
There was a problem hiding this comment.
This can be factored out with the use of the same code above starting on line 42, or the previous usage above can be changed.
ivng8
left a comment
There was a problem hiding this comment.
Finishing test cases and adding some seemingly redundant tests cases for subtract and minus for more code coverage.
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) |
There was a problem hiding this comment.
These test cases should be implemented asap to have more code coverage
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? | ||
| }); |
There was a problem hiding this comment.
Testing minus and division although redundant might be necessary for full code coverage because the implementation utilizes a switch case
beartackler
left a comment
There was a problem hiding this comment.
Also, consider a more detail description 💯
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? | ||
| }); |
There was a problem hiding this comment.
Current tests LGTM! I agree that testing negative exponents and exponents of exponents functionality could be a good idea.
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here | ||
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| } |
There was a problem hiding this comment.
A bit of confusion here with the state management. Consider refactoring to handle calculator inputs clearer. Consider similarities with case ActionKeys.EQUALS: line 113 - 125. Maybe abstract this out?
| } else { | ||
| this._buffer = this.popNumber().toString(); | ||
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { |
There was a problem hiding this comment.
This seems a bit akward - you pop the operator stack if EXP is found, compute the exponentiation, and replace the number stack with the result. Consider combining two numbers on the stack instead and handling like other operator keys
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) |
There was a problem hiding this comment.
did you mean to write tests for these TODO's?
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); | ||
| const result: number = Math.exp(num); | ||
| console.log("...it's", result); |
There was a problem hiding this comment.
consider abstracting this to a helper function that returns result using the operatorStack and numberStack, logic is the same as lines 119-121
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
| } | ||
|
|
||
| private pushNumber(): void { | ||
| private pushBuffer(): void { |
There was a problem hiding this comment.
careful renaming functions, doubled checked and seems like all references are renamed 👍
gartastrophe
left a comment
There was a problem hiding this comment.
review for implementation of e**
| MINUS = "-", | ||
| MULT = "*", | ||
| DIV = "/", | ||
| EXP = "exp", |
There was a problem hiding this comment.
could also make this a symbol, such as "**" instead of text to be consistent.
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
could also add tests for division and subtraction. they should behave similar to multiplication and division but worth checking.
| this._operatorStack[this._operatorStack.length - 1] === OperatorKeys.EXP | ||
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); |
There was a problem hiding this comment.
if we're changing pushNumber to pushBuffer, does popNumber also have to change?
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
moving on if something goes wrong? theoretically this should not occur since this function only happens when the key is pressed but this at least provides a way to move past an error?
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
Might be better to have a catch exception here so we don't crash and see a weird error message.
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this._buffer = this.popNumber().toString(); | ||
| if ( | ||
| this._operatorStack[this._operatorStack.length - 1] === |
There was a problem hiding this comment.
Might want to leave this on the same line to avoid confusion.
| this.pushNumber(); | ||
| this.pushBuffer(); | ||
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this.setState(State.ENTERING_SECOND_OPERAND); |
There was a problem hiding this comment.
Might want to connect this into one "if" statement so we don't have nested "if" to avoid confusion
zachmarino234
left a comment
There was a problem hiding this comment.
Overall this looks solid! Left some comments and some notes to remove stuff. Can we schedule a time to discuss the pressOperatorKey function?
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
||
| it("should display e**1 with `exp(1)`", (): void => { |
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
Delete before merging (also real)
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
Implement these tests to ensure everything is working.
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { | ||
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. |
There was a problem hiding this comment.
Not sure if this is the best way to move forward with this function. Can we investigate collapsing the stack before we approve this?
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
There was a problem hiding this comment.
should try to leave comments on the tests
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
There was a problem hiding this comment.
could give some clarity on what these console logs are doing through comments
| public pressOperatorKey(key: OperatorKeys): void { | ||
| this.pushNumber(); | ||
| this.pushBuffer(); | ||
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { |
There was a problem hiding this comment.
two consecutive ifs may be confusing here, should find a way to combine them
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
throwing an error here may be helpful instead
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) |
There was a problem hiding this comment.
Good tests so far! Make sure to write these tests before you implement next time
|
|
||
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
This is vague, what exactly is the proposed test here?
brantpan1
left a comment
There was a problem hiding this comment.
Left a few small comments, overall good job!
| } | ||
|
|
||
| private pushNumber(): void { | ||
| private pushBuffer(): void { |
There was a problem hiding this comment.
Im not sure that this change should be in this PR, it doesn't help with implementing EXP. Maybe split this into two PRs?
|
|
||
| public pressOperatorKey(key: OperatorKeys): void { | ||
| this.pushNumber(); | ||
| this.pushBuffer(); |
There was a problem hiding this comment.
See above, Im not sure this change actually helps implements EXP
| this._buffer = result.toString(); | ||
| } else { | ||
| this._buffer = this.popNumber().toString(); | ||
| } |
There was a problem hiding this comment.
[nit] 2 calls of pop number, maybe only if case for more specific application?
| break; | ||
| case ActionKeys.EQUALS: { | ||
| this.pushNumber(); | ||
| this.pushBuffer(); |
There was a problem hiding this comment.
See above, not sure this targets implementing exp.
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) |
There was a problem hiding this comment.
These should be implemented in this PR, already new testing implementation, so should be reasonable to add onto the end.
| console.log("doing exp", num); | ||
| const result: number = Math.exp(num); | ||
| console.log("...it's", result); |
| it("should display e**1 with `exp(1)`", (): void => { | ||
| calculator.pressOperatorKey(OperatorKeys.EXP); | ||
| calculator.pressNumericKey(NumericKeys.ONE); | ||
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("2.718281828459045"); | ||
| }); | ||
|
|
||
| it("should display e**4 with `exp(4)`", (): void => { | ||
| calculator.pressOperatorKey(OperatorKeys.EXP); | ||
| calculator.pressNumericKey(NumericKeys.FOUR); | ||
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("54.598150033144236"); | ||
| }); | ||
|
|
||
| it("should display (e**9)+7 with `exp(9)+7)`", (): void => { | ||
| calculator.pressOperatorKey(OperatorKeys.EXP); | ||
| calculator.pressNumericKey(NumericKeys.NINE); | ||
| calculator.pressOperatorKey(OperatorKeys.PLUS); | ||
| calculator.pressNumericKey(NumericKeys.SEVEN); | ||
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("8110.083927575384"); | ||
| }); | ||
|
|
||
| it("should display (e**9)*7 with `exp(9)*7)`", (): void => { | ||
| calculator.pressOperatorKey(OperatorKeys.EXP); | ||
| calculator.pressNumericKey(NumericKeys.NINE); | ||
| calculator.pressOperatorKey(OperatorKeys.MULT); | ||
| calculator.pressNumericKey(NumericKeys.SEVEN); | ||
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); |
There was a problem hiding this comment.
[nit] Arrange, Act, Assert comments for more clarity.
| MINUS = "-", | ||
| MULT = "*", | ||
| DIV = "/", | ||
| EXP = "exp", |
There was a problem hiding this comment.
I think that "exp" should be consistent with the previous symbols. You can use "^".
| expect(calculator.display()).toEqual("1"); | ||
| }); | ||
|
|
||
| it("should display e**1 with `exp(1)`", (): void => { |
There was a problem hiding this comment.
I think that it would be helpful to add comments to your code, create better titles for your tests, and define constants to make your code more readable.
| expect(displayValue).toEqual("8110.083927575384"); | ||
| }); | ||
|
|
||
| it("should display (e**9)*7 with `exp(9)*7)`", (): void => { |
There was a problem hiding this comment.
You could reduce redundancy by combining some tests because they are very similar. You could make a helper function to do this by having the numeric key be the input.
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
| if (this.getState() === State.ENTERING_FIRST_OPERAND) { | ||
| this._buffer = this.popNumber().toString(); | ||
| if ( | ||
| this._operatorStack[this._operatorStack.length - 1] === | ||
| OperatorKeys.EXP | ||
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| const result: number = Math.exp(num); | ||
| this._buffer = result.toString(); | ||
| } else { | ||
| this._buffer = this.popNumber().toString(); | ||
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| assert(this._numberStack.length === 2); | ||
| const right: number = this.popNumber(); | ||
| const left: number = this.popNumber(); | ||
| const result: number = this.compute(op, left, right); |
There was a problem hiding this comment.
Consider making the operands more scalable rather than using another else if statement when adding another operand.
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
No need to add assert check inside the implementation
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
No need to add assert check inside the implementation
LonghaoH
left a comment
There was a problem hiding this comment.
Looks good. Need to finish testing and some minor detailed changes in the implementation.
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) |
There was a problem hiding this comment.
You should implement all the tests and make sure they pass.
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here | ||
| this.setState(State.ENTERING_SECOND_OPERAND); |
There was a problem hiding this comment.
You're on the right track. Essentially, this line suggests that if you're not doing the exp operation, the other operations (+, -, *, /) requires two operands. Hence, you'll need to evaluate the operator on two operands.
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| // We can always collapse the stack. | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
Can you clarify on what this line means?
| // TODO(max): Test exp(negative) | ||
| // TODO(max): Support exp(exp(n)) | ||
| // TODO(max): Test 1+2+3+4... are they even legal? |
There was a problem hiding this comment.
Please write all your tests before submitting for code review
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
I don't understand either, let's find a time to chat about this.
| } | ||
|
|
||
| private pushNumber(): void { | ||
| private pushBuffer(): void { |
There was a problem hiding this comment.
Good change. Even though a number is being pushed, it's coming from the buffer, so the buffer is being pushed.
| ) { | ||
| this._operatorStack.pop(); | ||
| const num: number = this.popNumber(); | ||
| console.log("doing exp", num); |
There was a problem hiding this comment.
These console logs are good for debugging, but they should be removed before submitting a pull request.
smithsrose1
left a comment
There was a problem hiding this comment.
please look over your code design, and consider using switch statements instead of multiple if statements!
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { | ||
| const op: OperatorKeys = this._operatorStack.pop(); | ||
| assert(this._numberStack.length === 2); |
There was a problem hiding this comment.
not sure it would be best to use an assert statement, may cause runtime errors
| MINUS = "-", | ||
| MULT = "*", | ||
| DIV = "/", | ||
| EXP = "exp", |
There was a problem hiding this comment.
might not be the right value to use for EXP
| calculator.pressActionKey(ActionKeys.EQUALS); | ||
| const displayValue: string = calculator.display(); | ||
| expect(displayValue).toEqual("8110.083927575384"); | ||
| }); |
There was a problem hiding this comment.
consider rounding the values to a set decimal place
| this.setState(State.ENTERING_SECOND_OPERAND); | ||
| } | ||
| } else if (this.getState() === State.ENTERING_SECOND_OPERAND) { | ||
| if (key === OperatorKeys.PLUS || key === OperatorKeys.MINUS) { |
There was a problem hiding this comment.
consider using a switch statement instead of if statements
| this._numberStack = [result]; | ||
| } | ||
| if (key !== OperatorKeys.EXP) { | ||
| // I do not understand what is going on here |
There was a problem hiding this comment.
Should set the current state as entering into the second phase of operand if the key pressed is anything other than exponent.
| MINUS = "-", | ||
| MULT = "*", | ||
| DIV = "/", | ||
| EXP = "exp", |
There was a problem hiding this comment.
A "^" might be easier to press as an exponent key?
| expect(displayValue).toEqual("56721.58749302769"); | ||
| }); | ||
|
|
||
| // TODO(max): Test exp(negative) |
There was a problem hiding this comment.
If TODO comments won't be implemented later on, do not keep.
implement
e**x