Commits

Douglas Mendizabal  committed afe1810

Finished the Money example.

  • Participants
  • Parent commits 9d142be

Comments (0)

Files changed (7)

File Part I/money/Bank.cs

+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace money
+{
+    public class Bank
+    {
+        Hashtable rates = new Hashtable();
+
+        public Money Reduce(IExpression source, string to)
+        {
+            return source.Reduce(this, to);
+        }
+
+        public void AddRate(string from, string to, int rate)
+        {
+            rates.Add(new Pair(from, to), rate);
+        }
+
+        public int Rate(string from, string to)
+        {
+            if (from.Equals(to))
+                return 1;
+            int rate = (int) rates[new Pair(from, to)];
+            return rate;
+        }
+    }
+}

File Part I/money/IExpression.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace money
+{
+    public interface IExpression
+    {
+        Money Reduce(Bank bank, string to);
+        IExpression Plus(IExpression addend);
+        IExpression Times(int multiplier);
+    }
+}

File Part I/money/Money.cs

 
 namespace money
 {
-    public class Money
+    public class Money : IExpression
     {
         protected internal int amount;
         protected internal string currency;
             return new Money(amount, "USD");
         }
 
-        public Money Times(int multiplier)
+        public IExpression Times(int multiplier)
         {
             return new Money(amount * multiplier, currency);
         }
             return currency;
         }
 
-        public Money Plus(Money addend)
+        public IExpression Plus(IExpression addend)
         {
-            return new Money(amount + addend.amount, currency);
+            return new Sum(this, addend);
+        }
+
+        public Money Reduce(Bank bank, String to)
+        {
+            int rate = bank.Rate(currency, to);
+            return new Money(amount / rate, to);
         }
     }
 }

File Part I/money/Pair.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace money
+{
+    public class Pair
+    {
+        private string from;
+        private string to;
+
+        public Pair(string from, string to)
+        {
+            this.from = from;
+            this.to = to;
+        }
+
+        public override bool Equals(object obj)
+        {
+            Pair pair = (Pair) obj;
+            return from.Equals(pair.from) && to.Equals(pair.to);
+        }
+
+        public override int GetHashCode()
+        {
+            return 0;
+        }
+    }
+}

File Part I/money/Sum.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace money
+{
+    public class Sum : IExpression
+    {
+        public IExpression augend;
+        public IExpression addend;
+
+        public Sum(IExpression augend, IExpression addend)
+        {
+            this.augend = augend;
+            this.addend = addend;
+        }
+
+        public Money Reduce(Bank bank, string to)
+        {
+            int amount = augend.Reduce(bank, to).amount + addend.Reduce(bank, to).amount;
+            return new Money(amount, to);
+        }
+
+        public IExpression Plus(IExpression addend)
+        {
+            return new Sum(this, addend);
+        }
+
+        public IExpression Times(int multiplier)
+        {
+            return new Sum(augend.Times(multiplier), addend.Times(multiplier));
+        }
+    }
+}

File Part I/money/money.csproj

     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="Bank.cs" />
+    <Compile Include="IExpression.cs" />
     <Compile Include="Money.cs" />
+    <Compile Include="Pair.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Sum.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

File Part I/moneyTests/Tests.cs

         {
             Assert.True(Money.Dollar(5).Equals(Money.Dollar(5)));
             Assert.False(Money.Dollar(5).Equals(Money.Dollar(6)));
-            Assert.True(Money.Franc(5).Equals(Money.Franc(5)));
-            Assert.False(Money.Franc(5).Equals(Money.Franc(6)));
             Assert.False(Money.Dollar(5).Equals(Money.Franc(5)));
         }
 
         [Fact]
-        public void TestFrancMultiplication()
-        {
-            Money five = Money.Franc(5);
-            Assert.Equal(Money.Franc(10), five.Times(2));
-            Assert.Equal(Money.Franc(15), five.Times(3));
-        }
-
-        [Fact]
         public void TestCurrency()
         {
             Assert.Equal("USD", Money.Dollar(1).Currency());
         [Fact]
         public void TestSimpleAddition()
         {
-            Money sum = Money.Dollar(5).Plus(Money.Dollar(5));
-            Assert.True(Money.Dollar(10).Equals(sum));
+            Money five = Money.Dollar(5);
+            IExpression sum = five.Plus(five);
+            Bank bank = new Bank();
+            Money reduced = bank.Reduce(sum, "USD");
+            Assert.Equal(Money.Dollar(10), reduced);
+        }
+
+        [Fact]
+        public void TestPlusReturnsSum()
+        {
+            Money five = Money.Dollar(5);
+            IExpression result = five.Plus(five);
+            Sum sum = (Sum) result;
+            Assert.Equal(five, sum.augend);
+            Assert.Equal(five, sum.addend);
+        }
+
+        [Fact]
+        public void TestReduceSum()
+        {
+            IExpression sum = new Sum(Money.Dollar(3), Money.Dollar(4));
+            Bank bank = new Bank();
+            Money result = bank.Reduce(sum, "USD");
+            Assert.Equal(Money.Dollar(7), result);
+        }
+
+        [Fact]
+        public void TestReduceMoney()
+        {
+            Bank bank = new Bank();
+            Money result = bank.Reduce(Money.Dollar(1), "USD");
+            Assert.Equal(Money.Dollar(1), result);
+        }
+
+        [Fact]
+        public void TestReduceMoneyDifferentCurrency()
+        {
+            Bank bank = new Bank();
+            bank.AddRate("CHF", "USD", 2);
+            Money result = bank.Reduce(Money.Franc(2), "USD");
+            Assert.Equal(Money.Dollar(1), result);
+        }
+
+        [Fact]
+        public void TestIdentityRate()
+        {
+            Assert.Equal(1, new Bank().Rate("USD", "USD"));
+        }
+
+        [Fact]
+        public void TestMixedAddition()
+        {
+            IExpression fiveBucks = Money.Dollar(5);
+            IExpression tenFrancs = Money.Franc(10);
+            Bank bank = new Bank();
+            bank.AddRate("CHF", "USD", 2);
+            Money result = bank.Reduce(fiveBucks.Plus(tenFrancs), "USD");
+            Assert.Equal(Money.Dollar(10), result);
+        }
+
+        [Fact]
+        public void TestSumPlusMoney()
+        {
+            IExpression fiveBucks = Money.Dollar(5);
+            IExpression tenFrancs = Money.Franc(10);
+            Bank bank = new Bank();
+            bank.AddRate("CHF", "USD", 2);
+            IExpression sum = new Sum(fiveBucks, tenFrancs).Plus(fiveBucks);
+            Money result = bank.Reduce(sum, "USD");
+            Assert.Equal(Money.Dollar(15), result);
+        }
+
+        [Fact]
+        public void TestSumTimes()
+        {
+            IExpression fiveBucks = Money.Dollar(5);
+            IExpression tenFrancs = Money.Franc(10);
+            Bank bank = new Bank();
+            bank.AddRate("CHF", "USD", 2);
+            IExpression sum = new Sum(fiveBucks, tenFrancs).Times(2);
+            Money result = bank.Reduce(sum, "USD");
+            Assert.Equal(Money.Dollar(20), result);
         }
     }
 }