How to I use my firebase variables as an integer? - javascript

I have a simple program that you can post/accept games then report back the score. I am having an issue of updating the score as information stored in firebase is stored as a string. How do I take my score as an integer to add to it?
if (selfScore > oppScore) {
var ref = new Firebase('taken out');
var selfRef = firebase.database().ref("users/" + (selfKey));
selfRef.update({
"tScore": ("tScore" + 3)
});
}
Ideally, the score would take the previous score and add 3 but this is not the case. I'm new to firebase so if this is obvious, my bad. An edit to clarify when I remove tscore and just have tScore: +3 it just changes tScore to 3, it doesn't add it.

You cannot make some operations on field value within the update() method. So you should first read the value from the database and then update the record with the new value.
The best approach is to use a transaction for such operation, which will automatically do the read/write operation and, in addition, ensure "there are no conflicts with other clients writing to the same location at the same time".
You would then do as follows:
var selfRef = firebase.database().ref("users/" + selfKey + "/tScore");
selfRef.transaction(function(currentValue) {
return currentValue + 3;
});

Related

Firestore limit read snapshot by current time

I want to display the last 10 messages of a conversation. Then as the conversation progresses, obviously, I need to show those messages as well:
I am doing something like this:
//function a
db.collection("conversations/" + messageID + "/messages").orderBy("timestamp", "desc").limit(10).
get().then(function(querySnapshot) {
const time = Date.now();
//call function b and pass time as a parameter
//function b
db.collection("conversations/" + messageID + "/messages").where("timestamp", ">=", time)
What security rules will allow me ensure that time in function b is somewhat close to the current time?
Thanks!
You can use request.time for when the specific document was created, which is type of Timestamp, as stated in the Rules documentation.
I found this StackOverflow post which might help as well.

Inserting multiple entries in collection

I am attempting to create barcodes that increment by 1 for an entered quantity and add each of them to a MongoDB collection.
I use db.controlNumber.insert({controlNumber}) to do this, and I also use
console.log(controlNumber) to see my result. However, in the database, the incremented number will go to the max and enter that many times, where the console.log shows it increment.
while (i < count) {
i++;
controlNumber.controlNumber = controlVar[0] + "-" + controlVar[1] + "-" +
controlVar[2] + "-" + controlVar[3] + "-000" + i;
db.controlNumber.insert(controlNumber);
console.log(controlNumber);
}
I expect my mongoDB collection to have control number (for example if user wants 5 control numbers)
a-b-c-d-001
a-b-c-d-002
...
a-b-c-d-005
Instead, it makes 5 entries of
a-b-c-d-005
You're mutating controlNumber.controlNumber. Instead, create a new object to insert:
const toInsert = Object.assign({}, controlNumber, { controlNumber: i });
db.controlNumber.insert(toInsert)
It'd likely also be worth either using async/await or promises to handle asynchronous calls. If you do await db.controlNumber.insert(controlNumber) you wouldn't have run into any problems because it would have waited for the document to be fully inserted before moving on to the next one.

How to delete local storage of HTML5 by group?

I am creating localstorage dynamically like below
window.localStorage["DBname"+count]=JSON.stringify(values)
at the same time i am also creating some other local storage like
window.localStorage["login_detail"]=login_string
window.localStorage["page_config"]=page_config
so i can not use window.localStorage.clear(),because it will clear all my localstorage which i dont want, and also i can not use window.localStorage.removeItem["DBname"+count] because i count know how many "count" will come while execution.
so is there any way to delete localstorage like group delete kind of? help me out.
Simple solution
var prefix = "DBname",
continue = true,
on = 0;
while (continue) {
continue = localStorage.getItem(prefix + on)?true:false;
try { localStorage.removeItem(prefix + on); } catch (e) { continue = false; }
on += 1;
}
This will remove all local storage items beginning with DBname
Tests
Start:
DBname1
DBblah
DBnameCats
DBname 2
DBname 3
End:
DBblah
DBnameCats
An even better solution
var keys = Object.keys(localStorage),
prefix = "DBname";
for (var i = 0; i < keys.length; i += 1) {
if (keys[i].indexOf(prefix) === 0) {
localStorage.removeItem(keys[i]);
}
}
Tests
Start:
DBname1
DBblah
foobar
DBnameCats
DBname 2
DBname 3
End:
DBblah
foobar
Dealing with support
Add this one line:
Object.keys||(Object.keys=function(r){var e=[];for(var n in r)r.hasOwnProperty(n)&&e.push(n);return e});
That will let you use An even better solution on practically every browser.
I suppose you could iterate over all elements in the LocalStorage and find the keys you want to delete each individually.
A quick example would be:
function clearLocalStorageByKeyMatch(word) {
// Find items in the array where he key contains the word 'word'
var filtered = localStorage.filter(function(item, key) {
return key.indexOf(word) > -1;
});
Object.keys(filtered).forEach(function(item) {
localStorage[item] = null;
});
}
// clear localStorage where config word appear
// clearLocalStorageByKeyMatch('config');
You can also look at a library that handles that for you.
Iterating though localStorage keys/items - NO
Iterating over all the localStorage keys is not a good solution. Since localStorage could be used by other applications as well, it would be very inefficient to iterate through all items in localStorage and then remove them.
What is the best Approach
Since you are the owner of you application, you better can maintain the counts. On a rough level you can keep the "counts" you want to delete in future, may be the start and end position of count in the localStorage itself.
Once you know the start & end limit of "Count" - iterate and delete all the "DbName + Count" found in localStorage.
Another Workaround
You can have one single entity as JSON object for your application. Think of it as you are name-spacing all the localStorage items and encapsulating all of them inside one single variable.
var myApp={
"Dbname1":{},
"Dbname2":{},
"login_detail":{},
"page_config":{}
};
for saving this into localStorage:
localStorage["myApp"]=JSON.stringify(myApp);
for retrieving it back:
var myApp=JSON.parse(localStorage["myApp"]);
//now you can delete whatever db you want from `myApp` and save it back to localStorage.
This will keep other application out of danger from your code.

How do I find the next ID?

I am trying to find out the best way to implement nextId() in a Javascript app that issues unique IDs for its objects. If it matters, it's a program that I am doing as a learning experience that's pure JS, HTML, and CSS (no libraries, frameworks, DBMS, etc.). I saw a similar question on here on SO (although I wasn't able to find it again for the link) with answers that included not only storing a list of possible ids paired with a boolean value to determine if the id is used, but also storing deleted ids in a recycling list to use for future objects that need it. I think the latter option sounds better, but I'm sure there are even more ways to do it. Does anyone know if there is a pattern, algorithm, or otherwise best practice for this task?
EDIT:
I would like to allow users to share data at some point soon in the application's life, so IDs that already exist would likely become an issue at some point. I would like the IDs to be permanent as I will be persisting data with LocalStorage. A simple integer will work which I will prefix with a letter or two to identify the type of object. It would also be nice to fill in the holes, so the integer doesn't get too high when users use it long-term (wishful thinking).
Also, all objects are constructed from strings at the beginning of the program (I know it's insane).
If you just need an id that is unique per the lifetime of a page, you can use a simple monotomically increasing counter in the page:
var getUniqueID = (function() {
var cntr = 0;
return function() {
return cntr++;
};
})();
var idA = getUniqueID();
var idB = getUniqueID();
To make sure your ids are unique among all users is a taller task. Without involving a central server that coins unique ids for you, the general concept here is to create an id that is a combination of three things:
A token that is unique to the user (like a userID)
A token that is guaranteed to be unique for the session (like what we have above)
A random value.
Done right, there can never be a collision between two different users (because the userID is in the id) and the counter makes it so no user ever generates the same id twice in the same session and the random value makes the odds of a user generating the same id themselves in the same session extremely small.
var getGUID = (function() {
var cntr = 0;
return function(userID) {
var rand = Math.random().toString().replace(".", "");
return userID + "_" + rand + "_" + cntr++;
};
})();
var idA = getGUID(myUserID);
var idB = getGUID(myUserID);
Note: this is the simpler approach on GUID generation that assumes you already have a userID. There is a whole lot of research and literature on various strategies for generating a GUID which you can certainly read a lot more about if you want something beyond this. Some references on the topic:
http://en.wikipedia.org/wiki/Globally_unique_identifier
http://betterexplained.com/articles/the-quick-guide-to-guids/
http://www.uddi.org/pubs/draft-leach-uuids-guids-01.txt
Depending on the use case, I like to create a complex unique id:
function newGUID(){
var result = '';
var hexcodes = "0123456789abcdef".split("");
for (var index = 0; index < 32; index++) {
var value = Math.floor(Math.random() * 16);
switch (index) {
case 8:
result += '-';
break;
case 12:
value = 4;
break;
}
result += hexcodes[value];
}
return result;
}
You could use UUIDs as IDs. There's one answer here in SO where you can generate UUIDs in JS. UUIDs are usually enough to be used as IDs. Just to be sure that the id isn't a dupe, you can have an object whose keys are the used IDs. As IDs are generated, you can keep track of them by adding them in the object. You can then look them up by doing obj.hasOwnProperty(id).
You can do it like
var idStorage = {};
var id;
// generate ID that's unique and hasn't been used
do{
id = guid();
} while (idStorage.hasOwnProperty(id));
idStorage[id] = true;
// ID is usable
Also, IDs are supposed to be unique. They should never be reused at all.
AngularJS has a very simply approach to generating unique IDs: just increment a global counter. From src/Angular.js:
var uid = 0;
// ...
/**
* A consistent way of creating unique IDs in angular.
*
* Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
* we hit number precision issues in JavaScript.
*
* Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
*
* #returns {number} an unique alpha-numeric string
*/
function nextUid() {
return ++uid;
}
Of course, you should choose a solution depending on what time frame the generated IDs should be unique. The above solution will generate IDs which are unique for one session of one web page. For a simple single-page application (which is Angular's use case), this will do just fine. If you need them to be unique across multiple page loads, or unique for the same user, you'll need to persist the uid for a bit longer (in a cookie or in a database). If they need to be unique for a longer time, you might also need to look into longer IDs with more than 2^53 possible values.
I would use a UUID v4 since these IDs would always be unique in any circumstance (no additional logic to check if these ids are in use or to recicle old ones), just issue a new id whenever you need one.
Very simple implementation in JS as follows:
function generateUUID(){
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
$(function() {
$('button').bind('click', function() {
$('input').val(generateUUID());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" style="width: 350px;"/><button>GENERATE NEW ID</button>
Well, it's a bit unclear what you expect from these ids, however if you only want a unique id per type of entity in your system and your data must only live in memory, then you could use the following approach:
Note: I saw from the comments you wanted a prefix which represents the entity.
function identitySequence(base) {
var id = base || 0;
return function () {
return ++id;
};
}
//Lets say you had some sort of repository for every entity
function InMemoryUserRepository(nextId) {
this._nextId = nextId;
}
InMemoryUserRepository.prototype = {
constructor: InMemoryUserRepository,
get nextId() { return 'user-' + this._nextId(); }
//other operations, like save...
};
var userRepository = new InMemoryUserRepository(identitySequence());
userRepository.nextId; //user-1
Now, lets say you wanted your id sequence to be persistent in the localStorage, here's what you could do (extending the above code):
var userRepository = new InMemoryUserRepository(localStorageIdentitySequence('userIdSeq'));
userRepository.nextId; //user-1
//Reload page
userRepository.nextId; //user-2
function localStorageIdentitySequence(storageKey) {
var next = identitySequence(+localStorage.getItem(storageKey));
return function () {
return +(localStorage[storageKey] = next());
};
}
This works fine for a single machine, however if you want a unique id generator that will generate unique IDs across machines, then this approach will not work. You would have to generate the ID from a server that can be accessed by all clients, or you can generate a GUID on the client instead. There would be no way to know if the GUID was already generated by another client, but that would be very unlikely.

Multiple javascript timeouts - problem with live data fetching

I am building a real-time system which (with a use of websockets) updates a table with live data of different frequencies (can be 3 times per second, can be once every 2 seconds - dependant on the type of data).
I am currently struggling to find a way of letting the user know when a particular field has not been updated in the last 5 seconds. That is, if no new data is fetched, I shouldn't keep the old value there, but rather change it to '--' or something similar.
After a long way to the javascript, final function which updates fields looks like that (extremely simplified):
function changeValue(data){
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
}
This function gets called each time a field needs to be changed. I've got between 2 and 40 different fields (dependant on the user) that are changed.
What is the best way of setting timers in order to change the values of the fields to '--' every 5 seconds, if no update has been made?
I would be really grateful for some tips,
Thanks,
Karol.
Since you want to indicate timeout on a per-field basis, you have two obvious options:
Have a global interval timer that ticks over fairly frequently and looks through all of your fields for a timeout.
Have independent timers for each field which just deal with that field.
I think on balance I prefer (1) to (2), because we're only dealing with one interval timer then and it makes the housekeeping simpler.
Since IDs in documents must be unique, we can use your field ID values as a key in a hash (an object) to store last updated times. This is kind of a spin on the previous answer but works on a per-field basis. So here's how we'd set those last updated times:
var lastUpdatedTimes = {};
function changeValue(data){
var fieldId= data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
lastUpdatedTimes[fieldId] = new Date().getTime();
}
Then you set up an interval timer to check each of them.
function checkFieldsForTimeout(){
var now = new Date.getTime();
// For each ID in lastUpdatedTimes, see if 'now minus
// last updated' is > 5000 and is so, set the field
// text to '--' and remove that entry from the last
// updated list with "delete lastUpdatedTimes[itemId]".
}
Should a timed-out field spring back to life, the "--" will be replaced by some real text again.
By deleting the last updated time from "lastUpdatedTimes" whenever we put "--" into a field, we make sure that the interval timer isn't wasting time processing fields that have already been timed out.
This answer was extended to handling multiple fields after the comment by #Andrew (please see also his answer).
Introduce a property updatedTime, which holds the last time the data was updated, in each data. A periodic timer checks updatedTime for all data and updates the text field if appropriate. The check has to be twice as often as the detection period. Your function changeValue() updates updatedTime and the text field.
function checkData() {
var now = new Date.getTime();
for "each data" {
if (now - data.updatedTime >= 5000) {
var fieldId = data.fieldId;
$('span#'+fieldId).text('--');
}
}
}
function changeValue(data) {
var fieldId = data.fieldId;
var value = Math.round(data.value);
$('span#'+fieldId).text(value);
data.updatedTime = new Date.getTime();
}
// Install periodic timer to check last updates:
setInterval(checkData, 5000 / 2); // interval = half the required detection period

Categories

Resources