diff --git a/labs/6/Appliance.java b/labs/6/Appliance.java
index 2a65e61..4026645 100644
--- a/labs/6/Appliance.java
+++ b/labs/6/Appliance.java
@@ -1,33 +1,145 @@
-public class Appliance {
+/*
+ * %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 .
+ */
+
+/**
+ * Class representing a general appliance and containing basic methods
+ * that are used in multiple child classes. Supposed to be extended by
+ * other classes and not to be used as a standalone class.
+ *
+ * @author Dymik739
+ * @since 0.3
+ */
+public class Appliance implements Comparable {
+ /** Indicates if this device is drawing power from the power network. */
private boolean powerConnected;
+ /** Defines the type of this device */
+ private String type;
+
+ /**
+ * Constructor for this class. Should be called only from within
+ * constructors of other classes which inherit this one.
+ *
+ * @param connected defines if the device is connected to the network
+ * at the start
+ */
public Appliance(boolean connected) {
this.powerConnected = connected;
}
+ /**
+ * Getter for checking the power connection.
+ *
+ * @return true if connected and false otherwise
+ */
public boolean getPowerState() {
return powerConnected;
}
+ /**
+ * Getter for the device type variable.
+ *
+ * @return device type string
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Setter for setting the device type string.
+ * Should be used only from the constructors of the classes
+ * which inherit this one!
+ *
+ * @param type type of the device
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Method for connecting power to the device.
+ */
public void plug() {
powerConnected = true;
}
+ /**
+ * Method for disconnecting power from the device.
+ */
public void unplug() {
powerConnected = false;
}
+ /**
+ * Method for getting the smaller value out of two.
+ *
+ * @param v1 first value
+ * @param v2 second value
+ *
+ * @return smaller value of the two given
+ */
public float min(float v1, float v2) {
return v1 <= v2 ? v1 : v2;
}
+ /**
+ * Method for getting the bigger value out of two.
+ *
+ * @param v1 first value
+ * @param v2 second value
+ *
+ * @return bigger value of the two given
+ */
public float max(float v1, float v2) {
return v1 >= v2 ? v1 : v2;
}
+ /**
+ * Dummy method for getting the power consumption of the device.
+ * Should be overridden by the child class!
+ *
+ * @return current power consumption.
+ */
public float getPowerConsumption() {
return 0f;
}
+ /**
+ * Dummy method for performing the simulation.
+ * Should be overridden by the child class!
+ *
+ * @param seconds delta time for the correct simulation step
+ * @param ventRPM air flow created by the vent
+ */
public void step(float seconds, float ventRPM) {}
+
+ /**
+ * Method for comparing this appliance's power consumption to another
+ * one. Part os the Comparable implementation.
+ *
+ * @param o another appliance to compare to
+ *
+ * @return difference between power consumption values
+ */
+ @Override
+ public int compareTo(Appliance o) {
+ return (int) (getPowerConsumption() - o.getPowerConsumption());
+ }
}
diff --git a/labs/6/Dishwasher.java b/labs/6/Dishwasher.java
index 838005f..ed282c7 100644
--- a/labs/6/Dishwasher.java
+++ b/labs/6/Dishwasher.java
@@ -1,13 +1,58 @@
+/*
+ * %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 .
+ */
+
+/**
+ * Class which represents the behaviour of a dishwasher.
+ *
+ * @author Dymik739
+ * @since 0.3
+ */
public class Dishwasher extends Appliance {
- private float basePower = 160.0f;
+ /** Defines power usage at different stages of washing dishes. */
private float[] powerStates = {400f, 60f, 130f, 350f};
+
+ /** Shows how much time should pass before switching to the next stage */
private float nextPowerStateIn = 20f;
+
+ /** Shows current stage the dishwasher is performing, -1 for none */
private int currentState = -1;
+ /**
+ * Constructor for this class.
+ *
+ * @param plugged sets the starting power state of this device
+ */
public Dishwasher(boolean plugged) {
super(plugged);
+ super.setType("Dishwasher");
}
+ /**
+ * Method for simulating the devices' behaviour.
+ * Once started, it goes through every stage until it finishes washing
+ * the dishes (every stage has it's own power usage level. After that,
+ * it resets the device and turns it off automatically.
+ *
+ * @param seconds delta time to simulate for
+ * @param ventRPM air flow created by the vent
+ */
public void step(float seconds, float ventRPM) {
if (!super.getPowerState()) {
return;
@@ -24,7 +69,11 @@ public class Dishwasher extends Appliance {
unplug();
}
}
-
+
+ /**
+ * Overridden method for turning on this device.
+ * It automatically sets it to the correct stage and delay.
+ */
@Override
public void plug() {
super.plug();
@@ -33,6 +82,10 @@ public class Dishwasher extends Appliance {
nextPowerStateIn = 20f;
}
+ /**
+ * Overridden method for turning this device off.
+ * It automatically resets the current washing stage to -1.
+ */
@Override
public void unplug() {
super.unplug();
@@ -40,6 +93,12 @@ public class Dishwasher extends Appliance {
currentState = -1;
}
+ /**
+ * Method for calculating the power consumption of this device.
+ * Power usage depends on the current washing stage.
+ *
+ * @return float showing current power consumption
+ */
public float getPowerConsumption() {
if (super.getPowerState()) {
return powerStates[currentState];
@@ -47,4 +106,18 @@ public class Dishwasher extends Appliance {
return 0f;
}
}
+
+ /**
+ * Method for printing this devices' object in a nice way.
+ *
+ * @return String containing text description of this devices' state
+ */
+ @Override
+ public String toString() {
+ return String.format("Dishwasher(%s, %4.1fW, %2.1fs)",
+ super.getPowerState() ? "on" : "off", getPowerConsumption(),
+ super.getPowerState()
+ ? (3 - currentState) * 20 + nextPowerStateIn
+ : 0f);
+ }
}
diff --git a/labs/6/Main.java b/labs/6/Main.java
index d347ef1..eae546a 100644
--- a/labs/6/Main.java
+++ b/labs/6/Main.java
@@ -1,8 +1,82 @@
-import java.util.concurrent.TimeUnit;
+/*
+ * %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 .
+ */
+import java.util.Arrays;
+
+/**
+ * Main class that controls all the devices and regulates vent power.
+ *
+ * @author Dymik739
+ * @since 0.3
+ */
public class Main {
+ /**
+ * Defines the ServerRack power consumption at which the vent
+ * power is enabled.
+ */
+ private static final float VENT_START_POWER = 240f;
+
+ /**
+ * Defines the ServerRack power consumption at which the vent
+ * power is disabled.
+ */
+ private static final float VENT_STOP_POWER = 185f;
+
+ /** Defines magic number for real-time TTY output mode */
+ private static final int TTY_LIVE_MONITORING_MODE = 0;
+
+ /**
+ * Defines magic number for raw graph output mode for current
+ * power consumption and vent RPM
+ */
+ private static final int POWER_RPM_GRAPH_MODE = 1;
+
+ /** Defines magic number for raw graph output mode for total consumption */
+ private static final int TOTAL_CONSUMPTION_GRAPH_MODE = 2;
+
+ /**
+ * Defines magic number for raw graph output mode for vent rpm and
+ * power consumption relation
+ */
+ private static final int VENT_POWER_RPM_GRAPH_MODE = 3;
+
+ /** Defines the amount of simulation samples to get per every second */
+ private static final int TICKS_PER_SECOND = 720;
+
+ /** Defines the time simulation will run for (in seconds) */
+ private static final int SIMULATION_TIME = 240;
+
+ /**
+ * Main method for containing the devices, performing all
+ * checks and plugging the devices in and out.
+ *
+ * @param args accepts CLI arguments.
+ */
public static void main(String[] args) {
- Vent vent = new Vent(true);
+ float ventConsumed = 0f;
+ float totalPowerConsumed = 0f;
+
+ int outputMode = parseMode(args);
+ int liveStatsOutputDelay = parseOutputDelay(args);
+
+ Vent vent = new Vent(false); // defining vent as a special appliance
Appliance[] devices = {
new ServerRack(false),
@@ -11,53 +85,174 @@ public class Main {
new Dishwasher(false)
};
- devices[0].plug();
- devices[2].plug();
+ devices[2].plug(); // turning on RPI right away
+ // (RPI stands for Raspberry Pi)
- int i = 0;
- float ventConsumed = 0f;
- float totalPowerConsumed = 0f;
- //for (int i = 0; i < 180*10; i++) {
- while (true) {
- step(vent, devices, 0.1f);
- ventConsumed += vent.getPowerConsumption() * 0.1;
- totalPowerConsumed += getTotalPowerConsumption(vent, devices) * 0.1 / 3600;
- //System.out.print(String.format("Time: %02.1f; ", (float) i/10)
- System.out.print("Time: " + floatFormat((float)i/10, 2, 1) + "; "
- + getStats(vent, devices) + "; vent avg = "
- + floatFormat(ventConsumed*10/i, 3, 1)
- + "W; total = "
- + floatFormat(totalPowerConsumed, 3, 3) + "W\r");
- if (devices[0].getPowerConsumption() > 205) {
- vent.plug();
+ // letting the simulation run
+ for (int i = 1; i <= SIMULATION_TIME*TICKS_PER_SECOND; i++) {
+ step(vent, devices, (float) 1/TICKS_PER_SECOND); // stepping time
+
+ // performing accounting
+ ventConsumed += vent.getPowerConsumption() / TICKS_PER_SECOND;
+ totalPowerConsumed += getTotalPowerConsumption(vent, devices)
+ / TICKS_PER_SECOND / 3600;
+
+ // outputting the data in the desired format
+ if (outputMode == TTY_LIVE_MONITORING_MODE) {
+ System.out.print("Time: " + floatFormat((float)i/TICKS_PER_SECOND, 2, 2)
+ + "; " + getStats(vent, devices) + "; vent avg = "
+ + floatFormat(ventConsumed/TICKS_PER_SECOND/i, 4, 1)
+ + "W; total = "
+ + floatFormat(totalPowerConsumed, 4, 3) + "W\r");
+ } else if (outputMode == POWER_RPM_GRAPH_MODE) {
+ System.out.println(getTotalPowerConsumption(vent, devices)
+ + " " + vent.getRPM()/10);
+ } else if (outputMode == TOTAL_CONSUMPTION_GRAPH_MODE) {
+ System.out.println(totalPowerConsumed);
+ } else if (outputMode == VENT_POWER_RPM_GRAPH_MODE) {
+ System.out.println(vent.getRPM()/10 + " "
+ + vent.getPowerConsumption());
}
- if (devices[0].getPowerConsumption() < 190) {
- vent.unplug();
+ adjustVentPower(devices, vent);
+
+ managePower(i, devices);
+
+ if ((outputMode == TTY_LIVE_MONITORING_MODE)
+ && (liveStatsOutputDelay != 0)) {
+ try {
+ Thread.sleep(liveStatsOutputDelay);
+ } catch (Exception e) {
+ System.exit(0);
+ }
+ }
+ }
+
+ if (outputMode == TTY_LIVE_MONITORING_MODE) {
+ Appliance[] totalDevices = new Appliance[devices.length + 1];
+
+ for (int i = 0; i < devices.length; i++) {
+ totalDevices[i] = devices[i];
}
- if (i == 150) {
- devices[1].plug();
- } else if (i == 300) {
- devices[0].unplug();
- } else if (i == 400) {
- devices[3].plug();
- } else if (i == 700) {
- devices[0].plug();
- }
+ totalDevices[devices.length] = vent;
- try {
- //TimeUnit.SECONDS.sleep(1);
- Thread.sleep(2);
- } catch (Exception e) {
- System.exit(0);
- }
+ System.out.println("\nCurrently devices draw "
+ + floatFormat(getTotalPowerConsumption(totalDevices), 4, 2)
+ + "W from the power lines.");
- i++;
+ Arrays.sort(totalDevices);
+ printAppliances(totalDevices);
}
}
+ /**
+ * Method which decides on how to manage the vent power supply.
+ * It looks at power consumption of every ServerRack device
+ * and:
+ * - turns the vent on if ANY of them meet the VENT_START_POWER threshold
+ * - turns the vent off if ALL of them meet the VENT_STOP_POWER threshold
+ *
+ * @param devices list of devices to look at.
+ * @param vent vent to manage power for.
+ */
+ public static void adjustVentPower(Appliance[] devices, Vent vent) {
+ for (Appliance i : devices) {
+ if ("ServerRack".equals(i.getType())
+ && (i.getPowerConsumption() > VENT_START_POWER)) {
+ vent.plug();
+ return;
+ }
+ }
+
+ for (Appliance i : devices) {
+ if ("ServerRack".equals(i.getType())
+ && !(i.getPowerConsumption() < VENT_STOP_POWER)) {
+ return;
+ }
+ }
+
+ vent.unplug();
+ }
+
+ /**
+ * Method that plugs in and out the devices in a predefined manner.
+ *
+ * @param i current simulation time.
+ * @param devices device list to control.
+ */
+ public static void managePower(int i, Appliance[] devices) {
+ if (i == 25 * TICKS_PER_SECOND) {
+ devices[1].plug();
+ } else if (i == 35 * TICKS_PER_SECOND) {
+ devices[0].plug();
+ } else if (i == 50 * TICKS_PER_SECOND) {
+ devices[0].unplug();
+ } else if (i == 60 * TICKS_PER_SECOND) {
+ devices[3].plug();
+ } else if (i == 130 * TICKS_PER_SECOND) {
+ devices[0].plug();
+ }
+ }
+
+ /**
+ * Method for printing out a gives array of appliances.
+ *
+ * @param devices appliance array to print out.
+ */
+ public static void printAppliances(Appliance[] devices) {
+ for (Appliance i : devices) {
+ System.out.println(i);
+ }
+ }
+
+ /**
+ * Method for extracting output mode setting set from CLI.
+ *
+ * @param args CLI args array to use.
+ *
+ * @return int representing requested mode.
+ */
+ public static int parseMode(String[] args) {
+ for (String i : args) {
+ if ("--power-rpm-graph".equals(i)) {
+ return POWER_RPM_GRAPH_MODE;
+ } else if ("--total-consumption-graph".equals(i)) {
+ return TOTAL_CONSUMPTION_GRAPH_MODE;
+ } else if ("--vent-monitoring-graph".equals(i)) {
+ return VENT_POWER_RPM_GRAPH_MODE;
+ }
+ }
+
+ return TTY_LIVE_MONITORING_MODE;
+ }
+
+ /**
+ * Method for extracting output delay setting set from CLI.
+ *
+ * @param args CLI args array to use.
+ *
+ * @return delay in miliseconds.
+ */
+ public static int parseOutputDelay(String[] args) {
+ for (int i = 0; i < args.length; i++) {
+ if ("--output-delay".equals(args[i])) {
+ return Integer.parseInt(args[i+1]);
+ }
+ }
+
+ return 90;
+ }
+
+ /**
+ * Method for performing the simulation. Runs the respective .step()
+ * methods on all of the given appliances.
+ *
+ * @param vent vent object to process
+ * @param devices devices array to process
+ * @param seconds delta time to move forward.
+ */
public static void step(Vent vent, Appliance[] devices, float seconds) {
vent.step(seconds);
for (Appliance i : devices) {
@@ -65,6 +260,15 @@ public class Main {
}
}
+ /**
+ * Method for collecting the overall usage statistics to make it
+ * easy to output status line during TTY mode execution.
+ *
+ * @param vent vent object to track
+ * @param devices devices array to track
+ *
+ * @return String containing current stats for all the devices
+ */
public static String getStats(Vent vent, Appliance[] devices) {
float[] powerConsumption = new float[devices.length];
float totalPowerConsumption = 0;
@@ -77,25 +281,29 @@ public class Main {
String result = "PPD: ";
for (float i : powerConsumption) {
- //result += String.format("%03.1fW ", i);
result += String.format(floatFormat(i, 3, 1) + "W ");
-
}
float powerLinesDraw = totalPowerConsumption
+ vent.getPowerConsumption();
- //result += String.format("; Vent: %03.1fW, %05.0f RPM; Total power: %04.1fW",
result += "; Vent: " + floatFormat(vent.getPowerConsumption(), 3, 1)
+ "W, " + floatFormat(vent.getRPM(), 5, 0)
+ " RPM; Total power: " + floatFormat(powerLinesDraw, 4, 1)
+ "W";
- //vent.getPowerConsumption(), vent.getRPM(),
- //totalPowerConsumption + vent.getPowerConsumption());
return result;
}
+ /**
+ * Overloaded method for calculating the total power consumption
+ * (devices + the vent).
+ *
+ * @param vent vent to account
+ * @param devices array of devices to account
+ *
+ * @return sum of all the .getPowerConsumption() returned from devices
+ */
public static float getTotalPowerConsumption(Vent vent,
Appliance[] devices) {
float result = vent.getPowerConsumption();
@@ -107,6 +315,34 @@ public class Main {
return result;
}
+ /**
+ * Overloaded method for calculating the total power consumption
+ * (devices only).
+ *
+ * @param devices array of devices to account
+ *
+ * @return sum of all the .getPowerConsumption() returned from devices
+ */
+ public static float getTotalPowerConsumption(Appliance[] devices) {
+ float result = 0;
+
+ for (Appliance a : devices) {
+ result += a.getPowerConsumption();
+ }
+
+ return result;
+ }
+
+ /**
+ * Custom method which adds the support for arbitrary formatting of float
+ * numbers.
+ *
+ * @param num value to format
+ * @param leading amount of digits before period to print
+ * @param trailing amount of digits after perio to print
+ *
+ * @return String with formatted result
+ */
public static String floatFormat(float num, int leading, int trailing) {
String newNum = String.format("%0" + leading + "." + trailing + "f", num);
diff --git a/labs/6/RPI.java b/labs/6/RPI.java
index 7187d4c..40a698f 100644
--- a/labs/6/RPI.java
+++ b/labs/6/RPI.java
@@ -1,11 +1,59 @@
+/*
+ * %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 .
+ */
+
+/**
+ * Class which represents the RPI (Raspberry Pi) microcomputer.
+ *
+ * @author Dymik739
+ * @since 0.3
+ */
public class RPI extends Appliance {
+ /** Contains current power draw from the power supply. */
private float power = 15.0f;
+
+ /**
+ * Defines the delay after the startup when the power usage starts to drop
+ * to it's lowest value.
+ */
private float postBootDecreaseIn = 10.0f;
+ /**
+ * Constructor for this class.
+ *
+ * @param plugged sets the power state on the beginning
+ */
public RPI(boolean plugged) {
super(plugged);
+ super.setType("RPI");
}
+ /**
+ * Method which is used to simulate the device's behaviour.
+ * The device draws it's maximum power for postBootDecreaseIn
+ * seconds and gradually drops to it's lowest level, after that
+ * it always stays on the lowest power usage level until a
+ * reboot happens.
+ *
+ * @param seconds delta time to simulate for
+ * @param ventRPM air flow generated by the vent
+ */
public void step(float seconds, float ventRPM) {
postBootDecreaseIn -= seconds;
@@ -18,6 +66,24 @@ public class RPI extends Appliance {
}
}
+ /**
+ * Custom method for unplugging the device.
+ * Adds the automatic resetting to the default values right after
+ * turning the device off.
+ */
+ @Override
+ public void unplug() {
+ super.unplug();
+
+ power = 15f;
+ postBootDecreaseIn = 10f;
+ }
+
+ /**
+ * Method for getting the power draw of this device.
+ *
+ * @return current power consumption
+ */
public float getPowerConsumption() {
if (super.getPowerState()) {
return power;
@@ -25,4 +91,15 @@ public class RPI extends Appliance {
return 0f;
}
}
+
+ /**
+ * Method for printing this devices' object in a nice way.
+ *
+ * @return String containing text description of this devices' state
+ */
+ @Override
+ public String toString() {
+ return String.format("RPI(%s, %4.1fW)",
+ super.getPowerState() ? "on" : "off", getPowerConsumption());
+ }
}
diff --git a/labs/6/ServerRack.java b/labs/6/ServerRack.java
index d1cc71e..8a931ed 100644
--- a/labs/6/ServerRack.java
+++ b/labs/6/ServerRack.java
@@ -1,28 +1,124 @@
+/*
+ * %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 .
+ */
+
+/**
+ * Class which represents a server rack.
+ *
+ * @author Dymik739
+ * @since 0.3
+ */
public class ServerRack extends Appliance {
- private String type = "ServerRack";
+ /** Defines power used by the rack at lowest temperature. */
private float basePower = 160.0f;
+
+ /** Defines power limit for this rack */
private float maxPower = 350.0f;
+
+ /** Contains the inner temperature of this rack */
private float temperature = 20f;
+ /** Defines current usage of this device */
+ private float currentLoad = 0.2f;
+
+ /** Predicts the future change of the load */
+ private float loadVector = +1f;
+
+ /**
+ * Constructor for this class.
+ *
+ * @param plugged defines if the device is plugged in at the start
+ */
public ServerRack(boolean plugged) {
super(plugged);
+ super.setType("ServerRack");
}
+ /**
+ * Method for simulating this device behaviour.
+ * This rack processes video segments for the streaming platform and
+ * serves them to the public in different qualities. Every device requires
+ * the fragments to be encoded in it's respective format in order to play
+ * the stream. As such, the load rises when new fragment arrives and falls
+ * as it converts it into all the formats required.
+ *
+ * Temperature depends on many factors. Firstly, the device heats up while
+ * performing tasks and the rate is affected by:
+ * - current temperature (hotter = more power drawn);
+ * - load on the CPU (more load = more heat);
+ *
+ * Of course, the temperature can be reduced using the vent installed in
+ * the house. The rate of reduction is calculated using:
+ * - current temperature (the bigger the difference compared to the outside
+ * temperature, the larger impact the vent has on it);
+ * - air flow, created by the vent (the faster the air moves, the more
+ * heat it takes away from the system);
+ *
+ * This device can also cool itself down while standing still as the heat
+ * slowly transfers to the air even when the vent doesn't force it.
+ * The rate is calculated by only the temperature difference between inner
+ * and outer temperatures.
+ *
+ * @param seconds delta time to simulate for
+ * @param ventRPM air flow created by the vent
+ */
public void step(float seconds, float ventRPM) {
- if (super.getPowerState()) {
- temperature += min(basePower + (temperature - 20f) * 1.8f, maxPower)
- * seconds * 0.024f;
+ currentLoad += loadVector/10 * seconds;
+
+ if (currentLoad >= 1) {
+ loadVector = -1f;
+ } else if (currentLoad <= 0.2) {
+ loadVector = +1f;
}
- temperature -= (temperature - 20f) * ventRPM*0.0003f * seconds;
- temperature -= 0.006f * (temperature - 20f) * seconds;
+ if (super.getPowerState()) {
+ temperature += min(basePower + (temperature - 20f) * 1.8f
+ * max(min(currentLoad, 1), 0), maxPower) * seconds
+ * 0.024f;
+ }
+
+ temperature -= (temperature - 20f) * ventRPM * 0.00013f * seconds;
+ temperature -= 0.002f * (temperature - 20f) * seconds;
}
+ /**
+ * Method which calculates power consumption if this device.
+ *
+ * @return power consumption of this device
+ */
public float getPowerConsumption() {
if (super.getPowerState()) {
- return min(basePower + (temperature - 20f) * 1.8f, maxPower);
+ return min(basePower + (temperature - 20f) * 1.8f * max(min(currentLoad, 1), 0), maxPower);
} else {
return 0f;
}
}
+
+ /**
+ * Overridden toString() method for printing the state of this device.
+ *
+ * @return String representing current state of this device
+ */
+ @Override
+ public String toString() {
+ return String.format("ServerRack(%s, %4.1fW, %3.1f℃C, %3.1f%%)",
+ super.getPowerState() ? "on" : "off", getPowerConsumption(),
+ temperature, currentLoad * 100);
+ }
}
diff --git a/labs/6/Vent.java b/labs/6/Vent.java
index df62f3b..64336af 100644
--- a/labs/6/Vent.java
+++ b/labs/6/Vent.java
@@ -1,13 +1,111 @@
-public class Vent extends Appliance {
- private float maxPower = 90.0f;
- private float rpm = 0.0f;
- private final float rotorInertia = 7.0f;
- private final float maxRPM = 6500.0f;
+/*
+ * %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 .
+ */
+/**
+ * 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 possible
+ * 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()) {
@@ -16,9 +114,15 @@ public class Vent extends Appliance {
}
// air drag (always present)
- rpm -= (rpm / 200) / rotorInertia;
+ 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);
@@ -27,7 +131,24 @@ public class Vent extends Appliance {
}
}
+ /**
+ * 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);
+ }
}