John Squibb
Washing Machine
The washing machine is based on a very simple Kenmore appliance in the laundry room of my house. It only has two cycles, Permanent Press and Heavy Duty.
There are a couple of interfaces for the knobs. Usually I tend to name interfaces as adjectives, such as chargeable, or deletable, but for the appliances project, I am naming them as if they were true interface objects, such as a Cycle Knob or a Temperature Knob. They represent the real world interfaces on my washer, and not just a suggestion to code by contract!.
Namespaces and constants are used throughout. You'll also require the base classes found in Interval and Debug.
Specification Photos
The Code
<?php
namespace Washing_Machine;
// Defines requirements for a knob that selects cycle settings
interface Cycle_Knob
{
public function start();
public function stop();
public function select_cycle($cycle, $length);
}
// Defines requirements for a knob that selects temperature settings
interface Temperature_Knob
{
public function set_temperature($temperature);
}
// Defines requirements for a knob that sets load size settings
interface Load_Size_Knob
{
public function set_load_size($load_size);
}
/**
* The washing machine unit.
*/
class Unit
implements
Temperature_Knob,
Load_Size_Knob,
Cycle_Knob
{
/**
* Water Temperatures
*/
const TEMPERATURE_COLD = 0;
const TEMPERATURE_WARM = 1;
const TEMPERATURE_HOT = 2;
/**
* Load Sizes
*/
const LOAD_SIZE_SMALL = 0;
const LOAD_SIZE_MEDIUM = 1;
const LOAD_SIZE_LARGE = 2;
/**
* Cycles
*/
const CYCLE_HEAVY_DUTY = 0;
const CYCLE_PERMANENT_PRESS = 1;
/**
* Lengths for each cycle. These are not the actual lengths
* @see $this->cycle_times below for minutes in each lenght/cycle.
*/
const LENGTH_SHORT = 0;
const LENGTH_REGULAR = 1;
const LENGTH_SUPER = 2;
/**
* Length of Pause in minutes
*/
const MINUTES_PAUSE = 2;
/**
* Length of Spin in minutes
*/
const MINUTES_SPIN = 3;
/**
* Length of Rinse in minutes
*/
const MINUTES_RINSE = 3;
/**
* Cycle times.
* Set in $this->initialize_cycles() on construct.
*/
private $cycle_times = array();
/**
* Water temperature
*/
private $temperature;
/**
* Load size
*/
private $load_size;
/**
* Cycle
*/
private $cycle;
/**
* Length
*/
private $length;
/**
* Constructor
*/
public function __construct()
{
// Initialize cycles
$this->initialize_cycles();
// Set default temperature
$this->set_temperature(self::TEMPERATURE_COLD);
}
/**
* Sets minutes in each cycle
* Based on constants set for Cycles and Lengths.
* All times are in minutes.
*/
private function initialize_cycles()
{
$this->cycle_times = array
(
self::CYCLE_HEAVY_DUTY => array
(
self::LENGTH_SHORT => 4,
self::LENGTH_REGULAR => 8,
self::LENGTH_SUPER => 10
),
self::CYCLE_PERMANENT_PRESS => array
(
self::LENGTH_SHORT => 4,
self::LENGTH_REGULAR => 10,
self::LENGTH_SUPER => 14
)
);
}
/**
* Cleans up processes
*/
private function shutdown()
{
$this->cycle = NULL;
}
/**
* Sets water temperature.
*
* @param integer $temperature
*/
public function set_temperature($temperature)
{
$this->temperature = $temperature;
}
/**
* Sets load size for water level purposes
*
* @param integer $load_size
*/
public function set_load_size($load_size)
{
$this->load_size = $load_size;
}
/**
* Starts the unit.
*/
public function start()
{
\Debug\Trace::out
(
"starting machine with cycle of: {$this->cycle}"
);
$this->run_cycle($this->cycle);
$this->stop();
}
/**
* Stops the unit
*/
public function stop()
{
\Debug\Trace::out('stopping machine');
}
/**
* Selects the cycle
*
* @param integer $cycle
* @param integer $length
*/
public function select_cycle($cycle, $length)
{
$this->cycle = $cycle;
$this->length = $length;
}
/**
* Runs internally set cycle
*/
protected function run_cycle()
{
switch ($this->cycle)
{
case self::CYCLE_HEAVY_DUTY:
$this->fill();
$this->wash();
$this->rinse();
$this->spin();
break;
case self::CYCLE_PERMANENT_PRESS:
$this->fill();
$this->wash();
$this->pause();
$this->rinse();
$this->spin();
break;
}
}
/**
* Fills machine with water.
*/
protected function fill()
{
switch ($this->load_size)
{
case self::LOAD_SIZE_SMALL:
\Debug\Trace::out('Filling unit with water for SMALL load');
break;
case self::LOAD_SIZE_MEDIUM:
\Debug\Trace::out('Filling unit with water for MEDIUM load');
break;
case self::LOAD_SIZE_LARGE:
\Debug\Trace::out('Filling unit with water for LARGE load');
break;
}
}
/**
* Run wash cycle
*/
protected function wash()
{
$interval = \Time\Interval::get
(
\Time\Interval::MINUTES_TO_SECONDS,
$this->cycle_times[$this->cycle][$this->length]
);
do
{
\Debug\Trace::out("washing. {$interval} seconds to go");
\Time\Interval::tick();
}
while ($interval--);
}
/**
* Run spin cycle
*/
protected function spin()
{
$interval = \Time\Interval::get
(
\Time\Interval::MINUTES_TO_SECONDS,
self::MINUTES_SPIN
);
do
{
\Debug\Trace::out("spinning. {$interval} seconds to go");
\Time\Interval::tick();
}
while ($interval--);
}
/**
* Run rinse cycle
*/
protected function rinse()
{
$interval = \Time\Interval::get
(
\Time\Interval::MINUTES_TO_SECONDS,
self::MINUTES_RINSE
);
do
{
\Debug\Trace::out("rinsing. {$interval} seconds to go");
\Time\Interval::tick();
}
while ($interval--);
}
/**
* Pause/Cool Down Cycle
*/
protected function pause()
{
$interval = \Time\Interval::get
(
\Time\Interval::MINUTES_TO_SECONDS,
self::MINUTES_PAUSE
);
do
{
\Debug\Trace::out
(
"pause/cool down. {$interval} seconds to go"
);
\Time\Interval::tick();
}
while ($interval--);
}
}
Unit Test
<?php
/**
* Testing the washing machine appliance
*/
require_once '../base/time.php';
require_once '../base/debug.php';
require_once 'washing_machine.php';
$wm = new \Washing_Machine\Unit;
$wm->select_cycle($wm::CYCLE_PERMANENT_PRESS, $wm::LENGTH_SHORT);
$wm->start();
More
Tags: Bash,image,resize,imagemagick,php 5.3,google linux search,class constants, magic numbers
Short URL: http://sqb.in/F2t2