Firebase Drawing Demo and Sessions - javascript

I'm interested in using Firebase, but have some questions.
One demo I'm really interested in is the drawing demo: https://www.firebase.com/tutorial/#session/lijxbwexqv1
The key thing I'm curious about is how sessions in Firebase are handled and established. How is a random session key being created, and also how is it being put in the URL to establish where the data is coming from (see code below).
//Create a reference to the pixel data for our drawing.
var pixelDataRef = new Firebase('https://lijxbwexqv1.firebaseio-demo.com/');
I'd like to create an educational app. Where the user is shown a picture of something, and then on their phone are seeing corresponding information to the picture they're being shown. I know this is different from the drawing demo, but the concepts of sessions is similar. Basically each user would have a "session" or a firebase data set--that they could access using a custom URL.
Any help or pointers (docs even) regarding the establishment and storage sessions would be greatly appreciated.
Thanks in advanced.

The "session" keys are random strings. They are generated in the source as follows:
UserSession.prototype.generateSessionID_ = function () {
if (window.isDebugMode) {
return "chat";
} else {
var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
var retVal = chars.charAt(Math.floor(Math.random() * 26, 1));
for (var i = 0; i < 10; i++) {
retVal = retVal + chars.charAt(Math.floor(Math.random() * chars.length, 1));
}
return retVal;
}
}
You could also simply use Firebase.push(), which generates random ids that also serve as sequential, chronological record ids:
function generateSessionId(ref) {
return ref.push().name();
}
var fb = new Firebase(URL);
console.log( generateSessionId(fb) );

Related

push name and amount to javascript object

I am trying to create an app for a site and users can send money to people on this site. Kinda like twitch. So i wanna create a toplist but i am new to using objects so i'm having some trouble and to explain my problem in a more easy way i added comments in my code
var myvar = [];
cb.onTip(function(tip){
// If username already exists in myvar then i want to just increase the amount for this user else if username does not exist i want to push up the name and amount to myvar
myvar.push({name: tip.from_user, amount: tip.amount});
});
function sendtoplist(user) {
var msg;
for(var i = 0; i <= 3; i++) {
// Here i am trying to create a toplist but i want to sort it by the amount. How can i do this?
msg += myvar.name + ' ' + myvar.amount+'\n';
}
// For some reason this sendNotice returns undefined (probably because i have no idea how to work with objects)
cb.sendNotice(msg, '', '#000000', '#FFFFFF', 'bold');
cb.setTimeout(sendtoplist, 30000);
}
cb.setTimeout(sendtoplist, 30000);
Do you know which specific function is not working?
If so, which error does it show to you?
to your first function:
//myvar should be already as an array, imported from a database for example
cb.onTip(function(tip){
// If username already exists in myvar then i want to just increase the amount for this user else if username does not exist i want to push up the name and amount to myvar
var personName = {};
personName.name = tip.from_user;
personName.amount = tip.amount;
var userExist = false;
for (let i=0; i < myvar.length; i++) {
if (myvar[i].name == personName.name){
myvar[i].amount += personName.amount;
userExist = true;
break;
}
}
if (!userExist) {
myvar.push(personName);
}
});
Is it clear for you? if not let me know.
To your 2nd function, learn some AngularJS basics, it is pretty easy, there you can use a filter and exactly the filter you need which is called ("orderBy")
Note:
I really recommend you to learn a framework, instead of using plain JS. If you dont want to learn that much, just learn AngularJS, it must be easy to learn. But if you think you would like to learn some modern framework, the learn Angular (working with typescript is needed)

Writing to same document in a WriteBatch causes multiple writes in Firebase?

I want to know if, in Firebase, I perform multiple updates to the same document in a batch, will it cause a single write or multiple writes?
For instance, in this example code (in javascript):
const doc = getDocumentReference();
batch.update(doc, { foo: "a" });
batch.update(doc, { bar: "b" });
batch.commit();
Will there be a single write to the document updating everything or there will be two writes, one for each update?
Does the answer change if one of the two operations is a "set" instead of an "update"?
Thanks in advance
I haven't found any reference how the writes are counted, but I found it interesting and tried to figure it out by myself. I prepared test and looked on Metrics explorer on Google Cloud Platform (Firebase database are visible there as well) and it can show the writes_count.
I prepared following codes:
adding whole object at once:
let test = db.collection("test").doc("sdaasd3")
test.set({})
let update = {}
for (let i = 0; i < 100; i++) {
update[i.toString()] = i;
}
test.update(update);
Then updating 100 times:
let test = db.collection("test").doc("sdaasd2")
test.set({})
for (let i = 0; i < 100; i++) {
let update = {}
update[i.toString()] = i;
test.update(update)
}
And in by batch commit:
let test = db.collection("test").doc("sdaasd")
test.set({})
const batch = db.batch();
for (let i = 0; i < 100; i++) {
let update = {}
update[i.toString()] = i;
batch.update(test, update)
}
batch.commit();
I performed them and it seems that batch commit is exactly the same as updating whole object at once and it takes 2 writes (I think one is set which I used to clear object in Firebase). While updating 100 times took 101 writes. Here as it looks (executed in order like in the post 12:57,01:01,01:07)
I am not sure, if this test was reliable enough to your needs, but you can use the Matrix explorer on GCP to analyze that on your own.

How to perform fast search on JSON file?

I have a json file that contains many objects and options.
Each of these kinds:
{"item": "name", "itemId": 78, "data": "Some data", ..., "option": number or string}
There are about 10,000 objects in the file.
And when part of item value("ame", "nam", "na", etc) entered , it should display all the objects and their options that match this part.
RegExp is the only thing that comes to my mind, but at 200mb+ file it starts searching for a long time(2 seconds+)
That's how I'm getting the object right now:
let reg = new RegExp(enteredName, 'gi'), //enteredName for example "nam"
data = await fetch("myFile.json"),
jsonData = await data.json();
let results = jsonData.filter(jsonObj => {
let item = jsonObj.item,
itemId = String(jsonObj.itemId);
return reg.test(item) || reg.test(itemId);
});
But that option is too slow for me.
What method is faster to perform such search using js?
Looking up items by item number should be easy enough by creating a hash table, which others have already suggested. The big problem here is searching for items by name. You could burn a ton of RAM by creating a tree, but I'm going to go out on a limb and guess that you're not necessarily looking for raw lookup speed. Instead, I'm assuming that you just want something that'll update a list on-the-fly as you type, without actually interrupting your typing, is that correct?
To that end, what you need is a search function that won't lock-up the main thread, allowing the DOM to be updated between returned results. Interval timers are one way to tackle this, as they can be set up to iterate through large, time-consuming volumes of data while allowing for other functions (such as DOM updates) to be executed between each iteration.
I've created a Fiddle that does just that:
// Create a big array containing items with names generated randomly for testing purposes
let jsonData = [];
for (i = 0; i < 10000; i++) {
var itemName = '';
jsonData.push({ item: Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15) });
}
// Now on to the actual search part
let returnLimit = 1000; // Maximum number of results to return
let intervalItr = null; // A handle used for iterating through the array with an interval timer
function nameInput (e) {
document.getElementById('output').innerHTML = '';
if (intervalItr) clearInterval(intervalItr); // If we were iterating through a previous search, stop it.
if (e.value.length > 0) search(e.value);
}
let reg, idx
function search (enteredName) {
reg = new RegExp(enteredName, 'i');
idx = 0;
// Kick off the search by creating an interval that'll call searchNext() with a 0ms delay.
// This will prevent the search function from locking the main thread while it's working,
// allowing the DOM to be updated as you type
intervalItr = setInterval(searchNext, 0);
}
function searchNext() {
if (idx >= jsonData.length || idx > returnLimit) {
clearInterval(intervalItr);
return;
}
let item = jsonData[idx].item;
if (reg.test(item)) document.getElementById('output').innerHTML += '<br>' + item;
idx++;
}
https://jsfiddle.net/FlimFlamboyant/we4r36tp/26/
Note that this could also be handled with a WebWorker, but I'm not sure it's strictly necessary.
Additionally, this could be further optimized by utilizing a secondary array that is filled as the search takes place. When you enter an additional character and a new search is started, the new search could begin with this secondary array, switching to the original if it runs out of data.

javascript - download several files

I'm new in javascript and i need to maintain a site.
The actual fonctionnality is to download several card into a file, one card per tab. As users can have plenty of cards, treatment can not always succeed (too many tabs), i wanted create a file evey 20 tabs for instance.
var printTerm = function(grid){
var rows = grid.selected;
if(rows==null) return;
var ids = rows.map(function(val){return grid.getDataByRow(val).num_terme;});
var nbMax = 20;
var nbFic;
var idsPartiel;
var posDebut;
var posFin;
var a;
if(ids.length > nbMax)
{
idsPartiel = ids;
if(ids.length % nbMax == 0) nbFic = ids.length / nbMax;
else nbFic = ((ids.length - (ids.length % nbMax)) / nbMax) + 1;
for (i=0 ; i< nbFic ; i++)
{
posDebut = (nbMax * i);
if(i == nbFic - 1) posFin = idsPartiel.length + 1;
else posFin = posDebut + nbMax;
ids = idsPartiel.slice(posDebut,posFin);
a = new Element('a', 'id':'download','href':'php/utils/export2pdf.php?ids='+ids.join(',')})
.addEvent('click',function(){location.href=this.href;}).inject(document.body);
a.fireEvent('click');
a.dispose();
}
}
else
{
a = new Element('a',{'id':'download','href':'php/utils/export2pdf.php?ids='+ids.join(',')})
.addEvent('click',function(){location.href=this.href;}).inject(document.body);
a.fireEvent('click');
a.dispose();
}
};
When the number of cards is less or equal to nbMax, it works well, bu when there must be several files, not: only the last passage of the loop is creating the file.
When i try to see what happens with firebug, i see my lines of treatment, but only the last is ended.
Thanks for helping me.
If I read your code correctly, you are trying to make the browser download a ton of files into separate tabs. Most browsers won't really appreciate you trying to launch a loop of downloads that way, nor would a user really want that many save as dialogs potentially popping off.
You would be way better off packaging them into a zip file server side and sending ONE file. It would be more efficient and way more user friendly.

how can I reverse playback in web audio API but keep a forward version as well?

To my knowledge, the Web Audio API in google Chrome (v21) does not support the following:
source.playbackRate.value = -1;
I very much wish! I will be patient, but in the meantime, this post has a nice alternative solution. I have adopted it to try and reverse my own audio samples loaded from a loaded bufferlist, hoping that I can have both a forward and reversed version of each loaded buffer, like so:
function finishedLoading(bufferList) {
for (var it = 0; it < this.urlList.length; ++it) {
storedBuffer[it] = bufferList[it]; // assign bufferList to globals
storedBufferR[it] = bufferList[it];
// attempt to reverse storedBufferR only ...
Array.prototype.reverse.call( storedBufferR[it].getChannelData(0) );
Array.prototype.reverse.call( storedBufferR[it].getChannelData(1) );
}
}
The above function indeed reverses playback, however it reverses both 'storedbufferR' and 'storedbuffer' such that all buffers are reversed!
So here is where I get lost... I understand that Array.protoype affects all arrays, so I suppose I can see how 'storedBuffer' is affected by a reverse method on 'storedBufferR'. EDIT: the reverse method only affects the array in question
But is it possible to rewrite the above function to ensure array.protoype affects only the stored buffer I want reversed? If not, is there another way to go about storing both a forward and reversed version?
The comment about the two AudioBuffers sharing the same reference was on the right track, but the solution isn't to create a new AudioContext; rather, you just need to create a new AudioBuffer and clone the underlying Float32Arrays that hold the actual audio samples.
For example, this function would clone an AudioBuffer:
function cloneAudioBuffer(audioBuffer){
var channels = [],
numChannels = audioBuffer.numberOfChannels;
//clone the underlying Float32Arrays
for (var i = 0; i < numChannels; i++){
channels[i] = new Float32Array(audioBuffer.getChannelData(i));
}
//create the new AudioBuffer (assuming AudioContext variable is in scope)
var newBuffer = context.createBuffer(
audioBuffer.numberOfChannels,
audioBuffer.length,
audioBuffer.sampleRate
);
//copy the cloned arrays to the new AudioBuffer
for (var i = 0; i < numChannels; i++){
newBuffer.getChannelData(i).set(channels[i]);
}
return newBuffer;
}
Then, to modify the above...
function finishedLoading(bufferList) {
for (var it = 0; it < this.urlList.length; ++it) {
storedBuffer[it] = bufferList[it]; // assign bufferList to globals
storedBufferR[it] = cloneAudioBuffer(bufferList[it]);
// attempt to reverse storedBufferR only ...
Array.prototype.reverse.call( storedBufferR[it].getChannelData(0) );
Array.prototype.reverse.call( storedBufferR[it].getChannelData(1) );
}
}

Categories

Resources