目录
第三次博客 电信计费
一、前言
这几次大作业的目的是实现电信计费,使用多态的方式,用户可以是座机、手机,座机和手机可以进行通话,并且手机可以发送短信,在不同的地区使用不同的方式拨打电话的计费方式不同,手机发送短信根据信息的长短有不同的计费方式。总体来说,这几次大作业的难度较大,但是老师给出了类图,我们只需要根据类图完成相应的方法即可。每一次大作业都是有关联的,下一次大作业是在上一次的大作业的基础上进行略微的修改,并增加相应的功能,因此题量相对于之前的多边形的计算更少一些。
二、设计与分析
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元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。
错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
题目给出的类图如下:
图中User是用户类,包括属性:
userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。
ChargeMode是计费方式的抽象类:
chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。
getMonthlyRent()方法用于返回月租(monthlyRent)。
UserRecords是用户记录类,保存用户各种通话、短信的记录,
各种计费规则将使用其中的部分或者全部记录。
其属性从上到下依次是:
市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、
市内接听电话、省内(不含市内)接听电话、省外接听电话的记录
以及发送短信、接收短信的记录。
图中CommunicationRecord是抽象的通讯记录类:
包含callingNumber拨打号码、answerNumber接听号码两个属性。
CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。
CallRecord(通话记录类)包含属性:
通话的起始、结束时间以及
拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。
区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。
上图是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。
代码如下(点击展开)
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class Main {
public static void main(String[] args) throws ParseException {
ArrayList<user> users=new ArrayList<>();
Solve solve=new Solve();
Scanner input=new Scanner(System.in);
String s=input.nextLine();
while(!s.equals("end")){
if(s.length()!=0){
int cout= Solve.problem(s);
if(cout==1){
user us=null;
String[] s0=s.substring(2).split(" ");
for(user i:users){
if(i.getNumber().equals(s0[0])){
us=i;
}
}
if(us==null){
user user1=new user();
user1.setNumber(s0[0]);
if(s0[1].equals("0")){
user1.setChargeMode(new LandlinePhoneCharging());
}
users.add(user1);
}
}
else if(cout==2){
String[] s0=s.substring(2).split(" ");
solve.input_callRecond(users,s0);
}
}
s=input.nextLine();
}
Collections.sort(users,new MyComparator());
for(user i:users){
System.out.println(i.getNumber()+" "+sishewuru_2(i.calCost())+" "+sishewuru_2(i.calBalance()));
}
}
public static double sishewuru_2(double x){
String str = String.format("%.2f",x);
Double s = Double.parseDouble(str);
return s;
}
}
class MyComparator implements Comparator<user>{
@Override
public int compare(user o1, user o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
}
class Solve{
public static int problem(String s){
char s0=s.charAt(0);
String s1=s.substring(1);
if(s0=='u'){
if(format_u(s1)){
return 1;
}
}
else if(s0=='t'){
if(format_t(s1)){
return 2;
}
}
return 0;
}
public void input_callRecond(ArrayList<user> users, String[] s) throws ParseException {
if(s[0].equals(s[1])){
return;
}
CallRecord c=new CallRecord();
SimpleDateFormat formatter=new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
user call=null;
int callf,answerf;
c.setCallingNumber(s[0]);
c.setAnswerNumber(s[1]);
Date startTime=formatter.parse(s[2]+" "+s[3]);
Date endTime=formatter.parse(s[4]+" "+s[5]);
c.setCallingAddressAreaCode(s[0].substring(0,4));
c.setAnswerAddressAreaCode(s[1].substring(0,4));
c.setStartTime(startTime);
c.setEndTime(endTime);
for(user i:users){
if(i.getNumber().equals(c.getCallingNumber())){
call=i;
}
}
callf=City_Province_Land(c.getCallingAddressAreaCode());
answerf=City_Province_Land(c.getAnswerAddressAreaCode());
if(call!=null){
if(callf==answerf){
call.getUserRecords().addCallingInCityRecords(c);
}
else if(callf==0&&answerf==1||callf==1&&answerf==0){
call.getUserRecords().addCallingInProvinceRecords(c);
}
else{
call.getUserRecords().addCallingInLandRecords(c);
}
}
}
public static long lengthofTime(Date startTime,Date endTime){
long minute,second;
second = (endTime.getTime()-startTime.getTime())/1000;
if(second%60==0){
return second/60;
}
else return second/60+1;
}
public static int City_Province_Land(String Area){
if(Area.matches("^0791")){
return 0;
}
else if(Area.matches("^079[0-9]|0701")){
return 1;
}
else return 2;
}
public static boolean zuoji(String s){
return s.matches("^0[0-9]{9,11}");
}
public static boolean riqi(String s){
String[] s0=s.split("\\.");
if(s0.length==3){
if(s0[0].matches("^[0-9]{4}")&&s0[1].matches("^([1-9])|(1[0-2])")){
if(s0[1].matches("^([13578]|1[02])")){
return s0[2].matches("^[1-2][0-9]|[1-9]|3[01]");
}
else if(s0[1].matches("^[469]|11")){
return s0[2].matches("^[1-2][0-9]|[1-9]|30");
}
else if(s0[1].matches("^2")){
int nian=Integer.parseInt(s0[0]);
if(nian%4==0){
return s0[2].matches("^[1-2][0-9]|[0-9]");
}
else{
return s0[2].matches("^1[0-9]|[0-9]|2[0-8]");
}
}
}
}
return false;
}
public static boolean shijian(String s){
String[] s0=s.split(":");
if(s0.length==3){
if(s0[0].matches("^[0-1][0-9]|2[0-3]")){
if(s0[1].matches("^[0-5][0-9]")){
return s0[2].matches("^[0-5][0-9]");
}
}
}
return false;
}
public static boolean format_u(String s){
String[] s0=s.split(" ");
if(s0.length==2){
String s1=s0[0].substring(1);
return s0[0].charAt(0) == '-' && zuoji(s1) && s0[1].matches("^0") && s1.matches("^0791[0-9]{7,8}");
}
return false;
}
public static boolean format_t(String s){
String[] s0=s.split(" ");
if(s0.length==6){
String s1=s0[0].substring(1);
if(s0[0].charAt(0)=='-'&&zuoji(s1)&&zuoji(s0[1])&&riqi(s0[2])&&shijian(s0[3])&&riqi(s0[4])&&shijian(s0[5])){
return true;
}
}
return false;
}
}
abstract class CallChargeRule extends ChargeRule{
}
class CallRecord extends CommunicationRecord{
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String answerAddressAreaCode;
public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
this.answerAddressAreaCode = answerAddressAreaCode;
}
public void setCallingAddressAreaCode(String callingAddressAreaCode) {
this.callingAddressAreaCode = callingAddressAreaCode;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public Date getStartTime() {
return startTime;
}
public String getAnswerAddressAreaCode() {
return answerAddressAreaCode;
}
public String getCallingAddressAreaCode() {
return callingAddressAreaCode;
}
}
abstract class ChargeMode {
protected ArrayList<ChargeRule> chargeRules=new ArrayList<ChargeRule>();
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}
abstract double calCost(UserRecords userRecords);
abstract double getMonthlyRent();
}
abstract class ChargeRule {
abstract public double calCost(UserRecords userRecords);
}
abstract class CommunicationRecord {
private String callingNumber;
private String answerNumber;
public void setAnswerNumber(String answerNumber) {
this.answerNumber = answerNumber;
}
public String getAnswerNumber() {
return answerNumber;
}
public void setCallingNumber(String callingNumber) {
this.callingNumber = callingNumber;
}
public String getCallingNumber() {
return callingNumber;
}
}
class LandlinePhoneCharging extends ChargeMode{
private double monthlyRent=20;
public LandlinePhoneCharging(){
super();
getChargeRules().add(new LandPhoneInCityRule());
getChargeRules().add(new LandPhoneInProvinceRule());
getChargeRules().add(new LandPhoneInlandRule());
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
@Override
public double calCost(UserRecords userRecords) {
double ans=0;
for(ChargeRule i:getChargeRules()){
ans+=i.calCost(userRecords);
}
return ans;
}
}
class LandPhoneInCityRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInCityRecords()){
long minute=Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.1);
}
return res;
}
}
class LandPhoneInlandRule extends CallChargeRule{
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInLandRecords()){
long minute=Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.6);
}
return res;
}
}
class LandPhoneInProvinceRule extends CallChargeRule{
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInProvinceRecords()){
long minute=Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.3);
}
return res;
}
}
class MessageRecond extends CommunicationRecord {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class user {
private UserRecords userRecords=new UserRecords();
private double balance=100;
private ChargeMode chargeMode;
private String number;
public double calBalance(){
return balance-calCost()-chargeMode.getMonthlyRent();
}
public double calCost(){
return chargeMode.calCost(userRecords);
}
public double getBalance() {
return balance;
}
public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode = chargeMode;
}
public ChargeMode getChargeMode() {
return chargeMode;
}
public void setNumber(String number) {
this.number = number;
}
public String getNumber() {
return number;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public UserRecords getUserRecords() {
return userRecords;
}
}
class UserRecords {
private ArrayList<CallRecord>callingInCityRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>callingInProvinceRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>callingInLandRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInCityRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInProvinceRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInLandRecords=new ArrayList<CallRecord>();
private ArrayList<MessageRecond>sendMessageRecords=new ArrayList<MessageRecond>();
private ArrayList<MessageRecond>receiveMessageRecords=new ArrayList<MessageRecond>();
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 answerRecord){
answerInCityRecords.add(answerRecord);
}
public void addAnswerInProvinceRecords(CallRecord answerRecord){
answerInProvinceRecords.add(answerRecord);
}
public void addAnswerInLandRecords(CallRecord answerRecord){
answerInLandRecords.add(answerRecord);
}
public void addSendMessageRecords(MessageRecond sendMessageRecord){
sendMessageRecords.add(sendMessageRecord);
}
public void addReceiveMessageRecords(MessageRecond receiveMessageRecord){
receiveMessageRecords.add(receiveMessageRecord);
}
public ArrayList<CallRecord> getAnswerInCityRecords() {
return answerInCityRecords;
}
public ArrayList<CallRecord> getAnswerInLandRecords() {
return answerInLandRecords;
}
public ArrayList<CallRecord> getAnswerInProvinceRecords() {
return answerInProvinceRecords;
}
public ArrayList<CallRecord> getCallingInCityRecords() {
return callingInCityRecords;
}
public ArrayList<CallRecord> getCallingInLandRecords() {
return callingInLandRecords;
}
public ArrayList<CallRecord> getCallingInProvinceRecords() {
return callingInProvinceRecords;
}
public ArrayList<MessageRecond> getReceiveMessageRecords() {
return receiveMessageRecords;
}
public ArrayList<MessageRecond> getSendMessageRecords() {
return sendMessageRecords;
}
}
思路总结
解决问题先考虑解决问题的架构,这次大作业我们只需要根据题目给出的类图依次实现。首先对输入的数据进行判断,建立用户返回1,用户打电话返回2,对数据的处理返回大于2即可说明数据输入错误,丢弃数据不对其进行处理,当返回1时,需要比较该用户是否已经注册,如果没有注册就加入列表中,否则不处理,当返回2时,需要讲该数据根据号码加入到电话列表;当输入end结束,根据号码进行排序输出本月的话费以及余额。数据错误的情况是座机号码不对,因为我国的地区号可能为3位或4位,因此座机号码的长度为10到12,而不是11到12,(这个点如果不清楚会卡住);在加入电话列表时,需要判断打电话和接电话所在区域,可分为市内、省内、国内,根据区域号进行判断加入到不同的列表中,计算话费时,根据列表中的信息进行计算。
类图如下:
代码复杂度分析:
改进建议
此题的结构是根据该类问题最终的结构所设计的,因此有些类没有使用到!
2.第七次大作业
电信计费系列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
代码如下(点击展开)
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class Main {
public static void main(String[] args) throws ParseException {
ArrayList<user> users=new ArrayList<>();
Solve solve=new Solve();
Scanner input=new Scanner(System.in);
String s=input.nextLine();
while(!s.equals("end")){
if(s.length()!=0){
int cout= Solve.problem(s);
if(cout==1||cout==2){
user us=null;
String[] s0=s.substring(2).split(" ");
for(user i:users){
if(i.getNumber().equals(s0[0])){
us=i;
}
}
if(us==null){
user user1=new user();
user1.setNumber(s0[0]);
if(s0[1].equals("0")){
user1.setChargeMode(new LandlinePhoneCharging());
}
else if(s0[1].equals("1")){
user1.setChargeMode(new MobellinePhoneCharging());
}
users.add(user1);
}
}
else if(cout>2){
String[] s0=s.substring(2).split(" ");
solve.input_callRecond(users,s0,cout);
}
}
s=input.nextLine();
}
users.sort(new MyComparator());
for(user i:users){
System.out.println(i.getNumber()+" "+sishewuru_2(i.calCost())+" "+sishewuru_2(i.calBalance()));
}
}
public static double sishewuru_2(double x){
String str = String.format("%.2f",x);
return Double.parseDouble(str);
}
}
class MyComparator implements Comparator<user>{
@Override
public int compare(user o1, user o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
}
class Solve{
public static int problem(String s){
char s0=s.charAt(0);
String s1=s.substring(1);
if(s0=='u'){
return format_u(s1);
}
else if(s0=='t'){
return format_t(s1);
}
return 0;
}
public void input_callRecond(ArrayList<user> users, String[] s,int choice) throws ParseException {
if(s[0].equals(s[1])){
return;
}
CallRecord c=new CallRecord();
SimpleDateFormat formatter=new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
user call=null,answer=null;
int callf,answerf;
if(choice==3){
c.setCallingNumber(s[0]);
c.setAnswerNumber(s[1]);
Date startTime=formatter.parse(s[2]+" "+s[3]);
Date endTime=formatter.parse(s[4]+" "+s[5]);
c.setCallingAddressAreaCode(s[0].substring(0,4));
c.setAnswerAddressAreaCode(s[1].substring(0,4));
c.setStartTime(startTime);
c.setEndTime(endTime);
}
else if(choice==4){
c.setCallingNumber(s[0]);
c.setAnswerNumber(s[1]);
Date startTime=formatter.parse(s[3]+" "+s[4]);
Date endTime=formatter.parse(s[5]+" "+s[6]);
c.setCallingAddressAreaCode(s[0].substring(0,4));
c.setAnswerAddressAreaCode(s[2]);
c.setStartTime(startTime);
c.setEndTime(endTime);
}
else if(choice==5){
c.setCallingNumber(s[0]);
c.setAnswerNumber(s[2]);
Date startTime=formatter.parse(s[3]+" "+s[4]);
Date endTime=formatter.parse(s[5]+" "+s[6]);
c.setCallingAddressAreaCode(s[1]);
c.setAnswerAddressAreaCode(s[2].substring(0,4));
c.setStartTime(startTime);
c.setEndTime(endTime);
}
else if(choice==6){
c.setCallingNumber(s[0]);
c.setAnswerNumber(s[2]);
Date startTime=formatter.parse(s[4]+" "+s[5]);
Date endTime=formatter.parse(s[6]+" "+s[7]);
c.setCallingAddressAreaCode(s[1]);
c.setAnswerAddressAreaCode(s[3]);
c.setStartTime(startTime);
c.setEndTime(endTime);
}
for(user i:users){
if(i.getNumber().equals(c.getCallingNumber())){
call=i;
}
if(i.getNumber().equals(c.getAnswerNumber())){
answer=i;
}
}
callf=City_Province_Land(c.getCallingAddressAreaCode());
answerf=City_Province_Land(c.getAnswerAddressAreaCode());
if(call!=null){
if(callf==0){
call.getUserRecords().addCallingInCityRecords(c);
}
else if(callf==1){
call.getUserRecords().addCallingInProvinceRecords(c);
}
else{
call.getUserRecords().addCallingInLandRecords(c);
}
}
if(answer!=null){
if(answerf==0){
answer.getUserRecords().addAnswerInCityRecords(c);
}
else if(answerf==1){
answer.getUserRecords().addAnswerInProvinceRecords(c);
}
else{
answer.getUserRecords().addAnswerInLandRecords(c);
}
}
}
public static long lengthofTime(Date startTime,Date endTime){
long minute,second;
second = (endTime.getTime()-startTime.getTime())/1000;
if(second%60==0){
return second/60;
}
else return second/60+1;
}
public static int City_Province_Land(String Area){
if(Area.matches("^0791")){
return 0;
}
else if(Area.matches("^079[0-9]|0701")){
return 1;
}
else return 2;
}
public static boolean zuoji(String s){
return s.matches("^0[0-9]{9,11}");
}
public static boolean areaCode(String s){
return s.matches("0[0-9]{2,3}");
}
public static boolean mobelPhone(String s){
return s.matches("^1[0-9]{10}");
}
public static boolean riqi(String s){
String[] s0=s.split("\\.");
if(s0.length==3){
if(s0[0].matches("^[0-9]{4}")&&s0[1].matches("^([1-9])|(1[0-2])")){
if(s0[1].matches("^([13578]|1[02])")){
return s0[2].matches("^[1-2][0-9]|[1-9]|3[01]");
}
else if(s0[1].matches("^[469]|11")){
return s0[2].matches("^[1-2][0-9]|[1-9]|30");
}
else if(s0[1].matches("^2")){
int nian=Integer.parseInt(s0[0]);
if(nian%4==0){
return s0[2].matches("^[1-2][0-9]|[0-9]");
}
else{
return s0[2].matches("^1[0-9]|[0-9]|2[0-8]");
}
}
}
}
return false;
}
public static boolean shijian(String s){
String[] s0=s.split(":");
if(s0.length==3){
if(s0[0].matches("^[0-1][0-9]|2[0-3]")){
if(s0[1].matches("^[0-5][0-9]")){
return s0[2].matches("^[0-5][0-9]");
}
}
}
return false;
}
public static int format_u(String s){
String[] s0=s.split(" ");
if(s0.length==2){
String s1=s0[0].substring(1);
if(s0[0].charAt(0) == '-' && zuoji(s1) && s0[1].matches("^0") && s1.matches("^0791[0-9]{7,8}"))
return 1;
else if(s0[0].charAt(0) == '-' && mobelPhone(s1) && s0[1].matches("^1"))
return 2;
}
return 0;
}
public static int format_t(String s){
String[] s0=s.split(" ");
if(s0.length==6){
String s1=s0[0].substring(1);
if(s0[0].charAt(0) == '-' && zuoji(s1) && zuoji(s0[1]) && riqi(s0[2]) && shijian(s0[3]) && riqi(s0[4]) && shijian(s0[5]))
return 3;
}
else if(s0.length==7){
String s1=s0[0].substring(1);
if(s0[0].charAt(0)=='-'&&zuoji(s1)&&mobelPhone(s0[1])&&areaCode(s0[2])&&riqi(s0[3])&&shijian(s0[4])&&riqi(s0[5])&&shijian(s0[6]))
return 4;
else if(s0[0].charAt(0)=='-'&&zuoji(s0[2])&&mobelPhone(s1)&&areaCode(s0[1])&&riqi(s0[3])&&shijian(s0[4])&&riqi(s0[5])&&shijian(s0[6]))
return 5;
}
else if(s0.length==8){
String s1=s0[0].substring(1);
if(s0[0].charAt(0)=='-'&&mobelPhone(s1)&&areaCode(s0[1])&&mobelPhone(s0[2])&&areaCode(s0[3])&&riqi(s0[4])&&shijian(s0[5])&&riqi(s0[6])&&shijian(s0[7]))
return 6;
}
return 0;
}
}
abstract class CallChargeRule extends ChargeRule {
}
class CallRecord extends CommunicationRecord {
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String answerAddressAreaCode;
public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
this.answerAddressAreaCode = answerAddressAreaCode;
}
public void setCallingAddressAreaCode(String callingAddressAreaCode) {
this.callingAddressAreaCode = callingAddressAreaCode;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public Date getStartTime() {
return startTime;
}
public String getAnswerAddressAreaCode() {
return answerAddressAreaCode;
}
public String getCallingAddressAreaCode() {
return callingAddressAreaCode;
}
}
abstract class ChargeMode {
protected ArrayList<ChargeRule> chargeRules=new ArrayList<ChargeRule>();
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}
abstract double calCost(UserRecords userRecords);
abstract double getMonthlyRent();
}
abstract class ChargeRule {
abstract public double calCost(UserRecords userRecords);
}
abstract class CommunicationRecord {
private String callingNumber;
private String answerNumber;
public void setAnswerNumber(String answerNumber) {
this.answerNumber = answerNumber;
}
public String getAnswerNumber() {
return answerNumber;
}
public void setCallingNumber(String callingNumber) {
this.callingNumber = callingNumber;
}
public String getCallingNumber() {
return callingNumber;
}
}
class LandlinePhoneCharging extends ChargeMode {
private double monthlyRent=20;
public LandlinePhoneCharging(){
super();
getChargeRules().add(new LandPhoneInCityRule());
getChargeRules().add(new LandPhoneInProvinceRule());
getChargeRules().add(new LandPhoneInlandRule());
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
@Override
public double calCost(UserRecords userRecords) {
double ans=0;
for(ChargeRule i:getChargeRules()){
ans+=i.calCost(userRecords);
}
return ans;
}
}
class LandPhoneInCityRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInCityRecords()){
long minute= Solve.lengthofTime(i.getStartTime(),i.getEndTime());
int answerf;
answerf=Solve.City_Province_Land(i.getAnswerAddressAreaCode());
if(answerf==0)
res+=(minute*0.1);
else if(answerf==1)
res+=(minute*0.3);
else if(answerf==2)
res+=(minute*0.6);
}
return res;
}
}
class LandPhoneInlandRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInLandRecords()){
long minute= Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.6);
}
return res;
}
}
class LandPhoneInProvinceRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInProvinceRecords()){
long minute= Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.3);
}
return res;
}
}
class MobellinePhoneCharging extends ChargeMode {
private double monthlyRent=15;
public MobellinePhoneCharging(){
super();
getChargeRules().add(new MobelPhoneInCityRule());
getChargeRules().add(new MobelPhoneInProvinceRule());
getChargeRules().add(new MobelPhoneInlandRule());
}
@Override
public double getMonthlyRent() {
return monthlyRent;
}
@Override
public double calCost(UserRecords userRecords) {
double ans=0;
for(ChargeRule i:getChargeRules()){
ans+=i.calCost(userRecords);
}
return ans;
}
}
class MobelPhoneInCityRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInCityRecords()){
long minute= Solve.lengthofTime(i.getStartTime(),i.getEndTime());
int callf,answerf;
callf=Solve.City_Province_Land(i.getCallingAddressAreaCode());
answerf=Solve.City_Province_Land(i.getAnswerAddressAreaCode());
if(callf==0&&answerf==0)
res+=(minute*0.1);
else if(callf==0&&answerf==1){
res+=(minute*0.2);
}
else if(callf==0&&answerf==2){
res+=(minute*0.3);
}
}
return res;
}
}
class MobelPhoneInlandRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInLandRecords()){
long minute= Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.6);
}
for(CallRecord i:userRecords.getAnswerInLandRecords()){
long minute= Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.3);
}
return res;
}
}
class MobelPhoneInProvinceRule extends CallChargeRule {
@Override
public double calCost(UserRecords userRecords) {
double res=0;
for(CallRecord i:userRecords.getCallingInProvinceRecords()){
long minute= Solve.lengthofTime(i.getStartTime(),i.getEndTime());
if(minute>0)
res+=(minute*0.3);
}
return res;
}
}
class MessageRecond extends CommunicationRecord {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class user {
private UserRecords userRecords=new UserRecords();
private double balance=100;
private ChargeMode chargeMode;
private String number;
public double calBalance(){
return balance-calCost()-chargeMode.getMonthlyRent();
}
public double calCost(){
return chargeMode.calCost(userRecords);
}
public double getBalance() {
return balance;
}
public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode = chargeMode;
}
public ChargeMode getChargeMode() {
return chargeMode;
}
public void setNumber(String number) {
this.number = number;
}
public String getNumber() {
return number;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public UserRecords getUserRecords() {
return userRecords;
}
}
class UserRecords {
private ArrayList<CallRecord>callingInCityRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>callingInProvinceRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>callingInLandRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInCityRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInProvinceRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInLandRecords=new ArrayList<CallRecord>();
private ArrayList<MessageRecond>sendMessageRecords=new ArrayList<MessageRecond>();
private ArrayList<MessageRecond>receiveMessageRecords=new ArrayList<MessageRecond>();
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 answerRecord){
answerInCityRecords.add(answerRecord);
}
public void addAnswerInProvinceRecords(CallRecord answerRecord){
answerInProvinceRecords.add(answerRecord);
}
public void addAnswerInLandRecords(CallRecord answerRecord){
answerInLandRecords.add(answerRecord);
}
public void addSendMessageRecords(MessageRecond sendMessageRecord){
sendMessageRecords.add(sendMessageRecord);
}
public void addReceiveMessageRecords(MessageRecond receiveMessageRecord){
receiveMessageRecords.add(receiveMessageRecord);
}
public ArrayList<CallRecord> getAnswerInCityRecords() {
return answerInCityRecords;
}
public ArrayList<CallRecord> getAnswerInLandRecords() {
return answerInLandRecords;
}
public ArrayList<CallRecord> getAnswerInProvinceRecords() {
return answerInProvinceRecords;
}
public ArrayList<CallRecord> getCallingInCityRecords() {
return callingInCityRecords;
}
public ArrayList<CallRecord> getCallingInLandRecords() {
return callingInLandRecords;
}
public ArrayList<CallRecord> getCallingInProvinceRecords() {
return callingInProvinceRecords;
}
public ArrayList<MessageRecond> getReceiveMessageRecords() {
return receiveMessageRecords;
}
public ArrayList<MessageRecond> getSendMessageRecords() {
return sendMessageRecords;
}
}
思路分析
此次大作业是在上一次大作业的基础上进行修改完成的。题目增加了手机用户,因此需要考虑手机号码的判断是否合理,判断通话记录是手机跟手机还是手机跟座机,需要比较输入信息的根据空格分割下来的长度大小,因为如果是手机号码,需要附带区号,而座机号码不需要,因此输入的数据分割长度为6即两个座机号码通信,当长度为7说明有一个座机用户和一个手机用户,还需要详细判断拨打号码是手机还是接听号码是手机,当长度为8时,说明两个号码为手机号码,后面一个字符对应其区号,再根据区号选择该通话记录加入哪个列表中。
类图如下:
代码复杂度分析:
改进建议
此次代码是在上一次作业的基础上修改得到的,代码的复杂度还是比较高,但是对代码的增加比较方便,需要增加某一些功能不需要进行大幅度的修改,老师所设计的类图很好。主函数还应该更简单一些,将解决问题的步骤写入类中。
3.第八次大作业
电信计费系列3-短信计费
实现一个简单的电信计费程序,针对手机的短信采用如下计费方式:
1、接收短信免费,发送短信0.1元/条,超过3条0.2元/条,超过5条0.3元/条。
2、如果一次发送短信的字符数量超过10个,按每10个字符一条短信进行计算。
注意:短信内容只能由数字、字母、空格、英文逗号、英文句号组成,每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
点击展开
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class Main {
public static void main(String[] args) throws ParseException {
ArrayList<user> users=new ArrayList<>();
Solve solve=new Solve();
Scanner input=new Scanner(System.in);
String s=input.nextLine();
while(!s.equals("end")){
if(s.length()!=0){
int cout= Solve.problem(s);
if(cout==1||cout==2){
user us=null;
String[] s0=s.substring(2).split(" ");
for(user i:users){
if(i.getNumber().equals(s0[0])){
us=i;
}
}
if(us==null){
user user1=new user();
user1.setNumber(s0[0]);
if(s0[1].equals("3")){
user1.setChargeMode(new SendMessageCharging());
}
users.add(user1);
}
}
else if(cout == 7){
solve.input_message(users,s);
}
}
s=input.nextLine();
}
users.sort(new MyComparator());
for(user i:users){
System.out.println(i.getNumber()+" "+sishewuru_2(i.calCost())+" "+sishewuru_2(i.calBalance()));
}
}
public static double sishewuru_2(double x){
String str = String.format("%.2f",x);
return Double.parseDouble(str);
}
}
class MyComparator implements Comparator<user>{
@Override
public int compare(user o1, user o2) {
return o1.getNumber().compareTo(o2.getNumber());
}
}
class Solve{
public static int problem(String s){
char s0=s.charAt(0);
String s1=s.substring(1);
if(s0=='u'){
return format_u(s1);
}
else if(s0 == 'm'){
return format_m(s1);
}
return 0;
}
public void input_message(ArrayList<user> users, String s){
user send_user=null;
String sendstr = s.substring(2,13);
String Messages = s.substring(26);
for(user u:users){
if(u.getNumber().equals(sendstr)){
send_user=u;
}
}
MessageRecond mess = new MessageRecond();
mess.setMessage(Messages);
if(send_user!=null){
send_user.getUserRecords().addSendMessageRecords(mess);
}
}
public static long lengthofTime(Date startTime,Date endTime){
long minute,second;
second = (endTime.getTime()-startTime.getTime())/1000;
if(second%60==0){
return second/60;
}
else return second/60+1;
}
public static int City_Province_Land(String Area){
if(Area.matches("^0791")){
return 0;
}
else if(Area.matches("^079[0-9]|0701")){
return 1;
}
else return 2;
}
public static boolean zuoji(String s){
return s.matches("^0[0-9]{9,11}");
}
public static boolean areaCode(String s){
return s.matches("0[0-9]{2,3}");
}
public static boolean mobelPhone(String s){
return s.matches("^1[0-9]{10}");
}
public static boolean message(String s){
return s.matches("[0-9a-zA-Z\\s\\.,]+");
}
public static boolean riqi(String s){
String[] s0=s.split("\\.");
if(s0.length==3){
if(s0[0].matches("^[0-9]{4}")&&s0[1].matches("^([1-9])|(1[0-2])")){
if(s0[1].matches("^([13578]|1[02])")){
return s0[2].matches("^[1-2][0-9]|[1-9]|3[01]");
}
else if(s0[1].matches("^[469]|11")){
return s0[2].matches("^[1-2][0-9]|[1-9]|30");
}
else if(s0[1].matches("^2")){
int nian=Integer.parseInt(s0[0]);
if(nian%4==0){
return s0[2].matches("^[1-2][0-9]|[0-9]");
}
else{
return s0[2].matches("^1[0-9]|[0-9]|2[0-8]");
}
}
}
}
return false;
}
public static boolean shijian(String s){
String[] s0=s.split(":");
if(s0.length==3){
if(s0[0].matches("^[0-1][0-9]|2[0-3]")){
if(s0[1].matches("^[0-5][0-9]")){
return s0[2].matches("^[0-5][0-9]");
}
}
}
return false;
}
public static int format_u(String s){
String[] s0=s.split(" ");
if(s0.length==2){
String s1=s0[0].substring(1);
if(s0[0].charAt(0) == '-' && zuoji(s1) && s0[1].matches("^0") && s1.matches("^0791[0-9]{7,8}"))
return 1;
else if(s0[0].charAt(0) == '-' && mobelPhone(s1) && s0[1].matches("^[13]"))
return 2;
}
return 0;
}
public static int format_m(String s){
String send = s.substring(1, 12);
String recstr = s.substring(13, 24);
String messages = s.substring(25);
if(s.charAt(0)=='-'&&mobelPhone(send)&&mobelPhone(recstr)){
if(message(messages)){
return 7;
}
}
return 0;
}
}
abstract class CallChargeRule extends ChargeRule {
}
class CallRecord extends CommunicationRecord {
private Date startTime;
private Date endTime;
private String callingAddressAreaCode;
private String answerAddressAreaCode;
public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
this.answerAddressAreaCode = answerAddressAreaCode;
}
public void setCallingAddressAreaCode(String callingAddressAreaCode) {
this.callingAddressAreaCode = callingAddressAreaCode;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
public Date getEndTime() {
return endTime;
}
public Date getStartTime() {
return startTime;
}
public String getAnswerAddressAreaCode() {
return answerAddressAreaCode;
}
public String getCallingAddressAreaCode() {
return callingAddressAreaCode;
}
}
abstract class ChargeMode {
protected ArrayList<ChargeRule> chargeRules=new ArrayList<ChargeRule>();
public ArrayList<ChargeRule> getChargeRules() {
return chargeRules;
}
public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
this.chargeRules = chargeRules;
}
abstract double calCost(UserRecords userRecords);
abstract double getMonthlyRent();
}
abstract class ChargeRule {
abstract public double calCost(UserRecords userRecords);
}
abstract class CommunicationRecord {
private String callingNumber;
private String answerNumber;
public void setAnswerNumber(String answerNumber) {
this.answerNumber = answerNumber;
}
public String getAnswerNumber() {
return answerNumber;
}
public void setCallingNumber(String callingNumber) {
this.callingNumber = callingNumber;
}
public String getCallingNumber() {
return callingNumber;
}
}
class MessageRecond extends CommunicationRecord {
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
class SendMessageCharging extends ChargeMode{
private double monthlyRent = 0;
public SendMessageCharging(){
super();
chargeRules.add(new SendMessageRule());
}
@Override
double calCost(UserRecords userRecords) {
double sum_cost = 0;
for(ChargeRule i:chargeRules){
sum_cost += i.calCost(userRecords);
}
return sum_cost;
}
@Override
double getMonthlyRent() {
return monthlyRent;
}
}
class SendMessageRule extends CallChargeRule{
@Override
public double calCost(UserRecords userRecords) {
double sum = 0;
int num = 0;
for(MessageRecond m:userRecords.getSendMessageRecords()){
int len = m.getMessage().length();
if(len <= 10){
num ++;
}
else{
num += len/10;
if(len % 10 != 0){
num ++;
}
}
}
if(num <= 3){
sum = num*0.1;
}
else if(num <= 5){
sum = 0.3 + (num - 3) * 0.2;
}
else {
sum = 0.7 + (num - 5) * 0.3;
}
return sum;
}
}
class user {
private UserRecords userRecords=new UserRecords();
private double balance=100;
private ChargeMode chargeMode;
private String number;
public double calBalance(){
return balance-calCost()-chargeMode.getMonthlyRent();
}
public double calCost(){
return chargeMode.calCost(userRecords);
}
public double getBalance() {
return balance;
}
public void setChargeMode(ChargeMode chargeMode) {
this.chargeMode = chargeMode;
}
public ChargeMode getChargeMode() {
return chargeMode;
}
public void setNumber(String number) {
this.number = number;
}
public String getNumber() {
return number;
}
public void setUserRecords(UserRecords userRecords) {
this.userRecords = userRecords;
}
public UserRecords getUserRecords() {
return userRecords;
}
}
class UserRecords {
private ArrayList<CallRecord>callingInCityRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>callingInProvinceRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>callingInLandRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInCityRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInProvinceRecords=new ArrayList<CallRecord>();
private ArrayList<CallRecord>answerInLandRecords=new ArrayList<CallRecord>();
private ArrayList<MessageRecond>sendMessageRecords=new ArrayList<MessageRecond>();
private ArrayList<MessageRecond>receiveMessageRecords=new ArrayList<MessageRecond>();
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 answerRecord){
answerInCityRecords.add(answerRecord);
}
public void addAnswerInProvinceRecords(CallRecord answerRecord){
answerInProvinceRecords.add(answerRecord);
}
public void addAnswerInLandRecords(CallRecord answerRecord){
answerInLandRecords.add(answerRecord);
}
public void addSendMessageRecords(MessageRecond sendMessageRecord){
sendMessageRecords.add(sendMessageRecord);
}
public void addReceiveMessageRecords(MessageRecond receiveMessageRecord){
receiveMessageRecords.add(receiveMessageRecord);
}
public ArrayList<CallRecord> getAnswerInCityRecords() {
return answerInCityRecords;
}
public ArrayList<CallRecord> getAnswerInLandRecords() {
return answerInLandRecords;
}
public ArrayList<CallRecord> getAnswerInProvinceRecords() {
return answerInProvinceRecords;
}
public ArrayList<CallRecord> getCallingInCityRecords() {
return callingInCityRecords;
}
public ArrayList<CallRecord> getCallingInLandRecords() {
return callingInLandRecords;
}
public ArrayList<CallRecord> getCallingInProvinceRecords() {
return callingInProvinceRecords;
}
public ArrayList<MessageRecond> getReceiveMessageRecords() {
return receiveMessageRecords;
}
public ArrayList<MessageRecond> getSendMessageRecords() {
return sendMessageRecords;
}
}
思路分析
此次大作业是在上一次大作业的基础上,增加用户的操作--发送短信。在上一次大作业的基础上,需要在数据判断的方法中增加判断该数据是否为发送短信,并且对于短信的内容我们不需要进行处理,只需要在计算话费时,统计短信的条数,以及短信内容的长度,再计算话费的多少。
类图如下:
代码复杂度分析:
改进建议
此次大作业是在上一次的基础上增加方法实现,但是代码的长度超过了pta设置的长度范围,因此我把有些不需要的方法删除了!对于短信的内容不能使用split根据空格分割,因为如果有两个空格连在一起,会出现非零返回。
三、总结
这三次大作业,让我明白了结构的重要性,解决问题要先考虑解决思路,并将问题分块解决,一个好的结构能够大大提高代码的复用性。这三次大作业循序渐进,大作业是在上一次的基础上经过略微的修改和增加,即可实现需要增加的功能,而不需要重构。这几次大作业涉及到了多态,多态的实现是java的特点,同一个接口,有多种不同的实现方式,一个接口有多种不同的状态,方便了代码的书写,提高了代码的复用性。通过这几次大作业,我明白了我还需要改变解决问题的方式,先构思,将问题分块处理,依次实现某一部分的功能,对于java的多态、继承、接口等方法还需要多加练习,提高对这些方法的理解!
标签:return,String,ArrayList,s0,博客,new,public,第三次 From: https://www.cnblogs.com/MaiCo20207124/p/16968914.html