I'm quite stuck in the development of an app right now. What i want to do is upon submission by ng-click the following task will be performed:
generate a 5 digit random number.
this random number will then be validated in the database if exist.
if it exist it will generate another number which will then be validated again until such time that the value returns to zero.
for number 1 i already have this:
var gRandomNum = function(){
var snumRand = Math.floor((Math.random()*10000)+1);
var numRand = snumRand.toString();
var str_f = numRand.length;
if(str_f == 1){
str_final = "0000" + numRand;
} else if(str_f == 2){
str_final = "000" + numRand;
} else if(str_f == 3){
str_final = "00" + numRand;
} else if(str_f == 4){
str_final = "0" + numRand;
} else {
str_final = numRand;
}
return str_final;
}
for number 2
var validataRandNum = function(pdata){
return $http.get('api/cntTc/'+pdata).
success(function(data){
return data.tc_count;
});
}
for number 3
do{
var pdata = gRandomNum();
var ifValid = validataRandNum(pdata);
} while(ifValid < 0);
Here is what it looks like on my Scope function
$scope.ok = function(){
do{
var pdata = gRandomNum();
var ifValid = validataRandNum(pdata);
} while(ifValid < 0);
}
When i tried to verify the value of ifValid all i'm getting is undefined but when i clicked again the value will show up but it was from the last clicked value. I tried to implement a promise but got stucked on how to implement it inside a promise. If you can provide a code that will do just that it will be great.
Is there any way to move this to the server side?
To stick to doing this on the client, perhaps you can try to have validateRandNum() call itself recursively (but consider putting in some limits so it doesn't go on forever)...
var validataRandNum = function(getRandNumFunc, deferred){
deferred = deferred || $q.defer();
var pdata = getRandNumFunc();
$http.get('api/cntTc/'+pdata).
success(function(data){
if (data.tc_count < 0) {
validataRandNum(getRandNumFunc, deferred);
} else {
deferred.resolve(data.tc_count);
}
});
return deferred.promise;
};
$scope.ok = function(){
validataRandNum(gRandomNum).then(function (tc_count) {
$scope.tc_count = tc_count;
});
};
Related
Consider the below Angularjs 'service'. I would like to keep all my 'entries' related variables in this service so I can use them across controllers - as I believe the ideal angular pattern calls for. However, if I manipulate anyone of the variables from a controller - entries, entries_Sorted, entries_Loaded within the service object - they all seem to take on the same new value. I understand the factory object is a singleton but shouldn't these variables be independent? I don't expect or understand the behavior I am seeing. How is this useful? I must be doing something wrong.
To be clear:
If I set local variables within my controllers using this service's return methods, then update those local variables, all the three entries variables within the service will take on the new values.
Service code:
angular.
module('core.entry').
factory('Entry', ['$http', 'Topten', 'Stack', 'User',
function($http, Topten, Stack, User) {
var entries = [];
var entries_Sorted = [];
var entries_Loaded = [];
var service = {};
service.getEntries = function(stackId, callback) {
return $http.get('stacks/' + stackId + '/entries/')
.success(function(data) {
entries = data["entries"];
Topten.setToptens(data["topTen"]);
Stack.setOpenStack(data["stack"]);
callback(null, data);
})
.error(function(err) {
callback(err, null);
});
};
service.returnEntries = function() {
return entries;
}
service.sortEntries = function(callback) {
// 1. Loop through entries inner looping on toptens - adding topten score to total score
for (var i = 0; i < entries.length; i++) {
var thisEntry = entries[i];
var totalScore = 0;
var toptens = Topten.returnToptens();
for (var j = 0; j < toptens.length; j++) {
var thisTopten = toptens[j];
if (thisTopten["entryId"]) {
if (thisEntry["_id"] == thisTopten["entryId"]._id) {
totalScore = totalScore + thisTopten["score"];
}
}
}
thisEntry.totalScore = totalScore;
// 2. Add net (likes - dislikes) to entry.totalScore
for (var j = 0; j < thisEntry.votes.length; j++) {
var thisVote = thisEntry.votes[j]["vote"];
if (thisVote == "up") {
thisEntry["up"] = thisEntry["up"] + 1;
} else if (thisVote == "down") {
thisEntry["down"] = thisEntry["down"] + 1;
}
}
var netLikes = thisEntry["up"] - thisEntry["down"]; // one point each
thisEntry["totalScore"] = thisEntry["totalScore"] + netLikes;
}
// 3. Sort entries by entry.totalScore and return
entries_Sorted = entries.sort(function(a, b) {
return b.totalScore - a.totalScore;
});
callback();
};
service.returnEntries_Sorted = function() {
return entries_Sorted;
};
return service;
}
]);
My controller's code:
Entry.getEntries($routeParams.stackId, function(err, data) {
if(err) {
}
// get sorted entries (after return from getEntries)
Entry.sortEntries(function() {
self.entries_Sorted = Entry.returnEntries_Sorted();
self.loadMore();
});
});
self.loadMore = function() {
self.entries_Loaded = self.entries_Loaded.concat(self.entries_Sorted.splice(page * increment, increment));
self.page +=1;
}
Problem: After I call this local 'load_More' function, the properties in my service - entries, _Sorted, _Loaded - will all have the new 'spliced' value. ie. Entry.entries will have the same value as the controller's local self.entries_Sorted.
I'm trying to make a chat app (similar to Omegle.com) that matches native speakers to learners. I believe I have the correct algorithm, but my Javascript keeps throwing a message that Javascript heap out of memory error.
For example, let's say Speaker 1 speaks English and learns French and Speaker 2 speaks French and learns English (perfect match). My algorithm displays match found.
Queue Controller
socket.emit('in queue', {
speakingLanguages: speakingLanguages,
learningLanguages: learningLanguages
});
socket.on('chat start', function(data){
room = data.room;
$location.path('/chat');
});
server.js
var queue = [];
var rooms = {};
io.sockets.on('connection', function(socket){
console.log('User ' + socket.id + ' connected');
socket.on('in queue', function(data){
socket.speakingLanguages = data.speakingLanguages;
socket.learningLanguages = data.learningLanguages;
if (queue.length != 0){
for (var i = 0; i < queue.length; i++){
for (var j = 0; j < queue[i].speakingLanguages.length; j++){
for (var y = 0; y < socket.learningLanguages.length; y++){
if (queue[i].speakingLanguages[j] === socket.learningLanguages[y]){
console.log('a match was found!');
break;
}else{
queue.push(socket);
break;
}
}
}
}
}else{
queue.push(socket);
}
});
socket.on('send message', function(data){
var room = rooms[socket.id];
io.sockets.in(room).emit('send message', data);
});
});
But see, when I open up multiple windows on my browser to test a lot of cases, I get that error above. It says that I ran out of Javascript heap and I've been struggling with this for hours, but I don't know what to do.
Information:
speakingLanguages and learningLanguages are of type array (because people can speak multiple languages and learn multiple languages)
Every time a match is not found, I put them into the queue array
I was diligently writing down notes and investigating the algorithm and I think I've finally got it. I tested the algorithm and it seems to be working!
socket.on('in queue', function(data){
socket.speakingLanguages = data.speakingLanguages;
socket.learningLanguages = data.learningLanguages;
var found = false;
if (queue.length != 0){
for (var i = 0; i < socket.learningLanguages.length; i++){
for (var j = 0; j < queue.length; j++){
for (var y = 0; y < queue[j].speakingLanguages.length; y++){
if (socket.learningLanguages[i] === queue[j].speakingLanguages[y]){
console.log('a match was found');
var peer = queue.pop();
var room = socket.id + '#' + peer.id;
peer.join(room);
socket.join(room);
rooms[peer.id] = room;
rooms[socket.id] = room;
peer.emit('chat start', { room: room });
socket.emit('chat start', { room : room });
found = true;
break;
}
}
}
}
if (!found){
queue.push(socket);
}
}else{
queue.push(socket);
}
});
There is way too much for loop nesting in your code.
I made some changes to your code.
io.sockets.on('connection', function(socket){
console.log('User ' + socket.id + ' connected');
socket.on('in queue', function(data){
socket.speakingLanguages = data.speakingLanguages;
socket.learningLanguages = data.learningLanguages;
var searchingFor = [];
var toQueue = {};
var toUnqueue = {};
for (let spoken of socket.speakingLanguages) {
for (let learning of socket.learningLanguages) {
var searchKey = `S:${learning}L:${spoken}`;
var queueKey = `S:${spoken}L:${learning}`;
searchingFor.push(searchKey);
toQueue[queueKey] = socket;
toUnqueue[queueKey] = undefined;//Using `undefined` instead of `delete` for performance
}
}
//Search for a peer
var peer = false;//use an array[] if you want all matches
for (let searching of searchingFor) {
let result = queue[searching];
if(result) {
peer = result;
break;//You can change this part to find all matches
}
}
if (!peer) {
//No peer(s) found
//Add all possible combination of `spoken:learning` keys to the queue
//If someone searchs for one of these combinations we will be matched
socket.toUnqueue = toUnqueue;
Object.assign(queue, toQueue);
} else {
//We found a matching peer
console.log('a match was found');//If you use multiple matches you can ask what he prefers
//Unqueue other language combinations of the peer
Obeject.assign(queue, peer.toUnqueue);
//The rest of you logic goes here
var room = socket.id + '#' + peer.id;
peer.join(room);
socket.join(room);
rooms[peer.id] = room;
rooms[socket.id] = room;
peer.emit('chat start', { room: room });
socket.emit('chat start', { room : room });
}
});
socket.on('send message', function(data){
var room = rooms[socket.id];
io.sockets.in(room).emit('send message', data);
});
});
I changed the way you're using the queue.
Searching by key should be faster.
I didn't test it but it should be good.Tell me if it does the job!
I revised my code a bit using amenzou's answer and another one here
var queue = [];
var rooms = {};
var index = 0;
var intersect_safe = function(a, b){
var ai=0, bi=0;
var result = [];
while( ai < a.length && bi < b.length )
{
if (a[ai] < b[bi] ){ ai++; }
else if (a[ai] > b[bi] ){ bi++; }
else /* they're equal */
{
result.push(a[ai]);
ai++;
bi++;
}
}
return result;
}
io.sockets.on('connection', function(socket){
console.log('User ' + socket.id + ' connected');
socket.on('in queue', function(data){
socket.speakingLanguages = data.speakingLanguages;
socket.learningLanguages = data.learningLanguages;
if (queue.length != 0){
for (var i = 0; i < queue.length; i++){
var match = false;
var match1 = [];
var match2 = [];
match1 = intersect_safe(socket.learningLanguages, queue[i].speakingLanguages);
match2 = intersect_safe(socket.speakingLanguages, queue[i].learningLanguages);
if (match1.length != 0 && match2.length != 0){
console.log('match');
index = i;
match = true;
break;
}
}
if (match){
var peer = queue.splice(index, 1);
var room = socket.id + '#' + peer[0].id;
peer[0].join(room);
socket.join(room);
rooms[peer[0].id] = room;
rooms[socket.id] = room;
peer[0].emit('chat start', match2);
socket.emit('chat start', match1);
}else{
queue.push(socket);
}
}else{
queue.push(socket);
}
});
Works perfectly! Thank you very much for your help and advice, amenzou.
Have some trouble with Angular promise between two loops... First loop walk through an array of value, and for each value, make a PouchDB Query to retrieve some datas. Finally, would like to return to controller a JSON Object that would look like :
{
items: [
{
"attribute": "some value"
},
{
"attribute": "some other value"
},
...
],
"a_total": "some_total",
"another_total": "some_other_total"
}
In this object, "items"
Basically, put the code in a function that looks like :
var _stockByAreas = function(){
var deferred = $q.defer();
var data = {}; // Final datas to return to controller
// Get first array to loop into
var storageAreas = storageAreaService.storageAreaList();
var areas = []; // All of area
// Walk across array
angular.forEach(storageAreas, function(zone){
var area = {}; // First object to return
area.id = zone.id;
area.libelle = zone.libelle;
// Then make a PouchDB query to get all datas that involved
MyKitchenDB.query(function(doc, emit){
emit(doc.storage);
}, { key: area.id, include_docs: true }).then(function (result) {
area.sRef = "tabsController.addTo({id: '" + area.id + "'})";
area.nbProduct = 0;
area.totalQuantity = 0;
area.totalValue = 0;
// ... process result
if(result.rows.length > 0){
// Some results, so... let's go
area.sRef = "tabsController.outFrom({id: '" + area.id + "'})";
var rows = result.rows;
// Counter initialization
var total = 0;
var value = 0;
angular.forEach(rows, function(row){
total++;
var stocks = row.doc.stock;
angular.forEach(stocks, function(stock){
var nearOutOfDate = 0;
var nearStockLimit = 0;
quantity += stock.quantity;
value += stock.quantity * stock.price;
// Evalue la date de péremption
var peremptionDate = moment(stock.until);
var currentDate = moment();
if(currentDate.diff(peremptionDate, 'days') <= 1){
nearOutDate += 1;
}
});
area.nbProduct = total;
area.qteTotale = quantity;
area.valeur = value;
if(quantite == 1){
nearLimitOfStock += 1;
}
areas.push(area); // Add result to main array
});
}
}).catch(function (err) {
// Traite les erreurs éventuelles sur la requête
});
/**
* Hey Buddy... what i have to do here ?
**/
data.items = areas;
data.nearLimitOfStock = nearLimitOfStock;
data.nearOutOfDate = nearOutOfDate;
});
deferred.resolve(data);
return deferred.promise;
}
... But, console returns that "areas" is not defined, and other value too...
I think i don't really understand how promises runs...
Someone is abble to explain why i can't get the result that i expect in my case ?
Thx
Your code is too long, I just give you the approach.
Use $q.all() to ensure all your queries are completed. And use deferred.resolve(data) whenever your data for each query is arrived.
var _stockByAreas = function() {
var query = function(zone) {
var queryDef = $q.defer();
// timeout is for query and response simulations
setTimeout(function() {
// ...
queryDef.resolve( {data: 'MeTe-30'} );
}, 1000);
return queryDef.promise;
}
var promises = [];
angular.forEach(storageAreas, function(zone) {
// ...
promises.push( query(zone) );
});
return $q.all(promises);
}
_stockByAreas().then(function(res) {
// res[0] resolved data by query function for storageAreas[0]
// res[1] resolved data by query function for storageAreas[1]
// ...
});
I get the following error from the console: "TypeError: Cannot read property '0' of undefined", it has something to do with the array but I cannot find the mistake.
module.exports =
{
create_creeps: function()
{
var aHarvester = [[TOUGH,TOUGH, MOVE, CARRY, WORK, MOVE]["harvester"]];
Spawn.prototype.createMyCreep = function(aCreep,sRole) {
if (!Game.spawns.Spawn1.spawning){
var nameCount = 0;
var name = null;
while(name == null)
{
nameCount++;
var tryName = sRole + nameCount;
if(Game.creeps[tryName] == undefined)
name = tryName;
}
var dbg= this.canCreateCreep(aCreep, name);
if(dbg == OK) {
console.log("Creating creep " + sRole);
return this.createCreep(aCreep , name,{ role:sRole });
} else {
console.log("error "+dbg+" "+sRole);
}
}
};
Game.spawns.Spawn1.createMyCreep(aHarvester[0],aHarvester[1][0]);
};
}
Please separate arrays with a comma
So
[[TOUGH,TOUGH, MOVE, CARRY, WORK, MOVE]["harvester"]]
Should be
[[TOUGH,TOUGH, MOVE, CARRY, WORK, MOVE],["harvester"]]
I have create a filter but this filter is not working with array inside array.
'http://plnkr.co/edit/oygy79j3xyoGJmiPHm4g?p=info'
Above plkr link is working demo.
app.filter('checkboxFilter', function($parse) {
var cache = { //create an cache in the closure
result: [],
checkboxData: {}
};
function prepareGroups(checkboxData) {
var groupedSelections = {};
Object.keys(checkboxData).forEach(function(prop) {
//console.log(prop);
if (!checkboxData[prop]) {
return;
} //no need to create a function
var ar = prop.split('=');
//console.log("ar is - "+ar);
if (ar[1] === 'true') {
ar[1] = true;
} //catch booleans
if (ar[1] === 'false') {
ar[1] = false;
} //catch booleans
/* replacing 0 with true for show all offers */
if(ar[0]=='SplOfferAvailable.text'){
ar[1]='true';
}else{
}
//make sure the selection is there!
groupedSelections[ar[0]] = groupedSelections[ar[0]] || [];
//at the value to the group.
groupedSelections[ar[0]].push(ar[1]);
});
return groupedSelections;
}
function prepareChecks(checkboxData) {
var groupedSelections = prepareGroups(checkboxData);
var checks = [];
//console.log(groupedSelections);
Object.keys(groupedSelections).forEach(function(group) {
//console.log("groupedSelections- "+groupedSelections);
//console.log("group- "+group);
var needToInclude = function(item) {
//console.log("item- "+item);
// use the angular parser to get the data for the comparson out.
var itemValue = $parse(group)(item);
var valueArr = groupedSelections[group];
//console.log("valueArr- "+valueArr);
function checkValue(value) { //helper function
return value == itemValue;
}
//check if one of the values is included.
return valueArr.some(checkValue);
};
checks.push(needToInclude); //store the function for later use
});
return checks;
}
return function(input, checkboxData, purgeCache) {
if (!purgeCache) { //can I return a previous 'run'?
// is the request the same as before, and is there an result already?
if (angular.equals(checkboxData, cache.checkboxData) && cache.result.length) {
return cache.result; //Done!
}
}
cache.checkboxData = angular.copy(checkboxData);
var result = []; // this holds the results
//prepare the checking functions just once.
var checks = prepareChecks(checkboxData);
input.every(function(item) {
if (checks.every(function(check) {
return check(item);
})) {
result.push(item);
}
return result.length < 10000000; //max out at 100 results!
});
cache.result = result; //store in chache
return result;
};
});
above code is for check box filter.
when i click on checkbox called "Availability" it does not filter the result.
Please help me out.
Thanks.
I think that the way you are navigating through json is wrong because if you put in this way it works
"Location": "Riyadh",
"AvlStatus": "AVAILABLE"
"Rooms": {.....
You have to go in some way through Rooms and right now I think you're not doing that