FacePamphlet – Extensions

This is the extensions part, but after reading the extensions and one of them was converting from using the acm.graphics library to using the java.xswing library – (GCanvas – JPanel) then since the assignment 6 looks very interesting I am going to leave that one for another day because only had about 1 hour to do this extension.

The extensions

  • Search for some friends with key words e.g. part of the name
  • status line on 2-x lines
  • change the middle gcanvas to a jpanel – NOTE not going to do at present
  • friend finder – friends that you could link to from your friends already

Search for some friends with key words e.g. part of the name

To search for names that are already in the users list but you type in part of there name, then I have added in the search to the friends request button action and if no friend is found with that name then do a possible search of different names with the request as a search within each name. Of course do not want to add in the user that I am logged in as and any friends that the current user already has as friends, below is the java code that implements this

			Message = "Error : "+ ex.getMessage() + " Possible names : ";
			String[] possibleNames = repository.getUsers();
			for (int i =0; i < possibleNames.length; i++)
			{
				if (possibleNames[i].indexOf(requested) >= 0)
				{
					if (!possibleNames[i].equals(homeUserID))
					{
						// if not already my friend
						if (!repository.isMyFriend(possibleNames[i]))
							Message += possibleNames[i];
					}
				}
			}

status line on 2-x lines

How I implemented this was to create a array of GLabel which are an array length of the status line divided by the centre display texture width (CENTERTEXTWIDTH) e.g. so that if there is a status line of “genux is burping” then there would only be one array length but if the line was allot longer then there would be a X array length. Also since we do not want to break the word across two lines, I searched for the space after the centre display texture width and then cut the line there instead of in the middle of the word and then placed the rest of the sentence on the next line (that is where the endSpace integer value comes into play).

	if (statusCentre != null) 
		for (int i =0; i < statusCentre.length; i++)
		remove(statusCentre[i]);
	String theStatus = repository.getProperty(usersID + FILE_STATUS);
	if (theStatus != null)
	{
		theStatus = usersID + " is " + theStatus;
		int endSpace =0;
		int statusSize = (theStatus.length() / CENTERTEXTWIDTH)+1;
		statusCentre = new GLabel[statusSize];
		for (int i =0 ; i < statusSize; i++)
		{
			// endSpace = get the last space words and only output full words
			String outString = theStatus.substring((i * CENTERTEXTWIDTH) + endSpace);
			if (outString.length() > CENTERTEXTWIDTH)
			{
				// find the closet space
				int end = outString.indexOf(" ",CENTERTEXTWIDTH);
				outString = outString.substring(0,end); //CENTERTEXTWIDTH);
				endSpace += end-CENTERTEXTWIDTH;
			}
			statusCentre[i] = new GLabel(outString);
			statusCentre[i].setLocation(FPConstants.LEFT_MARGIN, FPConstants.STATUS_TOP+(i * statusCentre[i].getHeight()));
			statusCentre[i].setFont(FPConstants.STATUS_FONT);
			add(statusCentre[i]);
		}
	}

friend finder – friends that you could link to from your friends already

The friend finder, the way that I thought about this was everyone is a friend of the course CS106A, so using the repository getUsers it will return a array of users, so all I did was created a function that takes the current users friend array and also the friends of the course array and then just found the users that was in the course array list and not in current users list and returned that as a array (e.g. there could be more than one un-friended user), I did not implement any double click on the FPScrollableList because it will just be using the friend request method and as stated before I am looking at the assignment 6 and it is looking interesting :).

Below is how I used the throw away users of the intersection of both arrays (my friends and the course friends)

	// return a string array of names that are within the main group courseF and not in my friends group
	// could do a random return of different similar names with X as the maximum to return
	// but since a simple example then probably not needed ?
	private String[] returnNames(String[] myF, String[] courseF)
	{
		String[] returnS;
		int diff = courseF.length - myF.length;
		// equals 1 because the courseF would include the userID name as well
		if (diff == 1)
			returnS = new String[0];
		else
		{
			returnS = new String[diff-1];
			int insertI =0;
			// find the names that are not in myF and then insert into the returnS
			for (int i=0; i < courseF.length; i++)
			{
				Boolean inI = true;
				for (int j =0; j < myF.length;j++)
				{
					if (courseF[i].equals(myF[j]))
					{
						inI = false;
						break;
					}
				}
				if (inI && (!courseF[i].equals(homeUserID))) 
					returnS[insertI++] = courseF[i]; 
			}
		}
		return returnS;
	}

I have included the source code in the zip file attached with also the assignment and running interface.

FacePamphlet

This is FacePamphlet, that is a very simple incarnation of facebook (social network of people).

There are some milestones that allow you to head towards, like a stepping stone to figure out the path to take to get the assignment done. Here are the milestones and also some code that will be linked into the milestones

Milestone 1: Create the west side panel

To create the panels with the data, then need to pull some data from the files that are present on the filesystem. Things like the name of the user is stored in a file and also friends, requests of friends etc, so to create for example below the list of friends that I would have, the repository class is already created and that “talks” to the filesystem to get the data in question (either locally in my case, and also in the testing phrasing of the assignment) but if you changed it to a network setup then it would get the data from a remote server. I have created a few private variables that will store the different parts of the graphics user interface so that I can “talk” to them with just referencing there name, which makes it allot more easier to update there details in the future.

Below the first code will get the full user name from the repository and add it to the WEST panel and then it will retrieve the list of names of friends into a String array and then cycle through to add them to the friends list on the WEST panel again.

		usersName = new JButton(repository.getProperty(userID + FILE_NAME));
		add(usersName, WEST);
 
		friendsList = new FPScrollableList();
		// add to the friends list
		myFriends = repository.getMyFriends();
		for (int i=0; i < myFriends.length; i++)
			friendsList.add(myFriends[i]);
		add(new JLabel("Friends:"), WEST);
		add(friendsList,WEST);

Milestone 2 – interactors

Interactors with the different parts of the GUI is nice and a good way is using the above code, e.g. using private variables that can be able to talk to when we get clicks from the GUI on buttons and want to find out which item was clicked, also since we are using some stanford custom code like FPScrollableList, FPScollableTextArea which you have to add the listens and also tell the called function what command (in string text) has been called.

		friendsList.addActionListener(this);
		friendsList.setActionCommand(VISIT);

the VISIT is a static final string so that encase any thing is altered just alter it once (it equals = “VISITS”)

Milestone 3: Create the center panel

The centre panel creates the basic information of the user, but also displays a graphical image and also error reporting with status updates as well. With the graphics object the graphics is saved within a string format, which using the FPTools has a graphics to string converter, but to rescale the image I am seeing if the height/width is beyond centre size then alter the image by the size that is available divided by the size of the graphical object.

		if (picCentre.getHeight() > FPConstants.MAX_IMAGE_HEIGHT)
		{
			double newHeight = FPConstants.MAX_IMAGE_HEIGHT / picCentre.getHeight();
			picCentre.scale(newHeight);
		}
		if (picCentre.getWidth() > CENTERWIDTH)
		{
			double newWidth = CENTERWIDTH/ picCentre.getWidth();
			picCentre.scale(newWidth);
		}
		picCentre.setLocation(FPConstants.LEFT_MARGIN, FPConstants.IMAGE_TOP);
		add(picCentre);

updating the error messages I am using a function that takes the message as string and then just output the message, I am removing object and then just re-creating it and placing on the area specified in the FPConstants class. (you could test to see if there is any message length and thus create the infoMessage object)

	private void updateErrorMessage(String message)
	{
		if (infoMessage !=null) remove(infoMessage);
		infoMessage = new GLabel(message);
		infoMessage.setFont(FPConstants.INFO_MESSAGE_FONT);
		infoMessage.setColor(FPConstants.INFO_MESSAGE_COLOR);
		infoMessage.setLocation(FPConstants.LEFT_MARGIN, FPConstants.APPLICATION_HEIGHT - FPConstants.BOTTOM_MARGIN);
		add(infoMessage);
	}

Milestone 4: Implement the interactors

Here is the interactor for when you click on requesting a friend, or press enter on the friends name text box (getActionCommand), to start with I am getting the text of the friends and seeing if there is any friends with the same name already in my friends list, else if not then send a request. I have include the error reporting and also the message string is the error string that is being sent back to inform the user what is being happening.

	if ((event.getSource() == friendRequestButton) || event.getActionCommand().equals(FRIENDREQUEST))
		{
			String requested = friendRequest.getText();
			if (requested.length() > 0)
			{
				try 
				{
					if (repository.isMyFriend(requested))
						Message = requested + " is already your friend";
					else
					{
						repository.requestFriend(requested);
						Message = "Requested friend : " + requested;
					}
					repository.setProperty(homeUserID + FILE_LOG , "Requested friend " + requested);
				}
				catch (NullPointerException ex)
				{
					Message = "Not sure of name ? "+ requested + " : error : "+ ex.getMessage();
				}
				catch (ErrorException ex)
				{
					Message = "Not sure of name ? "+ requested + " : error : "+ ex.getMessage();
				}
			}
			friendRequest.setText("");
		}

Milestone 5: Shift over to the networked repository

Since I am running on the local PC, then I cannot connect to the Stanford server to test with, so will just guess that it is working :).

I also did implement a basic logging of the last actioned, in the users repository directory, and also if a user updates there pending friends request list and another user is viewing there FacePamphlet account and the friends list is updated then it will report the new friend in the status messages.

Going to implement in the extensions

  • Search for some friends with key words e.g. part of the name
  • status line on 2-x lines
  • change the middle gcanvas to a jpanel
  • friend finder – friends that you could link to from your friends already

Shall post extension next.

C# – Console Parameters test

As from my previous post on c++ console parameters, I thought that I would do one with c# (c sharp) as well, just to show the difference in the languages as well.

Compared to c++ where you cannot use the “==” (is equal to) operation because in c++ that is comparing two different memory locations and not the value within the left/right hand variables. Well in c# you can, there is a Equals method as well that you can use, but either or works fine, so in the example code below here is the main part, where I am comparing against a console parameter equalling -h (normally the help)

if (args[i].Equals("-h")) Console.WriteLine("-h option selected(equals)");
if (args[i]=="-h") Console.WriteLine("-h option selected (==)");

both of them are fine to use as you can see from the output at the bottom of the post, both will print out that “-h option selected”, best to use the Equals though.

Here is the full source code

using System;
 
namespace consoletest
{
	class MainClass
	{
		public static void Main (string[] args)
		{
			for (int i = 0; i < args.Length; i++)
			{
				Console.WriteLine("args " + i + " : " + args[i]);								
				if (args[i].Equals("-h")) Console.WriteLine("-h option selected(equals)");
				if (args[i]=="-h") Console.WriteLine("-h option selected (==)");
			}
		}
	}
}

and here is the output using mono as the .Net runtime environment, as you can see both -h has been outputed

mono consoletest.exe -h here
args 0 : -h
-h option selected(equals)
-h option selected (==)
args 1 : here

Console parameters

Someone asked me the other day when you are checking the console parameters for any passing in options how come something like

if (argv[i] == "-t")

does not work, well it does make sense when you look at it, but because the “-t” is actually a char[] (a string) then this would occupy a place in memory and thus you are checking against memory locations which unless you are very very very lucky, this would never come out correct, you need to use the string compare (strcmp) function as below

#include <iostream>
#include <string.h>
 
using namespace std;
 
int main(int argc, char** argv)
{
 for (int i =0 ; i < argc; i++)
 {
// output argument that was passed in.
   cout << argv[i] << endl;
// compare with "-t" option
   if (strcmp(argv[i],"-t")==0) cout << "the -t option" << endl;
 }
 return 0;
}

and the output would be something like

./consolet -t 40
./consolet
-t
the -t option
40

Dice Game – Part 2

Dice Game – Part 2.

And here are the Extensions

  • Add a high score feature. Save the top ten highest scores and names to a file and make it persistent between runs of the program. Read the file when you start and print out the hall of fame. If a player gets a score that preempts one of the early high scores, congratulate them and update the file before you quit so it is recorded for next time.
  • Incorporate the bonus scores for multiple Yahtzees in a game. As long as you have not entered a 0 in the Yahtzee box, the rules of the game give you a bonus chip worth 100 points for each additional Yahtzee you roll during the same game.
  • Beef up your Yahtzee to the variant called “Triple Yahtzee.” In this variant, each player manages three simultaneous scorecard columns, as if they were playing for three players at once. The player can assign a roll to any one of their three columns. All entries are scored normally with respect to categories and validity, but the values in the second column are doubled, and the third column values are tripled. The player

Yahtzee

Yahtzee

Category 9 – Full house

Once again, I am going to bubble sort (bubble sort at the bottom of this post) the dice values, so that I can check to see if there are 3 of the same values and 2 of other values that are the same. This is very similar to counting how many values are the same with three/four of a kind, but this time need to make sure that there are only 3 / 2 split of different values, and for the scoring value we only need to return true/false since the value if it is a full house it is 25 points or 0 for nothing.

So, the way that I have done it, is with checking to see if values are the same within the array (whilst scanning from the start to end) and if they are increment the count (counting of similar values), if the values changes then check to see if the count is equal to 3 or 2 (which is the full house requirements) and if so set a boolean value to true and keep on checking. To get to return true, need to see if both the 3 and 2 boolean values are true then we know that we have a full house.

	// need to check for 3 of the same value and then 2 of the same value
	private Boolean checkFullHouse(int[] dice)
	{
		int count =1;
		Boolean found3 = false, found2 = false;
		for (int i=1; i < YahtzeeConstants.N_DICE;i++)
		{
			if (dice[i] == dice[i-1]) 
				count++;
			else
			{
				if (count == 3)
					found3 = true;
				else if (count == 2)
					found2 = true;
				count=1;
			}
		}
		if (count == 3)
			found3 = true;
		else if (count == 2)
			found2 = true;
		if (found3 && found2) return true;
		return false;
	}

Categories 10,11 – Small/Large straight

The last two are very similar and because once again I am using the bubble sort to organise the array into a order then we just need to check the array by going through it from start to finish checking to make sure that the value before is 1 minus the present value in the array ( e.g. array being 3,4,5, present value is the 4 and the previous value is 3 which is correct), then add up these correct placements within the array and if the consecutive values are either 4 (small straight) or 5 (large straight) return true or false accordingly.

	// consecutiveValues = how many in a straight line
	private Boolean checkStraight(int[] dice, int consecutiveValues)
	{
		int inLine =1;
		for (int i =1; i < YahtzeeConstants.N_DICE; i++)
		{
			if ((dice[i-1]+1) == dice[i]) inLine++;
		}
		if (inLine >= consecutiveValues) return true;
		return false;
	}

The main thing within the program is to make sure that you are always accounting for the difference with the categories numbers (which start from 1) and the scoring values (which start from 0) or the dice numbers (which start from 0 again), of course could make the size of those arrays 1 bigger.

To create the score array and also so we know what is a score value of 0 or not, then the score array is setup with all values of -1.

	/* setup the scores to a value of -1, default value */
	private void setupScores(int[][] scoresSetup, int playersNum, int totalValues)
	{
		for (int i=0; i < playersNum; i++)
			for (int j=0; j < totalValues;j++)
				scoresSetup[i][j] = -1;
	}

So that when you are selecting a category to place the score of your dice and you try to select a category already selected, then just need to check the score for -1 and if so we know it is a category not already used.

	private Boolean updateScore(int[] scoresUpdate, int category, int score)
	{
		// default is -1, since cannot get this score value
		if (scoresUpdate[category] == -1)
		{
			scoresUpdate[category] = score;
			return false;
		}
		else
		{
			display.printMessage("Category already selected, please select another");
			return true;
		}
	}

Also within the source code, I have included a cheat mode so that you can insert the values of the dice in runtime (when you are asked about the number of players type in -99 and the cheat mode is activated and there is only 1 player setup).

The next post is the extensions of this assignment.

Yahtzee

Yahtzee, over the next two posts going to explain about the thoughts behind working out the categories within the game, e.g. yahtzee, straight etc. And then in the 3rd post I am going to do the extensions of the assignment.

So to start with here are the different types of categories that the 5 dice can fall into with also there score associated value. ( the number at the start is the category that the dice would fall into)

  • 1. Ones. Any dice configuration is valid for this category. The score is equal to the sum of all of the 1