Beware the night! Beware the night before the dawn!

This commit is contained in:
2025-04-06 23:38:58 +03:00
parent 88dc5c600e
commit b2482400a7
5 changed files with 108 additions and 247 deletions

View File

@ -36,6 +36,7 @@ public class App {
.register("remove_key", new RemoveKeyCommand())
.register("history", new HistoryCommand())
.register("insert", new InsertCommand())
.register("update", new UpdateCommand())
.build();
try {

View File

@ -3,180 +3,76 @@ package itmo.lab5.cli.commands;
import java.util.Date;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Arrays;
import itmo.lab5.cli.helpers.*;
import itmo.lab5.cli.CommandContext;
import itmo.lab5.interfaces.Command;
import itmo.lab5.models.enums.*;
import itmo.lab5.models.*;
public class InsertCommand implements Command {
private final Scanner scanner = new Scanner(System.in);
private final ReaderUtil inputReader = new ReaderUtil(scanner);
@Override
public String execute(String[] args, CommandContext context) {
if (args.length < 1 || !"null".equals(args[0])) {
if (args.length < 1) {
return "Usage: insert null {element}";
}
Scanner scanner = new Scanner(System.in);
Date creationDate = new Date();
String name = inputReader.promptString("- Enter name: ", false, null);
System.out.print("- Enter name: ");
String name = readNonEmptyString(scanner);
System.out.println("- Coordinates ");
int x = inputReader.promptNumber("\t Enter x: ", Integer.MIN_VALUE, Integer.MAX_VALUE, Integer::parseInt, null);
Long y = inputReader.promptNumber("\t Enter y: ", Long.MIN_VALUE, Long.MAX_VALUE, Long::parseLong, null);
var coordinates = new Coordinates(x, y);
System.out.println("- Coordinates:");
System.out.print("Enter x (int): ");
int x = readInt(scanner);
System.out.print("Enter y (Long): ");
Long y = readLongNotNull(scanner);
Coordinates coordinates = new Coordinates(x, y);
System.out.print("Enter square (Double > 0, <= 626): ");
Double area = readDoubleInRange(scanner, 0.0, 626.0);
System.out.print("Enter room count (int > 0): ");
int numberOfRooms = readIntMin(scanner, 1);
Double area = inputReader.promptNumber("\t Enter square: ", 0.0, 626.0, Double::parseDouble, null);
int numberOfRooms = inputReader.promptNumber("\t Enter rooms count: ", 1, Integer.MAX_VALUE, Integer::parseInt,
null);
System.out.println("- Furnish");
Furnish furnish = readEnum(scanner, Furnish.class);
Furnish furnish = inputReader.promptEnum("\t Enter furnish type: ", Furnish.class, null);
System.out.println("- View");
View view = readEnumNullable(scanner, View.class);
View view = inputReader.promptEnumNullable("\t Enter view type: ", View.class, null);
System.out.println("- Transport");
Transport transport = readEnum(scanner, Transport.class);
Transport transport = inputReader.promptEnum("\t Enter transport type: ", Transport.class, null);
System.out.println("- House");
System.out.print("Enter house's name: ");
System.out.print("\t Enter house name: ");
String houseName = scanner.nextLine().trim();
String houseName = scanner.nextLine();
House house = null;
if (!houseName.isBlank()) {
System.out.print("Enter house age (1-959): ");
int year = readIntInRange(scanner, 1, 959);
System.out.print("Enter house's floors count (1-77): ");
long numberOfFloors = readLongInRange(scanner, 1, 77);
house = new House(houseName, year, numberOfFloors);
if (!houseName.isEmpty()) {
int year = inputReader.promptNumber("\t Enter house age: ", 1, 959, Integer::parseInt, null);
long floors = inputReader.promptNumber("\t Enter house floors count: ", 1L, 77L, Long::parseLong, null);
house = new House(houseName, year, floors);
}
try {
HashMap<Integer, Flat> collection = (HashMap<Integer, Flat>) context.get("collection");
var newID = collection.size() + 1;
int newID = collection.size() + 1;
Flat flat = new Flat(
newID,
name,
coordinates,
creationDate,
area,
numberOfRooms,
furnish,
view,
transport,
house);
Flat flat = new Flat(newID, name, coordinates, creationDate, area,
numberOfRooms, furnish, view, transport, house);
collection.put(newID, flat);
} catch (ClassCastException e) {
return "There's an error while trying to add new element. Collection im some kind of broken.";
return "There's an error while trying to add new element. Collection is broken.";
}
return "New flat was successfully inserted!";
}
private String readNonEmptyString(Scanner scanner) {
while (true) {
String line = scanner.nextLine().trim();
if (!line.isEmpty())
return line;
System.out.print("Value can't be empty. Retry input: ");
}
}
private int readInt(Scanner scanner) {
while (true) {
try {
return Integer.parseInt(scanner.nextLine().trim());
} catch (NumberFormatException e) {
System.out.print("Please, enter integer: ");
}
}
}
private Long readLongNotNull(Scanner scanner) {
while (true) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
try {
return Long.parseLong(line);
} catch (NumberFormatException e) {
System.out.print("Please, enter Long: ");
}
} else {
System.out.print("Field can't be null. Retry: ");
}
}
}
private int readIntMin(Scanner scanner, int min) {
while (true) {
int value = readInt(scanner);
if (value >= min)
return value;
System.out.print("Number must be bigger than " + min + ". Retry: ");
}
}
private int readIntInRange(Scanner scanner, int min, int max) {
while (true) {
int value = readInt(scanner);
if (value >= min && value <= max)
return value;
System.out.print("Enter number in range [" + min + " ... " + max + "] ");
}
}
private long readLongInRange(Scanner scanner, long min, long max) {
while (true) {
try {
long value = Long.parseLong(scanner.nextLine().trim());
if (value >= min && value <= max)
return value;
System.out.print("Enter number in range [" + min + " ... " + max + "]");
} catch (NumberFormatException e) {
System.out.print("Enter Long number: ");
}
}
}
private Double readDoubleInRange(Scanner scanner, double min, double max) {
while (true) {
try {
Double value = Double.parseDouble(scanner.nextLine().trim());
if (value > min && value <= max)
return value;
System.out.print("Enter float in range [" + (min + 0.0001) + " ... " + max + "] ");
} catch (NumberFormatException e) {
System.out.print("Enter float number: ");
}
}
}
private <T extends Enum<T>> T readEnum(Scanner scanner, Class<T> enumClass) {
System.out.println("Allowed values: " + Arrays.toString(enumClass.getEnumConstants()));
while (true) {
String input = scanner.nextLine().trim();
try {
return Enum.valueOf(enumClass, input);
} catch (IllegalArgumentException e) {
System.out.print("You must enter one of values from the previous list: ");
}
}
}
private <T extends Enum<T>> T readEnumNullable(Scanner scanner, Class<T> enumClass) {
System.out
.println("Allowed values (or empty string): " + Arrays.toString(enumClass.getEnumConstants()));
while (true) {
String input = scanner.nextLine().trim();
if (input.isEmpty())
return null;
try {
return Enum.valueOf(enumClass, input);
} catch (IllegalArgumentException e) {
System.out.print("You must enter one of values from the previous list: ");
}
}
}
}

View File

@ -1,135 +1,97 @@
package itmo.lab5.cli.commands;
import itmo.lab5.models.*;
import itmo.lab5.models.enums.*;
import itmo.lab5.interfaces.Command;
import itmo.lab5.cli.CommandContext;
import java.util.*;
import itmo.lab5.cli.helpers.*;
import itmo.lab5.cli.CommandContext;
import itmo.lab5.interfaces.Command;
import itmo.lab5.models.enums.*;
import itmo.lab5.models.*;
public class UpdateCommand implements Command {
private final Scanner scanner = new Scanner(System.in);
private final ReaderUtil inputReader = new ReaderUtil(scanner);
@Override
public String execute(String[] args, CommandContext context) {
if (args.length < 1)
if (args.length < 1) {
return "Usage: update id {element}";
}
Map<Integer, Flat> collection = null;
int idToUpdate;
try {
idToUpdate = Integer.parseInt(args[1]);
idToUpdate = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
return "Invalid ID!";
return "Invalid ID format.";
}
try {
collection = (Map<Integer, Flat>) context.get("collection");
} catch (ClassCastException e) {
return "There's an error while trying to parse collection";
}
Map<Integer, Flat> collection = (Map<Integer, Flat>) context.get("collection");
if (!collection.containsKey(idToUpdate)) {
return "No flat with such ID: " + idToUpdate;
return "No flat with ID: " + idToUpdate;
}
Flat oldFlat = collection.get(idToUpdate);
Flat updatedFlat = readFlat(idToUpdate, oldFlat);
collection.put(idToUpdate, updatedFlat);
return "Flat with ID " + idToUpdate + " updated.";
}
private Flat readFlat(int id, Flat oldFlat) {
System.out.println("- New information for Flat #" + id);
String name = readString("Enter new name: ", false, oldFlat.getName());
Coordinates coordinates = readCoordinates(oldFlat.getCoordinates());
Date creationDate = new Date();
Double area = readNumber("Enter new square: ", 0.0, 626.0, Double::parseDouble, oldFlat.getArea());
int rooms = readNumber("Enter new rooms count: ", 1, Integer.MAX_VALUE, Integer::parseInt,
System.out.println("Updating flat with ID: " + idToUpdate);
String name = inputReader.promptString("- Enter name:", false, oldFlat.getName());
System.out.println("- Coordinates:");
int x = inputReader.promptNumber("\t Enter x:", Integer.MIN_VALUE, Integer.MAX_VALUE, Integer::parseInt,
oldFlat.getCoordinates().getX());
Long y = inputReader.promptNumber("\t Enter y:", Long.MIN_VALUE, Long.MAX_VALUE, Long::parseLong,
oldFlat.getCoordinates().getY());
Coordinates coordinates = new Coordinates(x, y);
Double area = inputReader.promptNumber("\t Enter square:", 0.0, 626.0, Double::parseDouble, oldFlat.getArea());
int rooms = inputReader.promptNumber("\t Enter rooms count:", 1, Integer.MAX_VALUE, Integer::parseInt,
oldFlat.getNumberOfRooms());
Furnish furnish = readEnum("Enter new furnish: ", Furnish.class, oldFlat.getFurnish());
View view = readEnumNullable("Enter new view (or empty string)", View.class, oldFlat.getView());
Transport transport = readEnum("Enter new transport: ", Transport.class, oldFlat.getTransport());
House house = readHouse(oldFlat.getHouse());
return new Flat(id, name, coordinates, creationDate, area, rooms, furnish, view, transport, house);
System.out.println("- Furnish:");
Furnish furnish = inputReader.promptEnum("\t Enter furnish type:", Furnish.class, oldFlat.getFurnish());
System.out.println("- View:");
View view = inputReader.promptEnumNullable("\t Enter view type:", View.class, oldFlat.getView());
System.out.println("- Transport:");
Transport transport = inputReader.promptEnum("\t Enter transport type:", Transport.class, oldFlat.getTransport());
System.out.println("- House:");
System.out.print("\t Enter house name: ");
String houseName = scanner.nextLine().trim();
House house = oldFlat.getHouse();
if (!houseName.isEmpty()) {
int year = inputReader.promptNumber("\t Enter house age: ", 1, 959, Integer::parseInt,
(house != null ? house.getYear() : 1));
long floors = inputReader.promptNumber("\t Enter house floors count: ", 1L, 77L, Long::parseLong,
(house != null ? house.getNumberOfFloors() : 1L));
house = new House(houseName, year, floors);
}
private Coordinates readCoordinates(Coordinates oldCoords) {
int x = readNumber("Введите координату X", Integer.MIN_VALUE, Integer.MAX_VALUE, Integer::parseInt,
oldCoords.getX());
Long y = readNumber("Введите координату Y", Long.MIN_VALUE, Long.MAX_VALUE, Long::parseLong, oldCoords.getY());
return new Coordinates(x, y);
}
Date creationDate = new Date();
private House readHouse(House oldHouse) {
System.out.print("Введите название дома (" + (oldHouse != null ? oldHouse.getName() : "null")
+ ", пусто — не изменять, полностью пусто — null): ");
String name = scanner.nextLine().trim();
if (name.isEmpty())
return oldHouse;
if (name.equals("null"))
return null;
Flat updatedFlat = new Flat(
idToUpdate,
name,
coordinates,
creationDate,
area,
rooms,
furnish,
view,
transport,
house);
int year = readNumber("Введите год постройки", 1, 959, Integer::parseInt, oldHouse.getYear());
long floors = readNumber("Введите количество этажей", 1L, 77L, Long::parseLong, oldHouse.getNumberOfFloors());
return new House(name, year, floors);
}
private String readString(String message, boolean allowEmpty, String oldValue) {
while (true) {
System.out.print(message + " (" + oldValue + "): ");
String input = scanner.nextLine().trim();
if (input.isEmpty())
return oldValue;
if (!input.isEmpty() || allowEmpty)
return input;
System.out.println("Строка не может быть пустой.");
}
}
private <T extends Enum<T>> T readEnum(String message, Class<T> enumClass, T oldValue) {
while (true) {
System.out.println(message + " (" + oldValue + ", варианты: "
+ String.join(", ", Arrays.stream(enumClass.getEnumConstants()).map(Enum::name).toList()) + "):");
String input = scanner.nextLine().trim();
if (input.isEmpty())
return oldValue;
try {
return Enum.valueOf(enumClass, input);
} catch (IllegalArgumentException e) {
System.out.println("Неверное значение. Повторите ввод.");
}
}
}
private <T extends Enum<T>> T readEnumNullable(String message, Class<T> enumClass, T oldValue) {
while (true) {
System.out.println(message + " (" + (oldValue != null ? oldValue : "null") + ", варианты: "
+ String.join(", ", Arrays.stream(enumClass.getEnumConstants()).map(Enum::name).toList()) + "):");
String input = scanner.nextLine().trim();
if (input.isEmpty())
return oldValue;
try {
return Enum.valueOf(enumClass, input);
} catch (IllegalArgumentException e) {
System.out.println("Неверное значение. Повторите ввод.");
}
}
}
private <T extends Comparable<T>> T readNumber(String message, T min, T max, Parser<T> parser, T oldValue) {
while (true) {
System.out.print(message + " (" + oldValue + "): ");
String input = scanner.nextLine().trim();
if (input.isEmpty())
return oldValue;
try {
T value = parser.parse(input);
if (value.compareTo(min) >= 0 && value.compareTo(max) <= 0)
return value;
} catch (Exception ignored) {
}
System.out.println("Некорректный ввод. Повторите попытку.");
}
}
interface Parser<T> {
T parse(String input) throws Exception;
collection.put(idToUpdate, updatedFlat);
return "Flat with ID " + idToUpdate + " was successfully updated.";
}
}

View File

@ -13,7 +13,7 @@ public class ReaderUtil {
public String promptString(String message, boolean allowEmpty, String oldValue) {
while (true) {
System.out.print(message);
if (!oldValue.isEmpty() || oldValue != null)
if (oldValue != null)
System.out.print(" (" + oldValue + "): ");
String input = scanner.nextLine().trim();
@ -30,9 +30,9 @@ public class ReaderUtil {
public <T extends Enum<T>> T promptEnum(String message, Class<T> enumClass, T oldValue) {
while (true) {
if (oldValue != null)
System.out.print("Now it's: " + oldValue + ". ");
System.out.println("Now it's: " + oldValue + ". ");
System.out.println(
System.out.print(
message + "(options: " +
String.join(", ", Arrays.stream(enumClass.getEnumConstants()).map(Enum::name).toList()) +
"): ");
@ -53,9 +53,9 @@ public class ReaderUtil {
public <T extends Enum<T>> T promptEnumNullable(String message, Class<T> enumClass, T oldValue) {
while (true) {
if (oldValue != null)
System.out.print("Now it's: " + oldValue + ". ");
System.out.println("Now it's: " + oldValue + ". ");
System.out.println(
System.out.print(
message + "(options: " +
String.join(", ", Arrays.stream(enumClass.getEnumConstants()).map(Enum::name).toList()) +
"): ");
@ -77,7 +77,9 @@ public class ReaderUtil {
System.out.print(message + " (" + oldValue + "): ");
String input = scanner.nextLine().trim();
if (input.isEmpty())
if (oldValue != null)
return oldValue;
try {
T value = parser.parse(input);
if (value.compareTo(min) >= 0 && value.compareTo(max) <= 0)

View File

@ -20,7 +20,7 @@ public class House {
}
public long getNumberOfFloors() {
return this.getNumberOfFloors();
return this.numberOfFloors;
}
public String toString() {