xxqblog1

Remember的Java-blog3

一、前言

       此次blog为电信计费系列的座机,手机,短信大作业总结。相对于前几次的多边形,这次在算法上更简单,但是涉及到的内容很多,比如容器的使用、抛出异常、抽象类、继承与多态、正则表达式、类和对象等知识点。下面我就这三次作业进行分析。

二、设计与分析

7-1 电信计费系列1-座机计费

实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。

输入格式:

输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。

输出格式:

根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。

错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

建议类图:
参见图1、2、3,可根据理解自行调整:

image.png

                                    图1
图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。

ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。

UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

                                     图2
图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。

CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
 

image.png

                                        图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.text.DateFormat;
  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.regex.Matcher;
  8 import java.util.regex.Pattern;
  9 
 10 //用户类——完成
 11 class User {
 12     private UserRecords userRecords = new UserRecords();// 用户记录
 13     private float balance = 100;// 余额
 14     private ChargeMode chargeMode = new ChargeMode();// 计费方式(地区)
 15     private String number;// 号码
 16     private String costMode;// 计费方式(座机,手机。。。)
 17 
 18     public float calBalance() {// 返回余额
 19         balance = balance - chargeMode.getMonthlyRent() - calCost() ;
 20         return (float) balance;
 21     }
 22 
 23     public float calCost() {// 返回计费总额
 24         return chargeMode.calCost(userRecords);
 25     }
 26 
 27     // get,set
 28     public UserRecords getUserRecords() {
 29         return userRecords;
 30     }
 31 
 32     public void setUserRecords(UserRecords userRecords) {
 33         this.userRecords = userRecords;
 34     }
 35 
 36     public double getBalance() {
 37         return balance;
 38     }
 39 
 40     public ChargeMode getChargeMode() {
 41         return chargeMode;
 42     }
 43 
 44     public void setChargeMode(ChargeMode chargeMode) {
 45         this.chargeMode = chargeMode;
 46     }
 47 
 48     public String getNumber() {
 49         return number;
 50     }
 51 
 52     public void setNumber(String number) {
 53         this.number = number;
 54     }
 55 
 56     public void setcostMode(String s) {// 传入计费方式
 57         this.costMode = s;
 58     }
 59 }
 60 
 61 //用户记录类——完成
 62 class UserRecords {
 63     // 拨打
 64     private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();// 市内拨打电话
 65     private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();// 省内拨打电话
 66     private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();// 省外拨打电话
 67     // 接听
 68     private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();// 室内接听电话
 69     private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();// 省内接听电话
 70     private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();// 省外接听电话
 71    
 72     // 添加电话记录
 73     // 拨打
 74     public void addCallingInCityRecords(CallRecord callRecord) {
 75         callingInCityRecords.add(callRecord);
 76     }
 77 
 78     public void addCallingInProvinceRecords(CallRecord callRecord) {
 79         callingInProvinceRecords.add(callRecord);
 80     }
 81 
 82     public void addCallingInLandRecords(CallRecord callRecord) {
 83         callingInLandRecords.add(callRecord);
 84     }
 85 
 86     // 接听
 87     public void addAnswerInCityRecords(CallRecord answerRecord) {
 88         answerInCityRecords.add(answerRecord);
 89     }
 90 
 91     public void addAnswerInProvinceRecords(CallRecord answerRecord) {
 92         answerInProvinceRecords.add(answerRecord);
 93     }
 94 
 95     public void addAnswerInLandRecords(CallRecord answerRecord) {
 96         answerInLandRecords.add(answerRecord);
 97     }
 98 
 99     // 添加短信记录
100     public void addSendMessageRecords(CallRecord answerRecord) {
101 
102     }
103 
104     public void addReceiveMessageRecords(CallRecord answerRecord) {
105 
106     }
107 
108     
109     // get方法
110     public ArrayList<CallRecord> getCallingInCityRecords() {
111         return callingInCityRecords;
112     }
113 
114     public ArrayList<CallRecord> getCallingInProvinceRecords() {
115         return callingInProvinceRecords;
116     }
117 
118     public ArrayList<CallRecord> getCallingInLandRecords() {
119         return callingInLandRecords;
120     }
121 
122     public ArrayList<CallRecord> getAnswerInCityRecords() {
123         return answerInCityRecords;
124     }
125 
126     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
127         return answerInProvinceRecords;
128     }
129 
130     public ArrayList<CallRecord> getAnswerInLandRecords() {
131         return answerInLandRecords;
132     }
133 
134 }
135 
136 //计费方式抽象类(直接计算费用总额)——完成
137 class ChargeMode {
138     private ArrayList<ChargeRule> chargeRules = new ArrayList<ChargeRule>();
139     private LandPhoneInCityRule cityCal = new LandPhoneInCityRule();// 城市内计费
140     private LandPhoneInProvinceRule provinceCal = new LandPhoneInProvinceRule();// 省内计费
141     private LandPhoneInlandRule landCal = new LandPhoneInlandRule();// 省外计费
142 
143     public ArrayList<ChargeRule> getChargeRules() {
144         return chargeRules;
145     }
146 
147     public float calCost(UserRecords userRecords) {// 计算费用总额
148         double sumOfcost = 0;
149         if (userRecords.getCallingInCityRecords().size() != 0) {// 如果容器不为空
150             sumOfcost  += cityCal.calCost(userRecords.getCallingInCityRecords());
151         }
152         if (userRecords.getCallingInProvinceRecords().size() != 0) {
153             sumOfcost +=  provinceCal.calCost(userRecords.getCallingInProvinceRecords());
154         }
155         if (userRecords.getCallingInLandRecords().size() != 0) {
156             sumOfcost +=  landCal.calCost(userRecords.getCallingInLandRecords());
157         }
158         return (float) sumOfcost;
159     }
160 
161     public float getMonthlyRent() {
162         return 20;// 月租
163     }
164 }
165 
166 //座机月租管理
167 class LandlinePhoneCharging extends ChargeMode {
168     private double monthlyRent = 20;// 月租20
169 
170     public float calCost(UserRecords userRecords) {// 放在父类算
171         return 0;
172     }
173 
174     public float getMonthlyRent() {
175         return (float) monthlyRent;
176     }
177 }
178 
179 //通话记录类——完成
180 class CallRecord extends CommunicationRecord {
181 
182     private Date startTime;// 起始时间
183     private Date endTime;// 结束时间
184     private String callingAddressAreaCode;// 拨号地点的区号
185     private String answerAddressAreaCode;// 接听地点的区号
186 
187     // get,set
188     public Date getStartTime() {
189         return startTime;
190     }
191 
192     public void setStartTime(Date startTime) {
193         this.startTime = startTime;
194     }
195 
196     public Date getEndTime() {
197         return endTime;
198     }
199 
200     public void setEndTime(Date endTime) {
201         this.endTime = endTime;
202     }
203 
204     public String getCallingAddressAreaCode() {
205         return callingAddressAreaCode;
206     }
207 
208     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
209         this.callingAddressAreaCode = callingAddressAreaCode;
210     }
211 
212     public String getAnswerAddressAreaCode() {
213         return answerAddressAreaCode;
214     }
215 
216     public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
217         this.answerAddressAreaCode = answerAddressAreaCode;
218     }
219 
220 }
221 
222 
223 //抽象的通讯记录类——完成
224 abstract class CommunicationRecord {
225     protected String callingNumber;// 拨打号码
226     protected String answerNumber;// 接听号码
227 
228     // get,set
229     public String getCallingNumber() {
230         return callingNumber;
231     }
232 
233     public void setCallingNumber(String callingNumber) {
234         this.callingNumber = callingNumber;
235     }
236 
237     public String getAnswerNumber() {
238         return answerNumber;
239     }
240 
241     public void setAnswerNumber(String answerNumber) {
242         this.answerNumber = answerNumber;
243     }
244 
245 }
246 
247 //市内通话(计费)——完成
248 class LandPhoneInCityRule extends CallChargeRule {
249 
250 
251     @Override
252     public double calCost(ArrayList<CallRecord> callRecords) {
253         // TODO Auto-generated method stub
254 
255         double sumofMoney = 0;
256         for (CallRecord e : callRecords) {
257             long second = (e.getEndTime().getTime() - e.getStartTime().getTime()) / 1000;// 毫秒——>秒
258             long minutes = (second + 59) / 60;// 秒——>分钟
259             sumofMoney += 0.1 * minutes; // 0.1元/min
260 
261         }
262         return sumofMoney;
263     }
264 
265 }
266 
267 //省内通话(计费)——完成
268 class LandPhoneInProvinceRule extends CallChargeRule {// forEach 循环将每条记录计算再进行累加
269 
270 
271     @Override
272     public double calCost(ArrayList<CallRecord> callRecords) {
273         // TODO Auto-generated method stub
274         double sumofMoney = 0;
275         for (CallRecord e : callRecords) {
276             long second = (e.getEndTime().getTime() - e.getStartTime().getTime()) / 1000;// 毫秒——>秒
277             long minutes = (second + 59) / 60;// 秒——>分钟
278             sumofMoney += 0.3 * minutes; // 0.3元/min
279 
280         }
281         return sumofMoney;
282     }
283 
284 }
285 
286 //省外通话(计费)——完成
287 class LandPhoneInlandRule extends CallChargeRule {// forEach 循环将每条记录计算再进行累加
288 
289     @Override
290     public double calCost(ArrayList<CallRecord> callRecords) {
291         double sumofMoney = 0;
292         for (CallRecord e : callRecords) {
293             double minute = ((e.getEndTime().getTime() - e.getStartTime().getTime()) / 1000.0 / 60.0);// 毫秒——>秒
294             if (minute > (int) minute) {
295                 sumofMoney = sumofMoney + 0.6 * ((int) minute + 1);
296             } else {
297                 sumofMoney = sumofMoney + 0.6 * minute;// 0.6元/min
298             }
299         }
300         return sumofMoney;
301     }
302 
303 }
304 
305 //通话计费规则抽象类(完成)
306 
307 abstract class CallChargeRule extends ChargeRule {
308 
309     public abstract double calCost(ArrayList<CallRecord> callRecords);
310 
311 }
312 
313 //收费规则抽象类(完成)
314 abstract class ChargeRule {
315    public abstract double calCost(ArrayList<CallRecord> callRecords);
316 }
317 
318 
319 
320 public class Main {// 主方法( 接受信息——处理信息——返回信息)
321 
322     
323     // 声明静态类型,便于更替
324     static  User user;
325 
326     public static void main(String[] args) throws ParseException {// SimpleDateFormat类型转换
327 
328         CallRecord callrecord = new CallRecord();
329         UserRecords userRecord = new UserRecords();
330         ArrayList<String> dateCumb = new ArrayList<>(); // 存放数据的容器
331         ArrayList<User> listOfuser = new ArrayList<User>();// 存放开户的容器
332         SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");// 标准日期格式
333        
334         // 接受信息,处理信息
335         Scanner in = new Scanner(System.in);
336         int sign = 1; // 控制循环进行
337         while (sign == 1) 
338         {
339             String date = in.nextLine();// 输入数据
340             // 防止重复数据
341             if (dateCumb.contains(date)) 
342                 continue;
343              else 
344                 dateCumb.add(date);
345             // 正则表达式过滤多余数据
346             String judge1 = "u-([0-9]){11,12} 0|t-[0-9]{11,12} [0-9]{10,12}( [0-9]{4}.([1-9]|10|11|12).([0-9]|[1-3][0-9]) ([0-9]|[0-2][0-9]):([0-5][0-9]):([0-5][0-9]))+|end";
347             if (!Pattern.matches(judge1, date)) 
348                 continue;
349             Pattern p = Pattern.compile( "[0-9]{10,12}|0|end|[0-9]{4}.([1-9]|10|11|12).([1-9]|[1-3][0-9]) ([0-9]|[0-9][0-9]):([0-9]|[0-5][0-9]):([0-5][0-9])");// 规范格式(分组)
350             Matcher m = p.matcher(date);// 依据正则表达式筛选
351             int guide = 0;// 控制循环导向
352             while (m.find()) {// 提取数据
353                 if (m.group(0).equals("end")) 
354                     sign = 0;// 标志结束,退出循环
355                 if (date.charAt(0) == 'u') 
356                 {// 输入到开户用户
357                     if (guide == 0) 
358                     {
359                         user = new User();
360                         user.setNumber(m.group(0));// 传入号码
361                     }
362                     if (guide == 1) 
363                     {
364                         user.setcostMode(m.group(0));// 传入计费方式
365                     }
366                     if (guide == 1) 
367                     {// 传入用户,并进行下一次传入
368                         listOfuser.add(user);
369                         user = null;
370                     }
371                     guide++;// 指向下一个用户
372                 } 
373                 else if (date.charAt(0) == 't') 
374                 {// 输入到通信信息
375                     if (guide == 2) 
376                     {// 所有日期格式
377                         if (judge3(m.group(0).length(), m.group(0), "yyyy.MM.dd HH:mm:ss")
378                                 || judge3(m.group(0).length(), m.group(0), "yyyy.M.dd HH:mm:ss")
379                                 || judge3(m.group(0).length(), m.group(0), "yyyy.MM.d HH:mm:ss")
380                                 || judge3(m.group(0).length(), m.group(0), "yyyy.M.d HH:mm:ss")) {
381                             callrecord.setStartTime(format.parse(m.group(0)));// 传入开始时间
382                         } else 
383                         {
384                             break;
385                         }
386                     }
387                     if (guide == 3) 
388                     {// 所有日期格式
389                         if (judge3(m.group(0).length(), m.group(0), "yyyy.MM.dd HH:mm:ss")
390                                 || judge3(m.group(0).length(), m.group(0), "yyyy.M.dd HH:mm:ss")
391                                 || judge3(m.group(0).length(), m.group(0), "yyyy.MM.d HH:mm:ss")
392                                 || judge3(m.group(0).length(), m.group(0), "yyyy.M.d HH:mm:ss") ) 
393                         {
394                             callrecord.setEndTime(format.parse(m.group(0)));// 传入结束时间
395                         }
396                         else 
397                         {
398                             break;
399                         }
400                     }
401                     if (guide == 0) 
402                     {
403                         callrecord = new CallRecord();// 刷新
404                         callrecord.setCallingNumber(m.group(0));// 传入拨打号码
405                         callrecord.setCallingAddressAreaCode(m.group(0).substring(0, 4));// 传入拨打地区
406                     }
407                     if (guide == 1) 
408                     {
409                         callrecord.setAnswerNumber(m.group(0));// 传入接听号码
410                         callrecord.setAnswerAddressAreaCode(m.group(0).substring(0, 4));// 传入接听地区
411                     }
412                     if (guide == 3) 
413                     {
414                         // forEach循环,对不同座机号匹配相应的通话记录
415                         for (User e : listOfuser) 
416                         {
417                             if (e.getNumber().equals(callrecord.getCallingNumber())) 
418                             {// 号码对应正确
419                                 String judge2 = "079[0-9]|0701";// 区号判断
420                                 if (callrecord.getCallingAddressAreaCode().equals("0791")
421                                         && callrecord.getAnswerAddressAreaCode().equals("0791")) 
422                                 {
423                                     e.getUserRecords().addCallingInCityRecords(callrecord);
424                                 } 
425                                 else if (callrecord.getCallingAddressAreaCode().equals("0791") && Pattern.matches(judge2, callrecord.getAnswerAddressAreaCode()))
426                                 {
427                                     e.getUserRecords().addCallingInProvinceRecords(callrecord);
428                                 } 
429                                 else 
430                                 {
431                                     e.getUserRecords().addCallingInLandRecords(callrecord);
432                                 }
433                             } else 
434                             {
435                                 continue;
436                             }
437                         }
438                     }
439                     guide++;// 指向下一条记录
440                 }
441             }
442         }
443 
444         // 返回信息
445         // 声明一个User类的数组,将容器中的对象取出来
446         User[] user = new User[listOfuser.size()];
447         User temp;// 交换元素
448         for (int i = 0; i < listOfuser.size(); i++) 
449         {
450             user[i] = listOfuser.get(i);
451         }
452 
453         // 仿造冒泡排序(将号码字符从小到大排序)
454         for (int i = 0; i < user.length - 1; i++) 
455         {
456             for (int j = 0; j < user.length - 1 - i; j++) 
457             {
458                 // 将号码提取出来比较大小
459                 double x = Double.parseDouble(user[j + 1].getNumber());
460                 double y = Double.parseDouble(user[j].getNumber());
461                 if (x < y) 
462                 {// user[j+1]号码比user[j]小
463                     temp = user[j + 1];
464                     user[j + 1] = user[j];
465                     user[j] = temp;
466                 }
467             }
468         }
469 
470         for (int i = 0; i < user.length; i++)
471         {
472             System.out.println(user[i].getNumber() + " " + user[i].calCost() + " " + user[i].calBalance());
473         }
474 
475     }
476     
477     public static boolean judge3(int length, String Date, String format) {// 仿造Date类中的代码,判断日期格式是否错误
478         int legalLen = length;
479         if ((Date == null) || (Date.length() != legalLen)) {
480             return false;
481         }
482         DateFormat Format = new SimpleDateFormat(format);
483         try {
484             Date date = Format.parse(Date);
485             return Date.equals(Format.format(date));
486         } catch (Exception e) {
487             return false;
488         }
489     }
490 }
点击展开我的代码

SourceMonitor的生成报表内容如下:

 

 小结:

         看这个报表就知道这道题写的不怎么样,但是但是我还是写完了它,尽管花费了我好多好多时间,还好老师给了类图,不然我会直接放弃的好吗。

 

7-1 电信计费系列2-手机+座机计费

实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
1、针对市内座机用户采用的计费方式(与电信计费系列1内容相同):
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
假设本市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
2、针对手机用户采用实时计费方式:
月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟;
注:被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11

输入:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,含手机和座机用户
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题在电信计费系列1基础上增加类型1-手机实时计费。
手机设置0或者座机设置成1,此种错误可不做判断。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
输入格式增加手机接打电话以及收发短信的格式,手机接打电话的信息除了号码之外需要额外记录拨打/接听的地点的区号,比如:
座机打手机:
t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:
t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11

注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。

输出:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
 

建议类图:
参见图1、2、3:

image.png
图1

图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。
UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

图2

图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
 

image.png
图3

图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。    
 

(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。

我的最终代码如下:

  1 import java.util.ArrayList;
  2 import java.util.Comparator;
  3 import java.util.Scanner;
  4 import java.util.regex.Matcher;
  5 import java.util.regex.Pattern;
  6 import java.math.BigDecimal;
  7 import java.text.SimpleDateFormat;
  8 import java.util.Date;
  9 import java.util.Locale;
 10 import java.text.ParseException;
 11  
 12 public class Main {
 13  
 14     public static void main(String[] args) {
 15  
 16         Outputtool outputtool = new Outputtool();
 17         Inputdeal inputdeal = new Inputdeal();
 18         ArrayList<User> users = new ArrayList<>();
 19         Scanner in = new Scanner(System.in);
 20         String input = in.nextLine();
 21  
 22         while (!input.equals("end")) {
 23             if (1 == inputdeal.check(input)) {
 24                 inputdeal.writeUser(users, input);
 25             } else if (2 == inputdeal.check(input)) {
 26                 inputdeal.writeRecord(users, input);
 27             }
 28             input = in.nextLine();
 29         }
 30  
 31         users.sort(new Comparator<User>() {
 32  
 33             @Override
 34             public int compare(User u1, User u2) {
 35                 if (u1.getNumber().charAt(0) == '0' && u2.getNumber().charAt(0) != '0')
 36                     return -1;
 37                 else if (u1.getNumber().charAt(0) != '0' && u2.getNumber().charAt(0) == '0')
 38                     return 1;
 39                 if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) 
 40                     return 1;
 41                 else 
 42                     return -1;
 43             }
 44         });
 45  
 46         for (User u : users) {
 47             System.out.print(u.getNumber() + " ");
 48             outputtool.output(u.calCost());
 49             System.out.print(" ");
 50             outputtool.output(u.calBalance());
 51             System.out.println();
 52  
 53         } 
 54     } 
 55 }
 56  
 57 abstract class ChargeMode {
 58     protected ArrayList<ChargeRule> chargeRules = new ArrayList<>();
 59     public abstract double calCost(UserRecords userRecords);
 60     public abstract double getMonthlyRent();
 61     public ArrayList<ChargeRule> getChargeRules() {
 62         return chargeRules;
 63     }
 64  
 65     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
 66         this.chargeRules = chargeRules;
 67     }
 68 }
 69  
 70 class UserRecords {
 71  
 72     private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
 73     private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
 74     private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
 75     private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
 76     private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
 77     private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
 78     private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
 79     private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();
 80  
 81     public void addCallingInCityRecords(CallRecord callRecord) {
 82         callingInCityRecords.add(callRecord);
 83     }
 84  
 85     public void addCallingInProvinceRecords(CallRecord callRecord) {
 86         callingInProvinceRecords.add(callRecord);
 87     }
 88  
 89     public void addCallingInLandRecords(CallRecord callRecord) {
 90         callingInLandRecords.add(callRecord);
 91     }
 92  
 93     public void addAnswerInCityRecords(CallRecord callRecord) {
 94         answerInCityRecords.add(callRecord);
 95     }
 96  
 97     public void aaddAnswerInProvinceRecords(CallRecord callRecord) {
 98         answerInProvinceRecords.add(callRecord);
 99     }
100  
101     public void addAnswerInLandRecords(CallRecord callRecord) {
102         answerInLandRecords.add(callRecord);
103     }
104  
105     public void addSendMessageRecords(MessageRecord callRecord) {
106         sendMessageRecords.add(callRecord);
107     }
108  
109     public void addReceiveMessageRecords(MessageRecord callRecord) {
110         receiveMessageRecords.add(callRecord);
111     }
112  
113     public ArrayList<CallRecord> getCallingInCityRecords() {
114         return callingInCityRecords;
115     }
116  
117     public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) {
118         this.callingInCityRecords = callingInCityRecords;
119     }
120  
121     public ArrayList<CallRecord> getCallingInProvinceRecords() {
122         return callingInProvinceRecords;
123     }
124  
125     public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) {
126         this.callingInProvinceRecords = callingInProvinceRecords;
127     }
128  
129     public ArrayList<CallRecord> getCallingInLandRecords() {
130         return callingInLandRecords;
131     }
132  
133     public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) {
134         this.callingInLandRecords = callingInLandRecords;
135     }
136  
137     public ArrayList<CallRecord> getAnswerInCityRecords() {
138         return answerInCityRecords;
139     }
140  
141     public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) {
142         this.answerInCityRecords = answerInCityRecords;
143     }
144  
145     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
146         return answerInProvinceRecords;
147     }
148  
149     public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) {
150         this.answerInProvinceRecords = answerInProvinceRecords;
151     }
152  
153     public ArrayList<CallRecord> getAnswerInLandRecords() {
154         return answerInLandRecords;
155     }
156  
157     public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) {
158         this.answerInLandRecords = answerInLandRecords;
159     }
160  
161     public ArrayList<MessageRecord> getSendMessageRecords() {
162         return sendMessageRecords;
163     }
164  
165     public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) {
166         this.sendMessageRecords = sendMessageRecords;
167     }
168  
169     public ArrayList<MessageRecord> getReceiveMessageRecords() {
170         return receiveMessageRecords;
171     }
172  
173     public void setReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) {
174         this.receiveMessageRecords = receiveMessageRecords;
175     }
176  
177 }
178  
179 class LandlinePhoneCharging extends ChargeMode {
180  
181     private double monthlyRent = 20;
182     public LandlinePhoneCharging() {
183         super();
184         chargeRules.add(new LandPhoneInCityRule());
185         chargeRules.add(new LandPhoneInProvinceRule());
186         chargeRules.add(new LandPhoneInlandRule());
187     }
188  
189     @Override
190     public double calCost(UserRecords userRecords) {
191         double sumCost = 0;
192         for (ChargeRule rule : chargeRules) {
193             sumCost += rule.calCost(userRecords);
194         }
195         return sumCost;
196     }
197  
198     @Override
199     public double getMonthlyRent() {
200         return monthlyRent;
201     }
202  
203 }
204  
205 class MobilePhoneCharging extends ChargeMode {
206  
207     private double monthlyRent = 15;
208     public MobilePhoneCharging() {
209         super();
210         chargeRules.add(new MobilePhoneInCityRule());
211         chargeRules.add(new MobilePhoneInProvinceRule());
212         chargeRules.add(new MobilePhoneInlandRule());
213     }
214  
215     @Override
216     public double calCost(UserRecords userRecords) {
217         double sumCost = 0;
218         for (ChargeRule rule : chargeRules) {
219             sumCost += rule.calCost(userRecords);
220         }
221         return sumCost;
222     }
223  
224     @Override
225     public double getMonthlyRent() {
226         return monthlyRent;
227     }
228  
229 }
230  
231 class Inputdeal {
232  
233     public int check(String input) {
234         if (input.matches("[u]-0791[0-9]{7,8}\\s[0]") || input.matches("[u]-1[0-9]{10}\\s[1]")) {
235             return 1;
236         } else if (input.matches("(([t]-0791[0-9]{7,8}\\s" + "0[0-9]{9,11}\\s)|" 
237                 + "([t]-0791[0-9]{7,8}\\s" + "1[0-9]{10}\\s" + "0[0-9]{2,3}\\s)|" 
238                 + "([t]-1[0-9]{10}\\s" + "0[0-9]{2,3}\\s" + "0[0-9]{9,11}\\s)|" 
239                 + "([t]-1[0-9]{10}\\s" + "0[0-9]{2,3}\\s" + "1[0-9]{10}\\s" + "0[0-9]{2,3}\\s))"
240                 
241                 + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.(((0?[13578]|1[02])\\.(0?"
242                 + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|((("
243                 + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))"
244                 + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])\\s"
245                 + "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]|[0-9][1-9][0-9]{2}|[1-9][0-9]{3})\\.((([13578]|1[02])\\.("
246                 + "[1-9]|[12][0-9]|3[01]))|(([469]|11)\\.([1-9]|[12][0-9]|30))|(2\\.([1-9]|[1][0-9]|2[0-8]))))|((("
247                 + "[0-9]{2})([48]|[2468][048]|[13579][26])|(([48]|[2468][048]|[3579][26])00))\\.2\\.29))"
248                 + "\\s([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])")) {
249             return 2;
250         }
251         return 0;
252     }
253  
254     @SuppressWarnings("unused")
255     private boolean validatet(String string) {
256         if (!string.matches("^([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$")) {
257             return false;
258         }
259         return true;
260     }
261  
262     public static boolean validate(String dateString) {
263         // 使用正则表达式 测试 字符 符合 dddd.dd.dd 的格式(d表示数字)
264         Pattern p = Pattern.compile("\\d{4}+[\\.]\\d{1,2}+[\\.]\\d{1,2}+");
265         Matcher m = p.matcher(dateString);
266         if (!m.matches()) {
267             return false;
268         }
269  
270         // 得到年月日
271         String[] array = dateString.split("\\.");
272         int year = Integer.valueOf(array[0]);
273         int month = Integer.valueOf(array[1]);
274         int day = Integer.valueOf(array[2]);
275  
276         if (month < 1 || month > 12) {
277             return false;
278         }
279         int[] monthLengths = new int[] { 0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
280         if (isLeapYear(year)) {
281             monthLengths[2] = 29;
282         } else {
283             monthLengths[2] = 28;
284         }
285         int monthLength = monthLengths[month];
286         if (day < 1 || day > monthLength) {
287             return false;
288         }
289         return true;
290     }
291  
292     /** 是否是闰年 */
293     private static boolean isLeapYear(int year) {
294         return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
295     }
296  
297     public boolean judge(String input) {
298  
299         return false;
300     }
301  
302     public void writeUser(ArrayList<User> users, String input) {
303         User usernew = new User();
304         String[] inputs = input.split(" ");
305         String num = inputs[0].substring(2);
306         for (User i : users) {
307             if (i.getNumber().equals(num)) {
308                 return;
309             }
310         }
311         usernew.setNumber(num);
312         int mode = Integer.parseInt(inputs[1]);
313         if (mode == 0) {
314             usernew.setChargeMode(new LandlinePhoneCharging());
315         } else if (mode == 1) {
316             usernew.setChargeMode(new MobilePhoneCharging());
317         }
318         users.add(usernew);
319     }
320  
321     public void writeRecord(ArrayList<User> users, String input) {
322         String[] inputs = input.split(" ");
323  
324         User callu = null, answeru = null;
325         CallRecord callrecord = new CallRecord(inputs);
326  
327         if (input.charAt(0) == 't') {
328             String out = inputs[0];
329             String in = "";
330             if (inputs.length == 6) {
331                 in = inputs[1];
332             } else if (inputs.length == 7) {
333                 in = inputs[1];
334             } else if (inputs.length == 8) {
335                 in = inputs[2];
336             }
337  
338             for (User i : users) {
339                 if (i.getNumber().equals(out)) {
340                     callu = i;
341                 }
342                 if (i.getNumber().equals(in)) {
343                     answeru = i;
344                 }
345                 if (callu != null && answeru != null) {
346                     break;
347                 }
348             }
349  
350             if (callu != null) {
351                 if (callrecord.getCallType().matches("^1[1-3]$")) {
352                     callu.getUserRecords().addCallingInCityRecords(callrecord);
353                 } else if (callrecord.getCallType().matches("^2[1-3]$")) {
354                     callu.getUserRecords().addCallingInProvinceRecords(callrecord);
355                 } else {
356                     callu.getUserRecords().addCallingInLandRecords(callrecord);
357                 }
358             }
359  
360             if (answeru != null) {
361                 if (callrecord.getCallType().matches("^[1-3]1$")) {
362                     answeru.getUserRecords().addAnswerInCityRecords(callrecord);
363                 } else if (callrecord.getCallType().matches("^[1-3]2$")) {
364                     answeru.getUserRecords().aaddAnswerInProvinceRecords(callrecord);
365                 } else {
366                     answeru.getUserRecords().addAnswerInLandRecords(callrecord);
367                 }
368             }
369         } else if (input.charAt(0) == 'm') {
370  
371         }
372  
373     }
374  
375 }
376  
377 abstract class CommunicationRecord {
378     protected String callingNumber;
379     protected String answerNumbe;
380  
381     public String getCallingNumber() {
382         return callingNumber;
383     }
384  
385     public void setCallingNumber(String callingNumber) {
386         this.callingNumber = callingNumber;
387     }
388  
389     public String getAnswerNumbe() {
390         return answerNumbe;
391     }
392  
393     public void setAnswerNumbe(String answerNumbe) {
394         this.answerNumbe = answerNumbe;
395     }
396  
397 }
398  
399 abstract class ChargeRule {
400  
401     abstract public double calCost(UserRecords userRecords);
402  
403 }
404  
405 class CallRecord extends CommunicationRecord {
406     private Date startTime;
407     private Date endTime;
408     private String callingAddressAreaCode;
409     private String answerAddressAreaCode;
410  
411     public String getCallType() {
412         String type = "";
413         if (callingAddressAreaCode.equals("0791")) {
414             type = type.concat("1");
415         } else if (callingAddressAreaCode.matches("^079[023456789]$") || callingAddressAreaCode.equals("0701")) {
416             type = type.concat("2");
417         } else {
418             type = type.concat("3");
419         }
420  
421         if (answerAddressAreaCode.equals("0791")) {
422             type = type.concat("1");
423         } else if (answerAddressAreaCode.matches("^079[023456789]$") || answerAddressAreaCode.equals("0701")) {
424             type = type.concat("2");
425         } else {
426             type = type.concat("3");
427         }
428  
429         return type;
430     }
431  
432     public CallRecord(String[] inputs) {
433         super();
434  
435         char type = inputs[0].charAt(0);
436         inputs[0] = inputs[0].substring(2);
437  
438         String sd = null, st = null, ed = null, et = null;
439  
440         if (type == 't') {
441             if (inputs.length == 6) {
442                 sd = inputs[2];
443                 st = inputs[3];
444                 ed = inputs[4];
445                 et = inputs[5];
446                 callingAddressAreaCode = inputs[0].substring(0, 4);
447                 answerAddressAreaCode = inputs[1].substring(0, 4);
448             } else if (inputs.length == 7) {
449                 sd = inputs[3];
450                 st = inputs[4];
451                 ed = inputs[5];
452                 et = inputs[6];
453                 if (inputs[0].charAt(0) != '0') {
454                     if (inputs[2].length() == 10) {
455                         answerAddressAreaCode = inputs[2].substring(0, 3);
456                     } else {
457                         answerAddressAreaCode = inputs[2].substring(0, 4);
458                     }
459                     callingAddressAreaCode = inputs[1];
460                 } else {
461                     if (inputs[0].length() == 10) {
462                         callingAddressAreaCode = inputs[0].substring(0, 3);
463                     } else {
464                         callingAddressAreaCode = inputs[0].substring(0, 4);
465                     }
466                     answerAddressAreaCode = inputs[2];
467                 }
468             } else if (inputs.length == 8) {
469                 sd = inputs[4];
470                 st = inputs[5];
471                 ed = inputs[6];
472                 et = inputs[7];
473                 callingAddressAreaCode = inputs[1];
474                 answerAddressAreaCode = inputs[3];
475             }
476         } else if (type == 'm') {
477  
478         }
479         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
480         try {
481             startTime = simpleDateFormat.parse(sd + " " + st);
482             endTime = simpleDateFormat.parse(ed + " " + et);
483         } catch (ParseException e) {
484         }
485  
486     }
487  
488     public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) {
489         super();
490         this.startTime = startTime;
491         this.endTime = endTime;
492         this.callingAddressAreaCode = callingAddressAreaCode;
493         this.answerAddressAreaCode = answerAddressAreaCode;
494     }
495  
496     public Date getStartTime() {
497         return startTime;
498     }
499  
500     public void setStartTime(Date startTime) {
501         this.startTime = startTime;
502     }
503  
504     public Date getEndTime() {
505         return endTime;
506     }
507  
508     public void setEndTime(Date endTime) {
509         this.endTime = endTime;
510     }
511  
512     public String getCallingAddressAreaCode() {
513         return callingAddressAreaCode;
514     }
515  
516     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
517         this.callingAddressAreaCode = callingAddressAreaCode;
518     }
519  
520     public String getAnswerAddressAreaCode() {
521         return answerAddressAreaCode;
522     }
523  
524     public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
525         this.answerAddressAreaCode = answerAddressAreaCode;
526     }
527 }
528  
529 abstract class CallChargeRule extends ChargeRule {
530  
531 }
532  
533 class LandPhoneInCityRule extends CallChargeRule {
534  
535     @Override
536     public double calCost(UserRecords userRecords) {
537         double sumCost = 0;
538         for (CallRecord call : userRecords.getCallingInCityRecords()) {
539             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
540             if (distanceS < 0) {
541                 continue;
542             }
543             double distanceM = (int) distanceS / 60;
544             if (distanceS % 60 != 0) {
545                 distanceM += 1;
546             }
547             if (call.getCallType().equals("11")) {
548                 sumCost += distanceM * 0.1;
549             } else if (call.getCallType().equals("12")) {
550                 sumCost += distanceM * 0.3;
551             } else if (call.getCallType().equals("13")) {
552                 sumCost += distanceM * 0.6;
553             }
554         }
555         return sumCost;
556     }
557 }
558  
559 class LandPhoneInlandRule extends CallChargeRule {
560  
561     @Override
562     public double calCost(UserRecords userRecords) {
563         double sumCost = 0;
564         for (CallRecord call : userRecords.getCallingInLandRecords()) {
565             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
566             if (distanceS < 0) {
567                 continue;
568             }
569             double distanceM = (int) distanceS / 60;
570             if (distanceS % 60 != 0) {
571                 distanceM += 1;
572             }
573             sumCost += distanceM * 0.6;
574         }
575         return sumCost;
576     }
577  
578 }
579  
580 class LandPhoneInProvinceRule extends CallChargeRule {
581  
582     @Override
583     public double calCost(UserRecords userRecords) {
584         double sumCost = 0;
585         for (CallRecord call : userRecords.getCallingInProvinceRecords()) {
586             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
587             if (distanceS < 0) {
588                 continue;
589             }
590             double distanceM = (int) distanceS / 60;
591             if (distanceS % 60 != 0) {
592                 distanceM += 1;
593             }
594             sumCost += distanceM * 0.3;
595         }
596         return sumCost;
597     }
598  
599 }
600  
601 class MobilePhoneInCityRule extends CallChargeRule {
602  
603     @Override
604     public double calCost(UserRecords userRecords) {
605         double sumCost = 0;
606         for (CallRecord call : userRecords.getCallingInCityRecords()) {
607             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
608             if (distanceS < 0) {
609                 continue;
610             }
611             double distanceM = (int) distanceS / 60;
612             if (distanceS % 60 != 0) {
613                 distanceM += 1;
614             }
615             if (call.getCallType().equals("11")) {
616                 sumCost += distanceM * 0.1;
617             } else if (call.getCallType().equals("12")) {
618                 sumCost += distanceM * 0.2;
619             } else if (call.getCallType().equals("13")) {
620                 sumCost += distanceM * 0.3;
621             }
622         }
623         return sumCost;
624     }
625  
626 }
627  
628 class MobilePhoneInlandRule extends CallChargeRule {
629  
630     @Override
631     public double calCost(UserRecords userRecords) {
632         double sumCost = 0;
633         for (CallRecord call : userRecords.getCallingInLandRecords()) {
634             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
635             if (distanceS < 0) {
636                 continue;
637             }
638             double distanceM = (int) distanceS / 60;
639             if (distanceS % 60 != 0) {
640                 distanceM += 1;
641             }
642             sumCost += distanceM * 0.6;
643         }
644         for (CallRecord call : userRecords.getAnswerInLandRecords()) {
645             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
646             if (distanceS < 0) {
647                 continue;
648             }
649             double distanceM = (int) distanceS / 60;
650             if (distanceS % 60 != 0) {
651                 distanceM += 1;
652             }
653             sumCost += distanceM * 0.3;
654         }
655         return sumCost;
656     }
657  
658 }
659  
660 class MobilePhoneInProvinceRule extends CallChargeRule {
661  
662     @Override
663     public double calCost(UserRecords userRecords) {
664         double sumCost = 0;
665         for (CallRecord call : userRecords.getCallingInProvinceRecords()) {
666             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
667             if (distanceS < 0) {
668                 continue;
669             }
670             double distanceM = (int) distanceS / 60;
671             if (distanceS % 60 != 0) {
672                 distanceM += 1;
673             }
674             if (call.getCallType().equals("21")) {
675                 sumCost += distanceM * 0.3;
676             } else if (call.getCallType().equals("22")) {
677                 sumCost += distanceM * 0.3;
678             } else if (call.getCallType().equals("23")) {
679                 sumCost += distanceM * 0.3;
680             }
681         }
682         return sumCost;
683     }
684  
685 }
686  
687 class MessageRecord extends CommunicationRecord {
688  
689     private String message;
690  
691     public String getMessage() {
692         return message;
693     }
694  
695     public void setMessage(String message) {
696         this.message = message;
697     }
698 }
699  
700 class User {
701  
702     private UserRecords userRecords = new UserRecords();
703     private double balance = 100;
704     private ChargeMode chargeMode;
705     private String number;
706  
707     public double calCost() {
708         return chargeMode.calCost(userRecords);
709     }
710  
711     public double calBalance() {
712         return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords);
713     }
714  
715     public UserRecords getUserRecords() {
716         return userRecords;
717     }
718  
719     public void setUserRecords(UserRecords userRecords) {
720         this.userRecords = userRecords;
721     }
722  
723     public ChargeMode getChargeMode() {
724         return chargeMode;
725     }
726  
727     public void setChargeMode(ChargeMode chargeMode) {
728         this.chargeMode = chargeMode;
729     }
730  
731     public String getNumber() {
732         return number;
733     }
734  
735     public void setNumber(String number) {
736         this.number = number;
737     }
738  
739 }
740  
741 class Outputtool {
742  
743     @SuppressWarnings("deprecation")
744     public void output(double out) {
745         BigDecimal numb = new BigDecimal(out);
746         out = numb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
747         System.out.print(out);
748     }
749 }
点击展开我的代码

 

SourceMonitor的生成报表内容如下:

 

 小结:

         有了第一题的铺垫,第二题写起来就顺利多了!有了多边形的打击还怕写不出别的吗?哦一步一步拿到满分真是太舒服了!!!

 

7-1 电信计费系列3-短信计费

实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。

输入:
输入信息包括两种类型
1、逐行输入南昌市手机用户开户的信息,每行一个用户。
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐 3-手机短信计费)
例如:u-13305862264 3
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题只针对类型3-手机短信计费。
2、逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.

注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。

本题只考虑短信计费,不考虑通信费用以及月租费。

建议类图:
参见图1、2、3:

image.png

图1

图1中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。    
UserRecords是用户记录类,保存用户各种通话、短信的记录,    
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
 

image.png

图2

    图2中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。
 

image.png

图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。

(提示:可以从UserRecords类中获取各种类型的callRecords)。
 

注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。

我的最终代码如下:

 

  1 import java.util.ArrayList;
  2 import java.util.Comparator;
  3 import java.util.Scanner;
  4 import java.util.regex.Matcher;
  5 import java.util.regex.Pattern;
  6 import java.math.BigDecimal;
  7 import java.text.SimpleDateFormat;
  8 import java.util.Date;
  9 import java.util.Locale;
 10 import java.text.ParseException;
 11  
 12 public class Main {
 13  
 14     public static void main(String[] args) {
 15  
 16         Outputtool outputtool = new Outputtool();
 17         Inputdeal inputdeal = new Inputdeal();
 18         ArrayList<User> users = new ArrayList<>();
 19         Scanner in = new Scanner(System.in);
 20  
 21         String input = in.nextLine();
 22  
 23         while (!input.equals("end")) {
 24             if (1 == inputdeal.check(input)) {
 25                 inputdeal.writeUser(users, input);
 26             } else if (2 == inputdeal.check(input)) {
 27                 inputdeal.writeRecord(users, input);
 28             }
 29             input = in.nextLine();
 30         }
 31  
 32         users.sort(new Comparator<User>() {
 33  
 34             @Override
 35             public int compare(User u1, User u2) {
 36                 if (u1.getNumber().charAt(0) == '0' && u2.getNumber().charAt(0) != '0') {
 37                     return -1;
 38                 } else if (u1.getNumber().charAt(0) != '0' && u2.getNumber().charAt(0) == '0') {
 39                     return 1;
 40                 }
 41                 if (Double.parseDouble(u1.getNumber()) > Double.parseDouble(u2.getNumber())) {
 42                     return 1;
 43                 } else {
 44                     return -1;
 45                 }
 46             }
 47         });
 48  
 49         for (User u : users) {
 50             System.out.print(u.getNumber() + " ");
 51             outputtool.output(u.calCost());
 52             System.out.print(" ");
 53             outputtool.output(u.calBalance());
 54             System.out.println();
 55  
 56         }
 57  
 58     }
 59  
 60 }
 61  
 62 abstract class ChargeMode {
 63     protected ArrayList<ChargeRule> chargeRules = new ArrayList<>();
 64  
 65     public abstract double calCost(UserRecords userRecords);
 66  
 67     public abstract double getMonthlyRent();
 68  
 69     public ArrayList<ChargeRule> getChargeRules() {
 70         return chargeRules;
 71     }
 72  
 73     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
 74         this.chargeRules = chargeRules;
 75     }
 76 }
 77  
 78 class UserRecords {
 79  
 80     private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
 81     private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
 82     private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
 83     private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
 84     private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
 85     private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
 86     private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
 87     private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();
 88  
 89     public void addCallingInCityRecords(CallRecord callRecord) {
 90         callingInCityRecords.add(callRecord);
 91     }
 92  
 93     public void addCallingInProvinceRecords(CallRecord callRecord) {
 94         callingInProvinceRecords.add(callRecord);
 95     }
 96  
 97     public void addCallingInLandRecords(CallRecord callRecord) {
 98         callingInLandRecords.add(callRecord);
 99     }
100  
101     public void addAnswerInCityRecords(CallRecord callRecord) {
102         answerInCityRecords.add(callRecord);
103     }
104  
105     public void aaddAnswerInProvinceRecords(CallRecord callRecord) {
106         answerInProvinceRecords.add(callRecord);
107     }
108  
109     public void addAnswerInLandRecords(CallRecord callRecord) {
110         answerInLandRecords.add(callRecord);
111     }
112  
113     public void addSendMessageRecords(MessageRecord callRecord) {
114         sendMessageRecords.add(callRecord);
115     }
116  
117     public void addReceiveMessageRecords(MessageRecord callRecord) {
118         receiveMessageRecords.add(callRecord);
119     }
120  
121     public ArrayList<CallRecord> getCallingInCityRecords() {
122         return callingInCityRecords;
123     }
124  
125     public void setCallingInCityRecords(ArrayList<CallRecord> callingInCityRecords) {
126         this.callingInCityRecords = callingInCityRecords;
127     }
128  
129     public ArrayList<CallRecord> getCallingInProvinceRecords() {
130         return callingInProvinceRecords;
131     }
132  
133     public void setCallingInProvinceRecords(ArrayList<CallRecord> callingInProvinceRecords) {
134         this.callingInProvinceRecords = callingInProvinceRecords;
135     }
136  
137     public ArrayList<CallRecord> getCallingInLandRecords() {
138         return callingInLandRecords;
139     }
140  
141     public void setCallingInLandRecords(ArrayList<CallRecord> callingInLandRecords) {
142         this.callingInLandRecords = callingInLandRecords;
143     }
144  
145     public ArrayList<CallRecord> getAnswerInCityRecords() {
146         return answerInCityRecords;
147     }
148  
149     public void setAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) {
150         this.answerInCityRecords = answerInCityRecords;
151     }
152  
153     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
154         return answerInProvinceRecords;
155     }
156  
157     public void setAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) {
158         this.answerInProvinceRecords = answerInProvinceRecords;
159     }
160  
161     public ArrayList<CallRecord> getAnswerInLandRecords() {
162         return answerInLandRecords;
163     }
164  
165     public void setAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) {
166         this.answerInLandRecords = answerInLandRecords;
167     }
168  
169     public ArrayList<MessageRecord> getSendMessageRecords() {
170         return sendMessageRecords;
171     }
172  
173     public void setSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) {
174         this.sendMessageRecords = sendMessageRecords;
175     }
176  
177     public ArrayList<MessageRecord> getReceiveMessageRecords() {
178         return receiveMessageRecords;
179     }
180  
181     public void setReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) {
182         this.receiveMessageRecords = receiveMessageRecords;
183     }
184  
185 }
186  
187 class LandlinePhoneCharging extends ChargeMode {
188  
189     private double monthlyRent = 20;
190  
191     public LandlinePhoneCharging() {
192         super();
193         chargeRules.add(new LandPhoneInCityRule());
194         chargeRules.add(new LandPhoneInProvinceRule());
195         chargeRules.add(new LandPhoneInlandRule());
196     }
197  
198     @Override
199     public double calCost(UserRecords userRecords) {
200         double sumCost = 0;
201         for (ChargeRule rule : chargeRules) {
202             sumCost += rule.calCost(userRecords);
203         }
204         return sumCost;
205     }
206  
207     @Override
208     public double getMonthlyRent() {
209         return monthlyRent;
210     }
211  
212 }
213  
214 class MobilePhoneCharging extends ChargeMode {
215  
216     private double monthlyRent = 15;
217  
218     public MobilePhoneCharging() {
219         super();
220         chargeRules.add(new MobilePhoneInCityRule());
221         chargeRules.add(new MobilePhoneInProvinceRule());
222         chargeRules.add(new MobilePhoneInlandRule());
223     }
224  
225     @Override
226     public double calCost(UserRecords userRecords) {
227         double sumCost = 0;
228         for (ChargeRule rule : chargeRules) {
229             sumCost += rule.calCost(userRecords);
230         }
231         return sumCost;
232     }
233  
234     @Override
235     public double getMonthlyRent() {
236         return monthlyRent;
237     }
238  
239 }
240  
241 class MobilePhoneMassageCharging extends ChargeMode {
242  
243     private double monthlyRent = 0;
244  
245     public MobilePhoneMassageCharging() {
246         super();
247         chargeRules.add(new MobilePhoneMessageRule());
248     }
249  
250     @Override
251     public double calCost(UserRecords userRecords) {
252         double sumCost = 0;
253         for (ChargeRule rule : chargeRules) {
254             sumCost += rule.calCost(userRecords);
255         }
256         return sumCost;
257     }
258  
259     @Override
260     public double getMonthlyRent() {
261         return monthlyRent;
262     }
263  
264 }
265  
266 class Inputdeal {
267  
268     public int check(String input) {
269         if (input.matches("[u]-0791[0-9]{7,8}\\s[0]") || input.matches("[u]-1[0-9]{10}\\s[13]")) {
270             return 1;
271         } else if (input.matches("[m]-1[0-9]{10}\\s" + "1[0-9]{10}\\s" + "[0-9a-zA-Z\\s\\.,]+")) {
272             return 2;
273         }
274         return 0;
275     }
276  
277     public void writeUser(ArrayList<User> users, String input) {
278         User usernew = new User();
279         String[] inputs = input.split(" ");
280         String num = inputs[0].substring(2);
281         for (User i : users) {
282             if (i.getNumber().equals(num)) {
283                 return;
284             }
285         }
286         usernew.setNumber(num);
287         int mode = Integer.parseInt(inputs[1]);
288         if (mode == 0) {
289             usernew.setChargeMode(new LandlinePhoneCharging());
290         } else if (mode == 1) {
291             usernew.setChargeMode(new MobilePhoneCharging());
292         } else if (mode == 3) {
293             usernew.setChargeMode(new MobilePhoneMassageCharging());
294         }
295         users.add(usernew);
296     }
297  
298     public void writeRecord(ArrayList<User> users, String input) {
299         String[] inputs = input.split(" ");
300         inputs[0] = inputs[0].substring(2);
301  
302         User callu = null, answeru = null;
303  
304         String out = inputs[0];
305         String in = "";
306         if (inputs.length == 6) {
307             in = inputs[1];
308         } else if (inputs.length == 7) {
309             in = inputs[1];
310         } else if (inputs.length == 8) {
311             in = inputs[2];
312         } else {
313             in = inputs[1];
314         }
315  
316         for (User i : users) {
317             if (i.getNumber().equals(out)) {
318                 callu = i;
319             }
320             if (i.getNumber().equals(in)) {
321                 answeru = i;
322             }
323             if (callu != null && answeru != null) {
324                 break;
325             }
326         }
327  
328         if (input.charAt(0) == 'm') {
329             MessageRecord messageRecord = new MessageRecord(input);
330             if (callu != null) {
331                 callu.getUserRecords().addSendMessageRecords(messageRecord);
332                 ;
333             }
334             if (answeru != null) {
335                 callu.getUserRecords().addReceiveMessageRecords(messageRecord);
336             }
337         }
338  
339     }
340  
341 }
342  
343 abstract class CommunicationRecord {
344     protected String callingNumber;
345     protected String answerNumbe;
346  
347     public String getCallingNumber() {
348         return callingNumber;
349     }
350  
351     public void setCallingNumber(String callingNumber) {
352         this.callingNumber = callingNumber;
353     }
354  
355     public String getAnswerNumbe() {
356         return answerNumbe;
357     }
358  
359     public void setAnswerNumbe(String answerNumbe) {
360         this.answerNumbe = answerNumbe;
361     }
362  
363 }
364  
365 abstract class ChargeRule {
366  
367     abstract public double calCost(UserRecords userRecords);
368  
369 }
370  
371 class CallRecord extends CommunicationRecord {
372     private Date startTime;
373     private Date endTime;
374     private String callingAddressAreaCode;
375     private String answerAddressAreaCode;
376  
377     public String getCallType() {
378         String type = "";
379         if (callingAddressAreaCode.equals("0791")) {
380             type = type.concat("1");
381         } else if (callingAddressAreaCode.matches("^079[023456789]$") || callingAddressAreaCode.equals("0701")) {
382             type = type.concat("2");
383         } else {
384             type = type.concat("3");
385         }
386  
387         if (answerAddressAreaCode.equals("0791")) {
388             type = type.concat("1");
389         } else if (answerAddressAreaCode.matches("^079[023456789]$") || answerAddressAreaCode.equals("0701")) {
390             type = type.concat("2");
391         } else {
392             type = type.concat("3");
393         }
394  
395         return type;
396     }
397  
398     public CallRecord(String[] inputs) {
399         super();
400  
401         char type = inputs[0].charAt(0);
402  
403         String sd = null, st = null, ed = null, et = null;
404  
405         if (type == 't') {
406             if (inputs.length == 6) {
407                 sd = inputs[2];
408                 st = inputs[3];
409                 ed = inputs[4];
410                 et = inputs[5];
411                 callingAddressAreaCode = inputs[0].substring(0, 4);
412                 answerAddressAreaCode = inputs[1].substring(0, 4);
413             } else if (inputs.length == 7) {
414                 sd = inputs[3];
415                 st = inputs[4];
416                 ed = inputs[5];
417                 et = inputs[6];
418                 if (inputs[0].charAt(0) != '0') {
419                     if (inputs[2].length() == 10) {
420                         answerAddressAreaCode = inputs[2].substring(0, 3);
421                     } else {
422                         answerAddressAreaCode = inputs[2].substring(0, 4);
423                     }
424                     callingAddressAreaCode = inputs[1];
425                 } else {
426                     if (inputs[0].length() == 10) {
427                         callingAddressAreaCode = inputs[0].substring(0, 3);
428                     } else {
429                         callingAddressAreaCode = inputs[0].substring(0, 4);
430                     }
431                     answerAddressAreaCode = inputs[2];
432                 }
433             } else if (inputs.length == 8) {
434                 sd = inputs[4];
435                 st = inputs[5];
436                 ed = inputs[6];
437                 et = inputs[7];
438                 callingAddressAreaCode = inputs[1];
439                 answerAddressAreaCode = inputs[3];
440             }
441         } else if (type == 'm') {
442  
443         }
444         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.getDefault());
445         try {
446             startTime = simpleDateFormat.parse(sd + " " + st);
447             endTime = simpleDateFormat.parse(ed + " " + et);
448         } catch (ParseException e) {
449         }
450  
451     }
452  
453     public CallRecord(Date startTime, Date endTime, String callingAddressAreaCode, String answerAddressAreaCode) {
454         super();
455         this.startTime = startTime;
456         this.endTime = endTime;
457         this.callingAddressAreaCode = callingAddressAreaCode;
458         this.answerAddressAreaCode = answerAddressAreaCode;
459     }
460  
461     public Date getStartTime() {
462         return startTime;
463     }
464  
465     public void setStartTime(Date startTime) {
466         this.startTime = startTime;
467     }
468  
469     public Date getEndTime() {
470         return endTime;
471     }
472  
473     public void setEndTime(Date endTime) {
474         this.endTime = endTime;
475     }
476  
477     public String getCallingAddressAreaCode() {
478         return callingAddressAreaCode;
479     }
480  
481     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
482         this.callingAddressAreaCode = callingAddressAreaCode;
483     }
484  
485     public String getAnswerAddressAreaCode() {
486         return answerAddressAreaCode;
487     }
488  
489     public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
490         this.answerAddressAreaCode = answerAddressAreaCode;
491     }
492 }
493  
494 abstract class CallChargeRule extends ChargeRule {
495  
496 }
497  
498 class LandPhoneInCityRule extends CallChargeRule {
499  
500     @Override
501     public double calCost(UserRecords userRecords) {
502         double sumCost = 0;
503         for (CallRecord call : userRecords.getCallingInCityRecords()) {
504             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
505             if (distanceS < 0) {
506                 continue;
507             }
508             double distanceM = (int) distanceS / 60;
509             if (distanceS % 60 != 0) {
510                 distanceM += 1;
511             }
512             if (call.getCallType().equals("11")) {
513                 sumCost += distanceM * 0.1;
514             } else if (call.getCallType().equals("12")) {
515                 sumCost += distanceM * 0.3;
516             } else if (call.getCallType().equals("13")) {
517                 sumCost += distanceM * 0.6;
518             }
519         }
520         return sumCost;
521     }
522  
523 }
524  
525 class LandPhoneInlandRule extends CallChargeRule {
526  
527     @Override
528     public double calCost(UserRecords userRecords) {
529         double sumCost = 0;
530         for (CallRecord call : userRecords.getCallingInLandRecords()) {
531             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
532             if (distanceS < 0) {
533                 continue;
534             }
535             double distanceM = (int) distanceS / 60;
536             if (distanceS % 60 != 0) {
537                 distanceM += 1;
538             }
539             sumCost += distanceM * 0.6;
540         }
541         return sumCost;
542     }
543  
544 }
545  
546 class LandPhoneInProvinceRule extends CallChargeRule {
547  
548     @Override
549     public double calCost(UserRecords userRecords) {
550         double sumCost = 0;
551         for (CallRecord call : userRecords.getCallingInProvinceRecords()) {
552             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
553             if (distanceS < 0) {
554                 continue;
555             }
556             double distanceM = (int) distanceS / 60;
557             if (distanceS % 60 != 0) {
558                 distanceM += 1;
559             }
560             sumCost += distanceM * 0.3;
561         }
562         return sumCost;
563     }
564  
565 }
566  
567 class MobilePhoneInCityRule extends CallChargeRule {
568  
569     @Override
570     public double calCost(UserRecords userRecords) {
571         double sumCost = 0;
572         for (CallRecord call : userRecords.getCallingInCityRecords()) {
573             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
574             if (distanceS < 0) {
575                 continue;
576             }
577             double distanceM = (int) distanceS / 60;
578             if (distanceS % 60 != 0) {
579                 distanceM += 1;
580             }
581             if (call.getCallType().equals("11")) {
582                 sumCost += distanceM * 0.1;
583             } else if (call.getCallType().equals("12")) {
584                 sumCost += distanceM * 0.2;
585             } else if (call.getCallType().equals("13")) {
586                 sumCost += distanceM * 0.3;
587             }
588  
589         }
590         return sumCost;
591     }
592  
593 }
594  
595 class MobilePhoneInlandRule extends CallChargeRule {
596  
597     @Override
598     public double calCost(UserRecords userRecords) {
599         double sumCost = 0;
600         for (CallRecord call : userRecords.getCallingInLandRecords()) {
601             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
602             if (distanceS < 0) {
603                 continue;
604             }
605             double distanceM = (int) distanceS / 60;
606             if (distanceS % 60 != 0) {
607                 distanceM += 1;
608             }
609             sumCost += distanceM * 0.6;
610         }
611         for (CallRecord call : userRecords.getAnswerInLandRecords()) {
612             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
613             if (distanceS < 0) {
614                 continue;
615             }
616             double distanceM = (int) distanceS / 60;
617             if (distanceS % 60 != 0) {
618                 distanceM += 1;
619             }
620             sumCost += distanceM * 0.3;
621         }
622         return sumCost;
623     }
624  
625 }
626  
627 class MobilePhoneInProvinceRule extends CallChargeRule {
628  
629     @Override
630     public double calCost(UserRecords userRecords) {
631         double sumCost = 0;
632         for (CallRecord call : userRecords.getCallingInProvinceRecords()) {
633             double distanceS = (-call.getStartTime().getTime() + call.getEndTime().getTime()) / 1000;
634             if (distanceS < 0) {
635                 continue;
636             }
637             double distanceM = (int) distanceS / 60;
638             if (distanceS % 60 != 0) {
639                 distanceM += 1;
640             }
641             if (call.getCallType().equals("21")) {
642                 sumCost += distanceM * 0.3;
643             } else if (call.getCallType().equals("22")) {
644                 sumCost += distanceM * 0.3;
645             } else if (call.getCallType().equals("23")) {
646                 sumCost += distanceM * 0.3;
647             }
648         }
649         return sumCost;
650     }
651  
652 }
653  
654 class MobilePhoneMessageRule extends CallChargeRule {
655  
656     @Override
657     public double calCost(UserRecords userRecords) {
658         double sumCost = 0;
659         int number = 0;
660         for (MessageRecord m : userRecords.getSendMessageRecords()) {
661             int length = m.getMessage().length();
662             if (length <= 10) {
663                 number++;
664             } else {
665                 number += length / 10;
666                 if (length % 10 != 0) {
667                     number++;
668                 }
669             }
670         }
671         if (number <= 3) {
672             sumCost = number * 0.1;
673         } else if (number <= 5) {
674             sumCost = 0.3 + 0.2 * (number - 3);
675         } else {
676             sumCost = 0.7 + 0.3 * (number - 5);
677         }
678         return sumCost;
679     }
680  
681 }
682  
683 class MessageRecord extends CommunicationRecord {
684  
685     private String message;
686  
687     public MessageRecord(String input) {
688         super();
689         this.message = input.substring(26);
690     }
691  
692     public String getMessage() {
693         return message;
694     }
695  
696     public void setMessage(String message) {
697         this.message = message;
698     }
699 }
700  
701 class User {
702  
703     private UserRecords userRecords = new UserRecords();
704     private double balance = 100;
705     private ChargeMode chargeMode;
706     private String number;
707  
708     public double calCost() {
709         return chargeMode.calCost(userRecords);
710     }
711  
712     public double calBalance() {
713         return balance - chargeMode.getMonthlyRent() - chargeMode.calCost(userRecords);
714     }
715  
716     public UserRecords getUserRecords() {
717         return userRecords;
718     }
719  
720     public void setUserRecords(UserRecords userRecords) {
721         this.userRecords = userRecords;
722     }
723  
724     public ChargeMode getChargeMode() {
725         return chargeMode;
726     }
727  
728     public void setChargeMode(ChargeMode chargeMode) {
729         this.chargeMode = chargeMode;
730     }
731  
732     public String getNumber() {
733         return number;
734     }
735  
736     public void setNumber(String number) {
737         this.number = number;
738     }
739  
740 }
741  
742 class Outputtool {
743  
744     @SuppressWarnings("deprecation")
745     public void output(double out) {
746         BigDecimal numb = new BigDecimal(out);
747         out = numb.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
748         System.out.print(out);
749     }
750 }
点击展开我的代码

 

SourceMonitor的生成报表内容如下:

 

 小结:

         第三次时间紧迫,写的匆匆忙忙,但是在同学的帮助下,还是顺利的写完啦~~~

 

三、踩坑心得以及改进建议

1.当类和对象非常多时,导致我对之间的关系有些混乱,这说明我还需要多加练习,应用需要更加熟练。

2.对包装类中的方法不够清楚,导致使用时常常报错,在之后需要多次使用其中的方法来增加印象。

3.对SimpleDateFormat类的不了解也导致第一题使用了错误的方法判断的时间,对其余部分的格式判断也简单判断,没有使用正则表达式判断,导致座机计费格式判断并不全面。在学会使用SimpleDateFormat类进行时间判断后,使用正则表达式进行了前面的号码的判断。

四、总结

         这次的pta的作业让我知道了如何面向对象去设计实验,面向对象的好处,它的思路更清晰,修改起来更简单,代码耦合度小,代码复杂度低的优点。当我掌握这种方法后可以使代码复用度更高,可以使后面需要加什么代码直接可以加上去,不用再去另外写新的代码了。这三次连续的大作业老师都给了类图,在设计上少走了很多弯路,但是在之后的题目完成过程中,学会设计更为重要!java还有很多很多工具功能没学,在今后尽量学习更多。

 

posted on 2022-12-10 21:38  Remember#  阅读(26)  评论(0编辑  收藏  举报

导航