智能家居是在当下家庭中越来越流行的一种配置方案,它通过物联网技术将家中的各种设备(如音视频设备、照明系统、窗帘控制、空调控制、安防系统、数字影院系统、影音服务器、影柜系统、网络家电等)连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。与普通家居相比,智能家居不仅具有传统的居住功能,兼备建筑、网络通信、信息家电、设备自动化,提供全方位的信息交互功能。请根据如下要去设计一个智能家居强电电路模拟系统。以下题目介绍中加粗的部分为本次迭代在“家居强电电路模拟程序-1”的基础上增加的功能要求。
1、控制设备
本题模拟的控制设备包括:开关、分档调速器、连续调速器。
开关:包括0和1两种状态。
开关有两个引脚,任意一个引脚都可以是输入引脚,而另一个则是输出引脚。开关状态为0时,无论输入电位是多少,输出引脚电位为0。当开关状态为1时,输出引脚电位等于输入电位。
分档调速器
按档位调整,常见的有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 转/分钟。电压在[80,100)V 区间对应转速为 80 转/分 钟,[100-120)V 区间对应转速为 160 转/分钟,[120-140)V 区间对应转速为 260 转/分钟,超过 140V 转速 为 360 转/分钟(本次迭代暂不考虑电压超标的异常情况)输入信息:
本次迭代考虑电阻:白炽灯的电阻为 10,日光灯的电阻为 5,吊扇的电阻为 20,落 地扇的电阻为 20
3、输入信息
1)输入设备信息
分别用设备标识符K、F、L、B、R、D、A分别表示开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇。
设备标识用标识符+编号表示,如K1、F3、L2等。
引脚格式:设备标识-引脚编号,例如:K1-1标识编号为1的开关的输入引脚。
三种控制开关的输入引脚编号为1,输出引脚编号为2。
受控设备的两个引脚编号分别为1、2。
约束条件:
不同设备的编号可以相同。
同种设备的编号可以不连续。
设备信息不单独输入,包含在连接信息中。
2)输入连接信息
一条连接信息占一行,用[]表示一组连接在一起的设备引脚,引脚与引脚之间用英文空格" "分隔。
格式:"["+引脚号+" "+...+" "+引脚号+"]"
例如:[K1-1 K3-2 D5-1]表示K1的输入引脚,K3的输出引脚,D5的1号引脚连接在一起。
约束条件:
不考虑调速器串联到其他调速器的情况。
不考虑调速器串联到其他调速器的情况。
考虑各类设备的并联接入。例如,K1 的输出接到 L2 的输入,L2 的输出再接其他设备属于串联接线。K1 的输出接到 L2 的输出,同时 K1 的输入接到 L2 的输入,这种情况属于并联。
本次迭代的连接信息不单独输入,包含在线路信息中。
3)输入控制设备调节信息
开关调节信息格式:
#+设备标识K+设备编号,例如:#K2,代表切换K2开关的状态。
分档调速器的调节信息格式:
#+设备标识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的一个部分,本题不考虑这种类型的输入,而是当将T1\T2的所有连接信息直接包含在T3中定义。
下次迭代中需要考虑这种类型的输入。
4、输出信息:
按开关、分档调速器、连续调速器、白炽灯、日光灯、吊扇、落地扇的顺序依次输出所有设备的状态或参数。每个设备一行。同类设备按编号顺序从小到大输出。
输出格式:@设备标识+设备编号+":" +设备参数值(控制开关的档位或状态、灯的亮度、风扇的转速,只输出值,不输出单位)
连续调速器的档位信息保留两位小数,即使小数为0,依然显示两位小数.00。
开关状态为0(打开)时显示turned on,状态为1(合上)时显示closed
如:
@K1:turned on
@B1:190
@L1:0.60
5、家居电路模拟系列所有题目的默认规则:
1)当计算电压值等数值的过程中,最终结果出现小数时,用截尾规则去掉小数部分,只保留整数部分。为避免精度的误差,所有有可能出现小数的数值用double类型保存并计算,不要作下转型数据类型转换,例如电压、转速、亮度等,只有在最后输出时再把计算结果按截尾规则,舍弃尾数,保留整数输出。
2)所有连接信息按电路从电源到接地的顺序依次输入,不会出现错位的情况。电源VCC一定是第一个连接的第一项,接地GND一定是最后一个连接的后一项。
3)连接信息如果只包含两个引脚,靠电源端的引脚在前,靠接地端的在后。
4)调速器的输入端只会直连VCC,不会接其他设备。整个电路最多只有连接在电源上的一个调速器,且不包含在并联单路中。
6、家居电路模拟系列1-4题目后续迭代设计:
1)电路结构变化:
迭代1:只有一条线路,所有元件串联
迭代2:线路中包含一个并联电路
迭代3:线路中包含多个串联起来的并联电路
迭代4:并联电路之间可能出现包含关系
电路结构变化示意图见图1。
2)计算方式的变化
迭代1只包含1个受控元件,不用计算电流,之后的电路计算要包含电流、电阻等电路参数。
3)电路元件的变化
每次迭代会增加1-2个新的电路元件。
import java.util.*;
// 设备类
abstract class Device {
protected String identifier; // 设备标识符
protected int pinNumber; // 引脚编号
protected double voltageIn; // 输入电压
protected double voltageOut; // 输出电压
public Device(String identifier, int pinNumber) {
this.identifier = identifier;
this.pinNumber = pinNumber;
this.voltageIn = 0.0;
this.voltageOut = 0.0;
}
public abstract void calculateVoltageOut();
}
// 控制设备类
abstract class ControlDevice extends Device {
protected int status; // 状态或档位属性
public ControlDevice(String identifier, int pinNumber) {
super(identifier, pinNumber);
this.status = 0;
}
public void setStatus(int status) {
this.status = status;
calculateVoltageOut();
}
public int getStatus() {
return status;
}
}
// 开关类
class Switch extends ControlDevice {
public Switch(String identifier, int pinNumber) {
super(identifier, pinNumber);
}
@Override
public void calculateVoltageOut() {
if (status == 1) {
voltageOut = voltageIn;
} else {
voltageOut = 0.0;
}
}
}
// 分档调速器类
class SpeedController extends ControlDevice {
public SpeedController(String identifier, int pinNumber) {
super(identifier, pinNumber);
}
@Override
public void calculateVoltageOut() {
switch (status) {
case 0:
voltageOut = 0.0;
break;
case 1:
voltageOut = voltageIn * 0.3;
break;
case 2:
voltageOut = voltageIn * 0.6;
break;
case 3:
voltageOut = voltageIn * 0.9;
break;
default:
voltageOut = 0.0;
break;
}
}
}
// 连续调速器类
class ContinuousController extends ControlDevice {
public ContinuousController(String identifier, int pinNumber) {
super(identifier, pinNumber);
}
@Override
public void calculateVoltageOut() {
voltageOut = voltageIn * status;
}
}
// 受控设备类
abstract class ControlledDevice extends Device {
public ControlledDevice(String identifier, int pinNumber) {
super(identifier, pinNumber);
}
}
// 灯类
class Lamp extends ControlledDevice {
private double resistance; // 电阻
public Lamp(String identifier, int pinNumber, double resistance) {
super(identifier, pinNumber);
this.resistance = resistance;
}
@Override
public void calculateVoltageOut() {
if (identifier.equals("B")) {
if (voltageIn <= 9.0) {
voltageOut = 0.0;
} else if (voltageIn >= 220.0) {
voltageOut = 200.0;
} else {
voltageOut = 50.0 * (voltageIn - 10.0);
}
} else if (identifier.equals("R")) {
if (voltageIn == 0.0) {
voltageOut = 0.0;
} else {
voltageOut = 180.0;
}
}
}
}
// 风扇类
class Fan extends ControlledDevice {
private double resistance; // 电阻
public Fan(String identifier, int pinNumber, double resistance) {
super(identifier, pinNumber);
this.resistance = resistance;
}
@Override
public void calculateVoltageOut() {
if (voltageIn < 80.0) {
voltageOut = 0.0;
} else if (voltageIn >= 150.0) {
voltageOut = 360.0;
} else {
voltageOut = 80.0 + (voltageIn - 80.0) * 2.0;
}
}
}
public class Main {
public static void main(String[] args) {
try {
Scanner scanner = new Scanner(System.in);
// 输入设备信息
Map<String, Device> deviceMap = new HashMap<>();
String line;
while (!(line = scanner.nextLine()).equals("end")) {
String[] deviceInfo = line.split(":");
String identifier = deviceInfo[0];
int pinNumber = Integer.parseInt(deviceInfo[1]);
Device device;
switch (identifier) {
case "K":
device = new Switch(identifier, pinNumber);
break;
case "F":
device = new SpeedController(identifier, pinNumber);
break;
case "L":
device = new ContinuousController(identifier, pinNumber);
break;
case "B":
device = new Lamp(identifier, pinNumber, 10.0);
break;
case "R":
device = new Lamp(identifier, pinNumber, 5.0);
break;
case "D":
device = new Fan(identifier, pinNumber, 20.0);
break;
default:
device = null;
break;
}
if (device != null) {
deviceMap.put(identifier + pinNumber, device);
}
}
// 输入连接信息
List<String[]> connections = new ArrayList<>();
while (!(line = scanner.nextLine()).equals("end")) {
String[] connectionInfo = line.substring(1, line.length() - 1).split(" ");
connections.add(connectionInfo);
}
// 构建电路
Map<String, Device> circuitDevices = new HashMap<>();
for (String[] connectionInfo : connections) {
Device previousDevice = null;
for (String devicePin : connectionInfo) {
Device device = deviceMap.get(devicePin);
if (device != null) {
if (previousDevice != null) {
previousDevice.voltageOut = device.voltageIn;
}
circuitDevices.put(devicePin, device);
previousDevice = device;
}
}
}
// 设置输入电压并计算设备输出
double voltageIn = 220.0;
for (Device device : circuitDevices.values()) {
device.voltageIn = voltageIn;
device.calculateVoltageOut();
}
// 输出设备状态
Set<String> identifiers = new TreeSet<>();
for (Device device : circuitDevices.values()) {
identifiers.add(device.identifier);
}
for (String identifier : identifiers) {
for (Device device : circuitDevices.values()) {
if (device.identifier.equals(identifier)) {
if (device instanceof ControlDevice) {
ControlDevice controlDevice = (ControlDevice) device;
System.out.println("@" + device.identifier + device.pinNumber + ":" + (controlDevice.status == 1 ? "closed" : "turned on"));
} else {
ControlledDevice controlledDevice = (ControlledDevice) device;
System.out.println("@" + device.identifier + device.pinNumber + ":" + String.format("%.2f", controlledDevice.voltageOut));
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}