nchu-software-oop-2022第6-8次作业(电信计费)总结

一、前言

       最后三次大作业主要围绕电信计费相关计算展开。难度和之前点线形系列相比降了好几个档次,即便还是有难调的地方。考点仍然是类、继承与多态,还有java容器的使用。作为java巨型作业,这几次虽然在计算量上降了难度,但在细节上还是层层加码滴。三道电信计费大题都给了类图作为参考,很明显,照着类图写还是能方便很多的,但不知世事险恶的我第一题还是用自己的方法写的,那几个被半天调不出来的代码搞崩心态的夜晚简直劝退。好在最后还是圆满完成了作业。除了电信计费还有其它一些简单题,分分钟写完的那种,本次博客还是浅浅提一下。好,话不多说,咱直接开始吧!

二、设计与分析

电信计费部分

题目

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

实现一个简单的电信计费程序:
假设南昌市电信分公司针对市内座机用户采用的计费方式:
月租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元。
每条通讯信息单独计费后累加,不是将所有时间累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。

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

输入样例:

在这里给出一组输入。例如:

u-079186300001 0
t-079186300001 058686330022 2022.1.3 10:00:25 2022.1.3 10:05:25
end

输出样例:

在这里给出相应的输出。例如:

079186300001 3.0 77.0

电信计费系列第一题,自己的方法写的

先把类图祭上

 没有任何继承关系,当时还没这个概念。

Customer(客户类):原本想用来存客户信息,可惜后来没有用到

Time(时间类):储存时间信息,不会用date类型变量时想出的笨方法

TimeOperation(时间格式判断、计算类):

时间计算:研究了老久的计算方法,把所有时间转化为毫秒对就这么直接,然后后面减去前面。

 

时间判断就不贴了,无非是一天有几个小时、一个月有几天这样的判断。

Locate(地点判断类):按题意写就行

 FormatCheck类:主要是输入格式正则表达式的格式判断。

 剩下就没啥了。。

sourceMonitor分析:

复杂度果然有亿点高,,深度还行。

代码:

import java.text.SimpleDateFormat;
import java.text.*;
import java.util.*;
import java.lang.*;
import java.util.regex.*;
public class Main{
    public static void main(String[] args){
        Scanner bjsn = new Scanner(System.in);
        FormatCheck formatCheck = new FormatCheck();
        Customer customer = new Customer();
        TimeOperation timeOperation = new TimeOperation();
        HashMap<String,Double>map = new HashMap<>();
        LinkedHashSet<String>set = new LinkedHashSet<>();
        Locate locate = new Locate();
        String[] userNote = new String[102];
        String[] callNote = new String[102];
        String s;
        int loc = 0;
        while(true){
            s = bjsn.nextLine();
            if(s.equals("end")){
                break;
            }
            if(s.length()==0||!formatCheck.isCheck(s)){
                continue;
            }
            if(s.matches("u-\\d{10,12} 0")){
                String t="";
                for(int i=2;s.charAt(i)!=' ';i++){
                    t+=s.charAt(i);
                }
                if(!map.containsKey(t)){
                    set.add(t);
                    map.put(t,0.0);
                }
            }
            else{
                callNote[loc++] = s;
            }
        }
        int ans = 0;
        while(ans < loc){
            Time[] tt = formatCheck.getTimeInfo(callNote[ans]);
            String[] ss = formatCheck.getTelephoneNum(callNote[ans]);
            Time t1 = tt[0];
            Time t2 = tt[1];
            if(!timeOperation.isTimeCorrect(t1)||!timeOperation.isTimeCorrect(t2)||ss[0].length()<10||ss[0].length()>12||ss[1].length()<10||ss[1].length()>12){
                ans++;
                continue;
            }
            String sta = tt[0].staString+" "+tt[0].endString;
            String end = tt[1].staString+" "+tt[1].endString;
            long t = timeOperation.timeCalc(sta,end);
            if(!map.containsKey(ss[0])||t<=0){
                ans++;
                continue;
            }
            double tm=map.get(ss[0]);
            if(locate.isIn(ss[0],ss[1])==1){
                tm+=0.1*t;
            }
            else if(locate.isIn(ss[0],ss[1])==0){
                tm+=0.3*t;
            }
            else{
                tm+=0.6*t;
            }
            map.put(ss[0],tm);
            ans++;
        }
        String[] res = new String[set.size()];
        int pos=0;
        for(String tt:set){
            res[pos++]=tt;
        }
        Arrays.sort(res);
        for(int i = 0; i < set.size() ;i++){
            double tip = map.get(res[i]);
            System.out.print(res[i]+" ");
            System.out.println((float)tip+" "+(float)Math.max(80 - tip,0));
        }
    }
}
class Customer{
    String telephoneNumber;
    int userType;
    long callTime;
}
class FormatCheck{
    boolean isCheck(String s){
        String su = "u-\\d{11,12} 0";
        String st="t-\\d{11,12} \\d{10,12} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2}";
        if(s.matches(su)||s.matches(st)){
            return true;
        }
        return false;
    }
    Time[] getTimeInfo(String s){
        Time[] res = new Time[2];
        List<String>list = new ArrayList<>();
        String regex = "\\d{4}.\\d{1,2}.\\d{1,2} \\d{2}:\\d{2}:\\d{2}";
        Pattern p = Pattern.compile(regex);
        Matcher matcher = p.matcher(s);
        while (matcher.find()) {
            list.add(matcher.group(0));
        }
        String s1 = list.get(0);
        String s2 = list.get(1);
        String ss1[] = s1.split(" ");
        String ss2[] = s2.split(" ");
        String str1[] = null;
        String str2[] = null;
        String str3[] = null;
        String str4[] = null;
        int t=0;
        for(String Str:ss1){
            t++;
            if(t==1){
                str1 = Str.split("\\.");
            }
            else{
                str2 = Str.split(":");
            }
        }
        t=0;
        for(String Str:ss2){
            t++;
            if(t==1){
                str3 = Str.split("\\.");
            }
            else{
                str4 = Str.split(":");
            }
        }
        long yyyy1=Long.parseLong(str1[0]);
        long mm1=Long.parseLong(str1[1]);
        long dd1=Long.parseLong(str1[2]);
        long hour1=Long.parseLong(str2[0]);
        long minute1=Long.parseLong(str2[1]);
        long second1=Long.parseLong(str2[2]);
        long yyyy2=Long.parseLong(str3[0]);
        long mm2=Long.parseLong(str3[1]);
        long dd2=Long.parseLong(str3[2]);
        long hour2=Long.parseLong(str4[0]);
        long minute2=Long.parseLong(str4[1]);
        long second2=Long.parseLong(str4[2]);
        res[0] = new Time(yyyy1,mm1,dd1,hour1,minute1,second1,ss1[0],ss1[1]);
        res[1] = new Time(yyyy2,mm2,dd2,hour2,minute2,second2,ss2[0],ss2[1]);
        return res;
    }
    String[] getTelephoneNum(String s){
        String[] res = new String[2];
        res[0]="";
        res[1]="";
        int i=2;
        for(i=2;s.charAt(i)!=' ';i++){
            res[0]+=s.charAt(i);
        }
        i++;
        for(;s.charAt(i)!=' ';i++){
            res[1]+=s.charAt(i);
        }
        return res;
    }
}
class Time{
    long yyyy,mm,dd,hour,minute,second;
    String staString,endString;
    public Time(long yyyy,long mm,long dd,long hour,long minute,long second,String staString,String endString){
        this.yyyy=yyyy;
        this.mm=mm;
        this.dd=dd;
        this.hour=hour;
        this.minute=minute;
        this.second=second;
        this.staString=staString;
        this.endString=endString;
    }
}
class TimeOperation{
    long timeCalc(String str1,String str2){
        if(str1.charAt(5)=='0'||str2.charAt(5)=='0'){
            return -1;
        }
        SimpleDateFormat pattern = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        long nd=1000*60*60*24;
        long nh=1000*60*60;
        long nm=1000*60;
        long ns=1000;
        long t=0;
        try{
            t=pattern.parse(str2).getTime()-pattern.parse(str1).getTime();
        }catch (Exception e){
            e.printStackTrace();
        }
        if(t<=0){
            return -1;
        }
        long dayNum=t/nd;
        long hourNum=t%nd/nh;
        long minuteNum=t%nd%nh/nm;
        long secondNum=t%nd%nh%nm/ns;
        long res=secondNum+minuteNum*60+hourNum*60*60+dayNum*60*60*24;
        long cnt=(res+59)/60;
        return cnt;
    }
    boolean isRn(long y){
        if((y%4==0&&y%100!=0)||y%400==0){
            return true;
        }
        return false;
    }
    boolean isTimeCorrect(Time startTime){
        if(startTime.mm<1||startTime.mm>12||startTime.dd<1||startTime.hour<0||startTime.hour>23||startTime.minute<0||startTime.minute>59||startTime.second<0||startTime.second>59){
            return false;
        }
        switch ((int)startTime.mm) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                if (startTime.dd > 31) return false;
                break;
            case 2:
                if (isRn(startTime.yyyy)) {
                    if (startTime.dd > 29) {
                        return false;
                    }
                } else {
                    if (startTime.dd > 28) {
                        return false;
                    }
                }
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if(startTime.dd>30){
                    return false;
                }
                break;
            default:
                break;
        }
        return true;
    }
}
class Locate{
    int isIn(String s1,String s2){
        String ss1=s1.substring(0,4);
        String ss2=s2.substring(0,4);
        if(ss1.equals(ss2)){
            return 1;
        }
        else if((ss2.substring(0,3).equals("079")||ss2.equals("0701"))&&(ss1.substring(0,3).equals("079")||ss1.equals("0701"))){
            return 0;
        }
        else{
            return -1;
        }
    }
}
View Code

 

电信计费系列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、2、3:

image.png
图1

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

image.png

图2

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

image.png
图3

图3是计费规则的相关类,这些类的核心方法是:
calCost(ArrayList<CallRecord> callRecords)。
该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。
输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。
SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。
LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。    

(提示:可以从UserRecords类中获取各种类型的callRecords)。
注意:以上图中所定义的类不是限定要求,根据实际需要自行补充或修改。

输入样例:

在这里给出一组输入。例如:

u-13811111111 1
t-13811111111 0791 13811111110 020 2022.1.3 08:00:00 2022.1.3 08:09:20
end

输出样例:

在这里给出相应的输出。例如:

13811111111 3.0 82.0

先把类图祭上:

 题目中类图一给,接下来就是看图写话。

Check类:判断输入是否符合要求,isValidDay判断日期,isVaildTime判断时间,isLeapYear判断是否闰年。

User类:用户信息类:主要包含如下信息:

userRecords存用户消费记录,chargeMode指消费模式,number为用户电话号码。函数部分主要为几个变量的修改和获取。

UserRecords类:用户消费记录,用arraylist容器储存通话信息。同样,函数部分修改或获取变量信息。

 

CommunicationRecord:通话记录类,callRecord以及下一题的sendMessageRecord继承。

CallRecord类:用于获取通话时间、通话双方所在位置。

 

ChargeRule类:缴费方式

 

CallChargeRule类:继承chargeRule类,指明缴费方案,计算由其继承者实现。

时间计算:

费用计算:

ChargeMode类:缴费形式,分座机缴费、手机缴费,以及市内、省内、国内计费。

正则表达式判断:

String patternStaStr = "u-0\\d{9,11}\\s0";
String patternStStr = "u-1\\d{10}\\s[12]";
String phoneToPhone = "t-0\\d{9,11}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
String phoneToMobile = "t-0\\d{9,11}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
String mobileToPhone = "t-1\\d{10}\\s0\\d{2,3}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
String mobileToMobile = "t-1\\d{10}\\s0\\d{2,3}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
String divideStr = "-|\\s";
String inProvince = "(079\\d|0701)";

sourceMonitor分析:

 

兄啊怎么最大复杂度这么高平均复杂度还是降了不少(喜)。

代码:

import java.lang.*;
import java.text.*;
import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner bjsn = new Scanner(System.in);
        Check check = new Check();
//        ArrayList<User>user = new ArrayList<>();
        Map<String,User>mp = new TreeMap<>();
        SimpleDateFormat patternDateStr = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        String patternStaStr = "u-0\\d{9,11}\\s0";
        String patternStStr = "u-1\\d{10}\\s[12]";
        String phoneToPhone = "t-0\\d{9,11}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String phoneToMobile = "t-0\\d{9,11}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String mobileToPhone = "t-1\\d{10}\\s0\\d{2,3}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String mobileToMobile = "t-1\\d{10}\\s0\\d{2,3}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String divideStr = "-|\\s";
        String inProvince = "(079\\d|0701)";
        Date d1 = new Date(),d2 = new Date();
        String info;
        while(true){
            info = bjsn.nextLine();
            if(info.equals("end")){
                break;
            }
            if(info.matches(patternStaStr) | info.matches(patternStStr)){
                String[] userInfo = info.split(divideStr);
                User user1 = new User(userInfo[2],userInfo[1]);
//                user.add(user1);
                mp.put(userInfo[1],user1);
            }
            else if(info.matches(phoneToPhone)){
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[3]) && check.isValidDay(userInfo[5]) && check.isValidTime(userInfo[4]) && check.isValidTime(userInfo[6])){
                    try {
                        d1 = patternDateStr.parse(userInfo[3] + " " + userInfo[4]);
                        d2 = patternDateStr.parse(userInfo[5] + " " + userInfo[6]);
                    }catch (ParseException e){

                    }
//                    for(int i=3;i<7;i++){
//                        System.out.println(userInfo[i]);
//                    }
//                    System.out.println(d1 + " " + d2);
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[1])){
                            CallRecord callRecord = new CallRecord();
                            callRecord.setStartTime(d1);
                            callRecord.setEndTime(d2);
                            callRecord.setCallingNumber(userInfo[1]);
                            callRecord.setAnswerAddressAreaCode(userInfo[2].substring(0,4));
                            tmp.getUserRecords().addCallingInCityRecords(callRecord);
                        }
                    }
                }
            }
            else if(info.matches(phoneToMobile)){
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[4]) && check.isValidDay(userInfo[6]) && check.isValidTime(userInfo[5]) && check.isValidTime(userInfo[7])){
                    try {
                        d1 = patternDateStr.parse(userInfo[4] + " " + userInfo[5]);
                        d2 = patternDateStr.parse(userInfo[6] + " " + userInfo[7]);
                    }catch (ParseException e){

                    }
                    CallRecord callRecord = new CallRecord();
                    callRecord.setStartTime(d1);
                    callRecord.setEndTime(d2);
                    callRecord.setCallingNumber(userInfo[1]);
                    callRecord.setAnswerNumber(userInfo[2]);
                    callRecord.setCallingAddressAreaCode("0791");
                    callRecord.setAnswerAddressAreaCode(userInfo[3]);
                    for(User tmp : mp.values()) {
                        if (tmp.getNumber().equals(userInfo[1])) {
                            tmp.getUserRecords().addCallingInCityRecords(callRecord);
                        }
                    }
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[2])){
                            if(!userInfo[3].matches(inProvince)){
                                tmp.getUserRecords().addAnswerInLandRecords(callRecord);
                            }
                        }
                    }
                }
            }
            else if(info.matches(mobileToPhone)){
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[4]) && check.isValidDay(userInfo[6]) && check.isValidTime(userInfo[5]) && check.isValidTime(userInfo[7])){
                    try {
                        d1 = patternDateStr.parse(userInfo[4] + " " + userInfo[5]);
                        d2 = patternDateStr.parse(userInfo[6] + " " + userInfo[7]);
                    }catch (ParseException e){

                    }
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[1])){
                            CallRecord callRecord = new CallRecord();
                            callRecord.setStartTime(d1);
                            callRecord.setEndTime(d2);
                            callRecord.setCallingNumber(userInfo[1]);
                            callRecord.setAnswerNumber(userInfo[3]);
                            callRecord.setCallingAddressAreaCode(userInfo[2]);
                            callRecord.setAnswerAddressAreaCode(userInfo[3].substring(0,4));
                            if(userInfo[2].equals("0791")){
                                tmp.getUserRecords().addCallingInCityRecords(callRecord);
                            }
                            else if(userInfo[2].matches(inProvince)){
                                tmp.getUserRecords().addCallingInProvinceRecords(callRecord);
                            }
                            else{
                                tmp.getUserRecords().addCallingInLandRecords(callRecord);
                            }
                        }
                    }
                }
            }
            else if(info.matches(mobileToMobile)){
//                System.out.println("114514");
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[5]) && check.isValidDay(userInfo[7]) && check.isValidTime(userInfo[6]) && check.isValidTime(userInfo[8])){
                    try {
                        d1 = patternDateStr.parse(userInfo[5] + " " + userInfo[6]);
                        d2 = patternDateStr.parse(userInfo[7] + " " + userInfo[8]);
                    }catch (ParseException e){

                    }
//                    System.out.println(userInfo[5] + " " + userInfo[6] + " " + userInfo[7] + " " + userInfo[8]);
//                    System.out.println(d1 + " " + d2);
                    CallRecord callRecord = new CallRecord();
                    callRecord.setStartTime(d1);
                    callRecord.setEndTime(d2);
                    callRecord.setCallingNumber(userInfo[1]);
                    callRecord.setAnswerNumber(userInfo[3]);
                    callRecord.setCallingAddressAreaCode(userInfo[2]);
                    callRecord.setAnswerAddressAreaCode(userInfo[4]);
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[1])){
                            if(userInfo[2].equals("0791")){
                                tmp.getUserRecords().addCallingInCityRecords(callRecord);
                            }
                            else if(userInfo[2].length() == 4 && userInfo[2].matches(inProvince)){
                                tmp.getUserRecords().addCallingInProvinceRecords(callRecord);
                            }
                            else{
                                tmp.getUserRecords().addCallingInLandRecords(callRecord);
                            }
                        }
                    }
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[3])){
                            if(!userInfo[4].matches(inProvince)){
                                tmp.getUserRecords().addAnswerInLandRecords(callRecord);
                            }
                        }
                    }
                }
            }
        }
        for(User tmp : mp.values()){
            System.out.println(tmp.getNumber() + " " + (float)tmp.calCost() + " " + (float)tmp.calBalance());
        }
    }
}
class Check{
    boolean isValidDay(String s){
        String[] temp = s.split("\\.");
        int yyyy = Integer.parseInt(temp[0]);
        int mm = Integer.parseInt(temp[1]);
        int dd = Integer.parseInt(temp[2]);
        if(mm < 1 || mm > 12 || dd < 1){
            return false;
        }
        switch (mm){
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:if(dd > 31){
                return false;
            }
                break;
            case 4:
            case 6:
            case 9:
            case 11:if(dd > 30){
                return false;
            }
                break;
            case 2:if(isLeapYear(yyyy)){
                if(dd > 29){
                    return false;
                }
            }
            else{
                if(dd > 28){
                    return false;
                }
            }
            break;
        }
        return true;
    }
    boolean isValidTime(String s){
        String[] temp = s.split(":");
        int hh = Integer.parseInt(temp[0]);
        int mm = Integer.parseInt(temp[1]);
        int ss = Integer.parseInt(temp[2]);
        if(hh < 0 || hh > 23 || mm < 0 || mm > 59 || ss < 0 || ss > 59){
            return false;
        }
        return true;
    }
    boolean isLeapYear(int yyyy){
        if((yyyy % 4 == 0 && yyyy % 100 != 0) || yyyy % 400 == 0){
            return true;
        }
        return false;
    }
}
class User{
    UserRecords userRecords = new UserRecords();
    double balance = 100;
    ChargeMode chargeMode;
    String number;
    public User(String t,String number){
        this.number = number;
        if(t.equals("0")){
            this.chargeMode = new LandlinePhoneCharging();
        }
        else if(t.equals("1")){
            this.chargeMode = new LandPhoneCharging();
        }
    }
    double calCost(){
        return chargeMode.calCost(userRecords);
    }
    double calBalance(){
        return getBalance() - chargeMode.getMonthlyRent() - calCost();
    }
    UserRecords getUserRecords(){
        return userRecords;
    }
    void setUserRecords(UserRecords userRecords){
        this.userRecords = userRecords;
    }
    double getBalance(){
        return balance;
    }
    ChargeMode getChargeMode(){
        return chargeMode;
    }
    void setChargeMode(ChargeMode chargeMode){
        this.chargeMode = chargeMode;
    }
    String getNumber(){
        return number;
    }
    void setNumber(String number){
        this.number = number;
    }
}
abstract class ChargeRule{
    abstract double calCost(ArrayList<CallRecord>callRecords);
}
abstract class CallChargeRule extends ChargeRule{
    abstract double calCost(ArrayList<CallRecord>callRecords);
}
class LandPhoneInCityRule extends CallChargeRule{
    @Override
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord callrecord : callRecords){
            double ans = Math.ceil((callrecord.getEndTime().getTime() - callrecord.getStartTime().getTime()) / 60000.0);
            if(callrecord.getCallingNumber().matches("0\\d+")){
                if(callrecord.getAnswerAddressAreaCode().matches("0791")){
                    ans *= 0.1;
                }
                else if(callrecord.getAnswerAddressAreaCode().matches("(079[^1]|0701)")){
                    ans *= 0.3;
                }
                else{
                    ans *= 0.6;
                }
            }
            else{
                if(callrecord.getAnswerAddressAreaCode().matches("0791")){
                    ans *= 0.1;
                }
                else if(callrecord.getAnswerAddressAreaCode().matches("(079[^1]|0701)")){
                    ans *= 0.2;
                }
                else{
                    ans *= 0.3;
                }
            }
            cnt += ans;
        }
        return cnt;
    }
}
class LandPhoneInProvinceRule extends CallChargeRule{
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord callrecord : callRecords){
            double ans = Math.ceil((callrecord.getEndTime().getTime() - callrecord.getStartTime().getTime()) / 60000.0);
            cnt += ans;
        }
        return cnt * 0.3;
    }
}
class LandPhoneInLandRule extends CallChargeRule{
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord callrecord : callRecords){
            double d = Math.ceil((callrecord.getEndTime().getTime() - callrecord.getStartTime().getTime()) / 60000.0);
            cnt += d;
        }
        return cnt * 0.6;
    }
}
abstract class ChargeMode{
    ArrayList<ChargeRule>chargeRules = new ArrayList<ChargeRule>();
    public ChargeMode(){
        chargeRules.add(new LandPhoneInCityRule());
        chargeRules.add(new LandPhoneInProvinceRule());
        chargeRules.add(new LandPhoneInLandRule());
        chargeRules.add(new AnswerLandRecords());
    }
    ArrayList<ChargeRule>getChargeRules(){
        return chargeRules;
    }
    void setChargeRules(ArrayList<ChargeRule>chargeRules){
        this.chargeRules = chargeRules;
    }
    abstract double calCost(UserRecords userRecords);
    abstract double getMonthlyRent();
}
class LandlinePhoneCharging extends ChargeMode{
    double monthlyRent = 20;
    public LandlinePhoneCharging(){
        super();
//        chargeRules.add(new LandPhoneInCityRule());
//        chargeRules.add(new LandPhoneInProvinceRule());
//        chargeRules.add(new LandPhoneInLandRule());
    }
    double calCost(UserRecords userRecords){
        double cnt = 0;
        cnt = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
        return cnt;
    }
    double getMonthlyRent(){
        return monthlyRent;
    }
}
class LandPhoneCharging extends ChargeMode{
    double monthlyRent = 15;
    public LandPhoneCharging(){
        super();
    }
    double calCost(UserRecords userRecords){
        double cnt = 0;
        cnt = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()) + getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords());
        return cnt;
    }
    double getMonthlyRent(){
        return monthlyRent;
    }
}
class UserRecords{
    ArrayList<CallRecord>callingInCityRecords = new ArrayList<>();
    ArrayList<CallRecord>callingInProvinceRecords = new ArrayList<>();
    ArrayList<CallRecord>callingInLandRecords = new ArrayList<>();
    ArrayList<CallRecord>answerInCityRecords = new ArrayList<>();
    ArrayList<CallRecord>answerInProvinceRecords = new ArrayList<>();
    ArrayList<CallRecord>answerInLandRecords = new ArrayList<>();
    void addCallingInCityRecords(CallRecord callRecord){
        callingInCityRecords.add(callRecord);
    }
    void addCallingInProvinceRecords(CallRecord callRecord){
        callingInProvinceRecords.add(callRecord);
    }
    void addCallingInLandRecords(CallRecord callRecord){
        callingInLandRecords.add(callRecord);
    }
    void addAnswerInCityRecords(CallRecord callRecord){
        answerInCityRecords.add(callRecord);
    }
    void addAnswerInProvinceRecords(CallRecord callRecord){
        answerInProvinceRecords.add(callRecord);
    }
    void addAnswerInLandRecords(CallRecord callRecord){
        answerInLandRecords.add(callRecord);
    }
    ArrayList<CallRecord>getCallingInCityRecords(){
        return callingInCityRecords;
    }
    ArrayList<CallRecord>getCallingInProvinceRecords(){
        return callingInProvinceRecords;
    }
    ArrayList<CallRecord>getCallingInLandRecords(){
        return callingInLandRecords;
    }
    ArrayList<CallRecord>getAnswerInCityRecords(){
        return answerInCityRecords;
    }
    ArrayList<CallRecord>getAnswerInProvinceRecords(){
        return answerInProvinceRecords;
    }
    ArrayList<CallRecord>getAnswerInLandRecords(){
        return answerInLandRecords;
    }
}
abstract class CommunicationRecord{
    String callingNumber;
    String answerNumber;
    String getCallingNumber(){
        return callingNumber;
    }
    void setCallingNumber(String callingNumber){
        this.callingNumber = callingNumber;
    }
    String getAnswerNumber(){
        return answerNumber;
    }
    void setAnswerNumber(String answerNumber){
        this.answerNumber = answerNumber;
    }
}
class CallRecord extends CommunicationRecord{
    Date startTime;
    Date endTime;
    String callingAddressAreaCode;
    String answerAddressAreaCode;
    Date getStartTime(){
        return startTime;
    }
    void setStartTime(Date startTime){
        this.startTime = startTime;
    }
    Date getEndTime(){
        return endTime;
    }
    void setEndTime(Date endTime){
        this.endTime = endTime;
    }
    String getCallingAddressAreaCode(){
        return callingAddressAreaCode;
    }
    void setCallingAddressAreaCode(String callingAddressAreaCode){
        this.callingAddressAreaCode = callingAddressAreaCode;
    }
    String getAnswerAddressAreaCode(){
        return answerAddressAreaCode;
    }
    void setAnswerAddressAreaCode(String answerAddressAreaCode){
        this.answerAddressAreaCode = answerAddressAreaCode;
    }
}

class AnswerLandRecords extends CallChargeRule{
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord tmp : callRecords){
            double ans = Math.ceil((tmp.getEndTime().getTime() - tmp.getStartTime().getTime()) / 60000.0);
            cnt += ans;
        }
        return cnt * 0.3;
    }
}
class MobileCharging extends ChargeMode{
    double monthlyRent = 15;
    public MobileCharging(){
        super();
    }
    double calCost(UserRecords userRecords){
        return getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()) + getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords());
    }
    double getMonthlyRent(){
        return monthlyRent;
    }
}
View Code

 

电信计费系列3-短信计费
Score 50
Author 蔡轲
Organization 南昌航空大学

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

逐行输入本月某些用户的短信信息,短信的格式:
m-主叫号码,接收号码,短信内容 (短信内容只能由数字、字母、空格、英文逗号、英文句号组成)
m-18907910010 13305862264 welcome to jiangxi.
m-13305862264 18907910010 thank you.

输入样例:

在这里给出一组输入。例如:

u-18907910010 3
m-18907910010 13305862264 aaaaaaaaaaaaaaaaaaaaaaa
end

输出样例:

在这里给出相应的输出。例如:

18907910010 0.3 99.7
电信计费系列最后一题,由于是按推荐类图写的,在第二题的基础上加个短信类就可以啦。
先把类图祭上

新加的MessageRecord类:存储信息内容。

MessageCharge类:获取短信缴费信息。

SendingMessageRule类:继承CommunicationRecord类, 用于计算费用。

其它类作相应修改:

chargeRules加入SendMessageRule

ChargeRule新增mesCost返回短信计费信息

正则表达式判断:

String patternStStr = "u-1\\d{10}\\s[13]";
String mobileToPhone = "t-1\\d{10}\\s0\\d{2,3}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
String mobileToMobile = "t-1\\d{10}\\s0\\d{2,3}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
String messageSending = "m-1\\d{10}\\s1\\d{10}\\s(\\d|\\w|\\s|,|[.])+";

sourceMonitor分析:

直接在第二题的基础上改的代码,各项指标十分甚至九分相似。。最大复杂度还是一如既往的大。

代码:

import java.lang.*;
import java.text.*;
import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner bjsn = new Scanner(System.in);
        Check check = new Check();
        Map<String,User>mp = new TreeMap<>();
        SimpleDateFormat patternDateStr = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        String patternStaStr = "u-0\\d{9,11}\\s0";
        String patternStStr = "u-1\\d{10}\\s[13]";
        String phoneToPhone = "t-0\\d{9,11}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String phoneToMobile = "t-0\\d{9,11}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String mobileToPhone = "t-1\\d{10}\\s0\\d{2,3}\\s0\\d{9,11}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String mobileToMobile = "t-1\\d{10}\\s0\\d{2,3}\\s1\\d{10}\\s0\\d{2,3}(\\s\\d{4}[.]([^0]|10|11|12)[.]\\d{1,2}\\s([01]\\d|20|21|22|23):[0-5]\\d:[0-5]\\d){2}";
        String messageSending = "m-1\\d{10}\\s1\\d{10}\\s(\\d|\\w|\\s|,|[.])+";
        String divideStr = "-|\\s";
        String inProvince = "(079\\d|0701)";
        Date d1 = new Date(),d2 = new Date();
        String info;
        while(true){
            info = bjsn.nextLine();
            if(info.equals("end")){
                break;
            }
            if(info.matches(patternStaStr) | info.matches(patternStStr)){
                String[] userInfo = info.split(divideStr);
                User user1 = new User(userInfo[2],userInfo[1]);
                mp.put(userInfo[1],user1);
            }
            else if(info.matches(phoneToPhone)){
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[3]) && check.isValidDay(userInfo[5]) && check.isValidTime(userInfo[4]) && check.isValidTime(userInfo[6])){
                    try {
                        d1 = patternDateStr.parse(userInfo[3] + " " + userInfo[4]);
                        d2 = patternDateStr.parse(userInfo[5] + " " + userInfo[6]);
                    }catch (ParseException e){

                    }
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[1])){
                            CallRecord callRecord = new CallRecord();
                            callRecord.setStartTime(d1);
                            callRecord.setEndTime(d2);
                            callRecord.setCallingNumber(userInfo[1]);
                            callRecord.setAnswerAddressAreaCode(userInfo[2].substring(0,4));
                            tmp.getUserRecords().addCallingInCityRecords(callRecord);
                        }
                    }
                }
            }
            else if(info.matches(phoneToMobile)){
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[4]) && check.isValidDay(userInfo[6]) && check.isValidTime(userInfo[5]) && check.isValidTime(userInfo[7])){
                    try {
                        d1 = patternDateStr.parse(userInfo[4] + " " + userInfo[5]);
                        d2 = patternDateStr.parse(userInfo[6] + " " + userInfo[7]);
                    }catch (ParseException e){

                    }
                    CallRecord callRecord = new CallRecord();
                    callRecord.setStartTime(d1);
                    callRecord.setEndTime(d2);
                    callRecord.setCallingNumber(userInfo[1]);
                    callRecord.setAnswerNumber(userInfo[2]);
                    callRecord.setCallingAddressAreaCode("0791");
                    callRecord.setAnswerAddressAreaCode(userInfo[3]);
                    for(User tmp : mp.values()) {
                        if (tmp.getNumber().equals(userInfo[1])) {
                            tmp.getUserRecords().addCallingInCityRecords(callRecord);
                        }
                    }
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[2])){
                            if(!userInfo[3].matches(inProvince)){
                                tmp.getUserRecords().addAnswerInLandRecords(callRecord);
                            }
                        }
                    }
                }
            }
            else if(info.matches(mobileToPhone)){
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[4]) && check.isValidDay(userInfo[6]) && check.isValidTime(userInfo[5]) && check.isValidTime(userInfo[7])){
                    try {
                        d1 = patternDateStr.parse(userInfo[4] + " " + userInfo[5]);
                        d2 = patternDateStr.parse(userInfo[6] + " " + userInfo[7]);
                    }catch (ParseException e){

                    }
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[1])){
                            CallRecord callRecord = new CallRecord();
                            callRecord.setStartTime(d1);
                            callRecord.setEndTime(d2);
                            callRecord.setCallingNumber(userInfo[1]);
                            callRecord.setAnswerNumber(userInfo[3]);
                            callRecord.setCallingAddressAreaCode(userInfo[2]);
                            callRecord.setAnswerAddressAreaCode(userInfo[3].substring(0,4));
                            if(userInfo[2].equals("0791")){
                                tmp.getUserRecords().addCallingInCityRecords(callRecord);
                            }
                            else if(userInfo[2].matches(inProvince)){
                                tmp.getUserRecords().addCallingInProvinceRecords(callRecord);
                            }
                            else{
                                tmp.getUserRecords().addCallingInLandRecords(callRecord);
                            }
                        }
                    }
                }
            }
            else if(info.matches(mobileToMobile)){
                String[] userInfo = info.split(divideStr);
                if(check.isValidDay(userInfo[5]) && check.isValidDay(userInfo[7]) && check.isValidTime(userInfo[6]) && check.isValidTime(userInfo[8])){
                    try {
                        d1 = patternDateStr.parse(userInfo[5] + " " + userInfo[6]);
                        d2 = patternDateStr.parse(userInfo[7] + " " + userInfo[8]);
                    }catch (ParseException e){

                    }
                    CallRecord callRecord = new CallRecord();
                    callRecord.setStartTime(d1);
                    callRecord.setEndTime(d2);
                    callRecord.setCallingNumber(userInfo[1]);
                    callRecord.setAnswerNumber(userInfo[3]);
                    callRecord.setCallingAddressAreaCode(userInfo[2]);
                    callRecord.setAnswerAddressAreaCode(userInfo[4]);
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[1])){
                            if(userInfo[2].equals("0791")){
                                tmp.getUserRecords().addCallingInCityRecords(callRecord);
                            }
                            else if(userInfo[2].length() == 4 && userInfo[2].matches(inProvince)){
                                tmp.getUserRecords().addCallingInProvinceRecords(callRecord);
                            }
                            else{
                                tmp.getUserRecords().addCallingInLandRecords(callRecord);
                            }
                        }
                    }
                    for(User tmp : mp.values()){
                        if(tmp.getNumber().equals(userInfo[3])){
                            if(!userInfo[4].matches(inProvince)){
                                tmp.getUserRecords().addAnswerInLandRecords(callRecord);
                            }
                        }
                    }
                }
            }
            else if(info.matches(messageSending)){
                String[] userInfo = info.split(divideStr);
                String messageInfo = info.substring(26);
                MessageRecord messageRecord = new MessageRecord();
                messageRecord.setMessage(messageInfo);
                for(User tmp : mp.values()){
                    if(tmp.getNumber().equals(userInfo[1])){
                        tmp.getUserRecords().addSendMessageRecords(messageRecord);
                    }
                }
            }
        }
        for(User tmp : mp.values()){
            System.out.println(tmp.getNumber() + " " + (float)tmp.calCost() + " " + (float)tmp.calBalance());
        }
    }
}
class Check{
    boolean isValidDay(String s){
        String[] temp = s.split("\\.");
        int yyyy = Integer.parseInt(temp[0]);
        int mm = Integer.parseInt(temp[1]);
        int dd = Integer.parseInt(temp[2]);
        if(mm < 1 || mm > 12 || dd < 1){
            return false;
        }
        switch (mm){
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:if(dd > 31){
                return false;
            }
                break;
            case 4:
            case 6:
            case 9:
            case 11:if(dd > 30){
                return false;
            }
                break;
            case 2:if(isLeapYear(yyyy)){
                if(dd > 29){
                    return false;
                }
            }
            else{
                if(dd > 28){
                    return false;
                }
            }
                break;
        }
        return true;
    }
    boolean isValidTime(String s){
        String[] temp = s.split(":");
        int hh = Integer.parseInt(temp[0]);
        int mm = Integer.parseInt(temp[1]);
        int ss = Integer.parseInt(temp[2]);
        if(hh < 0 || hh > 23 || mm < 0 || mm > 59 || ss < 0 || ss > 59){
            return false;
        }
        return true;
    }
    boolean isLeapYear(int yyyy){
        if((yyyy % 4 == 0 && yyyy % 100 != 0) || yyyy % 400 == 0){
            return true;
        }
        return false;
    }
}
class User{
    UserRecords userRecords = new UserRecords();
    double balance = 100;
    ChargeMode chargeMode;
    String number;
    public User(String t,String number){
        this.number = number;
        if(t.equals("0")){
            this.chargeMode = new LandlinePhoneCharging();
        }
        else if(t.equals("1")){
            this.chargeMode = new LandPhoneCharging();
        }
        else if(t.equals("3")){
            this.chargeMode = new MessageCharge();
        }
    }
    double calCost(){
        return chargeMode.calCost(userRecords);
    }
    double calBalance(){
        return getBalance() - chargeMode.getMonthlyRent() - calCost();
    }
    UserRecords getUserRecords(){
        return userRecords;
    }
    double getBalance(){
        return balance;
    }
    String getNumber(){
        return number;
    }
}
abstract class ChargeRule{
    abstract double calCost(ArrayList<CallRecord>callRecords);
    abstract double mesCost(ArrayList<MessageRecord>messageRecords);
}
abstract class MessageChargeRule extends ChargeRule {
    abstract double mesCost(ArrayList<MessageRecord> messageChargeRules);
}

abstract class CallChargeRule extends ChargeRule{
    abstract double calCost(ArrayList<CallRecord>callRecords);
}
class LandPhoneInCityRule extends CallChargeRule{
    @Override
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord callrecord : callRecords){
            double ans = Math.ceil((callrecord.getEndTime().getTime() - callrecord.getStartTime().getTime()) / 60000.0);
            if(callrecord.getCallingNumber().matches("0\\d+")){
                if(callrecord.getAnswerAddressAreaCode().matches("0791")){
                    ans *= 0.1;
                }
                else if(callrecord.getAnswerAddressAreaCode().matches("(079[^1]|0701)")){
                    ans *= 0.3;
                }
                else{
                    ans *= 0.6;
                }
            }
            else{
                if(callrecord.getAnswerAddressAreaCode().matches("0791")){
                    ans *= 0.1;
                }
                else if(callrecord.getAnswerAddressAreaCode().matches("(079[^1]|0701)")){
                    ans *= 0.2;
                }
                else{
                    ans *= 0.3;
                }
            }
            cnt += ans;
        }
        return cnt;
    }
    double mesCost(ArrayList<MessageRecord>messageRecords){
        return 0.0;
    }
}
class LandPhoneInProvinceRule extends CallChargeRule{
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord callrecord : callRecords){
            double ans = Math.ceil((callrecord.getEndTime().getTime() - callrecord.getStartTime().getTime()) / 60000.0);
            cnt += ans;
        }
        return cnt * 0.3;
    }
    double mesCost(ArrayList<MessageRecord>messageRecords){
        return 0.0;
    }
}
class LandPhoneInLandRule extends CallChargeRule{
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord callrecord : callRecords){
            double d = Math.ceil((callrecord.getEndTime().getTime() - callrecord.getStartTime().getTime()) / 60000.0);
            cnt += d;
        }
        return cnt * 0.6;
    }
    double mesCost(ArrayList<MessageRecord>messageRecords){
        return 0.0;
    }
}
abstract class ChargeMode{
    ArrayList<ChargeRule>chargeRules = new ArrayList<ChargeRule>();
    public ChargeMode(){
        chargeRules.add(new LandPhoneInCityRule());
        chargeRules.add(new LandPhoneInProvinceRule());
        chargeRules.add(new LandPhoneInLandRule());
        chargeRules.add(new AnswerLandRecords());
        chargeRules.add(new SendMessageRule());
    }
    ArrayList<ChargeRule>getChargeRules(){
        return chargeRules;
    }
    abstract double calCost(UserRecords userRecords);
    abstract double getMonthlyRent();
}
class LandlinePhoneCharging extends ChargeMode{
    double monthlyRent = 20;
    public LandlinePhoneCharging(){
        super();
    }
    double calCost(UserRecords userRecords){
        double cnt = 0;
        cnt = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
        return cnt;
    }
    double getMonthlyRent(){
        return monthlyRent;
    }
}
class LandPhoneCharging extends ChargeMode{
    double monthlyRent = 15;
    public LandPhoneCharging(){
        super();
    }
    double calCost(UserRecords userRecords){
        double cnt = 0;
        cnt = getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords()) + getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords()) + getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords()) + getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords());
        return cnt;
    }
    double getMonthlyRent(){
        return monthlyRent;
    }
}
class UserRecords{
    ArrayList<CallRecord>callingInCityRecords = new ArrayList<>();
    ArrayList<CallRecord>callingInProvinceRecords = new ArrayList<>();
    ArrayList<CallRecord>callingInLandRecords = new ArrayList<>();
    ArrayList<CallRecord>answerInCityRecords = new ArrayList<>();
    ArrayList<CallRecord>answerInProvinceRecords = new ArrayList<>();
    ArrayList<CallRecord>answerInLandRecords = new ArrayList<>();
    ArrayList<MessageRecord>sendMessageRecords = new ArrayList<>();
    ArrayList<MessageRecord>receiveMessagerecords = new ArrayList<>();
    void addCallingInCityRecords(CallRecord callRecord){
        callingInCityRecords.add(callRecord);
    }
    void addCallingInProvinceRecords(CallRecord callRecord){
        callingInProvinceRecords.add(callRecord);
    }
    void addCallingInLandRecords(CallRecord callRecord){
        callingInLandRecords.add(callRecord);
    }
    void addAnswerInLandRecords(CallRecord callRecord){
        answerInLandRecords.add(callRecord);
    }
    void addSendMessageRecords(MessageRecord messageRecord){
        sendMessageRecords.add(messageRecord);
    }
    ArrayList<MessageRecord>getSendMessageRecords(){
        return sendMessageRecords;
    }
    ArrayList<CallRecord>getCallingInCityRecords(){
        return callingInCityRecords;
    }
    ArrayList<CallRecord>getCallingInProvinceRecords(){
        return callingInProvinceRecords;
    }
    ArrayList<CallRecord>getCallingInLandRecords(){
        return callingInLandRecords;
    }
    ArrayList<CallRecord>getAnswerInLandRecords(){
        return answerInLandRecords;
    }
}
abstract class CommunicationRecord{
    String callingNumber;
    String answerNumber;
    String getCallingNumber(){
        return callingNumber;
    }
    void setCallingNumber(String callingNumber){
        this.callingNumber = callingNumber;
    }
    void setAnswerNumber(String answerNumber){
        this.answerNumber = answerNumber;
    }
}
class CallRecord extends CommunicationRecord{
    Date startTime;
    Date endTime;
    String callingAddressAreaCode;
    String answerAddressAreaCode;
    Date getStartTime(){
        return startTime;
    }
    void setStartTime(Date startTime){
        this.startTime = startTime;
    }
    Date getEndTime(){
        return endTime;
    }
    void setEndTime(Date endTime){
        this.endTime = endTime;
    }
    void setCallingAddressAreaCode(String callingAddressAreaCode){
        this.callingAddressAreaCode = callingAddressAreaCode;
    }
    String getAnswerAddressAreaCode(){
        return answerAddressAreaCode;
    }
    void setAnswerAddressAreaCode(String answerAddressAreaCode){
        this.answerAddressAreaCode = answerAddressAreaCode;
    }
}
class MessageRecord extends CommunicationRecord{
    String message;
    String getMessage(){
        return message;
    }
    void setMessage(String message){
        this.message = message;
    }
}
class MessageCharge extends ChargeMode{
    double monthlyRent = 0;
    @Override
    double calCost(UserRecords userRecords){
        return getChargeRules().get(4).mesCost(userRecords.getSendMessageRecords());
    }
    double getMonthlyRent(){
        return monthlyRent;
    }
}
class SendMessageRule extends MessageChargeRule{
    double calCost(ArrayList<CallRecord>callRecords){
        return 0.0;
    }
    double mesCost(ArrayList<MessageRecord>messageRecords){
        double cnt = 0;
        for(MessageRecord tmp : messageRecords){
            cnt += Math.ceil(tmp.getMessage().length() / 10.0);
        }
        if(cnt <= 3){
            return cnt * 0.1;
        }
        else if(cnt <= 5){
            return (cnt - 3) * 0.2 + 0.3;
        }
        else{
            return (cnt - 5) * 0.3 + 0.7;
        }
    }
}
class AnswerLandRecords extends CallChargeRule{
    double calCost(ArrayList<CallRecord>callRecords){
        double cnt = 0;
        for(CallRecord tmp : callRecords){
            double ans = Math.ceil((tmp.getEndTime().getTime() - tmp.getStartTime().getTime()) / 60000.0);
            cnt += ans;
        }
        return cnt * 0.3;
    }
    double mesCost(ArrayList<MessageRecord>messageRecords){
        return 0.0;
    }
}
View Code

电信计费系列完结撒花!

 

三次作业其它题目:
第六次T2

多态测试
Score 20
Author 董卫萍
Organization 绍兴文理学院元培学院

定义容器Container接口。模拟实现一个容器类层次结构,并进行接口的实现、抽象方法重写和多态机制测试。各容器类实现求表面积、体积的方法。

  1. 定义接口Container:
    属性:
    public static final double pi=3.1415926;
    抽象方法:
    public abstract double area();
    public abstract double volume();
    static double sumofArea(Container c[]);
    static double sumofVolume(Container c[]);
    其中两个静态方法分别计算返回容器数组中所有对象的面积之和、周长之和;
  2. 定义Cube类、Cylinder类均实现自Container接口。
    Cube类(属性:边长double类型)、Cylinder类(属性:底圆半径、高,double类型)。

输入格式:

第一行n表示对象个数,对象类型用cube、cylinder区分,cube表示立方体对象,后面输入边长,输入cylinder表示圆柱体对象,后面是底圆半径、高。

输出格式:

分别输出所有容器对象的表面积之和、体积之和,结果保留小数点后2位。

输入样例:

在这里给出一组输入。例如:

4
cube
15.7
cylinder
23.5 100
cube
46.8
cylinder
17.5 200

输出样例:

在这里给出相应的输出。例如:

56771.13
472290.12

水题,看看就好,没啥讲的。 

代码:

import java.util.*;
import java.lang.*;
public class Main{
    public static void main(String[] args){
        Container container = new Container();
        container.calc();
    }
}
class Container{
    boolean check(String s){

//        int len = s.length();
        if(s.charAt(1)=='u'){
            return true;
        }
        return false;
    }
    void calc(){
        Cube cube = new Cube();
        Cylinder cylinder = new Cylinder();
        double S=0,V=0;
        Scanner bjsn = new Scanner(System.in);
        int T = bjsn.nextInt();
        for(int i = 0; i < T; i++) {
            String s = bjsn.next();
//            System.out.println(s);
            if (check(s)) {
                double r = bjsn.nextDouble();
//                System.out.println(r);
                S += cube.sumOfArea(r);
                V += cube.volume(r);
            } else {
                double r = bjsn.nextDouble();
                double h = bjsn.nextDouble();
                S += cylinder.sumOfArea(r, h);
                V += cylinder.volume(r, h);
            }
        }
        System.out.printf("%.2f\n%.2f",S,V);
    }

}
class Cube{
    double sumOfArea(double r){
        return 6*r*r;
    }
    double volume(double r){
        return r*r*r;
    }
}
class Cylinder{
    double pi=3.1415926;
    double sumOfArea(double r,double h){
        return pi*r*r*2+2*pi*r*h;
    }
    double volume(double r,double h){
        return pi*r*r*h;
    }
}
View Code

第七次T2

sdut-Collection-sort--C~K的班级(II)
Score 10
Author 周雪芹
Organization 山东理工大学

经过不懈的努力,C~K终于当上了班主任。

现在他要统计班里学生的名单,但是C~K在教务系统中导出班级名单时出了问题,发现会有同学的信息重复,现在他想把重复的同学信息删掉,只保留一个,
但是工作量太大了,所以找到了会编程的你,你能帮他解决这个问题吗?

输入格式:

第一行输入一个N,代表C~K导出的名单共有N行(N<100000).

接下来的N行,每一行包括一个同学的信息,学号 姓名 年龄 性别。

输出格式:

第一行输出一个n,代表删除重复名字后C~K的班级共有几人。

接下来的n行,输出每一个同学的信息,输出按照学号从小到大的顺序。

输入样例:

6
0001 MeiK 20 M
0001 MeiK 20 M
0002 sdk2 21 M
0002 sdk2 21 M
0002 sdk2 21 M
0000 blf2 22 F

输出样例:

3
0000 blf2 22 F
0001 MeiK 20 M
0002 sdk2 21 M

代码:

import java.lang.*;
import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner bjsn = new Scanner(System.in);
        int n = Integer.parseInt(bjsn.nextLine());
        ArrayList<String>info = new ArrayList<>();
        for(int i = 1; i <= n; i++){
            String t = bjsn.nextLine();
            if(!info.contains(t)) {
                info.add(t);
            }
        }
        info.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int id1 = Integer.parseInt(o1.substring(0,4));
                int id2 = Integer.parseInt(o2.substring(0,4));
                return id1 - id2;
            }
        });
        System.out.println(info.size());
        for(String stu : info){
            System.out.println(stu);
        }
    }
}
View Code

第六次T3

阅读程序,按照题目需求修改程序
Score 10
Author 肖斌
Organization 西南石油大学
功能需求:
      使用集合存储3个员工的信息(有序);
      通过迭代器依次找出所有的员工。

提示:学生复制以下代码到编程区,并按需求进行调试修改

 

// 1、导入相关包
//定义员工类
class Employee {
    private String name;
    private int age;
    public Employee() {
        super();
    }
    public Employee(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
//主函数
public class Main {
    public static void main(String[] args) {
                // 1、创建有序集合对象
                Collection c ;
      // 创建3个员工元素对象
        for (int i = 0; i < 3; i++) {
            Scanner sc = new Scanner(System.in);
            String employeeName = sc.nextLine();
            int employeeAge = sc.nextInt();
            Employee employee = new Employee(employeeName, employeeAge);
            c.add(employee);
        }            
                // 2、创建迭代器遍历集合
                Iterator it;
                //3、遍历
                while (it.hasnext) {
                    //4、集合中对象未知,向下转型
                    Employee e =  it.next();
                    System.out.println(e.getName() + "---" + e.getAge());
                }
    }
}
题给代码

输入样例:

在这里给出一组输入。例如:

zs 
10
ls
20
ww 
30

输出样例:

在这里给出相应的输出。例如:

zs---10
ls---20
ww---30

这题有点阴间。。

代码:

import java.util.Collection;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Iterator;

// 1、导入相关包

//定义员工类
class Employee {

    private String name;
    private String age;

    public Employee() {
        super();
    }

    public Employee(String name, String age) {
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

//主函数
public class Main {

    public static void main(String[] args) {
        // 1、创建有序集合对象
        Collection c = new ArrayList<Employee>();
        Scanner sc = new Scanner(System.in);

        // 创建3个员工元素对象
        for (int i = 0; i < 3; i++) {
            String employeeName = sc.next();
            String employeeAge = sc.next();
            Employee employee = new Employee(employeeName, employeeAge);
            c.add(employee);
        }



        // 2、创建迭代器遍历集合
        Iterator it = c.iterator();

        //3、遍历
        int pos = 0;
        while (it.hasNext()) {
            
            //4、集合中对象未知,向下转型
            Employee e = (Employee)it.next();
            int age = Integer.parseInt(e.getAge());
            pos++;
            if(pos < 3)
                System.out.println(e.getName() + "---" + age);
            else
                System.out.print(e.getName() + "---" + age);
        }
    }

}
View Code

第八次作业T2

编写一个类Shop(商店)、内部类InnerCoupons(内部购物券)
Score 30
Author 吴光生
Organization 新余学院

编写一个类Shop(商店),该类中有一个成员内部类InnerCoupons(内部购物券),可以用于购买该商店的牛奶(假设每箱牛奶售价为50元)。要求如下:
(1)Shop类中有私有属性milkCount(牛奶的箱数,int类型)、公有的成员方法setMilkCount( )getMilkCount( )分别用于设置和获取牛奶的箱数。
(2)成员内部类InnerCoupons,有公有属性value(面值,int类型),一个带参数的构造方法可以设定购物券的面值value,一个公有的成员方法buy( )要求输出使用了面值为多少的购物券进行支付,同时使商店牛奶的箱数减少value/50。
(3)Shop类中还有成员变量coupons50(面值为50元的内部购物券,类型为InnerCoupons)、coupons100(面值为100元的内部购物券,类型为InnerCoupons)。
(4)在Shop类的构造方法中,调用内部类InnerCoupons的带参数的构造方法分别创建上面的购物券coupons50、coupons100。
在测试类Main中,创建一个Shop类的对象myshop,从键盘输入一个整数(大于或等于3),将其设置为牛奶的箱数。假定有顾客分别使用了该商店面值为50的购物券、面值为100的购物券各消费一次,分别输出消费后商店剩下的牛奶箱数。

输入格式:

输入一个大于或等于3的整数。

输出格式:

使用了面值为50的购物券进行支付
牛奶还剩XX箱
使用了面值为100的购物券进行支付
牛奶还剩XX箱

输入样例:

在这里给出一组输入。例如:

5

输出样例:

在这里给出相应的输出。例如:

使用了面值为50的购物券进行支付
牛奶还剩4箱
使用了面值为100的购物券进行支付
牛奶还剩2箱

 代码:

import java.util.*;
import java.lang.*;
public class Main {
    public static void main(String[] args){
        Scanner bjsn = new Scanner(System.in);
        int n = bjsn.nextInt();
        Shop shop = new Shop(n);
        shop.coupons50.buy();
        System.out.println("牛奶还剩" + shop.getMilkCount() + "箱");
        shop.coupons100.buy();
        System.out.println("牛奶还剩" + shop.getMilkCount() + "箱");
    }
}
class Shop{
    private int milkCount;
    void setMilkCount(int milkCount){
        this.milkCount = milkCount;
    }
    int getMilkCount(){
        return this.milkCount;
    }
    public Shop(int milkCount){
        super();
        this.milkCount = milkCount;
    }
    InnerCoupons coupons50 = new InnerCoupons(50);
    InnerCoupons coupons100 = new InnerCoupons(100);
    class InnerCoupons{
        public int value;
        public InnerCoupons(int value){
//            super();
            this.value = value;
        }
        void buy(){
            System.out.println("使用了面值为" + value + "的购物券进行支付");
            milkCount -= value / 50;
        }
    }
}
View Code

第八次作业T3

动物发声模拟器(多态)
Score 20
Author 刘凤良
Organization 天津仁爱学院

设计一个动物发生模拟器,用于模拟不同动物的叫声。比如狮吼、虎啸、狗旺旺、猫喵喵……。
定义抽象类Animal,包含两个抽象方法:获取动物类别getAnimalClass()、动物叫shout();
然后基于抽象类Animal定义狗类Dog、猫类Cat和山羊Goat,用getAnimalClass()方法返回不同的动物类别(比如猫,狗,山羊),用shout()方法分别输出不同的叫声(比如喵喵、汪汪、咩咩)。
最后编写AnimalShoutTest类测试,输出:
猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩

其中,在AnimalShoutTestMain类中,用speak(Animal animal){}方法输出动物animal的叫声,在main()方法中调用speak()方法,分别输出猫、狗和山羊对象的叫声。

请在下面的【】处添加代码。

//动物发生模拟器.  请在下面的【】处添加代码。
public class AnimalShoutTest2 {
    public static void main(String[] args) {        
         Cat cat = new Cat();
         Dog dog = new Dog();        
        Goat goat = new Goat();
         speak(cat);
         speak(dog);
         speak(goat);
    }
    //定义静态方法speak()
    【】
}
//定义抽象类Animal
【】class Animal{
    【】
}
//基于Animal类,定义猫类Cat,并重写两个抽象方法
class Cat 【】{
    【】    
    【】
}
//基于Animal类,定义狗类Dog,并重写两个抽象方法
class Dog 【】{
    【】
    【】
}
//基于Animal类,定义山羊类Goat,并重写两个抽象方法
class Goat 【】{
    【】
    【】
}

输入样例:

输出样例:

猫的叫声:喵喵
狗的叫声:汪汪
山羊的叫声:咩咩

 代码:

import java.util.*;
import java.lang.*;
public class Main {
    public static void main(String[] args){
        Cat cat = new Cat();
        Dog dog = new Dog();
        Goat goat = new Goat();
        speak(cat);
        speak(dog);
        speak(goat);
    }
    static void speak(Animal animal){
        System.out.println(animal.getAnimalClass() + "的叫声:" + animal.shout());
    }
}
//动物发生模拟器.  请在下面的【】处添加代码。
class AnimalShoutTest2 {
    public static void main(String[] args) {

    }
    //定义静态方法speak()


}

//定义抽象类Animal
abstract class Animal{
    abstract String getAnimalClass();
    abstract String shout();
}
//基于Animal类,定义猫类Cat,并重写两个抽象方法
class Cat extends Animal{
    String getAnimalClass(){
        return "猫";
    }
    String shout(){
        return "喵喵";
    }


}
//基于Animal类,定义狗类Dog,并重写两个抽象方法
class Dog extends Animal{
    String getAnimalClass(){
        return "狗";
    }
    String shout(){
        return "汪汪";
    }

}
//基于Animal类,定义山羊类Goat,并重写两个抽象方法
class Goat extends Animal{
    String getAnimalClass(){
        return "山羊";
    }
    String shout(){
        return "咩咩";
    }

}
View Code

三、踩坑心得

最后三次作业比较简单,坑也没踩多少。下面来简单地罗列一遍吧~

(1)区号有可能是三位

(2)日期中月份不能带前缀0(如1919年8月10日必须写成1919.8.10而不能写成1919.08.10)

因为这两个点爆WA无数发。。话说PTA评测机上午到中午这段时间抖动挺厉害的啊,同一代码时隔几十秒提交,分数能差个二三十分(部分测试点运行超时)。

(3)Date的getTime()真好用啊。。单位是毫秒,转化为分钟要除以60000.0。

(4)第七次作业T2,改代码的那道,防不胜防的格式错误。。(最后一行不能继续换行)

四、改进建议

经历了点线形系列的摧残,这三次大作业难度都算不上啥了。果然代码平均复杂度低、sourceMonitor分析数据好看还得靠老师给的推荐类图带。下面说几点我认为还可以优化的地方:

(1) 从sourceMonitor分析结果来看,虽然平均复杂度降低了,但最大复杂度还是惊人的高。这怕是main函数的锅。

截一小块过来,可以看出存在较多if嵌套。将其中部分改写为switch,case(如正则式匹配),或多写几个函数、类并引用,估计会好一些。

(2)可以把市内、省内、国内三种形式的通话计费方式写成独立的类,方便代码修改及复用。

五、总结

        这三次大作业虽然难度不大,但也让我学到了很多。从自己硬写高复杂度的烂代码,到从类图中提取有效信息,按照类图来写高质量代码,并由此更深刻地体会到面向对象的魅力、面向对象编程所带来的简洁、代码修改的方便,java的学习让我编程时的思路更加清晰、明朗。

        期末考试的顺利结束,意味着这个学期的java学习正式告一段落。这是本学期的最后一篇java博客,也是java课的最后一个任务。我在这个学期的java学习过程中,遇到了大大小小的困难,被一次次地搞心态,但是最后还是挺过来了。学习嘛,不遇到几次困难你永远不知道自己几斤几两,也永远不会进步。java课程的结束,并不意味着java学习的结束。技术发展日新月异,我们在短短一学期内所学到的,永远只是java宇宙的冰山一角。其它的学科也一样。学习也不能局限于学校里学的知识。同时,对于我们这种计算机类专业,在学习了理论知识以后要多多动手实践,只有自己用代码敲出来才能对知识点有更深刻的理解。学习不是一蹴而就的过程,更要的是博识多学、坚持不懈。千淘万漉虽辛苦,吹尽狂沙始到金。人生也是这样,克服所遇到的困难,让自己闪现出金子般的光芒!最后,在此感谢老师同学们对我java学习所提供的帮助!

posted @ 2022-12-06 21:42  _bjsn  阅读(91)  评论(0编辑  收藏  举报