一、前言:
- 这几个星期接触了电信计费的问题,这几次作业题量都相对来说不大,难度相对之前的点线形系列较低。
- 通过这几次的题目集重新巩固了正则表达式,以及继承与多态的运用。
- 第一次的题目集只要求写了座机计费,通过座机的区号判断所在位置,从而判断应该采用什么计费方式。
- 第二次的题目集增加了手机计费,不仅需要判断计费方式,还要判断拨打与接听的是手机还是座机。
- 第三次的题目集增加了短信计费,通过所在位置以及区号判断发短信价格。
- 三道题目,联系十分紧密,迭代关系,第一道题的源码第二题第三题都能够直接用上,再按照要求修改。
二、设计与分析:
7-1 电信计费系列1-座机计费
实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
输入格式:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。
输出格式:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
建议类图:
参见图1、2、3,可根据理解自行调整:
图1
图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。
UserRecords是用户记录类,保存用户各种通话、短信的记录,
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
图2
图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。
CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是
座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
(提示:可以从UserRecords类中获取各种类型的callRecords)。
后续扩展说明:
后续题目集将增加手机用户,手机用户的计费方式中除了与座机计费类似的主叫通话费之外,还包含市外接听电话的漫游费以及发短信的费用。在本题的设计时可统一考虑。
通话记录中,手机需要额外记录拨打/接听的地点的区号,比如:
座机打手机:t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
短信的格式:m-主叫号码,接收号码,短信内容
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you
输入样例:
在这里给出一组输入。例如:
u-079186300001 0
t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25
end
输出样例:
在这里给出相应的输出。例如:
079186300001 3.0 77.0
源码:
import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.Date; import java.util.ArrayList; public class Main { public static void main(String[] args) throws ParseException { Infor infor = new Infor(); infor.input(); } } class Infor{ public void input() throws ParseException { Scanner in = new Scanner(System.in); String[] x = new String[1000]; ArrayList<User> users = new ArrayList<>();//创建一个存储用户的数组 Map<String, User> mm = new HashMap<>(); int i = 0 , count = 0; String [] str = new String[1000]; for(i = 0 ; i < 1000; i++) { x[i] = in.nextLine(); String []a = x[i].split(" "); if(numberBegin(x[i])){//注册账户正确 String []num = a[0].split("-"); User user = new User(num[1]); for(int aa = 0 ;aa <= i ;aa++) { if (x[i].equals(x[aa])&&i!=0 &&i!= aa) break; if (aa == i) { users.add(user);//创建了一个用户 mm.put(num[1], user); str[count] = num[1]; count++; } } } if(numberCallRecordBegin(a[0]) ){//通话记录格式正确 int j = 0,pos = 0; String [] b = x[i].split(" "); String [] c = b[0].split("-");//把第一个拆分了 if( numberEnd(b[1]) && isDate(b[2]) && isTime(b[3]) && isDate(b[4]) &&isTime(b[5])){//全部格式正确 for(j = 0; j < 1000;j++){ if(c[1].equals(str[j])) { pos++; break; } } CallRecord callRecord = new CallRecord(); int result = 0;//开始地址 String endPlace = ""; result = getIsWhere(b[1]); switch(result){ case 1: endPlace = "市内";break; case 2: endPlace = "省内";break; case 3: endPlace = "国内";break; } String startDate = b[2] + " " + b[3]; String endDate = b[4] + " " + b[5]; SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date date1 = simpleDateFormat.parse(startDate); Date date2 = simpleDateFormat.parse(endDate); callRecord.setStartTime(date1); callRecord.setEndTime(date2); callRecord.setCallingNumber(c[1]); callRecord.setAnswerNumber(b[1]); callRecord.setCallingAddressAreaCode("南昌"); callRecord.setAnswerAddressAreaCode(endPlace); if(pos == 1) switch (result){ case 1:users.get(j).getUserRecords().addCallingInCityRecords(callRecord);break; case 2:users.get(j).getUserRecords().addCallingInProvinceRecords(callRecord);break; case 3:users.get(j).getUserRecords().addCallingInLandRecords(callRecord);break; } } } if(x[i].equals("end")) break; } for(User user : mm.values()){ System.out.println(user.getNumber() +" "+ user.calCost() +" "+ (80 - user.calCost()) ); } } public boolean numberBegin(String a){//注册的账号的内容 if(a.matches("^[u][-][0-9]{11}[0-9]{0,1}[ ][0]")) return true; else return false; } public boolean numberCallRecordBegin(String a){//通话记录的格式是否正确 if(a.matches("^[t][-][0-9]{10,12}")) return true; else return false; } public boolean numberEnd(String a){//判断是打电话的内容 if(a.matches("^[0-9]{10,12}")) return true; else return false; } public boolean isDate(String str) {//判断日期的合法性 boolean result = true; SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd"); try { format.setLenient(false); format.parse(str); }catch (Exception e){ result = false; } String [] a = str.split("[.]"); if(a[1].matches("^([1-9]|[1][0-2])") && a[2].matches("^([0][1-9]|[1-9]|[1-3][0-9])")) result = true; else result = false; return result; } public boolean isTime(String str){//判断时间是否合法 boolean result = true; SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); try { format.setLenient(false); format.parse(str); }catch (Exception e){ result = false; } String []a = str.split("[:]"); if(a[0].matches("^([0][0-9]|[1][0-9]|[2][0-3])") && a[1].matches("^([0][0-9]|[1-5][0-9])") &&a[2].matches("^([0][0-9]|[1-5][0-9])") ) result = true; else result = false; return result; } public int getIsWhere(String str){ int result = 0; if(str.matches("^[0][7][9][1][0-9]{7,8}"))//市内电话 result = 1; else if(str.matches("(([0][7][9][0-9][0-9]{7,8}))"))//省内电话 result = 2; else if(str.matches("[0][7][0][1][0-9]{7,8}"))//省内电话 result = 2; else//国内电话 result = 3; return result; } } class User { private UserRecords userRecords = new UserRecords();//用户记录 private double balance = 100;//余额 private ChargeMode chargeMode ;//计费方式 private String number = "";//号码 public User(String number) { this.number = number; this.chargeMode = new LandlinePhoneCharging(); } public double calBalance(){//总计剩余余额 return (balance - calCost() - chargeMode.getMonthlyRent()); } public double calCost(){//总计消费余额,这里面没有信息消费 double cost = chargeMode.calCost(userRecords); return cost; } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public ChargeMode getChargeMode() { return chargeMode; } public void setChargeMode(ChargeMode chargeMode) { this.chargeMode = chargeMode; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } } class UserRecords { private ArrayList<CallRecord> callingInCityRecords = new ArrayList<>(); private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<>(); private ArrayList<CallRecord> callingInLandRecords = new ArrayList<>(); private ArrayList<CallRecord> answerInCityRecords = new ArrayList<>(); private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<>(); private ArrayList<CallRecord> answerInLandRecords = new ArrayList<>(); private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<>(); private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<>(); public UserRecords() { } public void addCallingInCityRecords(CallRecord callRecord){ callingInCityRecords.add(callRecord); } public void addCallingInProvinceRecords(CallRecord callRecord){ callingInProvinceRecords.add(callRecord); } public void addCallingInLandRecords (CallRecord callRecord){ callingInLandRecords.add(callRecord); } public void addAnswerInCityRecords(CallRecord callRecord){ answerInCityRecords.add(callRecord); } public void addAnswerInProvinceRecords(CallRecord callRecord){ answerInLandRecords.add(callRecord); } public void answerInLandRecords (CallRecord callRecord){ answerInLandRecords.add(callRecord); } public void addSendMessageRecords(MessageRecord messageRecord){ sendMessageRecords.add(messageRecord); } public void addReceiveMessageRecords(MessageRecord messageRecord){ receiveMessageRecords.add(messageRecord); } public ArrayList<CallRecord> getCallingInCityRecords() { return callingInCityRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords() { return callingInProvinceRecords; } public ArrayList<CallRecord> getCallingInLandRecords() { return callingInLandRecords; } public ArrayList<CallRecord> getAnswerInCityRecords() { return answerInCityRecords; } public ArrayList<CallRecord> getAnswerInProvinceRecords() { return answerInProvinceRecords; } public ArrayList<CallRecord> getAnswerInLandRecords() { return answerInLandRecords; } public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } } abstract class CommunicationRecord{ protected String callingNumber; protected String answerNumber; public CommunicationRecord(){ } public String getCallingNumber() { return callingNumber; } public void setCallingNumber(String callingNumber) { this.callingNumber = callingNumber; } public String getAnswerNumber() { return answerNumber; } public void setAnswerNumber(String answerNumber) { this.answerNumber = answerNumber; } } class CallRecord extends CommunicationRecord{ private Date startTime; private Date endTime; private String callingAddressAreaCode; private String answerAddressAreaCode; public CallRecord(){ } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public String getCallingAddressAreaCode() { return callingAddressAreaCode; } public void setCallingAddressAreaCode(String callingAddressAreaCode) { this.callingAddressAreaCode = callingAddressAreaCode; } public String getAnswerAddressAreaCode() { return answerAddressAreaCode; } public void setAnswerAddressAreaCode(String answerAddressAreaCode) { this.answerAddressAreaCode = answerAddressAreaCode; } //还有继承的方法没有实现 } class MessageRecord extends CommunicationRecord{ private String message; public MessageRecord(){ } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } //还有继承的方法没有实现 } abstract class ChargeMode { private ArrayList<ChargeRule> chargeRules = new ArrayList<>(); private LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule(); private LandPhoneInLandRule landPhoneInLandRule = new LandPhoneInLandRule(); private LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule(); public ChargeMode(){ chargeRules.add(landPhoneInCityRule); chargeRules.add(landPhoneInProvinceRule); chargeRules.add(landPhoneInLandRule); } public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { this.chargeRules = chargeRules; } public abstract double calCost(UserRecords userRecords); public abstract double getMonthlyRent(); } class LandlinePhoneCharging extends ChargeMode{ private double monthlyRent = 20; public LandlinePhoneCharging(){ } @Override public double calCost(UserRecords userRecords) { //数据中有起始时间和终止时间 //打电话的地址和接电话的地址 //需要转换成数字 //需要 double cost1 = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()); double cost2 = getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()); double cost3 = getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()); return cost1 + cost2 + cost3; } @Override public double getMonthlyRent() { return monthlyRent; } } abstract class ChargeRule { public abstract double calCost(ArrayList<CallRecord> callRecord); } abstract class CallChargeRule extends ChargeRule{ public abstract double calCost(ArrayList<CallRecord> callRecord); } class LandPhoneInLandRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecord) {//这是一个数组 double second = 0,cost = 0,second1; for (int i = 0;i < callRecord.size() ;i++){ second = -(callRecord.get(i).getStartTime().getTime()-callRecord.get(i).getEndTime().getTime())/1000/60.0; DecimalFormat df = new DecimalFormat("0"); second1 = Double.parseDouble(df.format(second)); if(second > second1) second = second1 + 1; else second = second1; cost = cost + second * 0.6; DecimalFormat df1 = new DecimalFormat("0.0"); cost = Double.parseDouble(df1.format(cost)); } return cost; } } class LandPhoneInProvinceRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecord) { double second = 0,cost = 0,second1 = 0; for (int i = 0;i < callRecord.size() ;i++){ second = -(callRecord.get(i).getStartTime().getTime()-callRecord.get(i).getEndTime().getTime())/1000/60.0; DecimalFormat df = new DecimalFormat("0"); second1 = Double.parseDouble(df.format(second)); if(second > second1) second = second1 + 1; else second = second1; cost = cost + second * 0.3; DecimalFormat df1 = new DecimalFormat("0.0"); cost = Double.parseDouble(df1.format(cost)); } return cost; } } class LandPhoneInCityRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecord) { double second = 0,cost = 0,second1 = 0; for (int i = 0;i < callRecord.size() ;i++){ second = -(callRecord.get(i).getStartTime().getTime()-callRecord.get(i).getEndTime().getTime())/1000/60.0; DecimalFormat df = new DecimalFormat("0"); second1 = Double.parseDouble(df.format(second)); if(second > second1) second = second1 ; else second = second1; cost = cost + second * 0.1; DecimalFormat df1 = new DecimalFormat("0.0"); cost = Double.parseDouble(df1.format(cost)); } return cost; } }View Code
SourceMonitor报表如下:
7-1 电信计费系列2-手机+座机计费
实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
1、针对市内座机用户采用的计费方式(与电信计费系列1内容相同):
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
假设本市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
2、针对手机用户采用实时计费方式:
月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟;
注:被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
输入:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,含手机和座机用户
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题在电信计费系列1基础上增加类型1-手机实时计费。
手机设置0或者座机设置成1,此种错误可不做判断。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
输入格式增加手机接打电话以及收发短信的格式,手机接打电话的信息除了号码之外需要额外记录拨打/接听的地点的区号,比如:
座机打手机:
t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:
t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
建议类图:
参见图1、2、3:
图1
图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。
UserRecords是用户记录类,保存用户各种通话、短信的记录,
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
图2
图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
输入样例:
在这里给出一组输入。例如:
u-13811111111 1
t-13811111111 0791 13811111110 020 2022.1.3 08:00:00 2022.1.3 08:09:20
end
输出样例:
在这里给出相应的输出。例如:
13811111111 3.0 82.0
源代码:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Main { public static void main(String[] args) throws ParseException { LandPhonelnlandRule landPhonelnlandRule = new LandPhonelnlandRule(); LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule(); LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule(); LandlinePhoneCharging landlinePhoneCharging = new LandlinePhoneCharging(); landlinePhoneCharging.getChargeRules().add(landPhoneInCityRule); landlinePhoneCharging.getChargeRules().add(landPhoneInProvinceRule); landlinePhoneCharging.getChargeRules().add(landPhonelnlandRule); MobilePhoneInCityRule mobilePhoneInCityRule = new MobilePhoneInCityRule(); MobilePhoneInProvinceRule mobilePhoneInProvinceRule = new MobilePhoneInProvinceRule(); MobilePhoneInLandRule mobilePhoneInLandRule = new MobilePhoneInLandRule(); MobilePhoneCallOutCityRule mobilePhoneCallOutCityRule = new MobilePhoneCallOutCityRule(); MobilePhoneCallOutProvince mobilePhoneCallOutProvince = new MobilePhoneCallOutProvince(); MobilePhoneAnswerOutProvince mobilePhoneAnswerOutProvince = new MobilePhoneAnswerOutProvince(); MobilePhoneCharging mobilePhoneCharging = new MobilePhoneCharging(); mobilePhoneCharging.getChargeRules1().add(mobilePhoneInCityRule); mobilePhoneCharging.getChargeRules1().add(mobilePhoneInProvinceRule); mobilePhoneCharging.getChargeRules1().add(mobilePhoneInLandRule); mobilePhoneCharging.getChargeRules1().add(mobilePhoneCallOutCityRule); mobilePhoneCharging.getChargeRules1().add(mobilePhoneCallOutProvince); mobilePhoneCharging.getChargeRules1().add(mobilePhoneAnswerOutProvince); ArrayList<User> UserList = new ArrayList<>(); ArrayList<User> User1List = new ArrayList<>(); Scanner in = new Scanner(System.in); String m = in.nextLine(); int flag; while (!m.equals("end")) { Judge judge = new Judge(); if (judge.isUserInformation(m)) { String regex = "(0791)[\\d]{7,8}"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(m); while (matcher.find()) { flag = 0; for (User user : UserList ) { if (user.getNumber().equals(matcher.group(0))) { flag = 1; break; } } if (flag == 0) { UserList.add(new User(matcher.group(0))); } } } if (judge.isUser1Information(m)) { String regex = "[\\d][\\d]{10}"; Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(m); while (matcher.find()) { flag = 0; for (User user : User1List ) { if (user.getNumber().equals(matcher.group(0))) { flag = 1; break; } } if (flag == 0) { User1List.add(new User(matcher.group(0))); } } } if (judge.isCallingInformation(m)) { String[] a = m.split(" "); try { SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime = format.parse(a[2] + " " + a[3]); Date endTime = format.parse(a[4] + " " + a[5]); for (User user : UserList ) { if (user.getNumber().equals(a[0].substring(2))) { if (judge.isInCityCode(a[1].substring(0, 4))) { user.getUserRecords().addCallingInCityRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[1].substring(0, 4))); } else if (judge.isInProvinceCode(a[1].substring(0, 4))) { user.getUserRecords().addCallingInProvinceRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[1].substring(0, 4))); } else { user.getUserRecords().addCallingInLandRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[1].substring(0, 4))); } } } } catch (ParseException e) { e.printStackTrace(); } } if (judge.isCalling01Information(m)) { String[] a = m.split(" "); try { SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime = format.parse(a[3] + " " + a[4]); Date endTime = format.parse(a[5] + " " + a[6]); for (User user : UserList ) { if (user.getNumber().equals(a[0].substring(2))) { if (judge.isInCityCode(a[2])) { user.getUserRecords().addCallingInCityRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[2])); } else if (judge.isInProvinceCode(a[2])) { user.getUserRecords().addCallingInProvinceRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[2])); } else { user.getUserRecords().addCallingInLandRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[2])); } } } for (User user : User1List ) { if (user.getNumber().equals(a[1])) { if (judge.isAnswerInCityCode1(a[2])) { ; } else if (judge.isAnswerInProvinceCode1(a[2])) { ; } else { user.getUserRecords().addAnswerInLandRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[2])); } } } } catch (ParseException e) { e.printStackTrace(); } } if (judge.isCalling11Information(m)) { String[] a = m.split(" "); try { SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime = format.parse(a[4] + " " + a[5]); Date endTime = format.parse(a[6] + " " + a[7]); for (User user : User1List ) { if (user.getNumber().equals(a[0].substring(2))) { if (judge.isCallInCity(a[1])) { if (judge.isInCityCode(a[3])) { user.getUserRecords().addCallingInCityRecords(new CallRecord(startTime, endTime, a[1], a[3])); } else if (judge.isInProvinceCode(a[3])) { user.getUserRecords().addCallingInProvinceRecords(new CallRecord(startTime, endTime, a[1], a[3])); } else { user.getUserRecords().addCallingInLandRecords(new CallRecord(startTime, endTime, a[1], a[3])); } } else if (judge.isInProvinceCode(a[1])) { user.getUserRecords().addManYouInProvinceRecords(new CallRecord(startTime, endTime, a[1], a[3])); } else { user.getUserRecords().addManYouOutProvinceRecords(new CallRecord(startTime, endTime, a[1], a[3])); } } } for (User user : User1List ) { if (user.getNumber().equals(a[2])) { if (judge.isAnswerInCityCode1(a[3])) { ; } else if (judge.isAnswerInProvinceCode1(a[3])) { ; } else { user.getUserRecords().addAnswerInLandRecords(new CallRecord(startTime, endTime, a[0].substring(2, 6), a[2])); } } } } catch (ParseException e) { e.printStackTrace(); } } if (judge.isCalling10Information(m)) { String[] a = m.split(" "); try { SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); Date startTime = format.parse(a[3] + " " + a[4]); Date endTime = format.parse(a[5] + " " + a[6]); for (User user : User1List ) { if (user.getNumber().equals(a[0].substring(2))) { if (judge.isCallInCity(a[1])) { if (judge.isInCityCode(a[2].substring(0,4))) { user.getUserRecords().addCallingInCityRecords(new CallRecord(startTime, endTime, a[1], a[3])); } else if (judge.isInProvinceCode(a[2].substring(0,4))) { user.getUserRecords().addCallingInProvinceRecords(new CallRecord(startTime, endTime, a[1], a[3])); } else { user.getUserRecords().addCallingInLandRecords(new CallRecord(startTime, endTime, a[1], a[3])); } } else if (judge.isInProvinceCode(a[1])) { user.getUserRecords().addManYouInProvinceRecords(new CallRecord(startTime, endTime, a[1], a[3])); } else { user.getUserRecords().addManYouOutProvinceRecords(new CallRecord(startTime, endTime, a[1], a[3])); } } } } catch (ParseException e) { e.printStackTrace(); } } m = in.nextLine(); } for (User user : UserList ) { user.setChargeMode(landlinePhoneCharging); } for (User user:User1List ) { user.setChargeMode(mobilePhoneCharging); } for (int i = 0; i < UserList.size(); i++) { int index = -1; Double min = Double.parseDouble(UserList.get(i).getNumber()); for (int j = i + 1; j < UserList.size(); j++) { if (Double.parseDouble(UserList.get(j).getNumber()) < min) { min = Double.parseDouble(UserList.get(j).getNumber()); index = j; } } if (min != Double.parseDouble(UserList.get(i).getNumber())) { User user = UserList.get(i); UserList.set(i, UserList.get(index)); UserList.set(index, user); } } for (int i = 0; i < User1List.size(); i++) { int index = -1; Double min = Double.parseDouble(User1List.get(i).getNumber()); for (int j = i + 1; j < User1List.size(); j++) { if (Double.parseDouble(User1List.get(j).getNumber()) < min) { min = Double.parseDouble(User1List.get(j).getNumber()); index = j; } } if (min != Double.parseDouble(User1List.get(i).getNumber())) { User user = User1List.get(i); User1List.set(i, User1List.get(index)); User1List.set(index, user); } } for (User user : UserList ) { System.out.printf("%s %.1f %.1f\n", user.getNumber(), user.getChargeMode().calCost(user.getUserRecords()), user.getBalance()); } for (User user : User1List ) { System.out.printf("%s %.1f %.1f\n", user.getNumber(), user.getChargeMode().calCost(user.getUserRecords()), user.getBalance()); } } } abstract class CallChargeRule extends ChargeRule{ public double calCost(ArrayList<CallRecord> callRecords){ return 0; } } class CallRecord extends CommunicationRecord{ private Date startTime; private Date endTime; private String callingAddressAreaCode; private String answerAddressAreaCode; public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) { this.startTime = startTime; this.endTime = endTime; this.callingAddressAreaCode = callingAddressAreaCode; this.answerAddressAreaCode = answerAddressAreaCode; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public String getCallingAddressAreaCode() { return callingAddressAreaCode; } public void setCallingAddressAreaCode(String callingAddressAreaCode) { this.callingAddressAreaCode = callingAddressAreaCode; } public String getAnswerAddressAreaCode() { return answerAddressAreaCode; } public void setAnswerAddressAreaCode(String answerAddressAreaCode) { this.answerAddressAreaCode = answerAddressAreaCode; } } abstract class ChargeMode { private ArrayList<ChargeRule> chargeRules = new ArrayList<>(); private ArrayList<ChargeRule> chargeRules1 = new ArrayList<>(); public ArrayList<ChargeRule> getChargeRules1() { return chargeRules1; } public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { this.chargeRules = chargeRules; } public double calCost(UserRecords userRecords){ return 0; } public double getMonthlyRent(){ return 0; } } abstract class ChargeRule { public double calCost(ArrayList<CallRecord> callRecords){ return 0; } } abstract class CommunicationRecord { protected String callingNumber; protected String answerNumber; public String getCallingNumber() { return callingNumber; } public void setCallingNumber(String callingNumber) { this.callingNumber = callingNumber; } public String getAnswerNumber() { return answerNumber; } public void setAnswerNumber(String answerNumber) { this.answerNumber = answerNumber; } } class Judge { public boolean isUserInformation(String s){ String pattern ="(u-0791)[\\d]{7,8}[\\s][0-2]"; return s.matches(pattern); } public boolean isUser1Information(String s){ String pattern = "(u-)[1][\\d]{10}[\\s][0-2]"; return s.matches(pattern); } public boolean isCallingInformation(String s){ String pattern = "[t]-0791[0-9]{7,8}\\s" + "0[0-9]{9,11}\\s" + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(0?" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\\s" + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.((([13578]|1[02])\\.(" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])"; return s.matches(pattern); } public boolean isCalling01Information(String s){ String pattern = "[t]-0[0-9]{9,11}\\s" + "[1][\\d]{10}\\s"+"[\\d]{3,4}\\s"+ "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(0?" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\\s" + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.((([13578]|1[02])\\.(" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])"; return s.matches(pattern); } public boolean isCalling11Information(String s){ String pattern = "(t-)[1][\\d]{10}\\s"+"[\\d]{3,4}\\s" + "[1][\\d]{10}\\s"+"[\\d]{3,4}\\s"+ "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(0?" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\\s" + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.((([13578]|1[02])\\.(" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])"; return s.matches(pattern); } public boolean isCalling10Information(String s){ String pattern = "(t-)[1][\\d]{10}\\s"+"[\\d]{3,4}\\s" + "0[0-9]{9,11}\\s"+ "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(0?" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\\s" + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.((([13578]|1[02])\\.(" + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|(((" + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))" + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])"; return s.matches(pattern); } public boolean isInCityCode(String s){ String pattern = "0791"; return s.equals(pattern); } public boolean isInProvinceCode(String s){ String pattern = "((0790)|(0701)|((079)[2-9]))"; return s.matches(pattern); } public boolean isAnswerInCityCode1(String s){ String pattern = "0791"; return s.equals(pattern); } public boolean isAnswerInProvinceCode1(String s){ String pattern = "((0790)|(0701)|((079)[2-9]))"; return s.matches(pattern); } public boolean isCallInCity(String s){ String pattern = "0791"; return s.equals(pattern); } public boolean isCallInProvince(String s){ String pattern = "((0790)|(0701)|((079)[2-9]))"; return s.matches(pattern); } } class LandlinePhoneCharging extends ChargeMode{ private double monthlyRent = 20; public double calCost(UserRecords userRecords){ double sum=0; sum = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords())+getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords())+getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()); return sum; } public double getMonthlyRent(){ return monthlyRent; } } class LandPhoneCharging { private double monthly = 20; } class LandPhoneInCityRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords) { double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.1; } return sumCost; } } class LandPhoneInProvinceRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords){ double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.3; } return sumCost; } } class LandPhonelnlandRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords){ double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.6; } return sumCost; } } class MessageRecord extends CommunicationRecord{ private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class User { private UserRecords userRecords = new UserRecords(); private double balance = 100; private ChargeMode chargeMode; private String number; public User(String number) { this.number = number; } public double calBalance(){ return 0; } public double calCost(){ return 0; } public double getBalance() { return balance-chargeMode.calCost(userRecords)-chargeMode.getMonthlyRent(); } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public ChargeMode getChargeMode() { return chargeMode; } public void setChargeMode(ChargeMode chargeMode) { this.chargeMode = chargeMode; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } } class UserRecords { private ArrayList<CallRecord> callingInCityRecords = new ArrayList<>(); private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<>(); private ArrayList<CallRecord> callingInLandRecords = new ArrayList<>(); private ArrayList<CallRecord> answerInCityRecords = new ArrayList<>(); private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<>(); private ArrayList<CallRecord> answerInLandRecords = new ArrayList<>(); private ArrayList<CallRecord> manYouInProvinceRecords = new ArrayList<>(); private ArrayList<CallRecord> manYouOutProvinceRecords = new ArrayList<>(); private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<>(); private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<>(); public void addManYouInProvinceRecords(CallRecord callRecord){ manYouInProvinceRecords.add(callRecord); } public ArrayList<CallRecord> getManYouInProvinceRecords() { return manYouInProvinceRecords; } public ArrayList<CallRecord> getManYouOutProvinceRecords() { return manYouOutProvinceRecords; } public void addManYouOutProvinceRecords(CallRecord callRecord){ manYouOutProvinceRecords.add(callRecord); } public void addCallingInCityRecords(CallRecord callRecord){ callingInCityRecords.add(callRecord); } public void addCallingInProvinceRecords(CallRecord callRecord){ callingInProvinceRecords.add(callRecord); } public void addCallingInLandRecords(CallRecord callRecord){ callingInLandRecords.add(callRecord); } public void addAnswerInCityRecords(CallRecord callRecord){ answerInCityRecords.add(callRecord); } public void addAnswerInProvinceRecords(CallRecord callRecord){ answerInProvinceRecords.add(callRecord); } public void addAnswerInLandRecords(CallRecord callRecord){ answerInLandRecords.add(callRecord); } public ArrayList<CallRecord> getCallingInCityRecords() { return callingInCityRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords() { return callingInProvinceRecords; } public ArrayList<CallRecord> getCallingInLandRecords() { return callingInLandRecords; } public ArrayList<CallRecord> getAnswerInCityRecords() { return answerInCityRecords; } public ArrayList<CallRecord> getAnswerInProvinceRecords() { return answerInProvinceRecords; } public ArrayList<CallRecord> getAnswerInLandRecords() { return answerInLandRecords; } } class MobilePhoneCallOutCityRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords) { double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.3; } return sumCost; } } class MobilePhoneAnswerOutProvince extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords) { double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.3; } return sumCost; } } class MobilePhoneCallOutProvince extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords) { double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.6; } return sumCost; } } class MobilePhoneCharging extends ChargeMode{ private double monthlyRent = 15; public double calCost(UserRecords userRecords){ double sum=0; sum = getChargeRules1().get(0).calCost(userRecords.getCallingInCityRecords())+getChargeRules1().get(1).calCost(userRecords.getCallingInProvinceRecords())+getChargeRules1().get(2).calCost(userRecords.getCallingInLandRecords())+getChargeRules1().get(3).calCost(userRecords.getManYouInProvinceRecords())+getChargeRules1().get(4).calCost(userRecords.getManYouOutProvinceRecords())+getChargeRules1().get(5).calCost(userRecords.getAnswerInLandRecords());; return sum; } public double getMonthlyRent(){ return monthlyRent; } } class MobilePhoneInCityRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords) { double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.1; } return sumCost; } } class MobilePhoneInLandRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords) { double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.3; } return sumCost; } } class MobilePhoneInProvinceRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords) { double sumCost=0; long minute; for (CallRecord callRecord:callRecords ) { long startTime = callRecord.getStartTime().getTime(); long endTime = callRecord.getEndTime().getTime(); long second = (endTime-startTime)/1000; if (second%60>0){ minute = second/60+1; } else { minute = second/60; } sumCost = sumCost+minute*0.2; } return sumCost; } }View Code
SourceMonitor报表如下:
7-1 电信计费系列3-短信计费
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
输入:
输入信息包括两种类型
1、逐行输入南昌市手机用户开户的信息,每行一个用户。
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐 3-手机短信计费)
例如:u-13305862264 3
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题只针对类型3-手机短信计费。
2、逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.
注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
本题只考虑短信计费,不考虑通信费用以及月租费。
建议类图:
参见图1、2、3:
图1
图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。
UserRecords是用户记录类,保存用户各种通话、短信的记录,
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
图2
图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。
图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
输入样例:
在这里给出一组输入。例如:
u-18907910010 3
m-18907910010 13305862264 aaaaaaaaaaaaaaaaaaaaaaa
end
输出样例:
在这里给出相应的输出。例如:
18907910010 0.3 99.7
### 输入样例1:
在这里给出一组输入。例如:
u-18907910010 3
m-18907910010 13305862264 aaaaaaaaaaaa
m-18907910010 13305862264 aaaaaaa.
m-18907910010 13305862264 bb,bbbb
end
输出样例1:
在这里给出相应的输出。例如:
18907910010 0.5 99.5
源代码:
import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import java.util.Scanner; import java.util.TreeMap; import java.util.ArrayList; import java.util.Date; public class Main { public static void main(String[] args) throws ParseException { // TODO Auto-generated method stub Scanner in = new Scanner(System.in); String s = in.nextLine(); String numberjudge = "[u][-]1[3-9]\\d{9}[ ][3]"; String messagejudge = "m-1[3-9]\\d{9} 1[3-9]\\d{9} [a-z|0-9| |,|.]++"; TreeMap<String,User> set = new TreeMap<>(); String number; User user; int k = 0; while(!s.equals("end")) { if(k==0) { while(!s.equals("end")&&s.charAt(0)=='u') { if(s.matches(numberjudge)) { String ss[] = s.split(" "); user = new User(); number = ss[0].substring(ss[0].indexOf("-")+1); user.setNumber(number); set.put(number,user); } s = in.nextLine(); if(s.charAt(0)=='m') { k = 1; } } } while(!s.equals("end")&&s.charAt(0)=='m') { if(s.matches(messagejudge)) { //m-18907910010 13305862264 bb,bbbb MessageRecord record = new MessageRecord(); String s1 = s.substring(0,s.indexOf(" ")); String ss1 = s1.substring(s1.indexOf("-")+1);//发短信的电话号码 String s2 = s.substring(s.indexOf(" ")+1); String ss2 = s2.substring(0,s2.indexOf(" ")-1);//收短信的号码 String message = s2.substring(s2.indexOf(" ")+1); for (Map.Entry<String, User> e : set.entrySet()) { if(e.getKey().equals(ss1)) { record.setCallingNumber(ss1); record.setAnswerNumber(ss2); record.setMessage(message); e.getValue().getUserRecords().addSendMessageRecords(record); } } } s = in.nextLine(); } if(!s.equals("end")) { s = in.nextLine(); } } DecimalFormat d = new DecimalFormat("###0.0#"); for (Map.Entry<String, User> e : set.entrySet()) { System.out.println(e.getValue().getNumber()+" "+d.format(e.getValue().callCost())+" "+d.format(e.getValue().callBalance())); } } } abstract class AnswerChargeRule { public abstract double AnswerCost (ArrayList<CallRecord> callRecords); } class AnswerInLandRule extends AnswerChargeRule{ @Override public double AnswerCost(ArrayList<CallRecord> answerRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : answerRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.3 * n; } return cost; } } abstract class CallChargeRule{ private double price; public abstract double callCost (ArrayList<CallRecord> callRecords); public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } } class CallRecord { private String callingAdressAreaCode; private String AnswerAdressAreaCode; private Date startTime; private Date endTime; public String getCallingAdressAreaCode() { return callingAdressAreaCode; } public void setCallingAdressAreaCode(String callingAdressAreaCode) { this.callingAdressAreaCode = callingAdressAreaCode; } public String getAnswerAdressAreaCode() { return AnswerAdressAreaCode; } public void setAnswerAdressAreaCode(String answerAdressAreaCode) { AnswerAdressAreaCode = answerAdressAreaCode; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } } abstract class ChargeMode { private ArrayList<CallChargeRule> chargeRules = new ArrayList<>(); private ArrayList<AnswerChargeRule> answerule = new ArrayList<>(); public ArrayList<CallChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<CallChargeRule> chargeRules) { this.chargeRules = chargeRules; } public abstract double callCost(UserRecords userRecords); public abstract double getMonthlyRent (); public abstract void setMonthlyRent(double a); public ArrayList<AnswerChargeRule> getAnswerule() { return answerule; } public void setAnswerule(ArrayList<AnswerChargeRule> answerule) { this.answerule = answerule; } } class CommunicateRecord { protected String callingNumber; protected String answerNumber; public String getCallingNumber() { return callingNumber; } public void setCallingNumber(String callingNumber) { this.callingNumber = callingNumber; } public String getAnswerNumber() { return answerNumber; } public void setAnswerNumber(String answerNumber) { this.answerNumber = answerNumber; } } class LandlinePhoneCharging extends ChargeMode{ private double monthlyRent = 20; @Override public double callCost(UserRecords userRecords) { // TODO Auto-generated method stub CallChargeRule a = new LandPhoneInCityRule(); CallChargeRule b = new LandPhoneInProvinceRule(); CallChargeRule c = new LandPhoneInlandRule(); double callcost = a.callCost(userRecords.getCallingInCityRecords()) + b.callCost(userRecords.getCallingInProvinceRecords()) + c.callCost(userRecords.getCallingInLandRecords()); return callcost; } @Override public double getMonthlyRent() { // TODO Auto-generated method stub return monthlyRent; } public void setMonthlyRent(double monthlyRent) { this.monthlyRent = monthlyRent; } } class LandPhoneInCityRule extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.1 * n; } return cost; } } class LandPhoneInlandRule extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.6 * n; } return cost; } } class LandPhoneInProvinceRule extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.3 * n; } return cost; } } class MessageChargeRule { public double MessageCost(ArrayList<MessageRecord> messageRecords) { // TODO Auto-generated method stub double cost = 0; int i = 0; int j = 0; int n = messageRecords.size(); for(MessageRecord a : messageRecords) { j = 0; String m = a.getMessage(); int k = m.length(); if(k>10) { if(k%10>0) { j = k/10 + 1; } else { j = k/10; } } else { j = 1; } for(int x=1;x<=j;x++) { if(i+x<=3) { cost += 0.1; } else if(i+x>3&&i+x<=5) { cost += 0.2; } else { cost += 0.3; } } i +=j; } return cost; } } class MessageRecord extends CommunicateRecord{ private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class PhoneCharging extends ChargeMode{ private double monthlyRent = 15; @Override public double callCost(UserRecords userRecords) { // TODO Auto-generated method stub double cost = 0; CallChargeRule a = new PhoneInCittCallInLand(); CallChargeRule b = new PhoneInCityCallInCity(); CallChargeRule c = new PhoneInCityCallInProvince(); CallChargeRule d = new PhoneInLandCallOther(); CallChargeRule e = new PhoneInProvinceCallOther(); AnswerChargeRule f = new AnswerInLandRule(); cost += f.AnswerCost(userRecords.getAnswerInLandRecords()) + a.callCost(userRecords.getPhonecallingInCityInLandRecords()); cost += b.callCost(userRecords.getPhonecallingInCityInCityRecords()) + c.callCost(userRecords.getPhonecallingInCityInProvinceRecords()); cost += d.callCost(userRecords.getPhonecallingInLandOtherRecords()) + e.callCost(userRecords.getPhonecallingInProvinceRecords()); return cost; } @Override public double getMonthlyRent() { // TODO Auto-generated method stub return monthlyRent; } @Override public void setMonthlyRent(double monthlyRent) { // TODO Auto-generated method stub this.monthlyRent = monthlyRent; } } class PhoneInCittCallInLand extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.3 * n; } return cost; } } class PhoneInCityCallInCity extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.1 * n; } return cost; } }class PhoneInCityCallInProvince extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.2 * n; } return cost; } }class PhoneInLandCallOther extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.6 * n; } return cost; } } class PhoneInProvinceCallOther extends CallChargeRule{ @Override public double callCost(ArrayList<CallRecord> callRecords) { // TODO Auto-generated method stub double cost = 0; double m; for(CallRecord a : callRecords) { m = Double.valueOf(a.getEndTime().getTime() - a.getStartTime().getTime())/1000/60; int n = (int)m; if(m-n>0.000001) { n = n+1; } cost += 0.3 * n; } return cost; } } class User { private UserRecords userRecords = new UserRecords(); private double balance = 100; private ChargeMode chargemode1 = new LandlinePhoneCharging(); private ChargeMode chargemode2 = new PhoneCharging(); private MessageChargeRule message = new MessageChargeRule(); private String number; public double callBalance() { if(number.charAt(0)=='1') { balance = balance - message.MessageCost(userRecords.getSendMessageRecords()); } else { balance = balance - (this.callCost() + chargemode1.getMonthlyRent()); } return balance; } public double callCost() { if(number.charAt(0)=='1') { return message.MessageCost(userRecords.getSendMessageRecords()); } else { return chargemode1.callCost(userRecords); } } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public double getBalance() { return balance; } public ChargeMode getChargemode() { if(number.charAt(0)=='1') { return chargemode2; } else { return chargemode1; } } public void setChargemode(ChargeMode chargemode) { if(number.charAt(0)=='1') { this.chargemode2 = chargemode; } else { this.chargemode1 = chargemode; } } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } } class UserRecords { private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> PhonecallingInLandOtherRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> PhonecallingInCityInLandRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> PhonecallingInProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> PhonecallingInCityInProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> PhonecallingInCityInCityRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); public void addCallingInCityRecords (CallRecord callRecord) { callingInCityRecords.add(callRecord); } public void addCallingInProvinceRecords (CallRecord callRecord) { callingInProvinceRecords.add(callRecord); } public void addCallingInLandRecords (CallRecord callRecord) { callingInLandRecords.add(callRecord); } public void addAnswerInCityRecords (CallRecord answerRecord) { answerInCityRecords.add(answerRecord); } public void addAnswerInProvinceRecords (CallRecord answerRecord) { answerInProvinceRecords.add(answerRecord); } public void addAnswerInLandRecords (CallRecord answerRecord) { answerInLandRecords.add(answerRecord); } public void addSendMessageRecords (MessageRecord sendMessageRecord) { sendMessageRecords.add(sendMessageRecord); } public void addReceiveMessageRecords (MessageRecord receiveMessageRecord) { receiveMessageRecords.add(receiveMessageRecord); } public ArrayList<CallRecord> getCallingInCityRecords() { return callingInCityRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords() { return callingInProvinceRecords; } public ArrayList<CallRecord> getCallingInLandRecords() { return callingInLandRecords; } public ArrayList<CallRecord> getAnswerInCityRecords() { return answerInCityRecords; } public ArrayList<CallRecord> getAnswerInProvinceRecords() { return answerInProvinceRecords; } public ArrayList<CallRecord> getAnswerInLandRecords() { return answerInLandRecords; } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public ArrayList<CallRecord> getPhonecallingInLandOtherRecords() { return PhonecallingInLandOtherRecords; } public void addPhonecallingInLandOtherRecords(CallRecord phonecallingInLandOtherRecords) { PhonecallingInLandOtherRecords.add(phonecallingInLandOtherRecords); } public ArrayList<CallRecord> getPhonecallingInCityInLandRecords() { return PhonecallingInCityInLandRecords; } public void addPhonecallingInCityInLandRecords(CallRecord phonecallingInCityInLandRecords) { PhonecallingInCityInLandRecords.add(phonecallingInCityInLandRecords); } public ArrayList<CallRecord> getPhonecallingInCityInProvinceRecords() { return PhonecallingInCityInProvinceRecords; } public void addPhonecallingInCityInProvinceRecords(CallRecord phonecallingInCityInProvinceRecords) { PhonecallingInCityInProvinceRecords.add(phonecallingInCityInProvinceRecords); } public ArrayList<CallRecord> getPhonecallingInCityInCityRecords() { return PhonecallingInCityInCityRecords; } public void addPhonecallingInCityInCityRecords(CallRecord phonecallingInCityInCityRecords) { PhonecallingInCityInCityRecords.add(phonecallingInCityInCityRecords); } public ArrayList<CallRecord> getPhonecallingInProvinceRecords() { return PhonecallingInProvinceRecords; } public void addPhonecallingInProvinceRecords(CallRecord phonecallingInProvinceRecords) { PhonecallingInProvinceRecords.add(phonecallingInProvinceRecords); } }View Code
SourceMonitor报表如下:
三、采坑心得:
1.正则表达式输入错误。
2.数据进行处理时,当代码的复杂度过高时,每次新增功能时都要花很长的时间进行修改读取和判断格式错误上。
3.因为有许多无用代码,导致找到自己所需要的东西需要花费很多时间,所以我新建了一个项目,将所需要的类保留下来,这样节省了时间,在简化后的项目了增加这题所需要实现的功能。
四、改进建议:
1.多分几个函数,以此提高代码复用率,减少代码的复杂性。
2.尝试使用父类,抽象类,对代码进行忧化。
3.重写抽象方法:抽象类本身是抽象的、模糊的、不具体的类。父类中的功能是不能删除的,但其形式是不需要的(没有存在的意义),此时就可以将父类中功能的 具体实现 形式 给删掉,而我们需要在实际运用下根据自己的需求重写抽象方法来提高效率,获得有用数据。
五、总结:
1.类和类之间具有共同特征,将这些共同特征提取出来,形成的就是抽象类。抽象类无法创建对象即无法实例化。
2.抽象类是无法实例化的,无法创建对象的,所以抽象类是用来被子类继承的。
3.这几次的作业让我感受到了编写代码需要严谨,要考虑每种不同的情况,这样才能保证程序没有漏洞,在不严谨的思绪下写出来的代码,可能你用数据测试最后得到的结果却是正确的,最后找不到漏洞在哪,需要花更大量的时间去找到漏洞并且修复。
标签:return,String,double,ArrayList,BLOG,new,public From: https://www.cnblogs.com/20011211zqp/p/16971507.html