機房重構之餘額實時判斷

曹祥銘-Charles發表於2018-09-02

機房重構經過近一個月的努力,終於成型了!在優化的過程中,注意到非常多的問題,今天就來總結一下上機使用者的餘額實時判斷。

一、有什麼用

大家應該對網咖的收費系統有所瞭解,如果你上機的時候充值了5元,網咖的收費是每小時5元,也就是你的金錢只可以上機一個小時,當快到一個小時的時候,系統會提醒你的餘額不足,讓你充值,如果不充值,就會自動下機!同理機房收費系統也需要同樣的機制,要不然,老闆會賠錢的!哈哈!
說說之前的版本,沒有這個判斷機制,一個卡片裡面有5元(大於最低金額),上機之後,如果使用者不下機,便可以一直上機,當使用者下機之後,會發現欠下鉅額的費用,這種機制已經不符合實際情況了。

二、思路

1、要實現實時的判斷使用者的餘額,那就需要一個計算使用者餘額的方法。
2、方法裡要注意對於不同型別的使用者,採用不同的收費政策。固定使用者和臨時使用者的收費策略不一樣。
3、這個方法要根據時間的間隔自動執行計算,並實時更新到使用者的餘額中。採用timer控制元件。
4、計算出使用者的實時餘額後,還不行!還需要一個判斷機制,判斷使用者的餘額是否充足。也就是將餘額的不同切位幾個不同的狀態,比如大於10元的狀態,不進行提示,不足10元的狀態,提醒使用者充值,然後不足5元的狀態,讓使用者下機。這種在不同的狀態間轉換的情況,讓我突然想起了設計模式中的狀態模式
2、結合設計模式中的狀態模式,很好的對使用者的餘額進行判斷,並進行不同狀態的提示!很方便!

三、實現

1、首先需要封裝一個計算餘額的方法

//定義計算固定使用者花費金額的方法,括號裡的是需要傳進來的引數,也就是基本收據中的引數。因為結算需要基本資料中的資料
public double RegularUser(out  double casttime, double Rate,double  PrepareTime,double unitTime,DateTime StartDate, DateTime StartTime, DateTime EndDate, DateTime EndTime)
        {
            double castcash=0;//定義花費金額引數,預設為0

            TimeSpan d1 = EndDate.Subtract(StartDate);//計算開始上機日期與下機日期間相隔的時間
            TimeSpan t1 = EndTime.Subtract(StartTime);//計算開始上機時間與下機時間相隔的時間
            double  z1 = d1.TotalMinutes + t1.TotalMinutes;//將兩個時間加起來,此時為總分鐘數
            casttime = Math.Ceiling(z1 / unitTime);//根據基本資料中的計算週期,計算幾個週期
            if (z1<=PrepareTime)//如果上機時間小於準備時間,就不收費
            {
                castcash = 0;
            }
            else//如果上機時間大於準備時間,計算
            {
               castcash =Rate * Math.Ceiling(z1 / unitTime);
               //ceiling函式是計算除法的一種,如果有餘數,則不管餘數多少都會近1.
            }
            return castcash;//返回計算好的消費時間

        }
        //臨時使用者的同理
        public double CasualUser(out double casttime,double tmpRate, double PrepareTime, double unitTime, DateTime StartDate, DateTime StartTime, DateTime EndDate, DateTime EndTime)
        {

            double castcash = 0;

            TimeSpan d1 = EndDate.Subtract(StartDate);
            TimeSpan t1 = EndTime.Subtract(StartTime);
            double z1 = d1.TotalMinutes + t1.TotalMinutes;
            casttime = Math.Ceiling(z1 / unitTime);
            if (z1 < PrepareTime)
            {
                castcash = 0;
            }
            else
            {
                castcash = tmpRate * Math.Ceiling(z1 / unitTime);

            }
            return castcash;
        }

2、狀態模式的建立
計算餘額的方法已經封裝好了,接下來建立狀態模式。
PS:我是按照設計模式的書,先把狀態模式基本的程式碼敲出來了,然後根據自己的需要進行的改變,這也能看出來,自己對狀態模式的應用不夠熟悉。

public abstract class State//建立一個抽象的狀態類
    {
        public abstract void Checkbalance(Context balance,int cardno,double  limitcash);//設定抽象方法和所需要的引數及其型別
    }
public  class Context//建立了一個環境類
    {
        private State current;//封裝欄位
        private double balance;//這個用來接收傳進來的金額
        private double limitcash;//接收傳進來的限制金額
        private int cardno;//傳進來的卡號
        public  double  Balance { get => balance; set => balance = value; }
        public int Cardno { get => cardno; set => cardno = value; }
        public double Limitcash { get => limitcash; set => limitcash = value; }






     public void SetState(State s)//設定狀態的方法
        {
            current = s;
        }
        public void  Checkbalance()//狀態模式中狀態轉換時執行的方法
        {

            current.Checkbalance(this,cardno,Limitcash);//接收當前的狀態,卡號,限制金額

        }
    }
     class ConcreteStateC : State//具體的狀態類C
    {

        //金額大於最低限制金額limitcash+4
        public override void Checkbalance(Context balance, int cardno, double limitcash)
        {


             double limitcashp = limitcash + 4;
            if (balance.Balance >limitcashp)//大於的話,不執行操作
            {

            }
            else
            {
                balance.SetState(new ConcreteStateA());如果小於這個值,則轉入A狀態
                balance.Checkbalance();
            }

        }

    }

    public   class ConcreteStateA:State//具體的狀態類A
    {

        //金額少於最小限制金額+4元,則提醒使用者充值!
        public override void Checkbalance(Context balance,int  cardno,double  limitcash)
        {

            double limitcashp = limitcash + 4;
            if (balance.Balance<=limitcashp&&balance .Balance>limitcash)
            {
                throw new Exception(cardno + "餘額已經不足"+limitcashp+"元,請充值!");
            }
            else
            {
                balance.SetState(new ConcreteStateC());
                balance.Checkbalance();
            }

        }

    }
    public class ConcreteStateB : State
    {
        public override void Checkbalance(Context balance,int cardno, double limitcash)
        {

            if (balance.Balance <= limitcash)
            {

                throw new Exception(cardno + "餘額已經不足"+limitcash+"元,即將下機!");

            }
            else
            {
                balance.SetState(new ConcreteStateA());
                balance.Checkbalance();
            }

        }
    }

3、在客戶端中實現。
要想將這個實現,需要你已經完成了下機!如果你已經完成了下機的方法,並建立了相應的層。接下來就開始實現。
首先需要新增一個timer控制元件

在窗體的load事件中新增一下程式碼。
timer1.Interval = 60000;//計時器的計算時間間隔,這裡設定1分鐘,也就每隔一分鐘觸發一次事件
timer1.Tick += new EventHandler(timer1_Tick);
timer1.Start();
 private void timer1_Tick(object sender, EventArgs e)
{
//例項化基本資料層,查詢基本資料
            Entity.OnlineInfo line = new Entity.OnlineInfo();
            Entity.BasicData basic = new Entity.BasicData();
            Facade.Basicdatafacade facade1 = new Facade.Basicdatafacade();
            DataTable res = facade1.Basicdatacheck();
            //將基本資料複製給對應引數
            double Rate = double.Parse(res.Rows[0][0].ToString());
            double tmpRate = double.Parse(res.Rows[0][1].ToString());
            double unitTime = double.Parse(res.Rows[0][2].ToString());
            double PrepareTime = double.Parse(res.Rows[0][3].ToString());
            double limitCash = double.Parse(res.Rows[0][4].ToString());

            Facade.Loginandexitfacade facade = new Facade.Loginandexitfacade();
//查詢online表,現在是否有上機的學生
            DataTable re = facade.Loginandexitpropro();
            if (re.Rows.Count != 0)//如果有執行此步
            {
            //獲取現在的時間作為下機時間日期

                DateTime Enddate = DateTime.Parse(DateTime.Now.ToShortDateString().ToString());
                DateTime Endtime = DateTime.Parse(DateTime.Now.ToShortTimeString());


                foreach (DataRow dt in re.Rows)
                {
                    Downmethos methos = new Downmethos();

                    if (dt["type"].ToString().Trim() == "固定使用者")
                    {
                        double casttime;

                        double castcash = methos.RegularUser(out casttime, Rate, PrepareTime, unitTime, Startdate, Starttime, Enddate, Endtime);
                        Entity.CardInfo card = new Entity.CardInfo();
                        Facade.RegisterFacade facade2 = new Facade.RegisterFacade();
                        card.Cardno = int.Parse(dt[0].ToString());
                        DateTime Startdate = DateTime.Parse(dt[2].ToString());
                        DateTime Starttime = DateTime.Parse(dt[3].ToString());
                        DataTable resu = facade2.checkcardno(card);
                        double Cash = double.Parse(resu.Rows[0][2].ToString());
                        double finalcash = Cash - castcash;
                        //更新實餘額    
                        Facade.Recharegefacade f = new Facade.Recharegefacade();
                        card.Cash = finalcash;
                        card.Ischeck = "未結賬";
                        f.Rechargecard(card);
                        try
                        {
                            Context c = new Context();
                            ConcreteStateB b = new ConcreteStateB();
                            c.SetState(b);
                            c.Cardno = int.Parse(dt[0].ToString());
                            c.Balance = finalcash;
                            c.Limitcash = int.Parse(res.Rows[0][4].ToString());
                            c.Checkbalance();
                        }
                        catch (Exception ex)
                        {

                            DialogResult resut = MessageBox.Show(ex.Message, "餘額提醒", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                        }
                        finally
                        {


                            //Entity.sState state = new Entity.sState();
                            //Facade.statefacade sta = new Facade.statefacade();
                            //DataTable states = sta.sState();
                            //if (states.Rows[0][0].ToString().Trim() == "正在維護")
                            //{
                            //    DialogResult result = MessageBox.Show("系統正在維護,您即將下線!", "系統維護", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            //    if (result == DialogResult.OK)
                            //    {

                            if (finalcash <= limitCash)
                            {
                                Entity.downline downline = new Entity.downline();
                                Facade.DownLinefacade faca = new Facade.DownLinefacade();
                                downline.Cardno = int.Parse(dt[0].ToString());
                                downline.Consumetime = casttime;
                                downline.Consume = castcash;
                                downline.Offdate = DateTime.Parse(DateTime.Now.ToShortDateString());
                                downline.Offtime = DateTime.Parse(DateTime.Now.ToShortTimeString());
                                downline.Status = "true";
                                downline.Cash = finalcash;
                                downline.Computer = System.Environment.MachineName;
                                downline.Ischeck = "未結賬";
                                faca.downLine(downline);
                            }
                            else
                            {

                            }
                        }
                    }
                    else
                    {
                        double casttime;

                        double castcash = methos.CasualUser(out casttime, Rate, PrepareTime, unitTime, Startdate, Starttime, Enddate, Endtime);
                        Entity.CardInfo card = new Entity.CardInfo();
                        Facade.RegisterFacade facade2 = new Facade.RegisterFacade();
                        card.Cardno = int.Parse(dt[0].ToString());
                        DataTable resu = facade2.checkcardno(card);
                        double Cash = double.Parse(resu.Rows[0][2].ToString());
                        double finalcash = Cash - castcash;
                        //更新實餘額    
                        Facade.Recharegefacade f = new Facade.Recharegefacade();
                        card.Cash = finalcash;
                        card.Ischeck = "未結賬";
                        f.Rechargecard(card);
                        try
                        {
                            Context c = new Context();
                            ConcreteStateB b = new ConcreteStateB();
                            c.SetState(b);
                            c.Cardno = int.Parse(dt[0].ToString());
                            c.Balance = finalcash;
                            c.Limitcash = int.Parse(res.Rows[0][4].ToString());
                            c.Checkbalance();
                        }
                        catch (Exception ex)
                        {

                            DialogResult resut = MessageBox.Show(ex.Message, "餘額提醒", MessageBoxButtons.OK, MessageBoxIcon.Warning);

                        }
                        finally
                        {


                            if (finalcash <= limitCash)
                            {
                                Entity.sState state = new Entity.sState();
                                Facade.statefacade sta = new Facade.statefacade();
                                DataTable states = sta.sState();
                                Entity.downline downline = new Entity.downline();
                                Facade.DownLinefacade faca = new Facade.DownLinefacade();
                                downline.Cardno = int.Parse(dt[0].ToString());
                                downline.Consumetime = casttime;
                                downline.Consume = castcash;
                                downline.Offdate = DateTime.Parse(DateTime.Now.ToShortDateString());
                                downline.Offtime = DateTime.Parse(DateTime.Now.ToShortTimeString());
                                downline.Status = "true";
                                downline.Cash = finalcash;
                                downline.Computer = System.Environment.MachineName;
                                downline.Ischeck = "未結賬";
                                faca.downLine(downline);

                                //lblcastcash.Text = castcash.ToString();
                                //lblcasttime.Text = casttime.ToString();
                                //lbldowndate.Text = DateTime.Now.ToShortDateString();
                                //lbldowntime.Text = DateTime.Now.ToShortTimeString();

                                //}

                            }


                        }
                    }

                }
            }


        }

未完,還將更改!

相關文章