Home > Mobile >  Object.values() not updating variable
Object.values() not updating variable

Time:11-21

I have the variable G.playerStatsDifference defined as an array of objects:

playerStatsDifference: [{
        carpenter: 0,
        wood: 0,
        gunman: 0,
        gunpowder: 0,
        merchant: 0,
        gold: 0,
        fleet: 0,
        flagship: 0,
    }, {
        carpenter: 0,
        wood: 0,
        gunman: 0,
        gunpowder: 0,
        merchant: 0,
        gold: 0,
        fleet: 0,
        flagship: 0,
    }]

The point of this variable is to calculate the difference between G.playerStats which frequently changes.

My function to calculate the difference is:

const oldPlayerStats = JSON.parse(JSON.stringify(G.playerStats));
statsDifference(G, oldPlayerStats);  

for (let p = 0; p < 2; p  ) { 
    for (let s = 0; s < 8; s  ) { 
        Object.values(G.playerStatsDifference[p])[s] = Object.values(G.playerStats[p])[s] - Object.values(oldPlayerStats[p])[s];
    }    
}

The expected output would be to have playerStatsDifference

When running some tests I did some console logging and it gave me the correct calculations, but the G.playerStatsDiffence would not update.

Here is some of that testing, with the calulations being correct:

console.log("Current wood is "   Object.values(G.playerStats[0])[1]); //Current wood is 5
console.log("Old wood is "   Object.values(oldPlayerStats[0])[1]); //Old wood is 10
console.log(Object.values(G.playerStats[0])[1] - Object.values(oldPlayerStats[0])[1]); //-5

I thought maybe I was doing something wrong with the loops so I tried the following afterwards:

Object.values(G.playerStatsDifference[0])[1] = Object.values(G.playerStats[0])[1] - Object.values(oldPlayerStats[0])[1];

However this did not work either. Having said that, the following does work:

G.playerStatsDifference[0].wood = Object.values(G.playerStats[0])[1] - Object.values(oldPlayerStats[0])[1];

So it seems like I have some issue with the Object.values on G.playerStatsDifference. Any idea on why that is and how I can run that through the loop?

=====

EDIT: As those in the comments have pointed out my question is a bit confusing so I will try to clear it up here..

The G.playerStatsDifference value is supposed to track the difference between the previous value of G.playerStats and the current value of G.playerStats.

To do this I am setting the value of oldPlayerStats to equal G.playerStats and then updating G.playerStats to its new value.

I then need to run through the array of objects and subtract the value of G.playerStats from oldPlayerStats. This will produce the value of G.playerStatsDifference

That is what the loop is for, to go through each object key and do the calculation.

Hope this provides some clarity. Sorry for the poorly worded question.

CodePudding user response:

// for testing purposes, create an object with some random stats
const randomPlayerStats = () => Object.fromEntries(
  ['carpenter','wood','gunman','gunpowder','merchant','gold','fleet','flagship']
    .map(k=>[k,Math.random()*10|0]));

// array of the last player stats recorded for each player
let lastPlayerStats = [];

// create a new object from the existing object, subtracting each entry
// from the old object from the entry from the new object
// note: uses the ?? operator so that if there is no last object yet,
// the last object value will be treated as being zero
const difference = (playerStats, lastPlayerStats) => {
  let r = Object.fromEntries(Object.entries(playerStats).map(([k,v])=>
    [k, v-(lastPlayerStats?.[k]??0)]));
  lastPlayerStats = playerStats;
  return r;
};

// simulate 5 rounds of the game, with 2 players in the game
const playerCount = 2;
const simulatedRounds = 5;
for(let c=0;c<simulatedRounds;c  ) {
  let playerStats = [...Array(playerCount).keys()].map(i=>randomPlayerStats());
  let playerStatsDifference = playerStats.map((s,i)=>
    difference(s, lastPlayerStats[i]??{}));
  console.log('playerStats:');
  console.log(playerStats);
  console.log('playerStatsDifference:');
  console.log(playerStatsDifference);
}

CodePudding user response:

const diffBetweenObjectValues = (a, b) => {
  return Object.entries(a).reduce((result, [aKey, aVal]) => {
    result[aKey] = aVal - (b[aKey] ?? 0);
    return result;
  }, {});
}

const stats = { a: 1, b: 2 };
const updatedStats = { a: 1, b: 1 };

// Initial player stats are { a: 1, b: 2 }
const player = { stats: stats, diff: {} };

// Set the diff, value is { a: 0, b: 1 }
player.diff = diffBetweenObjectValues(player.stats, updatedStats);

// Actually update the stats, value is { a: 1, b: 1 }
player.stats = updatedStats;

Note that if a key is present in b but not a it's ignored. Also note that this only works properly if all the property values are numeric.

You can put the state transition in a function and just run it when you need to update the stats (like every tick of the game loop).

Response to comment

Ok, lets add another helper function

const zip = (a, b) => a.map((x, i) => [x, b[i]]);

const players = [...]; // array of players
const statUpdates = [...];   // array of stat updates
zip(players, statUpdates).forEach(([player, stats]) => {
  player.diff = diffBetweenObjectValues(player.stats, stats);
  player.stats = stats;
});

Zip combines the array of players and the array of stat updates in to pairs, then iterate over them with forEach, destructure the bits back out, and run the update. You can also just use a for loop, which is faster but harder to read and easier to get wrong (e.g. off-by-one errors). I would stick with the version until/unless your profiler tells you it's too slow.

  • Related