机房重构经过近一个月的努力,终于成型了!在优化的过程中,注意到非常多的问题,今天就来总结一下上机用户的余额实时判断。
一、有什么用
大家应该对网吧的收费系统有所了解,如果你上机的时候充值了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();
//}
}
}
}
}
}
}
未完,还将更改!