一、前言

1.知识点:

这三次作业并没有什么新的知识点,都是对之前学习的东西进行应用。

(1)PTA第六次题目集:只有两题,第一题为电信计费的座机收费。

(2)PTA第七次题目集:只有三题,第二题为第六次大作业电信计费的拓展内容。

(3)PTA第八次题目集:也只有三题,第一题为电信计费系列中一个单独的短信计费,比起前两次来说相对简单,且代码不复杂。

2、题量与难度:

 (1)总的来说,七八九次题目题量都不算多,每次都只有两三道,但是题目关联性很强,基本上从第六次的电信计费系列1开始,再到第七次第八次的电信计费系列,如果只是单凭题目的话,对于我而言,难度很大。但在第六次题目电信计费系列开始老师非常仁慈地给了我们类图,所以从总体上来说,将难度降低了很多。

 (2)除了电信计费系列题目之外,老师还给我们布置了一些比较简单的题目,我认为主要是为了让我们对类与对象的概念更加深入的理解与把握,比如七次题目集的C-K班级,八次题目的shop类和动物发声模拟器(继承与多态)等。

二、设计与分析

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

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

输入格式:

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

类图如下:

 

 

import java.util.Scanner;
import java.util.TreeMap;
import java.util.ArrayList;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class Main {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        Scanner input = new Scanner(System.in);
        String a = input.nextLine();
        TreeMap<String, User> records = new TreeMap<String, User>();
        String checkU = "[u]-[0-9]{11,12}\\s[0,1,2]";
        String checkT = "t-\\d{11,12}\\s\\d{10,12}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
        while (!a.equals("end")) {
            if (a.matches(checkU)) {
                String[] array = a.substring(2).split(" ");
                String number = array[0].substring(4);
                LandlinePhoneCharging mode = new LandlinePhoneCharging();// 你开户想要的套餐
                User user = new User(number, mode);// 开户 并且将你开户的号码与套餐传进用户里
                records.put(number, user);// 将这个用户信息传到这个容器里
            }
            if (a.matches(checkT)) {
                String[] array = a.substring(2).split(" ");
                String callingAddressAreaCode = array[0].substring(0, 4);// 拨打电话地区
                String answerAddressAreaCode = array[1].substring(0, 4);// 接听电话地区
                String callingNumber = array[0].substring(4);// 拨打电话号码
                String answerNumber = array[1].substring(4);// 接听电话号码
                String startDate = array[2] + " " + array[3];// 开始时间
                String endDate = array[4] + " " + array[5];// 结束时间
                String[] m = array[2].split("\\.");
                int Month1 = Integer.parseInt(m[1]);
                int Year1 = Integer.parseInt(m[0]);
                int Day1 = Integer.parseInt(m[2]);
                String[] n = array[4].split("\\.");
                int Month2 = Integer.parseInt(n[1]);
                int Year2 = Integer.parseInt(n[0]);
                int Day2 = Integer.parseInt(n[2]);
                if (!checkInputValidity(Year1, Month1, Day1) || m[1].charAt(0) == '0' || n[1].charAt(0) == '0'
                        || !checkInputValidity(Year2, Month2, Day2)) {

                } else {
                    Date startTime = new Date();
                    Date endTime = new Date();
                    SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
                    try {
                        startTime = format.parse(startDate);
                        endTime = format.parse(endDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    CallRecord callrecords = new CallRecord(callingNumber, answerNumber, startTime, endTime);
                    if (records.get(callingNumber) != null) {
                        if (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0791")) {
                            records.get(callingNumber).getUserRecords().addCallingCityRecords(callrecords);

                        } else if ((callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0790"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0792"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0793"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0794"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0795"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0796"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0797"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0798"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0799"))
                                || (callingAddressAreaCode.equals("0791") && answerAddressAreaCode.equals("0701")))
                            records.get(callingNumber).getUserRecords().addCallingProvinceRecords(callrecords);
                        else
                            records.get(callingNumber).getUserRecords().addCallingLandRecords(callrecords);
                    }
                }
            }

            a = input.nextLine();
        }
        for (User user : records.values()) {

            System.out.println("0791" + user.getNumber() + " " + Math.round(user.calCost() * 100) / 100.0 + " "
                    + Math.round(user.calBalance() * 100) / 100.0);
        }

    }

    public static boolean checkInputValidity(int year, int month, int day) { // 判断输入数据是否合法
        if (month < 1 || month > 12)
            return false;
        else if (day < 1 || day > 31)
            return false;
        else if ((month == 4 && day >= 31) || (month == 6 && day >= 31) || (month == 9 && day >= 31)
                || (month == 11 && day >= 31))
            return false;
        return true;
    }



}
abstract class CallChargeRule extends ChargeRule {
        public abstract  double calCost(ArrayList<CallRecord> callRecords);

}
class CallRecord extends CommunicationRecord{
    Date startTime;
    Date endTime;
    private String callingAddressAreaCode;
    private String answerAddressAreaCode;
    private String callingNumber;
    private String answerNumber;
    

    public CallRecord(String callingNumber, String answerNumber, Date startTime, Date endTime) {
        // TODO 自动生成的构造函数存根
        this.callingNumber = callingNumber;
        this.answerNumber = answerNumber;
        this.startTime = startTime;
        this.endTime = endTime;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public String getCallingAddressAreaCode() {
        return callingAddressAreaCode;
    }

    public void setCallingAddressAreaCode(String callingAddressAreaCode) {
        this.callingAddressAreaCode = callingAddressAreaCode;
    }

    public String getAnswerAddressAreaCode() {
        return answerAddressAreaCode;
    }

    public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
        this.answerAddressAreaCode = answerAddressAreaCode;
    }

}
abstract class ChargeMode {
    ArrayList<ChargeRule> chargeRules = new ArrayList<ChargeRule>();

    public ArrayList<ChargeRule> getChargeRules() {
        return chargeRules;
    }

    public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
        this.chargeRules = chargeRules;
    }

    public abstract double calCost(UserRecords userRecords);
    
    public abstract double getMonthlyRent();

}
abstract class ChargeRule {

    public abstract double calCost(ArrayList<CallRecord> callRecords);

}
abstract class CommunicationRecord {
     private String callingNumber;
     private String answerNumber;
     
     public String getCallingNumber() {
         return callingNumber;
     }
     public void setCallingNumber(String callingNumber) {
         this.callingNumber =callingNumber;
     }
     public String getAnswerNumber(){
         return answerNumber;
     }
     public void setAnswerNumber() {
         this.answerNumber =answerNumber;
     }
     
}
 class LandlinePhoneCharging extends ChargeMode {
    private double montlyRent = 20;

    public LandlinePhoneCharging() {
        super();
        // TODO 自动生成的构造函数存根
    }

    public double calCost(UserRecords userRecords) {
        getChargeRules().add(new LandPhoneInCityRule());
        getChargeRules().add(new LandPhoneInProvinceRule());
        getChargeRules().add(new LandPhoneInLandRule());
        double sum = 0;
        sum = super.getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords())
                + super.getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords())
                + super.getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
        return sum;
    }

    @Override
    public double getMonthlyRent() {
        // TODO 自动生成的方法存根
        return this.montlyRent;
    }

}
class LandPhoneInCityRule extends CallChargeRule {

    public double calCost(ArrayList<CallRecord> callRecords) {
        double sum = 0;
        for(CallRecord a:callRecords)
        sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0);
        sum = sum * 0.1;
        return sum;
    }

}
class LandPhoneInLandRule extends CallChargeRule {

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        // TODO 自动生成的方法存根
        double sum = 0;
        for (CallRecord a : callRecords)
            sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0);
        sum = sum * 0.6;
        return sum;
    }

}
class LandPhoneInProvinceRule extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double sum=0;
        for(CallRecord a:callRecords) 
            sum =sum+Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0);
            sum =sum*0.5;
            return sum;
        
    }

}
class MessageRecord {
    private String message;
    
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message =message;
    }

}
 class User {
    UserRecords userRecords = new UserRecords();
    private double balance = 100;
    ChargeMode chargeMode;
    private String number;
    

    public User(String number, ChargeMode mode) {
        // TODO 自动生成的构造函数存根
        this.number = number;
        this.chargeMode = mode;
    }

    public double calBalance() {
        return balance - calCost() - chargeMode.getMonthlyRent();
    }

    public double calCost() {
        return chargeMode.calCost(userRecords);
    }

    public UserRecords getUserRecords() {
        return userRecords;
    }

    public void setUserRecords(UserRecords userRecords) {
        this.userRecords = userRecords;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public ChargeMode getChargeMode() {
        return chargeMode;
    }

    public void setChargeMode(ChargeMode chargeMode) {
        this.chargeMode = chargeMode;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

}
class UserRecords {
        ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
        ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
        ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
        ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
        ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
        ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
        ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
        ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();

        public void addCallingCityRecords(CallRecord callRecord) {
            callingInCityRecords.add(callRecord);
        }

        public void addCallingProvinceRecords(CallRecord callRecord) {
            callingInProvinceRecords.add(callRecord);
        }

        public void addCallingLandRecords(CallRecord callRecord) {
            callingInLandRecords.add(callRecord);
        }

        public void addAnswerInCityRecords(CallRecord callRecord) {
            answerInCityRecords.add(callRecord);
        }

        public void addAnswerInProvinceRecords(CallRecord callRecord) {
            answerInProvinceRecords.add(callRecord);
        }

        public void addAnswerInLandRecords(CallRecord callRecord) {
            answerInLandRecords.add(callRecord);
        }

        public void addSendMessageRecords(MessageRecord sendMessageRecord) {
            sendMessageRecords.add(sendMessageRecord);
        }

        public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) {
            receiveMessageRecords.add(receiveMessageRecord);
        }

        public ArrayList<CallRecord> getCallingInCityRecords() {
            return callingInCityRecords;
        }

        public ArrayList<CallRecord> getCallingInProvinceRecords() {
            return callingInProvinceRecords;
        }

        public ArrayList<CallRecord> getCallingInLandRecords() {
            return callingInLandRecords;
        }

        public ArrayList<CallRecord> getAnswerInCityRecords() {
            return answerInCityRecords;
        }

        public ArrayList<CallRecord> getAnswerInProvinceRecords() {
            return answerInProvinceRecords;
        }

        public ArrayList<CallRecord> getAnswerInLandRecords() {
            return answerInLandRecords;
        }

        public ArrayList<MessageRecord> getSendMessageRecords() {
            return sendMessageRecords;
        }

        public ArrayList<MessageRecord> getReceiveMessageRecords() {
            return receiveMessageRecords;
        }


}

解释与心得:设计的思路最开始根据老师所给的类图依次创建好,然后计算话费,再创建主函数,利用正则表达式来判断格式的错误,另外我还用了TreeMap集合进行排序,算是一个比较新颖的点。

 

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

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

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

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

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

import java.util.Scanner;
import java.util.TreeMap;
import java.util.ArrayList;
import java.util.Date;
import java.text.ParseException;
import java.text.SimpleDateFormat;

public class Main {

    public static void main(String[] args) {
        // TODO 自动生成的方法存根
        Scanner input = new Scanner(System.in);
        String a = input.nextLine();
        TreeMap<String, User> records = new TreeMap<String, User>();
        String checkUlandline = "u-0\\d{9,11}\\s0";
        String checkUphone = "u-1\\d{10}\\s1";
        String checkTlandlineTolandline = "t-0\\d{9,11}\\s0\\d{9,11}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
        String checkTlandlineTophone = "t-0\\d{9,11}\\s1\\d{10}\\s0\\d{2,3}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
        String checkTphoneTophone = "t-1\\d{10}\\s0\\d{2,3}\\s1\\d{10}\\s0\\d{2,3}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
        String checkTphoneTolandline = "t-1\\d{10}\\s0\\d{2,3}\\s0\\d{2,3}\\d{7,8}\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d\\s\\d{4}.\\d{1,2}.\\d{1,2}\\s(0\\d|1\\d|2[0-3]):[0-5]\\d:[0-5]\\d";
        while (!a.equals("end")) {
            if (a.matches(checkUlandline)) {
                String[] array = a.substring(2).split(" ");
                String number = array[0];
                LandlinePhoneCharging mode = new LandlinePhoneCharging();// 你开户想要的套餐
                User user = new User(number, mode);// 开户 并且将你开户的号码与套餐传进用户里
                records.put(number, user);// 将这个用户信息传到这个容器里
            }

            if (a.matches(checkUphone)) {
                String[] array = a.substring(2).split(" ");
                String number = array[0];
                CellphoneCharging mode = new CellphoneCharging();
                User user = new User(number, mode);// 开户 并且将你开户的号码与套餐传进用户里
                records.put(number, user);// 将这个用户信息传到这个容器里
            }
            if (a.matches(checkTphoneTolandline)) { // 手机打座机
                String[] array = a.substring(2).split(" ");
                String callingAddressAreaCode = array[1];
                String answerAddressAreaCode = array[2].substring(0, 4);
                String callingNumber = array[0];// 拨打电话号码
                String answerNumber = array[2];// 接听电话号码
                String startDate = array[3] + " " + array[4];// 开始时间
                String endDate = array[5] + " " + array[6];// 结束时间
                String[] m = array[3].split("\\.");
                int Month1 = Integer.parseInt(m[1]);
                int Year1 = Integer.parseInt(m[0]);
                int Day1 = Integer.parseInt(m[2]);
                String[] n = array[5].split("\\.");
                int Month2 = Integer.parseInt(n[1]);
                int Year2 = Integer.parseInt(n[0]);
                int Day2 = Integer.parseInt(n[2]);
                if (!checkInputValidity(Year1, Month1, Day1) || m[1].charAt(0) == '0' || n[1].charAt(0) == '0'
                        || !checkInputValidity(Year2, Month2, Day2)) {

                } else {
                    Date startTime = new Date();
                    Date endTime = new Date();
                    SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
                    try {
                        startTime = format.parse(startDate);
                        endTime = format.parse(endDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    CallRecord callrecords = new CallRecord(callingNumber, answerNumber, startTime, endTime,
                            callingAddressAreaCode, answerAddressAreaCode);

                    if (answerAddressAreaCode.equals("0791")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingCityRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInCityRecords(callrecords);

                    } else if (answerAddressAreaCode.equals("0790") || answerAddressAreaCode.equals("0792")
                            || answerAddressAreaCode.equals("0793") || answerAddressAreaCode.equals("0794")
                            || answerAddressAreaCode.equals("0795") || answerAddressAreaCode.equals("0796")
                            || answerAddressAreaCode.equals("0797") || answerAddressAreaCode.equals("0798")
                            || answerAddressAreaCode.equals("0799") || answerAddressAreaCode.equals("0701")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingProvinceRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInProvinceRecords(callrecords);
                    } else {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingLandRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInLandRecords(callrecords);
                    }

                }
            } // 手机打座机
            if (a.matches(checkTphoneTophone)) { // 手机打手机
                String[] array = a.substring(2).split(" ");
                String callingAddressAreaCode = array[1];
                String answerAddressAreaCode = array[3];
                String callingNumber = array[0];// 拨打电话号码
                String answerNumber = array[2];// 接听电话号码
                String startDate = array[4] + " " + array[5];// 开始时间
                String endDate = array[6] + " " + array[7];// 结束时间
                CellphoneCharging mode = new CellphoneCharging();
//                User user = new User(answerNumber, mode);// 开户 并且将你开户的号码与套餐传进用户里
//                records.put(answerNumber, user);// 将这个用户信息传到这个容器里
                String[] m = array[4].split("\\.");
                int Month1 = Integer.parseInt(m[1]);
                int Year1 = Integer.parseInt(m[0]);
                int Day1 = Integer.parseInt(m[2]);
                String[] n = array[6].split("\\.");
                int Month2 = Integer.parseInt(n[1]);
                int Year2 = Integer.parseInt(n[0]);
                int Day2 = Integer.parseInt(n[2]);
                if (!checkInputValidity(Year1, Month1, Day1) || m[1].charAt(0) == '0' || n[1].charAt(0) == '0'
                        || !checkInputValidity(Year2, Month2, Day2)) {

                } else {
                    Date startTime = new Date();
                    Date endTime = new Date();
                    SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
                    try {
                        startTime = format.parse(startDate);
                        endTime = format.parse(endDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    CallRecord callrecords = new CallRecord(callingNumber, answerNumber, startTime, endTime,
                            callingAddressAreaCode, answerAddressAreaCode);

                    if (answerAddressAreaCode.equals("0791")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingCityRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInCityRecords(callrecords);

                    } else if (answerAddressAreaCode.equals("0790") || answerAddressAreaCode.equals("0792")
                            || answerAddressAreaCode.equals("0793") || answerAddressAreaCode.equals("0794")
                            || answerAddressAreaCode.equals("0795") || answerAddressAreaCode.equals("0796")
                            || answerAddressAreaCode.equals("0797") || answerAddressAreaCode.equals("0798")
                            || answerAddressAreaCode.equals("0799") || answerAddressAreaCode.equals("0701")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingProvinceRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInProvinceRecords(callrecords);
                    } else {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingLandRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInLandRecords(callrecords);
                    }

                }
            }

            if (a.matches(checkTlandlineTophone)) { // 座机打手机
                String[] array = a.substring(2).split(" ");
                String callingAddressAreaCode = array[0].substring(0, 4);// 拨打电话地区
                String answerAddressAreaCode = array[2];// 接听电话地区
                String callingNumber = array[0];// 拨打电话号码
                String answerNumber = array[1];// 接听电话号码
                String startDate = array[3] + " " + array[4];// 开始时间
                String endDate = array[5] + " " + array[6];// 结束时间
                String[] m = array[3].split("\\.");
                int Month1 = Integer.parseInt(m[1]);
                int Year1 = Integer.parseInt(m[0]);
                int Day1 = Integer.parseInt(m[2]);
                String[] n = array[5].split("\\.");
                int Month2 = Integer.parseInt(n[1]);
                int Year2 = Integer.parseInt(n[0]);
                int Day2 = Integer.parseInt(n[2]);
                if (!checkInputValidity(Year1, Month1, Day1) || m[1].charAt(0) == '0' || n[1].charAt(0) == '0'
                        || !checkInputValidity(Year2, Month2, Day2)) {

                } else {
                    Date startTime = new Date();
                    Date endTime = new Date();
                    SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
                    try {
                        startTime = format.parse(startDate);
                        endTime = format.parse(endDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    CallRecord callrecords = new CallRecord(callingNumber, answerNumber, startTime, endTime,
                            callingAddressAreaCode, answerAddressAreaCode);

                    if (answerAddressAreaCode.equals("0791")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingCityRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInCityRecords(callrecords);

                    } else if (answerAddressAreaCode.equals("0790") || answerAddressAreaCode.equals("0792")
                            || answerAddressAreaCode.equals("0793") || answerAddressAreaCode.equals("0794")
                            || answerAddressAreaCode.equals("0795") || answerAddressAreaCode.equals("0796")
                            || answerAddressAreaCode.equals("0797") || answerAddressAreaCode.equals("0798")
                            || answerAddressAreaCode.equals("0799") || answerAddressAreaCode.equals("0701")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingProvinceRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInProvinceRecords(callrecords);
                    } else {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingLandRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInLandRecords(callrecords);
                    }

                }
            } // 座机打手机

            if (a.matches(checkTlandlineTolandline)) { // 座机打座机
                String[] array = a.substring(2).split(" ");
                String callingAddressAreaCode = array[0].substring(0, 4);// 拨打电话地区
                String answerAddressAreaCode = array[1].substring(0, 4);// 接听电话地区
                String callingNumber = array[0];// 拨打电话号码
                String answerNumber = array[1];// 接听电话号码
                String startDate = array[2] + " " + array[3];// 开始时间
                String endDate = array[4] + " " + array[5];// 结束时间
                String[] m = array[2].split("\\.");
                int Month1 = Integer.parseInt(m[1]);
                int Year1 = Integer.parseInt(m[0]);
                int Day1 = Integer.parseInt(m[2]);
                String[] n = array[4].split("\\.");
                int Month2 = Integer.parseInt(n[1]);
                int Year2 = Integer.parseInt(n[0]);
                int Day2 = Integer.parseInt(n[2]);
                if (!checkInputValidity(Year1, Month1, Day1) || m[1].charAt(0) == '0' || n[1].charAt(0) == '0'
                        || !checkInputValidity(Year2, Month2, Day2)) {

                } else {
                    Date startTime = new Date();
                    Date endTime = new Date();
                    SimpleDateFormat format = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
                    try {
                        startTime = format.parse(startDate);
                        endTime = format.parse(endDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    CallRecord callrecords = new CallRecord(callingNumber, answerNumber, startTime, endTime,
                            callingAddressAreaCode, answerAddressAreaCode);

                    if (answerAddressAreaCode.equals("0791")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingCityRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInCityRecords(callrecords);

                    } else if (answerAddressAreaCode.equals("0790") || answerAddressAreaCode.equals("0792")
                            || answerAddressAreaCode.equals("0793") || answerAddressAreaCode.equals("0794")
                            || answerAddressAreaCode.equals("0795") || answerAddressAreaCode.equals("0796")
                            || answerAddressAreaCode.equals("0797") || answerAddressAreaCode.equals("0798")
                            || answerAddressAreaCode.equals("0799") || answerAddressAreaCode.equals("0701")) {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingProvinceRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInProvinceRecords(callrecords);
                    } else {
                        if (records.get(callingNumber) != null)
                            records.get(callingNumber).getUserRecords().addCallingLandRecords(callrecords);
                        if (records.get(answerNumber) != null)
                            records.get(answerNumber).getUserRecords().addAnswerInLandRecords(callrecords);
                    }
                }
            }
            // 座机打座机

            a = input.nextLine();
        }
        for (User user : records.values()) {
            System.out.println(user.getNumber() + " " + Math.round(user.calCost() * 100) / 100.0 + " "
                    + Math.round(user.calBalance() * 100) / 100.0);
        }

    }

    public static boolean checkInputValidity(int year, int month, int day) { // 判断输入数据是否合法
        if (month < 1 || month > 12)
            return false;
        else if (day < 1 || day > 31)
            return false;
        else if ((month == 4 && day >= 31) || (month == 6 && day >= 31) || (month == 9 && day >= 31)
                || (month == 11 && day >= 31))
            return false;
        else if (month == 2 && isLeapYear(year) == true && day > 29)
            return false;
        else if (month == 2 && isLeapYear(year) == false && day > 28)
            return false;
        else
            return true;
    }

    public static boolean isLeapYear(int year) { // 判断是否为闰年
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
            return true;
        else
            return false;
    }

}
abstract class CallChargeRule extends ChargeRule {
    public abstract double calCost(ArrayList<CallRecord> callRecords);

}


 abstract class MessageChargeRule extends ChargeRule {
//    public abstract double calCost(ArrayList<MessageRecord> messageRecords);
}
 class MessageRecord extends CommunicationRecord {
    String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}
 class SendMessageRule extends MessageChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        // TODO 自动生成的方法存根
        return 0;
    }
//
//    @Override
//    public double calCost(ArrayList<MessageRecord> messageRecords) {
//        // TODO 自动生成的方法存根
//        return 0;
//    }





}
 class User {
    UserRecords userRecords = new UserRecords();
    double balance = 100;
    ChargeMode chargeMode;
    String number;

    public User(String number, ChargeMode mode) {
        // TODO 自动生成的构造函数存根
        this.number = number;
        this.chargeMode = mode;
    }

    public double calBalance() {
        return balance - calCost() - chargeMode.getMonthlyRent();
    }

    public double calCost() {
        return chargeMode.calCost(userRecords);
    }

    public UserRecords getUserRecords() {
        return userRecords;
    }

    public void setUserRecords(UserRecords userRecords) {
        this.userRecords = userRecords;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

    public ChargeMode getChargeMode() {
        return chargeMode;
    }

    public void setChargeMode(ChargeMode chargeMode) {
        this.chargeMode = chargeMode;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

}

 class UserRecords {
    ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();
    ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();
    ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();
    ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();
    ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();
    ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();
    ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
    ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();

    public void addCallingCityRecords(CallRecord callRecord) {
        callingInCityRecords.add(callRecord);
    }

    public void addCallingProvinceRecords(CallRecord callRecord) {
        callingInProvinceRecords.add(callRecord);
    }

    public void addCallingLandRecords(CallRecord callRecord) {
        callingInLandRecords.add(callRecord);
    }

    public void addAnswerInCityRecords(CallRecord callRecord) {
        answerInCityRecords.add(callRecord);
    }

    public void addAnswerInProvinceRecords(CallRecord callRecord) {
        answerInProvinceRecords.add(callRecord);
    }

    public void addAnswerInLandRecords(CallRecord callRecord) {
        answerInLandRecords.add(callRecord);
    }

    public void addSendMessageRecords(MessageRecord sendMessageRecord) {
        sendMessageRecords.add(sendMessageRecord);
    }

    public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) {
        receiveMessageRecords.add(receiveMessageRecord);
    }

    public ArrayList<CallRecord> getCallingInCityRecords() {
        return callingInCityRecords;
    }

    public ArrayList<CallRecord> getCallingInProvinceRecords() {
        return callingInProvinceRecords;
    }

    public ArrayList<CallRecord> getCallingInLandRecords() {
        return callingInLandRecords;
    }

    public ArrayList<CallRecord> getAnswerInCityRecords() {
        return answerInCityRecords;
    }

    public ArrayList<CallRecord> getAnswerInProvinceRecords() {
        return answerInProvinceRecords;
    }

    public ArrayList<CallRecord> getAnswerInLandRecords() {
        return answerInLandRecords;
    }

    public ArrayList<MessageRecord> getSendMessageRecords() {
        return sendMessageRecords;
    }

    public ArrayList<MessageRecord> getReceiveMessageRecords() {
        return receiveMessageRecords;
    }

}
 class LandPhoneInProvinceRule extends CallChargeRule {
    public double calCost(ArrayList<CallRecord> callRecords) {
        double sum = 0;
        for (CallRecord a : callRecords)
            sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0);
        sum = sum * 0.3;
        return sum;
    }

}

 class LandPhoneInLandRule extends CallChargeRule {

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        // TODO 自动生成的方法存根
        double sum = 0;
        for (CallRecord a : callRecords)
            sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0);
        sum = sum * 0.6;
        return sum;
    }

}
 class LandPhoneInCityRule extends CallChargeRule {

    public double calCost(ArrayList<CallRecord> callRecords) {
        double sum = 0;
        for (CallRecord a : callRecords)
            sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0);
        sum = sum * 0.1;
        return sum;
    }

}
 class LandlinePhoneCharging extends ChargeMode {
    double montlyRent = 20;

    public LandlinePhoneCharging() {
        super();
        // TODO 自动生成的构造函数存根
    }

    public double calCost(UserRecords userRecords) {
        getChargeRules().add(new LandPhoneInCityRule());
        getChargeRules().add(new LandPhoneInProvinceRule());
        getChargeRules().add(new LandPhoneInLandRule());
        double sum = 0;
        sum = super.getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords())
                + super.getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords())
                + super.getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords());
        return sum;
    }

    @Override
    public double getMonthlyRent() {
        // TODO 自动生成的方法存根
        return this.montlyRent;
    }

}
 abstract class CommunicationRecord {
    String callingNumber;
    String answerNumber;

    public String getCallingNumber() {
        return callingNumber;
    }

    public void setCallingNumber(String callingNumber) {
        this.callingNumber = callingNumber;
    }

    public String getAnswerNumber() {
        return answerNumber;
    }

    public void setAnswerNumber(String answerNumber) {
        this.answerNumber = answerNumber;
    }
}


abstract class ChargeRule {

    public abstract double calCost(ArrayList<CallRecord> callRecords);

//    public abstract double CalCost(ArrayList<CallRecord> answerInCityRecords);

}


 abstract class ChargeMode {
    ArrayList<ChargeRule> chargeRules = new ArrayList<ChargeRule>();

    public ArrayList<ChargeRule> getChargeRules() {
        return chargeRules;
    }

    public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
        this.chargeRules = chargeRules;
    }

    public abstract double calCost(UserRecords userRecords);

    public abstract double getMonthlyRent();

}
 class CellPhoneInProvinceRule extends CallChargeRule {
    public double calCost(ArrayList<CallRecord> callRecords) {
        double sum = 0;
        for (CallRecord a : callRecords) {
            if (a.getCallingAddressAreaCode().equals("0791")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0) * 0.2;

            }
            if (a.getCallingAddressAreaCode().equals("0790") || a.getCallingAddressAreaCode().equals("0792")
                    || a.getCallingAddressAreaCode().equals("0793") || a.getCallingAddressAreaCode().equals("0794")
                    || a.getCallingAddressAreaCode().equals("0795") || a.getCallingAddressAreaCode().equals("0796")
                    || a.getCallingAddressAreaCode().equals("0797") || a.getCallingAddressAreaCode().equals("0798")
                    || a.getCallingAddressAreaCode().equals("0799") || a.getCallingAddressAreaCode().equals("0701")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.3;
    
            }
            if (!a.getCallingAddressAreaCode().equals("0790") && !a.getCallingAddressAreaCode().equals("0791")
                    && !a.getCallingAddressAreaCode().equals("0792") && !a.getCallingAddressAreaCode().equals("0793")
                    && !a.getCallingAddressAreaCode().equals("0794") && !a.getCallingAddressAreaCode().equals("0795")
                    && !a.getCallingAddressAreaCode().equals("0796") && !a.getCallingAddressAreaCode().equals("0797")
                    && !a.getCallingAddressAreaCode().equals("0798") && !a.getCallingAddressAreaCode().equals("0799")
                    && !a.getCallingAddressAreaCode().equals("0701")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.6;

            }
        }
        return sum;
    }
}


class CellPhoneInLandRule extends CallChargeRule {

    public double calCost(ArrayList<CallRecord> callRecords) {
        double sum = 0;
        for (CallRecord a : callRecords) {
            if (a.getCallingAddressAreaCode().equals("0791")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.3;
    
            }
            if (a.getCallingAddressAreaCode().equals("0790") || a.getCallingAddressAreaCode().equals("0792")
                    || a.getCallingAddressAreaCode().equals("0793") || a.getCallingAddressAreaCode().equals("0794")
                    || a.getCallingAddressAreaCode().equals("0795") || a.getCallingAddressAreaCode().equals("0796")
                    || a.getCallingAddressAreaCode().equals("0797") || a.getCallingAddressAreaCode().equals("0798")
                    || a.getCallingAddressAreaCode().equals("0799") || a.getCallingAddressAreaCode().equals("0701")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.3;
        
            }
            if (!a.getCallingAddressAreaCode().equals("0790") && !a.getCallingAddressAreaCode().equals("0791")
                    && !a.getCallingAddressAreaCode().equals("0792") && !a.getCallingAddressAreaCode().equals("0793")
                    && !a.getCallingAddressAreaCode().equals("0794") && !a.getCallingAddressAreaCode().equals("0795")
                    && !a.getCallingAddressAreaCode().equals("0796") && !a.getCallingAddressAreaCode().equals("0797")
                    && !a.getCallingAddressAreaCode().equals("0798") && !a.getCallingAddressAreaCode().equals("0799")
                    && !a.getCallingAddressAreaCode().equals("0701")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.6;
            }
        }

        return sum;
    }

}

 class CellPhoneInCityRule extends CallChargeRule {

    public double calCost(ArrayList<CallRecord> callRecords) {
        double sum = 0;
        for (CallRecord a : callRecords) {
            
            if (a.getCallingAddressAreaCode().equals("0791")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.1;
            
            }
            if (a.getCallingAddressAreaCode().equals("0790") || a.getCallingAddressAreaCode().equals("0792")
                    || a.getCallingAddressAreaCode().equals("0793") || a.getCallingAddressAreaCode().equals("0794")
                    || a.getCallingAddressAreaCode().equals("0795") || a.getCallingAddressAreaCode().equals("0796")
                    || a.getCallingAddressAreaCode().equals("0797") || a.getCallingAddressAreaCode().equals("0798")
                    || a.getCallingAddressAreaCode().equals("0799") || a.getCallingAddressAreaCode().equals("0701")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.3;
            
            }
            if (!a.getCallingAddressAreaCode().equals("0790") && !a.getCallingAddressAreaCode().equals("0791")
                    && !a.getCallingAddressAreaCode().equals("0792") && !a.getCallingAddressAreaCode().equals("0793")
                    && !a.getCallingAddressAreaCode().equals("0794") && !a.getCallingAddressAreaCode().equals("0795")
                    && !a.getCallingAddressAreaCode().equals("0796") && !a.getCallingAddressAreaCode().equals("0797")
                    && !a.getCallingAddressAreaCode().equals("0798") && !a.getCallingAddressAreaCode().equals("0799")
                    && !a.getCallingAddressAreaCode().equals("0701")) {
                sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0)* 0.6;

            }
        }
        return sum;
    }
}
 class CellphoneCharging extends ChargeMode {
    double montlyRent = 15;

    @Override
    public double calCost(UserRecords userRecords) {
        // TODO 自动生成的方法存根
        getChargeRules().add(new CellPhoneInCityRule());
        getChargeRules().add(new CellPhoneInProvinceRule());
        getChargeRules().add(new CellPhoneInLandRule());
        getChargeRules().add(new AnswerInLandRule());
        double sum = 0;
        sum = super.getChargeRules().get(0).calCost(userRecords.getCallingInCityRecords())
                + super.getChargeRules().get(1).calCost(userRecords.getCallingInProvinceRecords())
                + super.getChargeRules().get(2).calCost(userRecords.getCallingInLandRecords())
                + super.getChargeRules().get(3).calCost(userRecords.getAnswerInLandRecords());
        return sum;
    }

    @Override
    public double getMonthlyRent() {
        // TODO 自动生成的方法存根
        return montlyRent;
    }

}

class CallRecord extends CommunicationRecord {
    Date startTime;
    Date endTime;
    String callingAddressAreaCode;
    String answerAddressAreaCode;
    String callingNumber;
    String answerNumber;

    public CallRecord(String callingNumber, String answerNumber, Date startTime, Date endTime,
            String callingAddressAreaCode, String answerAddressAreaCode) {
        // TODO 自动生成的构造函数存根
        this.callingNumber = callingNumber;
        this.answerNumber = answerNumber;
        this.startTime = startTime;
        this.endTime = endTime;
        this.callingAddressAreaCode = callingAddressAreaCode;
        this.answerAddressAreaCode = answerAddressAreaCode;

    }

    public String getCallingNumber() {
        return callingNumber;
    }

    public void setCallingNumber(String callingNumber) {
        this.callingNumber = callingNumber;
    }

    public String getAnswerNumber() {
        return answerNumber;
    }

    public void setAnswerNumber(String answerNumber) {
        this.answerNumber = answerNumber;
    }

    public Date getStartTime() {
        return startTime;
    }

    public void setStartTime(Date startTime) {
        this.startTime = startTime;
    }

    public Date getEndTime() {
        return endTime;
    }

    public void setEndTime(Date endTime) {
        this.endTime = endTime;
    }

    public String getCallingAddressAreaCode() {
        return callingAddressAreaCode;
    }

    public void setCallingAddressAreaCode(String callingAddressAreaCode) {
        this.callingAddressAreaCode = callingAddressAreaCode;
    }

    public String getAnswerAddressAreaCode() {
        return answerAddressAreaCode;
    }

    public void setAnswerAddressAreaCode(String answerAddressAreaCode) {
        this.answerAddressAreaCode = answerAddressAreaCode;
    }

}
 class AnswerInLandRule extends CallChargeRule {

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        // TODO 自动生成的方法存根
        double sum = 0;
        for (CallRecord a : callRecords) {
            sum = sum + Math.ceil((a.getEndTime().getTime() - a.getStartTime().getTime()) / 1000.0 / 60.0);
        }
        sum = sum * 0.3;
        return sum;
    }

}

解释与心得:在最开始使用TreeMap的时候,在后面<>中定义了三个变量名称,报错之后才发现只能定义两个。此次大作业的类有很多,在写代码之后最好在纸上先理清楚它们的关系,这又有助于后面写代码。

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

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

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

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

import java.util.Scanner;
import java.util.TreeMap;
import java.util.ArrayList;


public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner in=new Scanner(System.in);
        String s=in.nextLine();
        TreeMap<String,User> tree=new TreeMap<String,User>();
        while(!s.equals("end")) {
            if(wrong(s)) {
                String[] s1=s.split(" ");
                String number3=s1[0].substring(2);
                LandlinePhoneCharging chargeMode=new LandlinePhoneCharging();
                User user=new User(chargeMode,number3);
                tree.put(number3, user);
            }
            if(wrong2(s)) {
                String[] s2=s.split(" ");
                String number1=s2[0].substring(2);
                String number2=s2[1];
                String message = s.substring(26);
                MessageRecord record=new MessageRecord(number1,number2,message);
                tree.get(number1).getUserRecords().addSendMessageRecords(record);
            }
            s=in.nextLine();
        }
        for (User user : tree.values()) {
            double cost = Math.round(user.calCost() * 100) / 100.0 ;
            System.out.printf(user.getNumber() + " " + "%.1f" + " "
                    + Math.round(user.calBalance() * 100) / 100.0,cost);
            System.out.println("");
        }

    }
    public static boolean wrong(String s) {
        if (!s.matches("u-[0-9]{11,12}\\s[3]")) {
            return false;
        }
        else {
            return true;
        }
    }
    public static boolean wrong2(String s) {
        if(s.matches("m-[0-9]{11,12}\\s[0-9]{11,12}\\s[\\d|\\w|\\s|.|,]+")) {
            return true;
        }
        else {
            return false;
        }
    }

}
abstract class ChargeMode {
    ArrayList<ChargeRule> chargeRule = new ArrayList<ChargeRule>();

    

    public ArrayList<ChargeRule> getChargeRule() {
        return chargeRule;
    }

    public void setChargeRule(ArrayList<ChargeRule> chargeRule) {
        this.chargeRule = chargeRule;
    }

    public abstract double calCost(UserRecords userRecords);    

}
abstract class ChargeRule {

    public ChargeRule() {
        // TODO Auto-generated constructor stub
    }
    public abstract double calCost(ArrayList<MessageRecord> MessageRecords) ;

}
abstract class CommunicationRecord {
    private String callingNumber;
    private String answerNumber;
    


    public CommunicationRecord(String callingNumber, String answerNumber) {
        super();
        this.callingNumber = callingNumber;
        this.answerNumber = answerNumber;
    }

    public CommunicationRecord() {
        // TODO Auto-generated constructor stub
    }

    public String getCallingNumber() {
        return callingNumber;
    }

    public void setCallingNumber(String callingNumber) {
        this.callingNumber = callingNumber;
    }

    public String getAnswerNumber() {
        return answerNumber;
    }

    public void setAnswerNumber(String answerNumber) {
        this.answerNumber = answerNumber;
    }
    
    

}
class LandlinePhoneCharging extends ChargeMode {

    public LandlinePhoneCharging() {
        super();
        // TODO 自动生成的构造函数存根
    }

    public double calCost(UserRecords userRecords) {
        getChargeRule().add(new SendMessageRule());
        double sum = 0;
        sum = super.getChargeRule().get(0).calCost(userRecords.getSendMessageRecords());
        return sum;
    }



}
abstract class MessageChargeRule extends ChargeRule{
    
}
class MessageRecord extends CommunicationRecord{
    String message;
    
    public MessageRecord(String callingNumber, String answerNumber, String message) {
        super(callingNumber, answerNumber);
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
    
    

}
class SendMessageRule extends MessageChargeRule{

    @Override
    public double calCost(ArrayList<MessageRecord> messageRecords) {
        // TODO 自动生成的方法存根
        double sum=0;
        double a,n=0;
        for(MessageRecord m:messageRecords) {
            a=Math.ceil(((MessageRecord)m).getMessage().length()/10.0);
            n=n+a;
        }
        if(n<=3) {
            sum=n*0.1;
        }
        if(n>3&&n<=5) {
            sum=0.3+(n-3)*0.2;
        }
        if(n>5) {
            sum=0.7+(n-5)*0.3;
        }
        return sum;


}
}
class User {
    UserRecords userRecords=new UserRecords();
    private double balance=100;
    ChargeMode chargemode;
    private String number;
    
    
    
    

    public User(ChargeMode chargemode, String number) {
        super();
        this.chargemode = chargemode;
        this.number = number;
    }

    public UserRecords getUserRecords() {
        return userRecords;
    }

    public void setUserRecords(UserRecords userRecords) {
        this.userRecords = userRecords;
    }

    public double getBalance() {
        return balance;
    }

    public ChargeMode getChargemode() {
        return chargemode;
    }

    public void setChargemode(ChargeMode chargemode) {
        this.chargemode = chargemode;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public User() {
        // TODO Auto-generated constructor stub
    }
    
    public double calBalance() {
        double calBalance=this.balance-calCost();
        return calBalance;
    }
    
    public double calCost() {
        return chargemode.calCost(userRecords);
    }
    
    
    

}
 class UserRecords {
     ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();
     ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();
    
     public void addSendMessageRecords(MessageRecord sendMessageRecord) {
         sendMessageRecords.add(sendMessageRecord);
     }
    
     public void addReceiveMessageRecords(MessageRecord receiveMessageRecord) {
         receiveMessageRecords.add(receiveMessageRecord);
     }

    public ArrayList<MessageRecord> getSendMessageRecords() {
        return sendMessageRecords;
    }

    public ArrayList<MessageRecord> getReceiveMessageRecords() {
        return receiveMessageRecords;
    }

     
    
}

 

 

 

 

 

 

 

Map

HashMap:JDK1.8 之前 HashMap 由数组+链表组成的,数组是 HashMap 存储元素的主体,链表则是主要为了解决哈希冲突而存在的,即 “拉链法” 解决冲突。JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间(哈希表对键进行散列,Map结构即映射表存放键值对)

LinkedHashMap:LinkedHashMap 继承自 HashMap,所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外,LinkedHashMap 在上面结构的基础上,增加了一条双向链表,使得键值对的插入顺序以及访问顺序等逻辑可以得以实现。

Hashtable:数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的

TreeMap:红黑树(平衡二叉排序树)

Set

HashSet: 基于 HashMap 实现的,底层采用 HashMap 来保存元素(不保证有序,唯一)

LinkedHashSet:LinkedHashSet 继承与 HashSet,并且其内部是通过 LinkedHashMap 来实现的。有点类似于我们之前说的LinkedHashMap 其内部是基于 Hashmap 实现一样,不过还是有一点点区别的。

 

TreeSet:红黑树,自平衡的排序二叉树(可实现自然排序,例如 a-z)

三、踩坑心得

虽然编写的代码大多数都能通过PTA的测试点,但其中还是有一些问题存在的。

这三次的大作业,让我收获颇丰,但同时也让我踩坑不少。

难度主要集中在对类这一大模块的语法,类与类之间的关系的掌握,正则表达式的使用也是一块硬骨头。但这次大作业的正则表达式相对上次对正则表达式的使用难度明显提高,让我一开始有些无所适从。

这次的题目还涉及到对Map,List的使用,让我们初步了解了java中的链表、集合等数据结构。

 

本次Blog题量和涉及到的知识点相比起第一次Blog多了不少,通过自己实现类与类之间关系而得到一些经验。实现LIst,Map接口的使用的过程中遇到了很多的困难,在同学们的帮助下都一一得到了解决。新的知识点例如多态和接口还需要进一步地夯实基础,勤看课本。

 

四、改进建议 

1.我应多在类方面下功夫,我认为类是可以很好的避免不同的错误。并且学了Java的几个原则之后,更好的体会到了如何完成类的设计。

2.部分框架的使用比c语言数组要简单,运用的更容易,可以帮我们减少很多错误,减少我们在修改时浪费的时间,在今后的设计中,自己要学习使用这些方便的集合框架的,使代码更加的简洁、方便,且实现功能。

3.多使用Java中的思想封装啊多态啊接口啊理解其中的优缺点以及适用性;
4.对于很多未知的功能查阅资料 最快的还是看实例 有时候一大堆文字可能看不懂这个时候需要我们通过实例去理解以及自己去设断点去调试;

五、总结
到了激动人心的总结时刻了,这又是我编程学习的一个进度点,也是这次blog作业的总结。回看自己以前写的代码,实在不堪入目,不过这也让我意识到,我实实在在的在进步,这是让我十分开心的,并且让我找到将编程学习下去的动力。

  1.感觉到自己学到了很多东西,从刚开始连创建 Scanner 类对象都要百度,到后面类的继承,看着自己写的代码越来越长,越来越复杂,感觉到自己的能力也越来越强。

  2.自己还是需要去理解很多概念,很多东西我其实都会用,但让我讲出来却是十分难的。

  3.自己还需多空出时间来学习,很多题目中涉及的知识点老师不会讲的很详细,自学能力还是要加强。

  4.对老师的建议就是希望在每次题目结束后,老师能给出一份正规的答案供大家参考学习,我相信这不仅可以方便同学们的学习,而且也可以规范大家的代码格式。众所周知,代码规范性是以后工作中重要的一个考察点。有一个良好的编写习惯,能为以后的找工作避免许多不必要的麻烦,同时也可以在招聘中为自己加分