// Path: src/main/java/pl/joegreen/sergeants/api/response/GameStartApiResponse.java
// @Value
// public class GameStartApiResponse {
//     /**
//      * Index of bot's player.
//      */
//     private int playerIndex;
//     /**
//      * Replay identifier. Use http://bot.generals.io/replays/{replayId} to see the replay in your browser.
//      */
//     @JsonProperty("replay_id")
//     private String replayId;
//     /**
//      * Identifier of the main chat room, useful when sending a chat message ({@link GeneralsApi#sendChatMessage(String, String)}).
//      */
//     @JsonProperty("chat_room")
//     private String chatRoom;
//     /**
//      * Identifier of the team chat room, useful when sending a chat message ({@link GeneralsApi#sendChatMessage(String, String)}).
//      * Can be null if there are no teams in the game.
//      */
//     @JsonProperty("team_chat_room")
//     private String teamChatRoom;
//     /**
//      * Array of player names, indexed by player index.
//      */
//     private String[] usernames;
//     /**
//      * Array if team identifiers of each player, indexed by player index. Can be null if there are no teams/
//      */
//     private Integer[] teams;
// 
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/api/response/GameUpdateApiResponse.java
// @Value
// public class GameUpdateApiResponse {
//     private int turn;
//     /**
//      * Diff to update the array with map (tiles/armies) representation. Use {@link MapPatcher} to apply the diff.
//      */
//     @JsonProperty("map_diff")
//     private int[] mapDiff;
//     /**
//      * Diff to update the array with cities representation. Use {@link MapPatcher} to apply the diff.
//      */
//     @JsonProperty("cities_diff")
//     private int[] citiesDiff;
//     /**
//      * Array of indexes of generals, indexed with player index. If general of player is not visible/does not exist, contains -1 in appropriate position.
//      */
//     private int[] generals;
//     /**
//      * Officially "the attackIndex field is unnecessary for bots -- it's used by our client to show/hide attack arrows when appropriate."
//      * Some people say it can be used to find out state of moves queue and plan more complex moves ;-)
//      */
//     private int attackIndex;
//     /**
//      * Array indexed by player index, includes things shown in the score table (titles, army, is dead). Does not include stars.
//      */
//     private ScoreApiResponse[] scores;
//     private double[] stars;
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/api/response/ScoreApiResponse.java
// @Value
// public class ScoreApiResponse {
//     /**
//      * Number of map tiles owned.
//      */
//     private int tiles;
//     /**
//      * Total army size.
//      */
//     private int total;
//     /**
//      * Player index.
//      */
//     @JsonProperty("i")
//     private int index;
//     /**
//      * True if player already lost.
//      */
//     private boolean dead;
// 
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/api/util/MapPatcher.java
// public class MapPatcher {
// 
//     public static int[] patch(int[] patch, int[] old) {
//         ArrayList<Integer> newArrayList = new ArrayList<>();
//         int patchIndex = 0;
//         while (patchIndex < patch.length) {
//             //matching
//             int matchingElements = patch[patchIndex++];
//             int startingIndex = newArrayList.size();
//             for (int oldIndex = startingIndex; oldIndex < startingIndex + matchingElements; ++oldIndex) {
//                 if (oldIndex < old.length) {
//                     newArrayList.add(old[oldIndex]);
//                 } else {
//                     newArrayList.add(0);
//                 }
//             }
// 
//             //mismatching
//             if (patchIndex < patch.length) {
//                 int misMatchingElements = patch[patchIndex++];
//                 while (misMatchingElements > 0) {
//                     newArrayList.add(patch[patchIndex++]);
//                     misMatchingElements--;
//                 }
//             }
//         }
//         return newArrayList.stream().mapToInt(i -> i).toArray();
//     }
// }


import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import pl.joegreen.sergeants.api.response.GameStartApiResponse;
import pl.joegreen.sergeants.api.response.GameUpdateApiResponse;
import pl.joegreen.sergeants.api.response.ScoreApiResponse;
import pl.joegreen.sergeants.api.util.MapPatcher;
import pl.joegreen.sergeants.framework.model.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
    }

    @Override
    public int getAttackIndex() {
        return attackIndex;
    }

    @Override
    public ImmutableMap<Position, Field> getFieldsMap() {
        return fieldsMap;
    }

    @Override
    public ImmutableMap<Position, VisibleField> getVisibleFieldsMap() {
        return visibleFieldsMap;
    }

    @Override
    public ImmutableList<Player> getPlayers() {
        return players;
    }

    @Override
    public GameStarted getGameStartedData() {
        return new GameStartedApiResponseImpl(startData);
    }


    private static ImmutableList<Player> createPlayersInfo(GameStartApiResponse startData, GameUpdateApiResponse firstUpdateData) {
        int numberOfPlayers = startData.getUsernames().length;
// Path: src/main/java/pl/joegreen/sergeants/api/response/GameStartApiResponse.java
// @Value
// public class GameStartApiResponse {
//     /**
//      * Index of bot's player.
//      */
//     private int playerIndex;
//     /**
//      * Replay identifier. Use http://bot.generals.io/replays/{replayId} to see the replay in your browser.
//      */
//     @JsonProperty("replay_id")
//     private String replayId;
//     /**
//      * Identifier of the main chat room, useful when sending a chat message ({@link GeneralsApi#sendChatMessage(String, String)}).
//      */
//     @JsonProperty("chat_room")
//     private String chatRoom;
//     /**
//      * Identifier of the team chat room, useful when sending a chat message ({@link GeneralsApi#sendChatMessage(String, String)}).
//      * Can be null if there are no teams in the game.
//      */
//     @JsonProperty("team_chat_room")
//     private String teamChatRoom;
//     /**
//      * Array of player names, indexed by player index.
//      */
//     private String[] usernames;
//     /**
//      * Array if team identifiers of each player, indexed by player index. Can be null if there are no teams/
//      */
//     private Integer[] teams;
// 
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/api/response/GameUpdateApiResponse.java
// @Value
// public class GameUpdateApiResponse {
//     private int turn;
//     /**
//      * Diff to update the array with map (tiles/armies) representation. Use {@link MapPatcher} to apply the diff.
//      */
//     @JsonProperty("map_diff")
//     private int[] mapDiff;
//     /**
//      * Diff to update the array with cities representation. Use {@link MapPatcher} to apply the diff.
//      */
//     @JsonProperty("cities_diff")
//     private int[] citiesDiff;
//     /**
//      * Array of indexes of generals, indexed with player index. If general of player is not visible/does not exist, contains -1 in appropriate position.
//      */
//     private int[] generals;
//     /**
//      * Officially "the attackIndex field is unnecessary for bots -- it's used by our client to show/hide attack arrows when appropriate."
//      * Some people say it can be used to find out state of moves queue and plan more complex moves ;-)
//      */
//     private int attackIndex;
//     /**
//      * Array indexed by player index, includes things shown in the score table (titles, army, is dead). Does not include stars.
//      */
//     private ScoreApiResponse[] scores;
//     private double[] stars;
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/api/response/ScoreApiResponse.java
// @Value
// public class ScoreApiResponse {
//     /**
//      * Number of map tiles owned.
//      */
//     private int tiles;
//     /**
//      * Total army size.
//      */
//     private int total;
//     /**
//      * Player index.
//      */
//     @JsonProperty("i")
//     private int index;
//     /**
//      * True if player already lost.
//      */
//     private boolean dead;
// 
// }
// 
// Path: src/main/java/pl/joegreen/sergeants/api/util/MapPatcher.java
// public class MapPatcher {
// 
//     public static int[] patch(int[] patch, int[] old) {
//         ArrayList<Integer> newArrayList = new ArrayList<>();
//         int patchIndex = 0;
//         while (patchIndex < patch.length) {
//             //matching
//             int matchingElements = patch[patchIndex++];
//             int startingIndex = newArrayList.size();
//             for (int oldIndex = startingIndex; oldIndex < startingIndex + matchingElements; ++oldIndex) {
//                 if (oldIndex < old.length) {
//                     newArrayList.add(old[oldIndex]);
//                 } else {
//                     newArrayList.add(0);
//                 }
//             }
// 
//             //mismatching
//             if (patchIndex < patch.length) {
//                 int misMatchingElements = patch[patchIndex++];
//                 while (misMatchingElements > 0) {
//                     newArrayList.add(patch[patchIndex++]);
//                     misMatchingElements--;
//                 }
//             }
//         }
//         return newArrayList.stream().mapToInt(i -> i).toArray();
//     }
// }


// Path: src/main/java/pl/joegreen/sergeants/framework/model/api/UpdatableGameState.java
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import pl.joegreen.sergeants.api.response.GameStartApiResponse;
import pl.joegreen.sergeants.api.response.GameUpdateApiResponse;
import pl.joegreen.sergeants.api.response.ScoreApiResponse;
import pl.joegreen.sergeants.api.util.MapPatcher;
import pl.joegreen.sergeants.framework.model.*;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

    }

    @Override
    public int getAttackIndex() {
        return attackIndex;
    }

    @Override
    public ImmutableMap<Position, Field> getFieldsMap() {
        return fieldsMap;
    }

    @Override
    public ImmutableMap<Position, VisibleField> getVisibleFieldsMap() {
        return visibleFieldsMap;
    }

    @Override
    public ImmutableList<Player> getPlayers() {
        return players;
    }

    @Override
    public GameStarted getGameStartedData() {
        return new GameStartedApiResponseImpl(startData);
    }


    private static ImmutableList<Player> createPlayersInfo(GameStartApiResponse startData, GameUpdateApiResponse firstUpdateData) {
        int numberOfPlayers = startData.getUsernames().length;
        Map<Integer, ScoreApiResponse> scoresMap = createScoresMap(firstUpdateData);