package arcade.controller; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import twitter4j.TwitterException; import util.FilePathFormatter; import arcade.database.Database; import arcade.exceptions.CorruptedDatabaseException; import arcade.exceptions.InvalidPaymentException; import arcade.exceptions.LoginErrorException; import arcade.exceptions.UsernameTakenException; import arcade.games.ArcadeInteraction; import arcade.games.Game; import arcade.games.GameData; import arcade.games.GameInfo; import arcade.games.UserGameData; import arcade.model.datapacket.UserSpecificData; import arcade.model.payment.PaymentManager; import arcade.model.social.TwitterConnection; import arcade.view.MainView; import arcade.view.forms.LoginView; public class Controller implements ArcadeInteraction { // Locations private static final String RESOURCE_LOCATION = "arcade.resources."; private static final String PAYMENT_MANAGER_LOCATION = "arcade.model.payment."; // Messages public static final String DEFAULT_LOGIN_MESSAGE = ""; // View private LoginView myLoginView; private MainView myView; // Resource private ResourceBundle myResources; // Models private Database myDb; private Map<String, GameInfo> myGameInfos; private Map<String, Collection<GameInfo>> userPurchasedGames; private Collection<GameInfo> myPurchasedGames; private PaymentManager myPaymentManager; private TwitterConnection myTwitter; private FilePathFormatter myFilePathFormatter = new FilePathFormatter(); private Game myCurrentGame; private GameInfo myCurrentGameInfo; public GameInfo getCurrentGameInfo() { return myCurrentGameInfo; } // Parameters private String myCurrentUser; private UserGameData myCurrentUserGameData; private GameData myCurrentGameData; public Controller(String language) { myResources = ResourceBundle.getBundle(RESOURCE_LOCATION + language); myDb = new Database(); myGameInfos = new HashMap<String, GameInfo>(); myPurchasedGames = new ArrayList<GameInfo>(); userPurchasedGames = new HashMap<String, Collection<GameInfo>>(); myLoginView = new LoginView(this, myResources); } /* * public Controller(ResourceBundle rb, String language) { myResources = rb; * myLanguage = language; } */ public void setLoginView(LoginView login) { myLoginView = login; } public void authenticate(String username, String password) throws LoginErrorException { if (loginCreteriaNotSatisfied(username, password)) { throw new LoginErrorException(); } myLoginView.dispose(); myCurrentUser = username; retrievePurchasedGames(username); organizeSnapshots(); myView = new MainView(this, myResources); } private void retrievePurchasedGames(String username) { if (!userPurchasedGames.containsKey(username)){ userPurchasedGames.put(username, new ArrayList<GameInfo>()); } myPurchasedGames = userPurchasedGames.get(username); } private boolean loginCreteriaNotSatisfied(String username, String password) { return !myDb.authenticateUsernameAndPassword(username, password); } private void organizeSnapshots() { List<String> gameNames = myDb.retrieveListOfGames(); for (String name : gameNames) { try { addNewGameInfoToList(name); } catch (MissingResourceException e) { continue; } } } private void addNewGameInfoToList(String gameName) throws MissingResourceException { GameInfo g = new GameInfo(myDb, gameName); myGameInfos.put(g.getName(), g); } /** * Create a new user profile by entering user-specific information. This * information is eventually stored in the database. * * @throws UsernameTakenException */ public void createNewUserProfile(UserSpecificData data) throws UsernameTakenException { if (usernameInDatabase(data.getUsername())) throw new UsernameTakenException(); myDb.createUser(data); try { String username = data.getUsername(); String password = data.getPassword(); authenticate(username, password); initializeUserGamePurchaseHistory(myCurrentUser); } catch (LoginErrorException e) { throw new CorruptedDatabaseException(); } } private void initializeUserGamePurchaseHistory(String username){ myPurchasedGames = new ArrayList<GameInfo>(); userPurchasedGames.put(username, myPurchasedGames); } // // Personalized Game-Center methods (trying without database) // // private void closeWriters(FileWriter fw, BufferedWriter bw) // throws IOException { // bw.close(); // fw.close(); // } // // private void closeReaders(FileReader fr, BufferedReader br) // throws IOException { // br.close(); // fr.close(); // } // // private void writeLine(BufferedWriter bw, String line) throws IOException { // bw.write(line); // bw.newLine(); // } // // private File createFileForLocation(String loc) { // File file = new File(loc); // if (file.exists()) { // try { // file.createNewFile(); // } catch (IOException e) { // e.printStackTrace(); // } // } // return file; // } // // private void copyFile(File origin, File target) throws IOException { // copyFile(origin, target, null); // } // // private void copyFile(File origin, File target, String newUser) // throws IOException { // FileReader fr = new FileReader(origin); // BufferedReader br = new BufferedReader(fr); // // FileWriter fw = new FileWriter(target); // BufferedWriter bw = new BufferedWriter(fw); // // String line; // while ((line = br.readLine()) != null) { // writeLine(bw, line); // } // if (newUser != null) // writeLine(bw, newUser); // closeWriters(fw, bw); // closeReaders(fr, br); // } // // private String formatUsernameForResourceFile(String username) { // return username + " ="; // } // // public void recordUserInPurchaseResourceFile(String username) // throws IOException { // File file1 = createFileForLocation(FILEWRITER_LOCATION); // File file2 = createFileForLocation(TMP_LOCATION); // copyFile(file2, file1, formatUsernameForResourceFile(username)); // copyFile(file1, file2); // } // // public void recordGamePurchaseHistory(String username, String gameName) // throws IOException { // File file1 = createFileForLocation(FILEWRITER_LOCATION); // File file2 = createFileForLocation(TMP_LOCATION); // replaceLine(file2, file1, username, gameName); // copyFile(file1, file2); // } // // private void replaceLine(File temp, File target, String username, // String gameName) throws IOException { // FileReader fr = new FileReader(temp); // BufferedReader br = new BufferedReader(fr); // // FileWriter fw = new FileWriter(target); // BufferedWriter bw = new BufferedWriter(fw); // // String line; // while ((line = br.readLine()) != null) { // if (line.contains(username)) // writeLine(bw, line + " " + gameName); // else // writeLine(bw, line); // } // closeWriters(fw, bw); // closeReaders(fr, br); // } // // public String[] getGamesForUser(String username) { // String games = userPurchaseHistory.getString(username); // return games.split(" "); // } /* * public void createNewUserProfile(String username, String pw, String * firstname, String lastname, String dateOfBirth) throws * UsernameTakenException { createNewUserProfile(username, pw, firstname, * lastname, dateOfBirth, NO_USER_IMAGE); } * * public void createNewUserProfile(String username, String pw, String * firstname, String lastname, String dateOfBirth, String imageFilePath) * throws UsernameTakenException { if (usernameInDatabase(username)) { throw * new UsernameTakenException(); } myDb.createUser(username, pw, firstname, * lastname, dateOfBirth, imageFilePath); try { authenticate(username, pw); * } catch (LoginErrorException e) { // this can't happen because just added * to db. throw new CorruptedDatabaseException(); } } */ private boolean usernameInDatabase(String username) { return myDb.usernameExists(username); } public void deleteUser(String username) { myDb.deleteUser(username); } /** * This should be called after a developer enters the information about his * / her game. The method will add the game entry to the database and create * a new GameInfo to display in the gamecenter. * * This sanitizes all the input so we guarantee that all names an genres are * lowercase on the backend. * * @param gameName * @param genre * @throws IOException */ /* * public void publish(GameSpecificData data){ myDb.createGame(data); * addNewGameInfoToList(data.getName()); } */ public void publish(String name, String genre, String author, double price, String extendsGame, String extendsMultiplayerGame, int ageRating, boolean singlePlayer, boolean multiplayer, String thumbnailPath, String adScreenPath, String description) { // Put info in DB myDb.createGame( name.toLowerCase(), genre.toLowerCase(), author, price, myFilePathFormatter.formatClassFilePath(extendsGame), myFilePathFormatter.formatClassFilePath(extendsMultiplayerGame), ageRating, singlePlayer, multiplayer, thumbnailPath, adScreenPath, description); // Put game info in map addNewGameInfoToList(name); } /** * First creates the appropriate PaymentManager for the transactionType if * the transactionType is Duke, then the DukePaymentManager is created. * * Then tries to complete the transaction with the paymentInfo. If the * transaction is unsuccessful, the InvalidPaymentExecption is thrown. * * @param transactionType * @param paymentInfo * @throws InvalidPaymentException */ public void performTransaction(GameInfo game, String transactionType, String[] paymentInfo) throws InvalidPaymentException { try { Class<?> paymentManagerClass = Class .forName(PAYMENT_MANAGER_LOCATION + transactionType); myPaymentManager = (PaymentManager) paymentManagerClass .newInstance(); } catch (ClassNotFoundException e) { throw new InvalidPaymentException(); } catch (InstantiationException e) { throw new InvalidPaymentException(); } catch (IllegalAccessException e) { throw new InvalidPaymentException(); } myPaymentManager.doTransaction(paymentInfo); updateGamePurchaseHistory(game); } private void updateGamePurchaseHistory(GameInfo game) { myPurchasedGames.add(game); userPurchasedGames.put(myCurrentUser, myPurchasedGames); } /** * Sets up a new twitter request to get access to a user's account. Returns * a URL that a user can access to authorize. * * @return * @throws TwitterException */ public String setUpTwitterRequest() throws TwitterException { myTwitter = new TwitterConnection(); return myTwitter.newRequest(); } /** * After the user authorizes the twitter request, s/he will have a pin. This * gets access using the provided pin, and sends a tweet containing text. * * @param pin * @param text * @throws TwitterException */ public void sendTweet(String pin, String text) throws TwitterException { myTwitter.sendTweet(pin, text); } /** * Rate a specific game, store in user-game database */ public void commentAndRateGame(String comment, double rating, String gameName) { myDb.insertCommentAndRating(myCurrentUser, gameName, comment, rating); } public void playGame(GameInfo gameinfo) { myCurrentGameInfo = gameinfo; myCurrentGame = gameinfo.getGame(this); myCurrentGame.run(); } /** * Get the list of games from the database. * * @return */ public Collection<GameInfo> getGameList() { return myGameInfos.values(); } /** * The collection of all games purchased by the user. Unfortunately, only * persists through current session, not saved in database. * * @return */ public Collection<GameInfo> getGamesPurchased() { return userPurchasedGames.get(myCurrentUser); //return myPurchasedGames; } /** * GameDetailPanel must call this method to get game-specific info. * * @param gameName * : name of the chosen game (String) * @return */ public GameInfo getGameDetail(String gameName) { return myGameInfos.get(gameName); } /** * UserProfile must call this method to retrieve User-specific information */ /** * TODO: Must add user-game specific detail * * @param user * , game (whatever that identifies the user and the game) * @return */ public UserGameData getUserGameData(Game game) { if (myCurrentUserGameData == null) { myCurrentUserGameData = myCurrentGameInfo.getUserGameData(game, myCurrentUser); } return myCurrentUserGameData; } @Override public void killGame() { int score = getCurrentUserGameData().getLastScore(); myDb.addNewHighScore(myCurrentUser, myCurrentGameInfo.getName(), score); myView.showEndGameView(score); myDb.storeUserGameData(getCurrentGame(), myCurrentUser, getCurrentUserGameData()); myCurrentGame = null; myCurrentGameInfo = null; } private UserGameData getCurrentUserGameData() { return myCurrentGameInfo.getUserGameData(myCurrentGame, myCurrentUser); } @Override public String getCurrentGame() { return myCurrentGameInfo.getName(); } @Override public GameData getGameData() { if (myCurrentGameData == null) { myCurrentGameData = myCurrentGameInfo.getGameData(myCurrentGame); } return myCurrentGameData; } }