Summary of PTA 6th~8th topic set
1 Introduction
Compared with the previous large polygon operations, these three pta operations are relatively simple. The routines of the three operations are similar. The main difficulty lies in understanding the class diagram of the telecom billing series of topics, and writing the correct regular expression to complete the filtering of the strings. Finally, the filtered results are stored in the corresponding array. When calculating the results Directly call the pre-written program to traverse the array. Most of the failures are caused by careless programming, for example, the initial bit setting of the intercepted string is wrong, or the regular expression is wrongly written, etc. As long as you pay attention to avoiding these subtle mistakes, then it can be said that these homeworks are generally quite handy to write.
2. Program Design Analysis
Topic set six
7-1 Telecom Billing Series 1 - Landline Billing
topic:
Implement a simple telecom billing program:
Assume that Nanchang Telecom Branch adopts the billing method for landline users in the city:
The monthly rent is 20 yuan, free calls, 0.1 yuan/minute for city calls, 0.3 yuan/minute for long-distance calls within the province, and 0.6 yuan/minute for domestic long-distance calls. A fraction of a minute shall be counted as one minute.
The area code of Nanchang City: 0791, and the city codes of various places in Jiangxi Province include: 0790~0799 and 0701.
Input format:
Input information includes two types
1. Enter the account opening information of Nanchang users line by line, one user per line,
Format: u-number billing type (billing types include: 0-landline 1-mobile phone real-time billing 2-mobile phone A package)
For example: u-079186300001 0
The landline number consists of 7-8 digits except the area code.
This question only considers the billing type 0-landline billing, and the billing types will be gradually added to the telecommunications series 2 and 3 questions.
2. Enter the communication information of some users in this month line by line, the communication information format:
Landline calling landline: t-calling number receiving number start time end time
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
The above four items are separated by an English space,
The time must conform to the "yyyy.MM.dd HH:mm:ss" format. Tip: Use the SimpleDateFormat class.
For the above two types of information, first enter all account opening information, and then enter all communication information, and the last line ends with "end".
Notice:
Illegal input in this question only judges whether the format is illegal, not whether the content is reasonable (except for time, otherwise it cannot be calculated), for example:
1. All the communication information entered are considered as communication information of the same month, and no judgment is made on whether the date is in the same month or multiple months, and the communication fee is directly accumulated, so the monthly rent is only calculated once.
2. If the time of multiple call records of the same phone number overlaps in the records, no judgment will be made in this case, and the cost of each record will be directly calculated and added up.
3. The area code of the user is not the area code of Nanchang City, and it is also treated as a normal user.
Output format:
According to the detailed communication information entered, calculate the current monthly expenses of all users who have opened an account (accurate to 2 decimal places,
unit: yuan). Suppose the initial balance of each user is 100 yuan.
Each communication message is billed separately and then accumulated, not all the time is accumulated and billed uniformly.
Format: number + English space + total call charge + English space + balance
One row for each user, and the users are sorted by number characters from small to large.
Error handling:
Lines that do not meet the format requirements in the input data are ignored.
Suggested class diagram:
See Figures 1, 2, and 3, and you can adjust according to your understanding:
Figure 1
Figure 1 User Is the user class, including attributes: userRecords (user record), balance(balance), chargeMode(billing method), number(Number). ChargeMode It is the abstract class of billing method: chargeRules It is a collection of various charging rules included in the charging method, ChargeRule See Figure 3 for the class definition. getMonthlyRent()method is used to return the monthly rent ( monthlyRent). UserRecords It is the user record class, which saves the records of various calls and text messages of the user. Various billing rules will use some or all of these records. Its attributes from top to bottom are: Calls within the city, calls within the province (excluding the city), calls outside the province, Records of calls received in the city, calls received in the province (excluding the city), and calls received outside the province And records of sending and receiving text messages.
Figure II
Figure 2 CommunicationRecord It is an abstract communication record class: Include callingNumber dial the number, answerNumber Two attributes of answering number. CallRecord(call records), MessageRecord(SMS record) is its subclass. CallRecord(call record class) contains attributes: start and end time of the call, and The area code of the place to dial ( callingAddressAreaCode),The area code of the pick-up location ( answerAddressAreaCode). Area codes are used to record where calls are made and received. If the landline cannot be moved, it is the local area code. If it is a mobile phone number, there will be a difference.
Figure three
Figure 3 shows the related classes of billing rules. The core methods of these classes are: calCost(ArrayList<CallRecord> callRecords). The method is based on the input parameter callRecords All the records in calculate a certain fee for a certain user; such as local call charges. Input parameters callRecords Constraints for : must be all records of a certain user that meet the requirements of the charging rules. LandPhoneInCityRule,LandPhoneInProvinceRule,LandPhoneInLandRule The three categories are The billing rule class for landline calls to calls within the city, within the province, and outside the province is used to realize the cost calculation of these three situations. (Tip: You can get from UserRecords Get various types of callRecords).
Subsequent expansion instructions:
Subsequent topic sets will add mobile phone users. The billing method for mobile phone users includes, in addition to calling charges similar to landline billing, roaming charges for receiving calls outside the city and charges for sending text messages. It can be considered uniformly in the design of this question.
In the call record, the mobile phone needs to additionally record the area code of the place where the call is made/received, such as:
Landline call mobile phone: t-calling number answering number answering place area code start time end time
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
Calling between mobile phones: t-calling number, dialing location, receiving number, receiving location area code, start time, end time
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
SMS format: m-calling number, receiving number, SMS content
m-18907910010 13305862264 welcome to jiangxi
m-13305862264 18907910010 thank you
Input sample:
A set of inputs is given here. E.g:
u-079186300001 0 t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25 end
Sample output:
The corresponding output is given here. E.g:
079186300001 3.0 77.0
The source code is as follows:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; public class Main { public static void main(String[] args) throws ParseException { Scanner sc=new Scanner(System.in); String s; s=sc.nextLine(); //Create an array of users List<User> users=new ArrayList<>(); List<CallRecord> communicationRecords=new ArrayList<>(); while(!s.equals("end")) { if(s.matches("[u]-[0][7]([9][0-9]|[0][1])[0-9]{7,8} [0-3]")==true||s.matches("^t\\-0\\d{9,11}\\s0\\d{9,11}((\\s\\d{4}\\.([1-9]|([1]{1}[0-2]{1}))\\.([1-9]|([1-2]{1}[0-9]{1})|3[0-1])\\s(([0-1][0-9])|(2[0-3]))\\:([0-5][0-9])\\:([0-5][0-9])){2})")==true) { //create user if(s.charAt(0)=='u') { User user = LineToUser(s); int flag=0; for (User user1 : users) { if(user1.getNumber().equals(user.getNumber())) { flag=1; break; } } if(flag==0) { users.add(user); } } //Create a call log else if(s.charAt(0)=='t') { communicationRecords.add(LineToCallRecord(s)); } } s=sc.nextLine(); } List<User> temp=new ArrayList<>(users); temp.sort(new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User user : temp) { List<CallRecord> temps=new ArrayList<>(); UserRecords userRecords=new UserRecords(); for (CallRecord communicationRecord : communicationRecords) { if(communicationRecord.getCallingNumber().equals(user.getNumber())) { String answerNumber = communicationRecord.getAnswerNumber(); //city if(answerNumber.substring(0,4).equals("0791")) { userRecords.addCallingInCityRecords(communicationRecord); } //province else if((answerNumber.substring(0,3).equals("079")&&!answerNumber.substring(0,4).equals("0791"))||answerNumber.substring(0,4).equals("0701")) { userRecords.addCallingInProvinceRecords(communicationRecord); } // domestic else { userRecords.addCallingInLandRecords(communicationRecord); } } } user.setUserRecords(userRecords); System.out.println(user.getNumber()+" "+Double.parseDouble(String.format("%.2f",user.calCost()))+" "+Double.parseDouble(String.format("%.2f",user.calBalance()))); } } private static User LineToUser(String str){ str = str.substring(2); String[] data = str.split(" "); return new User(data[0],Integer.parseInt(data[1])); } private static CallRecord LineToCallRecord(String str) throws ParseException { SimpleDateFormat format=new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); str = str.substring(2); String[] s = str.split(" "); CallRecord call=new CallRecord(); call.setCallingNumber(s[0]); call.setAnswerNumber(s[1]); String startTime=s[2]+" "+s[3]; String endTime=s[4]+" "+s[5]; Date date1=format.parse(startTime); Date date2=format.parse(endTime); call.setStartTime(date1); call.setEndTime(date2); return call; } } class User{ public User(String s1, int s2) { this.number=s1; if(s2==0) { this.chargeMode=new LandlinePhoneCharging(); } } private String number; private ChargeMode chargeMode; private double balance=100; UserRecords userRecords=new UserRecords(); public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public ChargeMode getChargeMode() { return chargeMode; } public void setChargeMode(ChargeMode chargeMode) { this.chargeMode = chargeMode; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public double calBalance() { ChargeMode chargeMode1=new LandlinePhoneCharging(); double monthlyRent = chargeMode1.getMonthlyRent(); return this.balance-calCost()-monthlyRent; } public double calCost() { ChargeMode chargeMode1=new LandlinePhoneCharging(); double cost = chargeMode1.CalCost(getUserRecords()); return cost; } } class UserRecords{ private ArrayList<CallRecord> callingInCityRecords=new ArrayList<>(); private ArrayList<CallRecord> callingInProvinceRecords=new ArrayList<>(); private ArrayList<CallRecord> callingInLandRecords=new ArrayList<>(); private ArrayList<CallRecord> answerInCityRecords=new ArrayList<>(); private ArrayList<CallRecord> answerInProvinceRecords=new ArrayList<>(); private ArrayList<CallRecord> answerInLandRecords=new ArrayList<>(); private ArrayList<MessageRecord> sendMessageRecords=new ArrayList<>(); private ArrayList<MessageRecord> receiveMessageRecords=new ArrayList<>(); public ArrayList<CallRecord> getCallingInCityRecords() { return callingInCityRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords() { return callingInProvinceRecords; } public void addCallingInCityRecords(CallRecord Records) { callingInCityRecords.add(Records); } public void addCallingInProvinceRecords(CallRecord Records) { callingInProvinceRecords.add(Records); } public void addCallingInLandRecords(CallRecord Records) { callingInLandRecords.add(Records); } public ArrayList<CallRecord> getCallingInLandRecords() { return callingInLandRecords; } public ArrayList<CallRecord> getAnswerInCityRecords() { return answerInCityRecords; } public void addAnswerInCityRecords(ArrayList<CallRecord> answerInCityRecords) { this.answerInCityRecords = answerInCityRecords; } public ArrayList<CallRecord> getAnswerInProvinceRecords() { return answerInProvinceRecords; } public void addAnswerInProvinceRecords(ArrayList<CallRecord> answerInProvinceRecords) { this.answerInProvinceRecords = answerInProvinceRecords; } public ArrayList<CallRecord> getAnswerInLandRecords() { return answerInLandRecords; } public void addAnswerInLandRecords(ArrayList<CallRecord> answerInLandRecords) { this.answerInLandRecords = answerInLandRecords; } public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public void addSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) { this.sendMessageRecords = sendMessageRecords; } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } public void addReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) { this.receiveMessageRecords = receiveMessageRecords; } } abstract class ChargeMode{ private ArrayList<ChargeRule> chargeRules=new ArrayList<>(); public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { this.chargeRules = chargeRules; } public abstract double CalCost(UserRecords userRecords); public abstract double getMonthlyRent(); } class LandlinePhoneCharging extends ChargeMode{ double MonthlyRent=20; @Override public double CalCost(UserRecords userRecords) { ChargeRule InCity=new LandPhoneInCityRule(); double InCityCost = InCity.calCost(userRecords.getCallingInCityRecords()); ChargeRule InLand=new LandPhoneInlandRule(); double InLandCost = InLand.calCost(userRecords.getCallingInLandRecords()); ChargeRule InProvince=new LandPhoneInProvince(); double InProvinceCost = InProvince.calCost(userRecords.getCallingInProvinceRecords()); return InCityCost+InProvinceCost+InLandCost; } @Override public double getMonthlyRent() { return MonthlyRent; } } abstract class CommunicationRecord{ private String callingNumber; private String answerNumber; public String getCallingNumber() { return callingNumber; } public void setCallingNumber(String callingNumber) { this.callingNumber = callingNumber; } public String getAnswerNumber() { return answerNumber; } public void setAnswerNumber(String answerNumber) { this.answerNumber = answerNumber; } } class MessageRecord extends CommunicationRecord{ private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class CallRecord extends CommunicationRecord{ private Date startTime; private Date endTime; private String callingAddressAreaCode; private String answerAddressAreaCode; public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public String getCallingAddressAreaCode() { return callingAddressAreaCode; } public void setCallingAddressAreaCode(String callingAddressAreaCode) { this.callingAddressAreaCode = callingAddressAreaCode; } public String getAnswerAddressAreaCode() { return answerAddressAreaCode; } public void setAnswerAddressAreaCode(String answerAddressAreaCode) { this.answerAddressAreaCode = answerAddressAreaCode; } } abstract class ChargeRule { public abstract double calCost(ArrayList<CallRecord> callRecords); } abstract class CallChargeRule extends ChargeRule{ } class LandPhoneInCityRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum=0; for (CallRecord callRecord : callRecords) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.1*res1; } return sum; } } class LandPhoneInProvince extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum=0; for (CallRecord callRecord : callRecords) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.3*res1; } return sum; } } class LandPhoneInlandRule extends CallChargeRule{ @Override public double calCost(ArrayList<CallRecord> callRecords) { double sum=0; for (CallRecord callRecord : callRecords) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.6*res1; } return sum; } }
The class diagram is as follows:
The SourceMonitor analysis diagram is as follows:
Code analysis:
1. Analyze the class diagram to get:
1. I built the framework of the topic according to the class diagram given in the topic. The main classes are the User class and the UserRecord class. These two classes store the basic information of the user and the records of the user's dialing and answering, which is convenient for the program to record and make calls. The area code and call duration, etc., among which the UserRecord class exists as a User attribute, so you only need to obtain the User objects corresponding to different registration numbers, you can query all the dialing and answering records of the user, and you can conveniently perform billing Operated.
2. On the basis of the above, I created the ChargeRule abstract class, which is mainly used to realize the processing methods of different dialing subjects, such as dialing a phone, answering a mobile phone, answering a mobile phone, etc. Since this question only involves the relationship between the phone and the phone Therefore, the implementation class is mainly the LandPhoneInCity class, the LandPhoneInPorvince class and the LandPhoneInLand class for domestic calls, and the billing method is determined according to the area code of the caller.
3. In the main method, I used a loop + regular expression to obtain valid information. If it is a registered user operation, I will process the obtained string, create a new User object and add it to the storage table users, otherwise if If it is a call record, create a corresponding communicationRecord object and store it in the table communicationRecords, and finally sort and traverse the users table to get the user's phone number, and then nest and traverse the communicationRecords table to find the record with the dialed number consistent with the above phone number, according to the dialed number The area code of the phone number, and store this call record in the table corresponding to UserRecord. Through such an operation, each call record can be corresponded to the call subject one by one, and finally the UserRecord is added to the corresponding user to complete the user's information entry... Finally, the users table is traversed, and the CalCost() method written in advance is called , the final billing result of each user can be obtained.
2. Analyze the SourceMonitor graph to get
1. Except that the maximum complexity exceeds expectations, most of the values of the code are controlled within the expected range, and the ring complexity is generally low.
2. This code is written in strict accordance with the class diagram provided by the title. Both the maximum depth and the average depth are at the expected value, and the code structure is relatively reasonable.
3. This code adopts more polymorphic design concepts, which effectively reduces the amount of code and improves the degree of code reuse. This can also be seen from the lower Method/Class value. Generally speaking, the code quality is better .
Topic set seven
7-1 Telecom Billing Series 2-Mobile Phone + Landline Billing
topic:
Realize the billing program of Nanchang Telecom Branch, assuming that the company adopts two billing schemes for mobile phone and landline users, respectively as follows:
1. The billing method adopted for landline users in the city (same content as Telecom Billing Series 1):
The monthly rent is 20 yuan, free calls, 0.1 yuan/minute for city calls, 0.3 yuan/minute for long-distance calls within the province, and 0.6 yuan/minute for domestic long-distance calls. A fraction of a minute shall be counted as one minute.
Suppose the area code of this city is 0791, and the city codes of various places in Jiangxi Province include: 0790~0799 and 0701.
2. Adopt real-time billing method for mobile phone users:
The monthly rent is 15 yuan, free calls within the city and the province, 0.1 yuan/minute for calls within the city, 0.2 yuan/minute for calls within the city, 0.3 yuan/minute for calls outside the province, and roaming within the province 0.3 yuan/minute for calls, 0.3 yuan/minute for calls when roaming outside the province, and 0.6 yuan/minute for calls when roaming outside the province;
Note: Whether the called phone belongs to the city, the province or the country is determined by the area code of the receiving location of the called phone. For example, in the following case, the mobile phone user 13307912264 in Nanchang answered the call in Guangzhou with the area code 020, and the calling number should be calculated as Call a long-distance outside the province, and at the same time, the mobile phone user 13307912264 will also be charged roaming charges for receiving calls outside the province:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
enter:
Input information includes two types
1. Enter the account opening information of Nanchang users line by line, one user per line, including mobile phone and landline users
Format: u-number billing type (billing types include: 0-landline 1-mobile phone real-time billing 2-mobile phone A package)
For example: u-079186300001 0
The landline number is concatenated by the area code and the phone number. The phone number contains 7-8 digits, and the highest digit of the area code is 0.
A mobile phone number consists of 11 digits, the highest digit being 1.
This question adds type 1-mobile phone real-time billing on the basis of telecom billing series 1.
Set the mobile phone to 0 or the landline to 1, this kind of error can not be judged.
2. Enter the communication information of some users in this month line by line, the communication information format:
Landline calling landline: t-calling number receiving number start time end time
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
The above four items are separated by an English space,
The time must conform to the "yyyy.MM.dd HH:mm:ss" format. Tip: Use the SimpleDateFormat class.
The input format adds the format of receiving and receiving calls and sending and receiving text messages on mobile phones. In addition to the number, the information on mobile phones needs to additionally record the area code of the place where the call is made/answered, such as:
From a landline to a mobile phone:
t-Calling number Answering number Answering place area code Start time End time
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
Calls between mobile phones:
t-Calling number Dialing location Answering number Answering location area code Start time End time
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
Note: For the above two types of information, first enter all account opening information, and then enter all communication information, and the last line ends with "end".
output:
According to the detailed communication information entered, calculate the monthly expenses of all users who have opened an account (accurate to 2 decimal places, unit yuan). Suppose the initial balance of each user is 100 yuan.
Each communication and SMS message is billed separately and then accumulated, not all messages are accumulated and billed uniformly.
Format: number + English space + total call charge + English space + balance
One row for each user, and the users are sorted by number characters from small to large.
Error handling:
Lines that do not meet the format requirements in the input data are ignored.
This question only makes wrong judgments on the format, and does not need to make unreasonable judgments on the content. For example, the time of two communication records of the same phone overlaps, and the account opening number is not the number of Nanchang City. Such cases are regarded as correct input calculations. But the time input must meet the requirements, for example, 2022.13.61 28:72:65 cannot be input.
Suggested class diagram:
See Figures 1, 2, and 3:
Figure 1
Figure 1 User Is the user class, including attributes: userRecords (user record), balance(balance), chargeMode(billing method), number(Number). ChargeMode It is the abstract class of billing method: chargeRules It is a collection of various charging rules included in the charging method, ChargeRule See Figure 3 for the class definition. getMonthlyRent()method is used to return the monthly rent ( monthlyRent). UserRecords It is the user record class, which saves the records of various calls and text messages of the user. Various billing rules will use some or all of these records. Its attributes from top to bottom are: Calls within the city, calls within the province (excluding the city), calls outside the province, Records of calls received in the city, calls received in the province (excluding the city), and calls received outside the province And records of sending and receiving text messages.
Figure II
Figure 2 CommunicationRecord It is an abstract communication record class: Include callingNumber dial the number, answerNumber Two attributes of answering number. CallRecord(call records), MessageRecord(SMS record) is its subclass. CallRecord(call record class) contains attributes: start and end time of the call, and The area code of the place to dial ( callingAddressAreaCode),The area code of the pick-up location ( answerAddressAreaCode). Area codes are used to record where calls are made and received. If the landline cannot be moved, it is the local area code. If it is a mobile phone number, there will be a difference.
Figure three
Figure 3 shows the related classes of billing rules. The core methods of these classes are: calCost(ArrayList<CallRecord> callRecords). The method is based on the input parameter callRecords All the records in calculate a certain fee for a certain user; such as local call charges. Input parameters callRecords Constraints for : must be all records of a certain user that meet the requirements of the charging rules. SendMessageRule It is the billing rule class for sending SMS, which is used to calculate the cost of sending SMS. LandPhoneInCityRule,LandPhoneInProvinceRule,LandPhoneInLandRule The three categories are the billing rule categories for calls made by landlines within the city, within the province, and outside the province, and are used to realize the cost calculation of these three situations.
(Hint: various types of callRecords can be obtained from the UserRecords class).
Note: The classes defined in the above figure are not limited requirements, and can be supplemented or modified according to actual needs.
Input sample:
A set of inputs is given here. E.g:
u-13811111111 1 t-13811111111 0791 13811111110 020 2022.1.3 08:00:00 2022.1.3 08:09:20 end
Sample output:
The corresponding output is given here. E.g:
13811111111 3.0 82.0
The source code is as follows:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; public class Main { public static void main(String[] args) throws ParseException { Scanner sc=new Scanner(System.in); String s; s=sc.nextLine(); //Create an array of users List<User> users=new ArrayList<>(); List<CallRecord> communicationRecords=new ArrayList<>(); while(!s.equals("end")) { if( s.matches("[u]-([0][7]([9][0-9]|[0][1])[0-9]{7,8}) [0-3]") ||s.matches("[u]-[1][0-9]{10} [0-3]") ||s.matches("(([t]-0791[0-9]{7,8}\\s0[0-9]{9,11})|([t]-0791[0-9]{7,8}\\s1[0-9]{10}\\s0[0-9]{2,3})|([t]-1[0-9]{10}\\s0[0-9]{2,3}\\s0[0-9]{9,11})|([t]-1[0-9]{10}\\s0[0-9]{2,3}\\s1[0-9]{10}\\s0[0-9]{2,3}))(\\s\\d{4}\\.([1-9]|([1]{1}[0-2]{1}))\\.([1-9]|([1-2]{1}[0-9]{1})|3[0-1])\\s(([0-1][0-9])|(2[0-3]))\\:([0-5][0-9])\\:([0-5][0-9])){2}")==true) { //create user if(s.charAt(0)=='u') { User user = LineToUser(s); int flag=0; for (User user1 : users) { if(user1.getNumber().equals(user.getNumber())) { flag=1; break; } } if(flag==0) { users.add(user); } } //Create a call log else if(s.charAt(0)=='t') { communicationRecords.add(LineToCallRecord(s)); } else if(s.charAt(0)=='m') { } } s=sc.nextLine(); } List<User> temp=new ArrayList<>(users); temp.sort(new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User user : temp) { UserRecords userRecords=new UserRecords(); for (CallRecord communicationRecord : communicationRecords) { // traverse to the caller if (communicationRecord.getCallingNumber().equals(user.getNumber())) { //city if (communicationRecord.gettype().matches("^1[1-3]$")) { userRecords.addCallingInCityRecords(communicationRecord); } else if (communicationRecord.gettype().matches("^2[1-3]$")) { userRecords.addCallingInProvinceRecords(communicationRecord); } else { userRecords.addCallingInLandRecords(communicationRecord); } } } for (CallRecord communicationRecord : communicationRecords) { //traverse to the receiver if(communicationRecord.getAnswerNumber().equals(user.getNumber())) { //city if(communicationRecord.gettype().matches("^[1-3]1$")) { userRecords.addAnswerInCityRecords(communicationRecord); } else if(communicationRecord.gettype().matches("^[1-3]2$")) { userRecords.addAnswerInProvinceRecords(communicationRecord); } else { userRecords.addAnswerInLandRecords(communicationRecord); } } } user.setUserRecords(userRecords); System.out.println(user.getNumber()+" "+Double.parseDouble(String.format("%.2f",user.calCost()))+" "+Double.parseDouble(String.format("%.2f",user.calBalance()))); } } private static User LineToUser(String str){ str = str.substring(2); String[] data = str.split(" "); return new User(data[0],Integer.parseInt(data[1])); } private static CallRecord LineToCallRecord(String str) throws ParseException { SimpleDateFormat format=new SimpleDateFormat("yyyy.MM.dd HH:mm:ss"); str = str.substring(2); String[] s = str.split(" "); CallRecord call=new CallRecord(); if(s.length==6) { call.setCallingNumber(s[0]); call.setAnswerNumber(s[1]); String startTime=s[2]+" "+s[3]; String endTime=s[4]+" "+s[5]; Date date1=format.parse(startTime); Date date2=format.parse(endTime); call.setStartTime(date1); call.setEndTime(date2); call.setCallingAddressAreaCode(s[0].substring(0,4)); call.setAnswerAddressAreaCode(s[1].substring(0,4)); } if(s.length==7) { if(s[0].charAt(0)!='0') { call.setCallingNumber(s[0]); call.setAnswerNumber(s[2]); call.setCallingAddressAreaCode(s[1]); call.setAnswerAddressAreaCode(s[2].substring(0,4)); String startTime=s[3]+" "+s[4]; String endTime=s[5]+" "+s[6]; Date date1=format.parse(startTime); Date date2=format.parse(endTime); call.setStartTime(date1); call.setEndTime(date2); } else { call.setCallingNumber(s[0]); call.setAnswerNumber(s[1]); call.setCallingAddressAreaCode(s[0].substring(0,4)); call.setAnswerAddressAreaCode(s[2]); String startTime=s[3]+" "+s[4]; String endTime=s[5]+" "+s[6]; Date date1=format.parse(startTime); Date date2=format.parse(endTime); call.setStartTime(date1); call.setEndTime(date2); } } else if(s.length==8) { call.setCallingNumber(s[0]); call.setCallingAddressAreaCode(s[1]); call.setAnswerNumber(s[2]); call.setAnswerAddressAreaCode(s[3]); String startTime=s[4]+" "+s[5]; String endTime=s[6]+" "+s[7]; Date date1=format.parse(startTime); Date date2=format.parse(endTime); call.setStartTime(date1); call.setEndTime(date2); } return call; } } class User{ @Override public String toString() { return "User{" + "number='" + number + '\'' + ", chargeMode=" + chargeMode + ", balance=" + balance + ", userRecords=" + userRecords + '}'; } public User(String s1, int s2) { this.number=s1; if(s2==0) { this.chargeMode=new LandlinePhoneCharging(); } else if (s2 == 1) { this.chargeMode=new MobilePhoneCharging(); } } private String number; private ChargeMode chargeMode; private double balance=100; UserRecords userRecords=new UserRecords(); public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public ChargeMode getChargeMode() { return chargeMode; } public void setChargeMode(ChargeMode chargeMode) { this.chargeMode = chargeMode; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public double calBalance() { double monthlyRent = chargeMode.getMonthlyRent(); return this.balance-calCost()-monthlyRent; } public double calCost() { double cost = chargeMode.CalCost(getUserRecords()); return cost; } } class UserRecords{ private ArrayList<CallRecord> callingInCityRecords=new ArrayList<>(); private ArrayList<CallRecord> callingInProvinceRecords=new ArrayList<>(); private ArrayList<CallRecord> callingInLandRecords=new ArrayList<>(); private ArrayList<CallRecord> answerInCityRecords=new ArrayList<>(); private ArrayList<CallRecord> answerInProvinceRecords=new ArrayList<>(); private ArrayList<CallRecord> answerInLandRecords=new ArrayList<>(); private ArrayList<MessageRecord> sendMessageRecords=new ArrayList<>(); private ArrayList<MessageRecord> receiveMessageRecords=new ArrayList<>(); public ArrayList<CallRecord> getCallingInCityRecords() { return callingInCityRecords; } public ArrayList<CallRecord> getCallingInProvinceRecords() { return callingInProvinceRecords; } public void addCallingInCityRecords(CallRecord Records) { callingInCityRecords.add(Records); } public void addCallingInProvinceRecords(CallRecord Records) { callingInProvinceRecords.add(Records); } public void addCallingInLandRecords(CallRecord Records) { callingInLandRecords.add(Records); } public ArrayList<CallRecord> getCallingInLandRecords() { return callingInLandRecords; } public ArrayList<CallRecord> getAnswerInCityRecords() { return answerInCityRecords; } public void addAnswerInCityRecords(CallRecord Records) { this.answerInCityRecords.add(Records); } public ArrayList<CallRecord> getAnswerInProvinceRecords() { return answerInProvinceRecords; } public void addAnswerInProvinceRecords(CallRecord Records) { this.answerInProvinceRecords.add(Records); } public ArrayList<CallRecord> getAnswerInLandRecords() { return answerInLandRecords; } public void addAnswerInLandRecords(CallRecord Records) { this.answerInLandRecords.add(Records); } public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public void addSendMessageRecords(ArrayList<MessageRecord> sendMessageRecords) { this.sendMessageRecords = sendMessageRecords; } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } public void addReceiveMessageRecords(ArrayList<MessageRecord> receiveMessageRecords) { this.receiveMessageRecords = receiveMessageRecords; } } abstract class ChargeMode{ private ArrayList<ChargeRule> chargeRules=new ArrayList<>(); public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { this.chargeRules = chargeRules; } public abstract double CalCost(UserRecords userRecords); public abstract double getMonthlyRent(); } class LandlinePhoneCharging extends ChargeMode{ double MonthlyRent=20; @Override public double CalCost(UserRecords userRecords) { ChargeRule InCity=new LandPhoneInCityRule(); double InCityCost = InCity.calCost(userRecords); ChargeRule InLand=new LandPhoneInlandRule(); double InLandCost = InLand.calCost(userRecords); ChargeRule InProvince=new LandPhoneInProvince(); double InProvinceCost = InProvince.calCost(userRecords); return InCityCost+InProvinceCost+InLandCost; } @Override public double getMonthlyRent() { return MonthlyRent; } } class MobilePhoneCharging extends ChargeMode{ double MonthlyRent=15; @Override public double CalCost(UserRecords userRecords) { //Outgoing billing + answering billing ChargeRule InCity=new MobilePhoneInCityRule(); double InCityCost = InCity.calCost(userRecords); ChargeRule InProvince=new MobilePhoneInProvince(); double InProvinceCost = InProvince.calCost(userRecords); ChargeRule InLand=new MobilePhoneInlandRule(); double InLandCost = InLand.calCost(userRecords); return InCityCost+InProvinceCost+InLandCost; } @Override public double getMonthlyRent() { return MonthlyRent; } } abstract class CommunicationRecord{ private String callingNumber; private String answerNumber; public String getCallingNumber() { return callingNumber; } public void setCallingNumber(String callingNumber) { this.callingNumber = callingNumber; } public String getAnswerNumber() { return answerNumber; } public void setAnswerNumber(String answerNumber) { this.answerNumber = answerNumber; } } class MessageRecord extends CommunicationRecord{ private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } class CallRecord extends CommunicationRecord{ @Override public String toString() { return "CallRecord{" + "startTime=" + startTime + ", endTime=" + endTime + ", callingAddressAreaCode='" + callingAddressAreaCode + '\'' + ", answerAddressAreaCode='" + answerAddressAreaCode + '\'' + '}'; } private Date startTime; private Date endTime; private String callingAddressAreaCode; private String answerAddressAreaCode; public String gettype() { String type=""; if(callingAddressAreaCode.equals("0791")) { type=type.concat("1"); } else if ((callingAddressAreaCode.substring(0,3).equals("079")&&!callingAddressAreaCode.equals("0791"))||callingAddressAreaCode.equals("0701")) { type= type.concat("2"); }else { type= type.concat("3"); } if(answerAddressAreaCode.equals("0791")) { type=type.concat("1"); } else if ((answerAddressAreaCode.substring(0,3).equals("079")&&!answerAddressAreaCode.equals("0791"))||answerAddressAreaCode.equals("0701")) { type= type.concat("2"); }else { type=type.concat("3"); } return type; } public Date getStartTime() { return startTime; } public void setStartTime(Date startTime) { this.startTime = startTime; } public Date getEndTime() { return endTime; } public void setEndTime(Date endTime) { this.endTime = endTime; } public String getCallingAddressAreaCode() { return callingAddressAreaCode; } public void setCallingAddressAreaCode(String callingAddressAreaCode) { this.callingAddressAreaCode = callingAddressAreaCode; } public String getAnswerAddressAreaCode() { return answerAddressAreaCode; } public void setAnswerAddressAreaCode(String answerAddressAreaCode) { this.answerAddressAreaCode = answerAddressAreaCode; } } abstract class ChargeRule { public abstract double calCost(UserRecords records); } abstract class CallChargeRule extends ChargeRule{ } class LandPhoneInCityRule extends CallChargeRule{ @Override public double calCost(UserRecords records) { double sum=0; for (CallRecord callRecord :records.getCallingInCityRecords()) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } if(callRecord.gettype().equals("11")) { sum+=0.1*res1; } else if (callRecord.gettype().equals("12")) { sum+=0.3*res1; } else { sum+=0.6*res1; } } return sum; } } class LandPhoneInProvince extends CallChargeRule{ @Override public double calCost(UserRecords records) { double sum=0; for (CallRecord callRecord :records.getCallingInProvinceRecords()) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.3*res1; } return sum; } } class LandPhoneInlandRule extends CallChargeRule{ @Override public double calCost(UserRecords records) { double sum=0; for (CallRecord callRecord :records.getCallingInLandRecords()) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.6*res1; } return sum; } } class MobilePhoneInCityRule extends CallChargeRule{ @Override public double calCost(UserRecords records) { double sum=0; for (CallRecord callRecord :records.getCallingInCityRecords()) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } if(callRecord.gettype().equals("11")) { sum+=0.1*res1; } else if (callRecord.gettype().equals("12")) { sum+=0.2*res1; } else { sum+=0.3*res1; } } return sum; } } class MobilePhoneInProvince extends CallChargeRule{ @Override public double calCost(UserRecords records) { double sum=0; for (CallRecord callRecord : records.getCallingInProvinceRecords()) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.3*res1; } return sum; } } class MobilePhoneInlandRule extends CallChargeRule{ @Override public double calCost(UserRecords records) { double sum=0; for (CallRecord callRecord : records.getCallingInLandRecords()) { Date endTime = callRecord.getEndTime(); Date startTime = callRecord.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.6*res1; } for (CallRecord answer : records.getAnswerInLandRecords()) { Date endTime =answer.getEndTime(); Date startTime =answer.getStartTime(); double f1,f2; f2=endTime.getTime(); f1=startTime.getTime(); double res = (f2 - f1) / 1000 / 60; int res1=(int) res; if(res-res1!=0) { res1=res1+1; } sum+=0.3*res1; } return sum; } }
The class diagram is as follows:
The SourceMonitor analysis diagram is as follows:
Code analysis:
1. The analysis class diagram is available
1. Compared with the previous question, which only involves fixed-line telephones, this question adds a module for mobile phone calls, so more modules need to be added on the basis of the original code, such as the MobilePhoneInCity module for calling calls from mobile phones in the city, and the mobile phone call module in the province. The roaming billing module MobilePhoneInProvince class, the domestic mobile phone dials the roaming module MobilePhoneInLand class to separately count the billing of dialing mobile phones in different regions.
2. At the same time, according to the requirements of the topic, domestic roaming mobile phone calls are also billed separately, so the mobile phone call answering billing array AnswerInLandRecords is added to UserRecord, and a loop traversal is added to the main method. Count their domestic roaming answering records. Finally, in the CalCost() method of the mobile phone user class, the cost of domestic roaming answering needs to be calculated and added to the result, so as to basically meet the requirements of the topic.
3. When designing regular expressions, it is necessary to add additional mobile phone user judgments, so there must be at least 6 more situations on the original basis. For specific codes, please refer to the main method.
2. Analyze the SourceMonitor analysis diagram to get
1. Except for a few properties such as the maximum complexity that failed to fall within the ideal range, all the basic properties of this code are at normal values, and the code has high reusability.
2. This code follows the basic framework of the previous question, adopts abstraction + polymorphism + inheritance mechanism, which greatly reduces code redundancy, so the Method/Class value is far lower than the upper limit of SourceMonitor analysis, and the code quality is relatively considerable .
3. The average depth and maximum depth are close to the upper limit, indicating that the code meets the quality requirements as a whole, but there is still room for optimization.
Topic set eight
7-1 Telecom Billing Series 3-SMS Billing
topic:
Implement a simple telecom billing program, and use the following billing method for SMS messages on mobile phones:
1. Receive SMS for free, send SMS 0.1 yuan/message, more than 3 0.2 yuan/message, more than 5 0.3 yuan/message.
2. If the number of characters in a short message sent at one time exceeds 10, it will be calculated as one short message per 10 characters.
enter:
Input information includes two types
1. Enter the account opening information of mobile phone users in Nanchang City line by line, one user per line.
Format: u-number billing type (billing types include: 0-landline 1-mobile phone real-time billing 2-mobile phone A package 3-mobile SMS billing)
For example: u-13305862264 3
The landline number is concatenated by the area code and the phone number. The phone number contains 7-8 digits, and the highest digit of the area code is 0.
A mobile phone number consists of 11 digits, the highest digit being 1.
This question is only for type 3 - SMS billing.
2. Enter the SMS information of some users this month line by line, the format of the SMS:
m-Calling number, receiving number, SMS content (SMS content can only be composed of numbers, letters, spaces, English commas, and English periods)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.
Note: For the above two types of information, first enter all account opening information, and then enter all communication information, and the last line ends with "end".
output:
According to the entered detailed SMS information, calculate the monthly SMS charges of all users who have opened an account (accurate to 2 decimal places, unit yuan). Suppose the initial balance of each user is 100 yuan.
Each SMS message is billed separately and then accumulated, not all messages are accumulated and billed uniformly.
Format: number + English space + total call charge + English space + balance
One row for each user, and the users are sorted by number characters from small to large.
Error handling:
Lines that do not meet the format requirements in the input data are ignored.
This question only makes wrong judgments on the format, and there is no need to make unreasonable judgments on the content. For example, the time of the two communication records of the same phone overlaps, the account opening number is not the number of Nanchang City, and you call yourself, etc. Correct input calculations. But the time input must meet the requirements, for example, 2022.13.61 28:72:65 cannot be input.
This question only considers SMS billing, and does not consider communication fees and monthly rental fees.
Suggested class diagram:
See Figures 1, 2, and 3:
Figure 1
Figure 1 User Is the user class, including attributes: userRecords (user record), balance(balance), chargeMode(billing method), number(Number). ChargeMode It is the abstract class of billing method: chargeRules It is a collection of various charging rules included in the charging method, ChargeRule See Figure 3 for the class definition. getMonthlyRent()method is used to return the monthly rent ( monthlyRent). UserRecords It is the user record class, which saves the records of various calls and text messages of the user. Various billing rules will use some or all of these records. Its attributes from top to bottom are: Calls within the city, calls within the province (excluding the city), calls outside the province, Records of calls received in the city, calls received in the province (excluding the city), and calls received outside the province And records of sending and receiving text messages.
Figure II
Figure 2 CommunicationRecord It is an abstract communication record class: Include callingNumber dial the number, answerNumber Two attributes of answering number. CallRecord(call records), MessageRecord(SMS record) is its subclass.
Figure three
Figure 3 shows the related classes of billing rules. The core methods of these classes are: calCost(ArrayList callRecords). The method is based on the input parameter callRecords All the records in calculate a certain fee for a certain user; such as local call charges. Input parameters callRecords Constraints for : must be all records of a certain user that meet the requirements of the charging rules. SendMessageRule It is the billing rule class for sending SMS, which is used to calculate the cost of sending SMS. LandPhoneInCityRule,LandPhoneInProvinceRule,LandPhoneInLandRule The three categories are the billing rule categories for calls made by landlines within the city, within the province, and outside the province, and are used to realize the cost calculation of these three situations. (Tip: You can get from UserRecords Get various types of callRecords).
Note: The classes defined in the above figure are not limited requirements, and can be supplemented or modified according to actual needs.
Input sample:
A set of inputs is given here. E.g:
u-18907910010 3 m-18907910010 13305862264 aaaaaaaaaaaaaaaaaaaaaaa end
Sample output:
The corresponding output is given here. E.g:
18907910010 0.3 99.7
Input example 1:
A set of inputs is given here. E.g:
u-18907910010 3 m-18907910010 13305862264 aaaaaaaaaaaa m-18907910010 13305862264 aaaaaaa. m-18907910010 13305862264 bb,bbbb end
Output sample 1:
The corresponding output is given here. E.g:
18907910010 0.5 99.5
The source code is as follows:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; public class Main { public static void main(String[] args) throws ParseException { Scanner sc=new Scanner(System.in); String s; s=sc.nextLine(); //Create an array of users List<User> users=new ArrayList<>(); List<MessageRecord> communicationRecords=new ArrayList<>(); while(!s.equals("end")) { if(s.matches("[u]-[1][0-9]{10} [0-3]") ||s.matches("m-1\\d{10}\\s1\\d{10}[ 0-9a-z,.A-Z]+")==true) { //create user if(s.charAt(0)=='u') { User user = LineToUser(s); int flag=0; for (User user1 : users) { if(user1.getNumber().equals(user.getNumber())) { flag=1; break; } } if(flag==0) { users.add(user); } } //Create a call log if(s.charAt(0)=='m') { MessageRecord messageRecord = LineToMessageRecord(s); communicationRecords.add(messageRecord); } } s=sc.nextLine(); } List<User> temp=new ArrayList<>(users); temp.sort(new Comparator<User>() { @Override public int compare(User o1, User o2) { return o1.getNumber().compareTo(o2.getNumber()); } }); for (User user : temp) { UserRecords re=new UserRecords(); for (MessageRecord communicationRecord : communicationRecords) { if(communicationRecord.getCallingNumber().equals(user.getNumber())) { re.addSendMessageRecords(communicationRecord); } } user.setUserRecords(re); System.out.println(user.getNumber()+" "+Double.parseDouble(String.format("%.2f",user.calCost()))+" "+Double.parseDouble(String.format("%.2f",user.calBalance()))); } } private static User LineToUser(String str){ str = str.substring(2); String[] data = str.split(" "); return new User(data[0],Integer.parseInt(data[1])); } private static MessageRecord LineToMessageRecord(String str) throws ParseException { str = str.substring(2); String[] s = str.split(" "); MessageRecord mesg=new MessageRecord(); mesg.setCallingNumber(s[0]); mesg.setAnswerNumber(s[1]); mesg.setMessage(str.substring(24)); return mesg; } } class User{ @Override public String toString() { return "User{" + "number='" + number + '\'' + ", chargeMode=" + chargeMode + ", balance=" + balance + ", userRecords=" + userRecords + '}'; } public User(String s1, int s2) { this.number=s1; if (s2 == 3) { this.chargeMode=new MobilePhoneCharging(); } } private String number; private ChargeMode chargeMode; private double balance=100; UserRecords userRecords=new UserRecords(); public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public ChargeMode getChargeMode() { return chargeMode; } public void setChargeMode(ChargeMode chargeMode) { this.chargeMode = chargeMode; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public UserRecords getUserRecords() { return userRecords; } public void setUserRecords(UserRecords userRecords) { this.userRecords = userRecords; } public double calBalance() { return this.balance-calCost(); } public double calCost() { double cost = chargeMode.CalCost(getUserRecords()); return cost; } } class UserRecords{ private ArrayList<MessageRecord> sendMessageRecords=new ArrayList<>(); private ArrayList<MessageRecord> receiveMessageRecords=new ArrayList<>(); public ArrayList<MessageRecord> getSendMessageRecords() { return sendMessageRecords; } public void addSendMessageRecords(MessageRecord sendMessageRecord) { sendMessageRecords.add(sendMessageRecord); } public ArrayList<MessageRecord> getReceiveMessageRecords() { return receiveMessageRecords; } public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) { receiveMessageRecords.add(receiveMessageRecord); } } abstract class ChargeMode{ private ArrayList<ChargeRule> chargeRules=new ArrayList<>(); public ArrayList<ChargeRule> getChargeRules() { return chargeRules; } public void setChargeRules(ArrayList<ChargeRule> chargeRules) { this.chargeRules = chargeRules; } public abstract double CalCost(UserRecords userRecords); } class MobilePhoneCharging extends ChargeMode{ // double MonthlyRent=15; @Override public double CalCost(UserRecords userRecords) { ChargeRule cal=new MessageChargeRule(); double InLandCost = cal.calCost(userRecords); return InLandCost; } } abstract class CommunicationRecord{ private String callingNumber; private String answerNumber; public String getCallingNumber() { return callingNumber; } public void setCallingNumber(String callingNumber) { this.callingNumber = callingNumber; } public String getAnswerNumber() { return answerNumber; } public void setAnswerNumber(String answerNumber) { this.answerNumber = answerNumber; } } class MessageRecord extends CommunicationRecord{ private String message; public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } @Override public String toString() { return "MessageRecord{" + "message='" + message + '\'' + '}'; } } abstract class ChargeRule { public abstract double calCost(UserRecords records); } class MessageChargeRule extends ChargeRule{ @Override public double calCost(UserRecords records) { int Messagesum=0; for (MessageRecord sendMessageRecord :records.getSendMessageRecords()) { if(sendMessageRecord.getMessage().length()>10) { Messagesum+=(sendMessageRecord.getMessage().length()/10); if(sendMessageRecord.getMessage().length()%10!=0) { Messagesum++; } } else { Messagesum++; } } double sum=0; if(Messagesum<=3) { sum+=(Messagesum*0.1); } else if(Messagesum>3&&Messagesum<=5) { sum+=((Messagesum-3)*0.2+0.3); } else if(Messagesum>5) { sum+=0.7+(Messagesum-5)*0.3; } return sum; } }
The class diagram is as follows:
The SourceMonitor analysis diagram is as follows:
Code analysis:
1. It can be obtained from the class diagram
1. Since this question only involves the billing of the SMS service, I deleted the part of the code related to the billing of the fixed-line phone and the part of the billing service of the mobile phone call, and only kept the module of creating a mobile phone user, and added it on the original basis The Message billing mode has been added to adapt to changes in topics.
2. Due to the deletion of many redundant modules, the dependency relationship reflected in this class diagram is relatively simple, mainly that the MessageCharge class implements the ChargeRule class, the MobilePhoneCharging class implements the ChargeMode class, and the MessageRecord class implements the CommunicationRecord class, each of which implements different modules Specific functions such as counting SMS records, calculating the length of SMS, calculating the total cost, etc. Finally, the User class couples these scattered modules to realize the functions required by the topic.
3. The main method of this code has little change except for the regular expression. The basic implementation logic is similar to the previous two questions, so I won’t repeat it here.
2. There are SourceMonitor analysis diagrams available
1. Except that the maximum complexity of the code exceeds the expected value, the other indices are all within the expected value, indicating that the cyclomatic complexity is ideal.
2. The value of Method/Class is small, indicating that there are fewer redundant classes and methods in the code, which once again reflects the advantages of the polymorphism-inheritance system.
3. Both the average depth and the maximum depth are within the ideal range, indicating that the redundancy of the code is low, there is no unnecessary time loss, and the resource utilization rate is high.
3. The experience of stepping on the pit
1. Due to the introduction of new mobile phone user classes in the seventh operation, more communication situations will be generated. If all these situations are calculated by loops, the program will be very redundant and difficult to maintain. And because in the communication record about the mobile phone, the area code must be added after the number of each mobile phone, which leads to the total length of the string array after the string is intercepted according to " " in different situations is not the same. So after analyzing the pros and cons, I decided to use the length of the string array obtained after intercepting " " to judge whether it is a call to a mobile phone, a mobile phone to a mobile phone, or a mobile phone to call a phone. Facts have proved that this method is indeed more concise and effective Reduced code redundancy.
2. To calculate the length of the message in the eighth job, it is necessary to judge whether the length of the message is greater than 10. If the length is greater than 10, every 10 digits is counted as a message. When I wrote the calculation algorithm for the first time, I rarely judged that the length of the last message is greater than 10, but not divisible by 10. For example, if the length is 36, it should be divided into 4 text messages, and the length of the last text message is 6. In the original version, I did not add the judgment condition, and only took the result after divisible by 10 as the number of text messages, resulting in the final number of text messages being only 3. It does not match the correct answer, which in turn leads to an error in the calculation of the entire SMS. Later, the targeted judgment was added, so that the program could run normally.
3. The text message interception of the eighth operation needs to also intercept the invalid spaces in the text message content into the text message. When I wrote it for the first time, I intercepted it according to the blank space. As a result, there were three points that always failed to pass. Later, through analysis, the content of the string intercepted from the 24th to the end was regarded as the text message content, and it passed smoothly. The reason why it is the 24th is that I intercepted the string similar to "m-18907910010 13305862264 aaaaaaaaaaaa" based on "-" in advance, classified it into two parts, and took the second part as the string after preliminary processing. The mobile phone number is fixed at 11 digits, the two mobile phone numbers are 22 digits, plus two spaces for division, the total is 24 digits, so the content after 24 digits is the text message content, and then call substring() to process after the first processing String, you can get the correct result.
4. Code improvement suggestions
1. In these three assignments, I built many methods that are not used temporarily based on the class diagram. In practical applications, they can be selectively deleted to reduce the code length and make the code more compact overall.
2. In these three operations, I implemented some operations in the main method, which is not very satisfactory. Because many modules are mixed together, the code is very difficult to debug. I also have a deep understanding in the process of programming. In order to figure out the problem of regular expressions, I had to create another project and copy the relevant code to avoid Unnecessary trouble caused by modifying the original project. Then it's endless trying to find examples that might not match the regex I wrote. This process is relatively inefficient and redundant. If you optimize the code structure from the beginning and try to avoid writing a lot of code in the main method and only use it as the entry point of the program, I think it will be more conducive to later maintenance and debugging.
3. In the cyclic traversal of the User part of the main method of the seventh job, you can modify the original traversal of the CommunicationRecords array twice to only traversal once, and only add a judgment in the inner nested loop. This can be done Further reduce the cyclomatic complexity.
5. Summary
1. Homework summary:
These assignments are generally of moderate difficulty, but compared with the previous large polygon assignments, which focus more on mathematics, these assignments focus more on the investigation of java characteristics and students' ability to restore and expand class diagrams. The logic of the question itself is not complicated. By writing and debugging the code, I have a better understanding of the object-oriented characteristics of java, and also realize the importance of "design" in "program design". Sometimes, a reasonable system design will have a huge positive impact on program portability, reusability, and ease of modification. On the contrary, a poor design will have a huge hindrance to later programming and maintenance.
2. Summary of recent learning: In the six weeks since the mid-term exam, I have mainly reviewed the programming ideas of interfaces, the use of lambda expressions, and the basic programming methods of javaFx, and finished the farmer crossing the river Graphical interface design. After that, I learned the principle of java thread programming, completed the java reproduction of the classic thread model of producer and consumer, and finally learned some ideas and concepts of java programming mode. It can be said that I have gained a lot. On the one hand, my understanding of java programming ideas is not deep enough, and I am not proficient in the application of design patterns. I hope that I can gradually make up for this shortcoming in future programming.
3. Suggestions to the teacher: I hope that the teacher can explain some classic design patterns and the usage scenarios of their codes in detail when talking about java design patterns, so that students can really understand and use these valuable knowledge.