How to manage distant database with C# and PHP - c#

I don't know how to process, and when i search in the internet, there is so many solutions, I'm a bit lost.
My task is to create a leaderboard, the game is developed in C# with unity and my internship supervisor just told me "You have to put some PHP into the database server of our client and then make a "bridge" between our game and this PHP"
I never used C# before (Java is sooo cooler) any advice, source with commented code "easy" to understand?

You may want to write your API. You will then call it with C# using web requests.
A very simple way to get data from your database is to switch through given endpoints in your the URL.
For instance, the following URL: http://yourserver.com/api/v1/?leaderboard/top
You may explode the URL to get the endpoints with $endpoints = explode('/', rtrim($_SERVER['QUERY_STRING'], '/'));. In this case, $endpoints[0] would give leaderboard.
You could then use a switch statement to handle your request.
// ...
$endpoints = explode('/', rtrim($_SERVER['QUERY_STRING'], '/'));
switch ($endpoints[0])
{
case 'leaderboard':
{
switch ($endpoints[1])
{
case 'top':
// Ask your database
$result = get_top_leaderboard();
echo json_encode($result);
break;
// case ...
}
break;
// case...
}
}
// ...
Use the same method with $_POST to get user entries, and write them in your database. Do not forget to protect yourself from SQL injections.
In C#, perform a GET request on your API:
var responseString = await client.GetStringAsync("http://yourserver.com/api/v1/?leaderboard/top");
Keep in mind this exemple is not secured. If you want to get sensible data from your database, do not let your API unsecured with public access.

Related

Realm sync permissions for flexibly-named partitions based on user id

I'm new to Realm Sync (and Realm). I'm trying to convert a REST / SQL Server system to Realm Sync (to avoid having to write my own local-device caching code).
I got a simple configuration working, with a single API-key user and the null partition, read and write permissions just set to true.
But for my more complex application, I want smaller sub-partitions to reduce the amount of data that needs to be cached on local devices, and I want the sub-partitions to be able to be created dynamically by the client. Ideally, I would like to allow an API-key user to connect to any partition whose name starts with their user id (or some other known string, e.g. the profile name). But I can't find a way to get a "starts with" condition into the permissions.
My best attempt was to try setting Read and Write sync permissions to:
{
"%%partition": {
"$regex": "^%%user.id"
}
}
but my client just fails to connect, saying Permission denied (BIND, REFRESH). (Yes, I tried using "$regex": /^%%user.id/ but the Realm UI rejected that syntax.) The Realm Sync log says "user does not have permission to sync on partition (ProtocolErrorCode=206)".
As you can see in the log image, the partition name was equal to the user id for this test.
Is what I'm trying to do possible? If so, how do I set up the Sync Permissions to make it work?
This can be done using a function. If, like me, you're new to Realm Sync and not fluent in Javascript, don't worry - it turns out to be not too hard to do, after all. (Thanks Jay for encouraging me to try it!)
I followed the instructions on the Define a Function page to create my userCanAccessPartition function like this:
exports = function(partition){
return partition.startsWith(context.user.id);
};
Then I set my sync permissions to:
{
"%%true": {
"%function": {
"name": "userCanAccessPartition",
"arguments": ["%%partition"]
}
}
}

Comunication between Location-based game and PHP REST webservice

I'm making a PokemonGo-like game.
Simply, each player chooses which faction to belong (indicated by three different colors); The main purpose of the game is to capture the towers that the server creates close to the player's geographical position.
Much of what I've described above has already been implemented and almost functional, but I have many doubts about the database and communication with it. I have currently written a REST web service in php that allows me to check if the players are registered and if they are online. Basically, in the player client in Unity I created a simple login interface where, after writing username and password, these data are inserted into a WWWForm object and the following call, UnityWebRequest.Post (loginUrl, form) , I can understand if the data entered corresponds to a registered user or not.
LoginStatus logInStatus = new LoginStatus();
var form = new WWWForm();
form.AddField("username",id); //id,pass = textField
form.AddField("password",pass);
using (UnityWebRequest www = UnityWebRequest.Post(loginUrl, form))
{
yield return www.Send();
if (www.isNetworkError)
gui.activatePopUp("Connection error, retry!");
else
{
var postResponse = www.downloadHandler.text;
gui.activatePopUp(logInStatus.getMessage(postResponse));
if (logInStatus.Success)
{
infos.username = id;
infos.password = pass;
SceneManager.LoadSceneAsync("ClientScene");
}
}
}
The loginUrl is a string variable that contains the login REST service address. So far, it's all simple and acceptable. The problem is that in the future I will need to retrieve much more information from the database, ie a player will be represented, for example, by the attributes Username, Faction, Level and so on. so what is the most appropriate way to intelligently communicate such an application with a web service rest? How do I make a smart mapping between my business classes and the relational model? Currently, the REST service queries a remote MySQL database.
Can some ORM be used?
A first solution I thought about is to apply the DAO pattern, let me return the records from the database as JSON and use a parser that recreates the objects. Do you think it's smart enough and efficient as a solution?

couchbase lite xamarin pull replication with sync-gateway

I want to pull documents with username attribute
as user1 for user1 like that for each user only attribute with their name.
This is my replication code.
private void setupreplication(){
Console.WriteLine ("Setting up replication");
Uri Server = new Uri("http://192.168.1.213:4984/aussie-coins-syncgw/");
var pull = _db.CreatePullReplication (Server);
var push = _db.CreatePushReplication (Server);
pull.Filter = "byUser";
pull.FilterParams = new Dictionary<string, object> { {"type", "user1"} };
pull.Continuous = true;
push.Continuous = true;
pull.Start();
push.Start();
}
This is my set filter code
_couchBaseLiteLocal.SetFilter("byUser", (revision, filterParams) =>
{
var typeParam = filterParams["type"].ToString();
return (typeParam != null) && typeParam.Equals("user1");
});
With the above code generic pull itself not working.
I just tried to do as given in the documentation.
I do not understand how the setfilter function works to filter data from server. It would be great if someone help in understanding how setfilter works and to make the above code working
Thanks in advance.
The filter function in pull replications can indeed return the specific documents you are interested in. But it's not very efficient, the filter function will run on all the documents on the remote database to determine which ones to pull, every time a pull replication is started.
Instead Sync Gateway introduces the concept of a sync function that incrementally routes and computes access control rules on documents. That way, when starting the pull replication, it's fast and straightforward for Sync Gateway to return the specific documents the user has access to.
You can specify individual channels in a pull replication from Sync Gateway if needed. But the thing to remember is that filtered pull replication between Sync Gateway and Couchbase Lite is not based on filter functions. It's based on the sync function and channel based filtering if needed.
In a P2P scenario (replications between two Couchbase Lite instances), the filter function model is used.

saving get data to a local variable

I was wondering is there a way to save get parameters that the website sends to the server to be saved to a local variable via java script. something like a cookie or the session variable.
EDIT 1:
I am also willing to save it to a server-side cookie, but i still don't know how to do that.
i am using MVC4 in VisualStudio with C# as server-side lang. if there is an easier method to do it server side I'm up for that.
EDIT 2
The comment game me an idea, and i managed to get the solution via the session class server-side. thanks ppl :)
function getUrlParams() {
var params = {};
window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(str,key,value) {
params[key] = value;
});
return params;
}
Using the Session.AddItem method i was able to save all the data i needed. thanks for your help guys.

Finding Connection by UserId in SignalR

I have a webpage that uses ajax polling to get stock market updates from the server. I'd like to use SignalR instead, but I'm having trouble understanding how/if it would work.
ok, it's not really stock market updates, but the analogy works.
The SignalR examples I've seen send messages to either the current connection, all connections, or groups. In my example the stock updates happen outside of the current connection, so there's no such thing as the 'current connection'. And a user's account is associated with a few stocks, so sending a stock notification to all connections or to groups doesn't work either. I need to be able to find a connection associated with a certain userId.
Here's a fake code example:
foreach(var stock in StockService.GetStocksWithBigNews())
{
var userIds = UserService.GetUserIdsThatCareAboutStock(stock);
var connections = /* find connections associated with user ids */;
foreach(var connection in connections)
{
connection.Send(...);
}
}
In this question on filtering connections, they mention that I could keep current connections in memory but (1) it's bad for scaling and (2) it's bad for multi node websites. Both of these points are critically important to our current application. That makes me think I'd have to send a message out to all nodes to find users connected to each node >> my brain explodes in confusion.
THE QUESTION
How do I find a connection for a specific user that is scalable? Am I thinking about this the wrong way?
I created a little project last night to learn this also. I used 1.0 alpha and it was Straight forward. I created a Hub and from there on it just worked :)
I my project i have N Compute Units(some servers processing work), when they start up they invoke the ComputeUnitRegister.
await HubProxy.Invoke("ComputeUnitReqisted", _ComputeGuid);
and every time they do something they call
HubProxy.Invoke("Running", _ComputeGuid);
where HubProxy is :
HubConnection Hub = new HubConnection(RoleEnvironment.IsAvailable ?
RoleEnvironment.GetConfigurationSettingValue("SignalREndPoint"):
"http://taskqueue.cloudapp.net/");
IHubProxy HubProxy = Hub.CreateHubProxy("ComputeUnits");
I used RoleEnviroment.IsAvailable because i can now run this as a Azure Role , a Console App or what ever in .NET 4.5. The Hub is placed in a MVC4 Website project and is started like this:
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(50);
RouteTable.Routes.MapHubs();
public class ComputeUnits : Hub
{
public Task Running(Guid MyGuid)
{
return Clients.Group(MyGuid.ToString()).ComputeUnitHeartBeat(MyGuid,
DateTime.UtcNow.ToEpochMilliseconds());
}
public Task ComputeUnitReqister(Guid MyGuid)
{
Groups.Add(Context.ConnectionId, "ComputeUnits").Wait();
return Clients.Others.ComputeUnitCameOnline(new { Guid = MyGuid,
HeartBeat = DateTime.UtcNow.ToEpochMilliseconds() });
}
public void SubscribeToHeartBeats(Guid MyGuid)
{
Groups.Add(Context.ConnectionId, MyGuid.ToString());
}
}
My clients are Javascript clients, that have methods for(let me know if you need to see the code for this also). But basicly they listhen for the ComputeUnitCameOnline and when its run they call on the server SubscribeToHeartBeats. This means that whenever the server compute unit is doing some work it will call Running, which will trigger a ComputeUnitHeartBeat on javascript clients.
I hope you can use this to see how Groups and Connections can be used. And last, its also scaled out over multiply azure roles by adding a few lines of code:
GlobalHost.HubPipeline.EnableAutoRejoiningGroups();
GlobalHost.DependencyResolver.UseServiceBus(
serviceBusConnectionString,
2,
3,
GetRoleInstanceNumber(),
topicPathPrefix /* the prefix applied to the name of each topic used */
);
You can get the connection string on the servicebus on azure, remember the Provider=SharedSecret. But when adding the nuget packaged the connectionstring syntax is also pasted into your web.config.
2 is how many topics to split it about. Topics can contain 1Gb of data, so depending on performance you can increase it.
3 is the number of nodes to split it out on. I used 3 because i have 2 Azure Instances, and my localhost. You can get the RoleNumber like this (note that i hard coded my localhost to 2).
private static int GetRoleInstanceNumber()
{
if (!RoleEnvironment.IsAvailable)
return 2;
var roleInstanceId = RoleEnvironment.CurrentRoleInstance.Id;
var li1 = roleInstanceId.LastIndexOf(".");
var li2 = roleInstanceId.LastIndexOf("_");
var roleInstanceNo = roleInstanceId.Substring(Math.Max(li1, li2) + 1);
return Int32.Parse(roleInstanceNo);
}
You can see it all live at : http://taskqueue.cloudapp.net/#/compute-units
When using SignalR, after a client has connected to the server they are served up a Connection ID (this is essential to providing real time communication). Yes this is stored in memory but SignalR also can be used in multi-node environments. You can use the Redis or even Sql Server backplane (more to come) for example. So long story short, we take care of your scale-out scenarios for you via backplanes/service bus' without you having to worry about it.

Categories