Android Open Source - wherewithal Game Concentration Activity






From Project

Back to project page wherewithal.

License

The source code is released under:

GNU General Public License

If you think the Android project wherewithal listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.curchod.wherewithal;
/*from  ww  w  .  ja va2s. c o  m*/
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.UnsupportedEncodingException;
  import java.util.Date;
  import java.util.Enumeration;
  import java.util.Hashtable;
  import java.util.Vector;

  import org.xmlpull.v1.XmlPullParser;
  import org.xmlpull.v1.XmlPullParserFactory;

  import android.app.Activity;
  import android.app.AlertDialog;
  import android.app.Dialog;
  import android.app.PendingIntent;
  import android.content.Context;
  import android.content.DialogInterface;
  import android.content.DialogInterface.OnDismissListener;
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.IntentFilter.MalformedMimeTypeException;
  import android.graphics.drawable.ColorDrawable;
  import android.nfc.NdefMessage;
  import android.nfc.NdefRecord;
  import android.nfc.NfcAdapter;
  import android.nfc.tech.MifareClassic;
  import android.os.AsyncTask;
  import android.os.Bundle;
  import android.os.Handler;
  import android.os.Parcelable;
  import android.util.Log;
  import android.view.LayoutInflater;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.SubMenu;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.animation.Animation;
  import android.view.animation.AnimationUtils;
  import android.widget.ArrayAdapter;
  import android.widget.ListAdapter;
  import android.widget.ListView;
  import android.widget.TableLayout;
  import android.widget.TableLayout.LayoutParams;
  import android.widget.TableRow;
  import android.widget.TextView;
  import android.widget.Toast;

  import com.curchod.domartin.Constants;
  import com.curchod.domartin.IWantTo;
  import com.curchod.domartin.TagDescription;
  import com.curchod.domartin.UtilityTo;
  import com.curchod.dto.Card;
  import com.curchod.dto.Game;
  import com.curchod.dto.PlayerInfo;

  /**
   * Based on ReadingStonesActivity.
   * Players will match cards on a grid with reading and writing cards separated.
   * 
   * When the user clicks on the Reading Stones button, the onClick calls loadGameFile() 
   * which in turn calls checkForGameReady() and then fillIntentAndStartNewActivity() before the thread ends.  
   * At the end the next GameReadingStonesActivity is started.
   * 
   * We call loadCardsFile()followed by loadPlayers().  If there is no players.xml file yet,
   * we create that and populate it with the player id's retrieved from the intent.
   * We use the normal method of number_of_players indicating how many times to iterate 
   * through the player_ids in the intent.  So we load their id's like this:
   * 0player_id= *id*
   * 1player_id= *id*
   * The loadPlayers() will also create PlayerInfo objects for players that are listed in the game
   * file and hence passed in in the intent, but not in the players.xml file because they
   * haven't logged in.  
   * 
   * Each time a NFC tag is detected, onNewIntent(Intent intent) is called.  This
   * method then calls resolveIntent3 which gets the NDEF messages, and extracts the record
   * with the card id.  This we call getId to associate that with a card from the cards file.
   * 
   * When a tag/card is scanned, onNewIntent(Intent intent) gets called.
   * This method simply calls resolveIntent.  This method gets an array of NDEF Messages, 
   * which is used to get an array of NDEF Records, of which the one in the 0 position contains the tag id.  
   * When found, the associateWithCardsFile method is called.
   * This method tried to associate the tag id with an id in the cards.xml file.
   * Due to hidden characters in the tag message, we use the removeHiddenCharacters 
   * so that we can match the tag id with the card id.
   * If the card is a registered game card, foundGameCard(Card) is called with that card as an arg.
   * This method decides what to do with the card, 
   * If it's a played card,  we show toast.
   * If it's a new card, call fistCard().
   * If it's not a new card, then we check to see what part of the turn the player is at and act accordingly.
   * 
   * When a match is found, updateTurnCards() is called.
   * if it is the second card scanned, dismiss the dialog and call showCards() followed by checkForMatch().
   * If the player tried to match two cards that don't, both words from those cards are shown in a contemplation window.
   * 
   * The score is incremented by the number of matches in each turn.  First pair is 1, second pair so the score goes up 2,
   * then the third match in a turn goes up three.  The score is kept in the global game_file object.
   * When the onCreate method is called, which will also happen if the device is rotated, the game file is
   * loaded again using an inner asynchronous task that then updates the score board when it completes.
   * 
   * After a player has matched all their cards, the game enters the final round.  Remaining players can
   * match their left over cards for 1 point each per match.  
   * @author Administrator
   *
   */
  public class GameConcentrationActivity extends Activity 
  {
    
    private static final String DEBUG_TAG = "GameReadingStonesActivity";
    private String test_id;
    private String test_name;
    private String test_status;
    private String class_id;
    NfcAdapter mfc_adapter;
    PendingIntent pending_intent;
    String[][] tech_lists_array;    
    IntentFilter ndef_filer;
    IntentFilter filters[];
    final Context context = this;
    //private String card_message;
    ArrayAdapter<TagDescription> a_adapter;
    Hashtable <String,Card> cards;
    private static final int right_card_id = 1;
      private static final int wrong_card_id = 2;
      private static final int icon_group = 1;
      private static final int instructions_menu_item_id = 3;
      private static final int reset_game_menu_item_id = 4;
      Hashtable <String,Card> played_cards;
      /** During each players turn, scanned cards are kept in this list.*/
      Vector <Card> turn_cards;
      /** This will hold all the card ids a players scans during their turn.*/
      Vector <String> turn_card_ids;
      ArrayAdapter<String> array_dapter;
      private Dialog list_dialog;
      private ListAdapter list_adapter;
      /** This stores two consecutive scanned cards to see if they match.*/
      private Vector <Card> card_pairs;
      /** When the cards.xml file is loaded, cards with the status set to played are added here.
       * Also, if the player matches two cards, both card ids are added to played_card_ids.*/
      private Vector <String> played_card_ids;
      /** This holds the player info objects from the players.xml file. */
      private Hashtable <String,PlayerInfo> players;
      /** This holds the player ids from the intent.*/
      private Vector <String>player_ids;
      private Hashtable <String, String> id_player_names;
      /** To hold the currently tag-scanning player id */
      private String current_player_id;      // ditto
      private String previously_played_card_id; // the gentlemanly way to do this
      private String previously_played_card_player_id;
      private String previously_played_word_id;     //
      private String previously_played_word_type;     //
      private Card previous_card;
      /** This holds the player names and scores */
      private TableLayout table;
      private int number_of_matches;
      private long last_turn_time;
      private Game game_file;
      /** After a player has one, the remaining players have a chance to match their remaining cards and get 1 point for each match when this has been set.*/
      private boolean final_round;
      /** Used to change the game status from ready to underway to final_round.*/
      private TextView game_status;
      private boolean end_game;
      /** We count the cards each time to calculate this.  If you have a better idea let us know.*/
      private int number_of_words;
      /** This will hold the number of matches a player has to find the winner*/
      private Hashtable <String, Double> id_player_matches;
      
    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_game_reading_stones);
      String method = "onCreate";
      String build = "build 177";
      Log.i(DEBUG_TAG, method+": "+build);
      setup();
      getIntentInfo();
      setTitle(test_name);
      mfc_adapter = NfcAdapter.getDefaultAdapter(this);
      pending_intent = PendingIntent.getActivity(this, 0,
                  new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
      ndef_filer = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
          try
          { 
            ndef_filer.addDataType("*/*");
          } catch (MalformedMimeTypeException e) 
          {
            Log.i(DEBUG_TAG, method+": ndef_filer.addDataType fail");
              throw new RuntimeException("fail", e);
          }
          filters = new IntentFilter[] {ndef_filer,};
          tech_lists_array = new String[][] { new String[] { MifareClassic.class.getName() } };
          setupGameObject();
          printGame(game_file, ": game file after setup.");
          loadCardsFile();
          loadPlayers();
          if (cards.size()!=0)
          {
            number_of_words = cards.size()/players.size();
          }
          Log.i(DEBUG_TAG, method+": number_of_words "+number_of_words);
          try
          {
            //printGame(game_file, ": game file before setup.");
          } catch (java.lang.NullPointerException npe)
          {
            Log.i(DEBUG_TAG, method+": game file npe");
          }
          createScoreboard();
          new AsyncLoadGameFileTask().execute("");
    }
    
    /**
     * Load the game file in the background, then call updateScoreFromGame in the 
     * onPostExecute method after the file is loaded.
     * @author user
     *
     */
    private class AsyncLoadGameFileTask extends AsyncTask <String, String, Game> 
    {  
      //private String debug = "YourCustomAsyncTask";
          @Override  
          protected void onPreExecute() 
          {  
              
          }  

          @Override  
          protected Game doInBackground(String ... String) 
          {
            //String method = "doInBackground";
            //Log.i(DEBUG_TAG, method+" start");
            IWantTo i_want_to = new IWantTo(context);
              Game result_game = i_want_to.loadTheGameFile();
              //Log.i(DEBUG_TAG, method+" we got game "+result_game.getTestName());
        return result_game;  
          } 

          @Override  
          protected void onPostExecute(Game result_game) 
          {  
            //String method = "onPostExecute";
            //Log.i(DEBUG_TAG, method+" finished");
            updateScoreFromGame(result_game);
          }  
    }
    
    /**
     * Take the scores from the status element of the result_game passed in as an argument
     * and replace the PlayerInfo object score.
     * @param result_game
     */
    private void updateScoreFromGame(Game result_game)
      {
        String method = "updateScoreFromGame";
        printGame(result_game, method+": result_game");
        Log.i(DEBUG_TAG, method+": game file before overwite");
        printGame(game_file, method+": game_file");
        game_file = result_game;
        Hashtable <String,PlayerInfo> temp_players = new Hashtable<String,PlayerInfo>();
        Enumeration<String> e = players.keys();
        Log.i(DEBUG_TAG, method+" players size "+players.size());
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        PlayerInfo this_player_info = players.get(key);
        String this_player_id = this_player_info.getId();
        PlayerInfo new_player_info = new PlayerInfo();
        String player_status = "0";
        try
        {
          player_status = game_file.getPlayerStatus(this_player_id); 
          new_player_info = players.get(key);
          printPlayerInfo(new_player_info, "new player info");
          //player_status = Integer.toString(new_player_info.getScore());
          Log.i(DEBUG_TAG, method+" player_status "+player_status);
        } catch  (java.lang.NullPointerException npe)
        {
          Log.i(DEBUG_TAG, method+" no score yet.  start at 0");
        }
        try
        {
          this_player_info.setScore(Integer.parseInt(player_status));
        } catch (java.lang.NumberFormatException nfe)
        {
          this_player_info.setScore(0);
        }
        printPlayerInfo(this_player_info, "this player info");
        //temp_players.put(this_player_id, this_player_info);
        temp_players.put(this_player_id, new_player_info);
        Log.i(DEBUG_TAG, method+" player_id "+this_player_id+" set score "+this_player_info.getScore());
      }
      players = temp_players;
      try
      {
        table.removeAllViews();
        createScoreboard();
      } catch (java.lang.NullPointerException npe)
      {
        Log.i(DEBUG_TAG, method+" no players to put in the scoreboard");
      }
      }
    
    /**
     * We create this table each time there is an update to a players score.
     * Using the list of ids in id_player_names we get the PlayerInfo and 
     * retrieve the score and the name and put them in a two column table.
     */
    private void createScoreboard()
    {
      Enumeration<String> e = id_player_names.keys();
      while (e.hasMoreElements())
      {
        table = (TableLayout) findViewById(R.id.TableLayout01);
            TableRow row = new TableRow(this);
        String key = e.nextElement();
        String name = id_player_names.get(key);
        PlayerInfo info = players.get(key);
        int score = info.getScore();
        TextView player_name_view = new TextView(this);
            TextView player_score_view = new TextView(this);   
            player_name_view.setText(name);
            player_score_view.setText(score+"");
            row.addView(player_name_view);
            row.addView(player_score_view);
            table.addView(row,new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
      }
      updateGameStatus();
    }
    
    /**
     *     <string name="game_ready">Game Ready</string>
       *     <string name="playing">Playing</string>
       *     <string name="final_round">Final Round</string>
       *     <string name="game_over">Game Over</string>
     */
    private void updateGameStatus()
    {
      String method = "updateGameStatus";
      String status_string = game_file.getTestStatus();
      if (status_string == null)
      {
        Log.i(DEBUG_TAG, method+" status is null");
      } else if (status_string.equals("setup"))
      {
        game_status.setText(R.string.game_ready);
        Log.i(DEBUG_TAG, method+" game ready");
      } else if (status_string.equals(Constants.GAME_OVER))
      {
        game_status.setText(R.string.game_over);
        Log.i(DEBUG_TAG, method+" game over");
      } else if (status_string.equals(Constants.FINAL_ROUND))
      {
        game_status.setText(R.string.final_round);
        Log.i(DEBUG_TAG, method+" final round");
      } else if (status_string.equals(Constants.PLAYING))
      {
        game_status.setText(R.string.playing);
        Log.i(DEBUG_TAG, method+" playing");
      }
    }
    
    /**
     * Initialize all the global variables before they are used.
     */
    private void setup()
    {
      game_status = (TextView)findViewById(R.id.text_view_game_status);
      turn_cards = new Vector<Card>();
      turn_card_ids = new Vector <String>();
          card_pairs = new Vector<Card>();
          played_card_ids = new Vector<String>();
          players = new Hashtable <String,PlayerInfo>();
          player_ids = new Vector<String>();
          id_player_names = new Hashtable<String, String>();
          current_player_id = "";
          previously_played_card_player_id = "";
          previously_played_word_id = "";   //
          previously_played_word_type = "";  
          previously_played_card_id = "";
          mock_word_counter = 0;
          final_round = false;
          id_player_matches = new Hashtable <String, Double> ();
    }
    
    /**
     * We call intent.getParcelableArrayExtra on the intent to return a Parcelable array
     * which holds NdefMessage objects which are the raw_messages.  We loop through all these
     * and cast them to NdefMessage objects and create an array of ndef_messages.
     * From this array we get an array of NdefRecords, which we loop thru to get each individual
     * record.  Since all we are looking for is a string of numbers representing a long card id
     * we simply call record.getPayload() on each record.  We only write to sector 1,
     * so we get the string id from the first record object.
     * This is sent to getIds to associate a card from the card file with that id.
     * @param intent
     */
    private void resolveIntent(Intent intent)
    {
      String method = "resolveIntent3";
      Parcelable[] raw_messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
      NdefMessage[] ndef_messages = null;
      if (raw_messages != null) 
      {
        Log.i(DEBUG_TAG, method+" rawMsgs != null");
        ndef_messages = new NdefMessage[raw_messages.length];
          for (int i = 0; i < raw_messages.length; i++) 
          {
            NdefMessage ndef_message = (NdefMessage)raw_messages[i];
              //Log.i(DEBUG_TAG, "i "+i+" ndef_message = "+ndef_message.toString());
              ndef_messages[i] = (NdefMessage) raw_messages[i];
          }
      } else
      {
        //Log.i(DEBUG_TAG, method+" raw_messages == null, or it's a virtual device");
        String test_card_type = (String)intent.getExtras().getString("test_card");
        getTestCard(test_card_type);
      }
      try
      {
        NdefRecord[] records = ndef_messages[0].getRecords();
        final int size = records.length;
        for (int i = 0; i < size; i++) 
        {
          NdefRecord record = records[i];
          String message = new String(record.getPayload());
          //Log.i(DEBUG_TAG, method+" "+i+" message "+message);
          if (i==0)
          {
            associateWithCardsFile(message);
          }
        }
      } catch (java.lang.NullPointerException npe)
      {
        Log.i(DEBUG_TAG, method+" NPE getting records");
        npe.printStackTrace();
      } catch (java.lang.ArrayIndexOutOfBoundsException aioobe)
      {
        Log.i(DEBUG_TAG, method+" AIOOBE getting records");
        aioobe.printStackTrace();
      }
    }
    
    /**
     * We had a problem with hidden characters, probably from the encoding and language info set into the tags.
     * This allows only numbers and a '-' character representing the long stored in the cards.xml file.
     * @param message
     * @return
     */
    private String removeHiddenCharacters(String message)
    {
      String dash = "-";
      char d = dash.charAt(0);
      StringBuffer sb = new StringBuffer();
      //Log.i(DEBUG_TAG, "printCharacters");
      for (int i = 0; i < message.length(); i++)
      {
        char c = message.charAt(i);
        //Log.i(DEBUG_TAG, i+" char "+c);
        if (Character.isDigit(c))
        {
          sb.append(c);
        } else if (c == d)
        {
          sb.append(d);
        }
      }
      String result = new String(sb);
      //Log.i(DEBUG_TAG, " result "+result);
      return result;
    }
    
    /**
     * Go through the cards.xml file and add game cards to the turn_cards Vector.
     * 
     * @param tag_id
     */
    private void associateWithCardsFile(String tag_id)
    {
      String method = "associateWithCardsFile";
      //Log.i(DEBUG_TAG, method+" tag_id to match "+tag_id+" from "+cards.size()+" cards.");
      tag_id.trim();
      Enumeration<String> e = cards.keys();
      while (e.hasMoreElements())
      {
        String this_card_id = e.nextElement();
        this_card_id.trim();
        String card_id_str = UtilityTo.encodeThisString(this_card_id, "UTF-8");
        String tag_id_str = removeHiddenCharacters(tag_id);
              //Log.i(DEBUG_TAG, method+" to card_id_str "+card_id_str);
        if (card_id_str.equals(tag_id_str))
        {
          Card matching_card = cards.get(this_card_id);
          foundGameCard(matching_card);
          break;
          
        }
      }
    }
    
    /**
     * All the branching needed when a card is scanned is done in one convenient method.
     * @param game_card
     */
    private void foundGameCard(Card game_card)
    {
      String method = "foundGameCard";
      current_player_id = game_card.getPlayerId();
      updateGameStatus();
      Log.i(DEBUG_TAG, method+" previously_played_card_player_id "+previously_played_card_player_id);
      Log.i(DEBUG_TAG, method+" current_player_id "+current_player_id);
      Log.i(DEBUG_TAG, method+" number_of_matches "+number_of_matches);
      if (end_game)
      {
        Log.i(DEBUG_TAG, method+" no more cards please.");
        Toast.makeText(this, "Game Over.  Reset to play again.", Toast.LENGTH_LONG ).show();
      } else if (played_card_ids.contains(game_card.getCardId()))
      {
        Toast.makeText(this, com.curchod.wherewithal.R.string.card_already_played, Toast.LENGTH_LONG ).show();
      } else
      {
        if (previously_played_card_player_id.equals(""))
        {
          Log.i(DEBUG_TAG, method+" first card in turn");
          firstCard(game_card);
        } else
        {
          // second card
          if (samePlayer(game_card.getPlayerId()))
          {
            if (sameWord(game_card.getWordId(), game_card.getWordType()))
            {
              Log.i(DEBUG_TAG, method+" same player, same word, match");
              int new_score = updateScore(game_card.getPlayerId());
                Toast.makeText(this, "Match! Score "+new_score, Toast.LENGTH_LONG ).show();
                updateAndSavePlayerAndGameInfo(game_card, new_score);
              resetAfterMatch();
            } else if (previously_played_word_id.equals("")&&number_of_matches>0)
            {
              Log.i(DEBUG_TAG, method+" first card after match");
              firstCard(game_card);
            } else
            {
              Log.i(DEBUG_TAG, method+" same player wrong word: contemplation");
              showContemplationPopup(game_card);
              resetTurn();
            }
          } else
          {
            Log.i(DEBUG_TAG, method+" different player.  first word");
            resetTurn();
            firstCard(game_card);
          }
        }
      }
      checkForEndOfTurn();
    }
    
    private void checkForEndOfTurn()
    {
      long current_time = new Date().getTime();
      long elapsed_time = current_time - last_turn_time;
      if (elapsed_time> 15000)
      {
        previously_played_card_player_id = "";
        resetTurn();
      } else
      {
        last_turn_time = current_time;
      }
    }
    
    private void resetTurn()
    {
        previously_played_word_id = "";
        previously_played_word_type = "";
        previously_played_card_id = "";
        previously_played_card_player_id = "";
        previous_card = new Card();
        number_of_matches = 0;
        turn_cards = new Vector<Card>();
        Toast.makeText(this, "Your turn is over.", Toast.LENGTH_LONG ).show();
    }
    
    private void firstCard(Card game_card)
    {
      String method = "firstCard";
      previously_played_word_type = game_card.getWordType();
      previously_played_word_id = game_card.getWordId();
      previously_played_card_player_id = game_card.getPlayerId();
      previously_played_card_id = game_card.getCardId();
      current_player_id = game_card.getPlayerId();
      previous_card = game_card;
      Log.i(DEBUG_TAG, method+" set up to show cards");
      turn_cards.add(game_card);
      turn_card_ids.add(game_card.getCardId());
      card_pairs.add(game_card);
      showCards();
      last_turn_time = new Date().getTime();
    }
    
    private void resetAfterMatch()
    {
        previously_played_word_id = "";
        previously_played_word_type = "";
        previously_played_card_id = "";
    }
    
    private boolean samePlayer(String game_card_player_id)
    {
      if (game_card_player_id.equals(previously_played_card_player_id))
      {
        return true;
      } else
      {
        return false;
      }
    }
    
    /**
     * Retuns false even if the card is the same as before.
     * Only returns true if it is the opposite type
     * @param game_card_id
     * @param game_card_type
     * @return
     */
    private boolean sameWord(String game_card_id, String game_card_type)
    {
      if (game_card_id.equals(previously_played_word_id))
      {
        if (previously_played_word_type.equals(game_card_type))
        {
          // same card again, right?
          return false;
        } else 
        {
          return true;
        }
      } else
      {
        return false;
      }
        
    }
    
    /**
     * Update card and game status.
     * reset set previous_player_id and previous_card_id
     * increment matches.
     * Save the the game.xml file using the status element as the score.
     * If any card has status yet-to-be-played then end_game is set to false.
     * @param game_card
     */
    private void updateAndSavePlayerAndGameInfo(Card game_card, int new_score)
    {
      String method = "updateAndSavePlayerAndGameInfo";
      addScoreToPlayerInfo(new_score, game_card.getPlayerId());
      turn_cards.add(game_card);
      turn_card_ids.add(game_card.getCardId());
      card_pairs.add(game_card);  // do we use this?  think not..
      double current_player_matches = id_player_matches.get(current_player_id); 
      current_player_matches = current_player_matches + 1;
      id_player_matches.put(current_player_id, current_player_matches); // increment this playrs matches.
        if (list_adapter != null)
        {
            played_card_ids.add(game_card.getCardId());
            played_card_ids.add(previously_played_card_id);
            Hashtable <String,Card> new_cards = new Hashtable <String,Card> ();
            end_game = true;  // if any cards are unplayed, we will set this to false again.
            Enumeration<String> e = cards.keys();
          while (e.hasMoreElements())
          {
            String key = e.nextElement();
            Card card = cards.get(key);
            String this_id = card.getCardId();
            updatePlayerMatchesStatus(card);
            card = setCardStatus(this_id, game_card, card);
            new_cards.put(this_id, card);
          }
          Log.i(DEBUG_TAG, method+" number_of_words "+number_of_words);
          cards = new_cards;
          checkForChangeOfStatus();
          showCards();
          saveCardsFile();
          IWantTo i_want_to = new IWantTo(context);
          updateGameObject();
              i_want_to.saveTheGameFile(game_file, class_id);
              if (end_game)
              {
                winner();
              }
        } else
        {
          Log.i(DEBUG_TAG, method+" list_adapter is null");
        }
    }
    
    /**
     * Compare the total number of matches for the current player with the
     * collected matches held in id_player_matches.
     * @param current_player_matches
     */
    private void checkForChangeOfStatus()
    {
      String method = "checkForChangeOfStatus";
      double player_matches = id_player_matches.get(current_player_id);
      Log.i(DEBUG_TAG, method+" if "+player_matches+" >= "+number_of_words);
      if (player_matches>=number_of_words)
      {
        String player_name = id_player_names.get(current_player_id);
        Toast.makeText(this, player_name+" finished. Final round.", Toast.LENGTH_LONG ).show();
        final_round = true;
        game_status.setText(R.string.final_round);
        game_file.setTestStatus(Constants.FINAL_ROUND);
        Log.i(DEBUG_TAG, method+" start final_round.");
      } else
      {
        Log.i(DEBUG_TAG, method+" number_of_words "+number_of_words+" player_matches "+player_matches);
        String game_status = game_file.getTestStatus();
        Log.i(DEBUG_TAG, method+" game_status: "+game_status);
        if (game_status.equals(Constants.GAME_READY))
        {
          game_file.setTestStatus(Constants.PLAYING);
          Log.i(DEBUG_TAG, method+" game_status: changed to "+game_status);
        }
      }
    }
    
    /**
     * If any card is yet to be played end_game is set to false.
     * We count the cards for the current player to determine how many cards it takes
     * to finish.
     * @param card
     */
    private void updatePlayerMatchesStatus(Card card)
    {
      String method = "updatePlayerMatchesStatus";
      if (card.getCardStatus().equals(Constants.YET_TO_BE_PLAYED))
      {
        end_game = false;
      }
    }
    
    private Card setCardStatus(String this_id, Card game_card, Card card)
    {
      String method = "setCardStatus";
      if (this_id.equals(game_card.getCardId()) || this_id.equals(previously_played_card_id))
      {
        card.setCardStatus(Constants.PLAYED);
        Log.i(DEBUG_TAG, method+" card "+this_id+" played "+card.getCardStatus()+" end_game "+end_game);
      } else
      {
        //Log.i(DEBUG_TAG, method+" card "+this_id+" status "+card.getCardStatus()+" end_game "+end_game);
      }
      return card;
    }
    
    /**
     * To do: this is the place to send info about the win to the learning record store.
     */
    private void winner()
    {
      String method = "winner";
      int highest_score = 0;
      String winner_name = null;
      Enumeration<String> e = id_player_names.keys();
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        String name = id_player_names.get(key);
        PlayerInfo info = players.get(key);
        int score = info.getScore();
        if (score > highest_score)
        {
          highest_score = score;
          winner_name = name;
        }
        Log.i(DEBUG_TAG, method+" score "+highest_score+" for "+winner_name);
      }
        Toast.makeText(this, winner_name+" won!  Final round over.", Toast.LENGTH_LONG ).show();
        game_status.setText(R.string.game_over);
        game_file.setTestStatus(Constants.GAME_OVER);
    }
    
    private void addScoreToPlayerInfo(int new_score, String scoring_player_id)
    {
      String method = "addScoreToPlayerInfo";
      Hashtable<String,String> player_statuses = game_file.getPlayerStatus();
      Log.i(DEBUG_TAG, method+" player_statuses "+player_statuses);
      Enumeration<String> e = player_statuses.keys();
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        String score = player_statuses.get(key);
        Log.i(DEBUG_TAG, method+" key "+key+" score "+score);
        PlayerInfo player_info = players.get(scoring_player_id);
        if (player_info.getId().equals(scoring_player_id))
        {
          player_info.setScore(new_score);
          Log.i(DEBUG_TAG, method+" update player "+player_info.getId()+" score to "+new_score);
          game_file.setPlayerStatus(key, score);
          replacePlayerInfoForPlayer(player_info);
          break;
        }
      }
      updateScoreFromGame(game_file);
    }
    
    private void replacePlayerInfoForPlayer(PlayerInfo player_info)
    {
      String method = "replacePlayerInfoForPlayer";
      Hashtable <String,PlayerInfo> temp_players = new Hashtable<String,PlayerInfo>();
        Enumeration<String> e = players.keys();
        //Log.i(DEBUG_TAG, method+" players size "+players.size());
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        PlayerInfo this_player_info = players.get(key);
        String this_player_id = this_player_info.getId();
        if (this_player_id.equals(player_info.getId()))
        {
          //Log.i(DEBUG_TAG, method+" update player "+this_player_id+" with new score "+player_info.getScore());
          temp_players.put(this_player_id, player_info);
        } else
        {
          //Log.i(DEBUG_TAG, method+" copying player "+this_player_id+" with old score "+this_player_info.getScore());
          temp_players.put(this_player_id, this_player_info);
        }    }
      players = temp_players;
    }
    
    /**
       * Helper method for onOptionsItemSelected.
       * @param right_or_wrong
       * @return
       */
      private NdefRecord getCardRecord(String right_or_wrong)
      {
        Enumeration<String> e = cards.keys();
          String key = e.nextElement();
          Card card = cards.get(key);
      NdefRecord  record = null;
      try 
      {
        if (right_or_wrong.equals("right"))
        {
          record = createMockRecord2(card.getCardId(), card.getText());
        } else
        {
          record = createMockRecord(card.getCardId(), card.getDefinition());
        }
      } catch (UnsupportedEncodingException uee) 
      {
        // TODO Auto-generated catch block
        uee.printStackTrace();
      }
      return record;
      }
      
      /**
       * Show a popup with the text and definition for both card pairs that do not match 
       * and let the user 'contemplate' their mistake for 20 seconds, then dismiss it.
       */
      private void showContemplationPopup(Card card2)
      {
        String method = "showContempationPopup";
        if (list_adapter != null)
        {
        list_dialog.dismiss();
      }
        String text1 = previous_card.getText();
        String def1 = previous_card.getDefinition();
        String text2 = card2.getText();
        String def2 = card2.getDefinition();
        //Log.i(DEBUG_TAG, method+" display "+def1+" and "+def1);
        LayoutInflater layout_inflater = LayoutInflater.from(context);
        ViewGroup group = (ViewGroup)findViewById(R.id.contemplation_linear_layoutB);
        final View popup_view = layout_inflater.inflate(R.layout.game_reading_contemplation_window, group);
      final AlertDialog.Builder alert_dialog_builder = new AlertDialog.Builder(context);
      alert_dialog_builder.setView(popup_view);
      final TextView text_view_1 = (TextView) popup_view.findViewById(R.id.textA);
      final TextView def_view_1 = (TextView) popup_view.findViewById(R.id.defA);
      final TextView text_view_2 = (TextView) popup_view.findViewById(R.id.textB);
      final TextView def_view_2 = (TextView) popup_view.findViewById(R.id.defB);
      text_view_1.setText(text1);
      def_view_1.setText(def1);
      text_view_2.setText(text2);
      def_view_2.setText(def2);
      final AlertDialog alert_dialog = alert_dialog_builder.create();
      alert_dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
          alert_dialog.show();
          Handler handler = new Handler(); 
          startSlideA(popup_view);
          handler.postDelayed(new Runnable() 
          { 
               public void run() 
               { 
                 startSlideB(popup_view);
               } 
          }, 5000); 
          handler.postDelayed(new Runnable() 
          { 
               public void run() 
               { 
                 alert_dialog.dismiss();
               } 
          }, 15000); 
      }
      
      private void startSlideA(View popup_view)
    {
      TextView def_view_1 = (TextView) popup_view.findViewById(R.id.defA);
          //Animation def_1_an =  AnimationUtils.loadAnimation(this, R.anim.diagonal_slide);
          //def_view_1.startAnimation(def_1_an);
    }
      
      private void startSlideB(View popup_view)
    {
      TextView def_view_2 = (TextView) popup_view.findViewById(R.id.defB);
          //Animation def_2_an =  AnimationUtils.loadAnimation(this, R.anim.diagonal_slide);
          //def_view_2.startAnimation(def_2_an);
    }
      
      /**
       * Increment player score, copy new hash to old hash, then save the players file.
       * Return the new score;
       * @param player_id
       */
      private int updateScore(String player_id)
      {
        String method = "updateScore";
        PlayerInfo player_info = players.get(player_id);
        int score = player_info.getScore();
        Log.i(DEBUG_TAG, method+" score before update "+score);
        previously_played_word_id = "";
        score = incrementScore(score);
        player_info.setScore(score);
        Hashtable <String,PlayerInfo> temp_players = new Hashtable<String,PlayerInfo>();
        Enumeration<String> e = players.keys();
        Log.i(DEBUG_TAG, method+" players size "+players.size());
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        PlayerInfo this_player_info = players.get(key);
        String this_player_id = this_player_info.getId();
        if (player_id.equals(this_player_id))
        {
          player_info.setScore(score);
          game_file.setPlayerStatus(player_id, Integer.toString(score));
          temp_players.put(player_id, player_info);
          Log.i(DEBUG_TAG, method+" player_id.equals(this_player_id) update score to "+score);
        } else
        {
          temp_players.put(this_player_id, this_player_info);
          Log.i(DEBUG_TAG, method+" player_id "+this_player_id+" score "+this_player_info.getScore());
        }
      }
      players = temp_players;
        table.removeAllViews();
        createScoreboard();
        return score;
      }
      
      /**
       * During the final round, each matched pair only increments the score by 1.
       * Otherwise, new_score = score + number_of_matches.
       * @param score
       * @return
       */
      private int incrementScore(int score)
      {
        int new_score = 0;
        if (final_round)
        {
          number_of_matches++;
            new_score = score + 1;
          
        } else
        {
          number_of_matches++;
            new_score = score + number_of_matches;
        }
        return new_score;
      }
      
      /**
       * Set everything back to what it should be before the game started.
       */
      private void resetGame()
      {
        String method = "resetGame";
        Log.i(DEBUG_TAG, method+" starting new game");
        resetAndSavePlayers();
        table.removeAllViews();
        createScoreboard();
        resetAndSaveCards();
      IWantTo i_want_to = new IWantTo(context);
      //printGame(game_file, "");
          setupGameObject();
          game_file.setTestStatus(Constants.READY);
          i_want_to.saveTheGameFile(game_file, class_id);
          played_cards = new Hashtable <String,Card> ();
          turn_cards = new Vector <Card> ();
          turn_card_ids = new Vector <String> ();
          card_pairs =  new Vector <Card> ();
          played_card_ids =  new Vector <String> ();
          previously_played_word_id = "";
        previously_played_word_type = "";
        previously_played_card_id = "";
        previously_played_card_player_id = "";
        previous_card = new Card();
        number_of_matches = 0;
        final_round = false;
        game_status.setText(R.string.game_ready);
      }
      
      private void resetAndSavePlayers()
      {
        String method = "resetPlayers";
        id_player_matches = new Hashtable <String, Double> ();
        Hashtable <String,PlayerInfo> temp_players = new Hashtable<String,PlayerInfo>();
        Enumeration<String> e = players.keys();
        //Log.i(DEBUG_TAG, method+" players size "+players.size());
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        PlayerInfo this_player_info = players.get(key);
        id_player_matches.put(key, (double)0);
        this_player_info.setScore(0);
        temp_players.put(this_player_info.getId(), this_player_info);
      }
      players = temp_players;
      savePlayersFile();
      }
      
      /**
       * Set all cards to 'yet_to_be_played'.
       */
      private void resetAndSaveCards()
      {
        String method = "resetCards";
        Hashtable <String,Card> cards_copy = new Hashtable <String,Card> ();
        Enumeration<String> e = cards.keys();
      while (e.hasMoreElements())
      {
        String this_card_id = e.nextElement();
        Card this_card = cards.get(this_card_id);
        //Log.i(DEBUG_TAG, method+" set card "+this_card.getDefinition()+" from "+this_card.getCardStatus()+" to yet to be played");
        this_card.setCardStatus(Constants.YET_TO_BE_PLAYED);
        cards_copy.put(this_card_id, this_card);
      }
      cards = cards_copy;
      saveCardsFile();
      }
      
      /**
       * This happens the at the start when the activity is created, or the game is reset. 
       */
      private void setupGameObject()
      {
        String method = "setupGameObject";
        printGame(game_file, method+" game_file before setup");
        game_file = new Game();
        game_file.setTestFormat("reading_stones");
        game_file.setTestId(test_id);
        game_file.setTestName(test_name);
        game_file.setTestType(Constants.READING);
        setGameStatus();
        Hashtable <String,String> player_id_status = new Hashtable<String,String>();
        Enumeration<String> e = players.keys();
        //Log.i(DEBUG_TAG, method+" players size "+players.size());
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        PlayerInfo player_info = players.get(key);
        player_id_status.put(player_info.getId(), player_info.getScore()+"");
        Log.i(DEBUG_TAG, method+" setting up "+player_info.getId()+" player status "+player_info.getScore());
      }
      game_file.setPlayerStatus(player_id_status);
      printGame(game_file, method+" game_file after setup");
      }
      
      /**
       * This happens every time a match is made. 
       */
      private void updateGameObject()
      {
        String method = "setupGameObject";
        printGame(game_file, method+" game_file before setup");
        setGameStatus();
        Hashtable <String,String> player_id_status = new Hashtable<String,String>();
        Enumeration<String> e = players.keys();
        //Log.i(DEBUG_TAG, method+" players size "+players.size());
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        PlayerInfo player_info = players.get(key);
        player_id_status.put(player_info.getId(), player_info.getScore()+"");
        Log.i(DEBUG_TAG, method+" setting up "+player_info.getId()+" player status "+player_info.getScore());
      }
      game_file.setPlayerStatus(player_id_status);
      printGame(game_file, method+" game_file after setup");
      }
      
      
      /**
       * As soon as a match is made the status is changed to playing, 
       * unless the final_round or end_game flag is set.
       */
      private void setGameStatus()
      {
        if (final_round)
        {
          game_file.setTestStatus(Constants.FINAL_ROUND);
        } else if (end_game)
        {
          game_file.setTestStatus(Constants.GAME_OVER);
        } else
        {
          // leave status the way it is.  It's either not ready, ready, or playing.
        }
      }
      
      /**
       * Create the dialog to show a list of scanned cards.
       * This will provide a list of the current turn cards for a single player
       * until a card from a new player is scanned and a new list starts.
       */
      private void showCards()
      {
        String method = "showCards";
        if (list_adapter != null)
        {
        list_dialog.dismiss();
      }
        list_dialog = new Dialog(this);
        String player_name = id_player_names.get(current_player_id);
        list_dialog.setTitle("Player "+player_name);
          LayoutInflater li = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
          View v = li.inflate(R.layout.game_reading_stones_popup, null, false);
          list_dialog.setContentView(v);
          list_dialog.setCancelable(true);
          list_dialog.setOnDismissListener(new OnDismissListener()
          {
            @Override
              public void onDismiss(final DialogInterface arg0) 
            {
              //resetTurn();
              }
          });
          //Log.i(DEBUG_TAG, method+" turn_cards "+turn_cards.size());
          String[] val = new String [turn_cards.size()];
          for (int i = 0; i < turn_cards.size(); i++)
          {
            Card card = turn_cards.get(i);
            String card_name = card.getCardId();
            String card_id = card.getIndex();
            val [i] = UtilityTo.getWord(card);
          }
          ListView list1 = (ListView) list_dialog.findViewById(R.id.popup_listview);
          list_adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, val);
          list1.setAdapter(list_adapter);
          list_dialog.show();
      }
      
      /**
       * For testing.  Currently this doesn't work?
       * @param card_id
       * @param word
       * @return
       * @throws UnsupportedEncodingException
       */
      private NdefRecord createMockRecord(String card_id, String word) throws UnsupportedEncodingException 
      {
        String method = "createMockRecord";
        Log.i(DEBUG_TAG, method);
          String lang = "en";
          String card_info = card_id+"@"+word;
          Log.i(DEBUG_TAG, method+" card_info "+card_info);
          byte [] card_bytes = card_info.getBytes();
          byte [] lang_bytes = lang.getBytes("UTF-8");
          int lang_length = lang_bytes.length;
          int card_info_length = card_bytes.length;
          Log.i(DEBUG_TAG, method+" lang_leng "+lang_length+" "+card_info_length);
          byte [] payload = new byte[1 + lang_length + card_info_length];
          payload[0] = (byte) lang_length;
          System.arraycopy(lang_bytes, 0, payload, 1, lang_length);
          System.arraycopy(card_bytes, 0, payload, 1 + lang_length, card_info_length);
          NdefRecord recordNFC = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
          byte [] payload1 = recordNFC.getPayload();
          Log.i(DEBUG_TAG, method+": payload check "+payload1.length);
          return recordNFC;
    }
      
      /**
       * For testing in a virtual device.
       * @param card_id
       * @param word
       * @return
       * @throws UnsupportedEncodingException
       */
      private NdefRecord createMockRecord2(String card_id, String word) throws UnsupportedEncodingException 
      {
        String method = "createMockRecord";
          String card_info = "en"+card_id+"@"+word;
          Log.i(DEBUG_TAG, method+" card_info "+card_info);
          byte [] card_bytes = card_info.getBytes();
          int card_info_length = card_bytes.length;
          Log.i(DEBUG_TAG, method+" info length "+card_info_length);
          byte [] payload = new byte[1 + card_info_length];
          UtilityTo.printBytes(payload, "payload");
          System.arraycopy(card_bytes, 0, payload, 1, card_info_length);
          NdefRecord recordNFC = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
          byte [] payload1 = recordNFC.getPayload();
          Log.i(DEBUG_TAG, method+": payload length "+payload1.length);
          UtilityTo.printBytes(payload1, "payload1");
          return recordNFC;
    }
      
      /**
       * Lload the cards.xml file and then call parseCards to do it.
       * We need to know what the last element in the card will be to finish each card object.
       * Right now, this is definition.
       * The full format is:
       *  <cards>
       *     <card>
       *         <card_id>
       *         <player_id>
       *         <player_name>
       *         <player_icon>
       *         <word_id>
       *         <word_type>
       *         <word_category>
       *         <text>
       *         <definition>
       *     </card> 
       *     ...
       * </cards>
       */
      private void parseCards()
      {
        final String method = "parseCards"; 
        //Log.i(DEBUG_TAG, method+": start parse");
        new Thread() 
        {
              public void run() 
              {
                FileInputStream fis = null;
          try 
          {
            fis = openFileInput(Constants.CARDS_XML);
            Log.i(DEBUG_TAG, method+": fis "+fis.available());
          } catch (FileNotFoundException e1) 
          {
            Log.i(DEBUG_TAG, method+": fnfe");
            e1.printStackTrace();
          } catch (java.io.IOException ioe)
          {
            Log.i(DEBUG_TAG, method+": ioe");
            ioe.printStackTrace();
          }
                  try 
                  {
                    Card card = new Card();
                    String tag = "";
                      XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
                      XmlPullParser parser = parserCreator.newPullParser();
                      parser.setInput(fis, null);
                      int parser_event = parser.getEventType();
                      while (parser_event != XmlPullParser.END_DOCUMENT) 
                      {
                          switch (parser_event) 
                          {
                          case XmlPullParser.TEXT:
                            if (true)
                            {
                              if (tag!=null)
                              {
                                String value = parser.getText();
                                if (tag.equals("card_id"))
                                {
                                  card.setCardId(value);
                                  //Log.i(DEBUG_TAG, "parsed card id: "+tag+" "+value);
                                } else if (tag.equals("player_id"))
                                {
                                  card.setPlayerId(value);
                                  player_ids.add(value);
                                  //Log.i(DEBUG_TAG, "parsed: "+tag+" "+value);
                                } else if (tag.equals("card_status"))
                                {
                                  card.setCardStatus(value);
                                  if (value.equals(Constants.PLAYED))
                                  {
                                    played_card_ids.add(card.getCardId());
                                    //Log.i(DEBUG_TAG, "card played");
                                  }
                                  //Log.i(DEBUG_TAG, "parsed: "+tag+" "+value);
                                } else if (tag.equals("player_name"))
                                {
                                  card.setPlayerName(value);
                                  //Log.i(DEBUG_TAG, "parsed: "+tag+" "+value);
                                } else if (tag.equals("word_id"))
                                {
                                  card.setWordId(value);
                                  //Log.i(DEBUG_TAG, "parsed: "+tag+" "+value);
                                } else if (tag.equals("word_type"))
                                {
                                  card.setWordType(value);
                                  //Log.i(DEBUG_TAG, "parsed: word_type "+tag+" "+value);
                                } else if (tag.equals("word_category"))
                                {
                                  card.setWordCategory(value);
                                  //Log.i(DEBUG_TAG, "parsed: "+tag+" "+value);
                                } else if (tag.equals("text"))
                                {
                                  card.setText(value);
                                  //Log.i(DEBUG_TAG, "parsed: "+tag+" "+value);
                                } else if (tag.equals("definition"))
                                {
                                  card.setDefinition(value);
                                  cards.put(card.getCardId(),card);
                                  //Log.i(DEBUG_TAG, method+" put "+card.getCardId()+" "+UtilityTo.getWord(card));
                                  card = new Card();
                                }
                              }
                              tag = null;
                            }
                            //Log.i(DEBUG_TAG, method+": parser.getText() "+parser.getText());
                              
                          case XmlPullParser.START_TAG:
                            tag = parser.getName();
                            //Log.i(DEBUG_TAG, "catpture set "+tag);
                          }
                          parser_event = parser.next();
                      }
                  } catch (Exception e) 
                  {
                    Log.i(DEBUG_TAG, method+": (not) exception(al)");
                    e.printStackTrace();
                  }
              }
        }.start();
        //Log.i(DEBUG_TAG, method+": finished");
      }
      
      /**
     * Set the test name id and status form intent.
     */
    private void getIntentInfo()
    {
      player_ids = new Vector<String>();
      id_player_names = new Hashtable<String, String>();
      String method = "getIntentInfo";
      Intent sender = getIntent();
      test_id = sender.getExtras().getString("test_id");
      test_name = sender.getExtras().getString("test_name"); // test_name
      test_status = sender.getExtras().getString("test_status");
      try
      {
        int number_of_players = Integer.parseInt(sender.getExtras().getString("number_of_players"));
        class_id = sender.getExtras().getString("class_id");
        for (int i = 0; i < number_of_players; i++)
        {
          String player_id =  sender.getExtras().getString(i+"player_id");
          String player_name =  sender.getExtras().getString(i+"player_name");
          //Log.i(DEBUG_TAG, method+" retrieved player id "+player_id+", player name "+player_name);
          id_player_names.put(player_id, player_name);
          player_ids.add(player_id);
        }
        //Log.i(DEBUG_TAG, method+" got test_name "+test_name+" test_status "+test_status+" test_id "+test_id);
      } catch (java.lang.NumberFormatException nufie)
      {
        Log.i(DEBUG_TAG, method+" NuFiE!");
        nufie.printStackTrace();
      }
    }
    
      /**
       * This method sets up whats needed to open the cards.xml file. 
       * If the file doesn't exist yet, create it.
       * Then call the parseCards() method.
       */
      private void loadCardsFile()
      {
        String method = "loadCardsFile";
        cards = new Hashtable <String,Card>();
        Context context = getApplicationContext();
        String file_path = context.getFilesDir().getAbsolutePath();//returns current directory.
        //Log.i(DEBUG_TAG, method+": file_path - "+file_path);
        File file = new File(file_path, Constants.CARDS_XML);
        boolean exists = file.exists();
        if (exists == false)
        {
          // what do we do if there is no file yet?
          Toast.makeText(this, "Please set up cards brefore game play", Toast.LENGTH_LONG ).show();
          //Log.i(DEBUG_TAG,"create new cards.xml file?");
        } else
        {
           //parseCards();
              IWantTo i_want_to = new IWantTo(context);
              cardsVectorToHash(i_want_to.loadCardsFile());
          if (cards.size() == 0)
            {
              // game not ready
            game_status.setText(R.string.game_not_ready);
              game_file.setTestStatus(Constants.GAME_NOT_READY);
              try
              {
                createScoreboard();
              } catch (java.lang.NullPointerException npe)
              {
                // game chose, no players yet, skip showing the scoreboard.
                updateGameStatus();
              }
            Toast.makeText(this, "No cards.  Please set up cards brefore game play", Toast.LENGTH_LONG ).show();
              //Log.i(DEBUG_TAG,"no cards!");
            }
        }
      }
      
      private void cardsVectorToHash(Vector <Card> cards_vector)
      {
        String method = "cardsVectorToHash";
        for (int i = 0; i < cards_vector.size(); i++)
        {
          Card card = cards_vector.get(i);
          cards.put(card.getCardId(), card);
          if (card.getCardStatus().equals(Constants.PLAYED))
          {
            try
              {
              double matches = id_player_matches.get(card.getPlayerId());
              matches = matches + .5;
              id_player_matches.put(card.getPlayerId(), matches);
              } catch (java.lang.NullPointerException npe)
              {
                Log.i(DEBUG_TAG, method+" npe at "+i);
                id_player_matches.put(card.getPlayerId(), Double.parseDouble("0.0"));
              }  
          } else if (card.getCardStatus().equals(Constants.YET_TO_BE_PLAYED))
          {
              
          }
          Log.i(DEBUG_TAG, method+" npe at "+i);
        }
        if (end_game)
        {
          game_status.setText(R.string.game_over);
            game_file.setTestStatus(Constants.GAME_OVER);
        }
      }
      
      /**
       * Save all the card info in the card.xml file, which has the following format:
       * We use the file_cards vector which represents cards from the cards we read and write.
       * <cards>
       *     <card>
       *         <card_id>
       *         <player_id>
       *         <player_name>
       *         <player_icon>
       *         <word_id>
       *         <word_type>
       *         <word_category>
       *         <text>
       *         <definition>
       *     </card> 
       *     ...
       * </cards>
       */
      private void saveCardsFile()
      {
        String method = "savedCardsFile";
          //Log.i(DEBUG_TAG, method);
        try 
        {
          FileOutputStream fos = openFileOutput(Constants.CARDS_XML, Context.MODE_PRIVATE);
          //Log.i(DEBUG_TAG, method+": FD "+fos.getFD());
            try
            {
              StringBuffer sb = new StringBuffer();
          sb.append("<cards>");
          Enumeration<String> e = cards.keys();
          while (e.hasMoreElements())
          {
            String key = e.nextElement();
            Card card = cards.get(key);
            sb.append("<card>");
              sb.append("<card_id>"+card.getCardId()+"</card_id>");
              sb.append("<card_status>"+card.getCardStatus()+"</card_status>");
              sb.append("<player_id>"+card.getPlayerId()+"</player_id>");
              sb.append("<player_name>"+card.getPlayerName()+"</player_name>");
              sb.append("<player_icon>"+card.getPlayerIcon()+"</player_icon>");
              sb.append("<word_id>"+card.getWordId()+"</word_id>");
              sb.append("<word_type>"+card.getWordType()+"</word_type>");
              sb.append("<word_category>"+card.getWordCategory()+"</word_category>");
              sb.append("<text>"+card.getText()+"</text>");
              sb.append("<definition>"+card.getDefinition()+"</definition>");
            sb.append("</card>");
            //Log.i(DEBUG_TAG, " card.getCardId(): "+card.getCardId()+" word "+UtilityTo.getWord(card));
          }
          sb.append("</cards>");
          //Log.i(DEBUG_TAG, method+" writing "+new String(sb));
          fos.write(new String(sb).getBytes());
          fos.close();
          //Log.i(DEBUG_TAG, method+": done");
             }catch (FileNotFoundException e)
            {
                Log.e(DEBUG_TAG, "FileNotFoundException");
        } catch (IOException e1) 
        {
          Log.e(DEBUG_TAG, "IOException");
          e1.printStackTrace();
        }
      } catch (IOException e) 
      {
        e.printStackTrace();
      }
      }
      
      /**
       * Setup to parse the players.xml file.  If there is no file, create one and populate it
       * with the info in the game file and asign random icons to players.
       */
      private void loadPlayers()
      {
        String method = "loadPlayers";
        Context context = getApplicationContext();
        String file_path = context.getFilesDir().getAbsolutePath();//returns current directory.
        //Log.i(DEBUG_TAG, method+": file_path - "+file_path);
        File players_file = new File(file_path, Constants.PLAYERS_XML);
        boolean exists = players_file.exists();
        //Log.i(DEBUG_TAG, method+": exists? "+exists);
        if (exists)
        {
          //Log.i(DEBUG_TAG, method+": parse players.xml and merge with game players");
          parsePlayers(Constants.PLAYERS_XML);
          //Log.i(DEBUG_TAG, method+": before merge");
          //printPlayers();
          mergeGamePlayersWithFilePlayers();
          //Log.i(DEBUG_TAG, method+": after merge");
          //printPlayers();
          savePlayersFile();
        } else
        {
          //Log.i(DEBUG_TAG, method+": create new players.xml and populate it from the inten.");
          createNewPlayersFile();
          populatePlayersFromIntent();
          savePlayersFile();
        }
      }
      
      /**
       * After parsing the cards and the players file, 
       * we create PlayerInfo objects for each player that has an id in player_ids
       * but doesn't already have an object in the players hash.
       * This vould happen if the players haven't logged in, and someone else sets up the game
       * and they want to go ahead and play without logging in.
       * We also initialize the score count for each player held in id_player_matches.
       */
      private void mergeGamePlayersWithFilePlayers()
      {
        String method = "mergeGamePlayersWithFilePlayers";
        for (int i = 0; i < player_ids.size(); i++)
        {
          String this_player_id = player_ids.get(i);
          id_player_matches.put(this_player_id, (double)0);
          //Log.i(DEBUG_TAG, method+": this_player_id "+this_player_id);
          if (!players.containsKey(this_player_id))
          {
            String player_name = id_player_names.get(this_player_id);
            PlayerInfo player_info = new PlayerInfo(player_name, 0, this_player_id, "crab_228");
            players.put(this_player_id, player_info);
            //Log.i(DEBUG_TAG, method+": put "+this_player_id+" into players hash named "+player_name);
          } else
          {
            //Log.i(DEBUG_TAG, method+": player "+this_player_id+" not in game");
          }
        }
      }
      
      /**
       * If there are no players logged in, we setup the player info from the ids sent in 
       * in the intent.
       */
      private void populatePlayersFromIntent()
      {
        for (int i = 0; i < player_ids.size(); i++)
        {
          String player_id = player_ids.get(i);
          PlayerInfo player_info = new PlayerInfo();
          player_info.setId(player_id);
          player_info.setName(player_id);
          player_info.setScore(0);
          player_info.setIcon("crab_228");
          players.put(player_id, player_info);
        }
      }
      
    /**
     * Using a string buffer, we create the initial players.xml file with a new entry for the first player with a default icon name.
     */
    private void createNewPlayersFile()
      {
        //Log.i(DEBUG_TAG, method+": Using a string buffer, we create the initial players.xml file with a new entry for the first player with a default icon name.");
        try 
        {
          FileOutputStream fos = openFileOutput(Constants.CARDS_XML, Context.MODE_PRIVATE);
            try
            {
              StringBuffer sb = new StringBuffer();
          sb.append("<players/>");
          fos.write(new String(sb).getBytes());
          fos.close();
            }catch(FileNotFoundException e)
            {
                Log.e(DEBUG_TAG, "FileNotFoundException");
        } catch (IOException e1) 
        {
          Log.e(DEBUG_TAG, "IOException");
          e1.printStackTrace();
        }
      } catch (IOException e) 
      {
        e.printStackTrace();
      }
      }
      
      /**
       * Parse the players.xml file.
       * As with other parsings, the final element indicates when to finish each player and 
       * add a PlayerInfo object to the players hash.
       * @param filename
       * @param pa
       */
      private void parsePlayers(final String filename)
      {
        final String method = "parsePlayers"; 
        Log.i(DEBUG_TAG, method+": start parse");
        new Thread() 
        {
              public void run() 
              {
                FileInputStream fis = null;
          try 
          {
            fis = openFileInput(filename);
            //Log.i(DEBUG_TAG, method+": fis "+fis.available());
          } catch (FileNotFoundException e1) 
          {
            Log.i(DEBUG_TAG, method+": fnfe");
            e1.printStackTrace();
          } catch (java.io.IOException ioe)
          {
            Log.i(DEBUG_TAG, method+": ioe");
            ioe.printStackTrace();
          }
                  try 
                  {
                    String tag = "";String name = "";int score = 0;String id = "";
                      XmlPullParserFactory parserCreator = XmlPullParserFactory.newInstance();
                      XmlPullParser parser = parserCreator.newPullParser();
                      parser.setInput(fis, null);
                      int parser_event = parser.getEventType();
                      while (parser_event != XmlPullParser.END_DOCUMENT) 
                      {
                          switch (parser_event) 
                          {
                          case XmlPullParser.TEXT:
                            if (true)
                            {
                              if (tag!=null)
                              {
                                String value = parser.getText();
                                if (tag.equals("name"))
                                {
                                  name = value;
                                  //Log.i(DEBUG_TAG, method+": name "+name);
                                } else if (tag.equals("score"))
                                {
                                  score = Integer.parseInt(value);
                                  //Log.i(DEBUG_TAG, method+": score "+score);
                                } else if (tag.equals("id"))
                                {
                                  id = value;
                                  //Log.i(DEBUG_TAG, method+": id "+id);
                                } else if (tag.equals("icon"))
                                {
                                  PlayerInfo player_info = new PlayerInfo(name, score, id, value);
                                  players.put(id, player_info);
                                  if (!player_ids.contains(id))
                                  {
                                    player_ids.add(id);
                                    //Log.i(DEBUG_TAG, method+": added to players_ids");
                                  }
                                  //Log.i(DEBUG_TAG, method+": name "+name+" id "+id+" icon "+value+" score "+score);
                                }
                              }
                              tag = null;
                            }
                              
                          case XmlPullParser.START_TAG:
                            tag = parser.getName();
                          }
                          parser_event = parser.next();
                      }
                  } catch (Exception e) 
                  {
                    Log.i(DEBUG_TAG, method+": (not) exception(al)");
                    e.printStackTrace();
                  }
              }
        }.start();
        Log.i(DEBUG_TAG, method+": finished");
      }
      
      /**
       * Write all the PlayerInfo objects as xml elements
       * @param path_to_players_files
       * @param name
       * @param id
       */
      public void savePlayersFile()
      {
        String method = "savePlayersFile";
          //Log.i(DEBUG_TAG, method+": players.size() "+players.size());
        try 
        {
          FileOutputStream fos = context.openFileOutput("players.xml", Context.MODE_PRIVATE);
          //Log.i(DEBUG_TAG, method+": FD "+fos.getFD());
            try
            {
              StringBuffer sb = new StringBuffer();
          sb.append("<players>");
          Enumeration<String> e = players.keys();
          while (e.hasMoreElements())
          {
            String key = e.nextElement();
            PlayerInfo info = players.get(key);
            sb.append("<player>");
            sb.append("<name>"+info.getName()+"</name>");
            sb.append("<score>"+info.getScore()+"</score>");
            sb.append("<id>"+info.getId()+"</id>");
            sb.append("<icon>"+info.getIcon()+"</icon>");
            sb.append("</player>");
            //Log.i(DEBUG_TAG, method+" added " + info.getName());
          }
          sb.append("</players>");
          //Log.i(DEBUG_TAG, "writing "+sb.toString());
          fos.write(new String(sb).getBytes());
          fos.close();
          //Log.i(DEBUG_TAG, method+": done");
            }catch(FileNotFoundException e)
            {
                Log.e(DEBUG_TAG, "FileNotFoundException");
        } catch (IOException e1) 
        {
          Log.e(DEBUG_TAG, "IOException");
          e1.printStackTrace();
        }
      } catch (IOException e) 
      {
        e.printStackTrace();
      }
      }
      
      /**
      * This is called each time a NFC tag is detected.
      */
      @Override
      public void onNewIntent(Intent intent) 
      {
          //Log.i(DEBUG_TAG, "onNewIntent - Foreground dispatch:  action: " + intent.getAction());   
          resolveIntent(intent);   
      }

      @Override
      public void onPause() 
      {
          super.onPause();
          try
          {
            mfc_adapter.disableForegroundDispatch(this);
          } catch (java.lang.NullPointerException npe)
          {
            //Log.i(DEBUG_TAG, "unable to disable Foreground Dispatch");
            npe.printStackTrace();
          }
      }
    
      /**
       * Testing card options, and a selection to get instructions on this game.
       * A player can also choose to reset the game.
       */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
    {
      super.onCreateOptionsMenu(menu);
      menu.add("Next Card").setIcon(android.R.drawable.star_big_off);
      SubMenu icon_choice = menu.addSubMenu("Choose").setIcon(android.R.drawable.ic_menu_gallery);
      icon_choice.add(icon_group, right_card_id, 1, "Right card");
      icon_choice.add(icon_group, wrong_card_id, 2, "Wrong card");
      menu.add(0 , instructions_menu_item_id, 0, R.string.instructions_menu_item);
      menu.add(0 , reset_game_menu_item_id, 0, R.string.reset_game_menu_item);
      return true;
    }
    
    /**
     * This method captures the NFC adapter which will be used to scan tags.
     * This is part of the "Foreground Dispatch" system.
     */
     @Override
       public void onResume() 
     {
           super.onResume();
           try
           {
             mfc_adapter.enableForegroundDispatch(this, pending_intent, filters, tech_lists_array);
           } catch (java.lang.NullPointerException npe)
           {
               //Log.i(DEBUG_TAG, "onResume:  npeee!");
               mfc_adapter = NfcAdapter.getDefaultAdapter(context);
               //nfc_adapter.enableForegroundDispatch(this,pendingIntent,writeTagFilters,techListsArray);
           }
       }
    
    /**
       * When testing on a virtual device we want a way to choose the next correct or incorrect card.
       */
      public boolean onOptionsItemSelected(MenuItem item) 
      {
        String method = "onOptionsItemSelected(MenuItem)";
        //Log.i(DEBUG_TAG, method+": Change the icon when the item is selected.");
        //Log.i(DEBUG_TAG, method+": selected "+item.toString());
        getIntent();
        if (item.getItemId() == right_card_id)
        {
          testCard();
            return true;
        } else if (item.getItemId() == wrong_card_id)
        {
          NdefRecord record = getCardRecord("wrong");
          final TagDescription description = new TagDescription("Wrong Word", record.getPayload());
          final Intent intent = new Intent(NfcAdapter.ACTION_TAG_DISCOVERED);
              intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, description.msgs);
              intent.putExtra("test_card", "wrong");
              onNewIntent(intent);
            return true;
        } else if (item.getItemId() == instructions_menu_item_id)
        {
          Intent intent = new Intent(GameConcentrationActivity.this, GameReadingStonesInstructionsActivity.class);
          startActivity(intent);
        } else if (item.getItemId() == reset_game_menu_item_id)
        {
          resetGame();
        } else if (item.toString().equals("Next Card"))
        {
          testCard();
        } 
        
        return super.onOptionsItemSelected(item);
      }
      
      /**
     * Pick the first card from the enumeration and send that id to the foundGameCard method. 
     * @param tag_id
     */
    private void testCard()
    {
      String method = "testCards";
      Log.i(DEBUG_TAG, method+" cards "+cards.size());
      Enumeration<String> e = cards.keys();
      while (e.hasMoreElements())
      {
        String this_card_id = e.nextElement();
        Card card = cards.get(this_card_id);
        String card_status = card.getCardStatus();
        Log.i(DEBUG_TAG, method+" card "+card.getDefinition()+" status "+card_status);
        if (!played_card_ids.contains(this_card_id)&&!card_status.equals(Constants.PLAYED))
        {        
          Log.i(DEBUG_TAG, method+" using "+card.getDefinition());
          card.setCardStatus(Constants.PLAYED);
          foundGameCard(card);
          Card matching_card = findMatchingCard(card);
          foundGameCard(matching_card);
          break;
        }
      }
    }
    
    /**
     * Find the matching card by checking the word id.  If it's the same, return the card.
     * If the card is not found, something is really wrong, and we return null.
     * @param card_to_match
     * @return
     */
    private Card findMatchingCard(Card card_to_match)
    {
      String method = "findMatchingCard";
      Enumeration<String> e = cards.keys();
      Log.i(DEBUG_TAG, method+" looking at "+cards.size()+" cards.");
      while (e.hasMoreElements())
      {
        String this_card_id = e.nextElement();
        Card this_card = cards.get(this_card_id);
        Log.i(DEBUG_TAG, method+" card "+UtilityTo.getWord(this_card)+" "+this_card_id);
        if (this_card.getWordId() == card_to_match.getWordId())
        {
          Log.i(DEBUG_TAG, method+" id == card_to_match");
          // make sure it's not the exact same card.
          if (this_card.getWordType()!=card_to_match.getWordType())
          {
            Log.i(DEBUG_TAG, method+" id == card_to_match");
            return this_card;
          } else
          {
            Log.i(DEBUG_TAG, method+" "+this_card.getWordType()+" = "+card_to_match.getWordType());
          }
        } else
        {
          Log.i(DEBUG_TAG, method+" id == "+card_to_match.getWordId());
        }
            
      }
      return null;
    }
      
      
      private int mock_word_counter;
      private void getTestCard(String test_card_type)
      {
        int i = 0;
        Enumeration<String> e = cards.keys();
        while (e.hasMoreElements())
        {
          String key = e.nextElement();
          Card card = cards.get(key);
          i++;
          if (i>mock_word_counter)
          {
            mock_word_counter++;
            foundGameCard(card);
          }
        }
      }
      
      private void printPlayers()
      {
        String method = "printPlayers";
        Enumeration<String> e = players.keys();
        Log.i(DEBUG_TAG, method+" players size "+players.size());
      while (e.hasMoreElements())
      {
        String key = e.nextElement();
        PlayerInfo this_player_info = players.get(key);
        Log.i(DEBUG_TAG, method+": name "+this_player_info.getName());
        Log.i(DEBUG_TAG, method+": id "+this_player_info.getId());
        Log.i(DEBUG_TAG, method+": score "+this_player_info.getScore());
        Log.i(DEBUG_TAG, method+": icon "+this_player_info.getIcon());
      }
      }
      
      private void printCard(Card card)
      {
        Log.i(DEBUG_TAG, "printCard --------");
        Log.i(DEBUG_TAG, "card "+card.getCardId());
        Log.i(DEBUG_TAG, "card "+card.getCardStatus());
        Log.i(DEBUG_TAG, "card "+card.getDefinition());
        Log.i(DEBUG_TAG, "card "+card.getIndex());
        Log.i(DEBUG_TAG, "card "+card.getPlayerIcon());
        Log.i(DEBUG_TAG, "card "+card.getPlayerId());
        Log.i(DEBUG_TAG, "card "+card.getPlayerName());
        Log.i(DEBUG_TAG, "card "+card.getText());
        Log.i(DEBUG_TAG, "card "+card.getWordCategory());
        Log.i(DEBUG_TAG, "card "+card.getWordId());
        Log.i(DEBUG_TAG, "card "+card.getWordType());
        Log.i(DEBUG_TAG, "printCard --------");
      }
      
      private void printGame(Game game, String message)
      {
        try
        {
          Log.i(DEBUG_TAG, "Game -------- "+message);
          Log.i(DEBUG_TAG, "class id "+game.getClassId());
          Log.i(DEBUG_TAG, "test format "+game.getTestFormat());
          Log.i(DEBUG_TAG, "test id "+game.getTestId());
          Log.i(DEBUG_TAG, "test status "+game.getTestStatus());
          Log.i(DEBUG_TAG, "test name "+game.getTestName());
          Log.i(DEBUG_TAG, "test type "+game.getTestType());
          Enumeration<String> e = players.keys();
          while (e.hasMoreElements())
          {
            String key = (String) e.nextElement();
            PlayerInfo this_player_info = players.get(key);
            String status = game.getPlayerStatus(key);
            Log.i(DEBUG_TAG, "Player status "+status);
            Log.i(DEBUG_TAG, "Player )(--");
            Log.i(DEBUG_TAG, "name "+this_player_info.getName());
          Log.i(DEBUG_TAG, "id "+this_player_info.getId());
          Log.i(DEBUG_TAG, "score "+this_player_info.getScore());
          Log.i(DEBUG_TAG, "icon "+this_player_info.getIcon());
          Log.i(DEBUG_TAG, "Player )(--");
          }
          Log.i(DEBUG_TAG, "Game --------");
        } catch (java.lang.NullPointerException npe)
        {
          Log.i(DEBUG_TAG, "No game file to print");
        }
      }
      
      private void printPlayerInfo(PlayerInfo this_player_info, String message)
      {
        Log.i(DEBUG_TAG, "Player )))) - "+message+" - (((((");
      Log.i(DEBUG_TAG, "name "+this_player_info.getName());
      Log.i(DEBUG_TAG, "id "+this_player_info.getId());
      Log.i(DEBUG_TAG, "score "+this_player_info.getScore());
      Log.i(DEBUG_TAG, "icon "+this_player_info.getIcon());
      Log.i(DEBUG_TAG, "Player )    ----------------    (");
      }
      
  }




Java Source Code List

com.curchod.domartin.AsyncLoadGameFile.java
com.curchod.domartin.Constants.java
com.curchod.domartin.Filer.java
com.curchod.domartin.HouseDeck.java
com.curchod.domartin.IWantTo.java
com.curchod.domartin.MockNdefMessages.java
com.curchod.domartin.NfcUtils.java
com.curchod.domartin.RemoteCall.java
com.curchod.domartin.Sarray.java
com.curchod.domartin.Scoring.java
com.curchod.domartin.TagDescription.java
com.curchod.domartin.UtilityTo.java
com.curchod.dto.Card.java
com.curchod.dto.DeckCard.java
com.curchod.dto.GameWord.java
com.curchod.dto.Game.java
com.curchod.dto.PlayerInfo.java
com.curchod.dto.SavedTest.java
com.curchod.dto.SingleWordTestResult.java
com.curchod.dto.SingleWord.java
com.curchod.json.VocabularyDefinition.java
com.curchod.json.VocabularyLearningObject.java
com.curchod.wherewithal.AddPlayerActivity.java
com.curchod.wherewithal.CardDeckActivity.java
com.curchod.wherewithal.CardDecksActivity.java
com.curchod.wherewithal.CardPlayerHouseDeckActivity.java
com.curchod.wherewithal.CardPlayerWordsActivity.java
com.curchod.wherewithal.CardPlayersListActivity.java
com.curchod.wherewithal.CardsActivity.java
com.curchod.wherewithal.GameConcentrationActivity.java
com.curchod.wherewithal.GameReadingStonesActivity.java
com.curchod.wherewithal.GameReadingStonesInstructionsActivity.java
com.curchod.wherewithal.GameSnazzyThumbworkActivity.java
com.curchod.wherewithal.GameWritingStonesActivity.java
com.curchod.wherewithal.GamesActivity.java
com.curchod.wherewithal.InstructionsActivity.java
com.curchod.wherewithal.MainActivity.java
com.curchod.wherewithal.PlayerActivity.java
com.curchod.wherewithal.PlayersActivity.java