오늘은 입고/출고 기능에 대해서 이어서 글을 써보고자 한다.

전체 공정을 생각해 보았을 때, 1-2주 정도면 필요한 최소의 기능을 장착할 수 있다고 생각한다.

간단한 기능 구현을 하고,

추후에 어떤 식으로 데이터를 관리할 것인지

csv / txt / access / excel 등등.. DataBase를 사용하지 않더라도 얼마든지 가능하므로 조급 해하지 말자.

 

우리가 지난번 위의 그림과 같이 시간을 출력하는 기능까지를 구현해두었다.

이제는 이어서 입고 기능 / 출고 기능을 구현할 차례이다.

 

우선, 첫 번째 생각할 것이

입고 시간 / 출고시간을 버튼 클릭 이벤트와 동시에 어딘가에 보여줘야 한다는 것이다.

코드는 아래와 같이 간단히 구성한다.

        /// <summary>
        /// 입고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnIn1_Click(object sender, EventArgs e)
        {
            lblIn1.Text = DateTime.Now.ToString("HH:mm");
        }

        /// <summary>
        /// 출고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOut1_Click(object sender, EventArgs e)
        {
            lblOut1.Text = DateTime.Now.ToString("HH:mm");
        }

단순히 버튼 옆에 lblIn1 / lblOut1이라는 라벨을 만들어두고

그 값으로 

  입고 버튼 클릭 시에는 lnlIn1의 텍스트 값으로 현재시간의 [시간:분]

  출고 버튼 클릭 시에는 lnlOut1의 텍스트 값으로 현재시간의 [시간:분]

을 보여준다.

 

자.. 실행해서 버튼을 한번 눌러보도록 하자.

 

입고버튼클릭

 

1분 경과 후... 50분이 되었을 때~ 출고 버튼 클릭

 

입고 시간 / 출고시간이 시간:분으로 출력되는 것을 확인할 수 있다.

 

이제는 둘의 차이가 몇 분이 났으며,

30분당 2,000원으로 보았을 때 결국 계산해야 할 금액이 얼마가 필요한 것인지를

알아보도록 하자

 

입고와 출고의 DateTime을 보존하여 보다 편하게 계산하기 위해서 전체 코드를 조금 수정하기로 한다.

전체 코드는 다음과 같다.

using System;
using System.Windows.Forms;

namespace ParkingManagement
{
    public partial class frmParkingManagement : Form
    {
        /// <summary>
        /// 주차장1의 인/아웃 시간관리
        /// </summary>
        private DateTime parking1_In;
        private DateTime parking1_Out;

        /// <summary>
        /// 컨스트럭터
        /// </summary>
        public frmParkingManagement()
        {
            InitializeComponent();
        }
        
        /// <summary>
        /// 입고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnIn1_Click(object sender, EventArgs e)
        {
            parking1_In = DateTime.Now;
            lblIn1.Text = parking1_In.ToString("HH:mm");
        }

        /// <summary>
        /// 출고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOut1_Click(object sender, EventArgs e)
        {
            parking1_Out = DateTime.Now;
            lblOut1.Text = parking1_Out.ToString("HH:mm");

            // (주차시간 / 단위시간) * 단위금액
            TimeSpan ts = parking1_Out - parking1_In;
        }
        
        /// <summary>
        /// 화면로드이벤트
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmParkingManagement_Load(object sender, EventArgs e)
        {
            timerMain.Start();
        }

        /// <summary>
        /// Timer Tick 이벤트
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerMain_Tick(object sender, EventArgs e)
        {
            lblNowTime.Text = DateTime.Now.ToString("HH:mm:ss");
        }
    }
}

 

바뀌는 부분을 설명하자면,

        /// <summary>
        /// 주차장1의 인/아웃 시간관리
        /// </summary>
        private DateTime parking1_In;
        private DateTime parking1_Out;

주차장 1의 인/아웃 버튼 클릭 시에 사용될 DateTime 즉, 버튼 클릭 이벤트 당시의 시간을 기록하여 담고 있을 공간을 지역변수로 외부 선언하였고

인/아웃의 버튼 클릭이벤트를 아래와 같이 바꾸어주었다.

        /// <summary>
        /// 입고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnIn1_Click(object sender, EventArgs e)
        {
            parking1_In = DateTime.Now;
            lblIn1.Text = parking1_In.ToString("HH:mm");
        }

        /// <summary>
        /// 출고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOut1_Click(object sender, EventArgs e)
        {
            parking1_Out = DateTime.Now;
            lblOut1.Text = parking1_Out.ToString("HH:mm");

            // (주차시간 / 단위시간) * 단위금액
            TimeSpan ts = parking1_Out - parking1_In;
        }
        

 

이유는, 아웃(출고) 이벤트를 수행할 때에 시간을 기록하고 있으므로,

따로 또 다른 형 변환을 시키지 않고, 처음 이벤트가 실행될 때에 값을 그대로 저장해두면 추가로 허튼짓?을 안 해도 되기 때문이다. 

※물론, 이렇게 하는 것이 100% 맞다는 것은 아니므로 형 변환을 통해서 값을 계산하여도 좋다.

 

        /// <summary>
        /// 출고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOut1_Click(object sender, EventArgs e)
        {
            parking1_Out = DateTime.Now.AddMinutes(41);
            lblOut1.Text = parking1_Out.ToString("HH:mm");

            // 주차시간계산
            TimeSpan ts = parking1_Out - parking1_In;
            CalcSum(ts);
        }

        /// <summary>
        /// 주차요금계산
        /// </summary>
        /// <param name="ts">시간차</param>
        /// <returns>요금계산결과</returns>
        private string CalcSum(TimeSpan ts)
        {
            return (Math.Ceiling(Convert.ToDecimal(ts.Minutes / Convert.ToDecimal(txtBaseTime.Text))) 
                * Convert.ToInt32(txtBaseMoney.Text)).ToString();
        }

내 나름대로 계산 모듈을 구현하면 위와 같이 된다.

출고 버튼 클릭이벤트에서는 지역변수에서 가지고 있던 값을 통해서 시간 차이를 구현하였고,

 

추차요금계산 메서드에서는 좀 난잡하지만, 시간차에 따른 요금계산을 실시하고 있다.

우선, 요금계산에 대해서 천천히 하나하나 살펴보도록 하자.

 

        /// <summary>
        /// 주차요금계산
        /// </summary>
        /// <param name="ts">시간차</param>
        /// <returns>요금계산결과</returns>
        private string CalcSum(TimeSpan ts)
        {
            return (Math.Ceiling(Convert.ToDecimal(ts.Minutes / Convert.ToDecimal(txtBaseTime.Text))) 
                * Convert.ToInt32(txtBaseMoney.Text)).ToString();
        }

 

Math.Ceiling이라는 녀석은 반올림/올림의 올림이다.

더 자시한 내용은 아래의 링크를 참고하자.

 

Math.Ceiling 메서드 (System)

지정된 수보다 크거나 같은 최소 정수 값을 반환합니다.Returns the smallest integral value greater than or equal to the specified number.

docs.microsoft.com

txtBaseTime.Text 베이스타임을 Decimal형태로 바꿔주고 시간차로(분으로 환산) 나누어준다.

    시간차 / 베이스타임

의 수식인셈이다.

 

이것은 소수점을 가지는 값이 되므로(물론, 나누어서 딱 떨어져서. 0 이 될 때도 있다)

Convert.ToDecimal로 전체 값을 형 변환해줄 필요가 있다.

 

그리고 그 값을 Ceiling으로 올림 처리해준다.

왜, 여기서 올림이냐??

 

단위 시간이 30분이고 2,000원을 요금으로 받겠다고 하였을 때로 가정하면 

   1분 ~ 30분까지의 주차요금은 2,000원

  31분 ~ 60분까지의 주차요금은 4,000원 

이 되어야 하기 때문이다.

 

여기까지 정리한 최종 소스는 아래와 같다.

using System;
using System.Windows.Forms;

namespace ParkingManagement
{
    public partial class frmParkingManagement : Form
    {
        /// <summary>
        /// 주차장1의 인/아웃 시간관리
        /// </summary>
        private DateTime parking1_In;
        private DateTime parking1_Out;

        /// <summary>
        /// 컨스트럭터
        /// </summary>
        public frmParkingManagement()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 입고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnIn1_Click(object sender, EventArgs e)
        {
            parking1_In = DateTime.Now;
            lblIn1.Text = parking1_In.ToString("HH:mm");
        }

        /// <summary>
        /// 출고이벤트_1
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOut1_Click(object sender, EventArgs e)
        {
            parking1_Out = DateTime.Now.AddMinutes(41);
            lblOut1.Text = parking1_Out.ToString("HH:mm");

            // 주차시간계산
            lblSum1.Text = CalcSum(parking1_Out - parking1_In);
        }

        /// <summary>
        /// 주차요금계산
        /// </summary>
        /// <param name="ts">시간차</param>
        /// <returns>요금계산결과</returns>
        private string CalcSum(TimeSpan ts)
        {
            return (Math.Ceiling(Convert.ToDecimal(ts.Minutes / Convert.ToDecimal(txtBaseTime.Text)))
                * Convert.ToInt32(txtBaseMoney.Text)).ToString();
        }

        /// <summary>
        /// 화면로드이벤트
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmParkingManagement_Load(object sender, EventArgs e)
        {
            timerMain.Start();
        }

        /// <summary>
        /// Timer Tick 이벤트
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerMain_Tick(object sender, EventArgs e)
        {
            lblNowTime.Text = DateTime.Now.ToString("HH:mm:ss");
        }
    }
}

 

 

또한 현재 진행 내용에 대해서는 

github에 소스를 올려두고, 하나씩 하나씩 기능도 같이 추가해 나아가고자 한다.

 

github.com/sungmanko/ParkingManagement

 

sungmanko/ParkingManagement

ParkingManagement. Contribute to sungmanko/ParkingManagement development by creating an account on GitHub.

github.com

소스는 위의 github에서 다운로드할 수 있다.

교육을 진행하면서 필요한것들과 느낀점들을 정리해본다.

개별적인 학습을 목적

 

<주제>

주차장관리시스템

 

<생각할것>

흔히 우리가 목격하게되는 주차장 시스템은 어떤식으로 이루어져있는가?

 

1. 입고

2. 정산

3. 금액을 지불

4. 출고

 

무인시스템의 주차장 관리 시스템을 만들어보도록한다.

 

폼의 디자인

주차관리시스템

 

입고버튼 : 차량이 입고되었을때의 이벤트

 - 라벨 = 입고시간

출고버튼 : 차량이 출고되었을때의 이벤트

 - 라벨 = 현재시간과 입고시간을 계산해서 몇분 주차중인지를 보여줌

현재금액 : 단위시간과 더불어서 현재 정산해야할 금액을 리얼타임표시 (1분단위 갱신)

 

타이머배치 : 화면상은 보이지않지만, 현재시간과 입고시간의 차이를 이용해서 금액을 보여줘야하므로 디자이너에 하나 추가해준다. (코드상에 넣어도 무관)

 

타이머 인터벌1000(1초)

        /// <summary>
        /// 화면로드이벤트
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void frmParkingManagement_Load(object sender, EventArgs e)
        {
            timerMain.Start();
        }

frmParkingManagement_Load 이벤트에서 타이머를 스타트해준다.

 

그리고 여기까지 준비가 되었으므로

타이머의 Tick 이벤트에 아래와같이 코드를 추가해준다.

        /// <summary>
        /// Timer Tick 이벤트
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerMain_Tick(object sender, EventArgs e)
        {
            lblNowTime.Text = DateTime.Now.ToString("HH:mm:ss");
        }

<참고> 

 

Timer 클래스 (System.Windows.Forms)

사용자가 정의한 간격마다 이벤트를 발생시키는 타이머를 구현합니다.Implements a timer that raises an event at user-defined intervals. 이 타이머는 Windows Forms 애플리케이션에서 사용할 수 있도록 최적화되었

docs.microsoft.com

DateTime.Now 는 현재의 시스템시간을 나타내는것이고 

ToString("HH:mm:ss"); 이부분은 시스템시간 전체에서 HH는 시간 / mm 은 분 / ss 는 초 를 출력하겠다는 설정이다.

 

 

DateTime 구조체 (System)

일반적으로 날짜와 시간으로 표시된 시간을 나타냅니다.Represents an instant in time, typically expressed as a date and time of day.

docs.microsoft.com

 

 

여기까지 했으면 한번 실행을 해보자.

아래와같이 될것이다.

 

 

지금까지 만든내용의 실행결과

일단 

여기까지 완성되었다.

 

다음글에서는 입고기능 / 출고기능 에 대해서 다루어 보도록 하겠다.

 

 

소스는 아래에서 최신판을 다운받을수있습니다.

 

sungmanko/ParkingManagement

ParkingManagement. Contribute to sungmanko/ParkingManagement development by creating an account on GitHub.

github.com

 

+ Recent posts