第三次博客作业
前言:这是本学期最后一次blog作业,最后一次的pta作业也降低了许多难度。
这三次作业主要是写电信计费功能,考察的知识点有很多。例如:lamda表达式的
运用,SimpleDate类的运用。相比之前难度降低,所以对我来说相对简单。
实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租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
以下是源码:
1 import java.util.Scanner; 2 import java.util.ArrayList; 3 import java.text.ParseException; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 import java.util.Collections; 7 8 public class Main { 9 public static void main(String[] args)throws Exception{ 10 Scanner input = new Scanner(System.in); 11 ArrayList<User> user = new ArrayList<>(); 12 ParseInput parseInput = new ParseInput(); 13 String s = input.nextLine(); 14 String regex = "[u][-]0791[0-9]{7,8}[ ][0]"; 15 String regex_ = ""; 16 int i = 0; 17 boolean flag = false; 18 while (!s.equals("end")){ 19 if(s.matches(regex)) { 20 for (int l = 0; l<user.size(); l++) { 21 if (parseInput.ParseInputNumber(s).equals(user.get(l).getNumber())) { 22 flag = true; 23 } 24 } 25 if (!flag) { 26 user.add(new User(parseInput.ParseInputNumber(s))); 27 user.get(i).setUsersRecords(new UsersRecords()); 28 i++; 29 regex_ = "[t][-]0791[0-9]{7,8}[ ][0-9]{10,12}[ ]([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9])[\\.]([1-9]|[1-9][0-9])[\\.]([1-9]|[1-9][0-9])[ ]([0-1][0-9]|2[0-3])[:][0-5][0-9][:][0-5][0-9][ ]([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9])[\\.]([1-9]|[1-9][0-9])[\\.]([1-9]|[1-9][0-9])[ ]([0-1][0-9]|2[0-3])[:][0-5][0-9][:][0-5][0-9]"; 30 } 31 } 32 else if(s.matches(regex_)) { 33 if (parseInput.ParseTimeFormat(s)) { 34 int j = 0; 35 for (; j<user.size(); j++) { 36 if (user.get(j).getNumber().equals(parseInput.ParseInputCalNumber(s))) { 37 CallRecord callRecord = new CallRecord(); 38 callRecord.setStartTime(parseInput.ParseInputStartDate(s)); 39 callRecord.setEndTime(parseInput.ParseInputEndData(s)); 40 callRecord.setCallingNumber(parseInput.ParseInputCalNumber(s)); 41 callRecord.setAnswerNumber(parseInput.ParseInputAnswerNumber(s)); 42 if (parseInput.ParseNumberArea(callRecord.getAnswerNumber()) == 1) { 43 user.get(j).getUsersRecords().addCallingInCityRecords(callRecord); 44 } else if (parseInput.ParseNumberArea(callRecord.getAnswerNumber()) == 2) { 45 user.get(j).getUsersRecords().addCallingInProvinceRecords(callRecord); 46 } else if(parseInput.ParseNumberArea(callRecord.getAnswerNumber())==0){ 47 user.get(j).getUsersRecords().addCallingInLandRecords(callRecord); 48 } 49 } 50 } 51 } 52 } 53 s = input.nextLine(); 54 } 55 56 Collections.sort(user); 57 58 for (i = 0;i< user.size();i++){ 59 System.out.println(user.get(i).getNumber()+" "+String.format("%.1f",user.get(i).CalCost())+" "+String.format("%.1f",user.get(i).CalBalance())); 60 } 61 } 62 } 63 abstract class CallChargeRule extends ChargeRule{ 64 public abstract double calCost(ArrayList<CallRecord> callRecords) throws Exception; 65 66 } 67 class CallRecord extends CommunicationRecord { 68 private Date startTime; 69 private Date endTime; 70 71 private String callingAddressAreaCode; 72 private String answerAddressAreaCode; 73 74 public Date getStartTime() { 75 return startTime; 76 } 77 78 public void setStartTime(Date startTime) { 79 this.startTime = startTime; 80 } 81 82 public Date getEndTime() { 83 return endTime; 84 } 85 86 public void setEndTime(Date endTime) { 87 this.endTime = endTime; 88 } 89 90 public String getCallingAddressAreaCode() { 91 return callingAddressAreaCode; 92 } 93 94 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 95 this.callingAddressAreaCode = callingAddressAreaCode; 96 } 97 98 public String getAnswerAddressAreaCode() { 99 return answerAddressAreaCode; 100 } 101 102 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 103 this.answerAddressAreaCode = answerAddressAreaCode; 104 } 105 106 public int getTimeOf() throws Exception { 107 SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 108 String start = simpleFormat.format(startTime); 109 String end = simpleFormat.format(endTime); 110 Date fromM = simpleFormat.parse(start.substring(0, 16)); 111 Date toM = simpleFormat.parse(end.substring(0, 16)); 112 113 simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 114 start = simpleFormat.format(startTime); 115 end = simpleFormat.format(endTime); 116 int secondStart = Integer.parseInt(start.substring(17, 19)); 117 int secondEnd = Integer.parseInt(end.substring(17, 19)); 118 119 long from = fromM.getTime(); 120 long to = toM.getTime(); 121 int gap = (int) ((to - from) / (1000 * 60)); 122 123 if (secondEnd > secondStart) { 124 gap++; 125 } 126 127 if (gap > 0) { 128 return gap; 129 } else return 0; 130 } 131 } 132 abstract class ChargeMode { 133 public ArrayList<ChargeRule> getChargeRules() { 134 return chargeRules; 135 } 136 137 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 138 this.chargeRules = chargeRules; 139 } 140 141 private ArrayList<ChargeRule> chargeRules = new ArrayList<ChargeRule>(); 142 143 public abstract double CalCost(UsersRecords usersRecords) throws Exception; 144 145 public abstract double getMonthlyRent(); 146 } 147 abstract class ChargeRule { 148 } 149 abstract class CommunicationRecord { 150 protected String callingNumber; 151 protected String answerNumber; 152 153 public String getCallingNumber() { 154 return callingNumber; 155 } 156 157 public void setCallingNumber(String callingNumber) { 158 this.callingNumber = callingNumber; 159 } 160 161 public String getAnswerNumber() { 162 return answerNumber; 163 } 164 165 public void setAnswerNumber(String answerNumber) { 166 this.answerNumber = answerNumber; 167 } 168 } 169 class DateUtil { 170 171 private int year; 172 private int month; 173 private int day; 174 175 public DateUtil(){ 176 177 } 178 179 public int getYear() { 180 return year; 181 } 182 183 public void setYear(int year) { 184 this.year = year; 185 } 186 187 public int getMonth() { 188 return month; 189 } 190 191 public void setMonth(int month) { 192 this.month = month; 193 } 194 195 public int getDay() { 196 return day; 197 } 198 199 public void setDay(int day) { 200 this.day = day; 201 } 202 203 public DateUtil(int year, int month, int day){ 204 this.year = year; 205 this.month = month; 206 this.day = day; 207 } 208 209 public boolean checkInputValidity(){ 210 if (month > 0 && month < 13 && day > 0 && day < 32) { 211 if (isLeapYear(year)) { 212 if ((day>29&&month==2)||(day>30&&month==4)||(day>30&&month==6)||(day>30&&month==9)||(day>30&&month==11)){ 213 return false; 214 } else { 215 return true; 216 } 217 } 218 else { 219 if ((day>28&&month==2)||(day>30&&month==4)||(day>30&&month==6)||(day>30&&month==9)||(day>30&&month==11)) { 220 return false; 221 } else { 222 return true; 223 } 224 } 225 } 226 else { 227 return false; 228 } 229 }//检测输入的年、月、日是否合法 230 public boolean isLeapYear(int year){ 231 if(year%400==0){ 232 return true; 233 } 234 else if(year%4==0&&year%100!=0){ 235 return true; 236 } 237 else { 238 return false; 239 } 240 }//判断year是否为闰年 241 } 242 class LandingPhoneCharging extends ChargeMode{ 243 244 CallChargeRule city = new LandPhoneInCityRule(); 245 CallChargeRule province = new LandPhoneInProvinceRule(); 246 CallChargeRule land = new LandPhoneInLandRule(); 247 248 @Override 249 public double CalCost(UsersRecords usersRecords) throws Exception{ 250 double sum = 0; 251 sum += city.calCost(usersRecords.getCallingInCityRecords()); 252 sum += province.calCost(usersRecords.getCallingInProvinceRecords()); 253 sum += land.calCost(usersRecords.getCallingInLandRecords()); 254 return sum; 255 } 256 257 @Override 258 public double getMonthlyRent() { 259 return monthlyRent; 260 } 261 262 private double monthlyRent = 20; 263 } 264 class LandPhoneInCityRule extends CallChargeRule{ 265 @Override 266 public double calCost(ArrayList<CallRecord> callRecords)throws Exception{ 267 int i = 0; 268 double sum = 0; 269 for(;i<callRecords.size();i++){ 270 sum += callRecords.get(i).getTimeOf()*0.1; 271 } 272 return sum; 273 } 274 } 275 class LandPhoneInLandRule extends CallChargeRule{ 276 @Override 277 public double calCost(ArrayList<CallRecord> callRecords)throws Exception { 278 int i = 0; 279 double sum = 0; 280 for(;i<callRecords.size();i++){ 281 sum += callRecords.get(i).getTimeOf()*0.6; 282 } 283 return sum; 284 } 285 } 286 class LandPhoneInProvinceRule extends CallChargeRule{ 287 @Override 288 public double calCost(ArrayList<CallRecord> callRecords)throws Exception { 289 int i = 0; 290 double sum = 0; 291 for(;i<callRecords.size();i++){ 292 sum += callRecords.get(i).getTimeOf()*0.3; 293 } 294 return sum; 295 } 296 } 297 class MessageRecord extends CommunicationRecord{ 298 private String message; 299 300 public String getMessage() { 301 return message; 302 } 303 304 public void setMessage(String message) { 305 this.message = message; 306 } 307 } 308 class ParseInput { 309 310 public String ParseInputNumber(String s){ 311 String ss[]=s.split("-"); 312 String sss[] =ss[1].split(" "); 313 return sss[0]; 314 } 315 316 public Date ParseInputStartDate(String s){ 317 String ss[]=s.split("-"); 318 String sss[] =ss[1].split(" "); 319 String ssss[] = sss[2].split("\\."); 320 String time[] = sss[3].split(":"); 321 int year = Integer.parseInt(ssss[0]); 322 int month = Integer.parseInt(ssss[1]); 323 int day = Integer.parseInt(ssss[2]); 324 int hour = Integer.parseInt(time[0]); 325 int minute = Integer.parseInt(time[1]); 326 int second = Integer.parseInt(time[2]); 327 Date date = new Date(year,month,day,hour,minute,second); 328 return date; 329 } 330 331 public Date ParseInputEndData(String s){ 332 String ss[]=s.split("-"); 333 String sss[] =ss[1].split(" "); 334 String ssss[] = sss[4].split("\\."); 335 String time[] = sss[5].split(":"); 336 int year = Integer.parseInt(ssss[0]); 337 int month = Integer.parseInt(ssss[1]); 338 int day = Integer.parseInt(ssss[2]); 339 int hour = Integer.parseInt(time[0]); 340 int minute = Integer.parseInt(time[1]); 341 int second = Integer.parseInt(time[2]); 342 Date date = new Date(year,month,day,hour,minute,second); 343 return date; 344 } 345 346 public String ParseInputCalNumber(String s){ 347 String ss[]=s.split("-"); 348 String sss[] = ss[1].split(" "); 349 return sss[0]; 350 } 351 352 public String ParseInputAnswerNumber(String s){ 353 String ss[]=s.split("-"); 354 String sss[] = ss[1].split(" "); 355 return sss[1]; 356 } 357 358 public int ParseNumberArea(String s){ 359 String regex1 = "0791[0-9]{7,8}"; 360 String regex2 = "079[023456789][0-9]{7,8}"; 361 String regex3 = "0701[0-9]{7,8}"; 362 if(s.matches(regex1)) { 363 return 1; 364 } 365 else if(s.matches(regex2)||s.matches(regex3)) { 366 return 2; 367 } 368 return 0; 369 } 370 371 public boolean ParseTimeFormat(String s){ 372 String ss[]=s.split("-"); 373 String sss[] =ss[1].split(" "); 374 String startDate[] = sss[2].split("\\."); 375 String endDate[] = sss[4].split("\\."); 376 377 378 DateUtil dateUtilStart = new DateUtil(Integer.parseInt(startDate[0]), Integer.parseInt(startDate[1]), Integer.parseInt(startDate[2])); 379 DateUtil dateUtilEnd = new DateUtil(Integer.parseInt(endDate[0]),Integer.parseInt(endDate[1]),Integer.parseInt(endDate[2])); 380 381 382 return dateUtilEnd.checkInputValidity()&&dateUtilStart.checkInputValidity(); 383 } 384 } 385 class User implements Comparable<User>{ 386 387 private UsersRecords usersRecords = new UsersRecords(); 388 private double balance = 100; 389 private ChargeMode chargeMode; 390 private String number; 391 392 public User(String number){ 393 this.number = number; 394 } 395 396 public User() { 397 398 } 399 400 public double CalCost()throws Exception{ 401 chargeMode = new LandingPhoneCharging(); 402 return chargeMode.CalCost(getUsersRecords()); 403 } 404 405 public double CalBalance()throws Exception{ 406 this.balance = balance - CalCost() - chargeMode.getMonthlyRent(); 407 return balance; 408 } 409 410 public double getBalance() { 411 return balance; 412 } 413 414 public UsersRecords getUsersRecords() { 415 return usersRecords; 416 } 417 418 public void setUsersRecords(UsersRecords usersRecords) { 419 this.usersRecords = usersRecords; 420 } 421 422 public ChargeMode getChargeMode() { 423 return chargeMode; 424 } 425 426 public void setChargeMode(ChargeMode chargeMode) { 427 this.chargeMode = chargeMode; 428 } 429 430 public String getNumber() { 431 return number; 432 } 433 434 public void setNumber(String number) { 435 this.number = number; 436 } 437 438 @Override 439 public int compareTo(User o) { 440 return this.getNumber().compareTo(o.getNumber()); 441 } 442 } 443 class UsersRecords { 444 445 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();//市内拨打电话 446 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();//省内拨打电话 447 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();//国内拨打电话 448 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();//市内接听电话 449 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();//省内接听电话 450 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();//国内接听电话 451 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();//发出短信 452 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();//接收短信 453 454 public ArrayList<CallRecord> getCallingInCityRecords() { 455 return callingInCityRecords; 456 } 457 458 public ArrayList<CallRecord> getCallingInProvinceRecords() { 459 return callingInProvinceRecords; 460 } 461 462 public ArrayList<CallRecord> getCallingInLandRecords() { 463 return callingInLandRecords; 464 } 465 466 public ArrayList<CallRecord> getAnswerInCityRecords() { 467 return answerInCityRecords; 468 } 469 470 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 471 return answerInProvinceRecords; 472 } 473 474 public ArrayList<CallRecord> getAnswerInLandRecords() { 475 return answerInLandRecords; 476 } 477 478 public ArrayList<MessageRecord> getSendMessageRecords() { 479 return sendMessageRecords; 480 } 481 482 public ArrayList<MessageRecord> getReceiveMessageRecords() { 483 return receiveMessageRecords; 484 } 485 486 public void addCallingInCityRecords(CallRecord callRecord){ 487 callingInCityRecords.add(callRecord); 488 } 489 490 public void addCallingInProvinceRecords(CallRecord callRecord){ 491 callingInProvinceRecords.add(callRecord); 492 } 493 494 public void addCallingInLandRecords(CallRecord callRecord){ 495 callingInLandRecords.add(callRecord); 496 } 497 498 public void addAnswerInCityRecords(CallRecord callRecord){ 499 answerInCityRecords.add(callRecord); 500 } 501 502 public void addAnswerInProvinceRecords(CallRecord callRecord){ 503 answerInProvinceRecords.add(callRecord); 504 } 505 506 public void addAnswerInLandRecords(CallRecord callRecord){ 507 answerInLandRecords.add(callRecord); 508 } 509 510 public void addSendMessageRecords(MessageRecord messageRecord){ 511 sendMessageRecords.add(messageRecord); 512 } 513 514 public void addReceiveMessageRecords(MessageRecord messageRecord){ 515 receiveMessageRecords.add(messageRecord); 516 } 517 }
这是类图
分析:
这道题要先判断电话号码的区域从而再将通话记录给分成不同的类型
最后在进行对话费的计算。
要注意的点:对于输入的通话记录进行格式判断。
对于输入的通话记录中的时间也要进行判断
实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
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)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
代码如下:
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.Scanner; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 public class Main { 7 public static void main(String[] args)throws Exception { 8 Scanner input = new Scanner(System.in); 9 ArrayList<User> user = new ArrayList<>(); 10 ParseInput parseInput = new ParseInput(); 11 String s = input.nextLine(); 12 String regex = "[u][-]0791[0-9]{7,8}[ ][0]"; 13 String regex2 = "[u][-][1][0-9]{10}[ ][1]"; 14 String regex_ = ""; 15 String regex2_ = " "; 16 int i = 0; 17 boolean flag = false; 18 while (!s.equals("end")) { 19 if (s.matches(regex)) { 20 for (int l = 0; l < user.size(); l++) { 21 if (parseInput.ParseInputNumber(s).equals(user.get(l).getNumber())) { 22 flag = true; 23 } 24 } 25 if (!flag) { 26 user.add(new User(parseInput.ParseInputNumber(s))); 27 user.get(i).setUsersRecords(new UsersRecords()); 28 i++; 29 regex_ = "[t][-]0791[0-9]{7,8}[ ][0-9]{10,12}[ ]([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[ ]([0-1][0-9]|2[0-3])[:][0-5][0-9][:][0-5][0-9][ ]([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[ ]([0-1][0-9]|2[0-3])[:][0-5][0-9][:][0-5][0-9]"; 30 regex2_ = "[t][-]([0-9]{10,12}|1[0-9]{10}[ ][0-9]{3,4})[ ](1[0-9]{10}[ ][0-9]{3,4}|[0-9]{10,12})[ ]([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[ ]([0-1][0-9]|2[0-3])[:][0-5][0-9][:][0-5][0-9][ ]([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[\\\\.]([1-9]|[1-9][0-9])[ ]([0-1][0-9]|2[0-3])[:][0-5][0-9][:][0-5][0-9]"; 31 } 32 flag = false; 33 } else if (s.matches(regex2)) { 34 for (int l = 0; l < user.size(); l++) { 35 if (parseInput.ParseInputNumber(s).equals(user.get(l).getNumber())) { 36 flag = true; 37 } 38 } 39 if (!flag) { 40 user.add(new User(parseInput.ParseInputNumber(s))); 41 user.get(i).setUsersRecords(new UsersRecords()); 42 i++; 43 } 44 flag =false; 45 } else if (s.matches("t-0791\\d{7,8} 0\\d{9,11} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2}")) { 46 if (parseInput.ParseTimeFormat(s)) { 47 int j = 0; 48 for (; j < user.size(); j++) { 49 if (user.get(j).getNumber().equals(parseInput.ParseInputCalNumber(s))) { 50 CallRecord callRecord = new CallRecord(); 51 callRecord.setStartTime(parseInput.ParseInputStartDate(s)); 52 callRecord.setEndTime(parseInput.ParseInputEndData(s)); 53 callRecord.setCallingNumber(parseInput.ParseInputCalNumber(s)); 54 callRecord.setAnswerNumber(parseInput.ParseInputAnswerNumber(s)); 55 callRecord.setAnswerAddressAreaCode(parseInput.EndParseArea(s)); 56 callRecord.setCallingAddressAreaCode(parseInput.StartParseArea(s)); 57 if (parseInput.ParseNumberArea(callRecord.getAnswerNumber()) == 1) { 58 user.get(j).getUsersRecords().addCallingInCityRecords(callRecord); 59 } else if (parseInput.ParseNumberArea(callRecord.getAnswerNumber()) == 2) { 60 user.get(j).getUsersRecords().addCallingInProvinceRecords(callRecord); 61 } else if (parseInput.ParseNumberArea(callRecord.getAnswerNumber()) == 0) { 62 user.get(j).getUsersRecords().addCallingInLandRecords(callRecord); 63 } 64 } 65 } 66 } 67 68 } 69 else if(s.matches("t-0791\\d{7,8} 1\\d{10} 0\\d{2,3} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2}")) { 70 if (parseInput.ParseTimeFormat(s)) { 71 int j = 0; 72 for (; j < user.size(); j++) { 73 if (user.get(j).getNumber().equals(parseInput.ParseInputCalNumber(s))) { 74 CallRecord callRecord = new CallRecord(); 75 callRecord.setStartTime(parseInput.ParseInputStartDate(s)); 76 callRecord.setEndTime(parseInput.ParseInputEndData(s)); 77 callRecord.setCallingNumber(parseInput.ParseInputCalNumber(s)); 78 callRecord.setAnswerNumber(parseInput.ParseInputAnswerNumber(s)); 79 callRecord.setAnswerAddressAreaCode(parseInput.EndParseArea(s)); 80 callRecord.setCallingAddressAreaCode(parseInput.StartParseArea(s)); 81 if (callRecord.getAnswerAddressAreaCode().matches("0791")) { 82 user.get(j).getUsersRecords().addCallingInCityRecords(callRecord); 83 } else if (callRecord.getAnswerAddressAreaCode().matches("[0][7][9][234567890]|[0][7][0][1]")) { 84 user.get(j).getUsersRecords().addCallingInProvinceRecords(callRecord); 85 } else user.get(j).getUsersRecords().addCallingInLandRecords(callRecord); 86 } 87 } 88 int k = 0; 89 for (; k < user.size(); k++) { 90 if (user.get(k).getNumber().equals(parseInput.ParseInputAnswerNumber(s))) { 91 CallRecord callRecord = new CallRecord(); 92 callRecord.setStartTime(parseInput.ParseInputStartDate(s)); 93 callRecord.setEndTime(parseInput.ParseInputEndData(s)); 94 callRecord.setCallingNumber(parseInput.ParseInputCalNumber(s)); 95 callRecord.setAnswerNumber(parseInput.ParseInputAnswerNumber(s)); 96 callRecord.setAnswerAddressAreaCode(parseInput.EndParseArea(s)); 97 callRecord.setCallingAddressAreaCode(parseInput.StartParseArea(s)); 98 if (callRecord.getAnswerAddressAreaCode().matches("0791")) { 99 user.get(k).getUsersRecords().addAnswerInCityRecords(callRecord); 100 } else if (callRecord.getAnswerAddressAreaCode().matches("[0][7][9][234567890]|[0][7][0][1]")) { 101 user.get(k).getUsersRecords().addAnswerInProvinceRecords(callRecord); 102 } else user.get(k).getUsersRecords().addAnswerInLandRecords(callRecord); 103 } 104 } 105 } 106 107 } 108 else if(s.matches("t-1\\d{10} 0\\d{2,3} 0\\d{9,11} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2}")){ 109 int j = 0; 110 for (; j < user.size(); j++) { 111 if (user.get(j).getNumber().equals(parseInput.ParseInputCalNumber(s))) { 112 CallRecord callRecord = new CallRecord(); 113 callRecord.setStartTime(parseInput.ParseInputStartDate(s)); 114 callRecord.setEndTime(parseInput.ParseInputEndData(s)); 115 callRecord.setCallingNumber(parseInput.ParseInputCalNumber(s)); 116 callRecord.setAnswerNumber(parseInput.ParseInputAnswerNumber(s)); 117 callRecord.setAnswerAddressAreaCode(parseInput.EndParseArea(s)); 118 callRecord.setCallingAddressAreaCode(parseInput.StartParseArea(s)); 119 if (callRecord.getCallingAddressAreaCode().matches("0791")){ 120 if(callRecord.getAnswerAddressAreaCode().matches("0791")){ 121 user.get(j).getUsersRecords().addCallingInCityRecords(callRecord); 122 } 123 else if(callRecord.getAnswerAddressAreaCode().matches("[0][7][9][234567890]|[0][7][0][1]")){ 124 user.get(j).getUsersRecords().addCallingInProvinceRecords(callRecord); 125 } 126 else user.get(j).getUsersRecords().addCallingInLandRecords(callRecord); 127 } 128 else if(callRecord.getCallingAddressAreaCode().matches("[0][7][9][234567890]|[0][7][0][1]")){ 129 user.get(j).getUsersRecords().addCallingProvinceRecords(callRecord); 130 } 131 else user.get(j).getUsersRecords().addCallingLandRecords(callRecord); 132 } 133 } 134 } 135 else if(s.matches("t-1\\d{10} 0\\d{2,3} 1\\d{10} 0\\d{2,3} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2}")){ 136 int j = 0; 137 for (; j < user.size(); j++) { 138 if (user.get(j).getNumber().equals(parseInput.ParseInputCalNumber(s))) { 139 CallRecord callRecord = new CallRecord(); 140 callRecord.setStartTime(parseInput.ParseInputStartDate(s)); 141 callRecord.setEndTime(parseInput.ParseInputEndData(s)); 142 callRecord.setCallingNumber(parseInput.ParseInputCalNumber(s)); 143 callRecord.setAnswerNumber(parseInput.ParseInputAnswerNumber(s)); 144 callRecord.setAnswerAddressAreaCode(parseInput.EndParseArea(s)); 145 callRecord.setCallingAddressAreaCode(parseInput.StartParseArea(s)); 146 if (callRecord.getCallingAddressAreaCode().matches("0791")){ 147 if(callRecord.getAnswerAddressAreaCode().matches("0791")){ 148 user.get(j).getUsersRecords().addCallingInCityRecords(callRecord); 149 } 150 else if(callRecord.getAnswerAddressAreaCode().matches("[0][7][9][234567890]|[0][7][0][1]")){ 151 user.get(j).getUsersRecords().addCallingInProvinceRecords(callRecord); 152 } 153 else user.get(j).getUsersRecords().addCallingInLandRecords(callRecord); 154 } 155 else if(callRecord.getCallingAddressAreaCode().matches("[0][7][9][234567890]|[0][7][0][1]")){ 156 user.get(j).getUsersRecords().addCallingProvinceRecords(callRecord); 157 } 158 else user.get(j).getUsersRecords().addCallingLandRecords(callRecord); 159 } 160 } 161 int k = 0; 162 for (; k < user.size(); k++) { 163 if (user.get(k).getNumber().equals(parseInput.ParseInputAnswerNumber(s))) { 164 CallRecord callRecord = new CallRecord(); 165 callRecord.setStartTime(parseInput.ParseInputStartDate(s)); 166 callRecord.setEndTime(parseInput.ParseInputEndData(s)); 167 callRecord.setCallingNumber(parseInput.ParseInputCalNumber(s)); 168 callRecord.setAnswerNumber(parseInput.ParseInputAnswerNumber(s)); 169 callRecord.setAnswerAddressAreaCode(parseInput.EndParseArea(s)); 170 callRecord.setCallingAddressAreaCode(parseInput.StartParseArea(s)); 171 if (callRecord.getAnswerAddressAreaCode().matches("0791")) { 172 user.get(k).getUsersRecords().addAnswerInCityRecords(callRecord); 173 } else if (callRecord.getAnswerAddressAreaCode().matches("[0][7][9][234567890]|[0][7][0][1]")) { 174 user.get(k).getUsersRecords().addAnswerInProvinceRecords(callRecord); 175 } else user.get(k).getUsersRecords().addAnswerInLandRecords(callRecord); 176 } 177 } 178 179 } 180 s = input.nextLine(); 181 } 182 183 Collections.sort(user); 184 185 for (i = 0;i< user.size();i++){ 186 System.out.println(user.get(i).getNumber()+" "+String.format("%.1f",user.get(i).CalCost())+" "+String.format("%.1f",user.get(i).CalBalance())); 187 } 188 } 189 } 190 191 abstract class CallChargeRule extends ChargeRule{ 192 public abstract double calCost(ArrayList<CallRecord> callRecords) throws Exception; 193 194 } 195 class CallRecord extends CommunicationRecord { 196 private Date startTime; 197 private Date endTime; 198 199 private String callingAddressAreaCode; 200 private String answerAddressAreaCode; 201 202 public Date getStartTime() { 203 return startTime; 204 } 205 206 public void setStartTime(Date startTime) { 207 this.startTime = startTime; 208 } 209 210 public Date getEndTime() { 211 return endTime; 212 } 213 214 public void setEndTime(Date endTime) { 215 this.endTime = endTime; 216 } 217 218 public String getCallingAddressAreaCode() { 219 return callingAddressAreaCode; 220 } 221 222 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 223 this.callingAddressAreaCode = callingAddressAreaCode; 224 } 225 226 public String getAnswerAddressAreaCode() { 227 return answerAddressAreaCode; 228 } 229 230 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 231 this.answerAddressAreaCode = answerAddressAreaCode; 232 } 233 234 public int getTimeOf() throws Exception { 235 SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 236 String start = simpleFormat.format(startTime); 237 String end = simpleFormat.format(endTime); 238 Date fromM = simpleFormat.parse(start.substring(0, 16)); 239 Date toM = simpleFormat.parse(end.substring(0, 16)); 240 241 simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 242 start = simpleFormat.format(startTime); 243 end = simpleFormat.format(endTime); 244 int secondStart = Integer.parseInt(start.substring(17, 19)); 245 int secondEnd = Integer.parseInt(end.substring(17, 19)); 246 247 long from = fromM.getTime(); 248 long to = toM.getTime(); 249 int gap = (int) ((to - from) / (1000 * 60)); 250 251 if (secondEnd > secondStart) { 252 gap++; 253 } 254 255 if (gap > 0) { 256 return gap; 257 } else return 0; 258 } 259 } 260 abstract class ChargeMode { 261 public ArrayList<ChargeRule> getChargeRules() { 262 return chargeRules; 263 } 264 265 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 266 this.chargeRules = chargeRules; 267 } 268 269 private ArrayList<ChargeRule> chargeRules = new ArrayList<ChargeRule>(); 270 271 public abstract double CalCost(UsersRecords usersRecords) throws Exception; 272 273 public abstract double getMonthlyRent(); 274 } 275 abstract class ChargeRule { 276 } 277 abstract class CommunicationRecord { 278 protected String callingNumber; 279 protected String answerNumber; 280 281 public String getCallingNumber() { 282 return callingNumber; 283 } 284 285 public void setCallingNumber(String callingNumber) { 286 this.callingNumber = callingNumber; 287 } 288 289 public String getAnswerNumber() { 290 return answerNumber; 291 } 292 293 public void setAnswerNumber(String answerNumber) { 294 this.answerNumber = answerNumber; 295 } 296 } 297 class DateUtil { 298 299 private int year; 300 private int month; 301 private int day; 302 303 public DateUtil(){ 304 305 } 306 307 public int getYear() { 308 return year; 309 } 310 311 public void setYear(int year) { 312 this.year = year; 313 } 314 315 public int getMonth() { 316 return month; 317 } 318 319 public void setMonth(int month) { 320 this.month = month; 321 } 322 323 public int getDay() { 324 return day; 325 } 326 327 public void setDay(int day) { 328 this.day = day; 329 } 330 331 public DateUtil(int year, int month, int day){ 332 this.year = year; 333 this.month = month; 334 this.day = day; 335 } 336 337 public boolean checkInputValidity(){ 338 if (month > 0 && month < 13 && day > 0 && day < 32) { 339 if (isLeapYear(year)) { 340 if ((day>29&&month==2)||(day>30&&month==4)||(day>30&&month==6)||(day>30&&month==9)||(day>30&&month==11)){ 341 return false; 342 } else { 343 return true; 344 } 345 } 346 else { 347 if ((day>28&&month==2)||(day>30&&month==4)||(day>30&&month==6)||(day>30&&month==9)||(day>30&&month==11)) { 348 return false; 349 } else { 350 return true; 351 } 352 } 353 } 354 else { 355 return false; 356 } 357 }//检测输入的年、月、日是否合法 358 public boolean isLeapYear(int year){ 359 if(year%400==0){ 360 return true; 361 } 362 else if(year%4==0&&year%100!=0){ 363 return true; 364 } 365 else { 366 return false; 367 } 368 }//判断year是否为闰年 369 } 370 class LandingPhoneCharging extends ChargeMode{ 371 372 CallChargeRule city = new LandPhoneInCityRule(); 373 CallChargeRule province = new LandPhoneInProvinceRule(); 374 CallChargeRule land = new LandPhoneInLandRule(); 375 376 @Override 377 public double CalCost(UsersRecords usersRecords) throws Exception{ 378 double sum = 0; 379 sum += city.calCost(usersRecords.getCallingInCityRecords()); 380 sum += province.calCost(usersRecords.getCallingInProvinceRecords()); 381 sum += land.calCost(usersRecords.getCallingInLandRecords()); 382 383 return sum; 384 } 385 386 @Override 387 public double getMonthlyRent() { 388 return monthlyRent; 389 } 390 391 private double monthlyRent = 20; 392 } 393 class LandPhoneInCityRule extends CallChargeRule{ 394 @Override 395 public double calCost(ArrayList<CallRecord> callRecords)throws Exception{ 396 int i = 0; 397 double sum = 0; 398 for(;i<callRecords.size();i++){ 399 sum += callRecords.get(i).getTimeOf()*0.1; 400 } 401 return sum; 402 } 403 } 404 class LandPhoneInLandRule extends CallChargeRule{ 405 @Override 406 public double calCost(ArrayList<CallRecord> callRecords)throws Exception { 407 int i = 0; 408 double sum = 0; 409 for(;i<callRecords.size();i++){ 410 sum += callRecords.get(i).getTimeOf()*0.6; 411 } 412 return sum; 413 } 414 } 415 class LandPhoneInProvinceRule extends CallChargeRule{ 416 @Override 417 public double calCost(ArrayList<CallRecord> callRecords)throws Exception { 418 int i = 0; 419 double sum = 0; 420 for(;i<callRecords.size();i++){ 421 sum += callRecords.get(i).getTimeOf()*0.3; 422 } 423 return sum; 424 } 425 } 426 class MessageRecord extends CommunicationRecord{ 427 private String message; 428 429 public String getMessage() { 430 return message; 431 } 432 433 public void setMessage(String message) { 434 this.message = message; 435 } 436 } 437 class MobilePhoneAnswerProvince extends CallChargeRule{ 438 @Override 439 public double calCost(ArrayList<CallRecord> callRecords) throws Exception { 440 int i = 0; 441 double sum = 0; 442 for(;i<callRecords.size();i++){ 443 sum += callRecords.get(i).getTimeOf()*0.3; 444 } 445 return sum; 446 } 447 } 448 class MobilePhoneCharging extends ChargeMode{ 449 private double monthlyRent = 15; 450 451 CallChargeRule city = new MobilePhoneCityRule(); 452 CallChargeRule province = new MobilePhoneProvinceRule(); 453 CallChargeRule land = new MobilePhoneLandRule(); 454 CallChargeRule answer = new MobilePhoneAnswerProvince(); 455 CallChargeRule province_ = new MobilePhoneProvince(); 456 CallChargeRule land_ = new MobilePhoneLand(); 457 458 @Override 459 public double CalCost(UsersRecords usersRecords) throws Exception { 460 double sum = 0; 461 sum+=city.calCost(usersRecords.getCallingInCityRecords()); 462 sum+=province.calCost(usersRecords.getCallingInProvinceRecords()); 463 sum+=land.calCost(usersRecords.getCallingInLandRecords()); 464 sum+=province_.calCost(usersRecords.getCallingProvinceRecords()); 465 sum+=land_.calCost(usersRecords.getCallingLandRecords()); 466 sum+=answer.calCost(usersRecords.getAnswerInLandRecords()); 467 return sum; 468 } 469 470 @Override 471 public double getMonthlyRent() { 472 return monthlyRent; 473 } 474 } 475 class MobilePhoneCityRule extends CallChargeRule{ 476 @Override 477 public double calCost(ArrayList<CallRecord> callRecords) throws Exception { 478 int i = 0; 479 double sum = 0; 480 for(;i<callRecords.size();i++){ 481 sum += callRecords.get(i).getTimeOf()*0.1; 482 } 483 return sum; 484 } 485 } 486 class MobilePhoneLand extends CallChargeRule{ 487 @Override 488 public double calCost(ArrayList<CallRecord> callRecords) throws Exception { 489 int i = 0; 490 double sum = 0; 491 for(;i<callRecords.size();i++){ 492 sum += callRecords.get(i).getTimeOf()*0.6; 493 } 494 return sum; 495 } 496 } 497 class MobilePhoneLandRule extends CallChargeRule{ 498 @Override 499 public double calCost(ArrayList<CallRecord> callRecords) throws Exception { 500 int i = 0; 501 double sum = 0; 502 for(;i<callRecords.size();i++){ 503 sum += callRecords.get(i).getTimeOf()*0.3; 504 } 505 return sum; 506 } 507 } 508 class MobilePhoneProvince extends CallChargeRule{ 509 @Override 510 public double calCost(ArrayList<CallRecord> callRecords) throws Exception { 511 int i = 0; 512 double sum = 0; 513 for(;i<callRecords.size();i++){ 514 sum += callRecords.get(i).getTimeOf()*0.3; 515 } 516 return sum; 517 } 518 } 519 class MobilePhoneProvinceRule extends CallChargeRule{ 520 @Override 521 public double calCost(ArrayList<CallRecord> callRecords) throws Exception { 522 int i = 0; 523 double sum = 0; 524 for(;i<callRecords.size();i++){ 525 sum += callRecords.get(i).getTimeOf()*0.2; 526 } 527 return sum; 528 } 529 } 530 class ParseInput { 531 532 public String ParseInputNumber(String s){ 533 String ss[]=s.split("-"); 534 String sss[] =ss[1].split(" "); 535 return sss[0]; 536 } 537 538 public Date ParseInputStartDate(String s){ 539 String ss[]=s.split("-"); 540 String sss[] =ss[1].split(" "); 541 String ssss[] = sss[sss.length-4].split("\\."); 542 String time[] = sss[sss.length-3].split(":"); 543 int year = Integer.parseInt(ssss[0]); 544 int month = Integer.parseInt(ssss[1]); 545 int day = Integer.parseInt(ssss[2]); 546 int hour = Integer.parseInt(time[0]); 547 int minute = Integer.parseInt(time[1]); 548 int second = Integer.parseInt(time[2]); 549 Date date = new Date(year-1900,month-1,day,hour,minute,second); 550 return date; 551 } 552 553 public Date ParseInputEndData(String s){ 554 String ss[]=s.split("-"); 555 String sss[] =ss[1].split(" "); 556 String ssss[] = sss[sss.length-2].split("\\."); 557 String time[] = sss[sss.length-1].split(":"); 558 int year = Integer.parseInt(ssss[0]); 559 int month = Integer.parseInt(ssss[1]); 560 int day = Integer.parseInt(ssss[2]); 561 int hour = Integer.parseInt(time[0]); 562 int minute = Integer.parseInt(time[1]); 563 int second = Integer.parseInt(time[2]); 564 Date date = new Date(year-1900,month-1,day,hour,minute,second); 565 return date; 566 } 567 568 public String ParseInputCalNumber(String s){ 569 String ss[]=s.split("-"); 570 String sss[] = ss[1].split(" "); 571 return sss[0]; 572 } 573 574 public String ParseInputAnswerNumber(String s){ 575 String ss[] = s.split(" "); 576 if(ss[1].length()==4||ss[1].length()==3){ 577 return ss[2]; 578 } 579 return ss[1]; 580 } 581 582 public int ParseNumberArea(String s){ 583 String regex1 = "0791[0-9]{7,8}"; 584 String regex2 = "079[023456789][0-9]{7,8}"; 585 String regex3 = "0701[0-9]{7,8}"; 586 if(s.matches(regex1)) { 587 return 1; 588 } 589 else if(s.matches(regex2)||s.matches(regex3)) { 590 return 2; 591 } 592 return 0; 593 } 594 595 public String StartParseArea(String s){ 596 String ss[]=s.split(" "); 597 if(ss[1].length()==4||ss[1].length()==3){ 598 return ss[1]; 599 } 600 else { 601 String sss[] = ss[0].split("-"); 602 return sss[1].substring(0,4); 603 } 604 } 605 606 public String EndParseArea(String s){ 607 String ss[] = s.split(" "); 608 if(ss[1].length()==4||ss[1].length()==3){ 609 if(ss[3].length()==4||ss[3].length()==3){ 610 return ss[3]; 611 } 612 else { 613 return ss[2].substring(0,4); 614 } 615 } 616 else { 617 if(ss[2].length()==4||ss[2].length()==3){ 618 return ss[2]; 619 } 620 else { 621 return ss[1].substring(0,4); 622 } 623 } 624 } 625 626 public boolean ParseTimeFormat(String s){ 627 String ss[]=s.split("-"); 628 String sss[] =ss[1].split(" "); 629 String startDate[] = sss[sss.length-4].split("\\."); 630 String endDate[] = sss[sss.length-2].split("\\."); 631 632 633 DateUtil dateUtilStart = new DateUtil(Integer.parseInt(startDate[0]), Integer.parseInt(startDate[1]), Integer.parseInt(startDate[2])); 634 DateUtil dateUtilEnd = new DateUtil(Integer.parseInt(endDate[0]),Integer.parseInt(endDate[1]),Integer.parseInt(endDate[2])); 635 636 637 return dateUtilEnd.checkInputValidity()&&dateUtilStart.checkInputValidity(); 638 } 639 } 640 class User implements Comparable<User>{ 641 642 private UsersRecords usersRecords = new UsersRecords(); 643 private double balance = 100; 644 private ChargeMode chargeMode; 645 private String number; 646 647 public User(String number){ 648 this.number = number; 649 if (!number.matches("[1][0-9]{10}")) 650 chargeMode = new LandingPhoneCharging(); 651 else chargeMode = new MobilePhoneCharging(); 652 } 653 654 public User() { 655 656 } 657 658 public double CalCost()throws Exception{ 659 return chargeMode.CalCost(getUsersRecords()); 660 } 661 662 public double CalBalance()throws Exception{ 663 this.balance = balance - CalCost() - chargeMode.getMonthlyRent(); 664 return balance; 665 } 666 667 public double getBalance() { 668 return balance; 669 } 670 671 public UsersRecords getUsersRecords() { 672 return usersRecords; 673 } 674 675 public void setUsersRecords(UsersRecords usersRecords) { 676 this.usersRecords = usersRecords; 677 } 678 679 public ChargeMode getChargeMode() { 680 return chargeMode; 681 } 682 683 public void setChargeMode(ChargeMode chargeMode) { 684 this.chargeMode = chargeMode; 685 } 686 687 public String getNumber() { 688 return number; 689 } 690 691 public void setNumber(String number) { 692 this.number = number; 693 } 694 695 @Override 696 public int compareTo(User o) { 697 return this.getNumber().compareTo(o.getNumber()); 698 } 699 } 700 701 class UsersRecords { 702 703 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();//市内拨打电话 704 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();//省内拨打电话 705 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();//国内拨打电话 706 private ArrayList<CallRecord> callingProvinceRecords = new ArrayList<CallRecord>();//在省内拨打电话 707 private ArrayList<CallRecord> callingLandRecords = new ArrayList<CallRecord>();//在省外拨打电话 708 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();//市内接听电话 709 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();//省内接听电话 710 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();//国内接听电话 711 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();//发出短信 712 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();//接收短信 713 714 public ArrayList<CallRecord> getCallingInCityRecords() { 715 return callingInCityRecords; 716 } 717 718 public ArrayList<CallRecord> getCallingInProvinceRecords() { 719 return callingInProvinceRecords; 720 } 721 722 public ArrayList<CallRecord> getCallingInLandRecords() { 723 return callingInLandRecords; 724 } 725 726 public ArrayList<CallRecord> getAnswerInCityRecords() { 727 return answerInCityRecords; 728 } 729 730 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 731 return answerInProvinceRecords; 732 } 733 734 public ArrayList<CallRecord> getAnswerInLandRecords() { 735 return answerInLandRecords; 736 } 737 738 public ArrayList<MessageRecord> getSendMessageRecords() { 739 return sendMessageRecords; 740 } 741 742 public ArrayList<MessageRecord> getReceiveMessageRecords() { 743 return receiveMessageRecords; 744 } 745 746 public void addCallingInCityRecords(CallRecord callRecord){ 747 callingInCityRecords.add(callRecord); 748 } 749 750 public void addCallingInProvinceRecords(CallRecord callRecord){ 751 callingInProvinceRecords.add(callRecord); 752 } 753 754 public void addCallingInLandRecords(CallRecord callRecord){ 755 callingInLandRecords.add(callRecord); 756 } 757 758 public void addAnswerInCityRecords(CallRecord callRecord){ 759 answerInCityRecords.add(callRecord); 760 } 761 762 public void addAnswerInProvinceRecords(CallRecord callRecord){ 763 answerInProvinceRecords.add(callRecord); 764 } 765 766 public void addAnswerInLandRecords(CallRecord callRecord){ 767 answerInLandRecords.add(callRecord); 768 } 769 770 public void addSendMessageRecords(MessageRecord messageRecord){ 771 sendMessageRecords.add(messageRecord); 772 } 773 774 public void addReceiveMessageRecords(MessageRecord messageRecord){ 775 receiveMessageRecords.add(messageRecord); 776 } 777 778 public ArrayList<CallRecord> getCallingProvinceRecords() { 779 return callingProvinceRecords; 780 } 781 782 public void addCallingProvinceRecords(CallRecord callRecord) { 783 callingProvinceRecords.add(callRecord); 784 } 785 786 public ArrayList<CallRecord> getCallingLandRecords() { 787 return callingLandRecords; 788 } 789 790 public void addCallingLandRecords(CallRecord callRecord) { 791 callingLandRecords.add(callRecord); 792 } 793 }
类图如下:和上图差不多
分析:
这次作业和上次相比增加了手机号码的用户,这对正则表达式的要求会变得更加高的
并且手机用户接听电话也会收费,所以在第一题的基础之上还要加上这个。
对于第一题已经完成的也用不了多久。
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
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)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.Scanner; 4 import java.text.SimpleDateFormat; 5 import java.util.Date; 6 public class Main { 7 public static void main(String[] args)throws Exception { 8 Scanner input = new Scanner(System.in); 9 ArrayList<User> user = new ArrayList<>(); 10 ParseInput parseInput = new ParseInput(); 11 String s = input.nextLine(); 12 String regex = "[u][-]0791[0-9]{7,8}[ ][0]"; 13 String regex2 = "[u][-][1][0-9]{10}[ ][1]"; 14 String regex3 = "[u][-][1][0-9]{10}[ ][3]"; 15 String regex_ = ""; 16 String regex2_ = " "; 17 int i = 0; 18 boolean flag = false; 19 while (!s.equals("end")) { 20 21 if(s.matches(regex3)){ 22 for (int l = 0; l < user.size(); l++) { 23 if (parseInput.ParseInputNumber(s).equals(user.get(l).getNumber())) { 24 flag = true; 25 } 26 } 27 if (!flag) { 28 user.add(new User(parseInput.ParseInputNumber(s))); 29 user.get(i).setUsersRecords(new UsersRecords()); 30 i++; 31 } 32 flag =false; 33 } 34 //座机打座机 35 36 //手机拨打座机 37 38 else if(s.matches("m-1[3-9]\\d{9} 1[3-9]\\d{9} [a-z|0-9| |,|.]+")) { 39 int j = 0; 40 for (; j < user.size(); j++) { 41 if (user.get(j).getNumber().equals(parseInput.ParseInputCalNumber(s))) { 42 MessageRecord messageRecord = new MessageRecord(); 43 String message = parseInput.getMessage(s); 44 int l = parseInput.getMessage(s).length(); 45 int k = 0; 46 while (l>10){ 47 messageRecord.setMessage(message.substring(k,k+10)); 48 user.get(j).getUsersRecords().addSendMessageRecords(messageRecord); 49 messageRecord = new MessageRecord(); 50 l-=10; 51 } 52 messageRecord.setMessage(message.substring(k)); 53 user.get(j).getUsersRecords().addSendMessageRecords(messageRecord); 54 } 55 } 56 } 57 s = input.nextLine(); 58 } 59 60 Collections.sort(user); 61 62 for (i = 0;i< user.size();i++){ 63 System.out.println(user.get(i).getNumber()+" "+String.format("%.1f",user.get(i).CalCost())+" "+String.format("%.1f",user.get(i).CalBalance())); 64 } 65 } 66 } 67 abstract class CallChargeRule extends ChargeRule{ 68 public abstract double calCost(ArrayList<CallRecord> callRecords) throws Exception; 69 70 } 71 class CallRecord extends CommunicationRecord { 72 private Date startTime; 73 private Date endTime; 74 75 private String callingAddressAreaCode; 76 private String answerAddressAreaCode; 77 78 public Date getStartTime() { 79 return startTime; 80 } 81 82 public void setStartTime(Date startTime) { 83 this.startTime = startTime; 84 } 85 86 public Date getEndTime() { 87 return endTime; 88 } 89 90 public void setEndTime(Date endTime) { 91 this.endTime = endTime; 92 } 93 94 public String getCallingAddressAreaCode() { 95 return callingAddressAreaCode; 96 } 97 98 public void setCallingAddressAreaCode(String callingAddressAreaCode) { 99 this.callingAddressAreaCode = callingAddressAreaCode; 100 } 101 102 public String getAnswerAddressAreaCode() { 103 return answerAddressAreaCode; 104 } 105 106 public void setAnswerAddressAreaCode(String answerAddressAreaCode) { 107 this.answerAddressAreaCode = answerAddressAreaCode; 108 } 109 110 public int getTimeOf() throws Exception { 111 SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm"); 112 String start = simpleFormat.format(startTime); 113 String end = simpleFormat.format(endTime); 114 Date fromM = simpleFormat.parse(start.substring(0, 16)); 115 Date toM = simpleFormat.parse(end.substring(0, 16)); 116 117 simpleFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 118 start = simpleFormat.format(startTime); 119 end = simpleFormat.format(endTime); 120 int secondStart = Integer.parseInt(start.substring(17, 19)); 121 int secondEnd = Integer.parseInt(end.substring(17, 19)); 122 123 long from = fromM.getTime(); 124 long to = toM.getTime(); 125 int gap = (int) ((to - from) / (1000 * 60)); 126 127 if (secondEnd > secondStart) { 128 gap++; 129 } 130 131 if (gap > 0) { 132 return gap; 133 } else return 0; 134 } 135 } 136 abstract class ChargeMode { 137 public ArrayList<ChargeRule> getChargeRules() { 138 return chargeRules; 139 } 140 141 public void setChargeRules(ArrayList<ChargeRule> chargeRules) { 142 this.chargeRules = chargeRules; 143 } 144 145 private ArrayList<ChargeRule> chargeRules = new ArrayList<ChargeRule>(); 146 147 public abstract double CalCost(UsersRecords usersRecords) throws Exception; 148 149 public abstract double getMonthlyRent(); 150 } 151 abstract class ChargeRule { 152 } 153 abstract class CommunicationRecord { 154 protected String callingNumber; 155 protected String answerNumber; 156 157 public String getCallingNumber() { 158 return callingNumber; 159 } 160 161 public void setCallingNumber(String callingNumber) { 162 this.callingNumber = callingNumber; 163 } 164 165 public String getAnswerNumber() { 166 return answerNumber; 167 } 168 169 public void setAnswerNumber(String answerNumber) { 170 this.answerNumber = answerNumber; 171 } 172 } 173 class DateUtil { 174 175 private int year; 176 private int month; 177 private int day; 178 179 public DateUtil(){ 180 181 } 182 183 public int getYear() { 184 return year; 185 } 186 187 public void setYear(int year) { 188 this.year = year; 189 } 190 191 public int getMonth() { 192 return month; 193 } 194 195 public void setMonth(int month) { 196 this.month = month; 197 } 198 199 public int getDay() { 200 return day; 201 } 202 203 public void setDay(int day) { 204 this.day = day; 205 } 206 207 public DateUtil(int year, int month, int day){ 208 this.year = year; 209 this.month = month; 210 this.day = day; 211 } 212 213 public boolean checkInputValidity(){ 214 if (month > 0 && month < 13 && day > 0 && day < 32) { 215 if (isLeapYear(year)) { 216 if ((day>29&&month==2)||(day>30&&month==4)||(day>30&&month==6)||(day>30&&month==9)||(day>30&&month==11)){ 217 return false; 218 } else { 219 return true; 220 } 221 } 222 else { 223 if ((day>28&&month==2)||(day>30&&month==4)||(day>30&&month==6)||(day>30&&month==9)||(day>30&&month==11)) { 224 return false; 225 } else { 226 return true; 227 } 228 } 229 } 230 else { 231 return false; 232 } 233 }//检测输入的年、月、日是否合法 234 public boolean isLeapYear(int year){ 235 if(year%400==0){ 236 return true; 237 } 238 else if(year%4==0&&year%100!=0){ 239 return true; 240 } 241 else { 242 return false; 243 } 244 }//判断year是否为闰年 245 } 246 class LandingPhoneCharging extends ChargeMode{ 247 248 CallChargeRule city = new LandPhoneInCityRule(); 249 CallChargeRule province = new LandPhoneInProvinceRule(); 250 CallChargeRule land = new LandPhoneInLandRule(); 251 252 @Override 253 public double CalCost(UsersRecords usersRecords) throws Exception{ 254 double sum = 0; 255 sum += city.calCost(usersRecords.getCallingInCityRecords()); 256 sum += province.calCost(usersRecords.getCallingInProvinceRecords()); 257 sum += land.calCost(usersRecords.getCallingInLandRecords()); 258 259 return sum; 260 } 261 262 @Override 263 public double getMonthlyRent() { 264 return monthlyRent; 265 } 266 267 private double monthlyRent = 20; 268 } 269 class LandPhoneInCityRule extends CallChargeRule{ 270 @Override 271 public double calCost(ArrayList<CallRecord> callRecords)throws Exception{ 272 int i = 0; 273 double sum = 0; 274 for(;i<callRecords.size();i++){ 275 sum += callRecords.get(i).getTimeOf()*0.1; 276 } 277 return sum; 278 } 279 } 280 class LandPhoneInLandRule extends CallChargeRule{ 281 @Override 282 public double calCost(ArrayList<CallRecord> callRecords)throws Exception { 283 int i = 0; 284 double sum = 0; 285 for(;i<callRecords.size();i++){ 286 sum += callRecords.get(i).getTimeOf()*0.6; 287 } 288 return sum; 289 } 290 } 291 class LandPhoneInProvinceRule extends CallChargeRule{ 292 @Override 293 public double calCost(ArrayList<CallRecord> callRecords)throws Exception { 294 int i = 0; 295 double sum = 0; 296 for(;i<callRecords.size();i++){ 297 sum += callRecords.get(i).getTimeOf()*0.3; 298 } 299 return sum; 300 } 301 } 302 abstract class MessageChargeRule extends ChargeRule{ 303 public abstract double calCost(ArrayList<MessageRecord> messageRecords) throws Exception; 304 } 305 class MessageRecord extends CommunicationRecord{ 306 private String message; 307 308 public String getMessage() { 309 return message; 310 } 311 312 public void setMessage(String message) { 313 this.message = message; 314 } 315 } 316 class MobilePhoneAnswerProvince extends CallChargeRule{ 317 @Override 318 public double calCost(ArrayList<CallRecord> callRecords) throws Exception { 319 int i = 0; 320 double sum = 0; 321 for(;i<callRecords.size();i++){ 322 sum += callRecords.get(i).getTimeOf()*0.3; 323 } 324 return sum; 325 } 326 } 327 class MobilePhoneMessageCharging extends ChargeMode{ 328 329 private double monthlyRent = 0; 330 MobilePhoneMessageRule mobilePhoneMessageRule = new MobilePhoneMessageRule(); 331 @Override 332 public double CalCost(UsersRecords usersRecords) throws Exception { 333 double sum = 0; 334 sum=mobilePhoneMessageRule.calCost(usersRecords.getSendMessageRecords()); 335 return sum; 336 } 337 338 @Override 339 public double getMonthlyRent() { 340 return this.monthlyRent; 341 } 342 } 343 class MobilePhoneMessageRule extends MessageChargeRule{ 344 345 @Override 346 public double calCost(ArrayList<MessageRecord> messageRecords) throws Exception { 347 int l = messageRecords.size(); 348 if(l<=3){ 349 return 0.1*l; 350 } 351 else if(l>3&&l<=5){ 352 return 0.3+0.2*(l-3); 353 } 354 else 355 return 0.7+0.3*(l-5); 356 } 357 } 358 359 class ParseInput { 360 361 public String ParseInputNumber(String s){ 362 String ss[]=s.split("-"); 363 String sss[] =ss[1].split(" "); 364 return sss[0]; 365 } 366 367 public Date ParseInputStartDate(String s){ 368 String ss[]=s.split("-"); 369 String sss[] =ss[1].split(" "); 370 String ssss[] = sss[sss.length-4].split("\\."); 371 String time[] = sss[sss.length-3].split(":"); 372 int year = Integer.parseInt(ssss[0]); 373 int month = Integer.parseInt(ssss[1]); 374 int day = Integer.parseInt(ssss[2]); 375 int hour = Integer.parseInt(time[0]); 376 int minute = Integer.parseInt(time[1]); 377 int second = Integer.parseInt(time[2]); 378 Date date = new Date(year-1900,month-1,day,hour,minute,second); 379 return date; 380 } 381 382 public Date ParseInputEndData(String s){ 383 String ss[]=s.split("-"); 384 String sss[] =ss[1].split(" "); 385 String ssss[] = sss[sss.length-2].split("\\."); 386 String time[] = sss[sss.length-1].split(":"); 387 int year = Integer.parseInt(ssss[0]); 388 int month = Integer.parseInt(ssss[1]); 389 int day = Integer.parseInt(ssss[2]); 390 int hour = Integer.parseInt(time[0]); 391 int minute = Integer.parseInt(time[1]); 392 int second = Integer.parseInt(time[2]); 393 Date date = new Date(year-1900,month-1,day,hour,minute,second); 394 return date; 395 } 396 397 public String ParseInputCalNumber(String s){ 398 String ss[]=s.split("-"); 399 String sss[] = ss[1].split(" "); 400 return sss[0]; 401 } 402 403 public String ParseInputAnswerNumber(String s){ 404 String ss[] = s.split(" "); 405 if(ss[1].length()==4||ss[1].length()==3){ 406 return ss[2]; 407 } 408 return ss[1]; 409 } 410 411 public int ParseNumberArea(String s){ 412 String regex1 = "0791[0-9]{7,8}"; 413 String regex2 = "079[023456789][0-9]{7,8}"; 414 String regex3 = "0701[0-9]{7,8}"; 415 if(s.matches(regex1)) { 416 return 1; 417 } 418 else if(s.matches(regex2)||s.matches(regex3)) { 419 return 2; 420 } 421 return 0; 422 } 423 424 public String StartParseArea(String s){ 425 String ss[]=s.split(" "); 426 if(ss[1].length()==4||ss[1].length()==3){ 427 return ss[1]; 428 } 429 else { 430 String sss[] = ss[0].split("-"); 431 return sss[1].substring(0,4); 432 } 433 } 434 435 public String EndParseArea(String s){ 436 String ss[] = s.split(" "); 437 if(ss[1].length()==4||ss[1].length()==3){ 438 if(ss[3].length()==4||ss[3].length()==3){ 439 return ss[3]; 440 } 441 else { 442 return ss[2].substring(0,4); 443 } 444 } 445 else { 446 if(ss[2].length()==4||ss[2].length()==3){ 447 return ss[2]; 448 } 449 else { 450 return ss[1].substring(0,4); 451 } 452 } 453 } 454 455 public boolean ParseTimeFormat(String s){ 456 String ss[]=s.split("-"); 457 String sss[] =ss[1].split(" "); 458 String startDate[] = sss[sss.length-4].split("\\."); 459 String endDate[] = sss[sss.length-2].split("\\."); 460 461 462 DateUtil dateUtilStart = new DateUtil(Integer.parseInt(startDate[0]), Integer.parseInt(startDate[1]), Integer.parseInt(startDate[2])); 463 DateUtil dateUtilEnd = new DateUtil(Integer.parseInt(endDate[0]),Integer.parseInt(endDate[1]),Integer.parseInt(endDate[2])); 464 465 466 return dateUtilEnd.checkInputValidity()&&dateUtilStart.checkInputValidity(); 467 } 468 469 public String getMessage(String s){ 470 return s.substring(26); 471 } 472 } 473 class User implements Comparable<User>{ 474 475 private UsersRecords usersRecords = new UsersRecords(); 476 private double balance = 100; 477 private ChargeMode chargeMode; 478 private String number; 479 480 public User(String number){ 481 this.number = number; 482 if (!number.matches("[1][0-9]{10}")) 483 chargeMode = new LandingPhoneCharging(); 484 else chargeMode = new MobilePhoneMessageCharging(); 485 } 486 487 public User() { 488 489 } 490 491 public double CalCost()throws Exception{ 492 return chargeMode.CalCost(getUsersRecords()); 493 } 494 495 public double CalBalance()throws Exception{ 496 this.balance = balance - CalCost() - chargeMode.getMonthlyRent(); 497 return balance; 498 } 499 500 public double getBalance() { 501 return balance; 502 } 503 504 public UsersRecords getUsersRecords() { 505 return usersRecords; 506 } 507 508 public void setUsersRecords(UsersRecords usersRecords) { 509 this.usersRecords = usersRecords; 510 } 511 512 public ChargeMode getChargeMode() { 513 return chargeMode; 514 } 515 516 public void setChargeMode(ChargeMode chargeMode) { 517 this.chargeMode = chargeMode; 518 } 519 520 public String getNumber() { 521 return number; 522 } 523 524 public void setNumber(String number) { 525 this.number = number; 526 } 527 528 @Override 529 public int compareTo(User o) { 530 return this.getNumber().compareTo(o.getNumber()); 531 } 532 } 533 class UsersRecords { 534 535 private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();//市内拨打电话 536 private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();//省内拨打电话 537 private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();//国内拨打电话 538 private ArrayList<CallRecord> callingProvinceRecords = new ArrayList<CallRecord>();//在省内拨打电话 539 private ArrayList<CallRecord> callingLandRecords = new ArrayList<CallRecord>();//在省外拨打电话 540 private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();//市内接听电话 541 private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();//省内接听电话 542 private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();//国内接听电话 543 private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();//发出短信 544 private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();//接收短信 545 546 public ArrayList<CallRecord> getCallingInCityRecords() { 547 return callingInCityRecords; 548 } 549 550 public ArrayList<CallRecord> getCallingInProvinceRecords() { 551 return callingInProvinceRecords; 552 } 553 554 public ArrayList<CallRecord> getCallingInLandRecords() { 555 return callingInLandRecords; 556 } 557 558 public ArrayList<CallRecord> getAnswerInCityRecords() { 559 return answerInCityRecords; 560 } 561 562 public ArrayList<CallRecord> getAnswerInProvinceRecords() { 563 return answerInProvinceRecords; 564 } 565 566 public ArrayList<CallRecord> getAnswerInLandRecords() { 567 return answerInLandRecords; 568 } 569 570 public ArrayList<MessageRecord> getSendMessageRecords() { 571 return sendMessageRecords; 572 } 573 574 public ArrayList<MessageRecord> getReceiveMessageRecords() { 575 return receiveMessageRecords; 576 } 577 578 public void addCallingInCityRecords(CallRecord callRecord){ 579 callingInCityRecords.add(callRecord); 580 } 581 582 public void addCallingInProvinceRecords(CallRecord callRecord){ 583 callingInProvinceRecords.add(callRecord); 584 } 585 586 public void addCallingInLandRecords(CallRecord callRecord){ 587 callingInLandRecords.add(callRecord); 588 } 589 590 public void addAnswerInCityRecords(CallRecord callRecord){ 591 answerInCityRecords.add(callRecord); 592 } 593 594 public void addAnswerInProvinceRecords(CallRecord callRecord){ 595 answerInProvinceRecords.add(callRecord); 596 } 597 598 public void addAnswerInLandRecords(CallRecord callRecord){ 599 answerInLandRecords.add(callRecord); 600 } 601 602 public void addSendMessageRecords(MessageRecord messageRecord){ 603 sendMessageRecords.add(messageRecord); 604 } 605 606 public void addReceiveMessageRecords(MessageRecord messageRecord){ 607 receiveMessageRecords.add(messageRecord); 608 } 609 610 public ArrayList<CallRecord> getCallingProvinceRecords() { 611 return callingProvinceRecords; 612 } 613 614 public void addCallingProvinceRecords(CallRecord callRecord) { 615 callingProvinceRecords.add(callRecord); 616 } 617 618 public ArrayList<CallRecord> getCallingLandRecords() { 619 return callingLandRecords; 620 } 621 622 public void addCallingLandRecords(CallRecord callRecord) { 623 callingLandRecords.add(callRecord); 624 } 625 }
类图与上图一样
分析:
这次只考察短信计费,所以这次的难点只有正则表达式。然后这次对代码长度进行了限制
所以需要对之前的代码进行删改
踩坑心得:
1.正则表达式在这三道题中有很大的作用,非常重要。
2.类的设计的完整性。
3.整个代码的耦合性。
改进建议:
在跨月时,对于月租这个属性应该也要考虑
总结:
一学期的Java课程结束了,感觉自己的编码能力还有待提高。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端