一、前言:

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

 

 

二、设计与分析:

 

第一道:

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

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

输入格式:

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

输出格式:

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

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

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

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

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

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

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

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

 

                                        图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。

LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是
座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。    
(提示:可以从UserRecords类中获取各种类型的callRecords)。

后续扩展说明:
后续题目集将增加手机用户,手机用户的计费方式中除了与座机计费类似的主叫通话费之外,还包含市外接听电话的漫游费以及发短信的费用。在本题的设计时可统一考虑。
通话记录中,手机需要额外记录拨打/接听的地点的区号,比如:
座机打手机:t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
短信的格式:m-主叫号码,接收号码,短信内容
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you

 

类图题目已给就累述;

 

SourceMonitor报表如下:

 

 

 

代码如下:

  1 import java.text.DecimalFormat;
  2 import java.text.ParseException;
  3 import java.text.SimpleDateFormat;
  4 import java.util.ArrayList;
  5 import java.util.Date;
  6 import java.util.Scanner;
  7 import java.util.*;
  8 
  9 public class Main {
 10     public static void main(String[] args) throws ParseException {
 11         Scanner in = new Scanner(System.in);
 12         ArrayList<User> users = new ArrayList<>();
 13         Map <String, User> i = new HashMap<>();
 14         SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
 15         Date date1,date2;
 16         String str;
 17         str = in.nextLine();
 18 
 19         while (!str.equals("end")){
 20             if (str.matches("u-\\d{11,12}\\s0")){//开户
 21                 String[] a = str.split("-|\\s");
 22                 User user = new User(a[2],a[1]);
 23                 users.add(user);
 24                 i.put(a[1],user);
 25             }else if (str.matches("t-\\d{11,12}\\s\\d{10,12}(\\s\\d{4}[.][^0]\\d?[.]\\d{1,2}\\s([01][0-9]|20|21|22|23):[0-5][0-9]:[0-5][0-9]){2}")) {//正则判断
 26                 String[] a = str.split("-|\\s");
 27                 if (isDate(a[3]) && isDate(a[5])) {
 28 
 29                     date1 = sdf.parse(a[3] + " " + a[4]);
 30                     date2 = sdf.parse(a[5] + " " + a[6]);
 31                     for (User u : i.values()) {//遍历已开户的用户寻找拨打电话的用户
 32                         if (u.getNumber().equals(a[1])) {
 33                             CallRecord callRecord = new CallRecord();
 34                             callRecord.setStartTime(date1);
 35                             callRecord.setEndTime(date2);
 36                             if (a[2].substring(0, 4).equals("0791"))
 37                                 u.getUserRecords().addCallingInCityRecords(callRecord);
 38                             else if (a[2].substring(0, 3).equals("079") || a[2].substring(0, 4).equals("0701")) {
 39                                 u.getUserRecords().addCallingInProvinceRecords(callRecord);
 40                             } else u.getUserRecords().addCallingInLandRecords(callRecord);
 41                         }
 42                     }
 43                 }
 44             }
 45             str = in.nextLine();
 46         }
 47 
 48         for (User u : i.values()){
 49             System.out.println(u.getNumber() +" "+ new DecimalFormat("0.0##").format(u.calCost()) + " "+ new DecimalFormat("0.0##").format(u.calBalance()));
 50         }
 51     }
 52     public static boolean isDate(String s){
 53         String[] a = s.split("[.]");
 54         int year = 0,month = 0,day = 0;
 55         year = Integer.parseInt(a[0]);
 56         month = Integer.parseInt(a[1]);
 57         day = Integer.parseInt(a[2]);
 58         if((!isLeapYear(year)&&month==2&&day>29)||month>12||month<1||day>31||day<1||(month==2&&day>28)||(month==4&&day>30)||(month==6&&day>30)||(month==9&&day>30)||(month==11&&day>30))
 59             return false;
 60         else
 61             return true;
 62     }
 63     public static boolean isLeapYear(int year) {
 64         if((year%4==0&&year%100!=0)||year%400==0) return true;
 65         else return false;
 66     }
 67 
 68 }
 69 
 70 abstract  class CallChargeRule extends ChargeRule{
 71 
 72     public abstract double calCost(ArrayList<CallRecord> callRecords);
 73 }
 74 
 75  class CallRecord extends CommunicationRecord{
 76     private Date startTime;
 77     private Date endTime;
 78     private String callingAddressAreaCode;
 79     private String answerAddressAreaCode;
 80 
 81     public Date getStartTime() {
 82         return startTime;
 83     }
 84 
 85     public void setStartTime(Date startTime) {
 86         this.startTime = startTime;
 87     }
 88 
 89     public Date getEndTime() {
 90         return endTime;
 91     }
 92 
 93     public void setEndTime(Date endTime) {
 94         this.endTime = endTime;
 95     }
 96 
 97     public String getCallingAddressAreaCode() {
 98         return callingAddressAreaCode;
 99     }
100 
101     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
102         this.callingAddressAreaCode = callingAddressAreaCode;
103     }
104 
105     public String getAnswerAddressAreaCode() {
106         return answerAddressAreaCode;
107     }
108 
109     public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
110         this.answerAddressAreaCode = answerAddressAreaCode;
111     }
112 }
113 
114 abstract  class ChargeMode {
115     private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
116 
117     public ChargeMode() {
118         chargeRules.add(new LandPhoneInCityRule());
119         chargeRules.add(new LandPhoneInProvinceRule());
120         chargeRules.add(new LandPhoneInLandRule());
121     }
122 
123     public ArrayList<ChargeRule> getChargeRules() {
124         return chargeRules;
125     }
126 
127     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
128         this.chargeRules = chargeRules;
129     }
130 
131     public abstract double calCost(UserRecords userRecords);
132 
133     public abstract double getMonthlyRent();
134 
135 }
136 
137  abstract class ChargeRule {
138     public abstract double calCost(ArrayList<CallRecord> callRecords);
139 }
140 abstract  class CommunicationRecord {
141     protected String callingNumber;
142     protected String answerNumber;
143 
144     public String getCallingNumber() {
145         return callingNumber;
146     }
147 
148     public void setCallingNumber(String callingNumber) {
149         this.callingNumber = callingNumber;
150     }
151 
152     public String getAnswerNumber() {
153         return answerNumber;
154     }
155 
156     public void setAnswerNumber(String answerNumber) {
157         this.answerNumber = answerNumber;
158     }
159 }
160  class LandlinePhoneCharging extends ChargeMode{
161     double monthlyRent = 20;
162 
163     public LandlinePhoneCharging() {
164         super();
165     }
166 
167     @Override
168     public double calCost(UserRecords userRecords) {
169        double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords())
170                 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords())
171                 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
172         return s;
173     }
174 
175     @Override
176     public double getMonthlyRent() {
177         return monthlyRent;
178     }
179 }
180 
181  class LandPhoneInCityRule extends CallChargeRule{
182     @Override
183     public double calCost(ArrayList<CallRecord> callRecords) {
184         double s = 0;
185         for (CallRecord a : callRecords){
186            s+=(((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000));
187            if (((a.getEndTime().getTime() - a.getStartTime().getTime()) / (1000))%60>0) s++;
188         }
189 
190         return 0.1 * s;
191     }
192 }
193 
194  class LandPhoneInLandRule extends CallChargeRule{
195     @Override
196     public double calCost(ArrayList<CallRecord> callRecords) {
197         double s = 0;
198         for (CallRecord a : callRecords){
199             s+=(((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000));
200             if (((a.getEndTime().getTime() - a.getStartTime().getTime()) / (1000))%60>0) s++;
201         }
202 
203         return 0.6 * s;
204     }
205 }
206 
207  class LandPhoneInProvinceRule extends CallChargeRule{
208     @Override
209     public double calCost(ArrayList<CallRecord> callRecords) {
210         double s = 0;
211       for (CallRecord a : callRecords){
212             s+=(((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000));
213             if (((a.getEndTime().getTime() - a.getStartTime().getTime()) / (1000))%60>0) s++;
214         }
215 
216         return 0.3 * s;
217     }
218 }
219  class MessageRecord extends CommunicationRecord {
220     private String message;
221 
222     public String getMessage() {
223         return message;
224     }
225 
226     public void setMessage(String message) {
227         this.message = message;
228     }
229 }
230  class User {
231     private UserRecords userRecords = new UserRecords();
232     private double balance = 100;
233     private ChargeMode chargeMode;
234     private String number;
235 
236     public User(String str ,String number) {
237         if (str.equals("0")) this.chargeMode = new LandlinePhoneCharging();
238         this.number = number;
239     }
240 
241     public double calBalance(){
242         return getBalance()-chargeMode.getMonthlyRent()-calCost();
243     }
244 
245     public double calCost(){
246         return chargeMode.calCost(userRecords);
247     }
248 
249     public UserRecords getUserRecords() {
250         return userRecords;
251     }
252 
253     public void setUserRecords(UserRecords userRecords) {
254         this.userRecords = userRecords;
255     }
256 
257     public double getBalance() {
258         return balance;
259     }
260 
261     public ChargeMode getChargeMode() {
262         return chargeMode;
263     }
264 
265     public void setChargeMode(ChargeMode chargeMode) {
266         this.chargeMode = chargeMode;
267     }
268 
269     public String getNumber() {
270         return number;
271     }
272 
273     public void setNumber(String number) {
274         this.number = number;
275     }
276 }
277 
278  class UserRecords {
279     private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
280     private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
281     private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
282     private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
283     private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
284     private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
285     private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
286     private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();
287 
288     public void addCallingInCityRecords(CallRecord callRecord){
289         callingInCityRecords.add(callRecord);
290     }
291     public void addCallingInProvinceRecords(CallRecord callRecord){
292         callingInProvinceRecords.add(callRecord);
293     }
294     public void addCallingInLandRecords(CallRecord callRecord){
295         callingInLandRecords.add(callRecord);
296     }
297     public void addAnswerInCityRecords(CallRecord callRecord){
298         answerInCityRecords.add(callRecord);
299     }
300     public void addAnswerInProvinceRecords(CallRecord callRecord){
301         answerInProvinceRecords.add(callRecord);
302     }
303     public void addAnswerInLandRecords(CallRecord callRecord){
304         answerInLandRecords.add(callRecord);
305     }
306     public void addSendMessageRecords(MessageRecord sendMessageRecord){
307         sendMessageRecords.add(sendMessageRecord);
308     }
309     public void addReceiveMessageRecords(MessageRecord receiveMessageRecord){
310         receiveMessageRecords.add(receiveMessageRecord);
311     }
312 
313     public ArrayList<CallRecord> getCallingInCityRecords() {
314         return callingInCityRecords;
315     }
316 
317     public ArrayList<CallRecord> getCallingInProvinceRecords() {
318         return callingInProvinceRecords;
319     }
320 
321     public ArrayList<CallRecord> getCallingInLandRecords() {
322         return callingInLandRecords;
323     }
324 
325     public ArrayList<CallRecord> getAnswerInCityRecords() {
326         return answerInCityRecords;
327     }
328 
329     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
330         return answerInProvinceRecords;
331     }
332 
333     public ArrayList<CallRecord> getAnswerInLandRecords() {
334         return answerInLandRecords;
335     }
336 
337     public ArrayList<MessageRecord> getSendMessageRecords() {
338         return sendMessageRecords;
339     }
340 
341     public ArrayList<MessageRecord> getReceiveMessageRecords() {
342         return receiveMessageRecords;
343     }
344 }

 

 

 

分析:

  • 在根据题目所给类图的提示下,将类于类之间的关系进行梳理搞明白它们的作用。
  • 记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
  • 这道题考察了正则表达式的应用,通过正则表达式将输入通话记录数据中出现的不符合格式要求的行一律忽略,并且判断是开户还是拨打电话。
  • 还考察了字符串的截取,灵活的运用substring以及split方法将开户电话号码、拨打电话号码、接听电话号码、拨打电话区号、接听电话区号、开始时间以及结束时间分别截取出来。

 

踩坑心得:

  • 由于正则表达式的错误,导致一直把正常的通话记录忽略,导致代码运行一部分错误,可以通过debug找出这种问题,将正则表达式删去重写。
  • 因为缺乏常识,不知道北京的区号为3位,正则表达式错误。
  • 还有日期格式的正则表达式问题。
  • 用户输出要排序。

 

第二道:

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

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

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

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

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

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

 

 类图如下:

 

SourceMonitor报表如下:

 

 

代码如下(点击可看):

  1 import java.text.DecimalFormat;
  2 import java.text.ParseException;
  3 import java.text.SimpleDateFormat;
  4 import java.util.*;
  5 
  6 public class Main {
  7     public static void main(String[] args) throws ParseException {
  8         Scanner in = new Scanner(System.in);
  9         Map <String, User> i = new TreeMap<>();
 10         SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
 11         Date date1,date2;
 12         String str;
 13         str = in.nextLine();
 14 
 15         while (!str.equals("end")){
 16                if (str.matches("u-0\\d{9,11}\\s0")){
 17                 String[] a = str.split("-|\\s");
 18                 User user = new User(a[2],a[1]);
 19                 i.put(a[1],user);
 20             } 
 21             
 22             str = in.nextLine();
 23         }
 24 
 25         for (User u : i.values()){
 26             System.out.println(u.getNumber() +" "+ new DecimalFormat("0.0##").format(u.calCost()) + " "+ new DecimalFormat("0.0##").format(u.calBalance()));
 27         }
 28     }
 29     public static boolean isDate(String s){
 30         String[] a = s.split("[.]");
 31         int year = 0,month = 0,day = 0;
 32         year = Integer.parseInt(a[0]);
 33         month = Integer.parseInt(a[1]);
 34         day = Integer.parseInt(a[2]);
 35         if((!isLeapYear(year)&&month==2&&day>29)||month>12||month<1||day>31||day<1||(month==2&&day>28)||(month==4&&day>30)||(month==6&&day>30)||(month==9&&day>30)||(month==11&&day>30))
 36             return false;
 37         else
 38             return true;
 39     }
 40     public static boolean isLeapYear(int year) {
 41         if((year%4==0&&year%100!=0)||year%400==0) return true;
 42         else return false;
 43     }
 44 
 45 }
 46 
 47 
 48 class AnswerInLandRecords extends CallChargeRule{
 49     @Override
 50     public double calCost(ArrayList<CallRecord> callRecords) {
 51         double s = 0;
 52         for (CallRecord a : callRecords){
 53             s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0);
 54         }
 55 
 56         return 0.3 * s;
 57     }
 58 }
 59 abstract class CallChargeRule extends ChargeRule{
 60 
 61     public abstract double calCost(ArrayList<CallRecord> callRecords);
 62 }
 63 
 64 class CallRecord extends CommunicationRecord{
 65     private Date startTime;
 66     private Date endTime;
 67     private String callingAddressAreaCode;
 68     private String answerAddressAreaCode;
 69 
 70     public Date getStartTime() {
 71         return startTime;
 72     }
 73 
 74     public void setStartTime(Date startTime) {
 75         this.startTime = startTime;
 76     }
 77 
 78     public Date getEndTime() {
 79         return endTime;
 80     }
 81 
 82     public void setEndTime(Date endTime) {
 83         this.endTime = endTime;
 84     }
 85 
 86     public String getCallingAddressAreaCode() {
 87         return callingAddressAreaCode;
 88     }
 89 
 90     public void setCallingAddressAreaCode(String callingAddressAreaCode) {
 91         this.callingAddressAreaCode = callingAddressAreaCode;
 92     }
 93 
 94     public String getAnswerAddressAreaCode() {
 95         return answerAddressAreaCode;
 96     }
 97 
 98     public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
 99         this.answerAddressAreaCode = answerAddressAreaCode;
100     }
101 }
102 abstract  class ChargeMode {
103     private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
104 
105     public ChargeMode() {
106         chargeRules.add(new LandPhoneInCityRule());
107         chargeRules.add(new LandPhoneInProvinceRule());
108         chargeRules.add(new LandPhoneInLandRule());
109         chargeRules.add(new AnswerInLandRecords());
110     }
111 
112     public ArrayList<ChargeRule> getChargeRules() {
113         return chargeRules;
114     }
115 
116     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
117         this.chargeRules = chargeRules;
118     }
119 
120     public abstract double calCost(UserRecords userRecords);
121 
122     public abstract double getMonthlyRent();
123 
124 }
125 
126 abstract class ChargeRule {
127     public abstract double calCost(ArrayList<CallRecord> callRecords);
128 }
129 abstract  class CommunicationRecord {
130     protected String callingNumber;
131     protected String answerNumber;
132 
133     public String getCallingNumber() {
134         return callingNumber;
135     }
136 
137     public void setCallingNumber(String callingNumber) {
138         this.callingNumber = callingNumber;
139     }
140 
141     public String getAnswerNumber() {
142         return answerNumber;
143     }
144 
145     public void setAnswerNumber(String answerNumber) {
146         this.answerNumber = answerNumber;
147     }
148 }
149 
150 class LandlinePhoneCharging extends ChargeMode{
151     double monthlyRent = 20;
152 
153     public LandlinePhoneCharging() {
154         super();
155     }
156     @Override
157     public double calCost(UserRecords userRecords) {
158        double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords())
159                 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords())
160                 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
161         return s;
162     }
163 
164     @Override
165     public double getMonthlyRent() {
166         return monthlyRent;
167     }
168 }
169 
170 class LandPhoneInCityRule extends CallChargeRule{
171     @Override
172     public double calCost(ArrayList<CallRecord> callRecords) {
173         double s = 0;
174         double d = 0;
175         for (CallRecord a : callRecords){
176             d = Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0);
177             if (!a.getCallingNumber().matches("0\\d+")) {
178                 if (a.getAnswerAddressAreaCode().matches("0791")) d = d * 0.1;
179                 else if (a.getAnswerAddressAreaCode().matches("(079[^1]|0701)")) d = d * 0.2;
180                 else d = d * 0.3;
181             }else {
182                 if (a.getAnswerAddressAreaCode().matches("0791")) d = d * 0.1;
183                 else if (a.getAnswerAddressAreaCode().matches("(079[^1]|0701)")) d = d * 0.3;
184                 else d = d * 0.6;
185             }
186             s+=d;
187         }
188 
189         return s;
190     }
191 }
192 class LandPhoneInLandRule extends CallChargeRule{
193     @Override
194     public double calCost(ArrayList<CallRecord> callRecords) {
195         double s = 0;
196         for (CallRecord a : callRecords){
197             s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0);
198         }
199 
200         return 0.6 * s;
201     }
202 }
203 class LandPhoneInProvinceRule extends CallChargeRule{
204     @Override
205     public double calCost(ArrayList<CallRecord> callRecords) {
206         double s = 0;
207         for (CallRecord a : callRecords){
208             s += Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 60000.0);
209         }
210 
211         return s*0.3;
212     }
213 }
214 class MessageRecord extends CommunicationRecord {
215     private String message;
216 
217     public String getMessage() {
218         return message;
219     }
220 
221     public void setMessage(String message) {
222         this.message = message;
223     }
224 }
225 
226 class PhoneCharging extends ChargeMode{
227     double monthlyRent = 15;
228 
229     public PhoneCharging() {
230         super();
231     }
232     @Override
233     public double calCost(UserRecords userRecords) {
234         double s = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords())
235                 + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords())
236                 + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords())
237                 + getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords());
238         return s;
239     }
240 
241     @Override
242     public double getMonthlyRent() {
243         return monthlyRent;
244     }
245 }
246 
247 class User {
248     private UserRecords userRecords = new UserRecords();
249     private double balance = 100;
250     private ChargeMode chargeMode;
251     private String number;
252 
253     public User(String str ,String number) {
254         if (str.equals("0")) this.chargeMode = new LandlinePhoneCharging();
255         else this.chargeMode = new PhoneCharging();
256         this.number = number;
257     }
258 
259     public double calBalance(){
260         return getBalance()-chargeMode.getMonthlyRent()-calCost();
261     }
262 
263     public double calCost(){
264         return chargeMode.calCost(userRecords);
265     }
266 
267     public UserRecords getUserRecords() {
268         return userRecords;
269     }
270 
271     public void setUserRecords(UserRecords userRecords) {
272         this.userRecords = userRecords;
273     }
274 
275     public double getBalance() {
276         return balance;
277     }
278 
279     public ChargeMode getChargeMode() {
280         return chargeMode;
281     }
282 
283     public void setChargeMode(ChargeMode chargeMode) {
284         this.chargeMode = chargeMode;
285     }
286 
287     public String getNumber() {
288         return number;
289     }
290 
291     public void setNumber(String number) {
292         this.number = number;
293     }
294 }
295 class UserRecords {
296     private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
297     private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
298     private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
299     private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
300     private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
301     private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
302     private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
303     private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();
304 
305     public void addCallingInCityRecords(CallRecord callRecord){
306         callingInCityRecords.add(callRecord);
307     }
308     public void addCallingInProvinceRecords(CallRecord callRecord){
309         callingInProvinceRecords.add(callRecord);
310     }
311     public void addCallingInLandRecords(CallRecord callRecord){
312         callingInLandRecords.add(callRecord);
313     }
314     public void addAnswerInCityRecords(CallRecord callRecord){
315         answerInCityRecords.add(callRecord);
316     }
317     public void addAnswerInProvinceRecords(CallRecord callRecord){
318         answerInProvinceRecords.add(callRecord);
319     }
320     public void addAnswerInLandRecords(CallRecord callRecord){
321         answerInLandRecords.add(callRecord);
322     }
323     public void addSendMessageRecords(MessageRecord sendMessageRecord){
324         sendMessageRecords.add(sendMessageRecord);
325     }
326     public void addReceiveMessageRecords(MessageRecord receiveMessageRecord){
327         receiveMessageRecords.add(receiveMessageRecord);
328     }
329 
330     public ArrayList<CallRecord> getCallingInCityRecords() {
331         return callingInCityRecords;
332     }
333 
334     public ArrayList<CallRecord> getCallingInProvinceRecords() {
335         return callingInProvinceRecords;
336     }
337 
338     public ArrayList<CallRecord> getCallingInLandRecords() {
339         return callingInLandRecords;
340     }
341 
342     public ArrayList<CallRecord> getAnswerInCityRecords() {
343         return answerInCityRecords;
344     }
345 
346     public ArrayList<CallRecord> getAnswerInProvinceRecords() {
347         return answerInProvinceRecords;
348     }
349 
350     public ArrayList<CallRecord> getAnswerInLandRecords() {
351         return answerInLandRecords;
352     }
353 
354     public ArrayList<MessageRecord> getSendMessageRecords() {
355         return sendMessageRecords;
356     }
357 
358     public ArrayList<MessageRecord> getReceiveMessageRecords() {
359         return receiveMessageRecords;
360     }
361 }
View Code

 

 

 

分析:

  • 这一次的题在电信计费系列1基础上增加类型1-手机实时计费,被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,根据手机和座机的不同进行不同的费用计算,
  • 并且要根据手机现所在地判断是省内漫游或是省外漫游,不同漫游方式每小时价格不同,以及接听电话也要计费,在不同地区接听电话计费价格也不同。
  • 有座机打座机,电话打座机,座机打电话,电话打电话。
  • 时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。

 踩坑心得:

  • 被打的座机不一定在南昌,我错误地将座机默认为都在南昌从而且导致答案错误。
  • 比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码等,此类情况都当成正确的输入计算。

 

第三道:

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

 

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

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

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

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

 

 类图如下:

 

SourceMonitor报表如下:

 

代码如下(点击可看):

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

 

 

 

分析:

  • 这一次题目集与前两道题相比难度有所降低,每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
  • 接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
  • 如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。

 

踩坑心得:

  • 第一次没有注意看题目,短信条数超过之前的还是算之前的价格计算,我把短信条数x最后的价格了导致我答案错误。
  • 本题相对简单无坑。

 

改进建议:

    无;

总结:

  • 这学期的Java题目集比上个学期的C难度提升了很多,需要自学的东西很多,所以花费的时间多了。
  • 在编写代码时需要绝对的认真,不能被打扰 ,精力不集中时容易写出BUG。
  • 在代码之前先要整体的规划,这几次作业是老师给了类图,如果没给就需要自己设计,自己设计会有些难度。
  • java还有很多很多工具功能没学,在今后尽量学习更多。

 

posted on 2022-06-16 23:40  OuDashen  阅读(133)  评论(0)    收藏  举报