diff --git a/Readme.md b/Readme.md index aa50c70..3896aec 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,7 @@ ### 1. Requirements python version 3.9 or higher ```bash -python -v +python3 -v ``` ### 2. Create virtual environments and install libs ```bash @@ -13,4 +13,37 @@ pip3 install -r requirements.txt ### 3. Run application ```bash python3 main.py -``` \ No newline at end of file +``` + +### 4. Arguments +Maps are saved in maps directory with json format.\ +It's two dimensional array of types of fields. \ +Example: +```json +[ + ["Corn", "Sunflower","Clay"], + ["Clay", "Soil","Clay"], + ["Sunflower", "Soil","Corn"] +] +``` +Warning! +Map must the same sizes what loaded map!\ +Change sizes map in config.py +```python +# Board settings: +VERTICAL_NUM_OF_FIELDS = 3 +HORIZONTAL_NUM_OF_FIELDS = 3 +``` +\ +#####4.1 Save generated map: +```bash +python main.py --save-map +``` +Map will be saved in maps directory. +Generated filename: map-uuid + +#####4.2 Load map +```bash +python main.py --load-map=name_of_map +``` +Map must be in the maps directory with json extension. \ No newline at end of file diff --git a/app/__init__.py b/app/__init__.py index 2354ad3..b5ae6fc 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -6,6 +6,7 @@ from threading import Event import pygame from config import * +from app.cmd_parser import Arg from app.graphsearch import Node from app.board import Board from app.tractor import Tractor @@ -14,11 +15,11 @@ from app.bfs import Bfs class App: - def __init__(self): + def __init__(self, args: list[Arg]): self.__running = True self.__screen = None self.__clock = None - self.__board = Board() + self.__board = Board(args=args) self.__tractor = Tractor(self.__board) self.__bot_is_running = Event() self.__moves = None diff --git a/app/board.py b/app/board.py index 27da7ff..ba98858 100644 --- a/app/board.py +++ b/app/board.py @@ -1,21 +1,30 @@ #!/usr/bin/python3 import copy +import json +import uuid import pygame import random +from app import Arg from app.fields import * from app.utils import get_class class Board: - def __init__(self, fields=None): + def __init__(self, fields=None, args: list[Arg] = None): if fields is None: fields = [] self.__fields = fields self.create_board() self.fill() self.generate_board() + if args is not None: + for arg in args: + if arg.get_arg_name() == SAVE_MAP: + self.save_map() + elif arg.get_arg_name() == LOAD_MAP: + self.load_map(arg.get_value()) # print(self.__fields) def get_fields(self) -> list: @@ -56,3 +65,59 @@ class Board: for j in range(VERTICAL_NUM_OF_FIELDS): print(f"{j} - {type(self.__fields[i][j]).__name__}", end=" | ") print() + + def convert_fields_to_list_of_types(self) -> list: + data = [] + for i in range(HORIZONTAL_NUM_OF_FIELDS): + data.append([]) + for j in range(VERTICAL_NUM_OF_FIELDS): + data[i].append(type(self.__fields[i][j]).__name__) + return data + + def convert_dict_map_to_list_map(self, dict_map: dict) -> list: + list_map = [] + for col in dict_map.values(): + list_map.append(copy.copy(col)) + return list_map + + def load_map(self, filename: str): + try: + with open(os.path.join(MAP_DIR,f"{filename}.{JSON}")) as f: + data = json.load(f) + except IOError: + raise IOError(f"Cannot load file: {filename}.{JSON}!") + + if data is None: + raise Exception("Cannot load json file") + + size_flag = True + # print(data) + if len(data) != HORIZONTAL_NUM_OF_FIELDS: + size_flag = False + for fields in data: + if len(fields) != VERTICAL_NUM_OF_FIELDS: + size_flag = False + if not size_flag: + raise Exception('Cannot load map! Incorrect size of map') + print("Map was successfully loaded!") + + # init map + for x in range(len(data)): + for y in range(len(data[x])): + field_type = data[x][y] + # print(field_type) + c = get_class("app.fields", field_type) + self.__fields[x][y] = c() + print("Map was successfully initialized!") + + def save_map(self) -> None: + if len(self.__fields) == 0: + raise Exception('Board is not initialized!') + + fields = self.convert_fields_to_list_of_types() + + try: + with open(os.path.join(MAP_DIR,f"{MAP_FILE_NAME}-{uuid.uuid4().hex}.{JSON}"), 'w') as f: + json.dump(fields, f) + except IOError: + raise IOError(f"Cannot save file:!") diff --git a/app/cmd_parser.py b/app/cmd_parser.py new file mode 100644 index 0000000..5620a4a --- /dev/null +++ b/app/cmd_parser.py @@ -0,0 +1,43 @@ +import sys +from config import * + + +class Arg: + def __init__(self, arg_name: str, value: str = None): + self.__arg_name = arg_name + self.__value = value + + def get_arg_name(self) -> str: + return self.__arg_name + + def get_value(self) -> str: + return self.__value + + +class CommandLineParser: + @staticmethod + def parse() -> list: + args = sys.argv[1:] + + results = [] + + if len(args) > 0: + for arg in args: + if arg == SAVE_MAP: + print("Saving map") + results.append(Arg(SAVE_MAP)) + + elif arg.find(LOAD_MAP, 0, len(LOAD_MAP)-1): + cmd = arg.split("=") + if len(cmd) == 2: + # print(cmd) + map_name = cmd[1] + print(f"Loading map: {map_name}") + results.append(Arg(LOAD_MAP, map_name)) + else: + raise Exception(f"Incorrect name of map: {cmd}!") + else: + raise Exception(f"Unknown arg {arg}") + # print(args) + + return results diff --git a/config.py b/config.py index 3b9c28d..eb06a0b 100644 --- a/config.py +++ b/config.py @@ -5,14 +5,14 @@ import os __all__ = ( 'WIDTH', 'HEIGHT', 'FIELD_SIZE', 'TIME_OF_MOVING', 'VERTICAL_NUM_OF_FIELDS', 'HORIZONTAL_NUM_OF_FIELDS', - 'FPS', 'CAPTION', 'RESOURCE_DIR', 'TRACTOR', 'PNG', + 'FPS', 'CAPTION', 'RESOURCE_DIR', 'MAP_DIR', 'TRACTOR', 'PNG', 'SAND', 'CLAY', 'GRASS', 'CORN', 'SUNFLOWER', 'FIELD_TYPES', 'TIME_OF_GROWING', 'AMOUNT_OF_CROPS', 'M_GO_FORWARD', 'M_ROTATE_LEFT', 'M_ROTATE_RIGHT', 'A_SOW', 'A_HARVEST', 'A_HYDRATE', 'A_FERTILIZE', 'A_DO_NOTHING', 'D_NORTH', 'D_EAST', 'D_SOUTH', 'D_WEST', - 'VALUE_OF_CROPS', 'VALUE_OF_PLANT', - 'VALUE_OF_SAND', 'VALUE_OF_CLAY' + 'VALUE_OF_CROPS', 'VALUE_OF_PLANT', 'VALUE_OF_SAND', 'VALUE_OF_CLAY', + 'MAP_FILE_NAME', 'JSON','SAVE_MAP', 'LOAD_MAP' ) # Board settings: @@ -29,10 +29,15 @@ CAPTION = 'Tractor' # Path BASE_DIR = os.path.dirname(__file__) RESOURCE_DIR = os.path.join(BASE_DIR, 'resources') +MAP_DIR = os.path.join(BASE_DIR, 'maps') +MAP_FILE_NAME = 'map' # Picture format PNG = "png" +# File format +JSON = 'json' + # Tractor settings TRACTOR = 'tractor' @@ -68,10 +73,14 @@ A_DO_NOTHING = "do nothing" # Costs fields: VALUE_OF_CROPS = 1 -VALUE_OF_PLANT = 3 +VALUE_OF_PLANT = 4 VALUE_OF_SAND = 7 VALUE_OF_CLAY = 10 # Times TIME_OF_GROWING = 2 TIME_OF_MOVING = 2 + +# Args +SAVE_MAP = '--save-map' +LOAD_MAP = '--load-map' diff --git a/main.py b/main.py index 0829046..0def039 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,8 @@ #!/usr/bin/python3 from app import App +from app.cmd_parser import CommandLineParser if __name__ == '__main__': - app = App() + args = CommandLineParser.parse() + app = App(args) app.run() diff --git a/maps/map-1.json b/maps/map-1.json new file mode 100644 index 0000000..7b60340 --- /dev/null +++ b/maps/map-1.json @@ -0,0 +1 @@ +[["Sunflower", "Corn", "Sand", "Sand", "Sand", "Sand", "Corn", "Sand", "Sunflower"], ["Grass", "Clay", "Clay", "Grass", "Grass", "Grass", "Corn", "Clay", "Sand"], ["Grass", "Clay", "Sunflower", "Corn", "Sand", "Sunflower", "Grass", "Corn", "Sand"], ["Grass", "Clay", "Corn", "Sand", "Sunflower", "Sand", "Grass", "Clay", "Grass"], ["Clay", "Corn", "Grass", "Sunflower", "Sunflower", "Corn", "Sunflower", "Grass", "Sand"], ["Clay", "Corn", "Corn", "Clay", "Corn", "Corn", "Grass", "Clay", "Clay"], ["Sand", "Sunflower", "Grass", "Corn", "Grass", "Sunflower", "Sand", "Sunflower", "Sand"], ["Corn", "Corn", "Sand", "Sunflower", "Sand", "Sand", "Clay", "Sunflower", "Sand"], ["Sunflower", "Corn", "Clay", "Sunflower", "Sunflower", "Sunflower", "Sunflower", "Sunflower", "Clay"], ["Grass", "Grass", "Corn", "Sand", "Sunflower", "Clay", "Clay", "Clay", "Sand"], ["Grass", "Clay", "Sand", "Corn", "Clay", "Corn", "Clay", "Corn", "Corn"], ["Corn", "Corn", "Grass", "Clay", "Sunflower", "Grass", "Sand", "Sand", "Sand"]] \ No newline at end of file diff --git a/maps/map-2.json b/maps/map-2.json new file mode 100644 index 0000000..77b4a68 --- /dev/null +++ b/maps/map-2.json @@ -0,0 +1 @@ +[["Corn", "Sunflower", "Corn", "Sand", "Grass", "Sunflower", "Sunflower", "Clay", "Sand"], ["Clay", "Sand", "Clay", "Grass", "Sand", "Clay", "Corn", "Sunflower", "Sand"], ["Sand", "Grass", "Grass", "Corn", "Grass", "Sand", "Corn", "Sunflower", "Clay"], ["Clay", "Sand", "Sunflower", "Sand", "Sunflower", "Corn", "Sunflower", "Corn", "Clay"], ["Corn", "Corn", "Clay", "Sand", "Clay", "Grass", "Clay", "Clay", "Grass"], ["Grass", "Sand", "Corn", "Sand", "Sand", "Sunflower", "Clay", "Sand", "Clay"], ["Sunflower", "Sand", "Grass", "Sand", "Sand", "Grass", "Grass", "Sand", "Corn"], ["Clay", "Sand", "Corn", "Sand", "Sunflower", "Clay", "Sunflower", "Grass", "Corn"], ["Sand", "Grass", "Sand", "Sand", "Clay", "Grass", "Sunflower", "Corn", "Corn"], ["Sand", "Sand", "Grass", "Grass", "Sand", "Corn", "Grass", "Sunflower", "Sand"], ["Clay", "Grass", "Clay", "Sand", "Grass", "Sunflower", "Corn", "Clay", "Sunflower"], ["Grass", "Grass", "Clay", "Corn", "Grass", "Clay", "Grass", "Clay", "Corn"]] \ No newline at end of file diff --git a/maps/map-3.json b/maps/map-3.json new file mode 100644 index 0000000..16f17e0 --- /dev/null +++ b/maps/map-3.json @@ -0,0 +1 @@ +[["Corn", "Grass", "Sand", "Corn", "Sand", "Clay", "Sunflower", "Corn", "Sunflower"], ["Sand", "Clay", "Clay", "Sunflower", "Sand", "Grass", "Corn", "Grass", "Sunflower"], ["Sunflower", "Clay", "Sunflower", "Sunflower", "Sand", "Sand", "Grass", "Corn", "Sand"], ["Sunflower", "Sunflower", "Grass", "Clay", "Sunflower", "Grass", "Sunflower", "Sunflower", "Grass"], ["Sunflower", "Corn", "Grass", "Sunflower", "Corn", "Corn", "Sand", "Corn", "Sunflower"], ["Clay", "Corn", "Corn", "Grass", "Sunflower", "Corn", "Grass", "Clay", "Corn"], ["Sand", "Sunflower", "Grass", "Grass", "Grass", "Clay", "Sand", "Sand", "Clay"], ["Sunflower", "Clay", "Grass", "Clay", "Corn", "Grass", "Grass", "Sand", "Sunflower"], ["Clay", "Corn", "Clay", "Grass", "Grass", "Sunflower", "Sand", "Corn", "Sand"], ["Sunflower", "Clay", "Grass", "Sand", "Clay", "Sunflower", "Corn", "Clay", "Sand"], ["Corn", "Sunflower", "Clay", "Clay", "Grass", "Sunflower", "Sand", "Corn", "Sunflower"], ["Grass", "Grass", "Corn", "Clay", "Sand", "Clay", "Grass", "Corn", "Sand"]] \ No newline at end of file