这两次迭代的难度对我而言比较大,而且临近期末,不可能再像之前一样花大把时间debug,所以都没拿到满分。
设计知识点:
数据分类,比较器等,更多的应该是物理电学知识,比如短路,短路逻辑的判断,接地线电压为,将串联电路和并联电路看做一个用电器等,这对物理基础和逻辑不清晰的同学来说写代码难度比较大。
总共就两道题,但难度可不小。平均要花一到两天时间写完。

题7:
智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。以下题目介绍中加粗的部分为本次迭代在“家居强电电路模拟程序-2”的基础上增加的功能要求。

1、控制设备

本题模拟的控制设备包括:开关、分档调速器、连续调速器、互斥开关。

开关:包括0和1两种状态。

开关有两个引脚,任意一个引脚都可以是输入引脚(接往电源端),而另一个则是输出引脚(接网接地端)。开关状态为0时,无论输入电位是多少,输出引脚电位为0。当开关状态为1时,输出引脚电位等于输入电位。
互斥开关:

互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚。

开关电路示意图如图1所示,左边是汇总引脚,编号为1;右边两个是分支引脚,右上的输出引脚为2,右下输出引脚为3。图中1、2、3引脚均可以是输入引脚,当1为输入引脚时,2、3引脚为输出引脚;1为输出引脚时,2、3引脚为输入引脚。

互斥开关只有两种状态:开关接往上面的2号引脚、接往下面的3号引脚。开关每次只能接通其中一个分支引脚,而另一个分支引脚处于断开状态。

互斥开关的默认状态为1、2引脚接通,1、3引脚断开。

图1中所示的互斥开关可以反过来接入电路,即汇总引脚接往接地端,两个分支引脚接往电源端。
image.png

图1 互斥开关

为避免短路,互斥开关设置了限流电阻,12引脚之间默认电阻为5,13引脚之间默认电阻为10。

分档调速器

按档位调整,常见的有3档、4档、5档调速器,档位值从0档-2(3/4)档变化。本次迭代模拟4档调速器,每个档位的输出电位分别为0、0.3、0.6、0.9倍的输入电压。
连续调速器

没有固定档位,按位置比例得到档位参数,数值范围在[0.00-1.00]之间,含两位小数。输出电位为档位参数乘以输入电压。
所有调速器都有两个引脚,一个固定的输入(引脚编号为1)、一个输出引脚(引脚编号为2)。当输入电位为0时,输出引脚输出的电位固定为0,不受各类开关调节的影响。

开关、调速器的初始状态/档位为0。

调速器的输入引脚编号为1,输出引脚编号为2。
除互斥开关外,其他控制设备的电阻为 0。

2、受控设备

本题模拟的受控设备包括:灯、风扇。两种设备都有两根引脚,通过两根引脚电压的电压差驱动设备工作。

灯有两种工作状态:亮、灭。在亮的状态下,有的灯会因引脚电位差的不同亮度会有区别。
风扇在接电后有两种工作状态:停止、转动。风扇的转速会因引脚间电位差的不同而有区别。
本次迭代模拟两种灯具。

白炽灯:

亮度在0~200lux(流明)之间。
电位差为0-9V时亮度为0,其他电位差按比例,电位差10V对应50ux,220V对应200lux,其他电位差与对应亮度值成正比。白炽灯超过220V。
日光灯:

亮度为180lux。
只有两种状态,电位差为0时,亮度为0,电位差不为0,亮度为180。
本次迭代模拟两种风扇。

吊扇:

工作电压区间为80V-150V,对应转速区间为80-360转/分钟。80V对应转速为80转/分钟,150V对应转速为360转/分钟,超过150V转速为360转/分钟(本次迭代暂不考虑电压超标的异常情况)。其他电压值与转速成正比,输入输出电位差小于80V时转速为0。
落地扇:

工作电压区间为 80V-150V,对应转速区间为 80-360 转/分钟;[80V,100V) 对应转速为 80 转/分钟;[100,120)V 对应转速为 160 转/分钟;[120,140)V 对应转速为 260 转/分钟;大于等于 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况)。

本次迭代模拟一种受控窗帘:

受控窗帘的电路符号为S,其最低工作电压为50V,电压达到或超过50V,窗帘即可正常工作,不考虑室外光照强度和室内空间大小等因素,窗帘受室内灯光的光照强度控制。

当电路中所有灯光的光照强度总和在[0,50)lux范围内,窗帘全开;
在[50,100)lux范围内,窗帘打开比例为0.8;
在[100,200)lux范围内,窗帘打开比例为0.6;
在[200,300)lux范围内,窗帘打开比例为0.4;
在[300,400)lux范围内,窗帘打开比例为0.2;
在400lux及以上范围内,窗帘关闭。
当电压低于50V,窗帘不工作,默认为全开状态。
如果电路中没有灯或者灯全部关闭,光照强度为0,窗帘处于全开状态。
受控设备电阻:白炽灯的电阻为 10,日光灯的电阻为 5,吊扇的电阻为 20,落地扇的电阻为 20,窗帘电阻为15。

3、输入信息

1)输入设备信息

分别用设备标识符K、F、L、B、R、D、A、H、S分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇、互斥开关、受控窗帘。

设备标识用标识符+编号表示,如K1、F3、L2等。
引脚格式:设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。

开关、分档调速器、连续调速器的输入引脚编号为1,输出引脚编号为2。
受控设备的两个引脚编号分别为1、2。
互斥开关的引脚编号已经在互斥开关的介绍部分说明。
约束条件:

不同设备的编号可以相同。
同种设备的编号可以不连续。
设备信息不单独输入,包含在连接信息中。

2)输入连接信息

一条连接信息占一行,用[]表示一组连接在一起的设备引脚,引脚与引脚之间用英文空格" "分隔。

格式:"["+引脚号+" "+引脚号+"]"
例如:[K1-1 K3-2]表示K1的1引脚,K3的2引脚连接在一起。
约束条件:

不考虑调速器串联到其他调速器的情况。
考虑各类设备的并联接入。例如,K1 的输出接到 L2 的输入,L2 的输出再接其他设备属于串联接线。K1 的输出接到 L2 的输出,同时 K1 的输入接到 L2 的输入,这种情况属于并联。

本次迭代的连接信息不单独输入,包含在线路信息中。

3)输入控制设备调节信息

开关、互斥开关调节信息格式:

+设备标识K+设备编号,例如:#K2,代表切换K2开关的状态。

+设备标识H+设备编号,例如:#H2,代表切换H2互斥开关的状态。

分档调速器的调节信息格式:

+设备标识F+设备编号+"+" 代表加一档,例如:#F3+,代表F3输出加一档。

+设备标识F+设备编号+"-" 代表减一档,例如:#F1-,代表F1输出减一档。

连续调速器的调节信息格式:

+设备标识L+设备编号+":" +数值 代表将连续调速器的档位设置到对应数值,例如:#L3:0.6,代表L3输出档位参数0.6。

4)电源接地标识:

VCC,电压220V,GND,电压0V。没有接线的引脚默认接地,电压为0V。

5)输入串联电路信息

一条串联电路占一行,串联电路由按从靠电源端到接地端顺序依次输入的 n 个连接 信息组成,连接信息之间用英文空格" "分隔。

串联电路信息格式:

"#T"+电路编号+":"+连接信息+" "+连接信息+...+" "+连接信息
例如:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] 一个串联电路的第一个引脚是 IN,代表起始端,靠电源。最后一个引脚是 OUT,代表结尾端, 靠接地。
约束条件:

不同的串联电路信息编号不同。

输入的最后一条电路信息必定是总电路信息,总电路信息的起始引脚是 VCC,结束引脚是 GND。

连接信息中的引脚可能是一条串联或并联电路的 IN 或者 OUT。例如:

T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT OUT]

T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT M2-IN] [M2-OUT OUT]

6)输入并联电路信息

一条并联电路占一行,并联电路由其包含的几条串联电路组成,串联电路标识之间用英文空格" "分隔。

格式:

"#M"+电路编号+":"+”[”+串联电路信息+" "+....+" "+串联电路信息+”]”
例如:#M1:[T1 T2 T3]
该例声明了一个并联电路,由 T1、T2、T3 三条串联电路并联而成,三条串联电路的 IN 短 接在一起构成 M1 的 IN,三条串联电路的 OUT 短接在一起构成 M1 的 OUT。
约束条件:

本次迭代不考虑并联电路中包含并联电路的情况。
本题不考虑输入电压或电压差超过220V的情况。

输入信息以end为结束标志,忽略end之后的输入信息。

本题中的并联信息所包含的串联电路的信息都在并联信息之前输入,不考虑乱序输入的情况。
只要不因短路而造成无穷大的电流烧坏电路(如电路中的部分短接),都是合理情况,在测试点的考虑范围之内。会造成无穷大的电流的短路本次迭代不考虑。

本次迭代考虑多个并联电路串联在一起的情况。

本题考虑一条串联电路中包含其他串联电路的情况。例如:

T3:[VCC K1-1] [K1-2 T2-IN] [T2-OUT K2-1] [K2-2 T1-IN] [T1-OUT GND]

本例中T1\T2两条串联电路T3的一个部分,本题考虑这种类型的输入。

4、输出信息:

按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、互斥开关、受控窗帘的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。

输出格式:

@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位)
连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。
开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed
如:
@K1:turned on
@B1:190
@L1:0.60
互斥开关显示1、2引脚的接通状态,接通时显示closed,断开时显示turned on。

如:

@H1:turned on

受控窗帘显示窗帘打开的百分比,如:

@S1:80%

5、家居电路模拟系列所有题目的默认规则:

1)当计算电压值等数值的过程中,最终结果出现小数时,用截尾规则去掉小数部分,只保留整数部分。为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算,不要作下转型数据类型转换,例如电压、转速、亮度等,只有在最后输出时再把计算结果按截尾规则,舍弃尾数,保留整数输出。

2)所有连接信息按电路从电源到接地的顺序依次输入,不会出现错位的情况。电源VCC一定是第一个连接的第一项,接地GND一定是最后一个连接的后一项。

3)连接信息如果只包含两个引脚,靠电源端的引脚在前,靠接地端的在后。

4)调速器的输入端只会直连VCC,不会接其他设备。整个电路最多只有连接在电源上的一个调速器,且不包含在并联单路中。

6、家居电路模拟系列1-4题目后续迭代设计:

1)电路结构变化:

迭代1:只有一条线路,所有元件串联
迭代2:线路中包含一个并联电路
迭代3:线路中包含多个串联起来的并联电路
迭代4:并联电路之间可能出现包含关系

电路结构变化示意图见图1。

2)计算方式的变化

迭代1只包含1个受控元件,不用计算电流,之后的电路计算要包含电流、电阻等电路参数。

3)电路元件的变化

每次迭代会增加1-2个新的电路元件。

image.png

图1:电路结构示意图

设计建议:

1、电路设备类:描述所有电路设备的公共特征。

2、受控设备类、控制设备类:对应受控、控制设备

3、串联电路类:一条由多个电路设备构成的串联电路,也看成是一个独立的电路设备

4、并联电路类:继承电路设备类,也看成是一个独立的电路设备

我的源码:

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
private static StoreAllinfo sa = new StoreAllinfo();
public static void main(String[] args) {

    //信息分流 -> 信息配置
    Cuanlian mainLian =infoSort();

    mainLian.setTv(220.0);

    // 分配电压
    mainLian.allocateV();

    //展示信息
    showAllInfo(mainLian);

}

private static Cuanlian infoSort() {
    Scanner in = new Scanner(System.in);

    Cuanlian mainCuanlian = new Cuanlian();
    //一行的信息
    ArrayList<String> lineInfo = new ArrayList<>();
    //设备配置的信息
    ArrayList<String> peizhiInfo = new ArrayList<>();
    //并联电路的信息
    ArrayList<String> binglianInfo = new ArrayList<>();

    String tempStr = "";

    while (true) {
        tempStr = in.nextLine();

        if (tempStr.equals("end")) {
            break;
        }

        if (tempStr.charAt(1) == 'T') {
            lineInfo.add(tempStr);
        } else if (tempStr.charAt(1) == 'M') {
            binglianInfo.add(tempStr);
        } else {
            peizhiInfo.add(tempStr);
        }
    }

    ArrayList<Cuanlian> cuanlians = new ArrayList<>();
    for (int lindex = 0; lindex < lineInfo.size(); lindex++) {
        Cuanlian cl = new Cuanlian();
        //经过鉴定为主串联



        cl.setName(lineInfo.get(lindex).substring(1, 3));

        String name = "";
        String type = "";

        ArrayList<String> machine = getMachine(lineInfo.get(lindex).substring(4));

        for (int mindex = 0; mindex < machine.size(); mindex++) {
            type = machine.get(mindex).substring(0, 1);
            name = machine.get(mindex);
            switch (type) {
                case "K": {
                    Kaiguan kg = new Kaiguan();
                    kg.setIsClose(0);
                    kg.setName(name);
                    cl.addKaiguans(kg);
                    sa.addKaiguan(kg);
                }
                ;
                break;
                case "F": {
                    Fendang fd = new Fendang();
                    fd.setName(name);
                    cl.setFendang(fd);

                }
                ;
                break;
                case "L": {
                    Lianxu lx = new Lianxu();
                    lx.setName(name);
                    cl.setLianxu(lx);

                }
                ;
                break;
                case "B": {
                    Baizhideng bz = new Baizhideng();
                    bz.setName(name);
                    cl.addYongdianqi(bz);
                    sa.addBaizhideng(bz);
                }
                ;
                break;
                case "R": {
                    Riguangdeng rgd = new Riguangdeng();
                    rgd.setName(name);
                    cl.addYongdianqi(rgd);
                    sa.addRiguangdeng(rgd);
                }
                ;
                break;
                case "D": {
                    Diaosan ds = new Diaosan();
                    ds.setName(name);
                    cl.addYongdianqi(ds);
                    sa.addDiaosan(ds);
                }
                ;
                break;
                case "A": {
                    Ruodisan rd = new Ruodisan();
                    rd.setName(name);
                    cl.addYongdianqi(rd);
                    sa.addRuodisan(rd);
                }
                break;
                case "H": {
                    Huchikaiguan hcg = new Huchikaiguan();
                    for (int i = 0; i < cuanlians.size(); i++) {
                        if(cuanlians.get(i).getHk().getName().equals(name)){
                            hcg = cuanlians.get(i).getHk();

                        }
                    }
                    hcg.setName(name);
                    cl.setHkLeadFoot(getLeadFootLine(lineInfo.get(lindex)));
                    cl.setHk(hcg);
                    sa.addHuchikaiguan(hcg);
                }
                break;
                case "S": {
                    Chuanglian cuanglian = new Chuanglian();
                    cuanglian.setName(name);
                    cl.addYongdianqi(cuanglian);
                    sa.addCuanglian(cuanglian);
                }
                break;
            }
        }
        if (lineInfo.get(lindex).charAt(5) == 'V') {
            cl.setMainCuircuit();
            mainCuanlian = cl;
        }
        cuanlians.add(cl);

    }


    ArrayList<Binglian> binglians = new ArrayList<>();
    for (int bindex = 0; bindex < binglianInfo.size(); bindex++) {
        String name = binglianInfo.get(bindex).substring(1, 3);
        Binglian bl = new Binglian();
        bl.setName(name);

        ArrayList<String> TsIn = new ArrayList<>();
        String regex = "\\[([^\\$$]+)\\]";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(binglianInfo.get(bindex));

        if (matcher.find()) {
            String contents = matcher.group(1);
            String[] str = contents.split("\\s+");
            for (String s : str) {
                TsIn.add(s);
            }
        }
        for (int tindex = 0; tindex < TsIn.size(); tindex++) {
            for (int cindex = 0; cindex < cuanlians.size(); cindex++) {
                if(cuanlians.get(cindex).getName().equals(TsIn.get(tindex))){
                    bl.addCuanlian(cuanlians.get(cindex));
                    break;
                }
            }
        }

        binglians.add(bl);
    }




    electricArrange(cuanlians,peizhiInfo);
    cuanlians.remove(mainCuanlian);
    for (int i = 0; i < binglians.size(); i++) {
        mainCuanlian.addYongdianqi(binglians.get(i));
    }

    for (int bindex = 0; bindex < binglians.size(); bindex++) {
        for (int cindex = 0; cindex < binglians.get(bindex).getCuanlians().size(); cindex++) {
            for (int clindex = 0; clindex < cuanlians.size(); clindex++) {
                if(binglians.get(bindex).getCuanlians().get(cindex) == cuanlians.get(clindex)){
                    cuanlians.remove(clindex);
                }
            }
        }
    }

    if(cuanlians.size()!=0){
        for (int i = 0; i < cuanlians.size(); i++) {
            mainCuanlian.addYongdianqi(cuanlians.get(i));
        }
    }
    return mainCuanlian;

    /*

T1:[IN H1-1] [H1-2 D2-1] [D2-2 OUT]

T2:[IN H1-1] [H1-3 D1-1] [D1-2 OUT]

M1:[T1 T2]

T4:[IN K3-1] [K3-2 B2-1] [B2-2 OUT]

T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]

M2:[T4 T5]

T3:[VCC K2-1] [K2-2 M1-IN] [M1-OUT M2-IN] [M2-OUT GND]

K1

K2

H1

end

     */
}
private static void electricArrange(ArrayList<Cuanlian> cuanlians,ArrayList<String> peizhiInfo){
    for (int peindex = 0; peindex < peizhiInfo.size(); peindex++) {
        //#K1 #F1+ #H1 #L1:1.00
        char peType = peizhiInfo.get(peindex).charAt(1);

        //好奇怪呀,为什么这个“”如果打在最后面name 就变成一个三位数了?
        String name = peizhiInfo.get(peindex).charAt(1)+""+peizhiInfo.get(peindex).charAt(2);//+peizhiInfo.get(peindex).charAt(2);

        //对于每一条通路,对得上的用电器,就将其信息进行修改
        //并且只有主路线才考虑调速器
        //其他通路只考虑开关与限制开关,并且保证限制开关即使会改变两次,也只是重复修改而已,并不影响结果

        //信息流循环 信息size ,对于每 单个信息 ,都会循环一次 通路 ,每个通路都会循环一次 电器size, 故每一条信息应该都被
        //考虑进去了
        loop:for (int cindex = 0; cindex < cuanlians.size(); cindex++) {

            if(cuanlians.get(cindex).isMainCuircuit()){
                switch (peType){
                    case 'F':{
                        char done = peizhiInfo.get(peindex).charAt(3);
                        if (done == '+') {
                            //我这里有一个 Yongdianqi 类的对象 dianqi ,我需要如何将它向下转型为
                            // 它的子类 Fenduan ,并且调用它的方法 .addStep()?
                            cuanlians.get(cindex).getFendang().addStep();
                        } else if(done == '-'){
                            cuanlians.get(cindex).getFendang().downStep();
                        }

                    }break;
                    case 'L':{
                        String para = peizhiInfo.get(peindex).substring(4);
                        cuanlians.get(cindex).getLianxu().setPara(Integer.parseInt(para));
                    }break;
                }
            }

            //如果现在的用电器类型与信息流里的不匹配,那么就直接跳过

            switch (peType){
                case 'K':{
                    //对于每一条通路的全部开关,先检测开关名字是否对得上,然后再对对得上的进行修改
                    for (int kaindex = 0; kaindex < cuanlians.get(cindex).getKaiguans().size(); kaindex++) {
                        Kaiguan kg = cuanlians.get(cindex).getKaiguans().get(kaindex);
                        if(kg.getName().equals(name)){
                            kg.Switch();
                            break;
                        }
                    }

                }break;
                case 'H':{
                    if(cuanlians.get(cindex).getHk() == null){
                        break;
                    }
                    if(cuanlians.get(cindex).getHk().getName().equals(name)){
                        cuanlians.get(cindex).getHk().switchLeadFoot();
                        break loop;
                    }
                }break;
            }

        }
    }

}

private static int getLeadFootLine(String s) {
    char[] chars = s.toCharArray();
    for (int i = 0; i < chars.length - 1; i++) {
        if(chars[i] == 'H'){
            if(chars[i-1] == '['){
                if(chars[i+3] == '3' || chars[i+3] == '2'){
                    return Integer.parseInt(chars[i+3]+"");
                }
            } else if(chars[i+4] == ']'){
                if(chars[i+3] == '3' || chars[i+3] == '2'){
                    return Integer.parseInt(chars[i+3]+"");
                }
            }
        }
    }
    return 0;
}

private static ArrayList<String> getMachine(String line) {
    ArrayList<String> returnStr = new ArrayList<>();
    String[] stringArr = line.split(" ");
    String regex = "\\b([A-Z]+\\d)";

    // 编译正则表达式
    Pattern pattern = Pattern.compile(regex);
    HashSet<String> found = new HashSet<>();  // 使用HashSet避免重复

    for (String test : stringArr) {
        Matcher matcher = pattern.matcher(test);
        while (matcher.find()) {
            found.add(matcher.group(1));
        }
    }

    Iterator<String> iterator = found.iterator();
    while (iterator.hasNext()) {
        returnStr.add(iterator.next());
    }

    return returnStr;
}

private static void showAllInfo(Cuanlian mainLian) {
    //开关
    sa.showAllKai();
    //主路线的分档调速器
    if (mainLian.getFendang() != null) {
        mainLian.getFendang().showInfo();
    }
    //主路线上的连续调速器
    if(mainLian.getLianxu() != null){
        mainLian.getLianxu().showInfo();
    }
    //白炽灯
    sa.showAllBai();
    //日光灯
    sa.showAllRig();
    //吊扇
    sa.showAllDia();
    //落地扇
    sa.showAllRuo();
    //互斥开关
    sa.showAllHck();
    //窗帘
    sa.showAllCua(mainLian.getTb());
    /*









     */


}

}

//串联电路
class Cuanlian extends Yongdianqi {

private Huchikaiguan hk ;
private int hkLeadFoot;


private ArrayList<Yongdianqi> dianqi = new ArrayList<>();
private ArrayList<Kaiguan> kaiguans = new ArrayList<>();
private Fendang fendang;
private Lianxu lianxu;

private double Tp = 1.0;
private double Tr;
private double Tv;
private double Tb;
private boolean isMainCuircuit;

// 这个方法的返回值是用于判断这条路的开关是否闭合,如出现普通开关未闭合 或是 限制开关未连接上,则判断为未闭合,因为电流不通过

public boolean allClose() {

    if(hk != null){
        if(hk.getLeadFoot() != hkLeadFoot){
            return false;
        }
    }
    for (int i = 0; i < kaiguans.size(); i++) {
        if(kaiguans.get(i).getIsClose() == 0){
            return false;
        }
    }

    //以下用于主电路判断是否连通 ,或是支线上的串联
    for (int dqIndex = 0; dqIndex < dianqi.size(); dqIndex++) {
        if(dianqi.get(dqIndex) instanceof Binglian){
            Binglian bl = (Binglian) dianqi.get(dqIndex);
            for (int blindex = 0; blindex < bl.getCuanlians().size(); blindex++) {
                if( bl.nullClose()){
                    return false;
                }
            }
        } else if(dianqi.get(dqIndex) instanceof Cuanlian){
            Cuanlian cl = (Cuanlian) dianqi.get(dqIndex);
            if(!cl.allClose()){
                return false;
            }
        }
    }

    return true;
}

public void caculateTr() {
    double tr = 0;
    if (allClose()) {
        if (hkLeadFoot != 0) {
            tr += hk.getR();
        }

        for (int i = 0; i < dianqi.size(); i++) {
            if(dianqi.get(i) instanceof Binglian){
                Binglian bl = (Binglian) dianqi.get(i);
                tr += bl.getBR();
            } else if(dianqi.get(i) instanceof Cuanlian){
                Cuanlian cl = (Cuanlian) dianqi.get(i);
                tr += cl.getTr();
            } else {
                tr += dianqi.get(i).getR();
            }
        }
    }
    Tr = tr;
}

public void caculateTp() {
    double para = 1.0;
    if (isMainCuircuit) {
        if (fendang != null) {
            para *= fendang.getPara();
        }
        if (lianxu != null) {
            para *= lianxu.getPara();
        }
    }
    Tp = para;
}

public void allocateV() {
    //分配逻辑:
    //先判断断路: 即电路是否为通路,一旦不为通路那么电压分配直接失败 ,将参数设置为0
    //如果为通路,则通过 电压 * 参数 得到可分配电压 ,然后按照电阻占比分配电压给每个用电器
    //  考虑到短路的存在 ,要将那种是通路且没有电阻的并联电路的电阻设置为0;

    //考虑短路
    //考虑断路


    caculateTr();
    if (Tr == 0) {
        return;
    }
    caculateTp();
    double totalV = Tv * Tp;
    if (allClose()) {
        for (int i = 0; i < dianqi.size(); i++) {
            double r = dianqi.get(i).getR();
            if(dianqi.get(i) instanceof Binglian){
                Binglian bl = (Binglian) dianqi.get(i);
                r = bl.getBR();
                bl.setBV((r / Tr) * totalV);

            } else if(dianqi.get(i) instanceof Cuanlian){
                Cuanlian cl = (Cuanlian) dianqi.get(i);
                r = cl.getTr();
                cl.setTv((r / Tr) * totalV);

            }else {
                dianqi.get(i).setV((r / Tr) * totalV);

            }

        }
    }
}

public void caculateTb() {
    allocateV();
    double Tlux = 0;
    //对于普通通路
    for (int i = 0; i < dianqi.size(); i++) {
        if (dianqi.get(i) instanceof Baizhideng) {
            Tlux += ((Baizhideng) dianqi.get(i)).getBrightNess();
        } else if (dianqi.get(i) instanceof Riguangdeng) {
            Tlux += ((Riguangdeng) dianqi.get(i)).getBrightNess();
        }
    }

    for (int i = 0; i < dianqi.size(); i++) {
        //对于串联电路
        if(dianqi.get(i) instanceof Cuanlian){
            Cuanlian cl = (Cuanlian) dianqi.get(i);
            cl.caculateTb();
            Tlux += cl.getTb();
        }//对于并联电路
        else if(dianqi.get(i) instanceof Binglian){
            Binglian bl = (Binglian) dianqi.get(i);
            Tlux += bl.getBB();
        }
    }
    Tb = Tlux;
}


public Cuanlian() {
}


public void addYongdianqi(Yongdianqi yd) {
    dianqi.add(yd);
}

public void addKaiguans(Kaiguan kg) {
    kaiguans.add(kg);
}

public ArrayList<Kaiguan> getKaiguans(){
    return kaiguans;
}


public void setHkLeadFoot(int leadFoot){
    hkLeadFoot = leadFoot;
}
public void setHk(Huchikaiguan hk){
    this.hk = hk;
}
public Huchikaiguan getHk(){
    return  hk;
}
public Lianxu getLianxu() {
    return lianxu;
}

public void setLianxu(Lianxu lianxu) {
    this.lianxu = lianxu;
    caculateTp();
}

public Fendang getFendang() {
    return fendang;
}

public void setFendang(Fendang fendang) {
    this.fendang = fendang;
    caculateTp();
}

public void setMainCuircuit() {
    isMainCuircuit = true;
}
public boolean isMainCuircuit(){
    return isMainCuircuit;
}

public ArrayList<Yongdianqi> getDianqi(){
    return dianqi;
}
public double getTr() {
    caculateTr();
    return Tr;
}

public void setTr(double tr) {
    caculateTr();
    Tr = tr;
}

public double getTv() {

    return Tv;
}

public void setTv(double tv) {
    Tv = tv;
    allocateV();
}

public double getTb() {
    caculateTb();
    return Tb;

}

public void setTb(double tb) {
    Tb = tb;
}

public double getTp() {
    caculateTp();
    return Tp;
}

public void setTp(double tp) {
    Tp = tp;
}

@Override
public void showInfo() {
    for (int i = 0; i < kaiguans.size(); i++) {
        kaiguans.get(i).showInfo();
    }
    if (fendang != null) {
        fendang.showInfo();
    }
    if (lianxu != null) {
        lianxu.showInfo();
    }
    for (int i = 0; i < dianqi.size(); i++) {
        dianqi.get(i).showInfo();
    }
}

}

class Binglian extends Yongdianqi {
private ArrayList cuanlians = new ArrayList<>();

public double getBB(){
    double bb = 0;
    for (int i = 0; i < cuanlians.size(); i++) {
        bb += cuanlians.get(i).getTb();
    }
    return bb;
}

public void addCuanlian(Cuanlian cuanlian) {
    cuanlians.add(cuanlian);
}

public Binglian() {
}


public ArrayList<Cuanlian> getCuanlians() {
    return cuanlians;
}

public void setCuanlians(ArrayList<Cuanlian> cuanlians) {
    this.cuanlians = cuanlians;
}

//并联里用于判断电路开关是为了确保,不会出现没有一条路是通的情况
//这个方法是用于判断并联电路是不是没有一条通路
public boolean nullClose(){
    for (int i = 0; i < cuanlians.size(); i++) {
        if(cuanlians.get(i).allClose()){
            return false;
        }
    }
    return true;
}
//    判断是否短路
public boolean isDuanlu(){
    for (int i = 0; i < cuanlians.size(); i++) {
        if(cuanlians.get(i).allClose() && cuanlians.get(i).getTr() == 0){
            for (int i1 = 0; i1 < cuanlians.size(); i1++) {
                if(cuanlians.get(i1).allClose() && cuanlians.get(i1).getTr() != 0 && i1 != i){
                    return true;
                }
            }
        }
    }
    return false;
}
public void caculateR() {
    if(isDuanlu()){
        setR(0);
        return;
    }
    double r = 0;
    if (!nullClose() ) {
        for (int i = 0; i < cuanlians.size(); i++) {
            if (cuanlians.get(i).getTr() == 0) {
                continue;
            }
            r += 1.0 / cuanlians.get(i).getTr();
        }
        if (r == 0) {
            return;
        }
        setR(1.0 / r);
    }

}

public double getBR() {
    caculateR();
    return getR();
}

public void allocateV() {
    for (int i = 0; i < cuanlians.size(); i++) {
        cuanlians.get(i).setTv(getV());
    }
}

public void setBV(double v) {
    setV(v);
    allocateV();
}

@Override
public void showInfo() {
}

}

abstract class Yongdianqi {
private String name;
private int sequence;
private double I;
private double R;
private double V;

public Yongdianqi() {
}

public Yongdianqi(String name, double i, double r, double v) {
    this.name = name;
    I = i;
    R = r;
    V = v;
}

public int getSequence() {
    return sequence;
}

public void setSequence(int sequece) {
    this.sequence = sequece;
}

public void setName(String name) {
    this.name = name;
    sequence = Character.valueOf(name.charAt(1));
}

public String getName() {
    return name;
}

public double getI() {
    return I;
}

public void setI(double i) {
    I = i;
}

public double getR() {
    return R;
}

public void setR(double r) {
    R = r;
}

public double getV() {
    return V;
}

public void setV(double v) {
    V = v;
}

abstract public void showInfo();

}

class Kaiguan {
private String name;
private int isClose;
private int sequence;

public void Switch() {
    if (isClose == 0) {
        isClose = 1;
    } else {
        isClose = 0;
    }
}

public void showInfo() {
    if (isClose == 0) {
        System.out.println("@" + name + ":turned on");
    } else {
        System.out.println("@" + name + ":closed");
    }
}

public void setSequence(int sequence){
    this.sequence = sequence;
}

public int getSequence() {
    return sequence;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
    sequence = Integer.parseInt(name.charAt(1)+"");
}

public int getIsClose() {
    return isClose;
}

public void setIsClose(int isClose) {
    this.isClose = isClose;
}

}

abstract class Tiaoshuqi {
private double para;

private String name;
private int sequence;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
    sequence = Character.valueOf(name.charAt(1));

}

public int getSequence() {
    return sequence;
}

public void setSequence(int sequence) {
    this.sequence = sequence;
}

public Tiaoshuqi() {
}

public Tiaoshuqi(double para, String name) {
    this.para = para;
    this.name = name;
}

public double getPara() {
    return para;
}

public void setPara(double para) {
    this.para = para;
}

abstract void showInfo();

}

class Fendang extends Tiaoshuqi {
private int step;
public void addStep() {
if (step < 3) {
step++;
}
caculatePara();
}

public void downStep() {
    if (step > 0) {
        step--;
    }
    caculatePara();
}

public Fendang() {
}

@Override
void showInfo() {
    System.out.println("@" + getName() + ":" + step);
}

private void caculatePara() {
    switch (step) {
        case 0:
            setPara(0);
            break;
        case 1:
            setPara(0.3);
            break;
        case 2:
            setPara(0.6);
            break;
        case 3:
            setPara(0.9);
            break;
        default:
            break;
    }

}

}

class Lianxu extends Tiaoshuqi {

public Lianxu() {
}

@Override
public void showInfo() {
    System.out.printf("@%s:%.2f", getName(), getPara());
    System.out.println();
}

public Lianxu(double p, String name) {
    super(p, name);
}

}

abstract class Light extends Yongdianqi {

private double brightNess;


public double getBrightNess() {
    caculateBri();
    return brightNess;
}

public void setBrightNess(double brightNess) {
    this.brightNess = brightNess;
}

public abstract void caculateBri();

}

class Baizhideng extends Light {
public Baizhideng() {
setR(10.0);
}

@Override
public void showInfo() {
    caculateBri();
    System.out.printf("@%s:%d", getName(), (int) getBrightNess());
    System.out.println();
}

@Override
public void caculateBri() {
    //0~9v :0
    //10v :50
    //220v :200
    //1.4v/lux
    double volt = getV();
    if (volt <= 9) {
        setBrightNess(0.0);
    } else if (volt >= 220) {
        setBrightNess(200.0);
    } else {
        setBrightNess(50 + (volt - 10) * ((150.0) / 210));
    }
}

}

class Riguangdeng extends Light {
public Riguangdeng() {
setR(5);
}

public Riguangdeng(double bright) {
    setBrightNess(bright);
}


@Override
public void showInfo() {
    caculateBri();
    System.out.printf("@%s:%d", getName(), (int) getBrightNess());
    System.out.println();
}

@Override
public void caculateBri() {
    double volt = getV();
    if (volt > 0) {
        setBrightNess(180);
    } else {
        setBrightNess(0);
    }
}

}

//这个是窗帘
class Chuanglian extends Yongdianqi {

private double R = 15.0;
private double bili = 1.0;

public void caculateBili(double lux) {
    if (getV() >= 50) {
        if (lux >= 0 && lux < 50) {
            bili = 1.0;
        } else if (lux >= 50 && lux <= 100) {
            bili = 0.8;
        } else if (lux >= 100 && lux < 200) {
            bili = 0.6;
        } else if (lux >= 200 && lux < 300) {
            bili = 0.4;
        } else if (lux >= 300 && lux < 400) {
            bili = 0.2;
        } else {
            bili = 0;
        }
    } else {
        bili = 1.0;
    }
}
public double getR(){
    return R;
}

@Override
public void showInfo() {
}

public void showInfo(double lux) {
    caculateBili(lux);
    System.out.println("@" + getName() + ":" + String.format("%.0f",bili * 100) + "%");
}

}

abstract class Fan extends Yongdianqi {
private double rspeed;

public Fan() {
}

public Fan(double rspeed) {
    this.rspeed = rspeed;
}

public abstract void caculateRsp();

public double getRspeed() {
    return rspeed;
}

public void setRspeed(double rspeed) {
    this.rspeed = rspeed;
}

@Override
public void showInfo() {
    caculateRsp();
    System.out.printf("@%s:%d", getName(), (int) getRspeed());
    System.out.println();
}

}

class Diaosan extends Fan {

public Diaosan() {
    setR(20);
}

public void caculateRsp() {
    double volt = getV();
    if (volt < 80) {
        setRspeed(0);
    } else if (volt >= 150) {
        setRspeed(360);
    } else {
        setRspeed((int) (80 + 4 * (volt - 80)));
    }

}

}

class Ruodisan extends Fan {
public Ruodisan() {
setR(20);
}

@Override
public void caculateRsp() {
    double volt = getV();
    if (volt < 80) {
        setRspeed(0);
    } else if (volt >= 80 && volt <= 99) {
        setRspeed(80);
    } else if (volt >= 100 && volt <= 119) {
        setRspeed(160);
    } else if (volt >= 120 && volt <= 139) {
        setRspeed(260);
    } else if (volt >= 140) {
        setRspeed(360);
    }
}

}

class Huchikaiguan extends Yongdianqi {
private String name;
private int leadFoot = 2;

public Huchikaiguan() {
}


public double getR() {
    if (leadFoot == 2) {
        return 5.0;
    } else {
        return 10.0;
    }
}

@Override
public void showInfo() {
    System.out.print("@" + name );
    if(leadFoot == 2){
        System.out.println(":closed");
    } else if(leadFoot == 3) {
        System.out.println(":turned on");
    }
}

@Override
public String getName() {
    return name;
}

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

public void switchLeadFoot() {
    if (leadFoot == 2) {
        leadFoot = 3;
    } else  if(leadFoot == 3){
        leadFoot = 2;
    }
}

public int getLeadFoot() {
    return leadFoot;
}

}

class StoreAllinfo {
ArrayList kgs = new ArrayList<>();
ArrayList bzs = new ArrayList<>();
ArrayList rgds = new ArrayList<>();
ArrayList dss = new ArrayList<>();
ArrayList rds = new ArrayList<>();
ArrayList cls = new ArrayList<>();
ArrayList hcks = new ArrayList<>();

public void addKaiguan(Kaiguan kg){
    kgs.add(kg);
    if(kgs.size()!=1){
        KaiguanSort();

    }
}
public void addBaizhideng(Baizhideng bzd){
    bzs.add(bzd);
    if(bzs.size()!=1){
        BaizhidengSort();

    }
}
public void addRiguangdeng(Riguangdeng rgd){
    rgds.add(rgd);
    if(rgds.size()!=1){
        RiguangdengSort();

    }
}
public void addDiaosan(Diaosan ds){
    dss.add(ds);
    if(dss.size()!=1){
        DiaosanSort();

    }
}
public void addRuodisan(Ruodisan rd){
    rds.add(rd);
    if(rds.size()!=1){
        RuodisanSort();
    }
}
public void addCuanglian(Chuanglian cl){
    cls.add(cl);
    if (cls.size()!=1){
        CuanglianSort();
    }
}
public void addHuchikaiguan(Huchikaiguan hck){
    for (int i = 0; i < hcks.size(); i++) {
        if(hcks.get(i) == hck){
            return;
        }
    }
    hcks.add(hck);
    if(hcks.size()!=1){
        HuchikaiguanSort();
    }
}


public void KaiguanSort(){
    Collections.sort(kgs, Comparator.comparingInt(Kaiguan::getSequence));
}
public void BaizhidengSort(){
    Collections.sort(bzs, Comparator.comparingInt(Baizhideng::getSequence));
}
public void RiguangdengSort(){
    Collections.sort(rgds, Comparator.comparingInt(Riguangdeng::getSequence));
}
public void DiaosanSort(){
    Collections.sort(dss, Comparator.comparingInt(Diaosan::getSequence));
}
public void RuodisanSort(){
    Collections.sort(rds, Comparator.comparingInt(Ruodisan::getSequence));
}
public void CuanglianSort(){
    Collections.sort(cls, Comparator.comparingInt(Chuanglian::getSequence));
}
public void HuchikaiguanSort(){
    Collections.sort(hcks, Comparator.comparingInt(Huchikaiguan::getSequence));
}

public void showAllKai(){
    for (int i = 0; i < kgs.size(); i++) {
        kgs.get(i).showInfo();
    }
}
public void showAllBai(){
    for (int i = 0; i < bzs.size(); i++) {
        bzs.get(i).showInfo();
    }
}
public void showAllRig(){
    for (int i = 0; i < rgds.size(); i++) {
        rgds.get(i).showInfo();
    }
}
public void showAllDia(){
    for (int i = 0; i < dss.size(); i++) {
        dss.get(i).showInfo();
    }
}
public void showAllRuo(){
    for (int i = 0; i < rds.size(); i++) {
        rds.get(i).showInfo();
    }
}
public void showAllCua(double lux){
    for (int i = 0; i < cls.size(); i++) {
        cls.get(i).showInfo(lux);
    }
}
public void showAllHck(){
    for (int i = 0; i < hcks.size(); i++) {
        hcks.get(i).showInfo();
    }
}

}

代码类的分析:
Main 类:是程序的入口点,包含 main 方法。首先调用 infoSort 方法来初始化电路,然后设置主电路的电压,分配电压,并展示所有信息。

infoSort 方法:这个方法用于从用户输入中读取电路的配置信息,包括串联、并联电路信息和设备配置信息。使用正则表达式来解析输入的字符串,并根据这些信息创建 Cuanlian(串联电路)和 Binglian(并联电路)对象。

electricArrange 方法:这个方法用于根据配置信息调整电路中的开关状态和调速器参数。

Cuanlian 类:表示一个串联电路,包含多个用电器(Yongdianqi 对象)、开关(Kaiguan 对象)和调速器(Fendang 和 Lianxu 对象)。它还包含方法来计算总电阻(caculateTr)、分配电压(allocateV)和计算亮度(caculateTb)。

Binglian 类:表示一个并联电路,包含多个串联电路(Cuanlian 对象)。包含方法来计算亮度(getBB)、判断是否有通路(nullClose)和判断是否短路(isDuanlu)。

Yongdianqi 抽象类:作为所有用电器的基类,包含用电器的基本信息和方法,如电阻(R)、电流(I)、电压(V)等。

Kaiguan 类:表示一个开关,包含开关状态和名称。

Tiaoshuqi 抽象类:作为调速器的基类,包含调速参数。

Fendang 类:表示分档调速器,可以增加或减少档位。

Lianxu 类:表示连续调速器。

Light 抽象类:作为所有光源的基类,包含亮度计算。

Baizhideng 类 和 Riguangdeng 类:分别表示白炽灯和日光灯,继承自 Light 类。

Chuanglian 类:表示窗帘,根据电压和亮度调整透光率。

Fan 抽象类:作为所有风扇的基类,包含转速计算。

Diaosan 类 和 Ruodisan 类:分别表示吊扇和落地扇,继承自 Fan 类。

Huchikaiguan 类:表示互斥开关,可以切换状态。

StoreAllinfo 类:用于存储和管理所有电路组件的实例,包含各种排序和显示信息的方法。

踩坑心得:我不清楚最正统的方式要如何管理这些数据,但我觉的可以一步一步思索下去就能够解决一些问题的
其中遇到的问题是对于多串联并联电路无法正确通过测试点,但是这一点在第4次迭代的时候实现了,这样的题目真的很容易让人不想再继续往下写,如果没有所谓分数与排名的“鞭策”的话。

第8题:

1、控制设备
本题模拟的控制设备包括:开关、分档调速器、连续调速器、互斥开关。

开关:包括0和1两种状态。

开关有两个引脚,任意一个引脚都可以是输入引脚(接往电源端),而另一个则是输出引脚(接网接地端)。开关状态为0时,无论输入电位是多少,输出引脚电位为0。当开关状态为1时,输出引脚电位等于输入电位。
互斥开关:

互斥开关有3个引脚:1个是汇总引脚,另两个是分支引脚。

开关电路示意图如图1所示,左边是汇总引脚,编号为1;右边两个是分支引脚,右上的输出引脚为2,右下输出引脚为3。图中1、2、3引脚均可以是输入引脚,当1为输入引脚时,2、3引脚为输出引脚;1为输出引脚时,2、3引脚为输入引脚。
互斥开关只有两种状态:开关接往上面的2号引脚、接往下面的3号引脚。开关每次只能接通其中一个分支引脚,而另一个分支引脚处于断开状态。
互斥开关的默认状态为1、2引脚接通,1、3引脚断开。
图1中所示的互斥开关可以反过来接入电路,即汇总引脚接往接地端,两个分支引脚接往电源端。

image.png

图1 互斥开关

为避免短路,互斥开关设置了限流电阻,1、2引脚之间默认电阻为5,1、3引脚之间默认电阻为10。

分档调速器

按档位调整,常见的有3档、4档、5档调速器,档位值从0档-2(3/4)档变化。本次迭代模拟4档调速器,每个档位的输出电位分别为0、0.3、0.6、0.9倍的输入电压。
连续调速器

没有固定档位,按位置比例得到档位参数,数值范围在[0.00-1.00]之间,含两位小数。输出电位为档位参数乘以输入电压。
所有调速器都有两个引脚,一个固定的输入(引脚编号为1)、一个输出引脚(引脚编号为2)。当输入电位为0时,输出引脚输出的电位固定为0,不受各类开关调节的影响。

开关、调速器的初始状态/档位为0。

开关的两个引脚编号为1、2。
除互斥开关外,其他控制设备的电阻为 0。

2、受控设备
本题模拟的受控设备包括:灯、风扇。两种设备都有两根引脚,通过两根引脚电压的电压差驱动设备工作。

灯有两种工作状态:亮、灭。在亮的状态下,有的灯会因引脚电位差的不同亮度会有区别。
风扇在接电后有两种工作状态:停止、转动。风扇的转速会因引脚间电位差的不同而有区别。
本次迭代模拟两种灯具。

白炽灯:

亮度在0~200lux(流明)之间。
电位差为0-9V时亮度为0,其他电位差按比例,电位差10V对应50ux,220V对应200lux,其他电位差与对应亮度值成正比。白炽灯超过220V。
日光灯:

亮度为180lux。
只有两种状态,电位差为0时,亮度为0,电位差不为0,亮度为180。
本次迭代模拟两种风扇。

吊扇:

工作电压区间为80V-150V,对应转速区间为80-360转/分钟。80V对应转速为80转/分钟,150V对应转速为360转/分钟,超过150V转速为360转/分钟(本次迭代暂不考虑电压超标的异常情况)。其他电压值与转速成正比,输入输出电位差小于80V时转速为0。
落地扇:

工作电压区间为 80V-150V,对应转速区间为 80-360 转/分钟;[80V,100V) 对应转速为 80 转/分钟;[100,120)V 对应转速为 160 转/分钟;[120,140)V 对应转速为 260 转/分钟;大于等于 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况)。

本次迭代模拟一种受控窗帘:

受控串联的电路符号为S,其最低工作电压为50V,电压达到或超过50V,窗帘即可正常工作,不考虑室外光照强度和室内空间大小等因素,窗帘受室内灯光的光照强度控制。
当电路中所有灯光的光照强度总和在[0,50)lux范围内,窗帘全开;
在[50,100)lux范围内,窗帘打开比例为0.8;
在[100,200)lux范围内,窗帘打开比例为0.6;
在[200,300)lux范围内,窗帘打开比例为0.4;
在[300,400)lux范围内,窗帘打开比例为0.2;
在400lux及以上范围内,窗帘关闭。
当电压低于50V,窗帘不工作,默认为全开状态。
如果电路中没有灯或者灯全部关闭,光照强度为0,窗帘处于全开状态。
受控设备电阻:白炽灯的电阻为 10,日光灯的电阻为 5,吊扇的电阻为 20,落地扇的电阻为 20,窗帘电阻为15。

3、输入信息
1)输入设备信息

分别用设备标识符K、F、L、B、R、D、A、H、S、P分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇、互斥开关、受控窗帘、二极管(见第6部分说明)。

设备标识用标识符+编号表示,如K1、F3、L2等。

引脚格式:
设备标识-引脚编号,例如:K1-1标识编号为1的开关的1号引脚。
开关、分档调速器、连续调速器的两个引脚编号为1、2。
受控设备的两个引脚编号分别为1、2。
互斥开关的引脚编号已经在互斥开关的介绍部分说明。

约束条件:
不同设备的编号可以相同。
设备信息不单独输入,包含在连接信息中。

2)输入连接信息

一条连接信息占一行,用[]表示一组连接在一起的设备引脚,引脚与引脚之间用英文空格" "分隔。

格式:
"["+引脚号+" "+引脚号+"]"
例如:[K1-1 K3-2]表示K1的1号引脚,K3的2号引脚连接在一起。

约束条件:
不考虑调速器串联到其他调速器的情况。
考虑各类设备的并联接入。例如,K1 的输出接到 L2 的输入,L2 的输出再接其他设备属于串联接线。K1 的输出接到 L2 的输出,同时 K1 的输入接到 L2 的输入,这种情况属于并联。

连接信息不单独输入,包含在线路信息中。

3)输入控制设备调节信息

开关、互斥开关调节信息格式:

+设备标识K+设备编号,例如:#K2,代表切换K2开关的状态。

+设备标识H+设备编号,例如:#H2,代表切换H2互斥开关的状态。

分档调速器的调节信息格式:

+设备标识F+设备编号+"+" 代表加一档,例如:#F3+,代表F3输出加一档。

+设备标识F+设备编号+"-" 代表减一档,例如:#F1-,代表F1输出减一档。

连续调速器的调节信息格式:

+设备标识L+设备编号+":" +数值 代表将连续调速器的档位设置到对应数值,例如:#L3:0.6,代表L3输出档位参数0.6。

4)电源接地标识:

VCC,电压220V,GND,电压0V。没有接线的引脚默认接地,电压为0V。

5)输入串联电路信息

一条串联电路占一行,串联电路信息由 n 个连接信息组成,连接信息按从靠电源端到接地端顺序依次输入,连接信息之间用英文空格" "分隔。

串联电路信息格式:
"#T"+电路编号+":"+连接信息+" "+连接信息+...+" "+连接信息
例如:#T1:[IN K1-1] [K1-2 D2-1] [D2-2 OUT] 一个串联电路的第一个引脚是 IN,代表起始端,靠电源。最后一个引脚是 OUT,代表结尾端, 靠接地。

约束条件:
不同的串联电路信息编号不同。
输入的最后一条电路信息必定是总电路信息,总电路信息的起始引脚是 VCC,结束引脚是 GND。
连接信息中的引脚可能是一条串联或并联电路的 IN 或者 OUT。例如:

T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT OUT]

T1:[IN K1-1] [K1-2 T2-IN] [T2-OUT M2-IN] [M2-OUT OUT]

6)输入并联电路信息

一条并联电路占一行,并联电路由其包含的几条串联电路组成,串联电路标识之间用英文空格" "分隔。

格式:

"#M"+电路编号+":"+”[”+串联电路信息+" "+....+" "+串联电路信息+”]”
例如:#M1:[T1 T2 T3]
该例声明了一个并联电路,由 T1、T2、T3 三条串联电路并联而成,三条串联电路的 IN 短接在一起构成 M1 的 IN,三条串联电路的 OUT 短接在一起构成 M1 的 OUT。
在本题中,并联电路M中的串联电路可以包含别的并联电路。

约束条件:

本题不考虑输入电压或电压差超过220V的情况。
输入信息以end为结束标志,忽略end之后的输入信息。
本题中的并联信息所包含的串联电路的信息都在并联信息之前输入,不考虑乱序输入的情况。
只要不因短路而造成无穷大的电流烧坏电路(如电路中的部分短接),都是合理情况。
本次迭代考虑多个并联电路串联在一起的情况。
本题考虑一条串联电路中包含其他串联电路和并联电路的情况。例如:

T3:[VCC K1-1] [K1-2 T2-IN] [T2-OUT K2-1] [K2-2 T1-IN] [T1-OUT GND]

本例中T1\T2两条串联电路是T3的一个部分,本题考虑这种类型的输入。
4、输出信息:
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、互斥开关、受控窗帘、二极管(见第6部分说明)的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。

输出格式:
@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位)+" "+设备所有引脚的电压(按编号从小到大顺序依次输出,电压的小数部分直接丢弃,保留整数输出,电压之间用”-”分隔)

说明:
连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。
开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed
如:
@K1:turned on 32-15
@B1:190 68-17
@L1:0.60 220-176
互斥开关按1、2引脚的接通状态显示,1,2接通-1,3断开时显示closed,1,3接通-1,2断开时显示turned on。
如:
@H1:turned on
受控窗帘显示窗帘打开的百分比,如:
@S1:80%

5、家居电路模拟系列所有题目的默认规则
1)当计算电压值等数值的过程中,最终结果出现小数时,用截尾规则去掉小数部分,只保留整数部分。为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算,不要作下转型数据类型转换,例如电压、转速、亮度等,只有在最后输出时再把计算结果按截尾规则,舍弃尾数,保留整数输出。

2)所有连接信息按电路从靠电源端到靠接地端的顺序依次输入,不会出现错位的情况。VCC/IN一定是第一个连接的第一项,GND/OUT一定是最后一个连接的后一项。

3)连接信息如果只包含两个引脚,靠电源端的引脚在前,靠接地端的在后。

4)调速器的输入端只会直连VCC,不会接其他设备。整个电路最多只有连接在电源上的一个调速器,且不包含在并联单路中。

5)本系列题目中元件的管脚除了互斥开关的1引脚,其他所有引脚在电路中最多只出现一次。

6、本题新增内容:
1)增加管脚电压的显示

在输出每个电器的状态信息后,再依次输出该电器每个管脚的电压。(格式详见输出信息部分)

2)电流限制

电器在工作时,过大的电流会引起电器过热,从而烧坏电路。本次迭代,每个元器件都有最大电流的设置,当实时电流超过最大电流时,在该电器输出信息的最后加入提示“exceeding current limit error”,与前面的信息之间用英文空格分隔。

例如:@B1:190 68-17 exceeding current limit error

本题各类电器的最大限定电流如下:

开关20、分档调速器18、连续调速器18、白炽灯9、日光灯5、吊扇12、落地扇14、互斥开关20、受控窗帘12、二极管8。

3)短路检测

如果电路出现无穷大的电流造成短路,所有元器件信息不输出,仅输出提示“short circuit error”

4)并联电路中包含并联

本次迭代考虑并联电路中包含并联电路的情况,即构成并联电路的串联电路可以包含别的并联电路。例如如下输入的电路,并联电路M2的其中一条串联电路T4中包含了另一条并联电路M1:

T1:[IN D2-1] [D2-2 H1-2] [H1-1 OUT]

T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]

M1:[T1 T2]

T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]

T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]

M2:[T4 T5]

5)二极管

增加二极管元件,其电路特性为:正向导通,反向截止;其电器符号如图4所示,当电流从左至右流过时,二极管导通”conduction”,电阻为0;电流从右至左流动时,二极管截止”cutoff”,电阻无穷大,相当于开关打开。

image.png

图2 二极管符号

二极管的标识符为’P’,左侧管脚编号为1,右侧管脚编号为2。

二极管如果两端电压相等,没有电流流过,分以下两种情况输出:

1、如果两端电压为0,二极管的导通/截止状态由接入方向决定,1号引脚靠近电源则状态为导通,反之为截止。
2、如果两端电压不为0,二极管导通。

7、设计建议
本题包含以下电路图中的所有连接情况:

image.png

图3 电路示意图

1、电路设备类:描述所有电路设备的公共特征。

2、受控设备类、控制设备类:对应受控、控制设备

3、串联电路类:一条由多个电路设备构成的串联电路,也看成是一个独立的电路设备

4、并联电路类:继承电路设备类,也看成是一个独立的电路设备

其他类以及类的属性、方法自行设计。

image.png

图4:建议设计类图

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

T1:[IN P2-2] [P2-1 H1-2] [H1-1 OUT]

T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]

M1:[T1 T2]

T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]

T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]

M2:[T4 T5]

T3:[VCC K2-1] [K2-2 M2-IN] [M2-OUT GND]

K1

K2

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

@K1:closed 220-220 exceeding current limit error
@K2:closed 220-220 exceeding current limit error
@K3:turned on 220-0
@B1:200 220-0 exceeding current limit error
@D1:0 0-0
@H1:closed 0-0-0
@P2:cutoff 0-0
输入样例2:
在这里给出一组输入。例如:

T1:[IN P2-1] [P2-2 H1-2] [H1-1 OUT]

T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]

M1:[T1 T2]

T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]

T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]

M2:[T4 T5]

T3:[VCC K2-1] [K2-2 M2-IN] [M2-OUT GND]

K1

K3

K2

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

@K1:closed 220-220 exceeding current limit error
@K2:closed 220-220 exceeding current limit error
@K3:closed 220-220 exceeding current limit error
@B1:200 220-0 exceeding current limit error
@D1:0 220-220
@H1:closed 0-220-220 exceeding current limit error
@P2:conduction 220-220 exceeding current limit error
输入样例3:
在这里给出一组输入。例如:

T1:[IN P2-2] [P2-1 H1-2] [H1-1 OUT]

T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]

M1:[T1 T2]

T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]

T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]

M2:[T4 T5]

T3:[VCC K2-1] [K2-2 M2-IN] [M2-OUT GND]

K1

K3

K2

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

@K1:closed 220-220 exceeding current limit error
@K2:closed 220-220 exceeding current limit error
@K3:closed 220-220
@B1:200 220-0 exceeding current limit error
@D1:0 220-220
@H1:closed 0-0-220
@P2:cutoff 0-220
输入样例4:
在这里给出一组输入。例如:

T3:[VCC K2-1] [K2-2 GND]

K2

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

short circuit error
输入样例5:
在这里给出一组输入。如果两端电压为0,二极管的导通/截止状态由接入方向决定,1号引脚靠近电源则状态为导通,反之截止。 例如:

T3:[VCC K2-2] [K2-1 P1-1] [P1-2 K1-2] [K1-1 GND]

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

@K1:turned on 0-0
@K2:turned on 0-220
@P1:conduction 0-0
输入样例6:
在这里给出一组输入。如果两端电压为0,二极管的导通/截止状态由接入方向决定,1号引脚靠近电源则状态为导通,反之截止。 例如:

T3:[VCC K2-2] [K2-1 P1-2] [P1-1 K1-2] [K1-1 GND]

end
输出样例6:
####### 。例如:

@K1:turned on 0-0
@K2:turned on 0-220
@P1:cutoff 0-0

我的源码:

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {
private static StoreAllinfo sa = new StoreAllinfo();

public static void main(String[] args) {

    //信息分流 -> 信息配置
    Cuanlian mainLian = infoSort();

    //“数据库”
    // mainLian.setStoreAllinfo(sa);

    mainLian.setTv(220.0);

    // 分配电压
    mainLian.allocateV();

    //展示信息
    showAllInfo(mainLian);

}

private static Cuanlian infoSort() {
    //第四次迭代:
    // 接下来要做的事:
    //    1. 给 互斥开关, 二极管 添加引脚和引脚电压
    //     2. 添加二极管类,可以根据引脚设置开关状态
    //     3. 添加电流 属性, 最大电流属性 和在show方法里额外的打印信息 ,包括短路提醒 和最大电流提醒
    //
    Scanner in = new Scanner(System.in);

    Cuanlian mainCuanlian = new Cuanlian();
    //一行的信息
    ArrayList<String> lineInfo = new ArrayList<>();
    //设备配置的信息
    ArrayList<String> peizhiInfo = new ArrayList<>();
    //并联电路的信息
    ArrayList<String> binglianInfo = new ArrayList<>();

    String tempStr = "";

    //数据分流
    while (true) {
        tempStr = in.nextLine();

        if (tempStr.equals("end")) {
            break;
        }

        if (tempStr.charAt(1) == 'T') {
            lineInfo.add(tempStr);
        } else if (tempStr.charAt(1) == 'M') {
            binglianInfo.add(tempStr);
        } else {
            peizhiInfo.add(tempStr);
        }
    }

    //包括主路线,子路线在内的各条串联路线信息
    ArrayList<Cuanlian> cuanlians = new ArrayList<>();


    for (int lindex = 0; lindex < lineInfo.size(); lindex++) {
        Cuanlian cl = new Cuanlian();
        cl.setName(getTname(lineInfo.get(lindex)));

        String name = "";
        String type = "";

        ArrayList<String> machine = getMachine(lineInfo.get(lindex).substring(4));


        for (int mindex = 0; mindex < machine.size(); mindex++) {

            type = machine.get(mindex).substring(0, 1);
            name = machine.get(mindex);


            switch (type) {
                case "K": {
                    Kaiguan kg = new Kaiguan();
                    kg.setIsClose(0);
                    kg.setName(name);
                    cl.addKaiguans(kg);
                    sa.addKaiguan(kg);
                }
                ;
                break;
                case "F": {
                    Fendang fd = new Fendang();
                    fd.setName(name);
                    cl.setFendang(fd);

                }
                ;
                break;
                case "L": {
                    Lianxu lx = new Lianxu();
                    lx.setName(name);
                    cl.setLianxu(lx);

                }
                ;
                break;
                case "B": {
                    Baizhideng bz = new Baizhideng();
                    bz.setName(name);
                    cl.addYongdianqi(bz);
                    sa.addBaizhideng(bz);
                }
                ;
                break;
                case "R": {
                    Riguangdeng rgd = new Riguangdeng();
                    rgd.setName(name);
                    cl.addYongdianqi(rgd);
                    sa.addRiguangdeng(rgd);
                }
                ;
                break;
                case "D": {
                    Diaosan ds = new Diaosan();
                    ds.setName(name);
                    cl.addYongdianqi(ds);
                    sa.addDiaosan(ds);
                }
                ;
                break;
                case "A": {
                    Ruodisan rd = new Ruodisan();
                    rd.setName(name);
                    cl.addYongdianqi(rd);
                    sa.addRuodisan(rd);
                }
                break;
                case "H": {
                    Huchikaiguan hcg = new Huchikaiguan();
                    for (int i = 0; i < cuanlians.size(); i++) {
                        if (cuanlians.get(i).getHk().getName().equals(name)) {
                            hcg = cuanlians.get(i).getHk();
                        }
                    }
                    hcg.setReverse(ifReverse(lineInfo.get(lindex),name));
                    hcg.setName(name);
                    cl.setHkLeadFoot(getLeadFootLine(lineInfo.get(lindex)));
                    cl.setHk(hcg);
                    sa.addHuchikaiguan(hcg);
                }
                break;
                case "S": {
                    Chuanglian cuanglian = new Chuanglian();
                    cuanglian.setName(name);
                    cl.addYongdianqi(cuanglian);
                    sa.addCuanglian(cuanglian);
                }
                break;
                case "P": {
                    erjiguan ej = new erjiguan();
                    ej.setName(name);
                    ej.setFoot(getFoot_in(lineInfo.get(lindex), name), getFoot_out(lineInfo.get(lindex), name));
                    //给二极管增加设置引脚
                    //通过引脚判断是否连通
                    cl.getKaiguans().add(ej);
                    sa.addErjiguan(ej);
                }
                break;
                case "M": {
                    Binglian bl = new Binglian();
                    bl.setName(name);
                    cl.addYongdianqi(bl);
                }
                break;
                case "T": {
                    Cuanlian cuanlian = new Cuanlian();
                    cuanlian.setName(name);
                    cl.addYongdianqi(cuanlian);
                }
                break;
            }
            Cuanlian.LinkInfo lf = cl.new LinkInfo(name);
            cl.addLinkInfo(lf);

        }
        if (lineInfo.get(lindex).charAt(5) == 'V') {
            cl.setMainCuircuit();
            mainCuanlian = cl;
        }
        cuanlians.add(cl);

    }

    //至此 ,主串联和串联分支便分配好了


    ArrayList<Binglian> binglians = new ArrayList<>();
    for (int bindex = 0; bindex < binglianInfo.size(); bindex++) {


        Binglian bl = new Binglian();

        String name = binglianInfo.get(bindex).substring(1, 3);
        bl.setName(name);

        ArrayList<String> TsIn = new ArrayList<>();
        String regex = "\\[([^\\$$]+)\\]";

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(binglianInfo.get(bindex));

        if (matcher.find()) {
            String contents = matcher.group(1);
            String[] str = contents.split("\\s+");
            for (String s : str) {
                TsIn.add(s);
            }
        }
        for (int tindex = 0; tindex < TsIn.size(); tindex++) {
            for (int cindex = 0; cindex < cuanlians.size(); cindex++) {
                if (cuanlians.get(cindex).getName().equals(TsIn.get(tindex))) {
                    bl.addCuanlian(cuanlians.get(cindex));
                    break;
                }
            }
        }

        binglians.add(bl);
    }


    electricArrange(cuanlians, peizhiInfo);


    for (int i = 0; i < binglians.size(); i++) {
        //并联电路各奔东西
        for (int cindex = 0; cindex < cuanlians.size(); cindex++) {
            ArrayList<Yongdianqi> ydqs = cuanlians.get(cindex).getDianqi();
            for (int dqindex = 0; dqindex < ydqs.size(); dqindex++) {
                //在串联电路中找到自己的名字
                if (ydqs.get(dqindex).getName().equals(binglians.get(i).getName())) {
                    ydqs.set(dqindex, binglians.get(i));
                    break;
                }
            }
        }
    }

    for (int cindex = 0; cindex < cuanlians.size(); cindex++) {
        //串联电路各奔东西
        for (int dqindex = 0; dqindex < cuanlians.get(cindex).getDianqi().size(); dqindex++) {
            Yongdianqi ydq = cuanlians.get(cindex).getDianqi().get(dqindex);
            //逐个检查发现有串联电路是作为用电器存在于其他串联电路中,于是将该串联电路的地址放到它应该在的地方
            if (ydq instanceof Cuanlian) {
                String name = ydq.getName();
                for (int ccindex = 0; ccindex < cuanlians.size(); ccindex++) {
                    if (cuanlians.get(ccindex).getName().equals(name)) {
                        cuanlians.get(cindex).getDianqi().set(dqindex, cuanlians.get(ccindex));
                        break;
                    }
                }
            }
        }
    }

    for (int i = 0; i < cuanlians.size(); i++) {
        cuanlians.get(i).setStoreAllinfo(sa);
    }

    cuanlians.remove(mainCuanlian);

    for (int bindex = 0; bindex < binglians.size(); bindex++) {
        for (int cindex = 0; cindex < binglians.get(bindex).getCuanlians().size(); cindex++) {
            for (int clindex = 0; clindex < cuanlians.size(); clindex++) {
                if (binglians.get(bindex).getCuanlians().get(cindex) == cuanlians.get(clindex)) {
                    //包含在并联电路中的串联被移去,如果还剩下串联电路,那可能是在其他路线上的串联电路
                    cuanlians.remove(clindex);
                }
            }
        }
    }
    //电路进行匹配后理论上不应该产生额外的串联


    int num = 1;
    while (num != 20) {
        num++;
    }

    return mainCuanlian;

/*

T1:[IN P2-2] [P2-1 H1-2] [H1-1 OUT]

T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]

M1:[T1 T2]

T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]

T5:[IN K1-1] [K1-2 B1-1] [B1-2 OUT]

M2:[T4 T5]

T6:[IN K5-1] [K5-2 GND]

T3:[VCC K2-1] [K2-2 M2-IN] [M2-OUT T6-1] [T6-2 GND]

K1

K3

K2

end

*/

}

private static boolean ifReverse(String s,String name) {
    String regex = name+"-(\\d)";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(s);
    if(m.find()){
        if(m.group(1).equals(1)){
            return false;
        }
        return true;
    }
    return false;
}

private static String getTname(String lineInfo) {
    String regex = "#(T\\d+):";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(lineInfo);
    if (m.find()) {
        return m.group(1);
    }
    return "";
}

//    获取输入引脚
private static int getFoot_in(String lineInfo, String name) {
    //#T1:[IN P2-2] [P2-1 H1-2] [H1-1 OUT]
    String getRegex = name + "-(\\d)";

    Pattern gp = Pattern.compile(getRegex);
    Matcher gm = gp.matcher(lineInfo);

    if (gm.find()) {
        //System.out.println(Integer.parseInt(gm.group(1)));
        return Integer.parseInt(gm.group(1));
    }

    return -1;
}

private static int getFoot_out(String lineInfo, String name) {
    String getRegex2 = name + "-(\\d)";

    Pattern gp = Pattern.compile(getRegex2);
    Matcher gm = gp.matcher(lineInfo);

    int account = 0;
    while (gm.find()) {
        account++;
        if (account == 2) {
            return Integer.parseInt(gm.group(1));
        }
    }
    return -1;
}


private static void electricArrange(ArrayList<Cuanlian> cuanlians, ArrayList<String> peizhiInfo) {
    for (int peindex = 0; peindex < peizhiInfo.size(); peindex++) {
        //#K1 #F1+ #H1 #L1:1.00
        char peType = peizhiInfo.get(peindex).charAt(1);

        //好奇怪呀,为什么这个“”如果打在最后面name 就变成一个三位数了?
        String name = peizhiInfo.get(peindex).charAt(1) + "" + peizhiInfo.get(peindex).charAt(2);//+peizhiInfo.get(peindex).charAt(2);

        //对于每一条通路,对得上的用电器,就将其信息进行修改
        //并且只有主路线才考虑调速器
        //其他通路只考虑开关与限制开关,并且保证限制开关即使会改变两次,也只是重复修改而已,并不影响结果

        //信息流循环 信息size ,对于每 单个信息 ,都会循环一次 通路 ,每个通路都会循环一次 电器size, 故每一条信息应该都被
        //考虑进去了
        loop:
        for (int cindex = 0; cindex < cuanlians.size(); cindex++) {

            if (cuanlians.get(cindex).isMainCuircuit()) {
                switch (peType) {
                    case 'F': {
                        char done = peizhiInfo.get(peindex).charAt(3);
                        if (done == '+') {
                            //我这里有一个 Yongdianqi 类的对象 dianqi ,我需要如何将它向下转型为
                            // 它的子类 Fenduan ,并且调用它的方法 .addStep()?
                            cuanlians.get(cindex).getFendang().addStep();
                        } else if (done == '-') {
                            cuanlians.get(cindex).getFendang().downStep();
                        }

                    }
                    break;
                    case 'L': {
                        String para = peizhiInfo.get(peindex).substring(4);
                        cuanlians.get(cindex).getLianxu().setPara(Double.parseDouble(para));
                    }
                    break;
                }
            }

            //如果现在的用电器类型与信息流里的不匹配,那么就直接跳过

            switch (peType) {
                case 'K': {
                    //对于每一条通路的全部开关,先检测开关名字是否对得上,然后再对对得上的进行修改
                    for (int kaindex = 0; kaindex < cuanlians.get(cindex).getKaiguans().size(); kaindex++) {
                        Kaiguan kg = cuanlians.get(cindex).getKaiguans().get(kaindex);
                        if (kg.getName().equals(name)) {
                            kg.Switch();
                            break;
                        }
                    }

                }
                break;
                case 'H': {
                    if (cuanlians.get(cindex).getHk() == null) {
                        break;
                    }
                    if (cuanlians.get(cindex).getHk().getName().equals(name)) {
                        cuanlians.get(cindex).getHk().switchLeadFoot();
                        break loop;
                    }
                }
                break;
            }

        }
    }

}

private static int getLeadFootLine(String s) {
    char[] chars = s.toCharArray();
    for (int i = 0; i < chars.length - 1; i++) {
        if (chars[i] == 'H') {
            if (chars[i - 1] == '[') {
                if (chars[i + 3] == '3' || chars[i + 3] == '2') {
                    return Integer.parseInt(chars[i + 3] + "");
                }
            } else if (chars[i + 4] == ']') {
                if (chars[i + 3] == '3' || chars[i + 3] == '2') {
                    return Integer.parseInt(chars[i + 3] + "");
                }
            }
        }
    }
    return 0;
}

private static ArrayList<String> getMachine(String line) {
    //#T4:[IN K3-1] [K3-2 M1-IN] [M1-OUT OUT]
    //#T1:[IN P2-2] [P2-1 H1-2] [H1-1 OUT]
    String regex = "([A-Z]\\d)-(1|IN)";
    Pattern p = Pattern.compile(regex);
    Matcher m = p.matcher(line);

    ArrayList<String> as = new ArrayList<>();

    while (m.find()) {
        as.add(m.group(1));
    }
    return as;
}

private static void showAllInfo(Cuanlian mainLian) {
    if(shortLine(mainLian)){
        System.out.println("short circuit error");
        return;
    }
    //开关
    sa.showAllKai();
    //主路线的分档调速器
    if (mainLian.getFendang() != null) {
        mainLian.getFendang().showInfo();
    }
    //主路线上的连续调速器
    if (mainLian.getLianxu() != null) {
        mainLian.getLianxu().showInfo();
    }
    //白炽灯
    sa.showAllBai();
    //日光灯
    sa.showAllRig();
    //吊扇
    sa.showAllDia();
    //落地扇
    sa.showAllRuo();
    //互斥开关
    sa.showAllHck();
    //窗帘
    sa.showAllCua(mainLian.getTb());
    //二极管
    sa.showAllErg();
    /*









     */


}
private static boolean shortLine(Cuanlian mainLian){
    if(mainLian.getTr() == 0 && mainLian.allClose()){
        return true;
    }
    return false;
}

}

//串联电路
class Cuanlian extends Yongdianqi {
//因为引脚电压的分配要考虑电路连接的线性情况
//所以需要在串联类里添加一个内部类,记录电路连接情况 ,分配电压便可以一个一个递减分配

private Huchikaiguan hk;
private int hkLeadFoot;

private StoreAllinfo storeAllinfo;

private ArrayList<Yongdianqi> dianqi = new ArrayList<>();
private ArrayList<Kaiguan> kaiguans = new ArrayList<>();


private Fendang fendang;
private Lianxu lianxu;


private double Tp = 1.0;
private double Tr;
private double Tv;
private double Tb;
private double Ti;
private boolean isMainCuircuit;

private ArrayList<LinkInfo> linkInfos = new ArrayList<>();


//连接信息
class LinkInfo {
    private String name;
    private double inV;
    private double outV;
    private double itsV;

    public LinkInfo(String name) {
        this.name = name;
    }


}

public void addLinkInfo(LinkInfo lf) {
    linkInfos.add(lf);
}


public ArrayList<LinkInfo> getLinkInfos() {
    return linkInfos;
}

public void setLinkInfos(ArrayList<LinkInfo> linkInfos) {
    this.linkInfos = linkInfos;
}

public StoreAllinfo getStoreAllinfo() {
    return storeAllinfo;
}

public void setStoreAllinfo(StoreAllinfo storeAllinfo) {
    this.storeAllinfo = storeAllinfo;
}

public double getTi() {
    return Ti;
}

public void setTi(double ti) {
    Ti = ti;
    allocateImaxWarning();
}

public void allocateImaxWarning() {
    if (hk != null) {
        if (Ti >= hk.getImax()) {
            hk.setImaxWarning(true);
        }
    }
    if (fendang != null) {
        if (Ti >= fendang.getImax()) {
            fendang.setImaxWarning(true);
        }
    } else if (lianxu != null) {
        if (Ti >= lianxu.getImax()) {
            lianxu.setImaxWarning(true);
        }
    }

    for (int i = 0; i < kaiguans.size(); i++) {
        if (Ti >= kaiguans.get(i).getImax()) {
            kaiguans.get(i).setImaxWarning(true);
        }
    }

    for (int i = 0; i < dianqi.size(); i++) {
        if (Ti > dianqi.get(i).getImax()) {
            dianqi.get(i).setImaxWarning(true);
        }
    }

}

//    这个方法的返回值是用于判断这条路的开关是否闭合,如出现普通开关未闭合 或是 限制开关未连接上,则判断为未闭合,因为电流不通过

public boolean allClose() {

    if (hk != null) {
        if (hk.getLeadFoot() != hkLeadFoot) {
            return false;
        }
    }
    for (int i = 0; i < kaiguans.size(); i++) {

        if (kaiguans.get(i).getIsClose() == 0) {

            return false;
        }

    }

    //以下用于主电路判断是否连通 ,或是支线上的串联
    for (int dqIndex = 0; dqIndex < dianqi.size(); dqIndex++) {
        if (dianqi.get(dqIndex) instanceof Binglian) {
            //并联
            Binglian bl = (Binglian) dianqi.get(dqIndex);
            for (int blindex = 0; blindex < bl.getCuanlians().size(); blindex++) {
                if (bl.nullClose()) {
                    return false;
                }
            }
        } else if (dianqi.get(dqIndex) instanceof Cuanlian) {
            //串联
            Cuanlian cl = (Cuanlian) dianqi.get(dqIndex);
            if (!cl.allClose()) {
                return false;
            }
        }
    }

    return true;
}

public void caculateTr() {
    double tr = 0;
    if (allClose()) {
        if (hkLeadFoot != 0) {
            tr += hk.getR();
        }

        for (int i = 0; i < dianqi.size(); i++) {
            if (dianqi.get(i) instanceof Binglian) {
                Binglian bl = (Binglian) dianqi.get(i);
                tr += bl.getBR();
            } else if (dianqi.get(i) instanceof Cuanlian) {
                Cuanlian cl = (Cuanlian) dianqi.get(i);
                tr += cl.getTr();
            } else {
                tr += dianqi.get(i).getR();
            }
        }
    }
    Tr = tr;
}

public void caculateTp() {
    double para = 1.0;
    if (isMainCuircuit) {
        if (fendang != null) {
            para *= fendang.getPara();
        }
        if (lianxu != null) {
            para *= lianxu.getPara();
        }
    }
    Tp = para;
}

public void allocateV() {
    //分配逻辑:
    //先判断断路: 即电路是否为通路,一旦不为通路那么电压分配直接失败 ,将参数设置为0
    //如果为通路,则通过 电压 * 参数 得到可分配电压 ,然后按照电阻占比分配电压给每个用电器
    //  考虑到短路的存在 ,要将那种是通路且没有电阻的并联电路的电阻设置为0;

    //考虑短路
    //考虑断路


    caculateTr();
    if (Tr != 0) {

        caculateTp();
        double totalV = Tv * Tp;
        //设置电流大小
        setTi(totalV / Tr);

        //对于开关打开电路上的电器输入电压全部等于输出电压
        //假设如果先不考虑存在串联电路和并联电路

        if (allClose()) {
            for (int i = 0; i < dianqi.size(); i++) {
                //用电器在分配电压的时候分配设置好引脚电压
                //开关在判断为串联电路的时候设置
                //调速器 和

                double r = dianqi.get(i).getR();
                if (dianqi.get(i) instanceof Binglian) {
                    Binglian bl = (Binglian) dianqi.get(i);
                    r = bl.getBR();
                    //这里在设置好电压后内置了分配,所以不用担心
                    bl.setBV((r / Tr) * totalV);
                    if(r==0){
                        bl.setBV(totalV);
                    }

                } else if (dianqi.get(i) instanceof Cuanlian) {
                    Cuanlian cl = (Cuanlian) dianqi.get(i);
                    r = cl.getTr();
                    //同上
                    cl.setTv((r / Tr) * totalV);

                    if(r==0){
                        cl.setTv(totalV);
                    }

                } else {
                    dianqi.get(i).setV((r / Tr) * totalV);
                }

                if (hk != null && hkLeadFoot == hk.getLeadFoot()) {
                    hk.setV((hk.getR() / Tr) * totalV);
                }

            }
        }
    }
    else {

    }
    allocateItsV();
    allocateLinkInfoV();
    //反哺一波
    linkInfoBack();
}

public void linkInfoBack() {
    for (int lindex = 0; lindex < linkInfos.size(); lindex++) {
        char type = linkInfos.get(lindex).name.charAt(0);
        String name = linkInfos.get(lindex).name;

        switch (type) {
            case 'H': {
                double outV= linkInfos.get(lindex).outV;
                double inV = linkInfos.get(lindex).inV;

                if(!hk.isReverse()){
                    //1是输入,2或3是输出
                    //
                    hk.setLeadFoot1V(inV);
                    if(hkLeadFoot == 2){
                        hk.setLeadFoot2V(outV);
                    }else {
                        hk.setLeadFoot3V(outV);
                    }

                }else {
                    if(hkLeadFoot == 2){
                        hk.setLeadFoot2V(inV);
                    }else {
                        hk.setLeadFoot3V(inV);
                    }
                    hk.setLeadFoot1V(outV);
                }

// if (!hk.isReverse()) {
// //这个时候1是输入引脚,2,3是输出引脚
// //这个时候是互斥开关,如果引脚连接的是1-2,
// if (hk.getLeadFoot() != hkLeadFoot) {
// if (hkLeadFoot == 2) {
// hk.setLeadFoot2V(0);
// } else if (hkLeadFoot == 3) {
// hk.setLeadFoot3V(0);
// }
// } else {
// if (hkLeadFoot == 2) {
// hk.setLeadFoot2V(linkInfos.get(lindex).outV);
// } else if (hkLeadFoot == 3) {
// hk.setLeadFoot3V(linkInfos.get(lindex).outV);
// }
// }
// hk.setLeadFoot1V(linkInfos.get(lindex).inV);
// }
// else {/*
// ----2---}
// }---1
// ----3---}
// */
// //这个时候2,3是输入引脚,1是输出引脚
// if(hk.getLeadFoot() == hkLeadFoot){
// if(hkLeadFoot == 2){
// hk.setLeadFoot2V(linkInfos.get(lindex).inV);
// } else {
// hk.setLeadFoot3V(linkInfos.get(lindex).inV);
// }
//
// }
// else {
// if(hkLeadFoot == 2){
// hk.setLeadFoot2V(0);
// }else {
// hk.setLeadFoot3V(linkInfos.get(lindex).inV);
// }
// }
// hk.setLeadFoot1V(linkInfos.get(lindex).outV);
//
// }

            }
            break;
            case 'K':
            case 'P': {
                for (int i = 0; i < kaiguans.size(); i++) {
                    if (kaiguans.get(i).getName().equals(name)) {
                        kaiguans.get(i).setFootInV(linkInfos.get(lindex).inV);
                        kaiguans.get(i).setFootOutV(linkInfos.get(lindex).outV);
                        if(kaiguans.get(i) instanceof erjiguan){
                            if(((erjiguan) kaiguans.get(i)).getIsClose()==0){
                                kaiguans.get(i).setFootOutV(0);
                            }
                        }
                    }
                }

            }
            break;
            default: {
                for (int i = 0; i < dianqi.size(); i++) {
                    if (dianqi.get(i).getName().equals(name)) {
                        dianqi.get(i).setFootInV(linkInfos.get(lindex).inV);
                        dianqi.get(i).setFootOutV(linkInfos.get(lindex).outV);
                        double v = linkInfos.get(lindex).inV - linkInfos.get(lindex).outV;
                        if(dianqi.get(i) instanceof Cuanlian){
                            ((Cuanlian) dianqi.get(i)).setTv(v);
                        } else if(dianqi.get(i) instanceof Binglian){
                            ((Binglian) dianqi.get(i)).setBV(v);
                        }
                    }
                    break;
                }
            }
        }
    }
}

public void allocateItsV() {
    //这个仅仅是做到了给用电器分配所占电压
    for (int lindex = 0; lindex < linkInfos.size(); lindex++) {
        LinkInfo lk = linkInfos.get(lindex);
        for (int dqindex = 0; dqindex < dianqi.size(); dqindex++) {
            Yongdianqi ydq = dianqi.get(dqindex);
            if (ydq.getName().equals(lk.name)) {
                lk.itsV = ydq.getV();
                break;
            }
        }
    }
    if (hk != null && hkLeadFoot == hk.getLeadFoot()) {
        for (int i = 0; i < linkInfos.size(); i++) {
            if (linkInfos.get(i).name.equals(hk.getName())) {
                linkInfos.get(i).itsV = hk.getV();
            }
        }
    }
}

public void allocateLinkInfoV() {
    //要求是LinkInfo必须是按照线性顺序依次添加的,不然就会分配错位
    double inputV = Tv;

    for (int lindex = 0; lindex < linkInfos.size(); lindex++) {
        //当它是风扇电灯时,当它是开关时,当它是调速器时,当它是互斥开关时,当它是二极管时
        char type = linkInfos.get(lindex).name.charAt(0);
        String name = linkInfos.get(lindex).name;
        LinkInfo lf = linkInfos.get(lindex);

        if (type == 'B' || type == 'R' || type == 'D') {
            linkInfos.get(lindex).inV = inputV;
            inputV -= linkInfos.get(lindex).itsV;
            if (inputV <= 1E-6) {
                inputV = 0;
            }
            linkInfos.get(lindex).outV = inputV;
        } else if (type == 'K') {
            for (int i = 0; i < storeAllinfo.kgs.size(); i++) {
                if (storeAllinfo.kgs.get(i).getName().equals(name)) {
                    lf.inV = inputV;
                    if (storeAllinfo.kgs.get(i).getIsClose() == 1) {
                        lf.outV = lf.inV;
                    }else {
                        lf.outV = 0;
                        inputV = 0;

                    }
                }
            }
        } else if (type == 'H') {
            for (int i = 0; i < storeAllinfo.hcks.size(); i++) {
                if (storeAllinfo.hcks.get(i).getName().equals(name)) {
                    lf.inV = inputV;
                    inputV -= lf.itsV;
                    if (inputV < 1E-6) {
                        inputV = 0;
                    }
                    lf.outV = inputV;
                }
            }
        } else if (type == 'P') {
            for (int i = 0; i < storeAllinfo.ejgs.size(); i++) {
                if (storeAllinfo.ejgs.get(i).getName().equals(name)) {
                    if (storeAllinfo.ejgs.get(i).getIsClose() == 1) {
                        if (inputV < 1E-6) {
                            inputV = 0;
                        }
                        if(Tr!=0){
                            lf.inV = inputV;
                        }
                        lf.outV = lf.inV;
                    } else {
                        lf.inV = inputV;
                        inputV = 0;
                        lf.outV = 0;
                    }
                }
            }
        } else if (type == 'F' || type == 'L') {
            lf.inV = 220;
            double para = 1;
            if (fendang != null) {
                para = fendang.getPara();
            } else {
                para = lianxu.getPara();
            }
            lf.outV = 220 - 220 * para;
        } else if(type == 'M' || type =='T'){
            lf.inV = inputV;
        }

        if(lindex == linkInfos.size()-1){
            lf.outV = 0;
        }


    }
}

// public void allocateFootV(){
// double tempTotalV = Tv;
// double tempV = 0;
//
//
// for (int dqIndex = 0; dqIndex < dianqi.size(); dqIndex++) {
// tempV = dianqi.get(dqIndex).getV();
// if(dianqi.get(dqIndex) instanceof Light){
// //如果是灯则对其引脚电压进行分配
// Light l = (Light) (dianqi.get(dqIndex));
// l.setInV(tempTotalV);
// l.setOutV(tempTotalV-=tempV);
//
// } else if(dianqi.get(dqIndex) instanceof Fan){
// //对电扇分配引脚电压
// Fan f = (Fan) (dianqi.get(dqIndex));
// f.setInV(tempTotalV);
// f.setOutV(tempTotalV-=tempV);
//
// } else if(dianqi.get(dqIndex) instanceof Cuanlian){
// //对串联电路则用递归分配其所带的用电器的引脚电压
// Cuanlian cl = (Cuanlian) dianqi.get(dqIndex);
// cl.allocateFootV();
// } else if(dianqi.get(dqIndex) instanceof Binglian){
// //对并联电路执行依次递归
//
// Binglian bl = (Binglian) dianqi.get(dqIndex);
// for (int blindex = 0; blindex < bl.getCuanlians().size(); blindex++) {
// bl.getCuanlians().get(blindex).allocateFootV();
// }
// }
// }
// }

public void caculateTb() {
    allocateV();
    double Tlux = 0;
    //对于普通通路
    for (int i = 0; i < dianqi.size(); i++) {
        if (dianqi.get(i) instanceof Baizhideng) {
            Tlux += ((Baizhideng) dianqi.get(i)).getBrightNess();
        } else if (dianqi.get(i) instanceof Riguangdeng) {
            Tlux += ((Riguangdeng) dianqi.get(i)).getBrightNess();
        }
    }

    for (int i = 0; i < dianqi.size(); i++) {
        //对于串联电路
        if (dianqi.get(i) instanceof Cuanlian) {
            Cuanlian cl = (Cuanlian) dianqi.get(i);
            cl.caculateTb();
            Tlux += cl.getTb();
        }//对于并联电路
        else if (dianqi.get(i) instanceof Binglian) {
            Binglian bl = (Binglian) dianqi.get(i);
            Tlux += bl.getBB();
        }
    }
    Tb = Tlux;
}


public Cuanlian() {
}


public void addYongdianqi(Yongdianqi yd) {
    dianqi.add(yd);
}

public void addKaiguans(Kaiguan kg) {
    kaiguans.add(kg);
}

public ArrayList<Kaiguan> getKaiguans() {
    return kaiguans;
}


public void setHkLeadFoot(int leadFoot) {
    hkLeadFoot = leadFoot;
}

public void setHk(Huchikaiguan hk) {
    this.hk = hk;
}

public Huchikaiguan getHk() {
    return hk;
}

public Lianxu getLianxu() {
    return lianxu;
}

public void setLianxu(Lianxu lianxu) {
    this.lianxu = lianxu;
    caculateTp();
}

public Fendang getFendang() {
    return fendang;
}

public void setFendang(Fendang fendang) {
    this.fendang = fendang;
    caculateTp();
}

public void setMainCuircuit() {
    isMainCuircuit = true;
}

public boolean isMainCuircuit() {
    return isMainCuircuit;
}

public ArrayList<Yongdianqi> getDianqi() {
    return dianqi;
}

public double getTr() {
    caculateTr();
    return Tr;
}

public void setTr(double tr) {
    caculateTr();
    Tr = tr;
}

public double getTv() {

    return Tv;
}

public void setTv(double tv) {
    Tv = tv;
    allocateV();
}

public double getTb() {
    caculateTb();
    return Tb;

}

public void setTb(double tb) {
    Tb = tb;
}

public double getTp() {
    caculateTp();
    return Tp;
}

public void setTp(double tp) {
    Tp = tp;
}

@Override
public void showInfo() {
    for (int i = 0; i < kaiguans.size(); i++) {
        kaiguans.get(i).showInfo();
    }
    if (fendang != null) {
        fendang.showInfo();
    }
    if (lianxu != null) {
        lianxu.showInfo();
    }
    for (int i = 0; i < dianqi.size(); i++) {
        dianqi.get(i).showInfo();
    }
}

@Override
public double getImax() {
    return 0;
}

}

class Binglian extends Yongdianqi {
private ArrayList cuanlians = new ArrayList<>();

public double getBB() {
    double bb = 0;
    for (int i = 0; i < cuanlians.size(); i++) {
        bb += cuanlians.get(i).getTb();
    }
    return bb;
}

public void addCuanlian(Cuanlian cuanlian) {
    cuanlians.add(cuanlian);
}

public Binglian() {
}


public ArrayList<Cuanlian> getCuanlians() {
    return cuanlians;
}

public void setCuanlians(ArrayList<Cuanlian> cuanlians) {
    this.cuanlians = cuanlians;
}

//并联里用于判断电路开关是为了确保,不会出现没有一条路是通的情况
//这个方法是用于判断并联电路是不是没有一条通路
public boolean nullClose() {
    for (int i = 0; i < cuanlians.size(); i++) {
        if (cuanlians.get(i).allClose()) {
            return false;
        }
    }
    return true;
}

//    判断是否短路
public boolean isDuanlu() {
    for (int i = 0; i < cuanlians.size(); i++) {
        if (cuanlians.get(i).allClose() && cuanlians.get(i).getTr() == 0) {
            for (int i1 = 0; i1 < cuanlians.size(); i1++) {
                if (cuanlians.get(i1).allClose() && cuanlians.get(i1).getTr() != 0 && i1 != i) {
                    return true;
                }
            }
        }
    }
    return false;
}

public void caculateR() {
    if (isDuanlu()) {
        setR(0);
        return;
    }
    double r = 0;
    if (!nullClose()) {
        for (int i = 0; i < cuanlians.size(); i++) {
            if (cuanlians.get(i).getTr() == 0) {
                continue;
            }
            r += 1.0 / cuanlians.get(i).getTr();
        }
        if (r == 0) {
            return;
        }
        setR(1.0 / r);
    }

}

public double getBR() {
    caculateR();
    return getR();
}

public void allocateV() {
    for (int i = 0; i < cuanlians.size(); i++) {
        cuanlians.get(i).setTv(getV());
    }
}

public void setBV(double v) {
    setV(v);
    allocateV();
}

@Override
public void showInfo() {
}

@Override
public double getImax() {
    return 0;
}

}

abstract class Yongdianqi {

private double footInV;
private double footOutV;
private String name;
private int sequence;
private double I;
private double R;
private double V;
private boolean ImaxWarning = false;

public double getFootInV() {
    return footInV;
}

public void setFootInV(double footInV) {
    this.footInV = footInV;
}

public double getFootOutV() {
    return footOutV;
}

public void setFootOutV(double footOutV) {
    this.footOutV = footOutV;
}

public Yongdianqi() {
}

public Yongdianqi(String name, double i, double r, double v) {
    this.name = name;
    I = i;
    R = r;
    V = v;
}

public int getSequence() {
    return sequence;
}

public void setSequence(int sequece) {
    this.sequence = sequece;
}

public void setName(String name) {
    this.name = name;
    sequence = Character.valueOf(name.charAt(1));
}

public String getName() {
    return name;
}

public double getI() {
    return I;
}

public void setI(double i) {
    I = i;
}

public double getR() {
    return R;
}

public void setR(double r) {
    R = r;
}

public double getV() {
    return V;
}

public void setV(double v) {
    V = v;
}

abstract public void showInfo();

public boolean isImaxWarning() {
    return ImaxWarning;
}

public void setImaxWarning(boolean imaxWarning) {
    ImaxWarning = imaxWarning;
}

public void SwitchImaxWarning() {
    ImaxWarning = !ImaxWarning;
}

public String setWarning() {
    return " exceeding current limit error";
}

abstract public double getImax();

}

class Kaiguan {
private boolean ImaxWarning;

private int foot_in;
private int foot_out;

private double footInV;
private double footOutV;

private String name;
private int isClose;
private int sequence;

public double getImax() {
    return 20;
}

public void Switch() {
    if (isClose == 0) {
        setIsClose(1);
    } else {
        setIsClose(0);
    }
}

public String setWaring() {
    return " exceeding current limit error";
}

public void showInfo() {
    if (isClose == 0) {
        System.out.print("@" + name + ":turned on");
        System.out.print(String.format(" %.0f-%.0f", footInV, footOutV));
    } else {
        System.out.print("@" + name + ":closed");
        System.out.print(String.format(" %.0f-%.0f", footInV, footOutV));
        if (isImaxWarning()) {
            System.out.print(setWaring());
        }
    }


    System.out.println();
}

public void setSequence(int sequence) {
    this.sequence = sequence;
}

public int getSequence() {
    return sequence;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
    sequence = Integer.parseInt(name.charAt(1) + "");
}

public int getIsClose() {
    return isClose;
}

public void setIsClose(int isClose) {
    this.isClose = isClose;
    if (isClose == 1) {
        foot_in = 1;
        foot_out = 2;
    } else {
        foot_in = 2;
        foot_out = 1;
    }
}

public double getFootInV() {
    return footInV;
}

public void setFootInV(double footInV) {
    this.footInV = footInV;
}

public double getFootOutV() {
    return footOutV;
}

public void setFootOutV(double footOutV) {
    this.footOutV = footOutV;
}

public int getFoot_in() {
    return foot_in;
}

public void setFoot_in(int foot_in) {
    this.foot_in = foot_in;
}

public int getFoot_out() {
    return foot_out;
}

public void setFoot_out(int foot_out) {
    this.foot_out = foot_out;
}

public boolean isImaxWarning() {
    return ImaxWarning;
}

public void setImaxWarning(boolean imaxWarning) {
    ImaxWarning = imaxWarning;
}

}

abstract class Tiaoshuqi {
private double footInV;
private double footOutV;

private double para;
private boolean ImaxWarning;

private String name;
private int sequence;

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
    sequence = Character.valueOf(name.charAt(1));

}

public int getSequence() {
    return sequence;
}

public void setSequence(int sequence) {
    this.sequence = sequence;
}

public Tiaoshuqi() {
}

public Tiaoshuqi(double para, String name) {
    this.para = para;
    this.name = name;
}

public double getPara() {
    return para;
}

public void setPara(double para) {
    this.para = para;
}

abstract void showInfo();

public boolean isImaxWarning() {
    return ImaxWarning;
}

public void setImaxWarning(boolean setImaxWarning) {
    this.ImaxWarning = setImaxWarning;
}

public double getFootInV() {
    return footInV;
}

public void setFootInV(double footInV) {
    this.footInV = footInV;
}

public double getFootOutV() {
    return footOutV;
}

public void setFootOutV(double footOutV) {
    this.footOutV = footOutV;
}

}

class Fendang extends Tiaoshuqi {

private int step;

public double getImax() {
    return 18;
}

public void addStep() {
    if (step < 3) {
        step++;
    }
    caculatePara();
}

public void downStep() {
    if (step > 0) {
        step--;
    }
    caculatePara();
}

public Fendang() {
}

public String setWaring() {
    return " exceeding current limit error";
}

@Override
void showInfo() {
    System.out.print("@" + getName() + ":" + step);
    System.out.print(String.format(" %.0f-%.0f", getFootInV(), getFootOutV()));
    if (isImaxWarning()) {
        System.out.print(setWaring());
    }
    System.out.println();
}

private void caculatePara() {
    switch (step) {
        case 0:
            setPara(0);
            break;
        case 1:
            setPara(0.3);
            break;
        case 2:
            setPara(0.6);
            break;
        case 3:
            setPara(0.9);
            break;
        default:
            break;
    }

}

}

class Lianxu extends Tiaoshuqi {

public double getImax() {
    return 18;
}


public Lianxu() {
}

public String setWarning() {
    return " exceeding current limit error";
}

@Override
public void showInfo() {
    System.out.printf("@%s:%.2f", getName(), getPara());
    System.out.print(String.format(" %.0f-%.0f", getFootInV(), getFootOutV()));
    if (isImaxWarning()) {
        System.out.print(setWarning());
    }
    System.out.println();
}

public Lianxu(double p, String name) {
    super(p, name);
}

}

abstract class Light extends Yongdianqi {
private double Imax;

private int foot_in = 1;
private int foot_out = 2;

private double inV;
private double outV;


private double brightNess;

public double getImax() {
    return Imax;
}

public void setImax(double imax) {
    Imax = imax;
}

public double getBrightNess() {
    caculateBri();
    return brightNess;
}

public void setBrightNess(double brightNess) {
    this.brightNess = brightNess;
}

public abstract void caculateBri();

public int getFoot_in() {
    return foot_in;
}

public void setFoot_in(int foot_in) {
    this.foot_in = foot_in;
}

public int getFoot_out() {
    return foot_out;
}

public void setFoot_out(int foot_out) {
    this.foot_out = foot_out;
}

public double getInV() {
    return inV;
}

public void setInV(double inV) {
    this.inV = inV;
}

public double getOutV() {
    return outV;
}

public void setOutV(double outV) {
    this.outV = outV;
}

}

class Baizhideng extends Light {
@Override
public double getImax() {
return 9;
}

public Baizhideng() {
    setR(10.0);
}

@Override
public void showInfo() {
    caculateBri();
    System.out.printf("@%s:%d", getName(), (int) getBrightNess());
    System.out.print(String.format(" %.0f-%.0f", getFootInV(), getFootOutV()));
    //发出电流过大警告
    if (isImaxWarning()) {
        System.out.print(setWarning());
    }
    System.out.println();
}


@Override
public void caculateBri() {
    //0~9v :0
    //10v :50
    //220v :200
    //1.4v/lux
    double volt = getV();
    if (volt <= 9) {
        setBrightNess(0.0);
    } else if (volt >= 220) {
        setBrightNess(200.0);
    } else {
        setBrightNess(50 + (volt - 10) * ((150.0) / 210));
    }
}

}

class Riguangdeng extends Light {
public double getImax() {
return 5;
}

public Riguangdeng() {
    setR(5);
}

public Riguangdeng(double bright) {
    setBrightNess(bright);
}


@Override
public void showInfo() {
    caculateBri();
    System.out.printf("@%s:%d", getName(), (int) getBrightNess());
    System.out.print(String.format(" %.0f-%.0f", getFootInV(), getFootOutV()));
    //发出电流过大警告
    if (isImaxWarning()) {
        System.out.println(setWarning());
    }
    System.out.println();
}

@Override
public void caculateBri() {
    double volt = getV();
    if (volt > 0) {
        setBrightNess(180);
    } else {
        setBrightNess(0);
    }
}

}

//这个是窗帘
class Chuanglian extends Yongdianqi {

private double R = 15.0;
private double bili = 1.0;

public double getImax() {
    return 12;
}

public void caculateBili(double lux) {
    if (getV() >= 50) {
        if (lux >= 0 && lux < 50) {
            bili = 1.0;
        } else if (lux >= 50 && lux <= 100) {
            bili = 0.8;
        } else if (lux >= 100 && lux < 200) {
            bili = 0.6;
        } else if (lux >= 200 && lux < 300) {
            bili = 0.4;
        } else if (lux >= 300 && lux < 400) {
            bili = 0.2;
        } else {
            bili = 0;
        }
    } else {
        bili = 1.0;
    }
}

public double getR() {
    return R;
}

@Override
public void showInfo() {
}

public void showInfo(double lux) {
    caculateBili(lux);
    System.out.print("@" + getName() + ":" + String.format("%.0f", bili * 100) + "%");
    System.out.print(String.format(" %.0f-%.0f", getFootInV(), getFootOutV()));
    //发出电流过大警告
    if (isImaxWarning()) {
        System.out.println(setWarning());
    }
    System.out.println();
}

}

abstract class Fan extends Yongdianqi {
private double Imax;

private int foot_in = 1;
private int foot_out = 2;

private double inV;
private double outV;

public double getImax() {
    return Imax;
}

public void setImax(double imax) {
    Imax = imax;
}

public int getFoot_in() {
    return foot_in;
}

public void setFoot_in(int foot_in) {
    this.foot_in = foot_in;
}

public int getFoot_out() {
    return foot_out;
}

public void setFoot_out(int foot_out) {
    this.foot_out = foot_out;
}

public double getInV() {
    return inV;
}

public void setInV(double inV) {
    this.inV = inV;
}

public double getOutV() {
    return outV;
}

public void setOutV(double outV) {
    this.outV = outV;
}

private double rspeed;

public Fan() {
}

public Fan(double rspeed) {
    this.rspeed = rspeed;
}

public abstract void caculateRsp();

public double getRspeed() {
    return rspeed;
}

public void setRspeed(double rspeed) {
    this.rspeed = rspeed;
}

@Override
public void showInfo() {
    caculateRsp();
    System.out.printf("@%s:%d", getName(), (int) getRspeed());
    System.out.print(String.format(" %.0f-%.0f", getFootInV(), getFootOutV()));
    //发出电流过大警告
    if (isImaxWarning()) {
        System.out.println(setWarning());
    }
    System.out.println();
}

}

class Diaosan extends Fan {
public double getImax() {
return 12;
}

public Diaosan() {
    setR(20);
}

public void caculateRsp() {
    double volt = getV();
    if (volt < 80) {
        setRspeed(0);
    } else if (volt >= 150) {
        setRspeed(360);
    } else {
        setRspeed((int) (80 + 4 * (volt - 80)));
    }

}

}

class Ruodisan extends Fan {

public double getImax() {
    return 14;
}

public Ruodisan() {
    setR(20);
}


@Override
public void caculateRsp() {
    double volt = getV();
    if (volt < 80) {
        setRspeed(0);
    } else if (volt >= 80 && volt <= 99) {
        setRspeed(80);
    } else if (volt >= 100 && volt <= 119) {
        setRspeed(160);
    } else if (volt >= 120 && volt <= 139) {
        setRspeed(260);
    } else if (volt >= 140) {
        setRspeed(360);
    }
}

}

class Huchikaiguan extends Yongdianqi {
private boolean isReverse = false;
private String name;
private int leadFoot = 2;
private double leadFoot2V;
private double leadFoot3V;
private double leadFoot1V;

public boolean isReverse() {
    return isReverse;
}

public void setReverse(boolean reverse) {
    isReverse = reverse;
}

public double getImax() {
    return 20;
}

public Huchikaiguan() {
}


public double getR() {
    if (leadFoot == 2) {
        return 5.0;
    } else {
        return 10.0;
    }
}

@Override
public void showInfo() {
    System.out.print("@" + name);
    if (leadFoot == 2) {
        System.out.print(":closed");
        //System.out.print(" "+getLeadFoot1V()+"-"+getLeadFoot2V()+"-"+getLeafFoot3V());

    } else if (leadFoot == 3) {
        System.out.print(":turned on");
    }

    System.out.print(String.format(" %.0f-%.0f-%.0f", getLeadFoot1V(), getLeadFoot2V(), getLeadFoot3V()));
    //发出电流过大警告

    if (isImaxWarning()) {
        System.out.print(setWarning());
    }
    System.out.println();
}

@Override
public String getName() {
    return name;
}

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

public void switchLeadFoot() {
    if (leadFoot == 2) {
        leadFoot = 3;
    } else if (leadFoot == 3) {
        leadFoot = 2;
    }
}

public int getLeadFoot() {
    return leadFoot;
}

public double getLeadFoot2V() {
    return leadFoot2V;
}

public void setLeadFoot2V(double leadFoot2V) {
    this.leadFoot2V = leadFoot2V;
}

public double getLeadFoot3V() {
    return leadFoot3V;
}

public void setLeadFoot3V(double leadFoot3V) {
    this.leadFoot3V = leadFoot3V;
}

public double getLeadFoot1V() {
    return leadFoot1V;
}

public void setLeadFoot1V(double leadFoot1V) {
    this.leadFoot1V = leadFoot1V;
}

}

class erjiguan extends Kaiguan {
private double leadFoot1V;
private double leadFoot2V;
public double getImax() {
return 8;
}

public void setFoot(int foot_in, int foot_out) {
    //情况是这样的,我希望输入引脚然后可以设置引脚
    //通过引脚判断到底是开启还是关闭状态
    setFoot_in(foot_in);
    setFoot_out(foot_out);

    if (foot_in == 1 && foot_out == 2) {
        setIsClose(1);

    } else {
        setIsClose(0);
    }
}

public void showInfo() {
    System.out.print("@" + getName() + ":");
    if (getIsClose() == 1) {
        System.out.print("conduction");
    } else if (getIsClose() == 0) {
        System.out.print("cutoff");
    }
    System.out.print(String.format(" %.0f-%.0f", getLeadFoot1V(), getLeadFoot2V()));

    if (isImaxWarning()) {
        System.out.print(setWaring());
    }
    System.out.println();
}

public double getLeadFoot1V() {
    if(getIsClose()==0){
        leadFoot1V = 0;
    }else {
        leadFoot1V = getFootInV();
    }
    return leadFoot1V;
}

public void setLeadFoot1V(double leadFoot1V) {
    this.leadFoot1V = leadFoot1V;
}

public double getLeadFoot2V() {
    if(getIsClose() == 0){
        leadFoot2V = getFootInV();
    }else {
        leadFoot2V = getFootOutV();
    }
    return leadFoot2V;
}

public void setLeadFoot2V(double leadFoot2V) {
    this.leadFoot2V = leadFoot2V;
}

}

class StoreAllinfo {
ArrayList kgs = new ArrayList<>();
ArrayList bzs = new ArrayList<>();
ArrayList rgds = new ArrayList<>();
ArrayList dss = new ArrayList<>();
ArrayList rds = new ArrayList<>();
ArrayList cls = new ArrayList<>();
ArrayList hcks = new ArrayList<>();

ArrayList<erjiguan> ejgs = new ArrayList<>();

public void addKaiguan(Kaiguan kg) {
    kgs.add(kg);
    if (kgs.size() != 1) {
        KaiguanSort();

    }
}

public void addBaizhideng(Baizhideng bzd) {
    bzs.add(bzd);
    if (bzs.size() != 1) {
        BaizhidengSort();

    }
}

public void addRiguangdeng(Riguangdeng rgd) {
    rgds.add(rgd);
    if (rgds.size() != 1) {
        RiguangdengSort();

    }
}

public void addDiaosan(Diaosan ds) {
    dss.add(ds);
    if (dss.size() != 1) {
        DiaosanSort();

    }
}

public void addRuodisan(Ruodisan rd) {
    rds.add(rd);
    if (rds.size() != 1) {
        RuodisanSort();
    }
}

public void addCuanglian(Chuanglian cl) {
    cls.add(cl);
    if (cls.size() != 1) {
        CuanglianSort();
    }
}

public void addHuchikaiguan(Huchikaiguan hck) {
    for (int i = 0; i < hcks.size(); i++) {
        if (hcks.get(i) == hck) {
            return;
        }
    }
    hcks.add(hck);
    if (hcks.size() != 1) {
        HuchikaiguanSort();
    }
}

public void addErjiguan(erjiguan e) {
    for (int i = 0; i < ejgs.size(); i++) {
        if (ejgs.get(i) == e) {
            return;
        }
    }
    ejgs.add(e);
    if (ejgs.size() != 1) {
        erjiguanSort();
    }
}

public void erjiguanSort() {
    Collections.sort(ejgs, Comparator.comparingInt(erjiguan::getSequence));
}

public void KaiguanSort() {
    Collections.sort(kgs, Comparator.comparingInt(Kaiguan::getSequence));
}

public void BaizhidengSort() {
    Collections.sort(bzs, Comparator.comparingInt(Baizhideng::getSequence));
}

public void RiguangdengSort() {
    Collections.sort(rgds, Comparator.comparingInt(Riguangdeng::getSequence));
}

public void DiaosanSort() {
    Collections.sort(dss, Comparator.comparingInt(Diaosan::getSequence));
}

public void RuodisanSort() {
    Collections.sort(rds, Comparator.comparingInt(Ruodisan::getSequence));
}

public void CuanglianSort() {
    Collections.sort(cls, Comparator.comparingInt(Chuanglian::getSequence));
}

public void HuchikaiguanSort() {
    Collections.sort(hcks, Comparator.comparingInt(Huchikaiguan::getSequence));
}

public void showAllErg() {
    for (int i = 0; i < ejgs.size(); i++) {
        ejgs.get(i).showInfo();
    }
}

public void showAllKai() {
    for (int i = 0; i < kgs.size(); i++) {
        kgs.get(i).showInfo();
    }
}

public void showAllBai() {
    for (int i = 0; i < bzs.size(); i++) {
        bzs.get(i).showInfo();
    }
}

public void showAllRig() {
    for (int i = 0; i < rgds.size(); i++) {
        rgds.get(i).showInfo();
    }
}

public void showAllDia() {
    for (int i = 0; i < dss.size(); i++) {
        dss.get(i).showInfo();
    }
}

public void showAllRuo() {
    for (int i = 0; i < rds.size(); i++) {
        rds.get(i).showInfo();
    }
}

public void showAllCua(double lux) {
    for (int i = 0; i < cls.size(); i++) {
        cls.get(i).showInfo(lux);
    }
}

public void showAllHck() {
    for (int i = 0; i < hcks.size(); i++) {
        hcks.get(i).showInfo();
    }
}

}
/*

//单并联互斥 非零返回? 可能是抛出了未被捕获的异常

T1:[IN P2-1] [P2-2 H1-2] [H1-1 OUT]

T2:[IN D1-1] [D1-2 H1-3] [H1-1 OUT]

M1:[T1 T2]

H1

T2:[IN D4-1] [D4-2 K2-1][K2-2 OUT]

T1:[IN D1-1] [D1-2 P2-2] [P2-1 OUT]

M1:[T1 T2]

T8:[IN D2-1] [D2-2 M1-1] [M1-2 OUT]

T9:[IN D3-1] [D3-2 K9-1] [K9-2 OUT]

M2:[T8 T9]

T4:[VCC K3-1] [K3-2 M2-IN] [M2-OUT GND]

K3

K9

K2

end

T9:[IN P2-1][P2-2 D8-1][D8-2 OUT]

T8:[IN K2-1][K2-2 D2-1][D2-2 T9-IN][T9-OUT OUT]

T1:[VCC D1-1][D1-2 K1-1][K1-2 T8-IN][T8-OUT GND]

K1

K2

end

*/

源码分析:
Main:程序的入口类,包含 main 方法。它负责初始化电路配置,分配电压,并展示所有信息。

StoreAllinfo:一个用于存储所有电路组件信息的类。它包含多个 ArrayList,分别存储不同类型的电路元件,如开关(Kaiguan)、灯泡(Baizhideng、Riguangdeng)、风扇(Diaosan、Ruodisan)、窗帘(Chuanglian)、互斥开关(Huchikaiguan)和二极管(erjiguan)。

Cuanlian:表示一个串联电路的类,它继承自 Yongdianqi 类。该类包含多个用电器、开关、调速器等,并提供方法来计算总电阻、分配电压、计算亮度等。

Binglian:表示一个并联电路的类,它也继承自 Yongdianqi 类。该类包含多个串联电路,并提供方法来计算并联电路的等效电阻和电压分配。

Yongdianqi(用电器):这是一个抽象类,为所有具体的用电器(如灯泡、风扇等)提供一个共同的接口。它包含电压、电流、电阻等基本属性。

Kaiguan(开关):表示电路中的一个开关组件,包含开关状态和名称,并提供切换状态的方法。

Tiaoshuqi(调速器):这是一个抽象类,用于表示可以调整电路参数的设备,如分档调速器和连续调速器。

Fendang(分档调速器):继承自 Tiaoshuqi 类,表示一个可以分档调节的调速器。

Lianxu(连续调速器):同样继承自 Tiaoshuqi 类,表示一个可以连续调节的调速器。

Light:这是一个抽象类,所有不同类型的光源(如白炽灯和日光灯)都继承自此类。

Baizhideng(白炽灯):继承自 Light 类,表示一个白炽灯泡,并提供计算亮度的方法。

Riguangdeng(日光灯):同样继承自 Light 类,表示一个日光灯,并提供计算亮度的方法。

Chuanglian(窗帘):继承自 Yongdianqi 类,表示一个可以通过电压控制透光率的窗帘。

Fan:这是一个抽象类,所有不同类型的风扇(如吊扇和落地扇)都继承自此类。

Diaosan(吊扇):继承自 Fan 类,表示一个吊扇,并提供计算转速的方法。

Ruodisan(落地扇):同样继承自 Fan 类,表示一个落地扇,并提供计算转速的方法。

Huchikaiguan(互斥开关):继承自 Yongdianqi 类,表示一个可以切换引脚状态的互斥开关。

erjiguan(二极管):继承自 Kaiguan 类,表示一个二极管,并提供根据引脚状态判断是否导通的方法。

我发现了原本存在的一些问题并进行了修改:

在 getMachine 方法中,正则表达式用于提取电路元件信息,但如果输入的格式与预期不符,可能会导致未捕获的异常,处理,对异常进行了数据丢弃。
shortLine 方法用于检测短路,但仅检查了主电路的总电阻和闭合状态。在复杂的电路中,可能存在未被检测到的短路情况,于是我重写了shortLine()对全部电路进行了检测
Huchikaiguan 类中的 switchLeadFoot 方法在切换引脚状态时没有考虑电路的当前状态,可能会导致不正确的行为。
在 Cuanlian 类的 allocateV 方法中,电压分配逻辑可能在面对复杂的电路结构时无法正确处理并联和串联电路的电压分配。

以下是同学提出的意见:
代码中存在硬编码的值(如电阻值、电压阈值等),这些应该被定义为常量或通过配置文件管理。
错误处理:代码应该添加适当的异常处理逻辑,以处理不合法的输入或电路状态。
代码重构:一些方法过长,包含多个功能,应该被拆分为更小的、更易管理的方法。
性能问题:在 StoreAllinfo 类中,对集合进行排序的方法(如 KaiguanSort)在每次添加新元素后都被调用,这可能会导致性能问题。可以考虑使用其他数据结构或延迟排序。

总结:
这两次作业我学会了如何在遇到无法解决的编程问题时及时与同学,老师进行沟通,即使不能完全解决问题,也能尽可能地将问题带来的损害最小化;复习了高中电路逻辑;
心平气和地接受自己代码能力的不足;学会使用Lambda表达式对类的对象进行排序(之前都是用比较器);

课程建议:
在每到一段大作业的全部迭代结束后,由出题老师对大作业的各次迭代进行网课讲解,并且对其中的测试点,注意事项进行拆解,这样或许能提高学生们的平均水平,如果老师们有心提高本专业本科生的的编程能力的话,没有的话就当我没说.