首页 > 其他分享 >PTA-oop第三次博客2022.12.4

PTA-oop第三次博客2022.12.4

时间:2022-12-05 20:23:42浏览次数:51  
标签:return String ArrayList PTA oop new public 2022.12 user

一.前言 

题目集六:

  本次大作业是第一次写电信计费,难度较前几次的多边形有了明显的下降,题目难点不再是算法的设计,而是类与类之间关系的设计,同样也是因为第一次写电信计费,刚开始的工作量确实很大,不过还好这一次题目集的题量不是很多,整体而言没有前几次作业的压力大

题目集七:

  电信计费系列二是在系列一上面添加了手机的计费规则,考察问题的核心还是我们对于类之间关系的掌握情况。不过好在这两次作业是分割开的,有了第一次实验代码的基础,添加手机的计费规则只需要对原来的代码进行修改就可以了,难度不大,主要问题还是时间格式的判断问题。

题目集八:

  电信计费系列三是有另外添加了短信的计费规则,不过在这次作业中甚至没有手机和座机之间电话的计算,这就变得更加简单了,不过同样的也多出了许多的问题,比如短信格式的判断等。

 

二.设计与分析

题目一:

实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租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 import java.util.ArrayList;
  2 import java.text.ParseException;
  3 import java.text.SimpleDateFormat;
  4 import java.util.Date;
  5 import java.util.Scanner;
  6 class Main {
  7     public static void main(String[] arges) {
  8         Scanner input = new Scanner(System.in);
  9         String date = input.nextLine();
 10         FormatTest f = new FormatTest(date);
 11         Tools t = new Tools();
 12         ArrayList<User> user = new ArrayList<User>();
 13         while (!date.equals("end")) {
 14             // System.out.print(t.isFromat()+"\n");
 15             if (f.isFromat()) {
 16                 if (f.getType() == 'u')
 17                     t.setUser(f, user);
 18                 else
 19                     t.setInfo(f, user);
 20             }
 21             date = input.nextLine();
 22             f = new FormatTest(date);
 23         }
 24         user = t.OrderUser(user);
 25         for (int i = 0; i < user.size(); i++) {
 26             System.out.print(user.get(i).getNumber()+" ");
 27             t.FormatOut(user.get(i).calCost());
 28             System.out.print(" ");
 29             t.FormatOut(user.get(i).calBalance());
 30             System.out.print("\n");
 31         }
 32     }
 33 }
 34 abstract class  CallChargeRule extends ChargeRules{
 35     
 36     public abstract double calCost(ArrayList<CallRecord> callRecords);
 37 }
 38 class CallRecord extends CommunicationRecord {
 39     private Date startTime;
 40     private Date endTime;
 41     private String callingAddressAreaCode;
 42     private String answerAddressAreaCode;
 43     public Date getStartTime() {
 44         return startTime;
 45     }
 46 
 47     public void setStartTime(Date startTime) {
 48         this.startTime = startTime;
 49     }
 50 
 51     public Date getendTime() {
 52         return endTime;
 53     }
 54 
 55     public void setendTime(Date endTime) {
 56         this.endTime = endTime;
 57     }
 58 
 59     public String getCallingAddressAreaCode() {
 60         return callingAddressAreaCode;
 61     }
 62 
 63     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
 64         this.callingAddressAreaCode = callingAddressAreaCode;
 65     }
 66 
 67     public String getAnswerAddressAreaCode() {
 68         return answerAddressAreaCode;
 69     }
 70 
 71     public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
 72         this.answerAddressAreaCode = answerAddressAreaCode;
 73     }
 74 
 75 }
 76 abstract class ChargeMode {
 77     protected ArrayList<ChargeRules> chargeRules = new ArrayList<>();
 78 
 79     public ArrayList<ChargeRules> getChargeRules() {
 80         return chargeRules;
 81     }
 82 
 83     public void setChargeRules(ArrayList<ChargeRules> chargeRules) {
 84         this.chargeRules = chargeRules;
 85     }
 86     public abstract double calCost(UserRecords userRecords);
 87     public abstract double getMonthlyRent();
 88 }
 89 abstract class ChargeRules {
 90 
 91 }
 92 abstract class CommunicationRecord {
 93     protected String callingNumber;
 94     protected String answerNumber;
 95     public String getCallingNumber() {
 96         return callingNumber;
 97     }
 98     public void setCallingNumber(String callingNumber) {
 99         this.callingNumber = callingNumber;
100     }
101     public String getAnswerNumber() {
102         return answerNumber;
103     }
104     public void setAnswerNumber(String answerNumber) {
105         this.answerNumber = answerNumber;
106     }
107 }
108 class FormatTest {
109     String s;
110     SimpleDateFormat Format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
111 
112     FormatTest(String s) {
113         this.s = s;
114     }
115 
116     public boolean isTimeFormat(String date) throws ParseException {
117 
118         Format.parse(date);
119 
120         String forhead = date.split(" ")[0];
121         String behind = date.split(" ")[1];
122         int year = Integer.parseInt(forhead.split("\\.")[0]);
123         int month = Integer.parseInt(forhead.split("\\.")[1]);
124         int day = Integer.parseInt(forhead.split("\\.")[2]);
125         int hours = Integer.parseInt(behind.split(":")[0]);
126         int minute = Integer.parseInt(behind.split(":")[1]);
127         int second = Integer.parseInt(behind.split(":")[2]);
128         if (month < 0 || month > 12)
129             return false;
130         int[] monthLengths = new int[] { 0, 31, -1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
131         if (isLeapYear(year)) {
132             monthLengths[2] = 29;
133         } else {
134             monthLengths[2] = 28;
135         }
136         int monthLength = monthLengths[month];
137         if (day < 1 || day > monthLength) {
138             return false;
139         }
140         if (hours < 0 || hours > 23)
141             return false;
142         if (second < 0 || second > 59)
143             return false;
144         if (minute < 0 || minute > 59)
145             return false;
146         return true;
147 
148     }
149 
150     private boolean isLeapYear(int year) {
151         return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
152     }
153 
154     public String getUserNumber() {
155         return s.substring(2).split(" ")[0];
156 
157     }
158 
159     public String getCallingAreaCode() {
160         return s.substring(2).split(" ")[0].substring(0, 4);
161 
162     }
163 
164     public String getAnswerAreaCode() {
165         return s.substring(2).split(" ")[1].substring(0, 4);
166 
167     }
168 
169     public String getCallingNumber() {
170         return s.substring(2).split(" ")[0];
171 
172     }
173 
174     public String getAnswerNumber() {
175         return s.substring(2).split(" ")[1];
176 
177     }
178 
179     public String getUserMode() {
180         return s.substring(2).split(" ")[1];
181 
182     }
183 
184     public Date getstartTime() {
185         Date startTime = null;
186         String detail[];
187         detail = s.substring(2).split(" ");
188         String StartTime = detail[2].concat(" " + detail[3]);
189         try {
190             startTime = Format.parse(StartTime);
191         } catch (ParseException e) {
192 
193             e.printStackTrace();
194         }
195         return startTime;
196     }
197 
198     public Date getendTime() {
199         Date endTime = null;
200         String detail[];
201         detail = s.substring(2).split(" ");
202         String EndTime = detail[4].concat(" " + detail[5]);
203         try {
204             endTime = Format.parse(EndTime);
205         } catch (ParseException e) {
206 
207             e.printStackTrace();
208         }
209         return endTime;
210 
211     }
212 
213     public char getType() {
214         return s.charAt(0);
215     }
216 
217     public boolean isFromat() {
218         try {
219             char type = s.charAt(0);
220             if (type == 'u') {
221                 return AccountFormat();
222             } else if (type == 't') {
223                 return InfoFormat();
224             } else
225                 return false;
226         } catch (Exception e) {
227             return false;
228         }
229     }
230 
231     private boolean InfoFormat() throws ParseException {
232         String tPattern = "t-\\d{10,12}\\s" + "\\d{10,12}\\s" +
233                  "([1-9][0-9]*\\.[1-9][0-9]?\\.[1-9][0-9]? ([0|1]?[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9] ?){2}";
234         if(s.matches(tPattern))
235             return true;
236         else
237                 return false;
238         /*String detail[];
239         detail = s.substring(2).split(" ");
240         if(detail.length!=6)
241             return false;
242         String StartTime = detail[2].concat(" " + detail[3]);
243         String EndTime = detail[4].concat(" " + detail[5]);
244         if (!isCallFormat(detail[0]))
245             return false;
246         if (!isCallFormat(detail[1]))
247             return false;
248         if (!isTimeFormat(StartTime))
249             return false;
250         if (!isTimeFormat(EndTime))
251             return false;
252         if (!isIntervalFormat(StartTime, EndTime))
253             return false;
254         return true;*/
255 
256     }
257 
258     private boolean isIntervalFormat(String startTime, String endTime) throws ParseException {
259         Date start = null;
260         Date end = null;
261 
262         start = Format.parse(startTime);
263 
264         end = Format.parse(endTime);
265 
266         Long interval = (end.getTime() - start.getTime()) / 1000;
267         if (interval < 0)
268             return false;
269         else
270             return true;
271 
272     }
273 
274     private boolean AccountFormat() {
275         String uPattern = "u-\\d{10,12}\\s[0-2]";
276         if(!s.matches(uPattern))
277             return false;
278         else
279             return true;
280         /*String detail[];
281         detail = s.substring(2).split(" ");
282         if(detail.length!=2)
283             return false;
284         String Call = detail[0];
285         String Type = detail[1];
286         if (!isCallFormat(Call))
287             return false;
288         if (!Type.matches("[012]"))
289             return false;
290         return true;*/
291 
292     }
293 
294     private boolean isCallFormat(String call) {
295         return call.matches("0791[0-9]{7,8}\\s" + "0[0-9]{9,11}\\s");
296     }
297 }
298 
299 
300 
301 class LandlinePhoneCharging extends ChargeMode{
302     private double monthlyRent=20;
303     public LandlinePhoneCharging() {
304         
305         /*super();
306         chargeRules.add(new LandPhoneInCityRule());
307         chargeRules.add(new LandPhoneInProvinceRule());
308         chargeRules.add(new LandPhoneInLandRule());*/
309     }
310     @Override
311     public double calCost(UserRecords userRecords) {
312         ArrayList<CallRecord> InCitycallRecords =new ArrayList<CallRecord>();
313         ArrayList<CallRecord> InProvincecallRecords =new ArrayList<CallRecord>();
314         ArrayList<CallRecord> InLandcallRecords =new ArrayList<CallRecord>();
315         CallChargeRule InCityCharge = new LandPhoneInCityRule();
316         CallChargeRule InProvinceCharge = new LandPhoneInProvinceRule();
317         CallChargeRule InLandCharge = new LandPhoneInLandRule();
318         for(int i=0;i<userRecords.getCallingInCityRecords().size();i++) 
319             InCitycallRecords.add(userRecords.getCallingInCityRecords().get(i));
320         for(int i=0;i<userRecords.getCallingInProvinceRecords().size();i++) 
321             InProvincecallRecords.add(userRecords.getCallingInProvinceRecords().get(i));
322         for(int i=0;i<userRecords.getCallingInLandRecords().size();i++) 
323             InLandcallRecords.add(userRecords.getCallingInLandRecords().get(i));
324         return InCityCharge.calCost(InCitycallRecords)+InProvinceCharge.calCost(InProvincecallRecords)+InLandCharge.calCost(InLandcallRecords);
325     }
326 
327     @Override
328     public double getMonthlyRent() {
329         // TODO 自动生成的方法存根
330         return monthlyRent;
331     }
332 
333     public void setMonthlyRent(double monthlyRent) {
334         this.monthlyRent = monthlyRent;
335     }
336 
337 }
338 class LandPhoneInCityRule extends CallChargeRule{
339     long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
340     long nh = 1000 * 60 * 60;// 一小时的毫秒数
341     long nm = 1000 * 60;// 一分钟的毫秒数
342     long ns = 1000;// 一秒钟的毫秒数
343     @Override
344     public double calCost(ArrayList<CallRecord> callRecords) {
345         double sum=0;
346         for(int i=0;i<callRecords.size();i++) {
347             Date startTime=callRecords.get(i).getStartTime();
348             Date endTime=callRecords.get(i).getendTime();
349             Long interval = (endTime.getTime() - startTime.getTime())/1000;
350             if(interval%60!=0)
351                 interval=(interval/60)+1;
352             else
353                 interval=interval/60;
354             sum=sum+interval*0.1;
355         }
356         return sum;
357     }
358 
359 }
360 class LandPhoneInLandRule extends CallChargeRule{
361     long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
362     long nh = 1000 * 60 * 60;// 一小时的毫秒数
363     long nm = 1000 * 60;// 一分钟的毫秒数
364     long ns = 1000;// 一秒钟的毫秒数
365     @Override
366     public double calCost(ArrayList<CallRecord> callRecords) {
367         double sum=0;
368         for(int i=0;i<callRecords.size();i++) {
369             Date startTime=callRecords.get(i).getStartTime();
370             Date endTime=callRecords.get(i).getendTime();
371             Long interval = (endTime.getTime() - startTime.getTime())/1000;
372             if(interval%60!=0)
373                 interval=(interval/60)+1;
374             else
375                 interval=interval/60;
376             sum=sum+interval*0.6;
377         }
378         return sum;
379     }
380 
381 }
382 class LandPhoneInProvinceRule extends CallChargeRule{
383     long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
384     long nh = 1000 * 60 * 60;// 一小时的毫秒数
385     long nm = 1000 * 60;// 一分钟的毫秒数
386     long ns = 1000;// 一秒钟的毫秒数
387     @Override
388     public double calCost(ArrayList<CallRecord> callRecords) {
389         double sum=0;
390         for(int i=0;i<callRecords.size();i++) {
391             Date startTime=callRecords.get(i).getStartTime();
392             Date endTime=callRecords.get(i).getendTime();
393             Long interval = (endTime.getTime() - startTime.getTime())/1000;
394             if(interval%60!=0)
395                 interval=(interval/60)+1;
396             else
397                 interval=interval/60;
398             sum=sum+interval*0.3;
399         }
400         return sum;
401     }
402 
403 }
404 class MessageRecord {
405     private String message;
406 
407     public String getMessage() {
408         return message;
409     }
410 
411     public void setMessage(String message) {
412         this.message = message;
413     }
414     
415 }
416 class Tools {
417     public void setInfo(FormatTest f, ArrayList<User> user) {
418         int call;
419         call=this.isAccounted(f.getCallingNumber(),user);
420         if(call!=-1) {
421             CallRecord record=new CallRecord();
422             record.setAnswerAddressAreaCode(f.getAnswerAreaCode());
423             record.setCallingAddressAreaCode(f.getCallingAreaCode());
424             record.setAnswerNumber(f.getAnswerNumber());
425             record.setCallingNumber(f.getCallingNumber());
426             record.setStartTime(f.getstartTime());
427             record.setendTime(f.getendTime());
428             user.get(call).setUserRecords(record);
429         }
430     }
431 
432     public void setUser(FormatTest t, ArrayList<User> user) {
433         User u = new User();
434         if (isAccounted(t.getUserNumber(), user) == -1) {
435             u.setNumber(t.getUserNumber());
436             if (t.getUserMode().matches("0"))
437                 u.setChargeMode(new LandlinePhoneCharging());
438             user.add(u);
439         }
440     }
441     public void setUserChargeMode(FormatTest t, ArrayList<User> user) {
442         User u = new User();
443         u.setNumber(t.getUserNumber());
444         user.add(u);
445     }
446     public int isAccounted(String num,ArrayList<User> user) {
447         for(int i=0;i<user.size();i++)
448             if(user.get(i).getNumber().equals(num))
449                 return i;
450         return -1;
451     }
452     public void FormatOut(double x) {
453         if ((x * 1e1) % 10 != 0)
454             System.out.printf("%.1f", x);
455         else
456             System.out.print(x);
457     }
458     public ArrayList<User> OrderUser(ArrayList<User> user){
459         ArrayList<User> u = new ArrayList<User>();
460         int index=0;
461         while (user.size()!=0){
462             {
463             index=0;
464                 for(int j=0;j<user.size();j++)
465                 {
466                     if(user.get(j).getNumber().compareTo(user.get(index).getNumber())<0)
467                         index=j;
468                 }
469                 u.add(user.get(index));
470                 user.remove(index);
471             }
472     }
473         return u;
474     }
475 }
476 class User {
477     private UserRecords userRecords = new UserRecords();
478     private double balance = 100;
479     private ChargeMode chargeMode;
480     private String number;
481 
482     public double calBalance() {
483         return balance-this.calCost()-this.chargeMode.getMonthlyRent();
484     }
485 
486     public double calCost() {
487         return this.chargeMode.calCost(userRecords);
488 
489     }
490 
491     public UserRecords getUserRecords() {
492         return userRecords;
493     }
494 
495     public void setUserRecords(CallRecord record) {
496         if(record.getAnswerAddressAreaCode().equals("0791"))
497             this.userRecords.addCallingInCityRecords(record);
498         else if(record.getAnswerAddressAreaCode().matches("079\\d||0701"))
499             this.userRecords.addCallingInProvinceRecords(record);
500         else
501             this.userRecords.addCallingInLandRecords(record);
502     }
503 
504     public double getBalance() {
505         return balance;
506     }
507 
508     public ChargeMode getChargeMode() {
509         return chargeMode;
510     }
511 
512     public void setChargeMode(ChargeMode chargeMode) {
513         this.chargeMode = chargeMode;
514     }
515 
516     public String getNumber() {
517         return number;
518     }
519 
520     public void setNumber(String number) {
521         this.number = number;
522     }
523 }
524 class UserRecords {
525     private ArrayList<CallRecord> callingInCityRecords =new  ArrayList<CallRecord>();
526     private ArrayList<CallRecord> callingInProvinceRecords =new  ArrayList<CallRecord>();
527     private ArrayList<CallRecord> callingInLandRecords =new  ArrayList<CallRecord>();
528     private ArrayList<CallRecord> answerInCityRecords =new  ArrayList<CallRecord>();
529     private ArrayList<CallRecord> answerInProvinceRecords =new  ArrayList<CallRecord>();
530     private ArrayList<CallRecord> answerInLandRecords =new  ArrayList<CallRecord>();
531     private ArrayList<MessageRecord> sendMessageRecords =new  ArrayList<MessageRecord>();
532     private ArrayList<MessageRecord> receiveMessageRecords =new ArrayList<MessageRecord>();
533 
534     public ArrayList<CallRecord> getCallingInCityRecords() {
535         return callingInCityRecords;
536     }
537 
538     public void addCallingInCityRecords(CallRecord callingInCityRecords) {
539         this.callingInCityRecords.add(callingInCityRecords);
540     }
541 
542     public ArrayList<CallRecord> getAnswerInCityRecords() {
543         return answerInCityRecords;
544     }
545 
546     public void addAnswerInCityRecords(CallRecord answerInCityRecords) {
547         this.answerInCityRecords.add(answerInCityRecords);
548     }
549 
550     public ArrayList<CallRecord> getCallingInProvinceRecords() {
551         return callingInProvinceRecords;
552     }
553 
554     public void addCallingInProvinceRecords(CallRecord callingInProvinceRecords) {
555         this.callingInProvinceRecords.add(callingInProvinceRecords);
556     }
557 
558     public ArrayList<CallRecord> getCallingInLandRecords() {
559         return callingInLandRecords;
560     }
561 
562     public void addCallingInLandRecords(CallRecord callingInLandRecords) {
563         this.callingInLandRecords.add(callingInLandRecords);
564     }
565 
566     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
567         return answerInProvinceRecords;
568     }
569 
570     public void addAnswerInProvinceRecords(CallRecord answerInProvinceRecords) {
571         this.answerInProvinceRecords.add(answerInProvinceRecords);
572     }
573 
574     public ArrayList<CallRecord> getAnswerInLandRecords() {
575         return answerInLandRecords;
576     }
577 
578     public void addAnswerInLandRecords(CallRecord answerInLandRecords) {
579         this.answerInLandRecords.add(answerInLandRecords);
580     }
581 
582     public ArrayList<MessageRecord> getSendMessageRecords() {
583         return sendMessageRecords;
584     }
585 
586     public void addSendMessageRecords(MessageRecord sendMessageRecords) {
587         this.sendMessageRecords.add(sendMessageRecords);
588     }
589 
590     public ArrayList<MessageRecord> getReceiveMessageRecords() {
591         return receiveMessageRecords;
592     }
593 
594     public void addReceiveMessageRecords(MessageRecord receiveMessageRecords) {
595         this.receiveMessageRecords.add(receiveMessageRecords);
596     }
597     
598 }
View Code

 

类图设计是在题目中就提供了一个参考,这也正是本题的难点,虽说是提供了参考,但是我们目前的能力也只能比着题目里的类图来进行写代码,看懂类图并且如何运用提供的类图写代码便成为了这道题目最难的点。题目算法较为简单,圈复杂度与代码深度都处于一个合理的范围。

题目二:

实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
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元。
每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。

  1 import java.util.ArrayList;
  2 import java.text.ParseException;
  3 import java.text.SimpleDateFormat;
  4 import java.util.Date;
  5 import java.util.Scanner;
  6 
  7 class Main {
  8     public static void main(String[] arges) {
  9         Scanner input = new Scanner(System.in);
 10         String data = input.nextLine();
 11         Format f = new Format(data);
 12         Tools t = new Tools();
 13         ArrayList<User> user = new ArrayList<User>();
 14         while (!data.equals("end")) {
 15             if (f.isFromat()) {
 16                 if (f.getType() == 'u')
 17                     t.setUser(f, user);
 18                 else
 19                     t.setInfo(f, user);
 20             }
 21             data = input.nextLine();
 22             f = new Format(data);
 23         }
 24         user = t.OrderUser(user);
 25         for (int i = 0; i < user.size(); i++) {
 26             System.out.print(user.get(i).getNumber()+" ");
 27             System.out.print(String.format("%.1f", user.get(i).calCost()));
 28             //t.FormatOut(user.get(i).calCost());
 29             System.out.print(" ");
 30         //    t.FormatOut(user.get(i).calBalance());
 31             System.out.print(String.format("%.1f", user.get(i).calBalance()));
 32             System.out.print("\n");
 33         }
 34         input.close();
 35     }
 36 
 37 }
 38 abstract class  CallChargeRule extends ChargeRules{
 39     public abstract double calCost(ArrayList<CallRecord> callRecords);
 40 }
 41 class CallRecord extends CommunicationRecord {
 42     private Date startTime;
 43     private Date endTime;
 44     private String callingAddressAreaCode;
 45     private String answerAddressAreaCode;
 46     public Date getStartTime() {
 47         return startTime;
 48     }
 49 
 50     public void setStartTime(Date startTime) {
 51         this.startTime = startTime;
 52     }
 53 
 54     public Date getendTime() {
 55         return endTime;
 56     }
 57 
 58     public void setendTime(Date endTime) {
 59         this.endTime = endTime;
 60     }
 61 
 62     public String getCallingAddressAreaCode() {
 63         return callingAddressAreaCode;
 64     }
 65 
 66     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
 67         this.callingAddressAreaCode = callingAddressAreaCode;
 68     }
 69 
 70     public String getAnswerAddressAreaCode() {
 71         return answerAddressAreaCode;
 72     }
 73 
 74     public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
 75         this.answerAddressAreaCode = answerAddressAreaCode;
 76     }
 77 
 78 }
 79 abstract class ChargeMode {
 80     protected ArrayList<CallChargeRule> chargeRules = new ArrayList<>();
 81 
 82     
 83     public abstract double calCost(UserRecords userRecords);
 84     public abstract double getMonthlyRent();
 85 }
 86 abstract class ChargeRules {
 87 
 88 }
 89 abstract class CommunicationRecord {
 90     protected String callingNumber;
 91     protected String answerNumber;
 92     public String getCallingNumber() {
 93         return callingNumber;
 94     }
 95     public void setCallingNumber(String callingNumber) {
 96         this.callingNumber = callingNumber;
 97     }
 98     public String getAnswerNumber() {
 99         return answerNumber;
100     }
101     public void setAnswerNumber(String answerNumber) {
102         this.answerNumber = answerNumber;
103     }
104 }
105 class Format {
106     String s;
107     SimpleDateFormat Format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
108 
109     Format(String s) {
110         this.s = s;
111     }
112 
113     public String getInfo(int n) {
114         return s.substring(2).split(" ")[n];
115 
116     }
117 
118     public String getUserNumber() {
119         return s.substring(2).split(" ")[0];
120 
121     }
122 
123     public String getUserMode() {
124         return s.substring(2).split(" ")[1];
125 
126     }
127 
128     public Date getstartTime(int n) {
129         Date startTime = null;
130         String detail[];
131         detail = s.substring(n).split(" ");
132         String StartTime = detail[n].concat(" " + detail[n + 1]);
133         try {
134             startTime = Format.parse(StartTime);
135         } catch (ParseException e) {
136 
137             e.printStackTrace();
138         }
139         return startTime;
140     }
141 
142     public Date getendTime(int n) {
143         Date endTime = null;
144         String detail[];
145         detail = s.substring(2).split(" ");
146         String EndTime = detail[n + 2].concat(" " + detail[n + 3]);
147         try {
148             endTime = Format.parse(EndTime);
149         } catch (ParseException e) {
150 
151             e.printStackTrace();
152         }
153         return endTime;
154 
155     }
156 
157     public char getType() {
158         return s.charAt(0);
159     }
160 
161     public boolean isFromat() {
162         if(s.equals(""))
163             return false;
164         char type = s.charAt(0);
165         if (type == 'u') {
166             return AccountFormat();
167         } else if (type == 't') {
168             return InfoFormat();
169         } else
170             return false;
171     }
172 
173     private boolean InfoFormat() {
174         String tPattern = "t-0\\d{9,11}\\s" + "0\\d{9,11}\\s"
175                 + "([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3}\\.(1[0-2]|[1-9])\\.([1-9]|(1|2)[0-9]|(30|31)) ([0|1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9] ?){2}";
176         String tPattern1 = "t-\\d{11}\\s\\d{3,4}\\s" + "\\d{11}\\s\\d{3,4}\\s"
177                 + "([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3}\\.(1[0-2]|[1-9])\\.([1-9]|(1|2)[0-9]|(30|31)) ([0|1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9] ?){2}";
178         String tPattern2 = "t-\\d{11}\\s\\d{3,4}\\s" + "\\d{10,12}\\s"
179                 + "([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3}\\.(1[0-2]|[1-9])\\.([1-9]|(1|2)[0-9]|(30|31)) ([0|1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9] ?){2}";
180         String tPattern3 = "t-\\d{10,12}\\s" + "1\\d{10}\\s\\d{3,4}\\s"
181                 + "([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3}\\.(1[0-2]|[1-9])\\.([1-9]|(1|2)[0-9]|(30|31)) ([0|1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9] ?){2}";
182         if (s.matches(tPattern) || s.matches(tPattern1) || s.matches(tPattern2) || s.matches(tPattern3))
183             return true;
184         else
185             return false;
186     }
187 
188     private boolean AccountFormat() {
189         String uPattern = "u-\\d{10,12}\\s[0-2]";
190         String uPattern1 = "u-\\d{11}\\s[0-2]";
191         if (s.matches(uPattern) )
192             return true;
193         else
194             return false;
195 
196     }
197 
198 
199 }
200 class LandlinePhoneCharging extends ChargeMode{
201     private double monthlyRent=20;
202     public LandlinePhoneCharging() {
203         super();
204         chargeRules.add(new LandPhoneInCityRule());
205         chargeRules.add(new LandPhoneInProvinceRule());
206         chargeRules.add(new LandPhoneInLandRule());
207     }
208     @Override
209     public double calCost(UserRecords userRecords) {
210         double sum=0;
211         for(CallChargeRule e:this.chargeRules) {
212             if(e instanceof LandPhoneInCityRule)
213                 sum+=e.calCost(userRecords.getCallingInCityRecords());
214             else if(e instanceof LandPhoneInProvinceRule)
215                 sum+=e.calCost(userRecords.getCallingInProvinceRecords());
216             else
217                 sum+=e.calCost(userRecords.getCallingInLandRecords());
218         }
219         return sum;
220     }
221 
222     @Override
223     public double getMonthlyRent() {
224         // TODO 自动生成的方法存根
225         return monthlyRent;
226     }
227 
228     public void setMonthlyRent(double monthlyRent) {
229         this.monthlyRent = monthlyRent;
230     }
231 
232 }
233 class LandPhoneInCityRule extends CallChargeRule{
234     @Override
235     public double calCost(ArrayList<CallRecord> callRecords) {
236         double sum=0;
237         for(int i=0;i<callRecords.size();i++) {
238             Date startTime=callRecords.get(i).getStartTime();
239             Date endTime=callRecords.get(i).getendTime();
240             Long interval = (endTime.getTime() - startTime.getTime())/1000;
241             if(interval%60!=0)
242                 interval=(interval/60)+1;
243             else
244                 interval=interval/60;
245             if(callRecords.get(i).getAnswerAddressAreaCode().matches("0791"))
246                 sum=sum+interval*0.1;
247             else if(callRecords.get(i).getAnswerAddressAreaCode().matches("079\\d||0701"))
248                 sum=sum+interval*0.3;
249             else
250                 sum=sum+interval*0.6;
251         }
252         return sum;
253     }
254 }
255 class LandPhoneInLandRule extends CallChargeRule{
256     @Override
257     public double calCost(ArrayList<CallRecord> callRecords) {
258         double sum=0;
259         for(int i=0;i<callRecords.size();i++) {
260             Date startTime=callRecords.get(i).getStartTime();
261             Date endTime=callRecords.get(i).getendTime();
262             Long interval = (endTime.getTime() - startTime.getTime())/1000;
263             if(interval%60!=0)
264                 interval=(interval/60)+1;
265             else
266                 interval=interval/60;
267             sum=sum+interval*0.6;
268         }
269         return sum;
270     }
271 
272 }
273 class LandPhoneInProvinceRule extends CallChargeRule{
274     long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
275     long nh = 1000 * 60 * 60;// 一小时的毫秒数
276     long nm = 1000 * 60;// 一分钟的毫秒数
277     long ns = 1000;// 一秒钟的毫秒数
278     @Override
279     public double calCost(ArrayList<CallRecord> callRecords) {
280         double sum=0;
281         for(int i=0;i<callRecords.size();i++) {
282             Date startTime=callRecords.get(i).getStartTime();
283             Date endTime=callRecords.get(i).getendTime();
284             Long interval = (endTime.getTime() - startTime.getTime())/1000;
285             if(interval%60!=0)
286                 interval=(interval/60)+1;
287             else
288                 interval=interval/60;
289             sum=sum+interval*0.3;
290         }
291         return sum;
292     }
293 
294 }
295 class MessageRecord {
296     private String message;
297 
298     public String getMessage() {
299         return message;
300     }
301 
302     public void setMessage(String message) {
303         this.message = message;
304     }
305     
306 }
307 class MobilePhoneAnswer extends CallChargeRule{
308     
309     @Override
310     public double calCost(ArrayList<CallRecord> answerRecords) {
311         double sum=0;
312         for(int i=0;i<answerRecords.size();i++) {
313             Date startTime=answerRecords.get(i).getStartTime();
314             Date endTime=answerRecords.get(i).getendTime();
315             Long interval = (endTime.getTime() - startTime.getTime())/1000;
316             if(interval%60!=0)
317                 interval=(interval/60)+1;
318             else
319                 interval=interval/60;
320             sum=sum+interval*0.3;
321         }
322         return sum;
323     }
324 
325 }
326 class MobilePhoneCharging extends ChargeMode{
327     private double monthlyRent=15;
328     public MobilePhoneCharging() {
329         super();
330         chargeRules.add(new MobilePhoneAnswer ());
331         chargeRules.add(new MobilePhoneInCity ());
332         chargeRules.add(new MobilePhoneInLand ());
333         chargeRules.add(new MobilePhoneInProvince ());
334     }
335 
336     @Override
337     public double calCost(UserRecords userRecords) {
338         double sum=0;
339         for(CallChargeRule e:this.chargeRules) {
340             if(e instanceof MobilePhoneAnswer)
341                 sum+=e.calCost(userRecords.getAnswerInLandRecords());
342             else if(e instanceof MobilePhoneInCity)
343                 sum+=e.calCost(userRecords.getCallingInCityRecords());
344             else if(e instanceof MobilePhoneInLand)
345                 sum+=e.calCost(userRecords.getCallingInLandRecords());
346             else
347                 sum+=e.calCost(userRecords.getCallingInProvinceRecords());
348         }
349         return sum;
350     }
351 
352     @Override
353     public double getMonthlyRent() {
354         // TODO 自动生成的方法存根
355         return monthlyRent;
356     }
357 
358     public void setMonthlyRent(double monthlyRent) {
359         this.monthlyRent = monthlyRent;
360     }
361 
362 }
363 class MobilePhoneInCity extends CallChargeRule{
364 
365     @Override
366     public double calCost(ArrayList<CallRecord> callRecords) {
367         double sum=0;
368         for(int i=0;i<callRecords.size();i++) {
369             Date startTime=callRecords.get(i).getStartTime();
370             Date endTime=callRecords.get(i).getendTime();
371             Long interval = (endTime.getTime() - startTime.getTime())/1000;
372             if(interval%60!=0)
373                 interval=(interval/60)+1;
374             else
375                 interval=interval/60;
376             if(callRecords.get(i).getAnswerAddressAreaCode().matches("0791"))
377                 sum=sum+interval*0.1;
378             else if(callRecords.get(i).getAnswerAddressAreaCode().matches("079\\d||0701"))
379                 sum=sum+interval*0.2;
380             else
381                 sum=sum+interval*0.3;
382         }
383         return sum;
384     }
385 
386 }
387 class MobilePhoneInLand extends CallChargeRule{
388 
389     @Override
390     public double calCost(ArrayList<CallRecord> callRecords) {
391         double sum=0;
392         for(int i=0;i<callRecords.size();i++) {
393             Date startTime=callRecords.get(i).getStartTime();
394             Date endTime=callRecords.get(i).getendTime();
395             Long interval = (endTime.getTime() - startTime.getTime())/1000;
396             if(interval%60!=0)
397                 interval=(interval/60)+1;
398             else
399                 interval=interval/60;
400             sum=sum+interval*0.6;
401         }
402         return sum;
403     }
404     
405 
406 }
407 class MobilePhoneInProvince extends CallChargeRule{
408 
409     @Override
410     public double calCost(ArrayList<CallRecord> callRecords) {
411         double sum=0;
412         for(int i=0;i<callRecords.size();i++) {
413             Date startTime=callRecords.get(i).getStartTime();
414             Date endTime=callRecords.get(i).getendTime();
415             Long interval = (endTime.getTime() - startTime.getTime())/1000;
416             if(interval%60!=0)
417                 interval=(interval/60)+1;
418             else
419                 interval=interval/60;
420             sum=sum+interval*0.3;
421         }
422         return sum;
423     }
424 
425 }
426 class Tools {
427     public void setInfo(Format f, ArrayList<User> user) {
428         int call;
429         call = this.isAccounted(f.getInfo(0), user);
430         CallRecord record = new CallRecord();
431         if(f.getInfo(1).length()==4||f.getInfo(1).length()==3) {
432             record.setCallingNumber(f.getInfo(0));
433             record.setCallingAddressAreaCode(f.getInfo(1));
434             record.setAnswerNumber(f.getInfo(2));
435             if(f.getInfo(3).length()==4||f.getInfo(3).length()==3) {
436                 record.setAnswerAddressAreaCode(f.getInfo(3));
437                 record.setStartTime(f.getstartTime(4));
438                 record.setendTime(f.getendTime(4));
439                 if (!record.getAnswerAddressAreaCode().matches("079\\d||0701")) {
440                     int AnswerCall = this.isAccounted(record.getAnswerNumber(), user);
441                     if (AnswerCall != -1) {
442                         user.get(AnswerCall).setUserRecords(record,1);
443                     }
444                 }
445             }else {
446                 record.setAnswerAddressAreaCode(getAreaCode(f.getInfo(2)));
447                 record.setStartTime(f.getstartTime(3));
448                 record.setendTime(f.getendTime(3));
449             }
450         }else {
451             record.setCallingNumber(f.getInfo(0));
452             record.setCallingAddressAreaCode(getAreaCode(f.getInfo(0)));
453             record.setAnswerNumber(f.getInfo(1));
454             if(f.getInfo(2).length()==4||f.getInfo(2).length()==3) {
455                 record.setAnswerAddressAreaCode(f.getInfo(2));
456                 record.setStartTime(f.getstartTime(3));
457                 record.setendTime(f.getendTime(3));
458                 if (!record.getAnswerAddressAreaCode().matches("079\\d||0701")) {
459                     int AnswerCall = this.isAccounted(record.getAnswerNumber(), user);
460                     if (AnswerCall != -1) {
461                         user.get(AnswerCall).setUserRecords(record,1);
462                     }
463                 }
464             }else {
465                 record.setAnswerAddressAreaCode(getAreaCode(f.getInfo(1)));
466                 record.setStartTime(f.getstartTime(2));
467                 record.setendTime(f.getendTime(2));
468             }
469         }
470         if (call != -1)
471             user.get(call).setUserRecords(record,0);
472     }
473 
474 
475     public void setUser(Format t, ArrayList<User> user) {
476         User u = new User();
477         if (isAccounted(t.getUserNumber(), user) == -1) {
478             u.setNumber(t.getUserNumber());
479             if (t.getUserMode().matches("0"))
480                 u.setChargeMode(new LandlinePhoneCharging());
481             if (t.getUserMode().matches("1"))
482                 u.setChargeMode(new MobilePhoneCharging());
483             user.add(u);
484         }
485     }
486 
487     public void setUserChargeMode(Format t, ArrayList<User> user) {
488         User u = new User();
489         u.setNumber(t.getUserNumber());
490         user.add(u);
491     }
492 
493     public int isAccounted(String num, ArrayList<User> user) {
494         for (int i = 0; i < user.size(); i++)
495             if (user.get(i).getNumber().equals(num))
496                 return i;
497         return -1;
498     }
499 
500     public void FormatOut(double x) {
501         if ((x * 1e1) % 10 != 0)
502             System.out.printf("%.1f", x);
503         else
504             System.out.print(x);
505     }
506 
507     public ArrayList<User> OrderUser(ArrayList<User> user) {
508         ArrayList<User> u = new ArrayList<User>();
509         int index = 0;
510         while (user.size() != 0) {
511             {
512                 index = 0;
513                 for (int j = 0; j < user.size(); j++) {
514                     if (user.get(j).getNumber().compareTo(user.get(index).getNumber()) < 0)
515                         index = j;
516                 }
517                 u.add(user.get(index));
518                 user.remove(index);
519             }
520         }
521         return u;
522     }
523 
524     public String getAreaCode(String s) {
525         return s.substring(0, 4);
526     }
527 
528     public int getMode(String s, ArrayList<User> user) {
529         int userNumber = this.isAccounted(s, user);
530         if (userNumber != -1) {
531             if (user.get(userNumber).getChargeMode() instanceof MobilePhoneCharging)
532                 return 1;
533             else
534                 return 0;
535         } else
536             return -1;
537     }
538 
539 }
540 class User {
541     private UserRecords userRecords = new UserRecords();
542     private double balance = 100;
543     private ChargeMode chargeMode;
544     private String number;
545 
546     public double calBalance() {
547         return balance - this.calCost() - this.chargeMode.getMonthlyRent();
548     }
549 
550     public double calCost() {
551         return this.chargeMode.calCost(userRecords);
552 
553     }
554 
555     public UserRecords getUserRecords() {
556         return userRecords;
557     }
558 
559     public void setUserRecords(CallRecord record,int type) {
560         if (type==0) {
561             if (record.getCallingAddressAreaCode().equals("0791"))
562                 this.userRecords.addCallingInCityRecords(record);
563             else if (record.getCallingAddressAreaCode().matches("079\\d||0701"))
564                 this.userRecords.addCallingInProvinceRecords(record);
565             else
566                 this.userRecords.addCallingInLandRecords(record);
567         } else {
568             this.userRecords.addAnswerInLandRecords(record);
569         }
570     }
571 
572     public double getBalance() {
573         return balance;
574     }
575 
576     public ChargeMode getChargeMode() {
577         return chargeMode;
578     }
579 
580     public void setChargeMode(ChargeMode chargeMode) {
581         this.chargeMode = chargeMode;
582     }
583 
584     public String getNumber() {
585         return number;
586     }
587 
588     public void setNumber(String number) {
589         this.number = number;
590     }
591 }
592 class UserRecords {
593     private ArrayList<CallRecord> callingInCityRecords =new  ArrayList<CallRecord>();
594     private ArrayList<CallRecord> callingInProvinceRecords =new  ArrayList<CallRecord>();
595     private ArrayList<CallRecord> callingInLandRecords =new  ArrayList<CallRecord>();
596     private ArrayList<CallRecord> answerInCityRecords =new  ArrayList<CallRecord>();
597     private ArrayList<CallRecord> answerInProvinceRecords =new  ArrayList<CallRecord>();
598     private ArrayList<CallRecord> answerInLandRecords =new  ArrayList<CallRecord>();
599     private ArrayList<MessageRecord> sendMessageRecords =new  ArrayList<MessageRecord>();
600     private ArrayList<MessageRecord> receiveMessageRecords =new ArrayList<MessageRecord>();
601 
602     public ArrayList<CallRecord> getCallingInCityRecords() {
603         return callingInCityRecords;
604     }
605 
606     public void addCallingInCityRecords(CallRecord callingInCityRecords) {
607         this.callingInCityRecords.add(callingInCityRecords);
608     }
609 
610     public ArrayList<CallRecord> getAnswerInCityRecords() {
611         return answerInCityRecords;
612     }
613 
614     public void addAnswerInCityRecords(CallRecord answerInCityRecords) {
615         this.answerInCityRecords.add(answerInCityRecords);
616     }
617 
618     public ArrayList<CallRecord> getCallingInProvinceRecords() {
619         return callingInProvinceRecords;
620     }
621 
622     public void addCallingInProvinceRecords(CallRecord callingInProvinceRecords) {
623         this.callingInProvinceRecords.add(callingInProvinceRecords);
624     }
625 
626     public ArrayList<CallRecord> getCallingInLandRecords() {
627         return callingInLandRecords;
628     }
629 
630     public void addCallingInLandRecords(CallRecord callingInLandRecords) {
631         this.callingInLandRecords.add(callingInLandRecords);
632     }
633 
634     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
635         return answerInProvinceRecords;
636     }
637 
638     public void addAnswerInProvinceRecords(CallRecord answerInProvinceRecords) {
639         this.answerInProvinceRecords.add(answerInProvinceRecords);
640     }
641 
642     public ArrayList<CallRecord> getAnswerInLandRecords() {
643         return answerInLandRecords;
644     }
645 
646     public void addAnswerInLandRecords(CallRecord answerInLandRecords) {
647         this.answerInLandRecords.add(answerInLandRecords);
648     }
649 
650     public ArrayList<MessageRecord> getSendMessageRecords() {
651         return sendMessageRecords;
652     }
653 
654     public void addSendMessageRecords(MessageRecord sendMessageRecords) {
655         this.sendMessageRecords.add(sendMessageRecords);
656     }
657 
658     public ArrayList<MessageRecord> getReceiveMessageRecords() {
659         return receiveMessageRecords;
660     }
661 
662     public void addReceiveMessageRecords(MessageRecord receiveMessageRecords) {
663         this.receiveMessageRecords.add(receiveMessageRecords);
664     }
665     
666 }
View Code

 

 

 

 在刚开始看到题目仅仅是添加了手机计费规则以为会很简单,直到真正开始实现代码时才发现需要修改的地方变多了,比如接受和处理数据的方式与上一题有了较大的差别。由于处理数据的方式变得更加复杂,在本次作业中出现了函数复杂度超出了合理范围的情况。还有改进空间。

题目三:

实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
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 import java.util.ArrayList;
  2 import java.text.ParseException;
  3 import java.text.SimpleDateFormat;
  4 import java.util.Date;
  5 import java.util.Scanner;
  6 public class Main {
  7     public static void main(String[] arges) {
  8         Scanner input = new Scanner(System.in);
  9         String data = input.nextLine();
 10         Format f = new Format(data);
 11         Tools t = new Tools();
 12         ArrayList<User> user = new ArrayList<User>();
 13         while (!data.equals("end")) {
 14             if (f.isFromat()) {
 15                 if (f.getType() == 'u')
 16                     t.setUser(f, user);
 17                 else
 18                     t.setInfo(f, user);
 19             }
 20             data = input.nextLine();
 21             f = new Format(data);
 22         }
 23         user = t.OrderUser(user);
 24         for (int i = 0; i < user.size(); i++) {
 25             System.out.print(user.get(i).getNumber()+" ");
 26             System.out.print(String.format("%.1f", user.get(i).calCost()));
 27             System.out.print(" ");
 28             System.out.print(String.format("%.1f", user.get(i).calBalance()));
 29             System.out.print("\n");
 30         }
 31         input.close();
 32     }
 33 
 34 }
 35 abstract class ChargeMode {
 36     protected ArrayList<MessageChargeRule> chargeRules = new ArrayList<>();
 37 
 38     
 39     public abstract double calCost(UserRecords MessageChargeRule);
 40     public abstract double getMonthlyRent();
 41 }
 42 abstract class ChargeRules {
 43 
 44 }
 45 abstract class CommunicationRecord {
 46     protected String callingNumber;
 47     protected String answerNumber;
 48     public String getCallingNumber() {
 49         return callingNumber;
 50     }
 51     public void setCallingNumber(String callingNumber) {
 52         this.callingNumber = callingNumber;
 53     }
 54     public String getAnswerNumber() {
 55         return answerNumber;
 56     }
 57     public void setAnswerNumber(String answerNumber) {
 58         this.answerNumber = answerNumber;
 59     }
 60 }
 61 class Format {
 62     String s;
 63     SimpleDateFormat Format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
 64 
 65     Format(String s) {
 66         this.s = s;
 67     }
 68 
 69     public String getInfo(int n) {
 70         return s.substring(2).split(" ")[n];
 71 
 72     }
 73 
 74     public String getUserNumber() {
 75         return s.substring(2).split(" ")[0];
 76 
 77     }
 78 
 79     public String getUserMode() {
 80         return s.substring(2).split(" ")[1];
 81 
 82     }
 83         public String getCallingNumber() {
 84         // TODO Auto-generated method stub
 85         return s.substring(2, 13);
 86     }
 87 
 88     public String getAnswerNumber() {
 89         // TODO Auto-generated method stub
 90         return s.substring(14, 25);
 91     }
 92 
 93     public String getMessage() {
 94         // TODO Auto-generated method stub
 95         return s.substring(26);
 96     }
 97 
 98     public Date getstartTime(int n) {
 99         Date startTime = null;
100         String detail[];
101         detail = s.substring(n).split(" ");
102         String StartTime = detail[n].concat(" " + detail[n + 1]);
103         try {
104             startTime = Format.parse(StartTime);
105         } catch (ParseException e) {
106 
107             e.printStackTrace();
108         }
109         return startTime;
110     }
111 
112     public Date getendTime(int n) {
113         Date endTime = null;
114         String detail[];
115         detail = s.substring(2).split(" ");
116         String EndTime = detail[n + 2].concat(" " + detail[n + 3]);
117         try {
118             endTime = Format.parse(EndTime);
119         } catch (ParseException e) {
120 
121             e.printStackTrace();
122         }
123         return endTime;
124 
125     }
126 
127     public char getType() {
128         return s.charAt(0);
129     }
130 
131     public boolean isFromat() {
132         if(s.equals(""))
133             return false;
134         char type = s.charAt(0);
135         if (type == 'u') {
136             return AccountFormat();
137         } else if (type == 'm') {
138             return InfoFormat();
139         } else
140             return false;
141     }
142 
143 private boolean InfoFormat() {
144         String tPattern = "m-1\\d{10}\\s" + "1\\d{10}\\s"
145                 + ".*";
146     if(s.matches(tPattern)){
147         String s1=getMessage();
148         for(int i=0;i<s1.length();i++) {
149             if(!s1.substring(i, i+1).matches("[0-9]|[a-z]|[A-Z]|\\s|\\,|\\."))
150                 return false;
151         }
152         return true;
153     }
154     else
155         return false;
156     }
157 
158     private boolean AccountFormat() {
159         String uPattern = "u-1\\d{10}\\s3";
160         return s.matches(uPattern);
161        // return true;
162     }
163 
164 }
165 abstract  class MessageChargeRule extends ChargeRules{
166     abstract public double calCost(UserRecords userRecords) ;
167 }
168 class MessageCharging extends ChargeMode{
169     public MessageCharging() {
170         super();
171         chargeRules.add(new SendMessageRule ());
172     }
173     @Override
174     public double calCost(UserRecords userRecords) {
175         return this.chargeRules.get(0).calCost(userRecords);
176     }
177 
178     @Override
179     public double getMonthlyRent() {
180         // TODO Auto-generated method stub
181         return 0;
182     }
183 
184 }
185 class MessageRecord extends CommunicationRecord{
186     private String message;
187 
188     public String getMessage() {
189         return message;
190     }
191 
192     public void setMessage(String message) {
193         this.message = message;
194     }
195     
196 }
197 class SendMessageRule extends MessageChargeRule{
198 
199     @Override
200     public double calCost(UserRecords userRecords) {
201         double sum=0;
202         int num=0;
203         for(int i=0;i<userRecords.getSendMessageRecords().size();i++) {
204             if(userRecords.getSendMessageRecords().get(i).getMessage().length()<=10)
205                 num++;
206             else {
207                 if(userRecords.getSendMessageRecords().get(i).getMessage().length()%10==0) {
208                     num+=userRecords.getSendMessageRecords().get(i).getMessage().length()/10;
209                 }
210                 else
211                 {
212                     num+=userRecords.getSendMessageRecords().get(i).getMessage().length()/10+1;
213                 }
214             }
215         }
216         if(num>0&&num<=3) {
217             sum=num*0.1;
218         }else if(num>3&&num<=5) {
219             sum=0.3+(num-3)*0.2;
220         }else if(num>5){
221             sum=0.7+(num-5)*0.3;
222         }
223         return sum;
224     }
225 
226     
227 }
228 class Tools {
229     public void setInfo(Format f, ArrayList<User> user) {
230         int call;
231         call = this.isAccounted(f.getInfo(0), user);
232         MessageRecord record = new MessageRecord();
233     if(call!=-1) {
234             record.setCallingNumber(f.getCallingNumber());
235             record.setAnswerNumber(f.getAnswerNumber());
236             record.setMessage(f.getMessage());
237             user.get(call).setUserRecords(record);
238         }
239     }
240 
241     public void setUser(Format t, ArrayList<User> user) {
242         User u = new User();
243         if (isAccounted(t.getUserNumber(), user) == -1) {
244             u.setNumber(t.getUserNumber());
245             u.setChargeMode(new MessageCharging());
246             user.add(u);
247         }
248     }
249 
250     public void setUserChargeMode(Format t, ArrayList<User> user) {
251         User u = new User();
252         u.setNumber(t.getUserNumber());
253         user.add(u);
254     }
255 
256     public int isAccounted(String num, ArrayList<User> user) {
257         for (int i = 0; i < user.size(); i++)
258             if (user.get(i).getNumber().equals(num))
259                 return i;
260         return -1;
261     }
262 
263     public void FormatOut(double x) {
264         if ((x * 1e1) % 10 != 0)
265             System.out.printf("%.1f", x);
266         else
267             System.out.print(x);
268     }
269 
270     public ArrayList<User> OrderUser(ArrayList<User> user) {
271         ArrayList<User> u = new ArrayList<User>();
272         int index = 0;
273         while (user.size() != 0) {
274             {
275                 index = 0;
276                 for (int j = 0; j < user.size(); j++) {
277                     if (user.get(j).getNumber().compareTo(user.get(index).getNumber()) < 0)
278                         index = j;
279                 }
280                 u.add(user.get(index));
281                 user.remove(index);
282             }
283         }
284         return u;
285     }
286 
287 
288 
289 
290 
291 }class User {
292     private UserRecords userRecords = new UserRecords();
293     private double balance = 100;
294     private ChargeMode chargeMode;
295     private String number;
296 
297     public double calBalance() {
298         return balance - this.calCost() - this.chargeMode.getMonthlyRent();
299     }
300 
301     public double calCost() {
302         return this.chargeMode.calCost(userRecords);
303 
304     }
305 
306     public UserRecords getUserRecords() {
307         return userRecords;
308     }
309 
310     public void setUserRecords(MessageRecord record) {
311         this.userRecords.addSendMessageRecords(record);
312     }
313 
314     public double getBalance() {
315         return balance;
316     }
317 
318     public ChargeMode getChargeMode() {
319         return chargeMode;
320     }
321 
322     public void setChargeMode(ChargeMode chargeMode) {
323         this.chargeMode = chargeMode;
324     }
325 
326     public String getNumber() {
327         return number;
328     }
329 
330     public void setNumber(String number) {
331         this.number = number;
332     }
333 }
334 class UserRecords {
335     private ArrayList<MessageRecord> sendMessageRecords =new  ArrayList<MessageRecord>();
336     private ArrayList<MessageRecord> receiveMessageRecords =new ArrayList<MessageRecord>();
337 
338     public ArrayList<MessageRecord> getSendMessageRecords() {
339         return sendMessageRecords;
340     }
341 
342     public void addSendMessageRecords(MessageRecord sendMessageRecords) {
343         this.sendMessageRecords.add(sendMessageRecords);
344     }
345 
346     public ArrayList<MessageRecord> getReceiveMessageRecords() {
347         return receiveMessageRecords;
348     }
349 
350     public void addReceiveMessageRecords(MessageRecord receiveMessageRecords) {
351         this.receiveMessageRecords.add(receiveMessageRecords);
352     }
353     
354 }
View Code

 

 

 

 

 此次题目仅仅是对于短信的计费规则,少了许多的判断格式条件,题目难度下降明显,不过在分析代码复杂度时发现还是存在函数复杂度过高的问题,应该与上次作业出现的问题一样,同时存在一个费用计算的复杂度过高的问题,还有改进空间。

三.踩坑心得

电信计费系列一:

  刚看到题目提供的类图时还是听震惊的,没想到这样一道简单的计费规则题目还有这么复杂的类图关系,刚开始写代码的时候看类图一直是似懂非懂,只能照着葫芦画瓢,先把类图上所有的类建好,然后挨个分析作用,这是一个很漫长又很折磨的过程,我们需要把自己的思路完全放在这个类图之上,限制了自己的想法。最后完全读懂了类图之后实现要求很简单,问题还是出现在格式判断上,题目要求只判断时间格式,所以我很正常的去网上搜索到了可以使用parse方法将输入的时间与正确时间的格式进行比对,匹配错误就抛出异常,看似是一个很完美的方法,但是写道最后也会有几个测试点一直过不去,在询问了同学后放弃了使用抛出异常的方法,还是使用了最朴实无华的正则表达式方法,即使正则表达式没有判断座机区号,年份格式,闰年依然成功全通测试点,这也为我第二次的电信计费修改代码埋下了伏笔。

电信计费系列二:

  系列二虽然添加了手机计费,但是还是存在着座机通话,我就试着把第一次的代码放上去提交,结果全是非零返回,这时的我还没有意识到问题的严重性,没办法只能开始修改代码处理数据,对于怎样判断是手机号还是座机号,最好的方法还是通过这一条数据之后的数据长度是不是4,如果是4那么这一条就是手机号,否则就是座机,我就是通过这个方法成功提交获得了不少的分数,但就是有点过不去,不用多想 ,就是格式判断的问题,我回过头来看正则表达式,但是怎么看都没问题,当时就想会不会是自己没有判断闰年导致的错误,我又花了好长一段时间把年份是闰年的判断了,加了个2月份是29天 的情况,结果还是答案不对,实在没有办法的我就开始对每一条正则表达开始测试,先是一个一个注释,这样还真让我找到问题在哪,原来是我年份的正则不对,话不多说,直接百度年份正则表达式怎么写,复制粘贴,多通过了一个测试点。同样另外一个格式问题,手机号必须是1开头,我没有做判断,起初原因还是题目上说的一句话,说什么手机格式 和座机格式错误不做判断,应该还是这一条要求的理解有误。

电信计费系列三:

  系列三相较于前两个系列难度下降不少,最主要的原因还是少了时间的格式判断,所以我一开始写完代码高高兴兴的提交后本以为会直接满分,结果就是一半的分数都没有,还是因为自己没有仔细看题,题目要求了短信内容格式,我没有做任何判断就进行了计算,不过到最后我也没有找到一个很好的方法来判断短信的格式,我是先判断了短信内容是字符,然后判断具体内容比如大小写字母,数字等等,希望有会更好方法的大佬教教我。获取短信内容也是一个坑。最好不要先把输入的数据按空格分割,因为短信的内容也会有空格,最好的是从固定的位置往后切,这样一定会得到完整的短信内容。计算短信费用也是一个坑,题目上说了超过三条计费会有变化,如果没有对样例进行计算的话,很容易就把超过 3条的情况直接按一个费用计算,其实题目真正要求是超出3条的部分用一种计费方式,没超过的用另外一种。

四.改进建议

  系列一二里面都是存在一些函数的复杂度较高,还可以进一步的修改提高代码的可读性。在系列一中对于一些类的理解有误,比如landlinephoneincity应该是打电话在市内的记录,但是我把他当成了接电话的,好在第一题的复杂度不高,理解错误还是可以通过测试点,在系列二就没那么好运了我只好重新写了系列一的一些代码。

五.总结

  这几周主要学习内容转变了方向,老师上课开始讲起了代码规范性,以及结构的设计等,听的是云里雾里,不过在后半部分讲的Javafx还是很有用,这也是我从开始写代码第一次接触到图形化编程,虽然Javafx使用的人并不多,但是我还是很认真的学习了不少功能,并且打算在接下来的实验中将自己写的农夫过河改编为图形化界面,让他变为一个真正的游戏。

标签:return,String,ArrayList,PTA,oop,new,public,2022.12,user
From: https://www.cnblogs.com/okdexiu/p/16950001.html

相关文章

  • 【日总结】2022.12.5
    学了一周whk,滚回来OI了。今天啥都没干,颓了一天。[ARC152E]XorAnnihilation感觉很强。题目看起来很复杂,所以我们要想办法转换题意。注意到所有的值异或和为\(0\),......
  • Pta6-8次题目集总结
    前言对于这三次大作业,主要的难题就是电信计费系列的题目,以及接口的使用还有迭代器的基本使用,最后一次大作业还复习了之前的多态的内容。总体来说这三次大作业难度不大,题量......
  • Hadoop和Hive的关系
    Hadoop和Hive的关系1.Hadoop是一个能够对大量数据进行分布式处理的软件框架。Hadoop最核心的设计就是hdfs和mapreduce,hdfs提供存储,mapreduce用于计算。2.Hive是Hadoop的延......
  • hadoop3.x集群搭建教程
    0.Hadoop和Java之间的版本配套官方描述:https://cwiki.apache.org/confluence/display/HADOOP2/HadoopJavaVersionshadoop3.x版本仅支持Java8hadoop2.7.x及以上版本支持J......
  • Hadoop掀起大数据革命 三巨头齐发力
    开源的数据处理平台凭借其低成本、高扩展性和灵活性的优势已经赢得了多数网络巨头的认可。现在Hadoop将进入更多企业。IBM将在明年推出内置NoSQL技术的DB2旗舰级数据库管理......
  • 论文解读(CDTrans)《CDTrans: Cross-domain Transformer for Unsupervised Domain Adapt
    论文信息论文标题:CDTrans:Cross-domainTransformerforUnsupervisedDomainAdaptation论文作者:TongkunXu,WeihuaChen,PichaoWang,FanWang,HaoLi,RongJin......
  • Hadoop是什么
    最近在网上看技术文章的时候不经意间看到了Hadoop,通过这篇文章介绍一下HadoopHadoop主要由HDFS、MapReduce和Hbase组成。它是一个分布式系统基础架构,由Apache基金会开发。......
  • 微软宣布全面拥抱Hadoop
    继SQLServer后,微软终于全面加入了Hadoop阵营!在10月12日的西雅图举行的​​SQLPASS2011峰会​​上,微软宣布将于从雅虎分拆出来的Hortonworks合作开发,在ApacheHadoop上实......
  • nchu-software-oop-2022-6
    7-1电信计费系列1-座机计费分数80  作者蔡轲  单位南昌航空大学实现一个简单的电信计费程序:假设南昌市电信分公司针对市内座机用户采用的计费方式:月租20......
  • nchu-software-oop-2022-8
    7-1电信计费系列3-短信计费分数50  作者蔡轲  单位南昌航空大学实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:1、接收短信免费,发送短信0.1......