package magic.model.player; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.DirectoryStream.Filter; import java.nio.file.Files; import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import magic.ai.MagicAIImpl; import magic.utility.MagicFileSystem; import magic.utility.MagicFileSystem.DataPath; public final class PlayerProfiles { private PlayerProfiles() {} // default AI avatars. private static final Path AVATARS_PATH = MagicFileSystem.getDataPath(DataPath.AVATARS); private static final Path AVATAR_LesVegas = AVATARS_PATH.resolve("tux").resolve("tux25.png"); private static final Path AVATAR_MontyCarlo = AVATARS_PATH.resolve("default").resolve("face09.png"); private static final Path AVATAR_MiniMax = AVATARS_PATH.resolve("default").resolve("face18.png"); private static final Path profilesPath = MagicFileSystem.getDataPath(DataPath.PLAYERS); private static final HashMap<String, PlayerProfile> profilesMap = new HashMap<>(); static { refreshMap(); } public static void refreshMap() { profilesMap.clear(); // Humans for (Path path : getProfilePaths("human")) { final String profileId = path.getFileName().toString(); final HumanProfile player = new HumanProfile(profileId); profilesMap.put(profileId, player); } // AIs for (Path path : getProfilePaths("ai")) { final String profileId = path.getFileName().toString(); final AiProfile player = new AiProfile(profileId); profilesMap.put(profileId, player); } } private static List<Path> getProfilePaths(final String playerType) { final Path playersPath = profilesPath.resolve(playerType); List<Path> profilePaths = getDirectoryPaths(playersPath); if (profilePaths.isEmpty()) { try { if (playerType.equals("human")) { createDefaultHumanPlayerProfiles(); } else { createDefaultAiPlayerProfiles(); } profilePaths = getDirectoryPaths(playersPath); } catch (IOException e) { throw new RuntimeException(e); } } return profilePaths; } private static List<Path> getDirectoryPaths(final Path rootPath) { final List<Path> paths = new ArrayList<>(); if (Files.exists(rootPath)) { try (DirectoryStream<Path> ds = Files.newDirectoryStream(rootPath, new DirectoriesFilter())) { for (Path p : ds) { paths.add(p.getFileName()); } } catch (IOException e) { throw new RuntimeException(e); } } return paths; } private static class DirectoriesFilter implements Filter<Path> { @Override public boolean accept(Path entry) throws IOException { return Files.isDirectory(entry); } } public static void createDefaultHumanPlayerProfiles() throws IOException { final HumanProfile profile = HumanProfile.create(getDefaultPlayerProfileName()); profile.save(); } private static String getDefaultPlayerProfileName() { final String systemUserName = System.getProperty("user.name"); return systemUserName == null ? "Player" : systemUserName; } public static void createDefaultAiPlayerProfiles() throws IOException { createAiPlayerProfile("Les Vegas", MagicAIImpl.VEGAS, 6, PlayerProfiles.AVATAR_LesVegas); createAiPlayerProfile("Mini Max", MagicAIImpl.MMAB, 6, PlayerProfiles.AVATAR_MiniMax); createAiPlayerProfile("Monty Carlo", MagicAIImpl.MCTS, 6, PlayerProfiles.AVATAR_MontyCarlo); } private static void createAiPlayerProfile( final String name, final MagicAIImpl aiImpl, final int level, final Path avatarPath) { final AiProfile profile = AiProfile.create(name, aiImpl, level); profile.save(); setPlayerAvatar(profile, avatarPath); } public static void setPlayerAvatar(final PlayerProfile profile, final Path avatarPath) { final Path targetPath = profile.getProfilePath().resolve("player.avatar"); try { Files.copy(avatarPath, targetPath, StandardCopyOption.REPLACE_EXISTING); } catch (NoSuchFileException ex) { System.err.println(ex); } catch (IOException ex) { throw new RuntimeException(ex); } } public static PlayerProfile getDefaultHumanPlayer() { return getHumanPlayerProfiles().values().iterator().next(); } public static PlayerProfile getDefaultAiPlayer() { for (PlayerProfile profile : getAiPlayerProfiles().values()) { final AiProfile aiProfile = (AiProfile) profile; if (aiProfile.getAiType() == MagicAIImpl.MCTS) { return profile; } } // No MCTS profile exists which can happen when importing // previous set of players and default AI profiles have // been deleted or changed by user. (see github issue #329). return getAiPlayerProfiles().values().iterator().next(); } private static HashMap<String, PlayerProfile> getPlayerProfiles(final Class<? extends PlayerProfile> profileClass) { final HashMap<String, PlayerProfile> filteredProfiles = new HashMap<>(); for (PlayerProfile profile : profilesMap.values()) { if (profile.getClass().equals(profileClass)) { filteredProfiles.put(profile.getId(), profile); } } return filteredProfiles; } public static HashMap<String, PlayerProfile> getHumanPlayerProfiles() { return getPlayerProfiles(HumanProfile.class); } public static HashMap<String, PlayerProfile> getAiPlayerProfiles() { return getPlayerProfiles(AiProfile.class); } /** * @param duelConfigId * @return */ public static PlayerProfile getPlayerProfile(String duelConfigId) { return profilesMap.get(duelConfigId); } public static HashMap<String, PlayerProfile> getPlayerProfiles() { return profilesMap; } public static void deletePlayer(final PlayerProfile playerProfile) { MagicFileSystem.deleteDirectory(getPlayerProfileDirectory(playerProfile)); profilesMap.remove(playerProfile.getId()); } private static Path getPlayerProfileDirectory(final PlayerProfile playerProfile) { return profilesPath.resolve(playerProfile.getPlayerType()).resolve(playerProfile.getId()); } public static boolean canDeleteProfile(final PlayerProfile playerProfile) { return getPlayerProfiles(playerProfile.getClass()).size() > 1; } }