Journal #Thirteen [DAT602] - Practical Project Development
Practical Project Development
JOURNAL #THIRTEEN [DAT602]
Practical Project Development
It’s well past time that this journal series for DAT602
included some practical examples of the project development being worked on, now that milestone 2 has been completed it’s reasonable to share the progress made. For those interested in seeing the complete MySql and C# please go to the GitHub repo.
MySQL DDL
The following SQL is the player table:
DROP TABLE IF EXISTS tblPlayer;
CREATE TABLE tblPlayer (
PlayerID int AUTO_INCREMENT,
Email varchar(50) NOT NULL,
Username varchar(10) NOT NULL,
`Password` BLOB NOT NULL,
AccountAdmin bit DEFAULT FALSE NOT NULL,
AccountLocked bit DEFAULT FALSE NOT NULL,
ActiveStatus bit DEFAULT FALSE NOT NULL,
FailedLogins tinyint DEFAULT 0 NOT NULL,
HighScore int DEFAULT 0 NOT NULL,
PRIMARY KEY (PlayerID),
CONSTRAINT UC_Email UNIQUE (Email),
CONSTRAINT UC_Username UNIQUE (Username),
CONSTRAINT CHK_Email CHECK (Email Like '_%@_%._%')
);
ALTER TABLE tblPlayer AUTO_INCREMENT=000001;
ALTER TABLE tblPlayer ADD COLUMN Salt varchar(36);
ALTER TABLE tblPlayer ENCRYPTION='Y'; -- Encrypt Player table
MySQL Create Users & Grants
Adding a mysql.user
to the database and setting grants:
SELECT `user`, `host` FROM mysql.user;
DROP USER IF EXISTS 'databaseAdmin'@'localhost';
CREATE USER IF NOT EXISTS 'databaseAdmin'@'localhost' IDENTIFIED BY 'P@ssword1';
GRANT ALL ON sdghGameDatabase TO 'databaseAdmin'@'localhost';
SHOW GRANTS FOR 'databaseAdmin'@'localhost';
SHOW GRANTS FOR 'root'@'localhost';
MySQL Procedures
The following are some of the procedures created as they relate to the CRUD analysis.
User login and home screen display data:
DROP PROCEDURE IF EXISTS LoginCheckCredentials;
DELIMITER //
CREATE DEFINER = 'root'@'localhost' PROCEDURE LoginCheckCredentials(
IN pUsername varchar(50),
IN pPassword BLOB
)
SQL SECURITY DEFINER
BEGIN
DECLARE retrieveSalt varchar(36) DEFAULT NULL;
DECLARE proposedUID int DEFAULT NULL;
DECLARE currentAS bit DEFAULT NULL;
SELECT Salt
FROM tblPlayer
WHERE
Username = pUsername
INTO retrieveSalt; -- Retrieves the users SALT record
SELECT PlayerID
FROM tblPlayer
WHERE
AES_ENCRYPT(CONCAT(retrieveSalt, pPassword), 'Game_Key_To_Encrypt') = `Password`
AND pUsername = Username
INTO proposedUID; -- Retrieves the users Username and Password
SELECT ActiveStatus
FROM tblPlayer
WHERE
Username = pUsername
INTO currentAS;
IF proposedUID IS NULL AND currentAS = 0 THEN
UPDATE tblPlayer
SET FailedLogins = FailedLogins +1, AccountLocked = (FailedLogins +1) > 5, ActiveStatus = (FailedLogins +1) < 1
WHERE
Username = pUsername;
SELECT 'You have entered an incorrect Username or Password, after 5 failed attempts your account will be locked' AS MESSAGE;
-- Increments the failed logins, if it equals 5 then account is locked
ELSEIF proposedUID IS NOT NULL AND currentAS = 0 THEN
UPDATE tblPlayer
SET ActiveStatus = 1, FailedLogins = 0, AccountLocked = 0
WHERE
Username = pUsername;
SELECT 'Success' AS MESSAGE;
SELECT GameID AS 'GameID', COUNT(pl.GameID) AS 'PlayerCount'
FROM tblPlayer py
JOIN tblPlay pl ON py.PlayerID = pl.PlayerID
GROUP BY pl.GameID;
SELECT Username AS 'Player', HighScore AS 'HighScore'
FROM tblPlayer;
-- If credentials are correct user is logged into account by setting active status to true
ELSE
SELECT 'You are logged in' AS MESSAGE;
SELECT GameID AS 'GameID', COUNT(pl.GameID) AS 'PlayerCount'
FROM tblPlayer py
JOIN tblPlay pl ON py.PlayerID = pl.PlayerID
GROUP BY pl.GameID;
SELECT Username AS 'Player', HighScore AS 'HighScore'
FROM tblPlayer;
-- Conditions are met so user is already logged in
END IF;
END //
DELIMITER ;
Moving a player to an adjacent tile:
DROP PROCEDURE IF EXISTS MovePlayer;
DELIMITER //
CREATE DEFINER = 'root'@'localhost' PROCEDURE MovePlayer(
IN pTileID int,
IN pPlayerID int,
IN pGameID int
)
SQL SECURITY DEFINER
BEGIN
DECLARE currentTurn varchar(10) DEFAULT NULL;
DECLARE availableTile int DEFAULT NULL;
DECLARE ifPlayerOnTileAreTheyActive bit DEFAULT NULL;
DECLARE currentTileRow tinyint DEFAULT NULL;
DECLARE currentTileColumn tinyint DEFAULT NULL;
DECLARE newTileRow tinyint DEFAULT NULL;
DECLARE newTileColumn tinyint DEFAULT NULL;
SELECT CharacterTurn -- Checks the character turn for the game
FROM tblGame
WHERE
GameID = pGameID
INTO currentTurn;
SELECT TileID -- Checks if a tile is empty and available
FROM tblTile
WHERE
TileID NOT IN (SELECT TileID
FROM tblPlay
WHERE
GameID = pGameID)
AND TileID = pTileID
AND HomeTile = FALSE
INTO availableTile;
SELECT ActiveStatus -- Checks the active status if a player is on the tile selected
FROM tblPlayer pl
JOIN tblPlay py ON pl.PlayerID = py.PlayerID
WHERE
py.TileID = pTileID
AND GameID = pGameID
INTO ifPlayerOnTileAreTheyActive; -- This allows player to move to a tile with another player located but the active status is 0
SELECT TileRow -- The current player tile row
FROM tblTile ti
JOIN tblPlay pl ON ti.TileID = pl.TileID
WHERE
PlayerID = pPlayerID
AND GameID = pGameID
INTO currentTileRow;
SELECT TileColumn -- The current player tile column
FROM tblTile ti
JOIN tblPlay pl ON ti.TileID = pl.TileID
WHERE
PlayerID = pPlayerID
AND GameID = pGameID
INTO currentTileColumn;
SELECT TileRow -- The selected tile row
FROM tblTile
WHERE
TileID = pTileID
INTO newTileRow;
SELECT TileColumn -- The selected tile column
FROM tblTile
WHERE
TileID = pTileID
INTO newTileColumn;
BEGIN
IF ((newTileRow = currentTileRow OR newTileRow = currentTileRow + 1 OR newTileRow = currentTileRow - 1)
AND (newTileColumn = currentTileColumn OR newTileColumn = currentTileColumn + 1 OR newTileColumn = currentTileColumn - 1))
AND (availableTile IS NOT NULL OR ifPlayerOnTileAreTheyActive = 0 OR pTileID = 001)
AND (currentTurn = (SELECT CharacterName
FROM tblPlay
WHERE
PlayerID = pPlayerID
AND GameID = pGameID)) THEN
UPDATE tblPlay
SET TileID = pTileID
WHERE
PlayerID = pPlayerID
AND GameID = pGameID;
SELECT 'Your character has moved!!!' AS MESSAGE;
SELECT TileColour, TileRow, TileColumn
FROM tblCharacter ch
JOIN tblPlay pl ON ch.CharacterName = pl.CharacterName
JOIN tblTile ti ON pl.TileID = ti.TileID
WHERE
PlayerID = pPlayerID;
ELSE
SELECT 'Your character cant move to this tile!!!' AS MESSAGE;
END IF;
END;
END //
DELIMITER ;
C# Data Access & Program
Data Access in C# for the Login Check Credentials Procedure and Program to display a selection list menu:
// Login Check Credentials Procedure
public HomeDisplayData LoginCheckCredentials(string pUsername, string pPassword)
{
HomeDisplayData theHomeDisplayData = new HomeDisplayData();
List paramInput = new List();
var paramUsername = new MySqlParameter("@Username", MySqlDbType.VarChar, 10);
var paramPassword = new MySqlParameter("@Password", MySqlDbType.Blob);
paramUsername.Value = pUsername;
paramPassword.Value = pPassword;
paramInput.Add(paramUsername);
paramInput.Add(paramPassword);
var aDataSet = MySqlHelper.ExecuteDataset(DataAccess.mySqlConnection, "LoginCheckCredentials(@Username,@Password)", paramInput.ToArray());
var aMessage = (aDataSet.Tables[0].Rows[0])["MESSAGE"].ToString();
theHomeDisplayData.message = aMessage;
Console.WriteLine(aMessage);
if ((aMessage == "Success") || (aMessage == "You are logged in"))
{
theHomeDisplayData.GameCount = (from aResult in aDataSet.Tables[1].AsEnumerable()
select
new GameCount
{
GameID = Convert.ToInt32(aResult.ItemArray[0].ToString()),
PlayerCount = Convert.ToInt32(aResult.ItemArray[1].ToString())
}).ToList();
theHomeDisplayData.PlayerHighScore = (from aResult in aDataSet.Tables[2].AsEnumerable()
select
new PlayerHighScore
{
Player = aResult.Field("Player"),
HighScore = Convert.ToInt32(aResult.ItemArray[1].ToString())
}).ToList();
theHomeDisplayData.haveData = true;
return theHomeDisplayData;
}
else
{
return null;
}
}
namespace DAT602_ConsoleApp
{
class Program
{
static void Main(string[] args)
{
bool showMenu = true;
while (showMenu)
{
showMenu = MainMenu();
}
}
private static bool MainMenu()
{
Console.Clear();
Console.WriteLine("Choose an option:");
Console.WriteLine("1) Register account");
Console.WriteLine("2) User login");
Console.WriteLine("3) Create a new game");
Console.WriteLine("4) Join a game");
Console.WriteLine("5) Move a player");
Console.WriteLine("6) Find a gem");
Console.WriteLine("7) Select a gem");
Console.WriteLine("8) Update turn");
Console.WriteLine("9) Logout of game");
Console.WriteLine("10) Enter admin area");
Console.WriteLine("11) Kill a game");
Console.WriteLine("12) Add a new player");
Console.WriteLine("13) Update a players details");
Console.WriteLine("14) Delete a player");
Console.WriteLine("15) Exit");
Console.Write("\r\nSelect an option: ");
DataAccess aDataAccess = new DataAccess();
switch (Console.ReadLine())
{
case "1":
Console.WriteLine(aDataAccess.NewUserRegistration("ConsoleU_1@appmail.com", "ConsoleU_1", "P@ssword1"));
Console.ReadLine();
return true;
case "2":
var aHomePage = aDataAccess.LoginCheckCredentials("ConsoleU_1", "P@ssword1");
Console.WriteLine("List of games");
foreach (var item in aHomePage.GameCount)
{
Console.WriteLine("This game id is: " + item.GameID.ToString());
Console.WriteLine("This game's player count is: " + item.PlayerCount.ToString());
}
Console.WriteLine("List of players");
foreach (var item in aHomePage.PlayerHighScore)
{
Console.WriteLine("This player is: " + item.Player);
Console.WriteLine("Their high score is: " + item.HighScore.ToString());
}
Console.ReadLine();
return true;
case "3":
Console.WriteLine(aDataAccess.NewGame("ConsoleU_1"));
Console.ReadLine();
return true;
case "4":
Console.WriteLine(aDataAccess.JoinGame("100003", "1"));
Console.ReadLine();
return true;
case "5":
var aTileInfo = aDataAccess.MovePlayer("32", "9", "100003");
Console.WriteLine("Tile Details");
foreach (var item in aTileInfo.TileInfo)
{
Console.WriteLine("This tile colour is: " + item.TileColour);
Console.WriteLine("The tile row is: " + item.TileRow.ToString());
Console.WriteLine("The tile column is: " + item.TileColumn.ToString());
}
Console.ReadLine();
return true;
case "6":
var aGemSelection = aDataAccess.FindGem("50", "9", "100003");
if (aGemSelection != null)
{
foreach (var item in aGemSelection.GemSelection)
{
Console.WriteLine("List of gems");
Console.WriteLine("This item id is: " + item.ItemID.ToString());
Console.WriteLine("This gem type is: " + item.GemType);
Console.WriteLine("The points are: " + item.Points.ToString());
Console.WriteLine("The game id is: " + item.GameID.ToString());
Console.WriteLine("This player id is: " + item.PlayerID.ToString());
Console.WriteLine("This play id is: " + item.PlayID.ToString());
Console.WriteLine("This tile id is: " + item.TileID.ToString());
}
}
Console.ReadLine();
return true;