oop-labs-collection/labs/6/Vent.java

155 lines
5.5 KiB
Java

/*
* %W% %E% Dymik739
* Email: dymik739@109.86.70.81
*
* Copyright (C) 2023 FIOT Dev Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* Class that represents a vent installed in the house.
* This device acts as a reactive load.
*
* @author Dymik739
* @since 0.3
*/
public class Vent extends Appliance {
/**
* Power draw limit set by the digital controller, designed by a KPI
* student. Built with the JK-triggers, may malfunction sometimes.
* Exceeding this limit may damage the engine, so it's hard limited.
*/
private float maxPower = 80.0f;
/**
* Current rotor revolutions per minute.
* Can also be defined as angular velocity or kinetic energy
* accumulated in the device.
*/
private float rpm = 0.0f;
/**
* Defines inertia of the rotor.
* Allows the rotor to withstand forces changing it's angular speed.
*/
private final float rotorInertia = 2.0f;
/**
* Target RPM the vent is tuned to maintain.
* Rotor draws full power until it reaches this speed, after that it
* draws only as much power as needed to maintain this speed.
*
* Might be tweaked up to match the exact RPM required, as the target
* RPM is more than actual RPM while running due to additional forces
* and failures in design of the microcontroller (it was also designed
* using JK-triggers as they were the ones that student used in their
* coursework last year).
*/
private final float maxRPM = 2013.0f;
/**
* Constructor for this class.
*
* @param plugged defines if the device is plugged into the power
* network right away
*/
public Vent(boolean plugged) {
super(plugged);
super.setType("Vent");
}
/**
* Method for simulating the device behaviour.
* As was stated before in the class docs, this device has reactive
* properties when it comes to loading the network. This means, it
* doesn't only change it's power usage during operation, but also
* follows some real-world physics laws while running.
*
* First, it uses the power, limited by a device microcontroller,
* to gain angular velocity, measured in RPM. Right before it reaches
* it's target RPM, the power draw falls with the exponential decrement
* law (can be seen from the graph in --vent-monitoring-graph mode).
*
* Once it meets the target RPM, it draws power to only maintain it's
* speed (the power goes to withstand air forces trying to slow the
* fan - and the attached rotor - down).
*
* After the power cuts off, the fan keeps rotating due to it's inertia
* and, when plugged back in, starts getting back up to it's target speed
* according to it's current RPM. The power draw from the network always
* meets the power used to gain angular velocity of the rotor.
*
* Also, as this vent is forcing the air through, the blades experience
* the air drag - it always tries to slow the fan down. As such, the
* air rag force is always calculated and depends of the RPM, which
* is proportional to the force being put on the blades.
*
* And the engineering level is kind of weird: on one hand, they
* engineer a smark device that can manage the RPM and limit the power
* to the rotor, but on the other hand they're unable to deal with
* reverse polarity the rotor generates while running, so they've
* just soldered a single diode on the wire and thus limited
* power down to just 80W! At least, the vent is still functional, so
* I guess it's good enough...
*
* @param seconds delta time to simulate for
*/
public void step(float seconds) {
// electric current usage
if (super.getPowerState()) {
rpm += max(min(((int) (maxRPM - rpm) * rotorInertia), maxPower), 0)
* 10 / rotorInertia * seconds;
}
// air drag (always present)
rpm -= (rpm / 20) / rotorInertia * seconds;
}
/**
* Method for calculating current power consumption of this device.
* Calculations are similar to the step() method above.
*
* @return current power consumption of this device
*/
public float getPowerConsumption() {
if (super.getPowerState()) {
return max(min(rotorInertia*(maxRPM - rpm), maxPower), 0);
} else {
return 0f;
}
}
/**
* Getter for RPM.
*
* @return current RPM
*/
public float getRPM() {
return rpm;
}
/**
* Method for ptinting out this device state in a nice way.
*
* @return string representation of this device state
*/
@Override
public String toString() {
return String.format("Vent(%s, %4.1fW, %4.0f RPM)",
super.getPowerState() ? "on" : "off", getPowerConsumption(),
rpm);
}
}