一、前言:
- 在这几个星期中开始写电信计费的pta作业,这几次作业题量都相对来说较小,难度较低。
- 第一次的题目集只要求写了座机计费,只考虑计费类型0-座机计费,通过接电话座机的区号判断采用什么计费方式。
- 第二次的题目集增加了手机计费,被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定。座机接电话不用钱。
- 第三次的题目集增加了短信计费,每条短信信息均单独计费后累加,不是将所有信息累计后统一计费,再通过所在位置以及区号判断发短信价格。
- 三道题目之间的联系十分紧密,为迭代关系,后面的题都是由前面的迭代而来。
二、设计与分析:
第一道:
电信计费系列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
类图题目已给就累述;
SourceMonitor报表如下:

代码如下:
1 import java.text.DecimalFormat; 2 import java.text.ParseException; 3 import java.text.SimpleDateFormat; 4 import java.util.ArrayList; 5 import java.util.Date; 6 import java.util.Scanner; 7 import java.util.*; 8 9 public class Main { 10 public static void main(String[] args) throws ParseException { 11 Scanner in = new Scanner(System.in); 12 ArrayList<User> users = new ArrayList<>(); 13 Map <String, User> i = new HashMap<>(); 14 SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); 15 Date date1,date2; 16 String str; 17 str = in.nextLine(); 18 19 while (!str.equals("end")){ 20 if (str.matches("u-\\d{11,12}\\s0")){//开户 21 String[] a = str.split("-|\\s"); 22 User user = new User(a[2],a[1]); 23 users.add(user); 24 i.put(a[1],user); 25 }else if (str.matches("t-\\d{11,12}\\s\\d{10,12}(\\s\\d{4}[.][^0]\\d?[.]\\d{1,2}\\s([01][0-9]|20|21|22|23):[0-5][0-9]:[0-5][0-9]){2}")) {//正则判断 26 String[] a = str.split("-|\\s"); 27 if (isDate(a[3]) && isDate(a[5])) { 28 29 date1 = sdf.parse(a[3] + " " + a[4]); 30 date2 = sdf.parse(a[5] + " " + a[6]); 31 for (User u : i.values()) {//遍历已开户的用户寻找拨打电话的用户 32 if (u.getNumber().equals(a[1])) { 33 CallRecord callRecord = new CallRecord(); 34 callRecord.setStartTime(date1); 35 callRecord.setEndTime(date2); 36 if (a[2].substring(0, 4).equals("0791")) 37 u.getUserRecords().addCallingInCityRecords(callRecord); 38 else if (a[2].substring(0, 3).equals("079") || a[2].substring(0, 4).equals("0701")) { 39 u.getUserRecords().addCallingInProvinceRecords(callRecord); 40 } else u.getUserRecords().addCallingInLandRecords(callRecord); 41 } 42 } 43 } 44 } 45 str = in.nextLine(); 46 } 47 48 for (User u : i.values()){ 49 System.out.println(u.getNumber() +" "+ new DecimalFormat("0.0##").format(u.calCost()) + " "+ new DecimalFormat("0.0##").format(u.calBalance())); 50 } 51 } 52 public static boolean isDate(String s){ 53 String[] a = s.split("[.]"); 54 int year = 0,month = 0,day = 0; 55 year = Integer.parseInt(a[0]); 56 month = Integer.parseInt(a[1]); 57 day = Integer.parseInt(a[2]); 58 if((!isLeapYear(year)&&month==2&&day>29)||month>12||month<1||day>31||day<1||(month==2&&day>28)||(month==4&&day>30)||(month==6&&day>30)||(month==9&&day>30)||(month==11&&day>30)) 59 return false; 60 else 61 return true; 62 } 63 public static boolean isLeapYear(int year) { 64 if((year%4==0&&year%100!=0)||year%400==0) return true; 65 else return false; 66 } 67 68 } 69 70 abstract class CallChargeRule extends ChargeRule{ 71 72 public abstract double calCost(ArrayList<CallRecord> callRecords); 73 } 74 75 class CallRecord extends CommunicationRecord{ 76 private Date startTime; 77 private Date endTime; 78 private String callingAddressAreaCode; 79 private String answerAddressAreaCode; 80 81 public Date getStartTime() { 82 return startTime; 83 } 84 85 public void setStartTime(Date startTime) { 86 this.startTime = startTime; 87 } 88 89 public Date getEndTime() { 90 return endTime; 91 } 92 93 public void setEndTime(Date endTime) { 94 this.endTime = endTime; 95 } 96 97 public String getCallingAddressAreaCode() { 98 return callingAddressAreaCode; 99 } 100 101 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 102 this.callingAddressAreaCode = callingAddressAreaCode; 103 } 104 105 public String getAnswerAddressAreaCode() { 106 return answerAddressAreaCode; 107 } 108 109 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 110 this.answerAddressAreaCode = answerAddressAreaCode; 111 } 112 } 113 114 abstract class ChargeMode { 115 private ArrayList<ChargeRule> chargeRules = new ArrayList<>(); 116 117 public ChargeMode() { 118 chargeRules.add(new LandPhoneInCityRule()); 119 chargeRules.add(new LandPhoneInProvinceRule()); 120 chargeRules.add(new LandPhoneInLandRule()); 121 } 122 123 public ArrayList<ChargeRule> getChargeRules() { 124 return chargeRules; 125 } 126 127 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 128 this.chargeRules = chargeRules; 129 } 130 131 public abstract double calCost(UserRecords userRecords); 132 133 public abstract double getMonthlyRent(); 134 135 } 136 137 abstract class ChargeRule { 138 public abstract double calCost(ArrayList<CallRecord> callRecords); 139 } 140 abstract class CommunicationRecord { 141 protected String callingNumber; 142 protected String answerNumber; 143 144 public String getCallingNumber() { 145 return callingNumber; 146 } 147 148 public void setCallingNumber(String callingNumber) { 149 this.callingNumber = callingNumber; 150 } 151 152 public String getAnswerNumber() { 153 return answerNumber; 154 } 155 156 public void setAnswerNumber(String answerNumber) { 157 this.answerNumber = answerNumber; 158 } 159 } 160 class LandlinePhoneCharging extends ChargeMode{ 161 double monthlyRent = 20; 162 163 public LandlinePhoneCharging() { 164 super(); 165 } 166 167 @Override 168 public double calCost(UserRecords userRecords) { 169 double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) 170 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) 171 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()); 172 return s; 173 } 174 175 @Override 176 public double getMonthlyRent() { 177 return monthlyRent; 178 } 179 } 180 181 class LandPhoneInCityRule extends CallChargeRule{ 182 @Override 183 public double calCost(ArrayList<CallRecord> callRecords) { 184 double s = 0; 185 for (CallRecord a : callRecords){ 186 s+=(((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000)); 187 if (((a.getEndTime().getTime() - a.getStartTime().getTime()) / (1000))%60>0) s++; 188 } 189 190 return 0.1 * s; 191 } 192 } 193 194 class LandPhoneInLandRule extends CallChargeRule{ 195 @Override 196 public double calCost(ArrayList<CallRecord> callRecords) { 197 double s = 0; 198 for (CallRecord a : callRecords){ 199 s+=(((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000)); 200 if (((a.getEndTime().getTime() - a.getStartTime().getTime()) / (1000))%60>0) s++; 201 } 202 203 return 0.6 * s; 204 } 205 } 206 207 class LandPhoneInProvinceRule extends CallChargeRule{ 208 @Override 209 public double calCost(ArrayList<CallRecord> callRecords) { 210 double s = 0; 211 for (CallRecord a : callRecords){ 212 s+=(((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000)); 213 if (((a.getEndTime().getTime() - a.getStartTime().getTime()) / (1000))%60>0) s++; 214 } 215 216 return 0.3 * s; 217 } 218 } 219 class MessageRecord extends CommunicationRecord { 220 private String message; 221 222 public String getMessage() { 223 return message; 224 } 225 226 public void setMessage(String message) { 227 this.message = message; 228 } 229 } 230 class User { 231 private UserRecords userRecords = new UserRecords(); 232 private double balance = 100; 233 private ChargeMode chargeMode; 234 private String number; 235 236 public User(String str ,String number) { 237 if (str.equals("0")) this.chargeMode = new LandlinePhoneCharging(); 238 this.number = number; 239 } 240 241 public double calBalance(){ 242 return getBalance()-chargeMode.getMonthlyRent()-calCost(); 243 } 244 245 public double calCost(){ 246 return chargeMode.calCost(userRecords); 247 } 248 249 public UserRecords getUserRecords() { 250 return userRecords; 251 } 252 253 public void setUserRecords(UserRecords userRecords) { 254 this.userRecords = userRecords; 255 } 256 257 public double getBalance() { 258 return balance; 259 } 260 261 public ChargeMode getChargeMode() { 262 return chargeMode; 263 } 264 265 public void setChargeMode(ChargeMode chargeMode) { 266 this.chargeMode = chargeMode; 267 } 268 269 public String getNumber() { 270 return number; 271 } 272 273 public void setNumber(String number) { 274 this.number = number; 275 } 276 } 277 278 class UserRecords { 279 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 280 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 281 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 282 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 283 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 284 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 285 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 286 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 287 288 public void addCallingInCityRecords(CallRecord callRecord){ 289 callingInCityRecords.add(callRecord); 290 } 291 public void addCallingInProvinceRecords(CallRecord callRecord){ 292 callingInProvinceRecords.add(callRecord); 293 } 294 public void addCallingInLandRecords(CallRecord callRecord){ 295 callingInLandRecords.add(callRecord); 296 } 297 public void addAnswerInCityRecords(CallRecord callRecord){ 298 answerInCityRecords.add(callRecord); 299 } 300 public void addAnswerInProvinceRecords(CallRecord callRecord){ 301 answerInProvinceRecords.add(callRecord); 302 } 303 public void addAnswerInLandRecords(CallRecord callRecord){ 304 answerInLandRecords.add(callRecord); 305 } 306 public void addSendMessageRecords(MessageRecord sendMessageRecord){ 307 sendMessageRecords.add(sendMessageRecord); 308 } 309 public void addReceiveMessageRecords(MessageRecord receiveMessageRecord){ 310 receiveMessageRecords.add(receiveMessageRecord); 311 } 312 313 public ArrayList<CallRecord> getCallingInCityRecords() { 314 return callingInCityRecords; 315 } 316 317 public ArrayList<CallRecord> getCallingInProvinceRecords() { 318 return callingInProvinceRecords; 319 } 320 321 public ArrayList<CallRecord> getCallingInLandRecords() { 322 return callingInLandRecords; 323 } 324 325 public ArrayList<CallRecord> getAnswerInCityRecords() { 326 return answerInCityRecords; 327 } 328 329 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 330 return answerInProvinceRecords; 331 } 332 333 public ArrayList<CallRecord> getAnswerInLandRecords() { 334 return answerInLandRecords; 335 } 336 337 public ArrayList<MessageRecord> getSendMessageRecords() { 338 return sendMessageRecords; 339 } 340 341 public ArrayList<MessageRecord> getReceiveMessageRecords() { 342 return receiveMessageRecords; 343 } 344 }
分析:
- 在根据题目所给类图的提示下,将类于类之间的关系进行梳理搞明白它们的作用。
- 记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
- 这道题考察了正则表达式的应用,通过正则表达式将输入通话记录数据中出现的不符合格式要求的行一律忽略,并且判断是开户还是拨打电话。
- 还考察了字符串的截取,灵活的运用substring以及split方法将开户电话号码、拨打电话号码、接听电话号码、拨打电话区号、接听电话区号、开始时间以及结束时间分别截取出来。
踩坑心得:
- 由于正则表达式的错误,导致一直把正常的通话记录忽略,导致代码运行一部分错误,可以通过debug找出这种问题,将正则表达式删去重写。
- 因为缺乏常识,不知道北京的区号为3位,正则表达式错误。
- 还有日期格式的正则表达式问题。
- 用户输出要排序。
第二道:
电信计费系列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。
类图如下:



SourceMonitor报表如下:

代码如下(点击可看):
1 import java.text.DecimalFormat; 2 import java.text.ParseException; 3 import java.text.SimpleDateFormat; 4 import java.util.*; 5 6 public class Main { 7 public static void main(String[] args) throws ParseException { 8 Scanner in = new Scanner(System.in); 9 Map <String, User> i = new TreeMap<>(); 10 SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); 11 Date date1,date2; 12 String str; 13 str = in.nextLine(); 14 15 while (!str.equals("end")){ 16 if (str.matches("u-0\\d{9,11}\\s0")){ 17 String[] a = str.split("-|\\s"); 18 User user = new User(a[2],a[1]); 19 i.put(a[1],user); 20 } 21 22 str = in.nextLine(); 23 } 24 25 for (User u : i.values()){ 26 System.out.println(u.getNumber() +" "+ new DecimalFormat("0.0##").format(u.calCost()) + " "+ new DecimalFormat("0.0##").format(u.calBalance())); 27 } 28 } 29 public static boolean isDate(String s){ 30 String[] a = s.split("[.]"); 31 int year = 0,month = 0,day = 0; 32 year = Integer.parseInt(a[0]); 33 month = Integer.parseInt(a[1]); 34 day = Integer.parseInt(a[2]); 35 if((!isLeapYear(year)&&month==2&&day>29)||month>12||month<1||day>31||day<1||(month==2&&day>28)||(month==4&&day>30)||(month==6&&day>30)||(month==9&&day>30)||(month==11&&day>30)) 36 return false; 37 else 38 return true; 39 } 40 public static boolean isLeapYear(int year) { 41 if((year%4==0&&year%100!=0)||year%400==0) return true; 42 else return false; 43 } 44 45 } 46 47 48 class AnswerInLandRecords extends CallChargeRule{ 49 @Override 50 public double calCost(ArrayList<CallRecord> callRecords) { 51 double s = 0; 52 for (CallRecord a : callRecords){ 53 s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 54 } 55 56 return 0.3 * s; 57 } 58 } 59 abstract class CallChargeRule extends ChargeRule{ 60 61 public abstract double calCost(ArrayList<CallRecord> callRecords); 62 } 63 64 class CallRecord extends CommunicationRecord{ 65 private Date startTime; 66 private Date endTime; 67 private String callingAddressAreaCode; 68 private String answerAddressAreaCode; 69 70 public Date getStartTime() { 71 return startTime; 72 } 73 74 public void setStartTime(Date startTime) { 75 this.startTime = startTime; 76 } 77 78 public Date getEndTime() { 79 return endTime; 80 } 81 82 public void setEndTime(Date endTime) { 83 this.endTime = endTime; 84 } 85 86 public String getCallingAddressAreaCode() { 87 return callingAddressAreaCode; 88 } 89 90 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 91 this.callingAddressAreaCode = callingAddressAreaCode; 92 } 93 94 public String getAnswerAddressAreaCode() { 95 return answerAddressAreaCode; 96 } 97 98 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 99 this.answerAddressAreaCode = answerAddressAreaCode; 100 } 101 } 102 abstract class ChargeMode { 103 private ArrayList<ChargeRule> chargeRules = new ArrayList<>(); 104 105 public ChargeMode() { 106 chargeRules.add(new LandPhoneInCityRule()); 107 chargeRules.add(new LandPhoneInProvinceRule()); 108 chargeRules.add(new LandPhoneInLandRule()); 109 chargeRules.add(new AnswerInLandRecords()); 110 } 111 112 public ArrayList<ChargeRule> getChargeRules() { 113 return chargeRules; 114 } 115 116 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 117 this.chargeRules = chargeRules; 118 } 119 120 public abstract double calCost(UserRecords userRecords); 121 122 public abstract double getMonthlyRent(); 123 124 } 125 126 abstract class ChargeRule { 127 public abstract double calCost(ArrayList<CallRecord> callRecords); 128 } 129 abstract class CommunicationRecord { 130 protected String callingNumber; 131 protected String answerNumber; 132 133 public String getCallingNumber() { 134 return callingNumber; 135 } 136 137 public void setCallingNumber(String callingNumber) { 138 this.callingNumber = callingNumber; 139 } 140 141 public String getAnswerNumber() { 142 return answerNumber; 143 } 144 145 public void setAnswerNumber(String answerNumber) { 146 this.answerNumber = answerNumber; 147 } 148 } 149 150 class LandlinePhoneCharging extends ChargeMode{ 151 double monthlyRent = 20; 152 153 public LandlinePhoneCharging() { 154 super(); 155 } 156 @Override 157 public double calCost(UserRecords userRecords) { 158 double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) 159 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) 160 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()); 161 return s; 162 } 163 164 @Override 165 public double getMonthlyRent() { 166 return monthlyRent; 167 } 168 } 169 170 class LandPhoneInCityRule extends CallChargeRule{ 171 @Override 172 public double calCost(ArrayList<CallRecord> callRecords) { 173 double s = 0; 174 double d = 0; 175 for (CallRecord a : callRecords){ 176 d = Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 177 if (!a.getCallingNumber().matches("0\\d+")) { 178 if (a.getAnswerAddressAreaCode().matches("0791")) d = d * 0.1; 179 else if (a.getAnswerAddressAreaCode().matches("(079[^1]|0701)")) d = d * 0.2; 180 else d = d * 0.3; 181 }else { 182 if (a.getAnswerAddressAreaCode().matches("0791")) d = d * 0.1; 183 else if (a.getAnswerAddressAreaCode().matches("(079[^1]|0701)")) d = d * 0.3; 184 else d = d * 0.6; 185 } 186 s+=d; 187 } 188 189 return s; 190 } 191 } 192 class LandPhoneInLandRule extends CallChargeRule{ 193 @Override 194 public double calCost(ArrayList<CallRecord> callRecords) { 195 double s = 0; 196 for (CallRecord a : callRecords){ 197 s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 198 } 199 200 return 0.6 * s; 201 } 202 } 203 class LandPhoneInProvinceRule extends CallChargeRule{ 204 @Override 205 public double calCost(ArrayList<CallRecord> callRecords) { 206 double s = 0; 207 for (CallRecord a : callRecords){ 208 s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 209 } 210 211 return s*0.3; 212 } 213 } 214 class MessageRecord extends CommunicationRecord { 215 private String message; 216 217 public String getMessage() { 218 return message; 219 } 220 221 public void setMessage(String message) { 222 this.message = message; 223 } 224 } 225 226 class PhoneCharging extends ChargeMode{ 227 double monthlyRent = 15; 228 229 public PhoneCharging() { 230 super(); 231 } 232 @Override 233 public double calCost(UserRecords userRecords) { 234 double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) 235 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) 236 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()) 237 + getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords()); 238 return s; 239 } 240 241 @Override 242 public double getMonthlyRent() { 243 return monthlyRent; 244 } 245 } 246 247 class User { 248 private UserRecords userRecords = new UserRecords(); 249 private double balance = 100; 250 private ChargeMode chargeMode; 251 private String number; 252 253 public User(String str ,String number) { 254 if (str.equals("0")) this.chargeMode = new LandlinePhoneCharging(); 255 else this.chargeMode = new PhoneCharging(); 256 this.number = number; 257 } 258 259 public double calBalance(){ 260 return getBalance()-chargeMode.getMonthlyRent()-calCost(); 261 } 262 263 public double calCost(){ 264 return chargeMode.calCost(userRecords); 265 } 266 267 public UserRecords getUserRecords() { 268 return userRecords; 269 } 270 271 public void setUserRecords(UserRecords userRecords) { 272 this.userRecords = userRecords; 273 } 274 275 public double getBalance() { 276 return balance; 277 } 278 279 public ChargeMode getChargeMode() { 280 return chargeMode; 281 } 282 283 public void setChargeMode(ChargeMode chargeMode) { 284 this.chargeMode = chargeMode; 285 } 286 287 public String getNumber() { 288 return number; 289 } 290 291 public void setNumber(String number) { 292 this.number = number; 293 } 294 } 295 class UserRecords { 296 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 297 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 298 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 299 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 300 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 301 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 302 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 303 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 304 305 public void addCallingInCityRecords(CallRecord callRecord){ 306 callingInCityRecords.add(callRecord); 307 } 308 public void addCallingInProvinceRecords(CallRecord callRecord){ 309 callingInProvinceRecords.add(callRecord); 310 } 311 public void addCallingInLandRecords(CallRecord callRecord){ 312 callingInLandRecords.add(callRecord); 313 } 314 public void addAnswerInCityRecords(CallRecord callRecord){ 315 answerInCityRecords.add(callRecord); 316 } 317 public void addAnswerInProvinceRecords(CallRecord callRecord){ 318 answerInProvinceRecords.add(callRecord); 319 } 320 public void addAnswerInLandRecords(CallRecord callRecord){ 321 answerInLandRecords.add(callRecord); 322 } 323 public void addSendMessageRecords(MessageRecord sendMessageRecord){ 324 sendMessageRecords.add(sendMessageRecord); 325 } 326 public void addReceiveMessageRecords(MessageRecord receiveMessageRecord){ 327 receiveMessageRecords.add(receiveMessageRecord); 328 } 329 330 public ArrayList<CallRecord> getCallingInCityRecords() { 331 return callingInCityRecords; 332 } 333 334 public ArrayList<CallRecord> getCallingInProvinceRecords() { 335 return callingInProvinceRecords; 336 } 337 338 public ArrayList<CallRecord> getCallingInLandRecords() { 339 return callingInLandRecords; 340 } 341 342 public ArrayList<CallRecord> getAnswerInCityRecords() { 343 return answerInCityRecords; 344 } 345 346 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 347 return answerInProvinceRecords; 348 } 349 350 public ArrayList<CallRecord> getAnswerInLandRecords() { 351 return answerInLandRecords; 352 } 353 354 public ArrayList<MessageRecord> getSendMessageRecords() { 355 return sendMessageRecords; 356 } 357 358 public ArrayList<MessageRecord> getReceiveMessageRecords() { 359 return receiveMessageRecords; 360 } 361 }
分析:
- 这一次的题在电信计费系列1基础上增加类型1-手机实时计费,被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,根据手机和座机的不同进行不同的费用计算,
- 并且要根据手机现所在地判断是省内漫游或是省外漫游,不同漫游方式每小时价格不同,以及接听电话也要计费,在不同地区接听电话计费价格也不同。
- 有座机打座机,电话打座机,座机打电话,电话打电话。
- 时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
踩坑心得:
- 被打的座机不一定在南昌,我错误地将座机默认为都在南昌从而且导致答案错误。
- 比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码等,此类情况都当成正确的输入计算。
第三道:
电信计费系列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。
本题只考虑短信计费,不考虑通信费用以及月租费。
类图如下:



SourceMonitor报表如下:

代码如下(点击可看):
1 import java.text.DecimalFormat; 2 import java.text.ParseException; 3 import java.text.SimpleDateFormat; 4 import java.util.*; 5 6 public class Main { 7 public static void main(String[] args) throws ParseException { 8 Scanner in = new Scanner(System.in); 9 Map <String, User> i = new TreeMap<>(); 10 SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); 11 Date date1,date2; 12 String str; 13 str = in.nextLine(); 14 15 while (!str.equals("end")){ 16 if (str.matches("u-0\\d{9,11}\\s0")|str.matches("u-1\\d{10}\\s[13]")){ 17 String[] a = str.split("-|\\s"); 18 User user = new User(a[2],a[1]); 19 i.put(a[1],user); 20 }else if (str.matches("t-0\\d{9,11}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}")) { 21 String[] a = str.split("-|\\s"); 22 if (isDate(a[3]) && isDate(a[5])){ 23 date1 = sdf.parse(a[3] + " " + a[4]); 24 date2 = sdf.parse(a[5] + " " + a[6]); 25 for (User u : i.values()) { 26 if (u.getNumber().equals(a[1])) { 27 CallRecord callRecord = new CallRecord(); 28 callRecord.setStartTime(date1); 29 callRecord.setEndTime(date2); 30 callRecord.setCallingNumber(a[1]); 31 callRecord.setAnswerAddressAreaCode(a[2].substring(0,4)); 32 33 u.getUserRecords().addCallingInCityRecords(callRecord); 34 } 35 } 36 } 37 } else if (str.matches("t-1\\d{10}\\s0\\d{2,3}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}")) { 38 String[] a = str.split("-|\\s"); 39 if (isDate(a[4]) && isDate(a[6])) { 40 date1 = sdf.parse(a[4] + " " + a[5]); 41 date2 = sdf.parse(a[6] + " " + a[7]); 42 43 for (User u : i.values()) { 44 if (u.getNumber().equals(a[1])) { 45 CallRecord callRecord = new CallRecord(); 46 callRecord.setStartTime(date1); 47 callRecord.setEndTime(date2); 48 callRecord.setCallingNumber(a[1]); 49 callRecord.setAnswerNumber(a[3]); 50 callRecord.setCallingAddressAreaCode(a[2]); 51 callRecord.setAnswerAddressAreaCode(a[3].substring(0,4)); 52 53 if (a[2].equals("0791")) 54 u.getUserRecords().addCallingInCityRecords(callRecord); 55 else if (a[2].matches("079\\d|0701")) { 56 u.getUserRecords().addCallingInProvinceRecords(callRecord); 57 } else u.getUserRecords().addCallingInLandRecords(callRecord); 58 } 59 } 60 } 61 }else if (str.matches("t-0\\d{9,11}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}")) { 62 String[] a = str.split("-|\\s"); 63 if (isDate(a[4]) && isDate(a[6])) { 64 date1 = sdf.parse(a[4] + " " + a[5]); 65 date2 = sdf.parse(a[6] + " " + a[7]); 66 CallRecord callRecord = new CallRecord(); 67 callRecord.setStartTime(date1); 68 callRecord.setEndTime(date2); 69 callRecord.setCallingNumber(a[1]); 70 callRecord.setAnswerNumber(a[2]); 71 callRecord.setCallingAddressAreaCode("0791"); 72 callRecord.setAnswerAddressAreaCode(a[3]); 73 for (User u : i.values()) { 74 if (u.getNumber().equals(a[1])) { 75 u.getUserRecords().addCallingInCityRecords(callRecord); 76 } 77 } 78 for (User r : i.values()) { 79 if (r.getNumber().equals(a[2])) { 80 if (!a[3].matches("079\\d|0701")) 81 r.getUserRecords().addAnswerInLandRecords(callRecord); 82 } 83 } 84 } 85 }else if (str.matches("t-1\\d{10}\\s0\\d{2,3}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}")) { 86 String[] a = str.split("-|\\s"); 87 if (isDate(a[5]) && isDate(a[7])) { 88 date1 = sdf.parse(a[5] + " " + a[6]); 89 date2 = sdf.parse(a[7] + " " + a[8]); 90 CallRecord callRecord = new CallRecord(); 91 callRecord.setStartTime(date1); 92 callRecord.setEndTime(date2); 93 callRecord.setCallingNumber(a[1]); 94 callRecord.setAnswerNumber(a[3]); 95 callRecord.setCallingAddressAreaCode(a[2]); 96 callRecord.setAnswerAddressAreaCode(a[4]); 97 for (User u : i.values()) { 98 if (u.getNumber().equals(a[1])) { 99 100 if (a[2].equals("0791")) 101 u.getUserRecords().addCallingInCityRecords(callRecord); 102 else if (a[2].length()==4&& a[2].startsWith("079") || a[2].equals("0701")) { 103 u.getUserRecords().addCallingInProvinceRecords(callRecord); 104 } else u.getUserRecords().addCallingInLandRecords(callRecord); 105 } 106 } 107 for (User r : i.values()) { 108 if (r.getNumber().equals(a[3])) { 109 if (!a[4].matches("(079\\d|0701)")) 110 r.getUserRecords().addAnswerInLandRecords(callRecord); 111 } 112 } 113 } 114 }else if (str.matches("m-1\\d{10}\\s1\\d{10}\\s(\\d|\\w|\\s|,|[.])+")){ 115 String[] a = str.split("-|\\s"); 116 String str1 = str.substring(26); 117 MessageRecord messageRecord = new MessageRecord(); 118 messageRecord.setMessage(str1); 119 120 for (User u : i.values()) { 121 if (u.getNumber().equals(a[1])) { 122 u.getUserRecords().addSendMessageRecords(messageRecord); 123 } 124 } 125 } 126 str = in.nextLine(); 127 } 128 129 for (User u : i.values()){ 130 System.out.println(u.getNumber() +" "+ new DecimalFormat("0.0##").format(u.calCost()) + " "+ new DecimalFormat("0.0##").format(u.calBalance())); 131 } 132 } 133 public static boolean isDate(String s){ 134 String[] a = s.split("[.]"); 135 int year ,month ,day; 136 year = Integer.parseInt(a[0]); 137 month = Integer.parseInt(a[1]); 138 day = Integer.parseInt(a[2]); 139 return (isLeapYear(year) || month != 2 || day <= 29) && month <= 12 && month >= 1 && day <= 31 && day >= 1 && (month != 2 || day <= 28) && (month != 4 || day <= 30) && (month != 6 || day <= 30) && (month != 9 || day <= 30) && (month != 11 || day <= 30); 140 } 141 public static boolean isLeapYear(int year) { 142 return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; 143 } 144 145 } 146 class AnswerInLandRecords extends CallChargeRule{ 147 @Override 148 public double calCost1(ArrayList<MessageRecord> messageRecords) { 149 return 0; 150 } 151 152 @Override 153 public double calCost(ArrayList<CallRecord> callRecords) { 154 double s = 0; 155 for (CallRecord a : callRecords){ 156 s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 157 } 158 159 return 0.3 * s; 160 } 161 } 162 abstract class CallChargeRule extends ChargeRule{ 163 @Override 164 public abstract double calCost(ArrayList<CallRecord> callRecords); 165 } 166 class CallRecord extends CommunicationRecord{ 167 private Date startTime; 168 private Date endTime; 169 private String callingAddressAreaCode; 170 private String answerAddressAreaCode; 171 172 public Date getStartTime() { 173 return startTime; 174 } 175 176 public void setStartTime(Date startTime) { 177 this.startTime = startTime; 178 } 179 180 public Date getEndTime() { 181 return endTime; 182 } 183 184 public void setEndTime(Date endTime) { 185 this.endTime = endTime; 186 } 187 188 public String getCallingAddressAreaCode() { 189 return callingAddressAreaCode; 190 } 191 192 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 193 this.callingAddressAreaCode = callingAddressAreaCode; 194 } 195 196 public String getAnswerAddressAreaCode() { 197 return answerAddressAreaCode; 198 } 199 200 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 201 this.answerAddressAreaCode = answerAddressAreaCode; 202 } 203 } 204 abstract class ChargeMode { 205 private ArrayList<ChargeRule> chargeRules = new ArrayList<>(); 206 207 public ChargeMode() { 208 chargeRules.add(new LandPhoneInCityRule()); 209 chargeRules.add(new LandPhoneInProvinceRule()); 210 chargeRules.add(new LandPhoneInLandRule()); 211 chargeRules.add(new AnswerInLandRecords()); 212 chargeRules.add(new SendMessageRule()); 213 } 214 215 public ArrayList<ChargeRule> getChargeRules() { 216 return chargeRules; 217 } 218 219 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 220 this.chargeRules = chargeRules; 221 } 222 223 public abstract double calCost(UserRecords userRecords); 224 225 public abstract double getMonthlyRent(); 226 227 } 228 abstract class ChargeRule { 229 public abstract double calCost1(ArrayList<MessageRecord> messageRecords); 230 public abstract double calCost(ArrayList<CallRecord> callRecords); 231 } 232 abstract class CommunicationRecord { 233 protected String callingNumber; 234 protected String answerNumber; 235 236 public String getCallingNumber() { 237 return callingNumber; 238 } 239 240 public void setCallingNumber(String callingNumber) { 241 this.callingNumber = callingNumber; 242 } 243 244 public String getAnswerNumber() { 245 return answerNumber; 246 } 247 248 public void setAnswerNumber(String answerNumber) { 249 this.answerNumber = answerNumber; 250 } 251 } 252 class LandlinePhoneCharging extends ChargeMode{ 253 double monthlyRent = 20; 254 255 public LandlinePhoneCharging() { 256 super(); 257 } 258 @Override 259 public double calCost(UserRecords userRecords) { 260 double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) 261 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) 262 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()); 263 return s; 264 } 265 266 @Override 267 public double getMonthlyRent() { 268 return monthlyRent; 269 } 270 } 271 class LandPhoneInCityRule extends CallChargeRule{ 272 @Override 273 public double calCost1(ArrayList<MessageRecord> messageRecords) { 274 return 0; 275 } 276 277 @Override 278 public double calCost(ArrayList<CallRecord> callRecords) { 279 double s = 0; 280 double d; 281 for (CallRecord a : callRecords){ 282 d = Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 283 if (!a.getCallingNumber().matches("0\\d+")) { 284 if (a.getAnswerAddressAreaCode().matches("0791")) d = d * 0.1; 285 else if (a.getAnswerAddressAreaCode().matches("(079\\d|0701)")) d = d * 0.2; 286 else d = d * 0.3; 287 }else { 288 if (a.getAnswerAddressAreaCode().matches("0791")) d = d * 0.1; 289 else if (a.getAnswerAddressAreaCode().matches("(079[^1]|0701)")) d = d * 0.3; 290 else d = d * 0.6; 291 } 292 s+=d; 293 } 294 295 return s; 296 } 297 } 298 class LandPhoneInLandRule extends CallChargeRule{ 299 @Override 300 public double calCost1(ArrayList<MessageRecord> messageRecords) { 301 return 0; 302 } 303 304 @Override 305 public double calCost(ArrayList<CallRecord> callRecords) { 306 double s = 0; 307 for (CallRecord a : callRecords){ 308 s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 309 } 310 311 return 0.6 * s; 312 } 313 } 314 class LandPhoneInProvinceRule extends CallChargeRule{ 315 @Override 316 public double calCost1(ArrayList<MessageRecord> messageRecords) { 317 return 0; 318 } 319 320 @Override 321 public double calCost(ArrayList<CallRecord> callRecords) { 322 double s = 0; 323 for (CallRecord a : callRecords){ 324 s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0); 325 } 326 327 return s*0.3; 328 } 329 } 330 abstract class MessageChargeRule extends ChargeRule{ 331 @Override 332 public abstract double calCost1(ArrayList<MessageRecord> messageRecords); 333 334 335 } 336 class MessageCharging extends ChargeMode{ 337 double monthlyRent = 0; 338 @Override 339 public double calCost(UserRecords userRecords) { 340 return getChargeRules().get(4).calCost1(userRecords.getSendMessageRecords()); 341 } 342 343 @Override 344 public double getMonthlyRent() { 345 return monthlyRent; 346 } 347 } 348 class MessageRecord extends CommunicationRecord { 349 private String message; 350 351 public String getMessage() { 352 return message; 353 } 354 355 public void setMessage(String message) { 356 this.message = message; 357 } 358 } 359 class PhoneCharging extends ChargeMode{ 360 double monthlyRent = 15; 361 362 public PhoneCharging() { 363 super(); 364 } 365 @Override 366 public double calCost(UserRecords userRecords) { 367 double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) 368 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) 369 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()) 370 + getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords()); 371 return s; 372 } 373 374 @Override 375 public double getMonthlyRent() { 376 return monthlyRent; 377 } 378 } 379 class SendMessageRule extends MessageChargeRule{ 380 @Override 381 public double calCost1(ArrayList<MessageRecord> messageRecords) { 382 double n = 0; 383 double s = 0; 384 for (MessageRecord a : messageRecords){ 385 s = Math.ceil(a.getMessage().length()/10.0); 386 n+=s; 387 } 388 389 if (n>5) return (n-5)*0.3 + 0.7; 390 else if (n>3) return (n-3)*0.2 + 0.3; 391 else return n*0.1; 392 } 393 394 @Override 395 public double calCost(ArrayList<CallRecord> callRecords) { 396 return 0; 397 } 398 } 399 class User { 400 private UserRecords userRecords = new UserRecords(); 401 private double balance = 100; 402 private ChargeMode chargeMode; 403 private String number; 404 405 public User(String str ,String number) { 406 if (str.equals("0")) this.chargeMode = new LandlinePhoneCharging(); 407 else if (str.equals("1"))this.chargeMode = new PhoneCharging(); 408 else if (str.equals("3")) this.chargeMode = new MessageCharging(); 409 this.number = number; 410 } 411 412 public double calBalance(){ 413 return getBalance()-chargeMode.getMonthlyRent()-calCost(); 414 } 415 416 public double calCost(){ 417 return chargeMode.calCost(userRecords); 418 } 419 420 public UserRecords getUserRecords() { 421 return userRecords; 422 } 423 424 public void setUserRecords(UserRecords userRecords) { 425 this.userRecords = userRecords; 426 } 427 428 public double getBalance() { 429 return balance; 430 } 431 432 public ChargeMode getChargeMode() { 433 return chargeMode; 434 } 435 436 public void setChargeMode(ChargeMode chargeMode) { 437 this.chargeMode = chargeMode; 438 } 439 440 public String getNumber() { 441 return number; 442 } 443 444 public void setNumber(String number) { 445 this.number = number; 446 } 447 } 448 class UserRecords { 449 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>(); 450 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>(); 451 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>(); 452 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>(); 453 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>(); 454 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>(); 455 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>(); 456 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>(); 457 458 public void addCallingInCityRecords(CallRecord callRecord){ 459 callingInCityRecords.add(callRecord); 460 } 461 public void addCallingInProvinceRecords(CallRecord callRecord){ 462 callingInProvinceRecords.add(callRecord); 463 } 464 public void addCallingInLandRecords(CallRecord callRecord){ 465 callingInLandRecords.add(callRecord); 466 } 467 public void addAnswerInCityRecords(CallRecord callRecord){ 468 answerInCityRecords.add(callRecord); 469 } 470 public void addAnswerInProvinceRecords(CallRecord callRecord){ 471 answerInProvinceRecords.add(callRecord); 472 } 473 public void addAnswerInLandRecords(CallRecord callRecord){ 474 answerInLandRecords.add(callRecord); 475 } 476 public void addSendMessageRecords(MessageRecord sendMessageRecord){ 477 sendMessageRecords.add(sendMessageRecord); 478 } 479 public void addReceiveMessageRecords(MessageRecord receiveMessageRecord){ 480 receiveMessageRecords.add(receiveMessageRecord); 481 } 482 483 public ArrayList<CallRecord> getCallingInCityRecords() { 484 return callingInCityRecords; 485 } 486 487 public ArrayList<CallRecord> getCallingInProvinceRecords() { 488 return callingInProvinceRecords; 489 } 490 491 public ArrayList<CallRecord> getCallingInLandRecords() { 492 return callingInLandRecords; 493 } 494 495 public ArrayList<CallRecord> getAnswerInCityRecords() { 496 return answerInCityRecords; 497 } 498 499 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 500 return answerInProvinceRecords; 501 } 502 503 public ArrayList<CallRecord> getAnswerInLandRecords() { 504 return answerInLandRecords; 505 } 506 507 public ArrayList<MessageRecord> getSendMessageRecords() { 508 return sendMessageRecords; 509 } 510 511 public ArrayList<MessageRecord> getReceiveMessageRecords() { 512 return receiveMessageRecords; 513 } 514 }
分析:
- 这一次题目集与前两道题相比难度有所降低,每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
- 接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
- 如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
踩坑心得:
- 第一次没有注意看题目,短信条数超过之前的还是算之前的价格计算,我把短信条数x最后的价格了导致我答案错误。
- 本题相对简单无坑。
改进建议:
无;
总结:
- 这学期的Java题目集比上个学期的C难度提升了很多,需要自学的东西很多,所以花费的时间多了。
- 在编写代码时需要绝对的认真,不能被打扰 ,精力不集中时容易写出BUG。
- 在代码之前先要整体的规划,这几次作业是老师给了类图,如果没给就需要自己设计,自己设计会有些难度。
- java还有很多很多工具功能没学,在今后尽量学习更多。
浙公网安备 33010602011771号