diff --git a/Project/.idea/uiDesigner.xml b/Project/.idea/uiDesigner.xml
index e96534f..8d2b59b 100644
--- a/Project/.idea/uiDesigner.xml
+++ b/Project/.idea/uiDesigner.xml
@@ -119,6 +119,15 @@
-
+
+
+
\ No newline at end of file
diff --git a/Project/src/DrawingAirplaneWindow.java b/Project/src/DrawingAirplaneWindow.java
index 186b922..7ffc0f3 100644
--- a/Project/src/DrawingAirplaneWindow.java
+++ b/Project/src/DrawingAirplaneWindow.java
@@ -51,4 +51,9 @@ public class DrawingAirplaneWindow extends JComponent implements IAdditionalDraw
g2d.drawOval((int)_startPosX + 27, (int)_startPosY + 11, 6, 4);
}
}
+
+ @Override
+ public int GetAddEnum() {
+ return _airplaneWindowEnum.GetAddEnum();
+ }
}
diff --git a/Project/src/DrawingPlane.java b/Project/src/DrawingPlane.java
index c3c1822..073e2a6 100644
--- a/Project/src/DrawingPlane.java
+++ b/Project/src/DrawingPlane.java
@@ -54,6 +54,11 @@ public class DrawingPlane extends JPanel
_airplaneWindow.SetAddEnum(countWindow);
}
+ //кол-во иллюминаторов
+ public int GetWindows(){
+ return _airplaneWindow.GetAddEnum();
+ }
+
//конструктор
public DrawingPlane(int speed, float weight, Color corpusColor, int countWindow, int planeWidth, int planeHeight)
{
diff --git a/Project/src/DrawingRectAirplaneWindow.java b/Project/src/DrawingRectAirplaneWindow.java
index eaacfb2..1b7c7df 100644
--- a/Project/src/DrawingRectAirplaneWindow.java
+++ b/Project/src/DrawingRectAirplaneWindow.java
@@ -51,4 +51,9 @@ public class DrawingRectAirplaneWindow extends JComponent implements IAdditional
g2d.drawRect((int)_startPosX + 27, (int)_startPosY + 11, 6, 4);
}
}
+
+ @Override
+ public int GetAddEnum() {
+ return _airplaneWindowEnum.GetAddEnum();
+ }
}
diff --git a/Project/src/DrawingTriangleAirplaneWindow.java b/Project/src/DrawingTriangleAirplaneWindow.java
index bdbebfb..d0112d8 100644
--- a/Project/src/DrawingTriangleAirplaneWindow.java
+++ b/Project/src/DrawingTriangleAirplaneWindow.java
@@ -60,4 +60,9 @@ public class DrawingTriangleAirplaneWindow extends JComponent implements IAdditi
g2d.drawPolygon(x_point, y_point, 3);
}
}
+
+ @Override
+ public int GetAddEnum() {
+ return _airplaneWindowEnum.GetAddEnum();
+ }
}
diff --git a/Project/src/DrawningObjectPlane.java b/Project/src/DrawningObjectPlane.java
index b988862..c945da1 100644
--- a/Project/src/DrawningObjectPlane.java
+++ b/Project/src/DrawningObjectPlane.java
@@ -50,4 +50,18 @@ public class DrawningObjectPlane implements IDrawningObject
return null;
}
+
+ public String GetInfo()
+ {
+ if(_plane != null)
+ {
+ return ExtentionPlane.GetDataForSave(_plane);
+ }
+ return null;
+ }
+
+ public static IDrawningObject Create(String data)
+ {
+ return new DrawningObjectPlane(ExtentionPlane.CreateDrawingPlane(data));
+ }
}
diff --git a/Project/src/ExtentionPlane.java b/Project/src/ExtentionPlane.java
new file mode 100644
index 0000000..1113796
--- /dev/null
+++ b/Project/src/ExtentionPlane.java
@@ -0,0 +1,48 @@
+import java.awt.*;
+
+public class ExtentionPlane
+{
+ //разделитель для записи информации по объекту в файл
+ private static final char _separatorForObject = ':';
+
+ //создание объекта из строки
+ public static DrawingPlane CreateDrawingPlane(String info)
+ {
+ String[] strs = info.split(String.valueOf(_separatorForObject));
+
+ //если простой самолёт
+ if(strs.length == 4)
+ {
+ Color color = new Color(Integer.parseInt(strs[2]));
+ return new DrawingPlane(Integer.parseInt(strs[0]), Float.valueOf(strs[1]), color, Integer.parseInt(strs[3]));
+ }
+
+ //если аэробус
+ if(strs.length == 7)
+ {
+ Color f_color = new Color(Integer.parseInt(strs[2]));
+ Color s_color = new Color(Integer.parseInt(strs[4]));
+
+ return new DrawingAirbus(Integer.parseInt(strs[0]), Integer.parseInt(strs[1]), f_color, Integer.parseInt(strs[3]),
+ s_color, Boolean.parseBoolean(strs[5]), Boolean.parseBoolean(strs[6]));
+ }
+
+ return null;
+ }
+
+ //сохранение объекта в строку
+ public static String GetDataForSave(DrawingPlane drawingPlane)
+ {
+ var plane = drawingPlane.Plane;
+ var str = String.format("%d%c%d%c%d%c%d", plane.GetSpeed(), _separatorForObject, (int)plane.GetWeight(), _separatorForObject,
+ plane.GetColor().getRGB(), _separatorForObject, drawingPlane.GetWindows());
+
+ //если объект не расширеный
+ if(!(plane instanceof EntityAirbus airbus))
+ {
+ return str;
+ }
+
+ return str + String.format("%c%s%c%b%c%b", _separatorForObject, airbus.AddColor().getRGB(), _separatorForObject, airbus.AddEngine(), _separatorForObject, airbus.AddCompartment());
+ }
+}
diff --git a/Project/src/FormMapWithSetPlanesGeneric.form b/Project/src/FormMapWithSetPlanesGeneric.form
index c845aca..019f752 100644
--- a/Project/src/FormMapWithSetPlanesGeneric.form
+++ b/Project/src/FormMapWithSetPlanesGeneric.form
@@ -1,19 +1,19 @@
diff --git a/Project/src/FormMapWithSetPlanesGeneric.java b/Project/src/FormMapWithSetPlanesGeneric.java
index 9e59919..be8d980 100644
--- a/Project/src/FormMapWithSetPlanesGeneric.java
+++ b/Project/src/FormMapWithSetPlanesGeneric.java
@@ -30,6 +30,12 @@ public class FormMapWithSetPlanesGeneric extends JFrame{
private JButton ButtonDeleteMap;
private JPanel GroupBoxMap;
private JButton ButtonShowDelete;
+ private JMenuBar MenuBarSaveLoad;
+ private JMenu MenuChoiceOperation;
+ private JMenuItem MenuItemLoadData;
+ private JMenuItem MenuItemSaveData;
+ private JMenuItem MenuItemLoadOneMapData;
+ private JMenuItem MenuItemSaveOneMapData;
//объект от коллекции карт
private final MapsCollection _mapsCollection;
@@ -46,7 +52,7 @@ public class FormMapWithSetPlanesGeneric extends JFrame{
{
super("Хранилище");
CreateWindow();
- _mapsCollection = new MapsCollection(730, 650);
+ _mapsCollection = new MapsCollection(730, 700);
ComboBoxSelectorMap.removeAllItems();
for (String elem : _mapsHashMap.keySet())
@@ -172,7 +178,7 @@ public class FormMapWithSetPlanesGeneric extends JFrame{
return;
}
- DrawningObjectPlane plane = _mapsCollection.get(ListBoxMaps.getSelectedValue().toString()).GetPlaneInDelete();
+ DrawningObjectPlane plane = (DrawningObjectPlane)_mapsCollection.get(ListBoxMaps.getSelectedValue().toString()).GetPlaneInDelete();
if(plane == null)
{
@@ -365,11 +371,106 @@ public class FormMapWithSetPlanesGeneric extends JFrame{
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
- if ((c < '0') || (c > '9')) {
+ if ((c < '0') || (c > '9'))
+ {
e.consume();
}
}
});
+
+ //обработка нажатия загрузки всех карт
+ MenuItemLoadData.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JFileChooser jfc = new JFileChooser();
+ int result = jfc.showOpenDialog(null);
+
+ if (result == JFileChooser.APPROVE_OPTION)
+ {
+ if (_mapsCollection.LoadData(jfc.getSelectedFile().getPath()))
+ {
+ ReloadMaps();
+ JOptionPane.showMessageDialog(null,"Загрузка данных прошла успешно",
+ "Результат", JOptionPane.INFORMATION_MESSAGE);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(null, "Ошибка загрузки данных",
+ "Результат", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ });
+
+ //обработка нажатия сохранения всех карт
+ MenuItemSaveData.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JFileChooser jfc = new JFileChooser();
+ int result = jfc.showSaveDialog(null);
+
+ if (result == JFileChooser.APPROVE_OPTION)
+ {
+ if (_mapsCollection.SaveData(jfc.getSelectedFile().getPath()))
+ {
+ JOptionPane.showMessageDialog(null,"Сохранение прошло успешно",
+ "Результат", JOptionPane.INFORMATION_MESSAGE);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(null, "Не сохранилось",
+ "Результат", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ });
+
+ //загрузка одной карты
+ MenuItemLoadOneMapData.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JFileChooser jfc = new JFileChooser();
+ int result = jfc.showOpenDialog(null);
+
+ if (result == JFileChooser.APPROVE_OPTION)
+ {
+ if (_mapsCollection.LoadOneData(jfc.getSelectedFile().getPath()))
+ {
+ ReloadMaps();
+ JOptionPane.showMessageDialog(null,"Загрузка данных прошла успешно",
+ "Результат", JOptionPane.INFORMATION_MESSAGE);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(null, "Ошибка загрузки данных",
+ "Результат", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ });
+
+ //сохранение одной карты
+ MenuItemSaveOneMapData.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JFileChooser jfc = new JFileChooser();
+ int result = jfc.showSaveDialog(null);
+
+ if (result == JFileChooser.APPROVE_OPTION)
+ {
+ if (_mapsCollection.SaveOneData(jfc.getSelectedFile().getPath(), ListBoxMaps.getSelectedValue().toString()))
+ {
+ JOptionPane.showMessageDialog(null,"Сохранение прошло успешно",
+ "Результат", JOptionPane.INFORMATION_MESSAGE);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(null, "Не сохранилось",
+ "Результат", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ });
}
private void createUIComponents()
diff --git a/Project/src/FormPlaneConfig.form b/Project/src/FormPlaneConfig.form
index 7566cae..a8b1418 100644
--- a/Project/src/FormPlaneConfig.form
+++ b/Project/src/FormPlaneConfig.form
@@ -298,7 +298,7 @@
-
+
@@ -335,16 +335,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -353,6 +343,15 @@
+
+
+
+
+
+
+
+
+
diff --git a/Project/src/FormPlaneConfig.java b/Project/src/FormPlaneConfig.java
index 2dfcd85..6a6cce7 100644
--- a/Project/src/FormPlaneConfig.java
+++ b/Project/src/FormPlaneConfig.java
@@ -35,7 +35,6 @@ public class FormPlaneConfig extends JFrame{
private JPanel GroubBoxSelectedCountWindow;
private JSpinner NumericUpDownCountWindow;
private JPanel MainPanel;
- private JLabel LabelTypeWindow;
private JLabel LabelSimpleWindow;
private JLabel LabelRectWindow;
private JLabel LabelTriangleWindow;
@@ -47,7 +46,14 @@ public class FormPlaneConfig extends JFrame{
//событие
Consumer EventAddPlane;
- public void AddEvent(Consumer ev){
+ //объект для контролирования работы DnD
+ Object dragObject;
+
+ //хранит в себе объект иллюминатор
+ Object enterObject;
+
+ public void AddEvent(Consumer ev)
+ {
EventAddPlane = ev;
}
@@ -86,7 +92,6 @@ public class FormPlaneConfig extends JFrame{
//рамки у Label
LabelAddColor.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
- LabelTypeWindow.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
LabelBaseColor.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
LabelModifiedObject.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
LabelSimpleObject.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
@@ -123,7 +128,6 @@ public class FormPlaneConfig extends JFrame{
PictureBoxPlane.addMouseListener(defCursor);
LabelBaseColor.addMouseListener(defCursor);
LabelAddColor.addMouseListener(defCursor);
- LabelTypeWindow.addMouseListener(defCursor);
PanelBlack.addMouseListener(drag);
PanelPurple.addMouseListener(drag);
@@ -140,11 +144,20 @@ public class FormPlaneConfig extends JFrame{
LabelRectWindow.addMouseListener(drag);
LabelTriangleWindow.addMouseListener(drag);
+ //настройка DnD для перетаскивания формы иллюминаторов
+ AdditWindowDropObject(LabelSimpleWindow);
+ AdditWindowDropObject(LabelRectWindow);
+ AdditWindowDropObject(LabelTriangleWindow);
+
+ AdditWindowDropTarget(PictureBoxPlane);
+
+ //передача объекта через событие
ButtonAddObject.addActionListener(e -> {
EventAddPlane.accept(_plane);
dispose();
});
+ //лямбда-выражение для закрытия формы
ButtonCancel.addActionListener(e -> dispose());
}
@@ -215,27 +228,84 @@ public class FormPlaneConfig extends JFrame{
revalidate();
}
}
- else if(dropItem instanceof JLabel label && LabelTypeWindow.getMousePosition() != null && _plane!=null)
+ }
+
+ void AdditWindowDropTarget(JComponent obj)
+ {
+ obj.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseEntered(MouseEvent e) {super.mouseEntered(e);
+ Window_DragEnter(obj);
+ }
+ @Override
+ public void mouseExited(MouseEvent e) {super.mouseExited(e);
+ DragExit();
+ }
+ });
+ }
+
+ void AdditWindowDropObject(JComponent obj)
+ {
+ obj.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {super.mousePressed(e);
+ Window_MouseDown(obj);
+ }
+ @Override
+ public void mouseReleased(MouseEvent e) {super.mouseReleased(e);
+ Window_DragDrop();
+ }
+ });
+ }
+
+ void Window_MouseDown(Object sender)
+ {
+ IAdditionalDrawingObject windows;
+ switch (((JLabel)sender).getText()){
+ case "Простая":
+ windows = new DrawingAirplaneWindow();
+ break;
+ case "Треугольная":
+ windows = new DrawingTriangleAirplaneWindow();
+ break;
+ case "Квадратная":
+ windows = new DrawingRectAirplaneWindow();
+ break;
+ default:
+ return;
+ }
+
+ enterObject = windows;
+ }
+
+ void Window_DragEnter(Object sender)
+ {
+ if(enterObject != null && IAdditionalDrawingObject.class.isAssignableFrom(enterObject.getClass()) && _plane != null)
{
- if(label == LabelSimpleWindow)
- {
- _plane.SetTypeWindow((int)NumericUpDownCountWindow.getValue(), new DrawingAirplaneWindow());
- Draw(_plane);
- }
+ setCursor(new Cursor(Cursor.HAND_CURSOR));
+ dragObject = sender;
+ }
+ }
- if(label == LabelRectWindow)
- {
- _plane.SetTypeWindow((int)NumericUpDownCountWindow.getValue(), new DrawingRectAirplaneWindow());
- Draw(_plane);
- }
+ void Window_DragDrop()
+ {
+ if(dragObject == null)
+ {
+ return;
+ }
- if(label == LabelTriangleWindow)
- {
- _plane.SetTypeWindow((int)NumericUpDownCountWindow.getValue(), new DrawingTriangleAirplaneWindow());
- Draw(_plane);
- }
+ _plane.SetTypeWindow((int)NumericUpDownCountWindow.getValue(), (IAdditionalDrawingObject)enterObject);
+ DragExit();
+ enterObject = null;
+ }
- repaint();
+ void DragExit()
+ {
+ if(enterObject != null && dragObject != null)
+ {
+ setCursor(Cursor.getDefaultCursor());
+ Draw(_plane);
+ dragObject = null;
}
}
}
diff --git a/Project/src/IAdditionalDrawingObject.java b/Project/src/IAdditionalDrawingObject.java
index cf9f27b..6aa61c2 100644
--- a/Project/src/IAdditionalDrawingObject.java
+++ b/Project/src/IAdditionalDrawingObject.java
@@ -4,4 +4,5 @@ public interface IAdditionalDrawingObject
{
void SetAddEnum(int airplaneWindow);
void DrawAirplaneWindow(Color colorAirplaneWindow, Graphics g, float _startPosX, float _startPosY);
+ int GetAddEnum();
}
diff --git a/Project/src/IDrawningObject.java b/Project/src/IDrawningObject.java
index fe90faa..1bafbc2 100644
--- a/Project/src/IDrawningObject.java
+++ b/Project/src/IDrawningObject.java
@@ -16,4 +16,7 @@ public interface IDrawningObject
//получение текущей позиции объекта
float[] GetCurrentPosition();
+
+ //получение информации по объекту
+ String GetInfo();
}
diff --git a/Project/src/MapWithSetPlanesGeneric.java b/Project/src/MapWithSetPlanesGeneric.java
index 7169b36..d69dd2b 100644
--- a/Project/src/MapWithSetPlanesGeneric.java
+++ b/Project/src/MapWithSetPlanesGeneric.java
@@ -17,13 +17,13 @@ public class MapWithSetPlanesGeneric _setPlanes;
+ private SetPlanesGeneric _setPlanes;
//набор удалённых объектов (двусвязный список)
public final LinkedList _deletePlane;
//карта
- private final U _map;
+ private U _map;
//конструктор
public MapWithSetPlanesGeneric(int picWidth, int picHeight, U map)
@@ -90,6 +90,28 @@ public class MapWithSetPlanesGeneric > _mapStorage;
+ public HashMap> _mapStorage;
//возвращение списка названий карт
public ArrayList Keys()
@@ -18,6 +20,12 @@ public class MapsCollection
//высота окна отрисовки
private final int _pictureHeight;
+ //разделитель для записи информации по элементу словаря в файл
+ private final char separatorDict = '|';
+
+ //разделитель для записи коллекции данных в файл
+ private final char separatorData = ';';
+
//конструктор
public MapsCollection(int pictureWidth, int pictureHeight)
{
@@ -43,8 +51,178 @@ public class MapsCollection
_mapStorage.remove(name);
}
+ //сохранение информации по самолётам в ангарах в файл
+ public Boolean SaveData(String filename)
+ {
+ File file = new File(filename);
+
+ if (file.exists())
+ {
+ file.delete();
+ }
+
+ try (BufferedWriter writter = new BufferedWriter(new FileWriter(filename)))
+ {
+ writter.write(String.format("MapsCollection" + System.lineSeparator()));
+
+ for(Map.Entry> entry : _mapStorage.entrySet())
+ {
+ writter.write("" + entry.getKey() + separatorDict + entry.getValue().GetData(separatorDict, separatorData) + "\n");
+ }
+ }
+ catch (IOException e) {
+ JOptionPane.showMessageDialog(null, e.getMessage());
+ }
+
+ return true;
+ }
+
+ //загрузка нформации по по самолётам в ангарах из файла
+ public Boolean LoadData(String filename)
+ {
+ File file = new File(filename);
+
+ if (!file.exists())
+ {
+ return false;
+ }
+
+ try (BufferedReader reader = new BufferedReader(new FileReader(filename)))
+ {
+ String str = "";
+
+ //если не содержит такую запись или пустой файл
+ if ((str = reader.readLine()) == null || !str.contains("MapsCollection"))
+ {
+ return false;
+ }
+
+ _mapStorage.clear();
+
+ while ((str = reader.readLine()) != null)
+ {
+ var element = str.split(String.format("\\%c", separatorDict));
+ AbstractMap map = null;
+
+ switch (element[1])
+ {
+ case "SimpleMap":
+ map = new SimpleMap();
+ break;
+ case "DesertStormMap":
+ map = new DesertStormMap();
+ break;
+ case "StarWarsMap":
+ map = new StarWarsMap();
+ break;
+ }
+
+ _mapStorage.put(element[0], new MapWithSetPlanesGeneric(_pictureWidth, _pictureHeight,
+ map));
+
+ _mapStorage.get(element[0]).LoadData(element[2].split(String.valueOf(separatorData)));
+ }
+ }
+ catch (IOException e)
+ {
+ JOptionPane.showMessageDialog(null, e.getMessage());
+ }
+
+ return true;
+ }
+
+ //сохранение информации по самолётам в ангарах в файл
+ public Boolean SaveOneData(String filename, String mapName)
+ {
+ File file = new File(filename);
+
+ if (file.exists())
+ {
+ file.delete();
+ }
+
+ try (BufferedWriter writter = new BufferedWriter(new FileWriter(filename)))
+ {
+ writter.write(String.format("SaveOneMap" + System.lineSeparator() + "Data of map:" + System.lineSeparator()));
+
+ for(Map.Entry> entry : _mapStorage.entrySet())
+ {
+ if(entry.getKey() == mapName)
+ {
+ writter.write("" + entry.getKey() + separatorDict + entry.getValue().GetData(separatorDict, separatorData) + "\n");
+
+ break;
+ }
+ }
+ }
+ catch (IOException e) {
+ JOptionPane.showMessageDialog(null, e.getMessage());
+ }
+
+ return true;
+ }
+
+ //загрузка информации по по самолётам в ангарах из файла
+ public Boolean LoadOneData(String filename)
+ {
+ File file = new File(filename);
+
+ if (!file.exists())
+ {
+ return false;
+ }
+
+ try (BufferedReader reader = new BufferedReader(new FileReader(filename)))
+ {
+ String str = "";
+
+ //если не содержит такую запись или пустой файл
+ if ((str = reader.readLine()) == null || !str.contains("SaveOneMap"))
+ {
+ return false;
+ }
+
+ while ((str = reader.readLine()) != null)
+ {
+ var element = str.split(String.format("\\%c", separatorDict));
+ AbstractMap map = null;
+
+ //добавление в коллекцию с устранением лишнего слова в названии
+ try {
+ switch (element[1]) {
+ case "SimpleMap":
+ map = new SimpleMap();
+ break;
+ case "DesertStormMap":
+ map = new DesertStormMap();
+ break;
+ case "StarWarsMap":
+ map = new StarWarsMap();
+ break;
+ }
+
+ //если имя загружаемой карты есть в коллекции
+ if (_mapStorage.get(element[0]) != null)
+ {
+ _mapStorage.get(element[0]).Clear();
+ }
+
+ _mapStorage.put(element[0], new MapWithSetPlanesGeneric
+ (_pictureWidth, _pictureHeight, map));
+ _mapStorage.get(element[0]).LoadData(element[2].split(String.valueOf(separatorData)));
+ } catch (Exception ex) { }
+ }
+ }
+ catch (IOException e)
+ {
+ JOptionPane.showMessageDialog(null, e.getMessage());
+ }
+
+ return true;
+ }
+
//Доступ к аэродрому
- public MapWithSetPlanesGeneric get(String index)
+ public MapWithSetPlanesGeneric get(String index)
{
if(_mapStorage.containsKey(index))
{
@@ -54,7 +232,7 @@ public class MapsCollection
return null;
}
- public DrawningObjectPlane Get(String name, int index)
+ public IDrawningObject Get(String name, int index)
{
if(_mapStorage.containsKey(name))
{