How to have a property add and sync when player spawn - multiplayer

Have a bit of problem understanding how to have the property theNumber add and sync.
1) I have two players
2) When the players spawn I want theNumber to add one so each player report a different sequential number
I just do not get it to work and would appreciate some help.
The following code is placed on the players that are spawned.
using UnityEngine;
using System.Collections;
using UnityEngine.Networking;
public class Player : NetworkBehaviour {
[SyncVar] public int theNumber;
private int _nr;
public override void OnStartLocalPlayer () {
print ("OnStartLocalPlayer");
_nr = theNumber;
CmdX (theNumber);
DoCalc ();
}
[Command]
void CmdX (int myInt) {
print ("theNumber: " + myInt);
}
[Client]
void DoCalc () {
_nr++;
CmdPrint (_nr);
}
[Command]
void CmdPrint (int nr) {
theNumber = nr;
print ("CLIENT CONNECTED WITH THE FOLLOWING NUMBER: " + theNumber);
}
}

You will want to change the value on the server when a new client connects and send it down. From the looks of it, you're modifying the value on the client only. Additionally, your [SyncVar] attribute on theNumber will synchronize the value across clients, so it may be changing it to the same value for each client.
Read more here: http://docs.unity3d.com/ScriptReference/Networking.SyncVarAttribute.html

Related

Retrying a complete testNG class and not just #Test method on skip/failure

I have implemented IRetryAnalyzer to re-run my failed test cases in my testNG class.
public class Retry implements IRetryAnalyzer {
private int retryCount = 0;
private int maxRetryCount = 1;
private int outcome;
// Below method returns 'true' if the test method has to be retried else 'false'
//and it takes the 'Result' as parameter of the test method that just ran
public boolean retry(ITestResult result) {
//outcome=result.getStatus();
if (retryCount < maxRetryCount ) {
result.getTestContext().getFailedTests().removeResult(result);
result.getTestContext().getSkippedTests().removeResult(result);
System.out.println("Retrying test " + result.getName() + " with status "
+ getResultStatusName(result.getStatus()) + " for the " + (retryCount+1) + " time(s).");
Reporter.log("Retrying test " + result.getName() + " with status "
+ getResultStatusName(result.getStatus()) + " for the " + (retryCount+1) + " time(s).");
retryCount++;
return true;
}
return false;
}
public String getResultStatusName(int status) {
String resultName = null;
if(status==1)
resultName = "SUCCESS";
if(status==2)
resultName = "FAILURE";
if(status==3)
resultName = "SKIP";
return resultName;
}
}
Now I have two Test methods:
#Test(priority = 3, enabled = true, dependsOnMethods={"step2"})
public void step3()
{.....................some code......}
#Test(priority = 4, enabled = true,dependsOnMethods={"step3"})
public void step4() {
....some codee..}
If step 3 fails, testNG skips step 4 which is as expected. But upon re-run it executes only step 3 and even if it passed at second attempt, step 4 which was skipped is not executed.
Is there any way I can re-run my whole TestNG failed class or an alternate solution to run my dependent cases after the #Test method they depend on fails.
Thanks in advance!
Please do the following to get this to work:
Remove the logic of removing failed and skipped tests from your org.testng.IRetryAnalyzer implementation i.e., the below two lines
result.getTestContext().getFailedTests().removeResult(result);
result.getTestContext().getSkippedTests().removeResult(result);
Include this logic of removing the skipped/failed tests from within either an #AfterMethod method (or) from within an afterInvocation() of a org.testng.IInvokedMethodListener listener implementation.
Something like below :
#AfterMethod
public void afterMethod(ITestResult result) {
IRetryAnalyzer retry = result.getMethod().getRetryAnalyzer();
if (retry == null) {
return;
}
result.getTestContext().getFailedTests().removeResult(result.getMethod());
result.getTestContext().getSkippedTests().removeResult(result.getMethod());
}
(or)
import org.testng.IInvokedMethod;
import org.testng.IInvokedMethodListener;
import org.testng.IRetryAnalyzer;
import org.testng.ITestResult;
public class Listener implements IInvokedMethodListener {
#Override
public void beforeInvocation(IInvokedMethod method, ITestResult testResult) {
}
#Override
public void afterInvocation(IInvokedMethod method, ITestResult result) {
IRetryAnalyzer retry = result.getMethod().getRetryAnalyzer();
if (retry == null) {
return;
}
result.getTestContext().getFailedTests().removeResult(result.getMethod());
result.getTestContext().getSkippedTests().removeResult(result.getMethod());
}
}
If you leverage the listener path, please ensure that you wire in the listener using one of the following ways :
via #Listeners annotation (or)
via <listeners> tag (or)
via service loaders in TestNG.
For more information refer to my blog post here.
Additing to the Krishnan Mahadevan answer, you can chose to skip
result.getTestContext().getFailedTests().removeResult(result.getMethod());
If you remove a failed test method then, depending on test case (step4) will be executed even when step3 gets fail after retry.

Schedule/batch for large number of webservice callouts?

I'am new to Apex and I have to call a webservice for every account (for some thousands of accounts).
Usualy a single webservice request takes 500 to 5000 ms.
As far as I know schedulable and batchable classes are required for this task.
My idea was to group the accounts by country codes (Europe only) and start a batch for every group.
First batch is started by the schedulable class, next ones start in batch finish method:
global class AccValidator implements Database.Batchable<sObject>, Database.AllowsCallouts {
private List<String> countryCodes;
private countryIndex;
global AccValidator(List<String> countryCodes, Integer countryIndex) {
this.countryCodes = countryCodes;
this.countryIndex = countryIndex;
...
}
// Get Accounts for current country code
global Database.QueryLocator start(Database.BatchableContext bc) {...}
global void execute(Database.BatchableContext bc, list<Account> myAccounts) {
for (Integer i = 0; i < this.AccAccounts.size(); i++) {
// Callout for every Account
HttpRequest request ...
Http http = new Http();
HttpResponse response = http.send(request);
...
}
}
global void finish(Database.BatchableContext BC) {
if (this.countryIndex < this.countryCodes.size() - 1) {
// start next batch
Database.executeBatch(new AccValidator(this.countryCodes, this.countryIndex + 1), 200);
}
}
global static List<String> getCountryCodes() {...}
}
And my schedule class:
global class AccValidatorSchedule implements Schedulable {
global void execute(SchedulableContext sc) {
List<String> countryCodes = AccValidator.getCountryCodes();
Id AccAddressID = Database.executeBatch(new AccValidator(countryCodes, 0), 200);
}
}
Now I'am stuck with Salesforces execution governors and limits:
For nearly all callouts I get the exceptions "Read timed out" or "Exceeded maximum time allotted for callout (120000 ms)".
I also tried asynchronous callouts, but they don't work with batches.
So, is there any way to schedule a large number of callouts?
Have you tried to limit your execute method to 100? Salesforce only allows 100 callout per transaction. I.e.
Id AccAddressID = Database.executeBatch(new AccValidator(countryCodes, 0), 100);
Perhaps this might help you:
https://salesforce.stackexchange.com/questions/131448/fatal-errorsystem-limitexception-too-many-callouts-101

Assign randomly chosen, but matching parameters for connected OMNeT++ gates?

I'm developing a network model in OMNeT++ in which I have introduced a custom channel type to represent links in my network. For one property of this channel type's instances, I'd like to assign a random parameter. However, the random number should be the same for connected gates.
My node definition has the following gates definition:
simple GridAgent
{
/* ... other paramters/definitions omitted ... */
gates:
inout agentConnections[];
}
In my network configuration, I connect nodes using the simple <--> syntax, e.g.:
someSwitchyard.agentConnections++ <--> AgentConnectionChannel <--> someWindfarm.agentConnections++;
Now, this AgentConnectionChannel has a property called impedance, which I'd like to randomly assign. This impedance property should be the same for both A -> B and B -> A. I have tried to add { impedance = default(unitform(1, 10)) } to the network definition, as well as putting **.agentConnections$o[*].channel.impedance = uniform(1, 10) into omnetpp.ini. In both cases, however, A -> B has a different value assigned than B -> A.
As indicated on the OMNet++ mailing list, this happens because the <--> syntax is actually a shorthand for creating two distinct connections, hence two drawings from the random number distribution happen.
How can I assign a random parameter to a connection's property and have the same value for both directions of two connected gates? Is there a way to do this in the omnetpp.ini file, or do I need to create a script in, e.g., Perl, Ruby, or Python to generate the omnetpp.ini for my runs?
There is no simple solution of your problem, and it could not be resolved manipulating omnetpp.ini file merely.
I propose manual rewriting a parameter value for the second direction. It requires preparing a C++ class for a channel (which you have probably done).
Assuming that your channel definition in NED is following:
channel AgentConnectionChannel extends ned.DatarateChannel {
#class(AgentConnectionChannel);
double impedance;
}
and in omnetpp.ini you has:
**.agentConnections$o[*].channel.impedance = uniform(1, 10)
you should prepare C++ class AgentConnectionChannel:
class AgentConnectionChannel: public cDatarateChannel {
public:
AgentConnectionChannel() : parAlreadyRewritten(false) {}
void setParAlreadyRewritten() {parAlreadyRewritten=true;}
protected:
virtual void initialize();
private:
bool parAlreadyRewritten;
private:
double impedance;
};
Define_Channel(AgentConnectionChannel);
void AgentConnectionChannel::initialize() {
if (parAlreadyRewritten == false) {
parAlreadyRewritten = true;
cGate * srcOut = this->getSourceGate();
cModule *owner = srcOut->getOwnerModule();
int index = srcOut->isVector() ? srcOut->getIndex() : -1;
cGate *srcIn = owner->gateHalf(srcOut->getBaseName(), cGate::INPUT,
index);
cChannel * channel = srcIn->findIncomingTransmissionChannel();
AgentConnectionChannel * reverseChan =
dynamic_cast<AgentConnectionChannel*>(channel);
if (reverseChan) {
reverseChan->setParAlreadyRewritten();
// assigning a value from forward direction channel
reverseChan->par("impedance") = this->par("impedance");
}
}
// and now read a parameter as usual
impedance = par("impedance").doubleValue();
EV << getFullPath() << ", impedance=" << impedance << endl;
}

Location not being saved to config.yml

I'm trying to save a Location in a config.yml, and when he steps onto that location, it provokes an action. However, that is not happening.
Sorry for including the entire code, but I thought it would be essential for this kind of program.
Main class:
public class Turrets extends JavaPlugin{
ArrayList<String> playersThatShouldPlaceBlock = new ArrayList<String>();
HashMap<String, String> turretName = new HashMap<String, String>();
String turretsMsg = ChatColor.RED + "[" + ChatColor.GOLD + "Turrets" + ChatColor.RED + "]" + ChatColor.GOLD + ": ";
public int waitForPlacement;
public void loadConfig() {
this.getConfig().addDefault("Turrets.", null);
this.saveConfig();
}
public void onEnable(){
new CreateTurretEvent(this);
loadConfig();
}
public void onDisable(){
loadConfig();
}
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args){
final Player p = (Player) sender;
if (cmd.getName().equalsIgnoreCase("turret")){
if (args.length < 2){
p.sendMessage(turretsMsg + ChatColor.RED + "Invalid usage! /turret [create or delete] [name]");
return true;
}
else if (args.length >= 2){
if (args[0].equalsIgnoreCase("create")){
if (args[1] != null){
p.sendMessage(turretsMsg + ChatColor.GOLD + "Place a block and YOU will become a turret when you step on it!");
playersThatShouldPlaceBlock.add(p.getName());
turretName.put(p.getName(), args[1]);
waitForPlacement = Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable(){
#Override
public void run() {
p.sendMessage(turretsMsg + ChatColor.RED + "You waited too long so the action was cancelled!");
playersThatShouldPlaceBlock.remove(p.getName());
}
}, 600L);
return true;
}
}
}
}
return false;
}
}
Listener class:
package me.mortadelle2.turrets;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerMoveEvent;
public class CreateTurretEvent implements Listener{
Turrets getter;
public CreateTurretEvent(Turrets plugin){
plugin.getServer().getPluginManager().registerEvents(this, plugin);
getter = plugin;
}
#EventHandler
public void playerPlacesBlockToBecomeTurret(BlockPlaceEvent e){
Player p = e.getPlayer();
if (getter.playersThatShouldPlaceBlock.contains(p.getName())){
p.sendMessage(getter.turretsMsg + "That block is now turretified!");
getter.getServer().getScheduler().cancelTask(getter.waitForPlacement);
getter.playersThatShouldPlaceBlock.remove(p.getName());
Location blockLocation = e.getBlock().getLocation();
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName()), blockLocation);
}
}
#EventHandler
public void playerStepsOnTurret(PlayerMoveEvent e){
Player p = e.getPlayer();
if (getter.getConfig().contains("test")){ //I will add something more specific than test later
p.sendMessage("This is a test");
}
}
}
Problem 1: spelling mistake (this problem has been edited out of the question at question revision 3)
You seem to have misspelled onDisbale(){. When a plugin is disabled, it will run the method onDisable() on your plugin. In your case it isn't run because you don't have a method with that exact signature.
How to prevent this in the future
By added #Override at the start of a method, you are saying that it MUST override a existing method found in a parent class. This can be used like:
#Override
public void onDisable() {
Problem 2: Implementation of the PlayerMoveEvent isn't finished yet
Notice, stackoverflow isn't a "we write code for you service"
By analyzing your code, you are saving your config in the following format:
playername:
turretname: (location object)
Step 1: changing the location saving
The bukkit configuration doesn't work properly with Location objects, you should change your location saving to
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".world", player.getLocation().getWorld().getName());
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".x", player.getLocation().getBlockX());
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".y", player.getLocation().getBlockY());
getter.getConfig().set("Turrets." + getter.turretName.get(p.getName())+ ".z", player.getLocation().getBlockZ());
This changes the configuration to store the world, x, y and z seperately
Step 2: parsing the config at the PlayerMoveEvent
Because we changed our config format, it will be easier to detect what turret we are standing on at the PlayerMoveEvent
We will the following method of detecting what block we are standing on at the PlayerMove
Check if the turret exists inside the configuration
ConfigurationSection sec = getter.getConfig().getConfigurationSection("Turrets."+getter.turretName.get(p.getName()));
// Todo: check if the player exists inside getter.turretName
if(sec != null){
....
}
Parse the configuration to check if the location is found
Location loc = event.getPlayer().getLocation();
if(loc.getBlockX() == sec.getInt("x") && loc.getBlockY() == sec.getInt("y") && loc.getBlockZ() == sec.getInt("z") && loc.getWorld().getName().equals(sec.getString("world"))) {
event.getPlayer().sendMessage("This is a test");
}
This should fix the problem you are having. The following improvements can be done:
Only call the player move code when the player changes the block
Use more descriptive variable names, for example getter should be renamed to main or plugin

MySQL Asynchronous?

Im basically facing a blocking problem.
I have my server coded based on C++ Boost.ASIO using 8 threads since the server has 8 logical cores.
My problem is a thread may face 0.2~1.5 seconds of blocking on a MySQL query and I honestly don't know how to go around that since MySQL C++ Connector does not support asynchronous queries, and I don't know how to design the server "correctly" to use multiple threads for doing the queries.
This is where I'm asking for opinions of what to do in this case.
Create 100 threads for async' query sql?
Could I have an opinion from experts about this?
Okay, the proper solution to this would be to extend Asio and write a mysql_service implementation to integrate this. I was almost going to find out how this is done right away, but I wanted to get started using an "emulation".
The idea is to have
your business processes using an io_service (as you are already doing)
a database "facade" interface that dispatches async queries into a different queue (io_service) and posts the completion handler back onto the business_process io_service
A subtle tweak needed here you need to keep the io_service on the business process side from shutting down as soon as it's job queue is empty, since it might still be awaiting a response from the database layer.
So, modeling this into a quick demo:
namespace database
{
// data types
struct sql_statement { std::string dml; };
struct sql_response { std::string echo_dml; }; // TODO cover response codes, resultset data etc.
I hope you will forgive my gross simplifications :/
struct service
{
service(unsigned max_concurrent_requests = 10)
: work(io_service::work(service_)),
latency(mt19937(), uniform_int<int>(200, 1500)) // random 0.2 ~ 1.5s
{
for (unsigned i = 0; i < max_concurrent_requests; ++i)
svc_threads.create_thread(boost::bind(&io_service::run, &service_));
}
friend struct connection;
private:
void async_query(io_service& external, sql_statement query, boost::function<void(sql_response response)> completion_handler)
{
service_.post(bind(&service::do_async_query, this, ref(external), std::move(query), completion_handler));
}
void do_async_query(io_service& external, sql_statement q, boost::function<void(sql_response response)> completion_handler)
{
this_thread::sleep_for(chrono::milliseconds(latency())); // simulate the latency of a db-roundtrip
external.post(bind(completion_handler, sql_response { q.dml }));
}
io_service service_;
thread_group svc_threads; // note the order of declaration
optional<io_service::work> work;
// for random delay
random::variate_generator<mt19937, uniform_int<int> > latency;
};
The service is what coordinates a maximum number of concurrent requests (on the "database io_service" side) and ping/pongs the completion back onto another io_service (the async_query/do_async_query combo). This stub implementation emulates latencies of 0.2~1.5s in the obvious way :)
Now comes the client "facade"
struct connection
{
connection(int connection_id, io_service& external, service& svc)
: connection_id(connection_id),
external_(external),
db_service_(svc)
{ }
void async_query(sql_statement query, boost::function<void(sql_response response)> completion_handler)
{
db_service_.async_query(external_, std::move(query), completion_handler);
}
private:
int connection_id;
io_service& external_;
service& db_service_;
};
connection is really only a convenience so we don't have to explicitly deal with various queues on the calling site.
Now, let's implement a demo business process in good old Asio style:
namespace domain
{
struct business_process : id_generator
{
business_process(io_service& app_service, database::service& db_service_)
: id(generate_id()), phase(0),
in_progress(io_service::work(app_service)),
db(id, app_service, db_service_)
{
app_service.post([=] { start_select(); });
}
private:
int id, phase;
optional<io_service::work> in_progress;
database::connection db;
void start_select() {
db.async_query({ "select * from tasks where completed = false" }, [=] (database::sql_response r) { handle_db_response(r); });
}
void handle_db_response(database::sql_response r) {
if (phase++ < 4)
{
if ((id + phase) % 3 == 0) // vary the behaviour slightly
{
db.async_query({ "insert into tasks (text, completed) values ('hello', false)" }, [=] (database::sql_response r) { handle_db_response(r); });
} else
{
db.async_query({ "update * tasks set text = 'update' where id = 123" }, [=] (database::sql_response r) { handle_db_response(r); });
}
} else
{
in_progress.reset();
lock_guard<mutex> lk(console_mx);
std::cout << "business_process " << id << " has completed its work\n";
}
}
};
}
This business process starts by posting itself on the app service. It then does a number of db queries in succession, and eventually exits (by doing in_progress.reset() the app service is made aware of this).
A demonstration main, starting 10 business processes on a single thread:
int main()
{
io_service app;
database::service db;
ptr_vector<domain::business_process> bps;
for (int i = 0; i < 10; ++i)
{
bps.push_back(new domain::business_process(app, db));
}
app.run();
}
In my sample, business_processes don't do any CPU intensive work, so there's no use in scheduling them across CPU's, but if you wanted you could easily achieve this, by replacing the app.run() line with:
thread_group g;
for (unsigned i = 0; i < thread::hardware_concurrency(); ++i)
g.create_thread(boost::bind(&io_service::run, &app));
g.join_all();
See the demo running Live On Coliru
I'm not a MySQL guru, but the following is generic multithreading advice.
Having NumberOfThreads == NumberOfCores is appropriate when none of the threads ever block and you are just splitting the load over all CPUs.
A common pattern is to have multiple threads per CPU, so one is executing while another is waiting on something.
In your case, I'd be inclined to set NumberOfThreads = n * NumberOfCores where 'n' is read from a config file, a registry entry or some other user-settable value. You can test the system with different values of 'n' to fund the optimum. I'd suggest somewhere around 3 for a first guess.