Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kata by Charlie Poole at Coding Dojo Segovia #12

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions dojosegovia/KataLonja.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 10.00
# Visual Studio 2008
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KataLonja", "KataLonja\KataLonja.csproj", "{EBE98BD2-764B-4AC6-9E4F-07CC5B6CC218}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EBE98BD2-764B-4AC6-9E4F-07CC5B6CC218}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EBE98BD2-764B-4AC6-9E4F-07CC5B6CC218}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EBE98BD2-764B-4AC6-9E4F-07CC5B6CC218}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EBE98BD2-764B-4AC6-9E4F-07CC5B6CC218}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
Binary file added dojosegovia/KataLonja.suo
Binary file not shown.
39 changes: 39 additions & 0 deletions dojosegovia/KataLonja/City.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KataLonja
{
public class PriceList : Dictionary<string, double> { }

public class City
{
private double depreciationFactor;

public City(string name, double distance)
{
this.Name = name;
this.Distance = distance;
this.Prices = new PriceList();
this.depreciationFactor = 1.0 - distance * .0001;
}

public string Name { get; set; }
public double Distance { get; set; }
public PriceList Prices { get; set; }

public double ActualPrice(string item)
{
if (!this.Prices.ContainsKey(item))
return 0.0;

return this.Prices[item] * depreciationFactor;
}

public double TravelCost
{
get { return 5 + 2 * Distance; }
}
}
}
51 changes: 51 additions & 0 deletions dojosegovia/KataLonja/CityTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;

namespace KataLonja
{
public class CityTests
{
private City city;

[SetUp]
public void CreateCity()
{
city = new City("Madrid", 800);
city.Prices.Add("Vieiras", 500);
city.Prices.Add("Centollos", 450);
}

[Test]
public void CityHasCorrectName()
{
Assert.That(city.Name, Is.EqualTo("Madrid"));
}

[Test]
public void CityHasCorrectDistance()
{
Assert.That(city.Distance, Is.EqualTo(800));
}

[TestCase("Vieiras", 460)]
[TestCase("Pulpo", 0)]
[TestCase("Centollos", 414)]
public void ActualPriceIsCorrect(string item, double expectedPrice)
{
var actualPrice = city.ActualPrice(item);
Assert.That(actualPrice, Is.EqualTo(expectedPrice), "Not as expected");

var calculatedPrice = city.Prices.ContainsKey(item)
? city.Prices[item] * (1.0 - city.Distance * 0.0001)
: 0.0;
Assert.That(actualPrice, Is.EqualTo(calculatedPrice), "Not as recalculated");
}

[Test]
public void TravelCostIsCorrect()
{
Assert.That(city.TravelCost, Is.EqualTo(5 + 2 * 800));
}
}
}
63 changes: 63 additions & 0 deletions dojosegovia/KataLonja/Development Notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
I started this solution at the 13 May 2011 Coding Dojo
in Segovia. I was asked to speak first and I talked
longer than I (or maybe others) expected, so we didn't
finish the Kata there. I am creating this file so that
the folks who saw the start can understand how I went
about finishing it, and to add some thoughts about
other ways to solve the problem.

STEPS

1. In the Coding Dojo, all the code was developed in
a single class called Destination (now City) and we
got so far as to calculate the revenue, travel cost
and profit for various loads of seafood.

2. On the train back to Madrid, I changed the class
name to City and did some refactoring so that names
made more sense. I also encapsulated the generic
dictionaries we used into derived classes Inventory
and PriceList. I transferred the methods that
calculate revenue and profit to the Inventory class,
giving them a City as an argument.

3. Back in my hotel, I created a Van class, having
Capacity and Contents properties. Contents is an
Inventory. The van tracks it's CurrentWeight and
RemainingCapacity, although those properties were
added only after I started writing the optimizer.

4. The Optimizer class has a general method to
optimize across a list of cities. It uses a
subordinate method to load a Van in an optimal
way for a single city. The second method is public
only for testing purposes. The constructor for the
class takes an Inventory representing the stock
on hand for shipping.

5. In the Optimizer.cs file there is also a static
class with an extension method that dumps the
information held by the optimizer. This allows
writing optimizer.DumpContents() without adding
a method that is purely for testing to the class
itself. Running the OptimalLoadForAllCities test
therefore displays the answer we are looking for.

NOTES

1. We started this Kata bottom-up, because I wanted
to be able to show some simple TDD coding at the
start. In fact, it might be smoother to do it
top-down, starting with the Optimizer. Maybe
somebody will try this and let us know.

2. The specific example data does not actually
exercise all parts of the code. For example, there
is an (untested) check in the code to reduce the
amount being loaded if it would otherwise increase
the load beyond the capacity of the van.

3. The possibility of a "girlfriend in Barcelona"
is not accounted for in the code.

Charlie
35 changes: 35 additions & 0 deletions dojosegovia/KataLonja/Inventory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KataLonja
{
public class Inventory : Dictionary<string,double>
{
public double GetRevenueForCity(City city)
{
double result = 0.0;

foreach (string product in Keys)
result += city.ActualPrice(product) * this[product];

return result;
}

public double GetProfitForCity(City city)
{
return GetRevenueForCity(city) - city.TravelCost;
}

public override string ToString()
{
StringBuilder sb = new StringBuilder();

foreach (string item in Keys)
sb.AppendFormat(" {0}:\t{1}\n", item, this[item]);

return sb.ToString();
}
}
}
61 changes: 61 additions & 0 deletions dojosegovia/KataLonja/InventoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;

namespace KataLonja
{
public class InventoryTests
{
private City city;
private Inventory inventory;

[SetUp]
public void Initialize()
{
inventory = new Inventory();

city = new City("Madrid", 800);
city.Prices.Add("Vieiras", 500);
city.Prices.Add("Centollos", 450);
}

[Test]
public void ItemsCanBeAdded()
{
inventory.Add("X", 100);
Assert.That(inventory.Count, Is.EqualTo(1));
inventory.Add("Y", 50);
Assert.That(inventory.Count, Is.EqualTo(2));
inventory.Add("Z", 50);
Assert.That(inventory.Count, Is.EqualTo(3));
}

[TestCase(0, 0, 0, Result = 0)]
[TestCase(50, 0, 0, Result = 23000)]
[TestCase(0, 100, 0, Result = 0)]
[TestCase(0, 0, 50, Result = 20700)]
[TestCase(50, 100, 50, Result = 43700)]
public double RevenueIsCalculatedCorrectly(double vieiras, double pulpo, double centollos)
{
inventory.Add("Vieiras", vieiras);
inventory.Add("Pulpo", pulpo);
inventory.Add("Centollos", centollos);

return inventory.GetRevenueForCity(city);
}

[TestCase(0, 0, 0, Result = -1605)]
[TestCase(50, 0, 0, Result = 21395)]
[TestCase(0, 100, 0, Result = -1605)]
[TestCase(0, 0, 50, Result = 19095)]
[TestCase(50, 100, 50, Result = 42095)]
public double ProfitIsCalculatedCorrectly(double vieiras, double pulpo, double centollos)
{
inventory.Add("Vieiras", vieiras);
inventory.Add("Pulpo", pulpo);
inventory.Add("Centollos", centollos);

return inventory.GetProfitForCity(city);
}
}
}
Binary file not shown.
73 changes: 73 additions & 0 deletions dojosegovia/KataLonja/KataLonja.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{EBE98BD2-764B-4AC6-9E4F-07CC5B6CC218}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>KataLonja</RootNamespace>
<AssemblyName>KataLonja</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="nunit.framework, Version=2.5.10.11092, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="City.cs" />
<Compile Include="CityTests.cs" />
<Compile Include="Inventory.cs" />
<Compile Include="InventoryTests.cs" />
<Compile Include="Optimizer.cs" />
<Compile Include="OptimizerTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Van.cs" />
<Compile Include="VanTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="KataLonja English Translation.pdf" />
</ItemGroup>
<ItemGroup>
<Content Include="Development Notes.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Loading