Match players in array of game searches - javascript

I have thought about this alot but i cant find a good solution..that is also fast in Javascript.
I have an array of objects..the objects are game searches for a random player.
The array may look like this:
const GameSearches[
{fromPlayerId:"378329",goalScore:20}
{fromPlayerId:"125342",goalScore:20}
{fromPlayerId:"378329",goalScore:20}
{fromPlayerId:"918273",goalScore:20}
{fromPlayerId:"378329",goalScore:20}
]
In this array i need to rund a function called CreateNewGame(Player1,Player2).
In this array i could create games with for example index 0 and 1. Index 2 and 3. Index 4 would be left in the array as there are no more players to match on.
Anyone got a good solution to this? It would really help me out.
I have tried different filter and map without finding a good solution.
The output should call a function createnewgame
Example:
createNewGame(GameSearches[0].from,GameSearches[1].from)
this function will be called as there are two players looking for a game. they do not have they same fromPlayerId so they should match.
I see some comments on that StackOverflow is not a free codingservice..the app has thousands of lines..this is only a small part. Im asking becouse i cant figure out the logic on how to to this. I do not need a full working example.

You can try something like this
const GameSearches = [
{fromPlayerId:"378329",goalScore:20},
{fromPlayerId:"125342",goalScore:20},
{fromPlayerId:"378329",goalScore:20},
{fromPlayerId:"918273",goalScore:20},
{fromPlayerId:"378329",goalScore:20}
];
const createNewGames = (player1, player2) => console.log(player1.fromPlayerId, player2.fromPlayerId)
const getMatch = (GameSearches) => {
while([...new Set(GameSearches)].length > 1){
const player1 = GameSearches[0];
GameSearches.shift();
const player2Index = GameSearches.findIndex(el => el.fromPlayerId !== player1.fromPlayerId)
const player2 = GameSearches[player2Index];
GameSearches.splice(player2Index,1)
createNewGames(player1, player2);
}
}
getMatch(GameSearches);

I think maybe i can use the suggestion of a for loop..and it will work fine.
for (let i = 0; i < games20GoalScore.length; i = i + 2) {
if (games20GoalScore[i + 1] !== undefined) {
console.log(games20GoalScore[i] + " : " + games20GoalScore[i + 1]);
if (games20GoalScore[i].from !== games20GoalScore[i + 1].from) {
console.log("Match");
}
}
}
This code is run each time the array get a new item.

Related

I want to generate unique ID

I want to generate unique ID in JavaScript. I have tried uuid npm package, it's good but it's not what I want.
For example what I get as a result from generating unique ID from uuid package is
9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
Is there any way to make specific format as I want.
For example I want my ID to look like this
XZ5678
In this example format is two uppercase letters and 4 numbers.
That's it, I'm looking for answer and thank you all in advance.
If you're just looking to generate a random sequence according to that pattern, you can do so relatively easily. To ensure it's unique, you'll want to run this function and then match it against a table of previously generated IDs to ensure it has not already been used.
In my example below, I created two functions, getRandomLetters() and getRandomDigits() which return a string of numbers and letters the length of the argument passed to the function (default is length of 1 for each).
Then, I created a function called generateUniqueID() which generates a new ID according to the format you specified. It checks to see if the ID already exists within a table of exiting IDs. If so, it enters a while loop which loops until a new unique ID is created and then returns its value.
const existingIDs = ['AA1111','XY1234'];
const getRandomLetters = (length = 1) => Array(length).fill().map(e => String.fromCharCode(Math.floor(Math.random() * 26) + 65)).join('');
const getRandomDigits = (length = 1) => Array(length).fill().map(e => Math.floor(Math.random() * 10)).join('');
const generateUniqueID = () => {
let id = getRandomLetters(2) + getRandomDigits(4);
while (existingIDs.includes(id)) id = getRandomLetters(2) + getRandomDigits(4);
return id;
};
const newID = generateUniqueID();
console.log(newID);
Not sure why you want this pattern but you could do like this:
const { floor, random } = Math;
function generateUpperCaseLetter() {
return randomCharacterFromArray('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
}
function generateNumber() {
return randomCharacterFromArray('1234567890');
}
function randomCharacterFromArray(array) {
return array[floor(random() * array.length)];
}
const identifiers = [];
function generateIdentifier() {
const identifier = [
...Array.from({ length: 2 }, generateUpperCaseLetter),
...Array.from({ length: 4 }, generateNumber)
].join('');
// This will get slower as the identifiers array grows, and will eventually lead to an infinite loop
return identifiers.includes(identifier) ? generateIdentifier() : identifiers.push(identifier), identifier;
}
const identifier = generateIdentifier();
console.log(identifier);
They way of what you are suggesting be pretty sure you are going to get duplicates and collitions, I strongly suggest go with uuid.
Also probably you can find this useful: https://www.npmjs.com/package/short-uuid
Or if you want to continue with your idea this could be helpful: Generate random string/characters in JavaScript

How do I loop over a VERY LARGE 2D array without causing a major performace hit?

I am attempting to iterate over a very large 2D array in JavaScript within an ionic application, but it is majorly bogging down my app.
A little background, I created custom search component with StencilJS that provides suggestions upon keyup. You feed the component with an array of strings (search suggestions). Each individual string is tokenized word by word and split into an array and lowercase
For example, "Red-Winged Blackbird" becomes
['red','winged','blackbird']
So, tokenizing an array of strings looks like this:
[['red','winged','blackbird'],['bald','eagle'], ...]
Now, I have 10,000+ of these smaller arrays within one large array.
Then, I tokenize the search terms the user inputs upon each keyup.
Afterwards, I am comparing each tokenized search term array to each tokenized suggestion array within the larger array.
Therefore, I have 2 nested for-of loops.
In addition, I am using Levenshtein distance to compare each search term to each element of each suggestion array.
I had a couple drinks so please be patient while i stumble through this.
To start id do something like a reverse index (not very informative). Its pretty close to what you are already doing but with a couple extra steps.
First go through all your results and tokenize, stem, remove stops words, decap, coalesce, ects. It looks like you've already done this but i'm adding an example for completion.
const tokenize = (string) => {
const tokens = string
.split(' ') // just split on words, but maybe rep
.filter((v) => v.trim() !== '');
return new Set(tokens);
};
Next what we want to do is generate a map that takes a word as an key and returns us a list of document indexes the word appears in.
const documents = ['12312 taco', 'taco mmm'];
const index = {
'12312': [0],
'taco': [0, 1],
'mmm': [2]
};
I think you can see where this is taking us... We can tokenize our search term and find all documents each token belongs, to work some ranking magic, take top 5, blah blah blah, and have our results. This is typically the way google and other search giants do their searches. They spend a ton of time in precomputation so that their search engines can slice down candidates by orders of magnitude and work their magic.
Below is an example snippet. This needs a ton of work(please remember, ive been drinking) but its running through a million records in >.3ms. Im cheating a bit by generate 2 letter words and phrases, only so that i can demonstrate queries that sometimes achieve collision. This really doesn't matter since the query time is on average propionate to the number of records. Please be aware that this solution gives you back records that contain all search terms. It doesn't care about context or whatever. You will have to figure out the ranking (if your care at this point) to achieve the results you want.
const tokenize = (string) => {
const tokens = string.split(' ')
.filter((v) => v.trim() !== '');
return new Set(tokens);
};
const ri = (documents) => {
const index = new Map();
for (let i = 0; i < documents.length; i++) {
const document = documents[i];
const tokens = tokenize(document);
for (let token of tokens) {
if (!index.has(token)) {
index.set(token, new Set());
}
index.get(token).add(i);
}
}
return index;
};
const intersect = (sets) => {
const [head, ...rest] = sets;
return rest.reduce((r, set) => {
return new Set([...r].filter((n) => set.has(n)))
}, new Set(head));
};
const search = (index, query) => {
const tokens = tokenize(query);
const canidates = [];
for (let token of tokens) {
const keys = index.get(token);
if (keys != null) {
canidates.push(keys);
}
}
return intersect(canidates);
}
const word = () => Math.random().toString(36).substring(2, 4);
const terms = Array.from({ length: 255 }, () => word());
const documents = Array.from({ length: 1000000 }, () => {
const sb = [];
for (let i = 0; i < 2; i++) {
sb.push(word());
}
return sb.join(' ');
});
const index = ri(documents);
const st = performance.now();
const query = 'bb iz';
const results = search(index, query);
const et = performance.now();
console.log(query, Array.from(results).slice(0, 10).map((i) => documents[i]));
console.log(et - st);
There are some improvements you can make if you want. Like... ranking! The whole purpose of this example is to show how we can cut down 1M results to maybe a hundred or so canidates. The search function has some post filtering via intersection which probably isn't what you want you want but at this point it doesn't really matter what you do since the results are so small.

How to use reduce and the ramda "hex2color" function to count list of hex values than have r in their color name?

"Use reduce and the hex2color function to count list of hex values than have r in their name";
My current attempt is below. The first piece I know needs to be fixed is the filter function. I need to be able to filter out any colors that have the letter "r", but cannot seem to find a way to easily fit that into the filter function. It could easily be a syntax issue as I think I am asking the filter to find any strings that === "r", even though I am trying to use "contains" to solve that and have it check the whole color word.
Once the filter function is working, I assume the next step is to simply use the reduce function, then compose them together. ( I could be way off off, however).
I am quite new to programming, any insight is extremely welcome. Thanks!!
const exercise3 = _ => {
const hexes = ["#0000ff", "#f5f5dc", "#cd853f", "#663399", "#ffa500"];
const letter = "r";
const mapper = hex2color;
console.log(map(mapper, hexes)); //blue,beige,peru,rebeccapurple,orange
const filterer = el => contains(hex2color(el), letter);
console.log(filter(filterer, hexes)); //yields nothing, I assume to using the filter wrong with "r".
const reducer = (acc, el) => acc + 1;
const mappedFn = map(mapper);
const filtererFn = filter(filterer);
const reducerFn = reduce(reducer, 0);
const composedFn = compose(reducerFn, filtererFn, mappedFn);
return composedFn(hexes);
};

Not truly async?

I have a array of about 18 000 elements. I'm creating a map application where I want to add the elements when the user zooms in to a certain level.
So when the user zooms in under 9 I loop tru the array looking for elements that is in the view.
However, it does take some time looping thru the elements, causing the map application lag each time the user zooms out and in of "level 9". Even if there are no elements to add or not, so the bottleneck is the looping I guess.
I've tried to solve it by asyncing it like:
function SearchElements(elementArr) {
var ret = new Promise(resolve => {
var arr = [];
for (var i in elementArr) {
var distanceFromCenter = getDistanceFromLatLonInKm(view.center.latitude, view.center.longitude, dynamicsEntities[i].pss_latitude, dynamicsEntities[i].pss_longitude);
var viewWidthInKm = getSceneWidthInKm(view, true);
if (distanceFromCenter > viewWidthInKm) continue;
arr.push(elementArr[i]);
}
resolve(arr);
});
return ret;
}
SearchElements(myElementsArray).Then(arr => {
// ...
});
But its still not async, this method hangs while the for loop runs.
Because you still have a tight loop that loops through all the elements in one loop, you'll always have the responsiveness issues
One way to tackle the issue is to works on chunks of the data
Note: I'm assuming elementArr is a javascript Array
function SearchElements(elementArr) {
var sliceLength = 100; // how many elements to work on at a time
var totalLength = elementArr.length;
var slices = ((totalLength + sliceLength - 1) / sliceLength) | 0; // integer
return Array.from({length:slices})
.reduce((promise, unused, outerIndex) =>
promise.then(results =>
Promise.resolve(elementArr.slice(outerIndex * sliceLength, sliceLength).map((item, innerIndex) => {
const i = outerIndex * sliceLength + innerIndex;
const distanceFromCenter = getDistanceFromLatLonInKm(view.center.latitude, view.center.longitude, dynamicsEntities[i].pss_latitude, dynamicsEntities[i].pss_longitude);
const viewWidthInKm = getSceneWidthInKm(view, true);
if (distanceFromCenter <= viewWidthInKm) {
return item; // this is like your `push`
}
// if distanceFromCenter > viewWidthInKm, return value will be `undefined`, filtered out later - this is like your `continue`
})).then(batch => results.concat(batch)) // concatenate to results
), Promise.resolve([]))
.then(results => results.filter(v => v !== undefined)); // filter out the "undefined"
}
use:
SearchElements(yourDataArray).then(results => {
// all results available here
});
My other suggestion in the comment was Web Workers (I originally called it worker threads, not sure where I got that term from) - I'm not familiar enough with Web Workers to offer a solution, however https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers and https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API should get you going
To be honest, I think this sort of heavy task would be better suited to Web Workers

(React.js)Why react cannot find the object?

I am a newbie learning to build a rpg game with React.js, and I found this part very confusing.
I am trying to update life with onClick and when life<damage, the object player is dropped. So the html looks like this:
The current player is generated like this:
<h4>You are: {this.props.targets[this.props.playerindex].name}</h4>
I use these code to handle attack and update the index:
handleAttack(index1,id2){
let players = this.state.players.slice();
let index2 = players.findIndex(x => x.id === id2);
let damage = players[index1].damage;
let life = players[index2].life;
console.log("Before(length):"+this.state.players.length);
if (life>damage){
players[index2].life = life-damage;}
else {players=players.filter(player => player.id !== id2);}
this.setState({players},()=>{console.log("After(length):"+this.state.players.length);
this.handleUpdateIndex();});
}
handleUpdateIndex(){
console.log("Before:"+this.state.playerindex);
let index=this.state.playerindex;
let length=this.state.players.length;
console.log("BeforeUpdate(length)"+this.state.players.length);
if(index<length-1)
{this.setState({playerindex:index+1},() => {console.log("After:"+this.state.playerindex);});}
else{this.setState({playerindex:0},() => {console.log("After:"+this.state.playerindex);});}
this.forceUpdate();
}
But sometimes the index will increment while it should not, and causes this:
I think it might be the asynchronous behavior of setState, but I don't know how should I solve this problem.
If you have a solution or another way to achieve the expected behavior, please help!
Code here:
App.js: https://ghostbin.com/paste/e9wjg
Attack.js: https://ghostbin.com/paste/3zbwk
I know what i am wrong:
when I am dropping a object, I should move the index back:
if (life>damage){
players[index2].life = life-damage;}
else {players=players.filter(player => player.id !== id2);
this.setState({playerindex:this.state.playerindex-1});}
This problem is solved, however please give me advice on this project if you like!

Categories

Resources