BLOG-3
一、前言
- 难度分析:近三次大作业难度相较与前面多边形难度有所下降,手机计费比座机计费大,而最后的短信计费难度则又降低。
- 题量:题量适中
- 知识点:继承多态容器,正则表达式等
二、设计与分析
1.题目一:7-1 电信计费系列1-座机计费
实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
南昌市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
输入格式:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码除区号外由是7-8位数字组成。
本题只考虑计费类型0-座机计费,电信系列2、3题会逐步增加计费类型。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
注意:
本题非法输入只做格式非法的判断,不做内容是否合理的判断(时间除外,否则无法计算),比如:
1、输入的所有通讯信息均认为是同一个月的通讯信息,不做日期是否在同一个月还是多个月的判定,直接将通讯费用累加,因此月租只计算一次。
2、记录中如果同一电话号码的多条通话记录时间出现重合,这种情况也不做判断,直接 计算每条记录的费用并累加。
3、用户区号不为南昌市的区号也作为正常用户处理。
输出格式:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,
单位元)。假设每个用户初始余额是100元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
建议类图:
参见图1、2、3,可根据理解自行调整:

图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
源码:
import java.util.Scanner;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
public class Main{
public static void main(String []args) throws ParseException {
Scanner input = new Scanner(System.in);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ArrayList<User> array = new ArrayList<>();
int flag = 0;
String s = input.nextLine();
String[] a ;
while (!s.equals("end")){
if(s.matches("[u][-](0791)[0-9]{7,8}[ ][0]")){
a = s.substring(2,s.length()).split("\\s");
for(int i = 0;i < array.size();i++){
if(Objects.equals(array.get(i).getNumber(), a[0])) {
flag = 1;
}
}
if(flag == 0) {
array.add(new User(a[0]));
flag = 0;
}
}
if(s.matches("t-(\\d){11,12}\\s(\\d){10,12}\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]"
+ "|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])"
+ "|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d\\s((((1[6-9]|[2-9]\\d)\\d{2}).([13578]|1[02]).([1-9]|[12]\\d|3[01]))"
+ "|(((1[6-9]|[2-9]\\d)\\d{2}).([13456789]|1[012]).([1-9]|[12]\\d|30))|(((1[6-9]|[2-9]\\d)\\d{2})-2-([1-9]|1\\d|2[0-8]))"
+ "|(((1[6-9]|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|((16|[2468][048]|[3579][26])00))-2-29-)) (20|21|22|23|[0-1]\\d):[0-5]\\d:[0-5]\\d")){
a = s.substring(2,s.length()).split("\\s");
for(int i=0;i< array.size();i++){
if(array.get(i).getNumber().equals(a[0])){
if(a[1].startsWith("0791")){
array.get(i).userRecord.addCallingInCityRecords(new CallRecord(a[2]+" "+a[3],a[4]+" "+a[5]));
array.get(i).setUserRecord(array.get(i).userRecord);
}
else if(a[1].substring(0,4).matches("(079\\d|0701)")){
array.get(i).userRecord.addCallingInProvinceRecords(new CallRecord(a[2]+" "+a[3],a[4]+" "+a[5]));
array.get(i).setUserRecord(array.get(i).userRecord);
}
else{
array.get(i).userRecord.addCallingInLandRecords(new CallRecord(a[2]+" "+a[3],a[4]+" "+a[5]));
array.get(i).setUserRecord(array.get(i).userRecord);
}
}
}
}
s = input.nextLine();
}
List<User> list = new ArrayList<>(array);
Collections.sort(list);
for (User e : list){
System.out.print(e.getNumber()+" ");
System.out.print(new DecimalFormat("0.0#").format(e.calCost()));
System.out.print(" ");
System.out.print(new DecimalFormat("0.0#").format(e.calBalance()));
System.out.println();
}
}
}
abstract class ChargeRule{
}
abstract class CallChargeRule extends ChargeRule{
public double calCost(ArrayList<CallRecord>callRecords){
return 0;
}
}
class CallRecord extends ChargeRule{
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String AnswerAddressAreaCode;
public CallRecord(String startTime,String endTime) throws ParseException {
this.startTime = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(startTime);
this.endTime = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").parse(endTime);
}
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 ChargeMode{
ArrayList<ChargeRule> chargeRule = new ArrayList<ChargeRule>();
public ArrayList<ChargeRule> getChargeRule(){
return chargeRule;
}
public void setChargeRule(ArrayList<ChargeRule> chargeRule){
this.chargeRule = chargeRule;
}
public double getMonthlyRent(){
return 20;
}
public double calCost(UserRecords userRecords){
return 0;
}
}
class LandlinePhoneCharging extends ChargeMode{
private double monthlyRent = 20;
public double calCost(UserRecords userRecords){
return monthlyRent * 1;
}
public double getMonthlyRent(){
return monthlyRent;
}
}
class CommunicationRecord{
protected String callingNumber;
protected 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 ChargeRule{
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class LandPhoneInCityRule extends CallChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){
double cost = 0;
double minute;
for (CallRecord e: callRecords){
minute = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime()) / 60000);
cost = cost + 0.1 * minute;
}
return cost;
}
}
class LandPhoneInProvinceRule extends CallChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){
double cost = 0;
double minute;
for (CallRecord e: callRecords){
minute = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime()) / 60000);
cost = cost + 0.3 * minute;
}
return cost;
}
}
class LandPhoneInIandRule extends CallChargeRule{
public double calCost(ArrayList<CallRecord> callRecords){
double cost = 0;
double minute;
for (CallRecord e: callRecords){
minute = (int) Math.ceil((double) (e.getEndTime().getTime()-e.getStartTime().getTime()) / 60000);
cost = cost + 0.6 * minute;
}
return cost;
}
}
class User implements Comparable<User> {
UserRecords userRecord = new UserRecords();
private double balance = 100;
ChargeMode chargeMode;
private String number;
public User(){
}
public void setBalance(double balance) {
this.balance = balance;
}
public User(String number) {
this.number = number;
}
public double calBalance(){
return balance - calCost() - 20;
}
public double calCost(){
LandPhoneInCityRule landPhoneInCityRule = new LandPhoneInCityRule();
LandPhoneInIandRule landPhoneInIandRule = new LandPhoneInIandRule();
LandPhoneInProvinceRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();
return landPhoneInIandRule.calCost(userRecord.getCallingInLandRecords())
+landPhoneInCityRule.calCost(userRecord.getCallingInCityRecords())
+landPhoneInProvinceRule.calCost(userRecord.getCallingInProvinceRecords());
}
public UserRecords getUserRecord(){
return userRecord;
}
public void setUserRecord(UserRecords userRecord){
this.userRecord = userRecord;
}
public double getBalance(){
return balance;
}
public ChargeMode getChargeMode(){
return chargeMode;
}
public void setChargeMode(ChargeMode chargeMode){
this.chargeMode = chargeMode;
}
public String getNumber(){
return number;
}
public void setNumber(String number){
this.number = number;
}
public int compareTo(User o) {
return this.getNumber().compareTo(o.getNumber());
}
}
class UserRecords{
ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
ArrayList<MessageRecord> sendMessageRecord = new ArrayList<MessageRecord>();
ArrayList<MessageRecord> receiveMessageRecord = new ArrayList<MessageRecord>();
public void addCallingInCityRecords(CallRecord callRecord){
callingInCityRecords.add(callRecord);
}
public void addCallingInProvinceRecords(CallRecord callRecord){
callingInProvinceRecords.add(callRecord);
}
public void addCallingInLandRecords(CallRecord callRecord){
callingInLandRecords.add(callRecord);
}
public void addAnswerInCityRecords(CallRecord callRecord){
answerInCityRecords.add(callRecord);
}
public void addAnswerInProvinceRecords(CallRecord callRecord){
answerInProvinceRecords.add(callRecord);
}
public void addAnswerInLandRecords(CallRecord callRecord){
answerInLandRecords.add(callRecord);
}
public void addSendMessageRecord(MessageRecord sendMessageRecord){
this.sendMessageRecord.add(sendMessageRecord);
}
public void addReceiveMessageRecord(MessageRecord receiveMessageRecord){
this.receiveMessageRecord.add(receiveMessageRecord);
}
public ArrayList<MessageRecord> getSendMessageRecord(){
return sendMessageRecord;
}
public ArrayList<MessageRecord> getReceiveMessageRecord(){
return receiveMessageRecord;
}
public ArrayList<CallRecord> getCallingInCityRecords(){
return callingInCityRecords;
}
public ArrayList<CallRecord> getCallingInProvinceRecords(){
return callingInProvinceRecords;
}
public ArrayList<CallRecord> getCallingInLandRecords(){
return callingInLandRecords;
}
public ArrayList<CallRecord> getAnswerInCityRecords(){
return answerInCityRecords;
}
public ArrayList<CallRecord> getAnswerInProvinceRecords(){
return answerInProvinceRecords;
}
public ArrayList<CallRecord> getAnswerInLandRecords(){
return answerInLandRecords;
}
}
代码类图:

分析:
本题由于老师已经将类图给出,将所给类补全后,在Main中利用正则表达式判断输入字符串,并进行容器的添加计算,需要将类与类之间的关系理顺
踩坑心得:
这题正则表达式的书写非常有难度,一定要小心仔细
2.题目二:7-1 电信计费系列2-手机+座机计费
实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
1、针对市内座机用户采用的计费方式(与电信计费系列1内容相同):
月租20元,接电话免费,市内拨打电话0.1元/分钟,省内长途0.3元/分钟,国内长途拨打0.6元/分钟。不足一分钟按一分钟计。
假设本市的区号:0791,江西省内各地市区号包括:0790~0799以及0701。
2、针对手机用户采用实时计费方式:
月租15元,市内省内接电话均免费,市内拨打市内电话0.1元/分钟,市内拨打省内电话0.2元/分钟,市内拨打省外电话0.3元/分钟,省内漫游打电话0.3元/分钟,省外漫游接听0.3元/分钟,省外漫游拨打0.6元/分钟;
注:被叫电话属于市内、省内还是国内由被叫电话的接听地点区号决定,比如以下案例中,南昌市手机用户13307912264在区号为020的广州接听了电话,主叫号码应被计算为拨打了一个省外长途,同时,手机用户13307912264也要被计算省外接听漫游费:
u-13307912264 1
t-079186330022 13307912264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
输入:
输入信息包括两种类型
1、逐行输入南昌市用户开户的信息,每行一个用户,含手机和座机用户
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐)
例如:u-079186300001 0
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题在电信计费系列1基础上增加类型1-手机实时计费。
手机设置0或者座机设置成1,此种错误可不做判断。
2、逐行输入本月某些用户的通讯信息,通讯信息格式:
座机呼叫座机:t-主叫号码 接听号码 起始时间 结束时间
t-079186330022 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:11
以上四项内容之间以一个英文空格分隔,
时间必须符合"yyyy.MM.dd HH:mm:ss"格式。提示:使用SimpleDateFormat类。
输入格式增加手机接打电话以及收发短信的格式,手机接打电话的信息除了号码之外需要额外记录拨打/接听的地点的区号,比如:
座机打手机:
t-主叫号码 接听号码 接听地点区号 起始时间 结束时间
t-079186330022 13305862264 020 2022.1.3 10:00:25 2022.1.3 10:05:11
手机互打:
t-主叫号码 拨号地点 接听号码 接听地点区号 起始时间 结束时间
t-18907910010 0791 13305862264 0371 2022.1.3 10:00:25 2022.1.3 10:05:11
注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细通讯信息,计算所有已开户的用户的当月费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条通讯、短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
建议类图:
参见图1、2、3:

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

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

图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
源码:
import java.util.ArrayList;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Collections;
import java.util.Scanner;
abstract class CallChargeRule extends ChargeRule{
public double calCost(ArrayList<CallRecord>callRecords) {
return 0;
}
}
class CallRecord {
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String answerAddressAreaCode;
public CallRecord(String starttime,String endtime, String callingAddressAreaCode, String answerAddressAreaCode) throws ParseException {
super();
SimpleDateFormat sf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
String date1 = starttime;
String date2 = endtime;
Date time1 = sf.parse(date1);
Date time2 = sf.parse(date2);
this.startTime = time1;
this.endTime = time2;
this.callingAddressAreaCode = callingAddressAreaCode;
this.answerAddressAreaCode = 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 ChargeMode {
private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
}
public double calCost(UserRecords userRecords) {
return 0;
}
public double getMonthlyRent() {
return 0;
}
}
abstract class ChargeRule {
}
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 LandlinePhoneCharging extends ChargeMode{
private double monthlyRent = 20;
public double getMonthlyRent() {
return monthlyRent;
}
public double calCost(UserRecords userRecords) {
double calcost = 0;
LandPhoneInCityRule incity = new LandPhoneInCityRule();
LandPhoneInProvinceRule inprovince = new LandPhoneInProvinceRule();
LandPhoneInlandRule inland = new LandPhoneInlandRule();
calcost = incity.calCost(userRecords.getCallinglnCityRecords()) + inprovince.calCost(userRecords.getCallinglnProvinceRecords()) + inland.calCost(userRecords.getCallinglnLandRecords());
return calcost;
}
}
class LandPhoneInCityRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.1 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class LandPhoneInlandRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.6 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class LandPhoneInProvinceRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
public class Main {
public static void main(String[] args) throws ParseException {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
String s0 = "u-079[0-9][0-9]{7,8} 0" ;
String s1 = "u-0701[0-9]{7,8} 0";
String s2 = "t-[0-9]{10,12} [0-9]{10,12} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}";
String s3 = "0791";
String s4 = "079[0-9]";
String s5 = "0701";
String s6 = "[0-9]{3,4}";
String s7 = "[0-9]{11}";
String s8 = "u-[0-9]{11} 1";
String s9 = "t-[0-9]{10,12} [0-9]{11} [0-9]{3,4} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}";
String s10 = "t-[0-9]{11} [0-9]{3,4} [0-9]{11} [0-9]{3,4} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}";
String s11 = "t-[0-9]{11} [0-9]{3,4} [0-9]{10,12} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2} [0-9]{4}.([1-9]||1[0-2]).([1-9]||[1-3][0-9]) [0-9]{2}.[0-9]{2}.[0-9]{2}";
String s12 = "[0-9]{10,12}";
String s13 = "0791[0-9]{7,8}";
String s14 = "079[0-9]{8,9}";
String s15 = "0701[0-9]{7,8}";
String s16 = "[0-9]{10,12}";
ArrayList<User>list = new ArrayList<>();
String s = in.nextLine();
while(!s.matches(s9)&&!s.matches(s10)&&!s.matches(s11)){
User a = new User();
if(s.matches(s0)||s.matches(s1)||s.matches(s8)){
a.setNumber((String) s.subSequence(2, s.length()-2));
int flag = 0;
for(User b :list) {
if(b.getNumber().equals((String) s.subSequence(2, s.length()-2))) {
flag++;
}
}
if(flag==0)
list.add(a);
}
s = in.nextLine();
if(s.equals("end")){
break;
}
}
while(!s.equals("end")) {
if(s.matches(s2)) {
String str[] = s.split(" ");
String num1 = str[0].substring(2);
String num2 = str[1];
String starttime = str[2]+" "+str[3];
String endtime = str[4]+" "+str[5];
if(check(starttime)&&check(endtime)) {
for(int i = 0;i<list.size();i++) {
if(list.get(i).getNumber().equals(num1)&&num2.matches(s13)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnCityRecords(callRecords);
}
else if(list.get(i).getNumber().equals(num1)&&(num2.matches(s14)||num2.matches(s15))&&!num2.matches(s13)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnProvinceRecords(callRecords);
}
else if(list.get(i).getNumber().equals(num1)&&!num2.matches(s13)&&!num2.matches(s14)&&!num2.matches(s15)&&num2.matches(s16)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnLandRecords(callRecords);
}
}
}
}
if(s.matches(s9)) {
String str[] = s.split(" ");
String num1 = str[0].substring(2);
String num2 = str[1];
String place = str[2];
String starttime = str[3]+" "+str[4];
String endtime = str[5]+" "+str[6];
if(check(starttime)&&check(endtime)) {
for(int i = 0;i<list.size();i++) {
if(list.get(i).getNumber().equals(num1)&&place.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnCityRecords(callRecords);
}
else if(list.get(i).getNumber().equals(num1)&&(place.matches(s4)||place.matches(s5))&&!place.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnProvinceRecords(callRecords);
}
else if(list.get(i).getNumber().equals(num1)&&!place.matches(s3)&&!place.matches(s4)&&!place.matches(s5)&&place.matches(s6)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnLandRecords(callRecords);
for(int j = 0;j<list.size();j++) {
if(list.get(j).getNumber().equals(num2)) {
list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
}
}
break;
}
else
if(list.get(i).getNumber().equals(num2)&&!place.matches(s3)&&!place.matches(s4)&&!place.matches(s5)&&place.matches(s6))
{
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
for(int j = 0;j<list.size();j++) {
if(list.get(j).getNumber().equals(num2)) {
list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
}
}
}
break;
}
}
}
if(s.matches(s10)) {
String str[] = s.split(" ");
String num1 = str[0].substring(2);
String place1 = str[1];
String num2 = str[2];
String place2 = str[3];
String starttime = str[4]+" "+str[5];
String endtime = str[6]+" "+str[7];
if(check(starttime)&&check(endtime)) {
for(int i = 0;i<list.size();i++) {
if(place1.matches(s3))
{
if(list.get(i).getNumber().equals(num1)&&place2.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnCityRecords(callRecords);
break;
}
else if(list.get(i).getNumber().equals(num1)&&(place2.matches(s4)||place2.matches(s5))&&!place2.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnProvinceRecords(callRecords);
break;
}
else if(list.get(i).getNumber().equals(num1)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s)&&place2.matches(s6)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnLandRecords(callRecords);
for(int j = 0;j<list.size();j++) {
if(list.get(j).getNumber().equals(num2)&&num1!=num2) {
list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
}
}
break;
}
else if(list.get(i).getNumber().equals(num2)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6))
{
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
break;
}
}
if((place1.matches(s4)||place1.matches(s5))&&!place1.matches(s3))
{
if(list.get(i).getNumber().equals(num1)&&place2.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords);
break;
}
else if(list.get(i).getNumber().equals(num1)&&(place2.matches(s4)||place2.matches(s5))&&!place2.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords);
break;
}
else if(list.get(i).getNumber().equals(num1)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords);
for(int j = 0;j<list.size();j++) {
if(list.get(j).getNumber().equals(num2)&&num1!=num2) {
list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
}
}
break;
}
else if(list.get(i).getNumber().equals(num2)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6))
{
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
break;
}
}
if(!place1.matches(s3)&&!place1.matches(s4)&&!place1.matches(s5)&&place1.matches(s6))
{
if(list.get(i).getNumber().equals(num1)&&place2.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords);
break;
}
else if(list.get(i).getNumber().equals(num1)&&(place2.matches(s4)||place2.matches(s5))&&!place2.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords);
break;
}
else if(list.get(i).getNumber().equals(num1)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords);
for(int j = 0;j<list.size();j++) {
if(list.get(j).getNumber().equals(num2)&&num1!=num2) {
list.get(j).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
}
}
break;
}
else if(list.get(i).getNumber().equals(num2)&&!place2.matches(s3)&&!place2.matches(s4)&&!place2.matches(s5)&&place2.matches(s6))
{
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addAnswerlnLandRoamRecords(callRecords);
for(int j = 0;j<list.size();j++) {
if(list.get(j).getNumber().equals(num1)&&num1!=num2) {
list.get(j).getUserRecords().addCallinglnLandRoamRecords(callRecords);
}
}
break;
}
}
}
}
}
if(s.matches(s11)) {
String str[] = s.split(" ");
String num1 = str[0].substring(2);
String place = str[1];
String num2 = str[2];
String starttime = str[3]+" "+str[4];
String endtime = str[5]+" "+str[6];
if(check(starttime)&&check(endtime)) {
for(int i = 0;i<list.size();i++) {
if(list.get(i).getNumber().equals(num1)&&place.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnCityRecords(callRecords);
}
else
if(list.get(i).getNumber().equals(num1)&&(place.matches(s4)||place.matches(s5))&&!place.matches(s3)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnProvinceRoamRecords(callRecords);
}
else
if(list.get(i).getNumber().equals(num1)&&!place.matches(s3)&&!place.matches(s4)&&!place.matches(s5)&&place.matches(s6)) {
CallRecord callRecords = new CallRecord(starttime, endtime, num1, num2);
list.get(i).getUserRecords().addCallinglnLandRoamRecords(callRecords);
}
}
}
}
s = in.nextLine();
}
for(int i = 0;i<list.size();i++) {
if(list.get(i).getNumber().matches(s6)) {
list.get(i).calBalance();
list.get(i).calCost();
}
if(list.get(i).getNumber().matches(s7)) {
list.get(i).calBalance1();
list.get(i).calCost1();
}
for(int j = 0;j<list.size()-1;j++) {
if(list.get(j).getNumber().compareTo(list.get(j+1).getNumber())>0) {
Collections.swap(list, j, j+1);
}
}
}
for(User l : list) {
if(l.getNumber().charAt(0)=='0') {
System.out.printf("%s %.1f %.1f\n",l.getNumber(),l.calCost(),l.calBalance());
}
if(l.getNumber().charAt(0)=='1') {
System.out.printf("%s %.1f %.1f\n",l.getNumber(),l.calCost1(),l.calBalance1());
}
}
}
public static boolean check(String s) {
SimpleDateFormat a = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
try {
a.setLenient(false);
a.parse(s);
}catch(Exception e) {
return false;
}
return true;
}
}
class MessageRecord {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class SmartlinePhoneCharging extends ChargeMode{
private double monthlyRent = 15;
public double getMonthlyRent() {
return monthlyRent;
}
public double calCost(UserRecords userRecords) {
double calcost = 0;
SmartPhoneInCityRule smartPhoneInCityRule = new SmartPhoneInCityRule();
SmartPhoneInProvinceRule smartPhoneInProvinceRule = new SmartPhoneInProvinceRule();
SmartPhoneInLandRule smartPhoneInLandRule = new SmartPhoneInLandRule();
SmartPhoneInProvinceRoamRule smartPhoneInProvinceRoamRule = new SmartPhoneInProvinceRoamRule();
SmartPhoneInLandCallingRoamRule smartPhoneInLandCallingRoamRule = new SmartPhoneInLandCallingRoamRule();
SmartPhoneInLandAnswerRoamRule smartPhoneInLandAnswerRoamRule = new SmartPhoneInLandAnswerRoamRule();
calcost = smartPhoneInCityRule.calCost(userRecords.getCallinglnCityRecords()) + smartPhoneInProvinceRule.calCost(userRecords.getCallinglnProvinceRecords()) + smartPhoneInLandRule.calCost(userRecords.getCallinglnLandRecords()) + smartPhoneInProvinceRoamRule.calCost(userRecords.getCallinglnProvinceRoamRecords()) + smartPhoneInLandCallingRoamRule.calCost(userRecords.getCallinglnLandRoamRecords()) + smartPhoneInLandAnswerRoamRule.calCost(userRecords.getAnswerlnLandRoamRecords());
return calcost;
}
}
class SmartPhoneInCityRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords) {
sum += 0.1 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class SmartPhoneInLandAnswerRoamRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class SmartPhoneInLandCallingRoamRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.6 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class SmartPhoneInLandRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class SmartPhoneInProvinceRoamRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.3 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class SmartPhoneInProvinceRule extends CallChargeRule{
@Override
public double calCost(ArrayList<CallRecord> callRecords) {
double sum = 0;
for(CallRecord a:callRecords){
sum += 0.2 * ((((a.getEndTime().getTime() - a.getStartTime().getTime())/1000)+59)/60);
}
return sum;
}
}
class User {
private UserRecords userRecords = new UserRecords();
private double balance = 100 ;
private ChargeMode chargeMode0;
private ChargeMode chargeMode1;
private String number;
public User() {
super();
this.chargeMode0 = new LandlinePhoneCharging();
this.chargeMode1 = new SmartlinePhoneCharging();
}
public double calBalance() {
double Balance = 0;
Balance = getBalance() - calCost() - getChargeMode().getMonthlyRent();
return Balance;
}
public double calCost() {
double sum = 0;
sum = getChargeMode().calCost(getUserRecords());
return sum;
}
public double calBalance1() {
double Balance = 0;
Balance = getBalance() - calCost1() - getChargeMode1().getMonthlyRent();
return Balance;
}
public double calCost1() {
double sum = 0;
sum = getChargeMode1().calCost(getUserRecords());
return sum;
}
public UserRecords getUserRecords() {
return userRecords;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public double getBalance() {
return balance;
}
public ChargeMode getChargeMode() {
return chargeMode0;
}
public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode0 = chargeMode;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public ChargeMode getChargeMode1() {
return chargeMode1;
}
public void setChargeMode1(ChargeMode chargeMode1) {
this.chargeMode1 = chargeMode1;
}
}
class UserRecords {
private ArrayList<CallRecord> callinglnCityRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> callinglnProvinceRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> callinglnLandRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> answerlnCityRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> answerlnProvinceRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> answerlnLandRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> callinglnProvinceRoamRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> callinglnLandRoamRecords = new ArrayList<CallRecord>();
private ArrayList<CallRecord> answerlnLandRoamRecords = new ArrayList<CallRecord>();
private ArrayList<MessageRecord> sendMessageReconds = new ArrayList<MessageRecord>();
private ArrayList<MessageRecord> receiveMessageReconds = new ArrayList<MessageRecord>();
public ArrayList<CallRecord> getCallinglnCityRecords() {
return callinglnCityRecords;
}
public void addCallinglnCityRecords(CallRecord callRecord) {
callinglnCityRecords.add(callRecord);
}
public ArrayList<CallRecord> getCallinglnProvinceRecords() {
return callinglnProvinceRecords;
}
public void addCallinglnProvinceRecords(CallRecord callRecord) {
callinglnProvinceRecords.add(callRecord);
}
public ArrayList<CallRecord> getCallinglnLandRecords() {
return callinglnLandRecords;
}
public void addCallinglnLandRecords(CallRecord callRecord) {
callinglnLandRecords.add(callRecord);
}
public ArrayList<CallRecord> getAnswerlnCityRecords() {
return answerlnCityRecords;
}
public void addAnswerlnCityRecords(CallRecord callRecord) {
answerlnCityRecords.add(callRecord);
}
public ArrayList<CallRecord> getAnswerlnProvinceRecords() {
return answerlnProvinceRecords;
}
public void addAnswerlnProvinceRecords(CallRecord callRecord) {
answerlnProvinceRecords.add(callRecord);
}
public ArrayList<CallRecord> getAnswerlnLandRecords() {
return answerlnLandRecords;
}
public void addAnswerlnLandRecords(CallRecord callRecord) {
answerlnLandRecords.add(callRecord);
}
public ArrayList<MessageRecord> getSendMessageReconds() {
return sendMessageReconds;
}
public void addSendMessageReconds(MessageRecord messageRecord) {
sendMessageReconds.add(messageRecord);
}
public ArrayList<MessageRecord> getReceiveMessageReconds() {
return receiveMessageReconds;
}
public void addReceiveMessageReconds(MessageRecord messageRecord) {
receiveMessageReconds.add(messageRecord);
}
public ArrayList<CallRecord> getCallinglnProvinceRoamRecords() {
return callinglnProvinceRoamRecords;
}
public void addCallinglnProvinceRoamRecords(CallRecord callRecord) {
callinglnProvinceRoamRecords.add(callRecord);
}
public ArrayList<CallRecord> getCallinglnLandRoamRecords() {
return callinglnLandRoamRecords;
}
public void addCallinglnLandRoamRecords(CallRecord callRecord) {
callinglnLandRoamRecords.add(callRecord);
}
public ArrayList<CallRecord> getAnswerlnLandRoamRecords() {
return answerlnLandRoamRecords;
}
public void addAnswerlnLandRoamRecords(CallRecord callRecord) {
answerlnLandRoamRecords.add(callRecord);
}
sourceMonitor图:

分析:
本题在之前的基础上增加算钱的类,依旧利用正则表达式判别输入字符串后进行操作
3.题目三:7-1 电信计费系列3-短信计费
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
输入:
输入信息包括两种类型
1、逐行输入南昌市手机用户开户的信息,每行一个用户。
格式:u-号码 计费类型 (计费类型包括:0-座机 1-手机实时计费 2-手机A套餐 3-手机短信计费)
例如:u-13305862264 3
座机号码由区号和电话号码拼接而成,电话号码包含7-8位数字,区号最高位是0。
手机号码由11位数字构成,最高位是1。
本题只针对类型3-手机短信计费。
2、逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.
注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。
本题只考虑短信计费,不考虑通信费用以及月租费。
建议类图:
参见图1、2、3:

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

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

图3
图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。
源码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
import java.text.ParseException;
abstract class ChargeMode {
private ArrayList<ChargeRule> chargeRules = new ArrayList<>();
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
}
public double calCost(UserRecords userRecords) {
return 0;
}
public double getMonthlyRent() {
return 0;
}
}
abstract class ChargeRule {
}
public class Main {
public static void main(String[] args) throws ParseException{
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
String s1 = "[0-9]{11}";
String s2 = "u-[0-9]{11} 3";
String s3 = "m-[0-9]{11} [0-9]{11} ";
String s4 = "m-[0-9]{11}";
String s5 = "m-[0-9]{11} [0-9]{11} [0-9|a-z|A-Z|\\s|\\.|\\,]+";
ArrayList<User> list = new ArrayList<User>();
String s = in.nextLine();
while(!s.matches(s5)){
User a = new User();
if(s.matches(s2)){
a.setNumber((String) s.subSequence(2, s.length()-2));
int flag = 0;
for(User b :list) {
if(b.getNumber().equals((String) s.subSequence(2, s.length()-2))) {
flag++;
}
}
if(flag==0)
list.add(a);
}
s = in.nextLine();
if(s.equals("end")){
break;
}
}
while(!s.equals("end")) {
if(s.matches(s5)) {
String str[] = ((String) s.subSequence(0, 25)).split(" ");
String num1 = str[0].substring(2);
String num2 = str[1];
String message = s.substring(26,s.length());
for(int i = 0;i<list.size();i++) {
if(list.get(i).getNumber().equals(num1)) {
MessageRecord messageRecord = new MessageRecord(message,num1,num2);
list.get(i).getUserRecords().addSendMessageReconds(messageRecord);
}
}
}
s = in.nextLine();
}
for(int i = 0;i<list.size();i++) {
if(list.get(i).getNumber().matches(s1)) {
list.get(i).calBalance();
list.get(i).calCost();
for(int j = 0;j<list.size()-1;j++) {
if(list.get(j).getNumber().compareTo(list.get(j+1).getNumber())>0) {
Collections.swap(list, j, j+1);
}
}
}
}
for(User l : list) {
System.out.printf("%s %.1f %.1f\n",l.getNumber(),l.calCost(),l.calBalance());
}
}
}
abstract class MessageChargeRule extends ChargeRule{
public double calCost(ArrayList<MessageRecord>messageRecord) {
return 0;
}
}
class MessageCharging extends ChargeMode{
public double calCost(UserRecords userRecords) {
double calcost = 0;
SendMessageRule sendMessageRule = new SendMessageRule ();
calcost = sendMessageRule.calCost(userRecords.getSendMessageReconds());
return calcost;
}
}
class MessageRecord {
private String message;
private String callingAddressAreaCode;
private String answerAddressAreaCode;
public MessageRecord(String message, String callingAddressAreaCode, String answerAddressAreaCode) {
super();
this.message = message;
this.callingAddressAreaCode = callingAddressAreaCode;
this.answerAddressAreaCode = answerAddressAreaCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class SendMessageRule extends MessageChargeRule{
@Override
public double calCost(ArrayList<MessageRecord> messageRecord) {
// TODO Auto-generated method stub
double calcost = 0;
int sum0 = 0;
for(MessageRecord messagerecord : messageRecord) {
int sum = 0;
if(messagerecord.getMessage().length()%10==0)
sum = messagerecord.getMessage().length()/10;
else {
sum = messagerecord.getMessage().length()/10 + 1;
}
sum0 += sum;
}
if(sum0<=3) {
calcost = 0.1*sum0;
}
if(sum0>3&&sum0<=5) {
calcost = 0.1*3 + (sum0-3)*0.2;
}
if(sum0>5) {
calcost = 0.1*3 + 0.2*2 + 0.3*(sum0-5);
}
return calcost;
}
}
class User {
private UserRecords userRecords = new UserRecords();
private double balance = 100 ;
private ChargeMode chargeMode;
private String number;
public User() {
super();
this.chargeMode = new MessageCharging();
}
public double calBalance() {
double Balance = 0;
Balance = getBalance() - calCost();
return Balance;
}
public double calCost() {
double sum = 0;
sum = getChargeMode().calCost(getUserRecords());
return sum;
}
public UserRecords getUserRecords() {
return userRecords;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public double getBalance() {
return balance;
}
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;
}
}
class UserRecords {
private ArrayList<MessageRecord> sendMessageReconds = new ArrayList<MessageRecord>();
private ArrayList<MessageRecord> receiveMessageReconds = new ArrayList<MessageRecord>();
public ArrayList<MessageRecord> getSendMessageReconds() {
return sendMessageReconds;
}
public void addSendMessageReconds(MessageRecord messageRecord) {
sendMessageReconds.add(messageRecord);
}
public ArrayList<MessageRecord> getReceiveMessageReconds() {
return receiveMessageReconds;
}
public void addReceiveMessageReconds(MessageRecord messageRecord) {
receiveMessageReconds.add(messageRecord);
}
}
类图:

三、踩坑心得
这三次计费的训练,和多边形一样,一层一层迭代,只要前面类图编写合理,后面的运用就会非常轻松。要理解给定类图,并编写代码。要保持高质量的正则表达式,对方法的书写也要合理,保证代码可扩展性
四、改进建议
由于已经给定了类图,对于类图的设计并无需要改进的地方,但是题目中的一些测试点还是不太理解,有些情况并未完善,有待完善
浙公网安备 33010602011771号