From dc452395925bfcf370babe02c53220fecf7c3450 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Sun, 20 Nov 2022 22:02:02 +0400
Subject: [PATCH 1/9] Added RollersCount serialization

---
 RollersCount.java | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/RollersCount.java b/RollersCount.java
index 7b9cdbe..38dbc92 100644
--- a/RollersCount.java
+++ b/RollersCount.java
@@ -1,5 +1,18 @@
 public enum RollersCount {
     Four,
     Five,
-    Six
+    Six;
+
+    public int getValue() {
+        return switch (this) {
+            case Four -> 4;
+            case Five -> 5;
+            case Six -> 6;
+        };
+    }
+
+    @Override
+    public String toString() {
+        return Integer.toString(getValue());
+    }
 }
-- 
2.25.1


From 63c379da6f707abdea3ab7db6b9e235501aa3d14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Sun, 20 Nov 2022 22:03:58 +0400
Subject: [PATCH 2/9] Now you can get rollers' count

---
 DrawingCrossRollers.java   | 4 ++++
 DrawingRollers.java        | 4 ++++
 DrawingSquaredRollers.java | 4 ++++
 IDrawingRollers.java       | 1 +
 4 files changed, 13 insertions(+)

diff --git a/DrawingCrossRollers.java b/DrawingCrossRollers.java
index 70e6e8c..ae392ee 100644
--- a/DrawingCrossRollers.java
+++ b/DrawingCrossRollers.java
@@ -19,6 +19,10 @@ public class DrawingCrossRollers implements IDrawingRollers {
         }
     }
 
+    public int getRollersCount() {
+        return rollersCount.getValue();
+    }
+
     public void draw(Graphics2D g, int x, int y, int artilleryWidth, int artilleryHeight) {
         g.setColor(color != null ? color : Color.BLACK);
         g.fillOval(x + artilleryWidth / 20, y + artilleryHeight * 7 / 15, artilleryWidth * 4 / 20, artilleryHeight * 10 / 32);
diff --git a/DrawingRollers.java b/DrawingRollers.java
index 7c55044..e23b53f 100644
--- a/DrawingRollers.java
+++ b/DrawingRollers.java
@@ -19,6 +19,10 @@ public class DrawingRollers implements IDrawingRollers {
         }
     }
 
+    public int getRollersCount() {
+        return rollersCount.getValue();
+    }
+
     public void draw(Graphics2D g, int x, int y, int artilleryWidth, int artilleryHeight) {
         g.setColor(color != null ? color : Color.BLACK);
         g.fillOval(x + artilleryWidth / 20, y + artilleryHeight * 7 / 15, artilleryWidth * 4 / 20, artilleryHeight * 10 / 32);
diff --git a/DrawingSquaredRollers.java b/DrawingSquaredRollers.java
index c15aebc..8e197cc 100644
--- a/DrawingSquaredRollers.java
+++ b/DrawingSquaredRollers.java
@@ -19,6 +19,10 @@ public class DrawingSquaredRollers implements IDrawingRollers {
         }
     }
 
+    public int getRollersCount() {
+        return rollersCount.getValue();
+    }
+
     public void draw(Graphics2D g, int x, int y, int artilleryWidth, int artilleryHeight) {
         g.setColor(color != null ? color : Color.BLACK);
         g.fillOval(x + artilleryWidth / 20, y + artilleryHeight * 7 / 15, artilleryWidth * 4 / 20, artilleryHeight * 10 / 32);
diff --git a/IDrawingRollers.java b/IDrawingRollers.java
index 166e40c..f63eb13 100644
--- a/IDrawingRollers.java
+++ b/IDrawingRollers.java
@@ -4,4 +4,5 @@ public interface IDrawingRollers {
     void setRollersCount(int num);
     void setColor(Color color);
     void draw(Graphics2D g, int x, int y, int artilleryWidth, int artilleryHeight);
+    int getRollersCount();
 }
-- 
2.25.1


From ade75a5dc3283ab638a8d4cf5299dd14c5b3173e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Sun, 20 Nov 2022 22:20:41 +0400
Subject: [PATCH 3/9] Added DrawingArtillery serialization and deserialization

---
 ArtillerySerde.java | 68 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
 create mode 100644 ArtillerySerde.java

diff --git a/ArtillerySerde.java b/ArtillerySerde.java
new file mode 100644
index 0000000..14544e3
--- /dev/null
+++ b/ArtillerySerde.java
@@ -0,0 +1,68 @@
+import java.awt.*;
+
+public class ArtillerySerde {  // Artillery Serialization/Deserialization
+    private static final String _separatorForObject = ":";
+
+    public static DrawingArtillery deserialize(String info) {
+        String[] strings = info.split(_separatorForObject);
+
+        int speed = Integer.parseInt(strings[0]);
+        float weight = Float.parseFloat(strings[1]);
+        Color bodyColor = new Color(Integer.parseInt(strings[2]));
+        IDrawingRollers rollers = switch (strings[3]) {
+            case "DrawingRollers" -> new DrawingRollers(Integer.parseInt(strings[4]), bodyColor);
+            case "DrawingCrossRollers" -> new DrawingCrossRollers(Integer.parseInt(strings[4]), bodyColor);
+            case "DrawingSquaredRollers" -> new DrawingSquaredRollers(Integer.parseInt(strings[4]), bodyColor);
+        };
+
+        if (strings.length == 5) {
+            EntityArtillery entity = new EntityArtillery(speed, weight, bodyColor);
+
+            return new DrawingArtillery(entity, rollers);
+        }
+
+        if (strings.length == 8) {
+            Color dopColor = new Color(Integer.parseInt(strings[5]));
+            boolean weapon = Boolean.parseBoolean(strings[6]);
+            boolean salvoBattery = Boolean.parseBoolean(strings[7]);
+
+            EntityAdvancedArtillery entity = new EntityAdvancedArtillery(speed, weight, bodyColor, dopColor, weapon, salvoBattery);
+
+            return new DrawingAdvancedArtillery(entity, rollers);
+        }
+
+        return null;
+    }
+
+    public static String serialize(DrawingArtillery drawingArtillery) {
+        EntityArtillery artillery = drawingArtillery.getArtillery();
+
+        String result = String.format(
+                "%d%s%f%s%d%s%s%s%d",
+                artillery.getSpeed(),
+                _separatorForObject,
+                artillery.getWeight(),
+                _separatorForObject,
+                artillery.getBodyColor().getRGB(),
+                _separatorForObject,
+                drawingArtillery.getRollers().getClass().getSimpleName(),
+                _separatorForObject,
+                drawingArtillery.getRollers().getRollersCount()
+        );
+
+        if (!(artillery instanceof EntityAdvancedArtillery advanced)) {
+            return result;
+        }
+
+        return String.format(
+                "%s%s%d%s%b%s%b",
+                result,
+                _separatorForObject,
+                advanced.getDopColor().getRGB(),
+                _separatorForObject,
+                advanced.getWeapon(),
+                _separatorForObject,
+                advanced.getSalvoBattery()
+        );
+    }
+}
-- 
2.25.1


From 8d4407de4c6d047a8022572d6f78a66bb93a6077 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Sun, 20 Nov 2022 22:27:21 +0400
Subject: [PATCH 4/9] Added DrawingObjectArtillery serialization and
 deserialization

---
 DrawingObjectArtillery.java | 12 ++++++++++++
 IDrawingObject.java         |  1 +
 2 files changed, 13 insertions(+)

diff --git a/DrawingObjectArtillery.java b/DrawingObjectArtillery.java
index 5292c9c..9036048 100644
--- a/DrawingObjectArtillery.java
+++ b/DrawingObjectArtillery.java
@@ -38,4 +38,16 @@ public class DrawingObjectArtillery implements IDrawingObject {
     public void drawingObject(Graphics2D g) {
         _artillery.drawTransport(g);
     }
+
+    public String getInfo() {
+        if (_artillery == null) {
+            return null;
+        }
+
+        return ArtillerySerde.serialize(_artillery);
+    }
+
+    public static IDrawingObject create(String data) {
+        return new DrawingObjectArtillery(ArtillerySerde.deserialize(data));
+    }
 }
diff --git a/IDrawingObject.java b/IDrawingObject.java
index f1effa3..67ea616 100644
--- a/IDrawingObject.java
+++ b/IDrawingObject.java
@@ -6,4 +6,5 @@ public interface IDrawingObject {
     void moveObject(Direction direction);
     void drawingObject(Graphics2D g);
     float[] getCurrentPosition();
+    String getInfo();
 }
-- 
2.25.1


From ebc0f0720459c7cca4007d0246827558d9f1bdd6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Sun, 20 Nov 2022 22:41:03 +0400
Subject: [PATCH 5/9] Added MapWithSetArtilleriesGeneric serialization and
 deserialization

---
 MapWithSetArtilleriesGeneric.java | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/MapWithSetArtilleriesGeneric.java b/MapWithSetArtilleriesGeneric.java
index 3c2774f..c00e5d6 100644
--- a/MapWithSetArtilleriesGeneric.java
+++ b/MapWithSetArtilleriesGeneric.java
@@ -124,4 +124,21 @@ public class MapWithSetArtilleriesGeneric<T extends IDrawingObject, U extends Ab
             index++;
         }
     }
+
+    public String getData(char separatorType, char separatorData) {
+        StringBuilder data = new StringBuilder(String.format("%s%c", _map.getClass().getSimpleName(), separatorType));
+
+        for (var artillery : _setArtilleries.getArtilleries()) {
+            data.append(String.format("%s%c", artillery.getInfo(), separatorData));
+        }
+
+        return data.toString();
+    }
+
+    @SuppressWarnings("unchecked")
+    public void loadData(String[] records) {
+        for (int i = records.length - 1; i >= 0; i--) {
+            _setArtilleries.insert((T) DrawingObjectArtillery.create(records[i]));
+        }
+    }
 }
-- 
2.25.1


From 96d181608fc954c79b79f26d60a367bdd1f81c0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Sun, 20 Nov 2022 23:07:02 +0400
Subject: [PATCH 6/9] Minor fixes in ArtillerySerde. Added MapsCollection
 saving to and loading from file

---
 ArtillerySerde.java |  8 +++----
 MapsCollection.java | 56 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 4 deletions(-)

diff --git a/ArtillerySerde.java b/ArtillerySerde.java
index 14544e3..196b35f 100644
--- a/ArtillerySerde.java
+++ b/ArtillerySerde.java
@@ -1,10 +1,10 @@
 import java.awt.*;
 
 public class ArtillerySerde {  // Artillery Serialization/Deserialization
-    private static final String _separatorForObject = ":";
+    private static final char _separatorForObject = ':';
 
     public static DrawingArtillery deserialize(String info) {
-        String[] strings = info.split(_separatorForObject);
+        String[] strings = info.split(Character.toString(_separatorForObject));
 
         int speed = Integer.parseInt(strings[0]);
         float weight = Float.parseFloat(strings[1]);
@@ -38,7 +38,7 @@ public class ArtillerySerde {  // Artillery Serialization/Deserialization
         EntityArtillery artillery = drawingArtillery.getArtillery();
 
         String result = String.format(
-                "%d%s%f%s%d%s%s%s%d",
+                "%d%c%f%c%d%c%s%c%d",
                 artillery.getSpeed(),
                 _separatorForObject,
                 artillery.getWeight(),
@@ -55,7 +55,7 @@ public class ArtillerySerde {  // Artillery Serialization/Deserialization
         }
 
         return String.format(
-                "%s%s%d%s%b%s%b",
+                "%s%c%d%c%b%c%b",
                 result,
                 _separatorForObject,
                 advanced.getDopColor().getRGB(),
diff --git a/MapsCollection.java b/MapsCollection.java
index 5b9f24c..46eefd5 100644
--- a/MapsCollection.java
+++ b/MapsCollection.java
@@ -1,3 +1,4 @@
+import java.io.*;
 import java.util.HashMap;
 import java.util.Set;
 
@@ -7,6 +8,9 @@ public class MapsCollection {
     private final int _pictureWidth;
     private final int _pictureHeight;
 
+    private final char separatorDict = '|';
+    private final char separatorData = ';';
+
     public Set<String> getKeys() {
         return _mapsStorage.keySet();
     }
@@ -38,4 +42,56 @@ public class MapsCollection {
         }
         return null;
     }
+
+    @SuppressWarnings("ResultOfMethodCallIgnored")
+    public boolean saveData(String filename) throws IOException {
+        File file = new File(filename);
+
+        if (file.exists()) {
+            file.delete();
+        }
+
+        file.createNewFile();
+
+        try (PrintWriter writer = new PrintWriter(file)) {
+            writer.println("MapsCollection");
+
+            for (var storage : _mapsStorage.entrySet()) {
+                writer.println(String.format("%s%c%s", storage.getKey(), separatorDict, storage.getValue().getData(separatorDict, separatorData)));
+            }
+        }
+
+        return true;
+    }
+
+    public boolean loadData(String filename) throws IOException {
+        File file = new File(filename);
+
+        if (!file.exists()) {
+            return false;
+        }
+
+        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+            String currentLine = reader.readLine();
+
+            if (currentLine == null || !currentLine.contains("MapsCollection")) {
+                return false;
+            }
+
+            _mapsStorage.clear();
+            while ((currentLine = reader.readLine()) != null) {
+                var elements = currentLine.split(Character.toString(separatorDict));
+
+                AbstractMap map = switch (elements[1]) {
+                    case "SimpleMap" -> new SimpleMap();
+                    case "ForestMap" -> new ForestMap();
+                };
+
+                _mapsStorage.put(elements[0], new MapWithSetArtilleriesGeneric<>(_pictureWidth, _pictureHeight, map));
+                _mapsStorage.get(elements[0]).loadData(elements[2].split(separatorData + "*(\n?)"));
+            }
+        }
+
+        return true;
+    }
 }
-- 
2.25.1


From 9b23e2f1192bac3a53f6bc88df7ad6829d1e5ea5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Mon, 21 Nov 2022 01:04:53 +0400
Subject: [PATCH 7/9] Base part has been completed

---
 ArtillerySerde.java            |  3 ++-
 FormMapWithSetArtilleries.java | 47 ++++++++++++++++++++++++++++++++++
 MapsCollection.java            |  7 +++--
 3 files changed, 54 insertions(+), 3 deletions(-)

diff --git a/ArtillerySerde.java b/ArtillerySerde.java
index 196b35f..d633e3f 100644
--- a/ArtillerySerde.java
+++ b/ArtillerySerde.java
@@ -13,6 +13,7 @@ public class ArtillerySerde {  // Artillery Serialization/Deserialization
             case "DrawingRollers" -> new DrawingRollers(Integer.parseInt(strings[4]), bodyColor);
             case "DrawingCrossRollers" -> new DrawingCrossRollers(Integer.parseInt(strings[4]), bodyColor);
             case "DrawingSquaredRollers" -> new DrawingSquaredRollers(Integer.parseInt(strings[4]), bodyColor);
+            default -> null;
         };
 
         if (strings.length == 5) {
@@ -38,7 +39,7 @@ public class ArtillerySerde {  // Artillery Serialization/Deserialization
         EntityArtillery artillery = drawingArtillery.getArtillery();
 
         String result = String.format(
-                "%d%c%f%c%d%c%s%c%d",
+                "%d%c%s%c%d%c%s%c%d",
                 artillery.getSpeed(),
                 _separatorForObject,
                 artillery.getWeight(),
diff --git a/FormMapWithSetArtilleries.java b/FormMapWithSetArtilleries.java
index 4c8e966..5112f61 100644
--- a/FormMapWithSetArtilleries.java
+++ b/FormMapWithSetArtilleries.java
@@ -1,13 +1,16 @@
 import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
 import javax.swing.text.DefaultFormatterFactory;
 import javax.swing.text.MaskFormatter;
 import java.awt.*;
+import java.io.IOException;
 import java.text.ParseException;
 import java.util.HashMap;
 import java.util.Optional;
 import java.util.Stack;
 
 public class FormMapWithSetArtilleries extends JFrame {
+    private JMenuBar menuBar;
     private JPanel pictureBox;
     private JPanel toolsGroup;
     private JLabel toolsLabel;
@@ -52,6 +55,50 @@ public class FormMapWithSetArtilleries extends JFrame {
 
         _mapsCollection = new MapsCollection(pictureBox.getWidth(), pictureBox.getHeight());
 
+        menuBar = new JMenuBar();
+
+        JMenu fileMenu = new JMenu("Файл");
+        menuBar.add(fileMenu);
+
+        JMenuItem saveMenuItem = new JMenuItem("Сохранить");
+        saveMenuItem.addActionListener(e -> {
+            JFileChooser dialog = new JFileChooser();
+            dialog.setFileFilter(new FileNameExtensionFilter("TXT file", "txt"));
+            dialog.showSaveDialog(this);
+
+            try {
+                if (_mapsCollection.saveData(dialog.getSelectedFile().getAbsolutePath())) {
+                    JOptionPane.showMessageDialog(this, "Сохранение прошло успешно", "Успех", JOptionPane.INFORMATION_MESSAGE);
+                } else {
+                    JOptionPane.showMessageDialog(this, "Не сохранилось", "Провал", JOptionPane.INFORMATION_MESSAGE);
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        });
+        fileMenu.add(saveMenuItem);
+
+        JMenuItem loadMenuItem = new JMenuItem("Загрузить");
+        loadMenuItem.addActionListener(e -> {
+            JFileChooser dialog = new JFileChooser();
+            dialog.setFileFilter(new FileNameExtensionFilter("TXT file", "txt"));
+            dialog.showOpenDialog(this);
+
+            try {
+                if (_mapsCollection.loadData(dialog.getSelectedFile().getAbsolutePath())) {
+                    reloadMaps();
+                    JOptionPane.showMessageDialog(this, "Загрузка прошла успешно", "Успех", JOptionPane.INFORMATION_MESSAGE);
+                } else {
+                    JOptionPane.showMessageDialog(this, "Не загрузилось", "Провал", JOptionPane.INFORMATION_MESSAGE);
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        });
+        fileMenu.add(loadMenuItem);
+
+        setJMenuBar(menuBar);
+
         comboBoxMapSelector.removeAllItems();
         for (var key : _mapsDict.keySet()) {
             comboBoxMapSelector.addItem(key);
diff --git a/MapsCollection.java b/MapsCollection.java
index 46eefd5..72a826c 100644
--- a/MapsCollection.java
+++ b/MapsCollection.java
@@ -59,6 +59,8 @@ public class MapsCollection {
             for (var storage : _mapsStorage.entrySet()) {
                 writer.println(String.format("%s%c%s", storage.getKey(), separatorDict, storage.getValue().getData(separatorDict, separatorData)));
             }
+
+            writer.flush();
         }
 
         return true;
@@ -80,15 +82,16 @@ public class MapsCollection {
 
             _mapsStorage.clear();
             while ((currentLine = reader.readLine()) != null) {
-                var elements = currentLine.split(Character.toString(separatorDict));
+                var elements = currentLine.split(String.format("\\%c", separatorDict));
 
                 AbstractMap map = switch (elements[1]) {
                     case "SimpleMap" -> new SimpleMap();
                     case "ForestMap" -> new ForestMap();
+                    default -> null;
                 };
 
                 _mapsStorage.put(elements[0], new MapWithSetArtilleriesGeneric<>(_pictureWidth, _pictureHeight, map));
-                _mapsStorage.get(elements[0]).loadData(elements[2].split(separatorData + "*(\n?)"));
+                _mapsStorage.get(elements[0]).loadData(elements[2].split(separatorData + "\n?"));
             }
         }
 
-- 
2.25.1


From d5533765089eb9754adcf8313078684bb225d070 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=9F=D0=BE=D0=BB?=
 =?UTF-8?q?=D0=B5=D0=B2=D0=BE=D0=B9?= <sergpolevoi@yandex.ru>
Date: Mon, 21 Nov 2022 01:48:43 +0400
Subject: [PATCH 8/9] Work is done 06

---
 FormMapWithSetArtilleries.java    | 37 ++++++++++++++++
 MapWithSetArtilleriesGeneric.java |  4 ++
 MapsCollection.java               | 73 ++++++++++++++++++++++++++++++-
 SetArtilleriesGeneric.java        |  4 ++
 4 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/FormMapWithSetArtilleries.java b/FormMapWithSetArtilleries.java
index 5112f61..16f6b4c 100644
--- a/FormMapWithSetArtilleries.java
+++ b/FormMapWithSetArtilleries.java
@@ -97,6 +97,43 @@ public class FormMapWithSetArtilleries extends JFrame {
         });
         fileMenu.add(loadMenuItem);
 
+        JMenuItem saveMapMenuItem = new JMenuItem("Сохранить карту");
+        saveMapMenuItem.addActionListener(e -> {
+            JFileChooser dialog = new JFileChooser();
+            dialog.setFileFilter(new FileNameExtensionFilter("TXT file", "txt"));
+            dialog.showSaveDialog(this);
+
+            try {
+                if (_mapsCollection.saveMap(Optional.ofNullable(listBoxMaps.getSelectedValue()).orElse(""), dialog.getSelectedFile().getAbsolutePath())) {
+                    JOptionPane.showMessageDialog(this, "Сохранение прошло успешно", "Успех", JOptionPane.INFORMATION_MESSAGE);
+                } else {
+                    JOptionPane.showMessageDialog(this, "Не сохранилось", "Провал", JOptionPane.INFORMATION_MESSAGE);
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        });
+        fileMenu.add(saveMapMenuItem);
+
+        JMenuItem loadMapMenuItem = new JMenuItem("Загрузить карту");
+        loadMapMenuItem.addActionListener(e -> {
+            JFileChooser dialog = new JFileChooser();
+            dialog.setFileFilter(new FileNameExtensionFilter("TXT file", "txt"));
+            dialog.showOpenDialog(this);
+
+            try {
+                if (_mapsCollection.loadMap(dialog.getSelectedFile().getAbsolutePath())) {
+                    reloadMaps();
+                    JOptionPane.showMessageDialog(this, "Загрузка прошла успешно", "Успех", JOptionPane.INFORMATION_MESSAGE);
+                } else {
+                    JOptionPane.showMessageDialog(this, "Не загрузилось", "Провал", JOptionPane.INFORMATION_MESSAGE);
+                }
+            } catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        });
+        fileMenu.add(loadMapMenuItem);
+
         setJMenuBar(menuBar);
 
         comboBoxMapSelector.removeAllItems();
diff --git a/MapWithSetArtilleriesGeneric.java b/MapWithSetArtilleriesGeneric.java
index c00e5d6..85c4474 100644
--- a/MapWithSetArtilleriesGeneric.java
+++ b/MapWithSetArtilleriesGeneric.java
@@ -19,6 +19,10 @@ public class MapWithSetArtilleriesGeneric<T extends IDrawingObject, U extends Ab
         _map = map;
     }
 
+    public U getMap() {
+        return _map;
+    }
+
     public int addArtillery(T artillery) {
         return _setArtilleries.insert(artillery);
     }
diff --git a/MapsCollection.java b/MapsCollection.java
index 72a826c..3b90b3c 100644
--- a/MapsCollection.java
+++ b/MapsCollection.java
@@ -59,8 +59,6 @@ public class MapsCollection {
             for (var storage : _mapsStorage.entrySet()) {
                 writer.println(String.format("%s%c%s", storage.getKey(), separatorDict, storage.getValue().getData(separatorDict, separatorData)));
             }
-
-            writer.flush();
         }
 
         return true;
@@ -97,4 +95,75 @@ public class MapsCollection {
 
         return true;
     }
+
+    @SuppressWarnings("ResultOfMethodCallIgnored")
+    public boolean saveMap(String mapName, String filename) throws IOException {
+        File file = new File(filename);
+
+        if (file.exists()) {
+            file.delete();
+        }
+
+        file.createNewFile();
+
+        MapWithSetArtilleriesGeneric<IDrawingObject, AbstractMap> map = _mapsStorage.getOrDefault(mapName, null);
+
+        if (map == null) {
+            return false;
+        }
+
+        try (PrintWriter writer = new PrintWriter(file)) {
+            writer.println("Map");
+            writer.println(mapName);
+            writer.println(map.getMap().getClass().getSimpleName());
+
+            for (var artillery : map._setArtilleries.getArtilleries()) {
+                writer.println(artillery.getInfo());
+            }
+        }
+
+        return true;
+    }
+
+    public boolean loadMap(String filename) throws IOException {
+        File file = new File(filename);
+
+        if (!file.exists()) {
+            return false;
+        }
+
+        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
+            String currentLine = reader.readLine();
+
+            if (currentLine == null || !currentLine.contains("Map")) {
+                return false;
+            }
+
+            String mapName = reader.readLine();
+
+            MapWithSetArtilleriesGeneric<IDrawingObject, AbstractMap> map;
+            if (_mapsStorage.containsKey(mapName)) {
+                map = _mapsStorage.get(mapName);
+                if (!map.getMap().getClass().getSimpleName().equals(reader.readLine())) {
+                    return false;
+                }
+            } else {
+                map = switch (reader.readLine()) {
+                    case "SimpleMap" -> new MapWithSetArtilleriesGeneric<>(_pictureWidth, _pictureHeight, new SimpleMap());
+                    case "ForestMap" -> new MapWithSetArtilleriesGeneric<>(_pictureWidth, _pictureHeight, new ForestMap());
+                    default -> null;
+                };
+            }
+
+            map._setArtilleries.clear();
+
+            while ((currentLine = reader.readLine()) != null) {
+                map._setArtilleries.insert(DrawingObjectArtillery.create(currentLine));
+            }
+
+            _mapsStorage.put(mapName, map);
+        }
+
+        return true;
+    }
 }
diff --git a/SetArtilleriesGeneric.java b/SetArtilleriesGeneric.java
index 7b8c6d0..0293a7b 100644
--- a/SetArtilleriesGeneric.java
+++ b/SetArtilleriesGeneric.java
@@ -53,4 +53,8 @@ public class SetArtilleriesGeneric<T> {
     public Iterable<T> getArtilleries() {
         return () -> _places.stream().filter(Objects::nonNull).iterator();
     }
+
+    public void clear() {
+        _places.clear();
+    }
 }
-- 
2.25.1


From 8abded35c8395366fb175c05404cdbcbe2e0fd25 Mon Sep 17 00:00:00 2001
From: ChipsEater <sergpolevoi@yandex.ru>
Date: Tue, 22 Nov 2022 15:59:06 +0400
Subject: [PATCH 9/9] Fixes

---
 MapsCollection.java | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/MapsCollection.java b/MapsCollection.java
index 3b90b3c..016f466 100644
--- a/MapsCollection.java
+++ b/MapsCollection.java
@@ -147,6 +147,7 @@ public class MapsCollection {
                 if (!map.getMap().getClass().getSimpleName().equals(reader.readLine())) {
                     return false;
                 }
+                map._setArtilleries.clear();
             } else {
                 map = switch (reader.readLine()) {
                     case "SimpleMap" -> new MapWithSetArtilleriesGeneric<>(_pictureWidth, _pictureHeight, new SimpleMap());
@@ -155,8 +156,6 @@ public class MapsCollection {
                 };
             }
 
-            map._setArtilleries.clear();
-
             while ((currentLine = reader.readLine()) != null) {
                 map._setArtilleries.insert(DrawingObjectArtillery.create(currentLine));
             }
-- 
2.25.1