calculator: major logic refactor, move up display code & use numerics
authorAlexis Laferrière <alexis.laf@xymus.net>
Sun, 3 Aug 2014 19:11:01 +0000 (15:11 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Wed, 27 Aug 2014 20:58:22 +0000 (16:58 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

examples/calculator/src/calculator_gtk.nit
examples/calculator/src/calculator_logic.nit
examples/calculator/src/calculator_test.nit

index d4edbdb..bd2bd11 100644 (file)
@@ -33,46 +33,21 @@ class CalculatorGui
 
        var context = new CalculatorContext
 
-       redef fun signal( sender, user_data )
+       redef fun signal(sender, op)
        do
-               var after_point = context.after_point
-               if after_point == null then
-                   after_point = 0
-               else
-                   after_point = (after_point.abs)
-               end
-
-               if user_data isa Char then # is an operation
-                       var c = user_data
-                       if c == '.' then
-                               but_dot.sensitive= false
+               if op isa Char then # is an operation
+                       if op == '.' then
+                               but_dot.sensitive = false
                                context.switch_to_decimals
-                               lbl_disp.text = "{context.current.to_i}."
                        else
-                               but_dot.sensitive= true
-                               context.push_op( c )
-
-                               var s = context.result.to_precision_native(6)
-                               var index : nullable Int = null
-                               for i in s.length.times do
-                                   var chiffre = s.chars[i]
-                                   if chiffre == '0' and index == null then
-                                       index = i
-                                   else if chiffre != '0' then
-                                       index = null
-                                   end
-                               end
-                               if index != null then
-                                       s = s.substring(0, index)
-                                       if s.chars[s.length-1] == ',' then s = s.substring(0, s.length-1)
-                               end
-                               lbl_disp.text = s
+                               but_dot.sensitive = true
+                               context.push_op op
                        end
-               else if user_data isa Int then # is a number
-                       var n = user_data
-                       context.push_digit( n )
-                       lbl_disp.text = context.current.to_precision_native(after_point)
+               else if op isa Int then # is a number
+                       context.push_digit op
                end
+
+               lbl_disp.text = context.display_text
        end
 
        init
index 9666d14..c5fbaf7 100644 (file)
 module calculator_logic
 
 class CalculatorContext
-       var result : nullable Float = null
+       var result: nullable Numeric = null
 
-       var last_op : nullable Char = null
+       var last_op: nullable Char = null
 
-       var current : nullable Float = null
-       var after_point : nullable Int = null
+       var current: nullable FlatBuffer = null
+       fun display_text: String
+       do
+               var result = result
+               var last_op = last_op
+               var current = current
+
+               var buf = new FlatBuffer
+
+               if result != null and (current == null or last_op != '=') then
+                       if last_op == '=' then buf.append "= "
+
+                       buf.append result.to_s
+                       buf.add ' '
+               end
+
+               if last_op != null and last_op != '=' then
+                       buf.add last_op
+                       buf.add ' '
+               end
+
+               if current != null then
+                       buf.append current.to_s
+                       buf.add ' '
+               end
+
+               return buf.to_s
+       end
 
        fun push_op( op : Char )
        do
                apply_last_op_if_any
                if op == 'C' then
-                       self.result = 0.0
+                       self.result = null
                        last_op = null
                else
                        last_op = op # store for next push_op
                end
 
                # prepare next current
-               after_point = null
-               current = null
+               self.current = null
        end
 
        fun push_digit( digit : Int )
        do
                var current = current
-               if current == null then current = 0.0
+               if current == null then current = new FlatBuffer
+               current.add digit.to_s.chars.first
+               self.current = current
 
-               var after_point = after_point
-               if after_point == null then
-                       current = current * 10.0 + digit.to_f
-               else
-                       current = current + digit.to_f * 10.0.pow(after_point.to_f)
-                       self.after_point -= 1
+               if last_op == '=' then
+                       self.result = null
+                       last_op = null
                end
-
-               self.current = current
        end
 
        fun switch_to_decimals
        do
-               if self.current == null then current = 0.0
-               if after_point != null then return
-
-               after_point = -1
+               var current = current
+               if current == null then current = new FlatBuffer.from("0")
+               if not current.chars.has('.') then current.add '.'
+               self.current = current
        end
 
        fun apply_last_op_if_any
@@ -69,23 +91,26 @@ class CalculatorContext
                var op = last_op
 
                var result = result
-               if result == null then result = 0.0
 
                var current = current
-               if current == null then current = 0.0
+               if current == null then current = new FlatBuffer
 
                if op == null then
-                       result = current
+                       result = current.to_n
                else if op == '+' then
-                       result = result + current
+                       result = result.add(current.to_n)
                else if op == '-' then
-                       result = result - current
+                       result = result.sub(current.to_n)
                else if op == '/' then
-                       result = result / current
+                       result = result.div(current.to_n)
                else if op == '*' then
-                       result = result * current
+                       result = result.mul(current.to_n)
                end
                self.result = result
                self.current = null
        end
 end
+
+redef universal Float
+       redef fun to_s do return to_precision(6)
+end
index 2d47acb..6937751 100644 (file)
@@ -28,8 +28,8 @@ context.push_digit( 3 )
 context.push_op( '*' )
 context.push_digit( 2 )
 context.push_op( '=' )
-var r = context.result.to_precision( 2 )
-assert r == "30.00" else print r
+var r = context.result
+assert r == "30.00" else print r or else "-"
 
 context = new CalculatorContext
 context.push_digit( 1 )
@@ -39,15 +39,15 @@ context.push_digit( 1 )
 context.push_op( '*' )
 context.push_digit( 3 )
 context.push_op( '=' )
-r = context.result.to_precision( 2 )
-assert r == "42.30" else print r
+r = context.result
+assert r == "42.30" else print r or else "-"
 
 context.push_op( '+' )
 context.push_digit( 1 )
 context.push_digit( 1 )
 context.push_op( '=' )
-r = context.result.to_precision( 2 )
-assert r == "53.30" else print r
+r = context.result
+assert r == "53.30" else print r or else "-"
 
 context = new CalculatorContext
 context.push_digit( 4 )
@@ -57,8 +57,8 @@ context.push_digit( 3 )
 context.push_op( '/' )
 context.push_digit( 3 )
 context.push_op( '=' )
-r = context.result.to_precision( 2 )
-assert r == "14.10" else print r
+r = context.result
+assert r == "14.10" else print r or else "-"
 
 #test multiple decimals
 context = new CalculatorContext
@@ -71,8 +71,8 @@ context.push_digit( 3 )
 context.push_op( '+' )
 context.push_digit( 1 )
 context.push_op( '=' )
-r = context.result.to_precision( 3 )
-assert r == "51.123" else print r
+r = context.result
+assert r == "51.123" else print r or else "-"
 
 #test 'C' button
 context = new CalculatorContext
@@ -83,5 +83,5 @@ context.push_digit( 1 )
 context.push_digit( 0 )
 context.push_op( '=' )
 context.push_op( 'C' )
-r = context.result.to_precision( 1 )
-assert r == "0.0" else print r
+r = context.result
+assert r == "0.0" else print r or else "-"