This picture inspired a contest between a few of my friends to rewrite this code in more proper OO style. 

[![coffee mug with code](https://i.stack.imgur.com/5GWOt.jpg)](https://i.stack.imgur.com/5GWOt.jpg)

This is what I have come up with.
Any thoughts:

```
public enum CoffeeKind
{
    Black = 1,
    Cappuccino,
    Espresso
}

public class Coffee
{
    //Measured in celcius
    public int Temprature { get; set; } = 30;
    public bool HasMilk { get; set; }
    public int Sugar { get; set; }
    public CoffeeKind Kind { get; set; }
    public bool Cold => Temprature < 24;
}

public enum CupSize
{
    Small = 1,
    Medium,
    Large,
    ExtraLarge
}

public class Cup
{
    public static Cup SMALL = new Cup(CupSize.Small);
    public static Cup MEDIUM = new Cup(CupSize.Medium);
    public static Cup LARGE = new Cup(CupSize.Large);
    public static Cup EXTRA_LARGE = new Cup(CupSize.ExtraLarge);

    public static Dictionary<CupSize, Cup> Cups = new Dictionary<CupSize, Cup>
    {
        [CupSize.Small] = SMALL,
        [CupSize.Medium] = MEDIUM,
        [CupSize.Large] = LARGE,
        [CupSize.ExtraLarge] = EXTRA_LARGE
    };

    public CupSize Size { get; }
    public int Amount { get; set; }
    public bool Empty => Amount == 0;
    public Coffee Coffee { get; set; }

    private Cup() : this(CupSize.Medium) { }
    private Cup(CupSize size)
    {
        Size = size;
    }

    public void Fill(CoffeeKind kind)
    {
        if (Empty)
        {
            Coffee = new Coffee { Kind = kind };
            Amount = SetAmountBySize(Size);
        }
    }

    private static int SetAmountBySize(CupSize size)
    {
        switch (size)
        {
            case CupSize.Small:
                return 100;
            case CupSize.Large:
                return 300;
            case CupSize.ExtraLarge:
                return 400;
            case CupSize.Medium:
            default:
                return 200;
        }
    }
}

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Name => $"{FirstName} {LastName}";
    public Cup Cup { get; set; }

    public Person() { }
    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }

    public void GetCoffee(CupSize size, CoffeeKind kind)
    {
        Cup = Cup.Cups[size];
        Cup.Fill(kind);
    }

    public void Drink()
    {
        if (Cup?.Empty == false && Cup?.Coffee?.Cold == false)
        {
            Cup.Amount = 0;
        }
    }

    public void Drink(int amount)
    {
        if (Cup?.Empty == false && Cup?.Coffee?.Cold == false)
        {
            Cup.Amount -= amount;
        }
    }
}

class Program
{
    const int EXIT = -1;
    const int GET_COFFEE = 1;
    const int DRINK_COFFEE = 2;
    const int DRINK_AMOUNT = 3;

    //TODO change these to use values of enum - or just change the calls to them
    const int SMALL = 1;
    const int MEDIUM = 2;
    const int LARGE = 3;
    const int EXTRA_LARGE = 4;

    const int BLACK = 1;
    const int CAPPUCCINO = 2;
    const int ESPRESSO = 3;

    static Person person;
    static void Main(string[] args)
    {
        Console.WriteLine("Enter first name:");
        string firstName = Console.ReadLine();
        Console.WriteLine("Enter last name:");
        string lastName = Console.ReadLine();

        person = new Person(firstName, lastName);

        var choice = GetUserAction();
        while (choice != EXIT)
        {
            if (choice == GET_COFFEE)
            {
                if (person?.Cup?.Empty == false)
                {
                    Console.WriteLine("Old coffee will be thrown out");
                }
                int cupSize = GetCupSize();
                int coffeeKind = GetCoffeKind();

                person.GetCoffee((CupSize)cupSize, (CoffeeKind)coffeeKind);
                Console.WriteLine($"Got a {person.Cup.Size.ToString()} size {person.Cup.Coffee.Kind.ToString()} coffee");
            }
            else if (choice == DRINK_COFFEE)
            {
                if (person?.Cup?.Empty == false)
                {
                    person.Drink();
                }
                else
                {
                    Console.WriteLine("Can not drink without coffee!");
                }
            }

            choice = GetUserAction();
        }
    }

    private static int GetCoffeKind()
    {
        Console.WriteLine($"{BLACK}: Black");
        Console.WriteLine($"{CAPPUCCINO}: Cappuccino");
        Console.WriteLine($"{ESPRESSO}: Espresso");

        var result = int.Parse(Console.ReadLine());

        if (result < BLACK || result > ESPRESSO)
        {
            return GetCoffeKind();
        }

        return result;
    }

    private static int GetCupSize()
    {
        Console.WriteLine($"{SMALL}: {nameof(SMALL)}");
        Console.WriteLine($"{MEDIUM}: Medium");
        Console.WriteLine($"{LARGE}: Large");
        Console.WriteLine($"{EXTRA_LARGE}: Extra Large");
        var result = int.Parse(Console.ReadLine());

        if (result < SMALL || result > EXTRA_LARGE)
        {
            return GetCupSize();
        }

        return result;
    }

    private static int GetUserAction()
    {
        Console.WriteLine("What would you like to do:");
        Console.WriteLine($"{GET_COFFEE}: Get coffee");
        // You can't drink coffee without a cup
        if (person?.Cup != null)
        {
            Console.WriteLine($"{DRINK_COFFEE}: Drink coffee");
            Console.WriteLine($"{DRINK_AMOUNT}: Drink some coffee");
        }
        Console.WriteLine($"{EXIT}: Exit");
        return int.Parse(Console.ReadLine());
    }
}

```