4. WaferLine 예광탄 – 4.2 WaferLine 클래스 정의 [Wafer 코팅 시뮬레이션]

안녕하세요. 언제나휴일입니다.

이번에는 WaferLine 클래스를 정의하는 실습입니다.

1. WaferLine 클래스 정의

WaferLine은 Wafer를 코팅하는 생산라인을 구현할 클래스입니다.

최종적으로 WaferLineLib.dll에 정의할 형식으로 public 접근 지정할게요.

    public class WaferLine
    {
    }

Wafer 코팅 공장에는 여러 개의 WaferLine이 있을 수 있을 거예요.

여기에서는 WaferLine을 구분하기 위한 일련 번호를 캡슐화할게요.

        public int No { get; }

생산 라인에 코팅할 때의 회전 속도와 코팅 액이 떨어지는 속도를 캡슐화합시다.

        public int Spin
        {
            get;
            set;
        }
        public int Drop
        {
            get;
            set;
        }

WaferLine에는 코팅에 사용할 Wafer와 코팅을 완료한 Wafer를 보관할 컬렉션이 필요하겠죠. 멤버 필드로 캡슐화할게요.

        List<Wafer> bwafers = new List<Wafer>();
        List<Wafer> awafers = new List<Wafer>();

WaferLine에서 하나의 Wafer를 코팅하면 bwafers에서 awafers에 옮겨야 하겠죠. 여기에서는 가장 최근에 코팅한 Wafer를 참조하는 속성을 제공할게요.

        public Wafer LastWafer
        {
            get
            {
                if (awafers.Count == 0)
                {
                    return null;
                }
                return awafers[awafers.Count - 1];
            }
        }

중앙 관제에서는 WaferLine의 상태를 흉내내어 표현해야 합니다.

Wafer를 하나 코팅하였을 때 코팅 전과 코팅 후의 Wafer 컬렉션의 개수를 공장의 실제 WaferLine과 동기화해 주어야 합니다. 이를 위해 코팅 완료하였을 때 개수를 동기화하기 위한 메서드를 제공할게요.

        public void EndCoating(int bwcnt, int awcnt)
        {
            while (bwafers.Count > bwcnt)
            {
                bwafers.RemoveAt(0);
            }
            while (awafers.Count < awcnt)
            {
                awafers.Add(null);
            }
        }

WaferLine에서 코팅하는 모습을 표현하기 위해 현재 코팅하는 Wafer를 참조하는 멤버 필드와 현재 코팅에 사용하는 코팅액의 남은 양을 멤버 필드로 캡슐화할게요.

        Wafer nwafer;
        int nowp;//1병은 1000쉘을 코팅할 수 있다.

그리고 외부에서 현재 코팅하는 Wafer를 참조하는 속성을 제공합시다.

        public Wafer Now { get { return nwafer; } }

코팅하기 전 Wafer 개수를 가져오기 할 수 있는 속성을 제공합시다.

        public int BWCnt
        {
            get { return bwafers.Count; }
        }

코팅한 Wafer 개수를 가져오기 할 수 있는 속성도 제공합시다.

        public int AWCnt
        {
            get { return awafers.Count; }
        }

코팅 액이 몇 병인지 기억하는 멤버도 캡슐화합시다.

        public int PCnt { get; set; }

현재 코팅에 사용하는 코탱 액이 몇 개의 쉘을 코팅할 수 있는지 남은 양을 기억하는 속성도 제공합시다. 이 멤버는 현재 코팅에 사용하는 한 병에서 남은 양으로 몇 개의 쉘을 코팅할 수 있는 지를 나타냅니다.

        public int NPcnt { get { return nowp; } }

코팅 액을 추가하는 메서드를 제공합시다. 여기에서는 최대 20병을 보관할 수 있게 하드코딩할게요.

보다 높은 품질로 구현하기 원하다면 보관할 수 있는 최대 병 수를 소프트코딩하세요.

        public int InPr(int pcnt)
        {
            int avail = 20 - PCnt;
            if (pcnt > avail)
            {
                pcnt = avail;
            }
            PCnt += pcnt;
            return PCnt;
        }

회전 속도와 코팅 액 낙하 속도를 설정하는 메서드를 제공합시다.

        public void SetSpin(int spin)
        {
            Spin = spin;
        }
        public void SetDrop(int drop)
        {
            Drop = drop;
        }

코팅할 때 품질은 랜덤하게 제공하는 것처럼 시뮬레이션하기 위해 랜덤 개체를 사용할게요.

        Random rand = new Random();

하나의 쉘을 코팅하는 메서드를 제공합시다.

        public bool Coating()
        {

코팅 액이 없으면 새로운 코팅액을 얻어옵니다. 하나의 병으로 코팅할 수 있는 쉘 수는 1000으로 하드코딩할게요.

            if (nowp == 0)
            {
                if (PCnt == 0)
                {
                    return false;
                }
                nowp = 1000;
                PCnt--;
            }

현재 코팅하는 Wafer가 null이라면 코팅하기 전 컬렉션에서 하나를 꺼내옵니다.

            if (nwafer == null)
            {
                if (bwafers.Count == 0)
                {
                    return false;
                }
                nwafer = bwafers[0];
                bwafers.RemoveAt(0);
            }

현재 코팅하는 Wafer에 하나의 쉘을 코팅하는 메서드를 호출하고 남은 코팅 액을 1 감소합니다.

            nwafer.Coating(rand.Next(70, 100));
            nowp--;

현재 코팅하는 Wafer에 다음 코팅 쉘로 이동을 시킵니다. 만약 실패하면 코팅을 완료한 것이므로 코팅 완료한 컬렉션으로 옮기는 작업을 수행합니다.

            if (nwafer.Increment() == false)
            {
                awafers.Add(nwafer);
                nwafer = null;
            }
            return true;
        }

ToString 메서드로 재정의합시다.

        public override string ToString()
        {
            return string.Format("WaferLine No:{0}", No);
        }

WaferLine에 코팅 완료한 Wafer를 열거할 수 있게 정의합시다.

    public class WaferLine : IEnumerable<Wafer>
    {
        ...생략...
        public IEnumerator<Wafer> GetEnumerator()
        {
            return awafers.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return awafers.GetEnumerator();
        }
    }

2. WaferLine 클래스 소스 코드

다음은 현재까지 작성한 WaferLine 클래스 전체 소스 코드입니다.

using System;
using System.Collections;
using System.Collections.Generic;
using WaferLineLib;

namespace WaferLineLib
{
    public class WaferLine : IEnumerable<Wafer>
    {
        public int No { get; }
        public int Spin
        {
            get;
            set;
        }
        public int Drop
        {
            get;
            set;
        }
        public WaferLine(int no)
        {
            No = no;
            Spin = 1000;
            Drop = 20;
        }
        List<Wafer> bwafers = new List<Wafer>();
        List<Wafer> awafers = new List<Wafer>();
        public Wafer LastWafer
        {
            get
            {
                if (awafers.Count == 0)
                {
                    return null;
                }
                return awafers[awafers.Count - 1];
            }
        }
        public void EndCoating(int bwcnt, int awcnt)
        {
            while (bwafers.Count > bwcnt)
            {
                bwafers.RemoveAt(0);
            }
            while (awafers.Count < awcnt)
            {
                awafers.Add(null);
            }
        }
        Wafer nwafer;
        int nowp;//1병은 1000쉘을 코팅할 수 있다.
        public Wafer Now { get { return nwafer; } }
        public int BWCnt
        {
            get { return bwafers.Count; }
        }
        public int InWafer(int wcnt)
        {
            int avail = 200 - BWCnt;
            if (wcnt > avail)
            {
                wcnt = avail;
            }
            for (int i = 0; i < wcnt; i++)
            {
                bwafers.Add(new Wafer());
            }
            return bwafers.Count;
        }
        public int AWCnt
        {
            get { return awafers.Count; }
        }
        public int PCnt { get; set; }
        public int NPcnt { get { return nowp; } }
        public int InPr(int pcnt)
        {
            int avail = 20 - PCnt;
            if (pcnt > avail)
            {
                pcnt = avail;
            }
            PCnt += pcnt;
            return PCnt;
        }
        public void SetSpin(int spin)
        {
            Spin = spin;
        }
        public void SetDrop(int drop)
        {
            Drop = drop;
        }
        Random rand = new Random();
        public bool Coating()
        {
            if (nowp == 0)
            {
                if (PCnt == 0)
                {
                    return false;
                }
                nowp = 1000;
                PCnt--;
            }
            if (nwafer == null)
            {
                if (bwafers.Count == 0)
                {
                    return false;
                }
                nwafer = bwafers[0];
                bwafers.RemoveAt(0);
            }
            nwafer.Coating(rand.Next(70, 100));
            nowp--;
            if (nwafer.Increment() == false)
            {
                awafers.Add(nwafer);
                nwafer = null;
            }
            return true;
        }
        public override string ToString()
        {
            return string.Format("WaferLine No:{0}", No);
        }

        public IEnumerator<Wafer> GetEnumerator()
        {
            return awafers.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return awafers.GetEnumerator();
        }
    }
}