《原神攻略》2.7版夜蘭全面配裝測試與配置建議

        目錄

1.對前三次作業的大體分析

2.設計與分析

3. 踩坑心得

4. 改進建議

5. 總結

一. 對前三次大作業的大體分析

1. 前三次大作業總體是一個體系的題目,主要是關於電信計費的多種計費混合實現。

2. 第一次大作業是基礎,做好了第一次座機計費的基礎,後面兩次的計費方式也就差不多了。

3. 第二次大作業是電話計費,主要複雜的問題就是如何解決對輸入資訊的判定和提取。

4.第三次大作業是最為簡單的,主要就是對資訊計費的資訊提取計算即可。

二. 設計與分析

1.第一個習題集的設計分析

程式碼及其類圖如下

import java.util.ArrayList;

import java.util.Date;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.text.DecimalFormat;

import java.util.Collections;

import java.util.Comparator;

import java.util.Scanner;

abstractclass CallChargeRule extends ChargeRule{

publicdouble calCost(ArrayList<CallRecord> callRecords) {

return 0;

}

}

class CallRecord extends CommunicationRecord{

private Date startTime = new Date();

private Date endTime = new Date();

private String callingAddressAreaCode;

private String answerAddressAreaCode;

public CallRecord() {

}

public Date getStartTime() {

returnthis.startTime;

}

publicvoid setStartTime(Date startTime) {

this.startTime=startTime;

}

public Date getEndTime() {

returnthis.endTime;

}

publicvoid setEndTime(Date endTime) {

this.endTime=endTime;

}

public String getCallingAddressAreaCode() {

returnthis.callingAddressAreaCode;

}

publicvoid setCallingAddressAreaCode(String callingAddressAreaCode) {

String s = callingAddressAreaCode.substring(0, 4);

this.callingAddressAreaCode=s;

}

public String getAnswerAddressAreaCode() {

returnthis.answerAddressAreaCode;

}

publicvoid setAnswerAddressAreaCode(String answerAddressAreaCode) {

String s = answerAddressAreaCode.substring(0, 4);

this.answerAddressAreaCode=s;

}

}

abstractclass ChargeMode {

private ArrayList<ChargeRule> chargeRules = new ArrayList<ChargeRule>();

public ArrayList<ChargeRule> getChargeRule(){

returnthis.chargeRules;

}

publicvoid setChargeRule(ArrayList<ChargeRule> chargeRules) {

this.chargeRules=chargeRules;

}

publicdouble calCost(UserRecords userRecords) {

return 0;

}

publicdouble getMonthlyRent() {

return 0;

}

}

abstractclass ChargeRule {

}

abstractclass CommunicationRecord {

String callingNumber;

String answerNumber;

public String getCallingNumber(){

return callingNumber;

}

publicvoid setCallingNumber(String callingNumber) {

}

}

class InputHandle {

private String input;

public InputHandle(String input) {

this.input=input;

}

publicboolean InputIsQualified(String input) {

String[] str = input.split(" ");

if(str.length>1) {

String s2 = str[0];

String s3 = str[1];

if(s2.matches("^u-0791\\d{7,8}$")&&s3.equals("0")) {

returntrue;

}

else {

returnfalse;

}

}

else {

returnfalse;

}

}

publicboolean inputTwoIsQualified(String input) {

String[] str = input.split(" ");

if(str.length>2) {

if(str[2].matches("[\\d]{4}.((0([1-9]{1}))|(1[1|2])|([1-9])).(([0-2]([1-9]{1}))|(3[0|1])|([1|2]0)|([1-9]))")&&str[3].matches("([0-2][0-9]):([0-5][0-9]):([0-5][0-9])")&&str[4].matches("[\\d]{4}.((0([1-9]{1}))|(1[1|2])|([1-9])).(([0-2]([1-9]{1}))|(3[0|1])|([1|2]0)|([1-9]))")&&str[5].matches("([0-2][0-9]):([0-5][0-9]):([0-5][0-9])")) {

if(IsCallingNumber(input)==true&&IsAnswerNumber(input)==true) {

returntrue;

}

else {

returnfalse;

}

}

else {

returnfalse;

}

}

else {

returnfalse;

}

}

public String getUnumber(String input){

String[] s1 = input.split(" ");

String[] s2 = s1[0].split("-");

return s2[1];

}

public String getInputIntoCallingNumber(String input) {

String[] s1 = input.split(" ");

if(s1[0].matches("t-0\\d{10,11}")) {

String[] s2 = s1[0].split("-");

return s2[1];

}

else {

returnnull;

}

}

publicboolean IsCallingNumber(String input) {

if(getInputIntoCallingNumber(input)!=null) {

returntrue;

}

else {

returnfalse;

}

}

publicboolean IsAnswerNumber(String input) {

if(getInputIntoAnswerNumber(input)!=null) {

returntrue;

}

else {

returnfalse;

}

}

publicint WhereAreTheNumber(String s) {

if(s.matches("(0791)(\\d{7,8})")) {//電話為室內電話

return 1;

}

elseif(s.matches("(0790)(\\d{7,8})")||s.matches("(0701)(\\d{7,8})")||s.matches("^(079)([2-9]{1})(\\d{7,8})")) {//電話為省內電話

return -1;

}

else {//電話為國內電話

return 0;

}

}

public String getInputIntoAnswerNumber(String input) {

String[] s2 = input.split(" ");

if(s2[1].matches("^0\\d{10,11}")) {

return s2[1];

}

else {

returnnull;

}

}

public Date getInputIntoStartTime(String input) throws ParseException {

String[] s = input.split(" ");

String s2 = s[2]+" "+s[3];

Date d = new Date();

SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");

d = sdf1.parse(s2);

return d;

}

public Date getInputIntoEndTime(String input) throws ParseException {

String[] s = input.split(" ");

String s2 = s[4]+" "+s[5];

Date d = new Date();

SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");

d = sdf1.parse(s2);

return d;

}

}

class LandlinePhoneCharging extends ChargeMode {

double monthlyRent = 20;

@Override

publicdouble calCost(UserRecords userRecords) {

double s=0;

CallChargeRule c = new LandPhonelnCityRule();

CallChargeRule p = new LandPhonelnProvinceRule();

CallChargeRule l = new LandPhonelnlandRule();

s+=c.calCost(userRecords.getCallingInCityRecords());

s+=p.calCost(userRecords.getCallingInProvinceRecords());

s+=l.calCost(userRecords.getCallingInLandRecords());

return s;

}

@Override

publicdouble getMonthlyRent() {

returnthis.monthlyRent;

}

}

class LandPhonelnCityRule extends CallChargeRule{

@Override

publicdouble calCost(ArrayList<CallRecord> callRecords) {

double s=0;

for(CallRecord k: callRecords) {

long time1 = k.getStartTime().getTime();

long time2 = k.getEndTime().getTime();

long time = Math.abs(time1-time2);

if(time/1000%60==0) {

double minute = (double)(time/1000/60);

s=s+0.1*minute;

}

else {

double minute = (double)(time/1000/60);

s=s+0.1*(minute+1);

}

}

return s;

}

}

class LandPhonelnlandRule extends CallChargeRule{

@Override

publicdouble calCost(ArrayList<CallRecord> callRecords) {

double s=0;

for(CallRecord k: callRecords) {

long time1 = k.getStartTime().getTime();

long time2 = k.getEndTime().getTime();

long time = Math.abs(time1-time2);

if(time/1000%60==0) {

double minute = (double)(time/1000/60);

s=s+0.6*minute;

}

else {

double minute = (double)(time/1000/60);

s=s+0.6*(minute+1);

}

}

return s;

}

}

class LandPhonelnProvinceRule extends CallChargeRule{

@Override

publicdouble calCost(ArrayList<CallRecord> callRecords) {

double s=0;

for(CallRecord k: callRecords) {

long time1 = k.getStartTime().getTime();

long time2 = k.getEndTime().getTime();

long time = Math.abs(time1-time2);

if(time/1000%60==0) {

double minute = (double)(time/1000/60);

s=s+0.3*minute;

}

else {

double minute = (double)(time/1000/60);

s=s+0.3*(minute+1);

}

}

return s;

}

}

publicclass Main {

publicstaticvoid main(String[] args) throws ParseException {

Scanner sc = new Scanner(System.in);

CallRecord c;

UserRecords userRecord;

LandlinePhoneCharging l = new LandlinePhoneCharging();

ArrayList<User> users = new ArrayList<User>();

while (true) {

int t=0;

String s = sc.nextLine();

InputHandle input = new InputHandle(s);

if(input.InputIsQualified(s)) {

t++;

if(users.isEmpty()) {

User u2 = new User();

String[] s1 = s.split(" ");

String s2 = s1[0].substring(2);

u2.setNumber(s2);

u2.setChargeMode(l);

users.add(u2);

userRecord = new UserRecords();

u2.setUserRecords(userRecord);

}

else {

for(User u:users) {

if(u.getNumber().equals(input.getUnumber(s))) {

t++;

}

}

if(t==1) {

User u2 = new User();

String[] s1 = s.split(" ");

String s2 = s1[0].substring(2);

u2.setNumber(s2);

u2.setChargeMode(l);

users.add(u2);

userRecord = new UserRecords();

u2.setUserRecords(userRecord);

}

}

}

elseif(input.inputTwoIsQualified(s)) {

for(User ur : users) {

if(ur.getNumber().equals(input.getInputIntoCallingNumber(s))||ur.getNumber().equals(input.getInputIntoAnswerNumber(s))) {

c = new CallRecord();

c.setAnswerAddressAreaCode(input.getInputIntoAnswerNumber(s));

c.setCallingAddressAreaCode(input.getInputIntoCallingNumber(s));

c.setStartTime(input.getInputIntoStartTime(s));

c.setEndTime(input.getInputIntoEndTime(s));

if(input.WhereAreTheNumber(input.getInputIntoAnswerNumber(s))==0) {

ur.getUserRecords().addCallingInLandRecords(c);

}

if(input.WhereAreTheNumber(input.getInputIntoAnswerNumber(s))==1) {

ur.getUserRecords().addCallingInCityRecords(c);

}

if(input.WhereAreTheNumber(input.getInputIntoAnswerNumber(s))==-1) {

ur.getUserRecords().addCallingInProvinceRecords(c);

}

}

}

}

else {

if(s.equals("end")) {

break;

}

}

}

users=sort(users);

for(User ur2:users) {

System.out.println(ur2.getNumber()+" "+OutFormat.doubleFormat(ur2.calCost())+" "+OutFormat.doubleFormat(ur2.calBalance()));

}

sc.close();

}

publicstatic ArrayList<User> sort(ArrayList<User> us) {

Collections.sort(us,new Comparator<User>() {

@Override

publicint compare(User o1, User o2) {

if(o1.getNumber().compareTo(o2.getNumber())>0)

return 1;

else {

return -1;

}

}

});

return us;

}

}

class MessageRecord extends CommunicationRecord{

String message;

public String getMessage() {

returnthis.message;

}

publicvoid setMessage(String message) {

this.message=message;

}

}

class OutFormat {

publicstatic Double doubleFormat(double b) {

DecimalFormat df = new DecimalFormat("#.0");

Double output = Double.valueOf(df.format(b));

return output;

}

}

class User {

private UserRecords userRecords = new UserRecords();

privatedouble balance = 100;

private ChargeMode chargeMode;

private String number;

public User(InputHandle inputHandle) {

}

public User() {

}

publicdouble calBalance() {

this.balance = this.getBalance()-this.calCost()-this.chargeMode.getMonthlyRent();

returnthis.balance;

}

publicdouble calCost() {

returnthis.chargeMode.calCost(this.userRecords);

}

public UserRecords getUserRecords() {

returnthis.userRecords;

}

publicvoid setUserRecords(UserRecords userRecords) {

this.userRecords=userRecords;

}

publicdouble getBalance() {

returnthis.balance;

}

publicvoid setChargeMode(ChargeMode chargeMode) {

this.chargeMode=chargeMode;

}

public ChargeMode getChargeMode() {

returnthis.chargeMode;

}

publicvoid setNumber(String number) {

this.number=number;

}

public String getNumber() {

returnthis.number;

}

}

class UserRecords {//包括3種撥打記錄和3種接聽記錄和2種簡訊記錄

private ArrayList<CallRecord> callingInCityRecords = new ArrayList<CallRecord>();

private ArrayList<CallRecord> callingInProvinceRecords = new ArrayList<CallRecord>();

private ArrayList<CallRecord> callingInLandRecords = new ArrayList<CallRecord>();

private ArrayList<CallRecord> answerInCityRecords = new ArrayList<CallRecord>();

private ArrayList<CallRecord> answerInProvinceRecords = new ArrayList<CallRecord>();

private ArrayList<CallRecord> answerInLandRecords = new ArrayList<CallRecord>();

private ArrayList<MessageRecord> sendMessageRecords = new ArrayList<MessageRecord>();

private ArrayList<MessageRecord> receiveMessageRecords = new ArrayList<MessageRecord>();

public UserRecords() {

}

publicvoid addCallingInCityRecords(CallRecord callRecord) {

this.callingInCityRecords.add(callRecord);

}

publicvoid addCallingInProvinceRecords(CallRecord callRecord) {

this.callingInProvinceRecords.add(callRecord);

}

publicvoid addCallingInLandRecords(CallRecord callRecord) {

this.callingInLandRecords.add(callRecord);

}

publicvoid addAnswerInCityRecords(CallRecord callRecord) {

this.answerInCityRecords.add(callRecord);

}

publicvoid addAnswerInProvinceRecords(CallRecord callRecord) {

this.answerInProvinceRecords.add(callRecord);

}

publicvoid addAnswerInLandRecords(CallRecord callRecord) {

this.answerInLandRecords.add(callRecord);

}

publicvoid addSendMessageRecords (MessageRecord messageRecord) {

this.sendMessageRecords.add(messageRecord);

}

publicvoid addReceiveMessageRecords (MessageRecord messageRecord) {

this.receiveMessageRecords.add(messageRecord);

}

public ArrayList<MessageRecord> getSendMessageRecords(){

returnthis.sendMessageRecords;

}

public ArrayList<MessageRecord> getReceiveMessageRecords(){

returnthis.receiveMessageRecords;

}

public ArrayList<CallRecord> getCallingInCityRecords(){

returnthis.callingInCityRecords;

}

public ArrayList<CallRecord> getCallingInProvinceRecords(){

returnthis.callingInProvinceRecords;

}

public ArrayList<CallRecord> getCallingInLandRecords(){

returnthis.callingInLandRecords;

}

public ArrayList<CallRecord> getAnswerInCityRecords(){

returnthis.answerInCityRecords;

}

public ArrayList<CallRecord> getAnswerInProvinceRecords(){

returnthis.answerInProvinceRecords;

}

public ArrayList<CallRecord> getAnswerInLandRecords(){

returnthis.answerInLandRecords;

}

}

 

 下面是我的複雜度分析圖

1. 因為有了已經知道的類圖,所以只需要根據類圖設計就可以了。

2. 在實現user資訊的錄入和判定資訊邏輯有點複雜,需要多次測試去完善判定資訊和條件。

3.在main函式中有太多的if,else判斷,極大的提高了我的類複雜度。

4.在對資料處理的函式中,我對每一個方法都進行了註釋,因為很多方法都差不多,不填上註釋很容易用錯。

2.第二個習題集的分析

 設計上:在設計手機的計費方式中,我沿用座機計費的程式碼,並補充對手機計費的方法,同時在main函式中新增手機計費的內容。

elseif(input.inputTwoIsQualified(s)) {//座機打座機

for(User ur : users) {

if(ur.getNumber().equals(input.getInputIntoCallingNumber(s))||ur.getNumber().equals(input.getInputIntoAnswerNumber(s))) {

c = new CallRecord();

c.setAnswerAddressAreaCode(input.getInputIntoAnswerNumber(s));

c.setCallingAddressAreaCode(input.getInputIntoCallingNumber(s));

c.setStartTime(input.getInputIntoStartTime(s));

c.setEndTime(input.getInputIntoEndTime(s));

if(!ur.getNumber().equals(input.getInputIntoAnswerNumber(s))||input.getInputIntoCallingNumber(s).equals(input.getInputIntoAnswerNumber(s))) {

if(input.WhereAreTheNumber(input.getInputIntoAnswerNumber(s))==0) {

ur.getUserRecords().addCallingInLandRecords(c);

}

if(input.WhereAreTheNumber(input.getInputIntoAnswerNumber(s))==1) {

ur.getUserRecords().addCallingInCityRecords(c);

}

if(input.WhereAreTheNumber(input.getInputIntoAnswerNumber(s))==-1) {

ur.getUserRecords().addCallingInProvinceRecords(c);

}

}

}

}

}

elseif(input2.IsLandPhoneToSmartPhone(s)) {//座機打手機

for(User ur : users) {

if(ur.getNumber().equals(input2.zuojiCallNumber(s))||ur.getNumber().equals(input2.smartAnswerNumber(s))) {

c = new CallRecord();

c.setCallingAddressAreaCode(input2.zuojiCallCode(s));

c.setAnswerAddressAreaCode(input2.smartAnswerCode(s));

c.setStartTime(input2.getInputIntoStartTime(s));

c.setEndTime(input2.getInputIntoEndTime(s));

if(ur.getNumber().equals(input2.zuojiCallNumber(s))) {//使用者為撥打使用者

if(input2.WhereAreTheSmartPhoneNumber(input2.smartAnswerCode(s))==1) {//為座機市內打電話且手機接聽省內

ur.getUserRecords().addCallingInCityRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.smartAnswerCode(s))==-1) {//為座機省內打電話且手機接聽省內

ur.getUserRecords().addCallingInProvinceRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.smartAnswerCode(s))==0) {//為座機國內打電話且手機接聽省內

ur.getUserRecords().addCallingInLandRecords(c);

}

}

if(ur.getNumber().equals(input2.smartAnswerNumber(s))){//使用者為接聽使用者

if(input2.WhereAreTheSmartPhoneNumber(input2.smartAnswerCode(s))==0) {

ur.getUserRecords().addAnswerInLandRecords(c);

}

}

}

}

}

elseif(input2.IsTheQualitiedInput(s)) {//手機打手機||手機打座機

for(User ur : users) {

if(ur.getNumber().equals(input2.getInputIntoSmartPheoneCallingNumber(s))||ur.getNumber().equals(input2.getInputIntoSmartPheoneAnswerNumber(s))) {

String[] s1 = s.split(" ");

if(s1.length==7) {//手機打座機

c = new CallRecord();

c.setCallingAddressAreaCode(input2.getInputIntoPhoneCallingCode(s));

c.setAnswerAddressAreaCode(input2.getInputIntoLandAnswerCode(s));

c.setStartTime(input2.getInputIntoStartTime(s));

c.setEndTime(input2.getInputIntoEndTime(s));

if(ur.getNumber().equals(input2.getInputIntoSmartPheoneCallingNumber(s))) {

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==1&&input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoLandAnswerCode(s))==1) {

ur.getUserRecords().addCallingInCityRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==1&&input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoLandAnswerCode(s))==-1) {

ur.getUserRecords().addCallingInProvinceRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==1&&input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoLandAnswerCode(s))==0) {

ur.getUserRecords().addCallingInLandRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==-1) {

ur.getUserRecords().addCallingInProvinceRoamingRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==0) {

ur.getUserRecords().addCallingInLandRoamingRecords(c);

}

}

}

else {//手機打手機

c = new CallRecord();

c.setCallingAddressAreaCode(input2.getInputIntoPhoneCallingCode(s));

c.setAnswerAddressAreaCode(input2.getInputIntoSmartAnswerCode(s));

c.setStartTime(input2.getInputIntoStartTime(s));

c.setEndTime(input2.getInputIntoEndTime(s));

if(ur.getNumber().equals(input2.getInputIntoSmartPheoneCallingNumber(s))) {//該使用者為撥打使用者

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==1&&input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoSmartAnswerCode(s))==1) {

ur.getUserRecords().addCallingInCityRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==1&&input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoSmartAnswerCode(s))==-1) {

ur.getUserRecords().addCallingInProvinceRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==1&&input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoSmartAnswerCode(s))==0) {

ur.getUserRecords().addCallingInLandRecords(c);

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==0) {

ur.getUserRecords().addCallingInLandRoamingRecords(c);;

}

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoPhoneCallingCode(s))==-1) {

ur.getUserRecords().addCallingInProvinceRoamingRecords(c);

}

}

if(ur.getNumber().equals(input2.getInputIntoSmartPheoneAnswerNumber(s))) {//該使用者為接聽使用者

if(input2.WhereAreTheSmartPhoneNumber(input2.getInputIntoSmartAnswerCode(s))==0) {

ur.getUserRecords().addAnswerInLandRecords(c);

}

}

}

}

}

}

 分析:基本的思路和方法處理第一次習題差不多,就是多了對手機資訊的處理和手機座機混合輸入的處理,

但是由於沿用了第一次習題的main類,所以在其中又加入了手機,手機座機的資訊判斷處理,導致main裡面有更多的if-else判斷,加大了main的圈複雜度。

3.第三個題目集的分析

分析:因為這個題目集的難度偏低,實現起來比較容易,所以在main裡面的判斷少了些許,圈複雜度明顯低與前兩題。

三.踩坑心得

1.第一個習題集在處理字串的判斷時,正則表示式出錯了,對正則表示式的使用還不太熟悉。

2.在儲存user的相關資訊時,需要判斷是否為空的情況,如果為空也得add一個user。

3.第二個習題集中,出現了很多userecord的儲存錯誤,主要是根據提取的資訊號碼和區號去選擇set相應的user和callRecord的相關資訊

4. 在第三個題目集的計算中,需要注意簡訊的長度,根據簡訊的長度計算不同的收費。

四.改進建議

1.將main中的對輸入資訊的if-else判斷放在一個單獨的邏輯判斷類中,以此減少夯餘的if-else判斷。

2.可以考慮採用繼承的方法去實現對手機,座機資訊的提取和判斷,從而減少程式碼的重複。

五.總結

1.學會使用繼承和多型簡化重複的程式碼

2.學會了使用Arrilist操作多個物件,並學會使用其中的各類方法。

3.學習並加強使用了正則表示式,利用正則表示式簡化格式問題。

4.學會了用容器介面和多型的複用。

5.深刻體會了類的設計的單一原則的重要性,避免在一個類中設計多個交叉呼叫的方法。

以上是 《原神攻略》2.7版夜蘭全面配裝測試與配置建議 的全部内容, 来源链接: utcz.com/yxgl/576602.html

回到顶部