一、前言
- 难度分析:近三次大作业难度相较与前面多边形难度有所下降,手机计费比座机计费大,而最后的短信计费难度则又降低。
- 题量:题量适中
- 知识点:继承多态容器,正则表达式等
二、设计与分析
1.题目一: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
源码:
import java.util.Scanner; import java.text.DecimalFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Objects; public class Main{ public static void main(String []args) throws ParseException { Scanner input = new Scanner(System.in); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); ArrayList<User> array = new ArrayList<>(); int flag = 0; String s = input.nextLine(); String[] a ; while (!s.equals("end")){ if(s.matches("[u][-](0791)[0-9]{7,8}[ ][0]")){ a = s.substring(2,s.length()).split("\\s"); for(int i = 0;i < array.size();i++){ if(Objects.equals(array.get(i).getNumber(), a[0])) { flag = 1; } } if(flag == 0) { array.add(new User(a[0])); flag = 0; } } if(s.matches("t-(\\d){11,12}\\s(\\d){10,12}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]" + "|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])" + "|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))" + "|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))" + "|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d")){ a = s.substring(2,s.length()).split("\\s"); for(int i=0;i< array.size();i++){ if(array.get(i).getNumber().equals(a[0])){ if(a[1].startsWith("0791")){ array.get(i).userRecord.addCallingInCityRecords(new CallRecord(a[2]+" "+a[3],a[4]+" "+a[5])); array.get(i).setUserRecord(array.get(i).userRecord); } else if(a[1].substring(0,4).matches("(079\\d|0701)")){ array.get(i).userRecord.addCallingInProvinceRecords(new CallRecord(a[2]+" "+a[3],a[4]+" "+a[5])); array.get(i).setUserRecord(array.get(i).userRecord); } else{ array.get(i).userRecord.addCallingInLandRecords(new CallRecord(a[2]+" "+a[3],a[4]+" "+a[5])); array.get(i).setUserRecord(array.get(i).userRecord); } } } } s = input.nextLine(); } List<User> list = new ArrayList<>(array); Collections.sort(list); for (User e : list){ System.out.print(e.getNumber()+" "); System.out.print(new DecimalFormat("0.0#").format(e.calCost())); System.out.print(" "); System.out.print(new DecimalFormat("0.0#").format(e.calBalance())); System.out.println(); } } } abstract class ChargeRule{ } abstract class CallChargeRule extends ChargeRule{ public double calCost(ArrayList<CallRecord>callRecords){ return 0; } } class CallRecord extends ChargeRule{ private Date startTime; private Date endTime; private String callingAddressAreaCode; private String AnswerAddressAreaCode; public CallRecord(String startTime,String endTime) throws ParseException { this.startTime = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(startTime); this.endTime = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(endTime); } 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{ ArrayList<ChargeRule> chargeRule = new ArrayList<ChargeRule>(); public ArrayList<ChargeRule> getChargeRule(){ return chargeRule; } public void setChargeRule(ArrayList<ChargeRule> chargeRule){ this.chargeRule = chargeRule; } public double getMonthlyRent(){ return 20; } public double calCost(UserRecords userRecords){ return 0; } } class LandlinePhoneCharging extends ChargeMode{ private double monthlyRent = 20; public double calCost(UserRecords userRecords){ return monthlyRent * 1; } public double getMonthlyRent(){ return monthlyRent; } } 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 MessageRecord extends ChargeRule{ private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class LandPhoneInCityRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords){ double cost = 0; double minute; for (CallRecord e: callRecords){ minute = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime()) / 60000); cost = cost + 0.1 * minute; } return cost; } } class LandPhoneInProvinceRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords){ double cost = 0; double minute; for (CallRecord e: callRecords){ minute = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime()) / 60000); cost = cost + 0.3 * minute; } return cost; } } class LandPhoneInIandRule extends CallChargeRule{ public double calCost(ArrayList<CallRecord> callRecords){ double cost = 0; double minute; for (CallRecord e: callRecords){ minute = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime()) / 60000); cost = cost + 0.6 * minute; } return cost; } } class User implements Comparable<User> { UserRecords userRecord = new UserRecords(); private double balance = 100; ChargeMode chargeMode; private String number; public User(){ } public void setBalance(double balance) { this.balance = balance; } public User(String number) { this.number = number; } public double calBalance(){ return balance - calCost() - 20; } public double calCost(){ LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule(); LandPhoneInIandRule landPhoneInIandRule = new LandPhoneInIandRule(); LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule(); return landPhoneInIandRule.calCost(userRecord.getCallingInLandRecords()) +landPhoneInCityRule.calCost(userRecord.getCallingInCityRecords()) +landPhoneInProvinceRule.calCost(userRecord.getCallingInProvinceRecords()); } public UserRecords getUserRecord(){ return userRecord; } public void setUserRecord(UserRecords userRecord){ this.userRecord = userRecord; } public double getBalance(){ return 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; } public int compareTo(User o) { return this.getNumber().compareTo(o.getNumber()); } } class UserRecords{ ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); ArrayList<MessageRecord> sendMessageRecord = new ArrayList<MessageRecord>(); ArrayList<MessageRecord> receiveMessageRecord = 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 callRecord){ answerInCityRecords.add(callRecord); } public void addAnswerInProvinceRecords(CallRecord callRecord){ answerInProvinceRecords.add(callRecord); } public void addAnswerInLandRecords(CallRecord callRecord){ answerInLandRecords.add(callRecord); } public void addSendMessageRecord(MessageRecord sendMessageRecord){ this.sendMessageRecord.add(sendMessageRecord); } public void addReceiveMessageRecord(MessageRecord receiveMessageRecord){ this.receiveMessageRecord.add(receiveMessageRecord); } public ArrayList<MessageRecord> getSendMessageRecord(){ return sendMessageRecord; } public ArrayList<MessageRecord> getReceiveMessageRecord(){ return 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; } }
代码类图:
分析:
本题由于老师已经将类图给出,将所给类补全后,在Main中利用正则表达式判断输入字符串,并进行容器的添加计算,需要将类与类之间的关系理顺
踩坑心得:
这题正则表达式的书写非常有难度,一定要小心仔细
2.题目二: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)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
源码:
import java.util.ArrayList; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Collections; import java.util.Scanner; abstract class CallChargeRule extends ChargeRule{ public double calCost(ArrayList<CallRecord>callRecords) { return 0; } } class CallRecord { private Date startTime; private Date endTime; private String callingAddressAreaCode; private String answerAddressAreaCode; public CallRecord(String starttime,String endtime, String callingAddressAreaCode, String answerAddressAreaCode) throws ParseException { super(); SimpleDateFormat sf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); String date1 = starttime; String date2 = endtime; Date time1 = sf.parse(date1); Date time2 = sf.parse(date2); this.startTime = time1; this.endTime = time2; 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<>(); public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { } public double calCost(UserRecords userRecords) { return 0; } public double getMonthlyRent() { return 0; } } abstract class ChargeRule { } abstract class CommunicationRecord { private String callingNumber; private 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; public double getMonthlyRent() { return monthlyRent; } public double calCost(UserRecords userRecords) { double calcost = 0; LandPhoneInCityRule incity = new LandPhoneInCityRule(); LandPhoneInProvinceRule inprovince = new LandPhoneInProvinceRule(); LandPhoneInlandRule inland = new LandPhoneInlandRule(); calcost = incity.calCost(userRecords.getCallinglnCityRecords()) + inprovince.calCost(userRecords.getCallinglnProvinceRecords()) + inland.calCost(userRecords.getCallinglnLandRecords()); return calcost; } } class LandPhoneInCityRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.1 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class LandPhoneInlandRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.6 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class LandPhoneInProvinceRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } public class Main { public static void main(String[] args) throws ParseException { // TODO Auto-generated method stub Scanner in = new Scanner(System.in); String s0 = "u-079[0-9][0-9]{7,8} 0" ; String s1 = "u-0701[0-9]{7,8} 0"; String s2 = "t-[0-9]{10,12} [0-9]{10,12} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}"; String s3 = "0791"; String s4 = "079[0-9]"; String s5 = "0701"; String s6 = "[0-9]{3,4}"; String s7 = "[0-9]{11}"; String s8 = "u-[0-9]{11} 1"; String s9 = "t-[0-9]{10,12} [0-9]{11} [0-9]{3,4} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}"; String s10 = "t-[0-9]{11} [0-9]{3,4} [0-9]{11} [0-9]{3,4} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}"; String s11 = "t-[0-9]{11} [0-9]{3,4} [0-9]{10,12} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}"; String s12 = "[0-9]{10,12}"; String s13 = "0791[0-9]{7,8}"; String s14 = "079[0-9]{8,9}"; String s15 = "0701[0-9]{7,8}"; String s16 = "[0-9]{10,12}"; ArrayList<User>list = new ArrayList<>(); String s = in.nextLine(); while(!s.matches(s9)&&!s.matches(s10)&&!s.matches(s11)){ User a = new User(); if(s.matches(s0)||s.matches(s1)||s.matches(s8)){ a.setNumber((String) s.subSequence(2, s.length()-2)); int flag = 0; for(User b :list) { if(b.getNumber().equals((String) s.subSequence(2, s.length()-2))) { flag++; } } if(flag==0) list.add(a); } s = in.nextLine(); if(s.equals("end")){ break; } } while(!s.equals("end")) { if(s.matches(s2)) { String str[] = s.split(" "); String num1 = str[0].substring(2); String num2 = str[1]; String starttime = str[2]+" "+str[3]; String endtime = str[4]+" "+str[5]; if(check(starttime)&&check(endtime)) { for(int i = 0;i<list.size();i++) { if(list.get(i).getNumber().equals(num1)&&num2.matches(s13)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnCityRecords(callRecords); } else if(list.get(i).getNumber().equals(num1)&&(num2.matches(s14)||num2.matches(s15))&&!num2.matches(s13)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnProvinceRecords(callRecords); } else if(list.get(i).getNumber().equals(num1)&&!num2.matches(s13)&&!num2.matches(s14)&&!num2.matches(s15)&&num2.matches(s16)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnLandRecords(callRecords); } } } } if(s.matches(s9)) { String str[] = s.split(" "); String num1 = str[0].substring(2); String num2 = str[1]; String place = str[2]; String starttime = str[3]+" "+str[4]; String endtime = str[5]+" "+str[6]; if(check(starttime)&&check(endtime)) { for(int i = 0;i<list.size();i++) { if(list.get(i).getNumber().equals(num1)&&place.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnCityRecords(callRecords); } else if(list.get(i).getNumber().equals(num1)&&(place.matches(s4)||place.matches(s5))&&!place.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnProvinceRecords(callRecords); } else if(list.get(i).getNumber().equals(num1)&&!place.matches(s3)&&!place.matches(s4)&&!place.matches(s5)&&place.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnLandRecords(callRecords); for(int j = 0;j<list.size();j++) { if(list.get(j).getNumber().equals(num2)) { list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords); } } break; } else if(list.get(i).getNumber().equals(num2)&&!place.matches(s3)&&!place.matches(s4)&&!place.matches(s5)&&place.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); for(int j = 0;j<list.size();j++) { if(list.get(j).getNumber().equals(num2)) { list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords); } } } break; } } } if(s.matches(s10)) { String str[] = s.split(" "); String num1 = str[0].substring(2); String place1 = str[1]; String num2 = str[2]; String place2 = str[3]; String starttime = str[4]+" "+str[5]; String endtime = str[6]+" "+str[7]; if(check(starttime)&&check(endtime)) { for(int i = 0;i<list.size();i++) { if(place1.matches(s3)) { if(list.get(i).getNumber().equals(num1)&&place2.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnCityRecords(callRecords); break; } else if(list.get(i).getNumber().equals(num1)&&(place2.matches(s4)||place2.matches(s5))&&!place2.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnProvinceRecords(callRecords); break; } else if(list.get(i).getNumber().equals(num1)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s)&&place2.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnLandRecords(callRecords); for(int j = 0;j<list.size();j++) { if(list.get(j).getNumber().equals(num2)&&num1!=num2) { list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords); } } break; } else if(list.get(i).getNumber().equals(num2)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addAnswerlnLandRoamRecords(callRecords); break; } } if((place1.matches(s4)||place1.matches(s5))&&!place1.matches(s3)) { if(list.get(i).getNumber().equals(num1)&&place2.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords); break; } else if(list.get(i).getNumber().equals(num1)&&(place2.matches(s4)||place2.matches(s5))&&!place2.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords); break; } else if(list.get(i).getNumber().equals(num1)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords); for(int j = 0;j<list.size();j++) { if(list.get(j).getNumber().equals(num2)&&num1!=num2) { list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords); } } break; } else if(list.get(i).getNumber().equals(num2)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addAnswerlnLandRoamRecords(callRecords); break; } } if(!place1.matches(s3)&&!place1.matches(s4)&&!place1.matches(s5)&&place1.matches(s6)) { if(list.get(i).getNumber().equals(num1)&&place2.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords); break; } else if(list.get(i).getNumber().equals(num1)&&(place2.matches(s4)||place2.matches(s5))&&!place2.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords); break; } else if(list.get(i).getNumber().equals(num1)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords); for(int j = 0;j<list.size();j++) { if(list.get(j).getNumber().equals(num2)&&num1!=num2) { list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords); } } break; } else if(list.get(i).getNumber().equals(num2)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addAnswerlnLandRoamRecords(callRecords); for(int j = 0;j<list.size();j++) { if(list.get(j).getNumber().equals(num1)&&num1!=num2) { list.get(j).getUserRecords().addCallinglnLandRoamRecords(callRecords); } } break; } } } } } if(s.matches(s11)) { String str[] = s.split(" "); String num1 = str[0].substring(2); String place = str[1]; String num2 = str[2]; String starttime = str[3]+" "+str[4]; String endtime = str[5]+" "+str[6]; if(check(starttime)&&check(endtime)) { for(int i = 0;i<list.size();i++) { if(list.get(i).getNumber().equals(num1)&&place.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnCityRecords(callRecords); } else if(list.get(i).getNumber().equals(num1)&&(place.matches(s4)||place.matches(s5))&&!place.matches(s3)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords); } else if(list.get(i).getNumber().equals(num1)&&!place.matches(s3)&&!place.matches(s4)&&!place.matches(s5)&&place.matches(s6)) { CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2); list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords); } } } } s = in.nextLine(); } for(int i = 0;i<list.size();i++) { if(list.get(i).getNumber().matches(s6)) { list.get(i).calBalance(); list.get(i).calCost(); } if(list.get(i).getNumber().matches(s7)) { list.get(i).calBalance1(); list.get(i).calCost1(); } for(int j = 0;j<list.size()-1;j++) { if(list.get(j).getNumber().compareTo(list.get(j+1).getNumber())>0) { Collections.swap(list, j, j+1); } } } for(User l : list) { if(l.getNumber().charAt(0)=='0') { System.out.printf("%s %.1f %.1f\n",l.getNumber(),l.calCost(),l.calBalance()); } if(l.getNumber().charAt(0)=='1') { System.out.printf("%s %.1f %.1f\n",l.getNumber(),l.calCost1(),l.calBalance1()); } } } public static boolean check(String s) { SimpleDateFormat a = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); try { a.setLenient(false); a.parse(s); }catch(Exception e) { return false; } return true; } } class MessageRecord { private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class SmartlinePhoneCharging extends ChargeMode{ private double monthlyRent = 15; public double getMonthlyRent() { return monthlyRent; } public double calCost(UserRecords userRecords) { double calcost = 0; SmartPhoneInCityRule smartPhoneInCityRule = new SmartPhoneInCityRule(); SmartPhoneInProvinceRule smartPhoneInProvinceRule = new SmartPhoneInProvinceRule(); SmartPhoneInLandRule smartPhoneInLandRule = new SmartPhoneInLandRule(); SmartPhoneInProvinceRoamRule smartPhoneInProvinceRoamRule = new SmartPhoneInProvinceRoamRule(); SmartPhoneInLandCallingRoamRule smartPhoneInLandCallingRoamRule = new SmartPhoneInLandCallingRoamRule(); SmartPhoneInLandAnswerRoamRule smartPhoneInLandAnswerRoamRule = new SmartPhoneInLandAnswerRoamRule(); calcost = smartPhoneInCityRule.calCost(userRecords.getCallinglnCityRecords()) + smartPhoneInProvinceRule.calCost(userRecords.getCallinglnProvinceRecords()) + smartPhoneInLandRule.calCost(userRecords.getCallinglnLandRecords()) + smartPhoneInProvinceRoamRule.calCost(userRecords.getCallinglnProvinceRoamRecords()) + smartPhoneInLandCallingRoamRule.calCost(userRecords.getCallinglnLandRoamRecords()) + smartPhoneInLandAnswerRoamRule.calCost(userRecords.getAnswerlnLandRoamRecords()); return calcost; } } class SmartPhoneInCityRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords) { sum += 0.1 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class SmartPhoneInLandAnswerRoamRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class SmartPhoneInLandCallingRoamRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.6 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class SmartPhoneInLandRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class SmartPhoneInProvinceRoamRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class SmartPhoneInProvinceRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum = 0; for(CallRecord a:callRecords){ sum += 0.2 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60); } return sum; } } class User { private UserRecords userRecords = new UserRecords(); private double balance = 100 ; private ChargeMode chargeMode0; private ChargeMode chargeMode1; private String number; public User() { super(); this.chargeMode0 = new LandlinePhoneCharging(); this.chargeMode1 = new SmartlinePhoneCharging(); } public double calBalance() { double Balance = 0; Balance = getBalance() - calCost() - getChargeMode().getMonthlyRent(); return Balance; } public double calCost() { double sum = 0; sum = getChargeMode().calCost(getUserRecords()); return sum; } public double calBalance1() { double Balance = 0; Balance = getBalance() - calCost1() - getChargeMode1().getMonthlyRent(); return Balance; } public double calCost1() { double sum = 0; sum = getChargeMode1().calCost(getUserRecords()); return sum; } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public double getBalance() { return balance; } public ChargeMode getChargeMode() { return chargeMode0; } public void setChargeMode(ChargeMode chargeMode) { this.chargeMode0 = chargeMode; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public ChargeMode getChargeMode1() { return chargeMode1; } public void setChargeMode1(ChargeMode chargeMode1) { this.chargeMode1 = chargeMode1; } } class UserRecords { private ArrayList<CallRecord> callinglnCityRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callinglnProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callinglnLandRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerlnCityRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerlnProvinceRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerlnLandRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callinglnProvinceRoamRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> callinglnLandRoamRecords = new ArrayList<CallRecord>(); private ArrayList<CallRecord> answerlnLandRoamRecords = new ArrayList<CallRecord>(); private ArrayList<MessageRecord> sendMessageReconds = new ArrayList<MessageRecord>(); private ArrayList<MessageRecord> receiveMessageReconds = new ArrayList<MessageRecord>(); public ArrayList<CallRecord> getCallinglnCityRecords() { return callinglnCityRecords; } public void addCallinglnCityRecords(CallRecord callRecord) { callinglnCityRecords.add(callRecord); } public ArrayList<CallRecord> getCallinglnProvinceRecords() { return callinglnProvinceRecords; } public void addCallinglnProvinceRecords(CallRecord callRecord) { callinglnProvinceRecords.add(callRecord); } public ArrayList<CallRecord> getCallinglnLandRecords() { return callinglnLandRecords; } public void addCallinglnLandRecords(CallRecord callRecord) { callinglnLandRecords.add(callRecord); } public ArrayList<CallRecord> getAnswerlnCityRecords() { return answerlnCityRecords; } public void addAnswerlnCityRecords(CallRecord callRecord) { answerlnCityRecords.add(callRecord); } public ArrayList<CallRecord> getAnswerlnProvinceRecords() { return answerlnProvinceRecords; } public void addAnswerlnProvinceRecords(CallRecord callRecord) { answerlnProvinceRecords.add(callRecord); } public ArrayList<CallRecord> getAnswerlnLandRecords() { return answerlnLandRecords; } public void addAnswerlnLandRecords(CallRecord callRecord) { answerlnLandRecords.add(callRecord); } public ArrayList<MessageRecord> getSendMessageReconds() { return sendMessageReconds; } public void addSendMessageReconds(MessageRecord messageRecord) { sendMessageReconds.add(messageRecord); } public ArrayList<MessageRecord> getReceiveMessageReconds() { return receiveMessageReconds; } public void addReceiveMessageReconds(MessageRecord messageRecord) { receiveMessageReconds.add(messageRecord); } public ArrayList<CallRecord> getCallinglnProvinceRoamRecords() { return callinglnProvinceRoamRecords; } public void addCallinglnProvinceRoamRecords(CallRecord callRecord) { callinglnProvinceRoamRecords.add(callRecord); } public ArrayList<CallRecord> getCallinglnLandRoamRecords() { return callinglnLandRoamRecords; } public void addCallinglnLandRoamRecords(CallRecord callRecord) { callinglnLandRoamRecords.add(callRecord); } public ArrayList<CallRecord> getAnswerlnLandRoamRecords() { return answerlnLandRoamRecords; } public void addAnswerlnLandRoamRecords(CallRecord callRecord) { answerlnLandRoamRecords.add(callRecord); }
sourceMonitor图:
分析:
本题在之前的基础上增加算钱的类,依旧利用正则表达式判别输入字符串后进行操作
3.题目三: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)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
源码:
import java.util.ArrayList; import java.util.Collections; import java.util.Scanner; import java.text.ParseException; abstract class ChargeMode { private ArrayList<ChargeRule> chargeRules = new ArrayList<>(); public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { } public double calCost(UserRecords userRecords) { return 0; } public double getMonthlyRent() { return 0; } } abstract class ChargeRule { } public class Main { public static void main(String[] args) throws ParseException{ // TODO Auto-generated method stub Scanner in = new Scanner(System.in); String s1 = "[0-9]{11}"; String s2 = "u-[0-9]{11} 3"; String s3 = "m-[0-9]{11} [0-9]{11} "; String s4 = "m-[0-9]{11}"; String s5 = "m-[0-9]{11} [0-9]{11} [0-9|a-z|A-Z|\\s|\\.|\\,]+"; ArrayList<User> list = new ArrayList<User>(); String s = in.nextLine(); while(!s.matches(s5)){ User a = new User(); if(s.matches(s2)){ a.setNumber((String) s.subSequence(2, s.length()-2)); int flag = 0; for(User b :list) { if(b.getNumber().equals((String) s.subSequence(2, s.length()-2))) { flag++; } } if(flag==0) list.add(a); } s = in.nextLine(); if(s.equals("end")){ break; } } while(!s.equals("end")) { if(s.matches(s5)) { String str[] = ((String) s.subSequence(0, 25)).split(" "); String num1 = str[0].substring(2); String num2 = str[1]; String message = s.substring(26,s.length()); for(int i = 0;i<list.size();i++) { if(list.get(i).getNumber().equals(num1)) { MessageRecord messageRecord = new MessageRecord(message,num1,num2); list.get(i).getUserRecords().addSendMessageReconds(messageRecord); } } } s = in.nextLine(); } for(int i = 0;i<list.size();i++) { if(list.get(i).getNumber().matches(s1)) { list.get(i).calBalance(); list.get(i).calCost(); for(int j = 0;j<list.size()-1;j++) { if(list.get(j).getNumber().compareTo(list.get(j+1).getNumber())>0) { Collections.swap(list, j, j+1); } } } } for(User l : list) { System.out.printf("%s %.1f %.1f\n",l.getNumber(),l.calCost(),l.calBalance()); } } } abstract class MessageChargeRule extends ChargeRule{ public double calCost(ArrayList<MessageRecord>messageRecord) { return 0; } } class MessageCharging extends ChargeMode{ public double calCost(UserRecords userRecords) { double calcost = 0; SendMessageRule sendMessageRule = new SendMessageRule (); calcost = sendMessageRule.calCost(userRecords.getSendMessageReconds()); return calcost; } } class MessageRecord { private String message; private String callingAddressAreaCode; private String answerAddressAreaCode; public MessageRecord(String message, String callingAddressAreaCode, String answerAddressAreaCode) { super(); this.message = message; this.callingAddressAreaCode = callingAddressAreaCode; this.answerAddressAreaCode = answerAddressAreaCode; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class SendMessageRule extends MessageChargeRule{ @Override public double calCost(ArrayList<MessageRecord> messageRecord) { // TODO Auto-generated method stub double calcost = 0; int sum0 = 0; for(MessageRecord messagerecord : messageRecord) { int sum = 0; if(messagerecord.getMessage().length()%10==0) sum = messagerecord.getMessage().length()/10; else { sum = messagerecord.getMessage().length()/10 + 1; } sum0 += sum; } if(sum0<=3) { calcost = 0.1*sum0; } if(sum0>3&&sum0<=5) { calcost = 0.1*3 + (sum0-3)*0.2; } if(sum0>5) { calcost = 0.1*3 + 0.2*2 + 0.3*(sum0-5); } return calcost; } } class User { private UserRecords userRecords = new UserRecords(); private double balance = 100 ; private ChargeMode chargeMode; private String number; public User() { super(); this.chargeMode = new MessageCharging(); } public double calBalance() { double Balance = 0; Balance = getBalance() - calCost(); return Balance; } public double calCost() { double sum = 0; sum = getChargeMode().calCost(getUserRecords()); return sum; } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public double getBalance() { return balance; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public ChargeMode getChargeMode() { return chargeMode; } public void setChargeMode(ChargeMode chargeMode) { this.chargeMode = chargeMode; } } class UserRecords { private ArrayList<MessageRecord> sendMessageReconds = new ArrayList<MessageRecord>(); private ArrayList<MessageRecord> receiveMessageReconds = new ArrayList<MessageRecord>(); public ArrayList<MessageRecord> getSendMessageReconds() { return sendMessageReconds; } public void addSendMessageReconds(MessageRecord messageRecord) { sendMessageReconds.add(messageRecord); } public ArrayList<MessageRecord> getReceiveMessageReconds() { return receiveMessageReconds; } public void addReceiveMessageReconds(MessageRecord messageRecord) { receiveMessageReconds.add(messageRecord); } }
类图:
三、踩坑心得
这三次计费的训练,和多边形一样,一层一层迭代,只要前面类图编写合理,后面的运用就会非常轻松。要理解给定类图,并编写代码。要保持高质量的正则表达式,对方法的书写也要合理,保证代码可扩展性
四、改进建议
由于已经给定了类图,对于类图的设计并无需要改进的地方,但是题目中的一些测试点还是不太理解,有些情况并未完善,有待完善