第三次大作业总结

一、总结前言

           本次总结是关于笔者这一段时间Java学习内容的总结,涉及到最近三次PTA大作业,题目主题是电信计费,相比之前的点线型要简单不少,在老师刻意简化的情况下,终于第三次完成的差不多,实在是可喜可贺,笔者就不多赘述。

二、设计与分析

         第六次和第七次的大作业属于继承关系,所以就只选择第七次进行解析。

题目:

实现南昌市电信分公司的计费程序,假设该公司针对手机和座机用户分别采取了两种计费方案,分别如下:
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.Date;
import java.lang.reflect.Array;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws ParseException{
    ArrayList<User> users= new ArrayList<User>();
    DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
        boolean have;
        Scanner input = new Scanner(System.in);
        String s ;
        s= input.nextLine();          
         while(s.charAt(0)=='u')
         {
            have = false;
            User user= new User();
            user.setNumber(s.substring(2, s.indexOf(' ')));
            String[] a=s.split(" ");
            if(a[1].equals("0")) {
            user.setChargeMode(new LandlinePhoneCharging());
            }
            if(a[1].equals("1")){
            user.setChargeMode(new CellPhoneCharging());    
            }
            for(User u:users) 
            {
                if(u.getNumber().equals(user.getNumber()))            
                {
                    have = true;
                    break;
                }
            }
                if(!have)
                users.add(user);                            
            s= input.nextLine();                     
         }
    
      Check ck = new Check();
      Getaddress isWhere = new Getaddress();
      GettrueLine gettrue = new GettrueLine();
      while(!s.equals("end")) {
          s = gettrue.get(s,input); 
          if(s.equals("end")) 
           {       
         break;
         } 
          String l=s.substring(2);
          String[] ss=l.split(" ");
        if(s.charAt(0)=='t')
         {
             if(ss.length==6) {
                String StartTime = ss[2]+" "+ss[3];
                String EndTime = ss[4]+" "+ss[5];
                Date date1 = dateFormat.parse(StartTime);
                Date date2 = dateFormat.parse(EndTime);
                
                CallRecord callRecord = new CallRecord();
                callRecord.setStartTime(date1);
                callRecord.setEndTime(date2);
                callRecord.setCallingNumber(ss[0]);
                callRecord.setAnswerNumber(ss[1]);
                
                for(int i = 0;i<users.size();i++) {
                    if(users.get(i).getNumber().equals(ss[0])) {//拨打电话是南昌市的号码
                        String AearCode2 = ss[1].substring(0,4);
                        if(isWhere.where(AearCode2)==0) {//市内拨打
                            if(!ck.repeat(users.get(i).getUserRecords().getCallingInCityRecords(),callRecord))
                                users.get(i).getUserRecords().addCallingInCityRecords(callRecord);
                        }
                        else if(isWhere.where(AearCode2)==1) {//省内拨打
                            if(!ck.repeat(users.get(i).getUserRecords().getCallingInProvinceRecords(),callRecord))
                                users.get(i).getUserRecords().addCallingInProvinceRecords(callRecord);
                        }
                        else if(isWhere.where(AearCode2)==2){//国内拨打
                            if(!ck.repeat(users.get(i).getUserRecords().getCallingInLandRecords(),callRecord))
                            users.get(i).getUserRecords().addCallingInLandRecords(callRecord);
                        }
                    } 
               }            
          } 
             if(ss.length==7) {
                    String StartTime = ss[3]+" "+ss[4];
                    String EndTime = ss[5]+" "+ss[6];
                    Date date1 = dateFormat.parse(StartTime);
                    Date date2 = dateFormat.parse(EndTime);
                    
                    CallRecord callRecord = new CallRecord();
                    callRecord.setStartTime(date1);
                    callRecord.setEndTime(date2);
                    callRecord.setCallingNumber(ss[0]);
                    callRecord.setAnswerNumber(ss[1]);
                    
                    for(int i = 0;i<users.size();i++) {
                        if(users.get(i).getNumber().equals(ss[0])) {//拨打电话是南昌市的号码
                            String AearCode2 = ss[2];
                            if(isWhere.where(AearCode2)==0) {//市内拨打
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingInCityRecords(),callRecord))
                                    users.get(i).getUserRecords().addCallingInCityRecords(callRecord);
                            }
                            else if(isWhere.where(AearCode2)==1) {//省内拨打
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingInProvinceRecords(),callRecord))
                                    users.get(i).getUserRecords().addCallingInProvinceRecords(callRecord);
                            }
                            else {//国内拨打
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingInLandRecords(),callRecord))
                                users.get(i).getUserRecords().addCallingInLandRecords(callRecord);
                            }
                        } 
                   }
                    for(int i = 0;i<users.size();i++) {
                        if(users.get(i).getNumber().equals(ss[1])) {//接听的号码是否开户
                            String AearCode2 = ss[2];
                            if(isWhere.where(AearCode2)==2) {//国内接听                                
                        if(!ck.repeat(users.get(i).getUserRecords().getAnswerInLandRecords(),callRecord))
                                users.get(i).getUserRecords().addAnswerInLandRecords(callRecord);
                            }
                        } 
                   }                
              } 
             if(ss.length==8) {
                    String StartTime = ss[4]+" "+ss[5];
                    String EndTime = ss[6]+" "+ss[7];
                    Date date1 = dateFormat.parse(StartTime);
                    Date date2 = dateFormat.parse(EndTime);
                    
                    CallRecord callRecord = new CallRecord();
                    callRecord.setStartTime(date1);
                    callRecord.setEndTime(date2);
                    callRecord.setCallingNumber(ss[0]);
                    callRecord.setAnswerNumber(ss[2]);
                    
                    for(int i = 0;i<users.size();i++) {
                        if(users.get(i).getNumber().equals(ss[0])) {//拨打电话是南昌市的号码
                            String AearCode1 = ss[1];
                            String AearCode2 = ss[3];
                            if(isWhere.where(AearCode1)==0&&isWhere.where(AearCode2)==0) {//市内打市内
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingFromCityToCityRecords(),callRecord))
                                    users.get(i).getUserRecords().addCallingFromCityToCityRecords(callRecord);
                            }
                            else if(isWhere.where(AearCode1)==0&&isWhere.where(AearCode2)==1) {//市内打省内
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingFromCityToProvinceRecords(),callRecord))
                                    users.get(i).getUserRecords().addCallingFromCityToProvinceRecords(callRecord);
                            }
                            else if(isWhere.where(AearCode1)==0&&isWhere.where(AearCode2)==2){//市内打国内
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingFromCityToLandRecords(),callRecord))
                                users.get(i).getUserRecords().addCallingFromCityToLandRecords(callRecord);
                            }
                            else if(isWhere.where(AearCode1)==1){//省内漫游
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingFromProvinceRecords(),callRecord))
                                users.get(i).getUserRecords().addCallingFromProvinceRecords(callRecord);
                            }
                            else if(isWhere.where(AearCode1)==2){//国内漫游
                                if(!ck.repeat(users.get(i).getUserRecords().getCallingFromLandRecords(),callRecord))
                                users.get(i).getUserRecords().addCallingFromLandRecords(callRecord);
                            }
                            
                        } 
                   }
                    for(int i = 0;i<users.size();i++) {
                        if(users.get(i).getNumber().equals(ss[2])) {//接听的号码是否开户
                            String AearCode2 = ss[3];
                            if(isWhere.where(AearCode2)==2) {//国内接听                                
                        if(!ck.repeat(users.get(i).getUserRecords().getAnswerInLandRecords(),callRecord))
                                users.get(i).getUserRecords().addAnswerInLandRecords(callRecord);
                            }
                        } 
                   }                
              } 
             
         }
        s= input.nextLine();
     }
     
      for(User u : users) {
                    System.out.printf("%s %.1f %.1f\n",u.getNumber(),u.calCost(),u.calBalance());
                }
     }    
}

class AnswerInLandRecords extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.3 * a;
            }
            return cost;
    }

}

abstract class CallChargeRule extends ChargeRule {

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

class CallingFromCityToCityRecords extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.1 * a;
            }
            return cost;
    }

}
 class CallingFromCityToLandRecords extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.3 * a;
            }
            return cost;
    }

}
class CallingFromCityToProvinceRecords extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.2 * a;
            }
            return cost;
    }

}
class CallingFromLandRecords extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.6 * a;
            }
            return cost;
    }

}
 class CallingFromProvinceRecords extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.3 * a;
            }
            return cost;
    }

}
class CallRecord extends CommunicationRecord{

    private Date startTime;
    private Date endTime;
    private String callingAddressAreaCode;
    private String answerAddressAreaCode;
    
     /* StartTime的set和get  */
    public Date getStartTime()
    {
        return startTime;    
    }
    public void setStartTime(Date startTime)
    {
        this.startTime=startTime;
    }
     /* EndTime的set和get  */
    public Date getEndTime()
    {
        return endTime;    
    }
    public void setEndTime(Date endTime)
    {
        this.endTime=endTime;
    }
     /* CallingAddressAreaCode的set和get  */
    public String getCallingAddressAreaCode()
    {
        return callingAddressAreaCode;      
    }
    public void setCallingAddressAreaCode(String callingAddressAreaCode)
    {
        this.callingAddressAreaCode = callingAddressAreaCode;
    }
    /* AnswerAddressAreaCode的set和get  */
    public String getAnswerAddressAreaCode()
    {
        return answerAddressAreaCode;      
    }
    public void setAnswerAddressAreaCode(String answerAddressAreaCode)
    {
        this.answerAddressAreaCode = answerAddressAreaCode;
    }
     public int getSecMin() {
        return (int) ((endTime.getTime() - startTime.getTime()) / 1000);
    }
}
class CellPhoneCharging extends ChargeMode  {
    private double monthlyRent = 15;
    @Override
    public double calCost(UserRecords userRecords) {

        double cost = 0;
        ArrayList<CallRecord> fromCityToCityRecords = userRecords.getCallingFromCityToCityRecords();//获取拨打市内电话记录
        ArrayList<CallRecord> fromCityToProvinceRecords = userRecords.getCallingFromCityToProvinceRecords();//获取拨打省内电话记录
        ArrayList<CallRecord> fromCityToLandRecords = userRecords.getCallingFromCityToLandRecords();//获取拨打国内电话记录
        ArrayList<CallRecord> fromProvinceRecords = userRecords.getCallingFromProvinceRecords();//获取省内漫游
        ArrayList<CallRecord> fromLandRecords = userRecords.getCallingFromLandRecords();//获取省内漫游
        ArrayList<CallRecord> answerInLandRecords = userRecords.getAnswerInLandRecords();//获取省内漫游
        

        CallChargeRule cellPhoneCityToCityyRule = new CallingFromCityToCityRecords();//市内主叫市内        
        CallChargeRule cellPhoneCityToProvinceRule = new CallingFromCityToProvinceRecords();//市内主叫省内
        CallChargeRule cellPhoneCityToLandRule = new CallingFromCityToLandRecords();//市内主叫国内
        CallChargeRule cellPhoneFromProvinceRule = new CallingFromProvinceRecords();//市内主叫国内
        CallChargeRule cellPhoneFromLandRule = new CallingFromLandRecords();//市内主叫国内
        CallChargeRule cellPhoneAnswerInLandRule = new AnswerInLandRecords();//市内主叫国内
        
        

        cost += cellPhoneCityToCityyRule.calCost(fromCityToCityRecords);
        cost += cellPhoneCityToProvinceRule.calCost( fromCityToProvinceRecords);
        cost += cellPhoneCityToLandRule.calCost(fromCityToLandRecords);
        cost += cellPhoneFromProvinceRule.calCost(fromProvinceRecords);
        cost += cellPhoneFromLandRule.calCost(fromLandRecords);
        cost += cellPhoneAnswerInLandRule.calCost(answerInLandRecords);
        
        return cost;
    }

    @Override
    public double getMonthlyRent() {
        return monthlyRent;
    }




}
abstract class ChargeMode {

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

     public void setChargeRules(ArrayList<ChargeRule> chargeRules) {
            this.chargeRules = chargeRules;
        }
     
     public abstract double calCost(UserRecords userRecords);
     
     public abstract double getMonthlyRent();
}
abstract class ChargeRule {
    abstract double calCost(ArrayList<CallRecord> callRecords);
}
class Check {
    
    boolean check(String s) {
        if(s.matches("t-\\d{11,12} \\d{11,12} \\d{4}.\\d{1,2}.\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}")) {
            return true;
        }
        else if(s.matches("t-\\d{11,12} \\d{11} \\d{3,4} \\d{4}.\\d{1,2}.\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}"))
        {
            return true;
        }
        else if(s.matches("t-\\d{11} \\d{3,4} \\d{11} \\d{3,4} \\d{4}.\\d{1,2}.\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2} \\d{4}.\\d{1,2}.\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}"))
        {
            return true;
        }
        
        return false;
    }
    boolean repeat(ArrayList<CallRecord> callRecords,CallRecord callRecord) {
        for(CallRecord c: callRecords) {
            if(c.getStartTime().equals(callRecord.getStartTime())&&c.getEndTime().equals(callRecord.getEndTime())) {
                return true;
            }
        }
        return false;
    }
}

abstract class CommunicationRecord {
   protected String callingNumber;
   protected String answerNumber;
    
   /* CallingNumber的set和get  */
   public String getCallingNumber()
   {
        return callingNumber;      
   }
   public void setCallingNumber(String callingNumber)
   {
       this.callingNumber = callingNumber;
   }
   /* AnswerNumber的set和get  */
   public String getAnswerNumber()
   {
        return answerNumber;      
   }
   public void setAnswerNumber(String answerNumber)
   {
       this.answerNumber = answerNumber;
   }
}
class Getaddress {
    int where(String s){
        if(s.equals("0701")) {
            return 1;//省内
        }
        else if(s.substring(0, 3).equals("079")){
            if(s.charAt(3)=='1') {
                return 0;//南昌市
            }
            else {
                return 1;//省内
            }
        }
        else {
            return 2;//
        }
    }
}
 class GettrueLine {
     Check ck = new Check();
    String get(String s,Scanner in) {
        while(!ck.check(s)&&!s.equals("end")) {
            s = in.nextLine();
        }
        return s;
    }
}
class LandlinePhoneCharging extends ChargeMode  {
    private double monthlyRent = 20;
    @Override
    public double calCost(UserRecords userRecords) {

        double cost = 0;
        ArrayList<CallRecord> callInCityRecords = userRecords.getCallingInCityRecords();//获取拨打市内电话记录
        ArrayList<CallRecord> callInProvinceRecords = userRecords.getCallingInProvinceRecords();//获取拨打省内电话记录
        ArrayList<CallRecord> callInLandRecords = userRecords.getCallingInLandRecords();//获取拨打国内电话记录

        CallChargeRule landPhoneInCityRule = new LandPhoneInCityRule();//市内主叫市内        
        CallChargeRule landPhoneInProvinceRule = new LandPhoneInProvinceRule();//市内主叫省内
        CallChargeRule landPhoneInLandRule = new LandPhoneInLandRule();//市内主叫国内

        cost += landPhoneInCityRule.calCost(callInCityRecords);
        cost += landPhoneInProvinceRule.calCost(callInProvinceRecords);
        cost += landPhoneInLandRule.calCost(callInLandRecords);
        return cost;
    }

    @Override
    public double getMonthlyRent() {
        return monthlyRent;
    }


}
class LandPhoneInCityRule extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.1 * a;
            }
            return cost;
    }

}
class LandPhoneInLandRule extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.6 * a;
            }
            return cost;
    }

}
class LandPhoneInProvinceRule extends CallChargeRule{

    @Override
    public double calCost(ArrayList<CallRecord> callRecords) {
        double cost = 0;
            for (CallRecord callRecord : callRecords) {
                int a = callRecord.getSecMin() / 60;
                int b = callRecord.getSecMin() % 60;
                if (b != 0)
                    a++;
                cost = cost + 0.3 * a;
            }
            return cost;
    }

}
class MessageRecord extends CommunicationRecord{
   private String message;
    
    public String getMessage()
    {
        return message;    
    }
    public void setMessage(String message)
    {
        this.message=message;
    }
    
    
}
class User implements Comparable<User>{
    private double balance = 100;
    private String number;    
    private UserRecords userRecords = new UserRecords();
    private ChargeMode chargeMode;   
    
    public double calBalance()
    {
        balance -= calCost()+chargeMode.getMonthlyRent();
        return balance;
        
    }
    public double calCost()
    {
        return chargeMode.calCost(userRecords);       
    }

    public UserRecords getUserRecords()
    {
        return userRecords;      
    }
    public void setUserRecords (UserRecords userRecords)
    {
        this.userRecords = userRecords;
    }
    /* balance和get  */
    public double getBalance()
    {
        return balance;        
    }
    /* ChargeMode的set和get  */
    public ChargeMode getChargeMode()
    {
        return chargeMode;      
    }
    public void setChargeMode(ChargeMode chargeMode)
    {
        this.chargeMode = chargeMode;
    }
    /* number的set和get  */
    public String  getNumber() {
        return number;
    }
    public void setNumber(String number) {
        
        this.number = number;
    }

    @Override
    public int compareTo(User u) {
        return number.compareTo(u.getNumber());
    }
    @Override
    public int hashCode() {
        return 1;
    }
    @Override
    public boolean equals(Object object) {
        if (object instanceof User){
            return number.equals(((User) object).number);
        }
        return false;
    }
}
class UserRecords {
    private ArrayList<CallRecord> callingInCityRecords= new ArrayList<CallRecord>();//市内打
    private ArrayList<CallRecord> callingInProvinceRecords= new ArrayList<CallRecord>();//省内打
    private ArrayList<CallRecord> callingInLandRecords= new ArrayList<CallRecord>();//国内打
    private ArrayList<CallRecord> answerInCityRecords= new ArrayList<CallRecord>();//市内接
    private ArrayList<CallRecord> answerInProvinceRecords= new ArrayList<CallRecord>();//省内接
    
    private ArrayList<CallRecord> callingFromCityToCityRecords= new ArrayList<CallRecord>();//市内打市内
    private ArrayList<CallRecord> callingFromCityToProvinceRecords= new ArrayList<CallRecord>();//市内打省内
    private ArrayList<CallRecord> callingFromCityToLandRecords= new ArrayList<CallRecord>();//市内打国内
    private ArrayList<CallRecord> callingFromProvinceRecords= new ArrayList<CallRecord>();//省内漫游打
    private ArrayList<CallRecord> callingFromLandRecords= new ArrayList<CallRecord>();//国内漫游打
    private ArrayList<CallRecord> answerInLandRecords= new ArrayList<CallRecord>();//国内漫游接
    
   // private ArrayList<MessageRecord> sendMessageRecords= new ArrayList<MessageRecord>();//
   // private ArrayList<MessageRecord> receiveMessageRecords= new ArrayList<MessageRecord>();//
    public void addAnswerInLandRecords (CallRecord answerRecord)//国内漫游接
    {
        answerInLandRecords.add(answerRecord);
    }
    public  ArrayList<CallRecord> getAnswerInLandRecords(){
        return answerInLandRecords;
    }   
    
    public void addCallingFromProvinceRecords (CallRecord callRecord)//省内漫游
    {
        callingFromProvinceRecords.add(callRecord);
    }
    public  ArrayList<CallRecord> getCallingFromProvinceRecords(){
        return callingFromProvinceRecords;
    }
    
    public void addCallingFromLandRecords (CallRecord callRecord)//国内漫游
    {
        callingFromLandRecords.add(callRecord);
    }
    public  ArrayList<CallRecord> getCallingFromLandRecords(){
        return callingFromLandRecords;
    }     
    
    public void addCallingFromCityToCityRecords (CallRecord callRecord)//市内打市内
    {
        callingFromCityToCityRecords.add(callRecord);
    }
    public  ArrayList<CallRecord> getCallingFromCityToCityRecords(){
        return callingFromCityToCityRecords;
    }
    
    public void addCallingFromCityToProvinceRecords(CallRecord callRecord)//市内打省内
    {
        callingFromCityToProvinceRecords.add(callRecord);
    }
    public  ArrayList<CallRecord> getCallingFromCityToProvinceRecords(){
        return callingFromCityToProvinceRecords;
    }
    
    
    public void addCallingFromCityToLandRecords (CallRecord callRecord)//市内打国内
    {
        callingFromCityToLandRecords.add(callRecord);
    }
    public  ArrayList<CallRecord> getCallingFromCityToLandRecords(){
        return callingFromCityToLandRecords;
    }
    
    
    public void addCallingInCityRecords(CallRecord callRecord)
    {
        callingInCityRecords.add(callRecord);
    }
    public void addCallingInProvinceRecords(CallRecord callRecord)
    {
        callingInProvinceRecords.add(callRecord);
    }
    public void addCallingInLandRecords(CallRecord callRecord)
    {
        callingInLandRecords.add(callRecord);
    }
    public void addAnswerInCityRecords (CallRecord answerRecord)
    {
        answerInCityRecords.add(answerRecord);
    }
    public void addAnswerInProvinceRecords (CallRecord answerRecord)
    {
        answerInProvinceRecords.add(answerRecord);
    }
    
    
    public  ArrayList<CallRecord> getCallingInCityRecords(){
        return callingInCityRecords;
    }
    public  ArrayList<CallRecord> getCallingInProvinceRecords(){
        return callingInProvinceRecords;
    }
    public  ArrayList<CallRecord> getCallingInLandRecords(){
        return callingInLandRecords;
    }
    public  ArrayList<CallRecord> getAnswerInCityRecords(){
        return callingInCityRecords;
    }
    public  ArrayList<CallRecord> getAnswerInProvinceRecords(){
        return callingInProvinceRecords;
    }
    
}

 

 

           本题因为老师给出了类图,所以可以很容易的把大体的框架搭出来,除了主函数main之外,user和userrecord这两个类是用户的关键类,chargemode是计费类的父类,chargerule是负责计算费用的抽象类,userRecords (用户记录)、balance(余额)、chargeMode(计费方式)、number(号码)。 ChargeMode是计费方式的抽象类: chargeRules是计费方式所包含的各种计费规则的集合,ChargeRule类的定义见图3。 getMonthlyRent()方法用于返回月租(monthlyRent)。 UserRecords是用户记录类,保存用户各种通话、短信的记录, 各种计费规则将使用其中的部分或者全部记录。 其属性从上到下依次是: 市内拨打电话、省内(不含市内)拨打电话、省外拨打电话、 市内接听电话、省内(不含市内)接听电话、省外接听电话的记录 以及发送短信、接收短信的记录。CommunicationRecord是抽象的通讯记录类: 包含callingNumber拨打号码、answerNumber接听号码两个属性。 CallRecord(通话记录)、MessageRecord(短信记录)是它的子类。CallRecord(通话记录类)包含属性: 通话的起始、结束时间以及 拨号地点的区号(callingAddressAreaCode)、接听地点的区号(answerAddressAreaCode)。 区号用于记录在哪个地点拨打和接听的电话。座机无法移动,就是本机区号,如果是手机号,则会有差异。计费规则的相关类,这些类的核心方法是: calCost(ArrayList<CallRecord> callRecords)。 该方法针根据输入参数callRecords中的所有记录计算某用户的某一项费用;如市话费。 输入参数callRecords的约束条件:必须是某一个用户的符合计费规则要求的所有记录。 SendMessageRule是发送短信的计费规则类,用于计算发送短信的费用。 LandPhoneInCityRule、LandPhoneInProvinceRule、LandPhoneInLandRule三个类分别是座机拨打市内、省内、省外电话的计费规则类,用于实现这三种情况的费用计算。

第八次大作业

题目

 

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

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

注意:以上两类信息,先输入所有开户信息,再输入所有通讯信息,最后一行以“end”结束。
输出:
根据输入的详细短信信息,计算所有已开户的用户的当月短信费用(精确到小数点后2位,单位元)。假设每个用户初始余额是100元。
每条短信信息均单独计费后累加,不是将所有信息累计后统一计费。
格式:号码+英文空格符+总的话费+英文空格符+余额
每个用户一行,用户之间按号码字符从小到大排序。

错误处理:
输入数据中出现的不符合格式要求的行一律忽略。
本题只做格式的错误判断,无需做内容上不合理的判断,比如同一个电话两条通讯记录的时间有重合、开户号码非南昌市的号码、自己给自己打电话等,此类情况都当成正确的输入计算。但时间的输入必须符合要求,比如不能输入2022.13.61 28:72:65。

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

 

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws ParseException{
    ArrayList<User> users= new ArrayList<User>();
        boolean have;
        Scanner input = new Scanner(System.in);
        String s ;
        s= input.nextLine();          
         while(s.charAt(0)=='u')
         {
            have = false;
            User user= new User();
            user.setNumber(s.substring(2, s.indexOf(' ')));
            String[] a=s.split(" ");
            
            if(a[1].equals("3")){
                user.setChargeMode(new MessageCharge());
            }
            for(User u:users) 
            {
                if(u.getNumber().equals(user.getNumber()))            
                {
                    have = true;
                    break;
                }
            }
                if(!have)
                users.add(user);                            
            s= input.nextLine();                     
          }
         
     Check ck = new Check();
     GettrueLine gettrue = new GettrueLine();
      while(!s.equals("end")) {
//          s = gettrue.get(s,input); 
//          if(s.equals("end")) 
//            {       
//          break;
//          } 
          String l=s.substring(2);
          String[] ss=l.split(" ");
        if(s.charAt(0)=='m')
        {                
            MessageRecord messageRecord = new MessageRecord();
                for(int i = 0;i<users.size();i++) {
                    if(users.get(i).getNumber().equals(ss[0])) {//是南昌市的号码
                        
                   String  content = l.substring(24);
                   messageRecord.setMessage(content);
                   int a =content.length();
                  // int b = 0;
                   while(a>0) {
                   users.get(i).getUserRecords().addSendMessageRecords(messageRecord);
                   a-=10;
                   }
                   
               }
            }
          }          
         
        s= input.nextLine();
        if(s.equals("end")) 
           {       
         break;
         } 
     }
     
      for(User u : users) {
                    System.out.printf("%s %.1f %.1f\n",u.getNumber(),u.calCost(),u.calBalance());
                }
     }    
}

class User implements Comparable<User>{
    private double balance = 100;
    private String number;    
    private UserRecords userRecords = new UserRecords();
    private ChargeMode chargeMode;   
    
    public double calBalance()
    {
        balance -= calCost();
        return balance;
        
    }
    public double calCost()
    {
        return chargeMode.calCost(userRecords);       
    }

    public UserRecords getUserRecords()
    {
        return userRecords;      
    }
    public void setUserRecords (UserRecords userRecords)
    {
        this.userRecords = userRecords;
    }
    /* balance和get  */
    public double getBalance()
    {
        return balance;        
    }
    /* ChargeMode的set和get  */
    public ChargeMode getChargeMode()
    {
        return chargeMode;      
    }
    public void setChargeMode(ChargeMode chargeMode)
    {
        this.chargeMode = chargeMode;
    }
    /* number的set和get  */
    public String  getNumber() {
        return number;
    }
    public void setNumber(String number) {
        
        this.number = number;
    }

    @Override
    public int compareTo(User u) {
        return number.compareTo(u.getNumber());
    }

    @Override
    public int hashCode() {
        return 1;
    }
    @Override
    public boolean equals(Object object) {
        if (object instanceof User){
            return number.equals(((User) object).number);
        }
        return false;
    }
}
class UserRecords {
    
    private ArrayList<MessageRecord> sendMessageRecords= new ArrayList<MessageRecord>();//
 
    public void addSendMessageRecords (MessageRecord sendMessageRecord)
    {
        sendMessageRecords.add(sendMessageRecord);
    }
    public  ArrayList<MessageRecord> getSendMessageRecords(){
        return this.sendMessageRecords;
    }
  
    
}
abstract class ChargeMode {

     protected ArrayList<MessageRule> chargeRules = new ArrayList<>();
    
     public ArrayList<MessageRule> getChargeRules() {
            return chargeRules;
        }

     public void setChargeRules(ArrayList<MessageRule> chargeRules) {
            this.chargeRules = chargeRules;
        }
     
     public abstract double calCost(UserRecords userRecords);

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

//    @Override
    public double calCost(UserRecords userRecords) {
         double cost = 0;
          
                int i = userRecords.getSendMessageRecords().size();
                if(i<=3) 
                {
                    cost += i*0.1;              
                }
                if(i>3&&i<5)
                {
                    cost += 0.3+0.2*(i-3);
                }
                if(i>=5)
                {
                    cost = 0.7+0.3*(i-5);
                }
            
            return cost;
        
    }

}
class MessageCharge extends ChargeMode {

    @Override
    public double calCost(UserRecords userRecords) {
         double cost = 0;
         
         MessageRule messageRule = new MessageRule();    
     
         cost += messageRule.calCost(userRecords);
            return cost;
}
} class Check {
    
    boolean check(String s) {
         if(s.matches("m-\\d{11} \\d{11} [A-Za-z0-9,.]+"))
        {
            return true;
        }
        
        return false;
    }
}
class GettrueLine {
     Check ck = new Check();
    String get(String s,Scanner in) {
        while(!ck.check(s)&&!s.equals("end")) {
            s = in.nextLine();
        }
        return s;
    }
}

 

这一次的比较简单,但比较遗憾的是笔者没能将判断内容是否符合的部分完成,正则表达式笔者掌握的还是不太到位,其他部分继承前两次大作业的思路就可以完成,还是比较简单的。

三、踩坑心得  

            这三次大作业还是踩到了坑的,比如第七次大作业,笔者做的时候因为一个bug一直通不过去,通过debug一步一步慢慢的查慢慢的看才找到是在前面计费种类错了把手机的计费记作了座机的计费,所以在设计的时候一定要明确,不然一个小小的地方出了问题整个就会出错。还有一处错误比较低级,第八次大作业的短信计费,看老师题目要求和实际短信收费是不一样的,老师出题不够严谨,所以有些数据是需要进行改变的,这个坐了的自然会发现。


四、改进建议

        改进意见的话就是题目可以稍微严谨一点,可以多给一些测试样例,还有就是电话的跨越了一整天的电话收费,如果刚好是跨了月,跨了年,应该会有不同的计费方法,可以在后续进行修改,再就是希望可以多多给些类图,方便打出框架。

 

五、总结    

       总的来说,除了第八次大作业难度一降到底,完成的差不多,其他的还是没能很好完成,正则表达式笔者还是没完全掌握,不过笔者也逐渐感受到面向对象的好处,可以系统的完整的完成题目,还是希望老师可以多多讲解一些相关题目,方便更好理解。让笔者可以学习到正确的代码应该是什么样子的,这样笔者对题目的理解会更上一层楼。

 

posted @ 2022-06-09 00:31  小诚c  阅读(77)  评论(0)    收藏  举报