Parse data from PHP to C# for High Scores

If anyone can help with this, it would be greatly appreciated. I have an online high score board working for my game. But, it would be nice to have the names align left in the window, and the scores align right, to give it that “Arcade” look. I send the Player’s name and score to the MySQL server and then retrieve the list of scores. But to get the alignments, I’m thinking I need to parse the names and scores after retrieving them. Any ideas on how to do this in C#?

Here is a screen shot:

Here is what the code looks like:

using UnityEngine;
using System.Collections;
using System.Text;
using System.Security;

public class Highscore : MonoBehaviour{
	//DECLARE VARIABLES - WEB CONNECTIONS
	public string secretKey = "aliensyncscores";
	public string PostScoreUrl = "http://www.aliensync.com/games/highscore/postScore.php?";
	public string GetHighscoreUrl = "http://www.aliensync.com/games/highscore/getHighscore.php";

	private string name = "Name";
	private int score;
	private string WindowTitel = "";
	private string Score = "";
	public int dataSendCount;
	public Rect demoArea;
	
	public string postdata;
	public int scoredata;
	public string namedata;
	
	public GUISkin Skin;
	public float windowWidth = 380;
	private float windowHeight = 300;
	public Rect windowRect;

	public int maxNameLength = 15;
	public int getLimitScore = 10;
	
	public Transform gameCon;
	private GameControl gamecon;
	
	//INITIALIZE SOME VARIABLES-------------------->
	void Start (){
		gamecon=gameCon.GetComponent<GameControl>();
		dataSendCount=0;
		score=gamecon.gamePoints;	
	}
	//SETUP FOR CONDITIONS TO POST DATA TO PHP
	void Update (){
		if(gamecon.hiScoreSection==1){
			if(dataSendCount<3){
				dataSendCount+=1;
			}
		}
		if(dataSendCount==1){
			StartCoroutine(PostScore());
		}
		windowRect = new Rect (Screen.width*0.5f -(windowWidth*0.5f), 10, windowWidth, Screen.height*0.75f);
		windowHeight = Screen.height*0.75f;
	}
	
	//BRING THE NAME AND SCORE DATA FROM PHP-------------------->
	IEnumerator GetScore(){
		Score = "";
			
    	WindowTitel = "Loading";
		
		WWWForm form = new WWWForm();
		form.AddField("limit",getLimitScore);
		
    	WWW www = new WWW(GetHighscoreUrl,form);
    	yield return www;
		
		if(www.text == ""){
			print("There was an error getting the high score: " + www.error);
			WindowTitel = "There was an error getting the high score";
    	}else{
			WindowTitel = "HISCORES";
			Score = www.text;
		}
	}
	
	//SEND THE NAME AND SCORE DATA TO PHP-------------------->
	IEnumerator PostScore(){
		string _name = name;
		int _score = score;
		
		string hash = Md5Sum(_name + _score + secretKey).ToLower();
		
		WWWForm form = new WWWForm();
		form.AddField("name",_name);
		form.AddField("score",_score);
		form.AddField("hash",hash);
		
		WWW www = new WWW(PostScoreUrl,form);
		WindowTitel = "Wait";
		yield return www;
		
    	if(www.text == "done"){
       		StartCoroutine("GetScore");
    	}else {
			print("There was an error posting the high score: " + www.error);
			WindowTitel = "There was an error posting the high score";
		}
	}
	
	//CAPTURE DATA
	void OnGUI(){
		GUI.skin = Skin;
		
		//CONDITION 0: CAPTURE FROM PLAYER NAME AND SCORE TO SEND TO PHP-------------------->
		if(gamecon.hiScoreSection==0){
			demoArea= new Rect(Screen.width*0.1f,Screen.height*0.1f,Screen.width-Screen.width*0.2f,Screen.height-Screen.height*0.5f);
			GUI.Box(demoArea,"SUBMIT SCORE");
			GUI.BeginGroup(demoArea);
		
				GUI.Label(new Rect(10,50,80,25), "Name: ");
				GUI.Label(new Rect(10,90,80,25), "Score: ");
		
				name = GUI.TextField(new Rect(120, 50, 150,25), name,14);
				GUI.Label(new Rect(120, 90, 80, 25), score.ToString());
						
			GUI.EndGroup();
		}
		
		//CONDITION 1: DISPLAY WINDOW FOR DATA FROM PHP-------------------->
		if(gamecon.hiScoreSection==1){
			windowRect = GUI.Window(0, windowRect, DoMyWindow, WindowTitel);
		}
	}
	//DATA FOR CONDITION 1 TO DISPLAY-------------------->
	void DoMyWindow(int windowID){
		GUI.skin = Skin;
    	GUI.Label (new Rect (windowWidth / 2 - windowWidth / 2, 70, windowWidth, windowHeight), Score);
    }
	
	//NEEDED TO COMMUNICATE WITH PHP-------------------->
	public string Md5Sum(string input){
    	System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
    	byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
    	byte[] hash = md5.ComputeHash(inputBytes);
 
    	StringBuilder sb = new StringBuilder();
    	for (int i = 0; i < hash.Length; i++){
    	    sb.Append(hash[i].ToString("X2"));
    	}
    	return sb.ToString();
	}
}

Thanks for any help. Peace. :slight_smile:

Alien,

I did something very similar. I but tabs (“\t”) between each string in the entry and new lines (“\n”) between each entry. Then called Split a couple of times.

The code I used to parse it in C# :

//the string passed ParseScoreString MUST be of the form:
	// name\tscore\twhenSet\n
	public void ParseScoreString(string scoreString)
	{
		string[] splitScores = scoreString.Trim().Split('\n');
		if (scoreString == string.Empty)
			return;
		int count = 0;
		foreach (string entry in splitScores)
		{
			//throw an error if the string is not properly formatted
			if(!entry.Contains("\t"))
				throw new Exception("Improperly formatted data from database " + entry);
			string[] temp = entry.Split('\t');
			highScoreList.Add(new HighScoreElement(
				name:temp[0], score:int.Parse(temp[1]), whenSet:smile:ateTime.Parse(temp[2]), zeroBasedRank: count));
			count ++;
		}
	
	}

and the php code running on my server:

if($_GET['table'] == "Standard")
	    $sth = $dbh->query('SELECT name, score, whenSet FROM Standard ORDER BY score DESC LIMIT 100');
	elseif($_GET['table'] == "Survival")
		$sth = $dbh->query('SELECT name, score, whenSet FROM Survival ORDER BY score DESC LIMIT 100');
	else
		die("Invalid table");

	$sth->setFetchMode(PDO::FETCH_ASSOC);
    $result = $sth->fetchAll();
 
    if(count($result) > 0) {
        foreach($result as $r) {
            echo $r['name'], "\t", $r['score'], "\t", $r['whenSet'], "\n";
        }
    }

The php code might be a little confusing. I have two different tables for two different game modes, that’s why the ‘Survival’ and ‘Standard’ part. I can elaborate more if you want.

Cheers,
Cahman

Thanks CahMan. Actually, if you could explain the C# a little bit, that would help.

Sure, I’ll give it a try.

So the way the php is setup, I get the whole table as one big glob. Here’s an example of what the input might be:

scoreString = “Bill\t1200\12Nov2012\nBob\1300\15Sep2010”;

	//the string passed ParseScoreString MUST be of the form:
	// name\tscore\twhenSet\n
	public void ParseScoreString(string scoreString)
	{
		//make an array out of the input.  Trim() removes any leading and trailing white spaces.
		//Split(\n) brakes the string into an array of springs at each \n
		string[] splitScores = scoreString.Trim().Split('\n');
		//So now splitScores[0] = Bill\t1200\t12Nov2012
		//       splitScores[1] = Bob\t1300\t15Sep2010
		
		//This just checks to make sure I got a valid string from the server
		//Should probably do this first... but I didn't.
		if (scoreString == string.Empty)
			return;
			
		//This is the score position
		int count = 0;
		
		//now, for each entry in splitScores
		foreach (string entry in splitScores)
		{
			//if theres no \t in the string, then there is something wrong with the data
			//in the database, so throw an error
			if(!entry.Contains("\t"))
				throw new Exception("Improperly formatted data from database " + entry);
			
			//now split the string on the \t char.  So the first time through the foreach loop:
			//temp[0] = Bill
			//temp[1] = 1200
			//temp[2] = 12Nov2012
			string[] temp = entry.Split('\t');
			
			//HighScoreElement is a class I wrote.  It basically just stores those pieces of data
			//and handles displaying them to the screen.  This is creating a new highscore element
			//with named parameters (name: value is a named parameter if you've not seen them before)
			//and adding them to a list.
			//int.Parse turns a string to an int.  DateTime.parse turns a string into a DateTime 
			highScoreList.Add(new HighScoreElement(
				name:temp[0], score:int.Parse(temp[1]), whenSet:smile:ateTime.Parse(temp[2]), zeroBasedRank: count));
			
			//get the next position on the high score table.  
			count ++;
		}
	
	}

Here’s the pertinent information from the High Score Element class:

public class HighScoreElement{
	
	
	string name;
	DateTime whenSet;
	public int score{get; private set;}
	int rank;
	
	
	
	
	public HighScoreElement(string name, int score, DateTime whenSet, int zeroBasedRank)
	{
		this.name = name;
		this.score = score;
		this.whenSet = whenSet;
		this.rank = zeroBasedRank + 1; //rank is 1 based, not zero based
	}

...

	//displays the high scores in a nice format.  Assumes that is being called
	//from an On_GUI block. Assumes GUILayout has already been initialized and will be
	//closed by the caller.
	public void Display()
	{
		GUILayout.BeginHorizontal();
		
		GUILayout.Label (rank.ToString() + ". " + name, GUI.skin.GetStyle("HighScoreText"));

		GUILayout.Label (score.ToString(), GUI.skin.GetStyle("HighScoreText"));
		GUILayout.Label(whenSet.ToString());//, GUI.skin.GetStyle("HighScoreText"));

		GUILayout.EndHorizontal();

	}

The “HighScoreText” GUIStyle might be what your after. I think they are fixed width, but I can look up the details if you want.

Here’s an example of the what it looks like (if you pardon my poor artistic eye).

If you have any specific questions about the code, just let them rip!

Cheers,
CahMan

Thanks CahMan. I think I’m on the right track with this. I’m having some trouble with the highScoreList.Add(new HighScoreElement). How do I handle the highScoreList? I keep getting an error: Type int' does not contain a definition for Add’ and no extension method Add' of type int’ could be found…
I tried making it an int variable and a string variable. Where am I missing this? Thanks.

Alien,

One major difference in our approaches is that I used a C# generic List type to store high score elements locally. Generic Lists are one of the most powerful and most awesomest things about C#. Here’s a link to a pretty good description of them. The ‘add’ method is for Lists.

Please keep in mind, you don’t HAVE to do this the same way I did.

Cahman

Thanks CahMan. Got it working. I may try to use the DateTime idea too. For anyone interested, here is the final code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Security;

public class Highscore : MonoBehaviour{
	//DECLARE VARIABLES - WEB CONNECTIONS-------------------->
	public string secretKey = "aliensyncscores";
	public string PostScoreUrl = "http://www.aliensync.com/games/highscore/postScore.php?";
	public string GetHighscoreUrl = "http://www.aliensync.com/games/highscore/getHighscore.php";
	public WWW www;
	private string name="Name";
	private int score;
	private string WindowTitel = "";
	private string scoretext = "";
	public int dataSendCount;
	public Rect demoArea;
	public  int count;
	List<string> scoreList = new List<string>();
	List<string> nameList = new List<string>();
	public GUISkin Skin;
	public float windowWidth = 380;
	private float windowHeight = 300;
	public Rect windowRect;

	public int maxNameLength = 15;
	public int getLimitScore = 10;
	
	public Transform gameCon;
	private GameControl gamecon;
	
	//INITIALIZE SOME VARIABLES-------------------->
	void Start (){
		gamecon=gameCon.GetComponent<GameControl>();
		dataSendCount=0;
		score=gamecon.gamePoints;	
	}
	
	//SETUP FOR CONDITIONS TO POST DATA TO PHP
	void Update (){
		if(gamecon.hiScoreSection==1){
			if(dataSendCount<3){
				dataSendCount+=1;
			}
		}
		if(dataSendCount==1){
			StartCoroutine(PostScore());
		}
		windowRect = new Rect (Screen.width*0.5f -(windowWidth*0.5f), 10, windowWidth, Screen.height*0.75f);
		windowHeight = Screen.height*0.75f;
	}
	
		
	//SEND THE NAME AND SCORE DATA TO PHP-------------------->
	IEnumerator PostScore(){
		string _name = name;
		int _score = score;
		
		string hash = Md5Sum(_name + _score + secretKey).ToLower();
		
		WWWForm form = new WWWForm();
		form.AddField("name",_name);
		form.AddField("score",_score);
		form.AddField("hash",hash);
		
		www = new WWW(PostScoreUrl,form);
		WindowTitel = "Wait";
		yield return www;
		
    	if([url]www.text[/url] == "done"){
       		StartCoroutine("GetScore");
    	}else {
			print("There was an error posting the high score: " + [url]www.error);[/url]
			WindowTitel = "There was an error posting the high score";
		}
	}
	
	//BRING THE NAME AND SCORE DATA FROM PHP-------------------->
	IEnumerator GetScore(){
		//scoretext = "";
    	WindowTitel = "Loading";
		
		WWWForm form = new WWWForm();
		form.AddField("limit",getLimitScore);
		
    	www = new WWW(GetHighscoreUrl,form);
    	yield return www;
		
		if([url]www.text[/url] == ""){
			print("There was an error getting the high score: " + [url]www.error);[/url]
			WindowTitel = "There was an error getting the high score";
    	}else{
			WindowTitel = "HISCORES";
			scoretext = [url]www.text;[/url]
			ParseScoreString();
		}
	}
	
	public void ParseScoreString(){
        //make an array out of the input.  Trim() removes any leading and trailing white spaces.
        //Split(\n) brakes the string into an array of springs at each \n
        string[] splitScores = scoretext.Trim().Split('\n');

        //So now splitScores[0] = Bill\t1200\t12Nov2012
        //       splitScores[1] = Bob\t1300\t15Sep2010

        //This just checks to make sure I got a valid string from the server
        if (scoretext == string.Empty){
			return;
			count = 0;
		}

        //now, for each entry in splitScores
        foreach (string entry in splitScores){

            //if theres no \t in the string, then there is something wrong with the data in the database, so throw an error
            if(!entry.Contains("\t"))
                print("Improperly formatted data from database " + entry);
			
            //now split the string on the \t char.  So the first time through the foreach loop:
            //temp[0] = Bill
            //temp[1] = 1200
            //temp[2] = 12Nov2012
            string[] temp = entry.Split('\t');

            nameList.Add(temp[0]);
			scoreList.Add(temp[1]);
            //get the next position on the high score table.  
            count ++;
        }
    }
	
	//CAPTURE DATA
	void OnGUI(){
		GUI.skin = Skin;
		
		//CONDITION 0: CAPTURE FROM PLAYER NAME AND SCORE TO SEND TO PHP-------------------->
		if(gamecon.hiScoreSection==0){
			demoArea= new Rect(Screen.width*0.1f,Screen.height*0.1f,Screen.width-Screen.width*0.2f,Screen.height-Screen.height*0.5f);
			GUI.Box(demoArea,"SUBMIT SCORE");
			GUI.BeginGroup(demoArea);
		
				GUI.Label(new Rect(10,50,80,25), "Name: ");
				GUI.Label(new Rect(10,90,80,25), "Score: ");
		
				name = GUI.TextField(new Rect(120, 50, 150,25), name,14);
				GUI.Label(new Rect(120, 90, 80, 25), score.ToString());
						
			GUI.EndGroup();
		}
		
		//CONDITION 1: DISPLAY WINDOW FOR DATA FROM PHP-------------------->
		if(gamecon.hiScoreSection==1){
			windowRect = GUI.Window(0, windowRect, DoMyWindow, WindowTitel);
		}
	}
	
	//DATA FOR CONDITION 1 TO DISPLAY-------------------->
	void DoMyWindow(int windowID){
		GUI.skin = Skin;
		string _index="";
		string _names="";
		string _scores="";
	
		for (var i = 0; i < count; i++){
			_index +=i +1+ "." + "\n";
			_names += nameList[i] + "\n";
		    _scores += scoreList[i] + "\n";
		}
		GUI.Label (new Rect (0, 70, 50, 200), _index);
		GUI.Label (new Rect (50, 70, 100, 500), _names);
		GUI.Label (new Rect (250, 70, 100, 500), _scores);
    	
    }
	
//----------------------------------------------------------------------------------------------------------------->
	
	//NEEDED TO COMMUNICATE WITH PHP-------------------->
	public string Md5Sum(string input){
    	System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create();
    	byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
    	byte[] hash = md5.ComputeHash(inputBytes);
 
    	StringBuilder sb = new StringBuilder();
    	for (int i = 0; i < hash.Length; i++){
    	    sb.Append(hash[i].ToString("X2"));
    	}
    	return sb.ToString();
	}
}
1 Like