본문 바로가기

후쿠오카 개발자모임/주차장 관리시스템

[C#] 주차장 관리시스템 #2

반응형

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

전체 공정을 생각해 보았을 때, 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에서 다운로드할 수 있다.

반응형