Considering a machine which has finite number of possible states, and there will be only one state in which the machine is said to be in.
Ex:- Vending machine could be in sleep mode or requesting coins from user etc…
The machine may change its state, which could depend upon the triggers.
Ex:- User inserting coins into the machine, might change the machine state from sleep to accepting the coins.
Each state would have next possible states which are associated.
State Machine Diagram :
Below is the sample code, which works using state machine algorithm.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace StateMachine_BeverageVendingMachine
{
class Program
{
static void Main(string[] args)
{
//creating vending machine instance and setting default product cost
BeverageVendingMachine machine = new BeverageVendingMachine() { Cost = 10 };
while (true)
{
try
{
Console.WriteLine("Current State : " + machine.ToString());
//if machine state is sleep, then asking user to enter coins
if (machine.CurrentState == MachineState.Sleep)
{
Console.WriteLine("Please enter coins for amount : " + (machine.Cost - machine.Amount));
Int32 coin = GetValidOption((i) =>i>0 && i <= (machine.Cost - machine.Amount), "Please enter coins for amount : " + (machine.Cost - machine.Amount));
machine.AddCoins(coin);
}
//if machine state is coins status, then asking for the remaining amount or either giving a cancel option
if (machine.CurrentState == MachineState.Coin_Status)
{
Console.WriteLine("Please enter coins for amount : " + (machine.Cost - machine.Amount) + " or hit -1 to cancel");
Int32 coin = GetValidOption((i) => i > 0 && i <= (machine.Cost - machine.Amount) || i == -1, "Please enter coins for amount : " + (machine.Cost - machine.Amount) + " or hit -1 to cancel");
if (coin == -1)
machine.Cancel();
else
machine.AddCoins(coin);
}
//if machine state is active, then asking user to select beverage option
if (machine.CurrentState == MachineState.Active)
{
Console.WriteLine("Please select menu \n 1. coffee\n 2. Tea");
Int32 coin = GetValidOption((i) => i == 1 || i == 2, "Please select menu \n 1. coffee\n 2. Tea");
if (coin == 1)
machine.Product = "Coffee";
if (coin == 2)
machine.Product = "Tea";
//supplyin the selected product
machine.Supply();
}
}
catch (Exception exp)
{
Console.WriteLine("Error : " + exp.Message);
}
}
}
public static Int32 GetValidOption(Func<int, bool> validate, string msg)
{
while (true)
{
Int32 option = 0;
if (int.TryParse(Console.ReadLine(), out option))
{
if (validate(option))
return option;
else
Console.WriteLine(msg);
}
else
Console.WriteLine("Please enter valid number");
}
}
}
public class BeverageVendingMachine
{
Dictionary<StateTransition, MachineState> machineTransitions = null;
public MachineState CurrentState { get; set; }
public int Amount { get; set; }
public int Cost { get; set; }
public string Product { get; set; }
public BeverageVendingMachine()
{
//adding each possible statetransition for a given state to dictionary.
machineTransitions = new Dictionary<StateTransition, MachineState>()
{
{ new StateTransition(MachineState.Sleep,MachineCommand.Sleep2CoinCheck), MachineState.Coin_Check},
{ new StateTransition(MachineState.Coin_Status,MachineCommand.CoinStatus2Cancel), MachineState.Cancel},
{ new StateTransition(MachineState.Coin_Check,MachineCommand.CoinCheck2CointStatus), MachineState.Coin_Status},
{ new StateTransition(MachineState.Coin_Status,MachineCommand.CoinStatus2Active), MachineState.Active},
{ new StateTransition(MachineState.Active,MachineCommand.Active2Supply), MachineState.Supply},
{ new StateTransition(MachineState.Supply,MachineCommand.Supply2Sleep), MachineState.Sleep},
{ new StateTransition(MachineState.Cancel,MachineCommand.Cancel2Sleep), MachineState.Sleep}
};
this.CurrentState = MachineState.Sleep;
}
//when user inserts coins
public void AddCoins(Int32 coin)
{
//In sleep state the amount is 0, hence changing the state to coin check state
if (Amount == 0)
GetNextState(MachineCommand.Sleep2CoinCheck);
//adding the total amount inserted so far
Amount += coin;
//if amount collected is same as cost
if (Amount == Cost)
{
//changing the coin check to coin status and then coin status to active
if (CurrentState == MachineState.Coin_Check)
GetNextState(MachineCommand.CoinCheck2CointStatus);
GetNextState(MachineCommand.CoinStatus2Active);
}
else
//changing coin check to coin status, when user enters coins, but the amount is less than the actual cost
if (CurrentState == MachineState.Coin_Check)
GetNextState(MachineCommand.CoinCheck2CointStatus);
}
//If user selects cancel operation, after entering few coins
public void Cancel()
{
//changing the state to cancel and sleep
GetNextState(MachineCommand.CoinStatus2Cancel);
GetNextState(MachineCommand.Cancel2Sleep);
//handovering the amout collected before cancel
if (Amount > 0)
Console.WriteLine("Please collect your amount : {0}", Amount);
Amount = 0;
}
//after user selects product from menu
public void Supply()
{
//supplying the product
GetNextState(MachineCommand.Active2Supply);
Console.WriteLine("Supplying {0} ...", Product);
//going to sleep mode
GetNextState(MachineCommand.Supply2Sleep);
Console.WriteLine("Thanks for choosing this vending machine");
Amount = 0;
}
//setting the next state based on current state and command issued
public void GetNextState(MachineCommandcommand)
{
StateTransition trans = new StateTransition(CurrentState, command);
MachineState nextState;
if (machineTransitions.TryGetValue(trans, out nextState))
{
CurrentState = nextState;
}
else
throw new Exception(string.Format("No valid state transition for state : {0}, command : {1}", CurrentState, command));
}
public override string ToString()
{
return CurrentState.ToString();
}
}
//each state transition object is the reference of StateTransition class
public class StateTransition
{
readonly MachineState CurrentState;
readonly MachineCommandCommand;
public StateTransition(MachineState state, MachineCommand command)
{
this.CurrentState = state;
this.Command = command;
}
public override bool Equals(object obj1)
{
StateTransition obj = obj1 as StateTransition;
return (obj.Command == this.Command && obj.CurrentState == this.CurrentState);
}
public override int GetHashCode()
{
return (10 * CurrentState.GetHashCode()) + (10 * Command.GetHashCode());
}
}
//Vending machine, finite possible states
public enum MachineState
{
Sleep = 1,
Coin_Check = 2,
Cancel = 3,
Coin_Status = 4,
Active = 5,
Supply = 6
}
//Vending machine, possible state transitions
public enum MachineCommand
{
Sleep2CoinCheck = 1,
CoinStatus2Cancel = 2,
Cancel2Sleep = 3,
CoinCheck2CointStatus = 4,
CoinStatus2Active = 5,
Active2Supply = 6,
Supply2Sleep = 7
}
}
Output :
this is great .
ReplyDeletethanks for the information you share .
Microsoft Office Office Pro Software Download
Very interesting piece..
ReplyDeleteView website about Cold Laser Fort Worth
I like the helpful info you provide in your articles.I am quite certain I’ll learn lots of new stuff right here!
ReplyDeleteRecommended Little Susitna Salmon Fishing Alaska Guides, IFishAlaska
So this is how it works. Thanks for the info. www.seattleseo.biz
ReplyDeleteTerrific job, this information is exactly what I was looking for. Thank you very much.
ReplyDeleteBest Spicewood landscape lighting click here
The machine may change its state
ReplyDeleteInformative URL for Seattle Painter Contractor
there will be only one state in which the machine is said to be in.
ReplyDeleteGreat data for Dallas Apartments for Rent
User inserting coins into the machine, might change the machine state from sleep to accepting the coins.
ReplyDeleteGet Best Info for Thailand Yoga Teacher Training School
Great and useful article. Creating content regularly is very tough. Your points are motivated me to move on
ReplyDeleteDigital Marketing Company in Chennai
this is very nice blog this studying course information very useful to everyone who have learning this information.this education information is very helpful to start my carrier with technology.
ReplyDeleteBase SAS Training in chennai
Your blog is given a more future updates for viewers.
ReplyDeletePython Training in Chennai
Great and useful article.
ReplyDeleteVMware Training in Chennai