Converting FirebaseDataSnapshot into a JS object - firebase

I am pushing on object into my ROOMS array with .on("child_added", ....) as below. One of the parts of that object is an array of other objects (Player obj which has some properties like id, name, and so on). How do i assign to ROOMS.players because snap.child("players").val() does not work (EXCEPTION: Error trying to diff '[object Object]') snap.child("players").val() structure looks something like this:
-rooms
-id
-name
-isRoomFull
+board
-players
-kEFvdfeff84fdfdff
-id
-name
-kEFvd4545dfjh9fvv
-id
-name
getRooms() {
this.roomsRef.on("child_added", function(snap) {
ROOMS.push({
id: snap.child("id").val(),
name: snap.child("name").val(),
players: [], //how to assign to this property
isRoomFull: snap.child("isRoomFull").val(),
board: snap.child("board").val(),
})
});

I would try something like that:
var obj = snap.child("players").val().players;
var players = Object.keys(obj).map(key => return obj[key]);
ROOMS.push({
id: snap.child("id").val(),
name: snap.child("name").val(),
players: players,
isRoomFull: snap.child("isRoomFull").val(),
board: snap.child("board").val(),
});
See this question for more details:
Converting a JS object to an array

Related

Get an array of specific parameters from Image Collection of Google Earth Engine

I've got an Image Collection like:
ImageCollection : {
features : [
0 : {
type: Image,
id: MODIS/006/MOD11A1/2019_01_01,
properties : {
LST_Day_1km : 12345,
LST_Night_1km : 11223,
system:index : "2019-01-01",
system:asset_size: 764884189,
system:footprint: LinearRing,
system:time_end: 1546387200000,
system:time_start: 1546300800000
},
1 : { ... }
2 : { ... }
...
],
...
]
From this collection, how can I get an array of objects of specific properties? Like:
[
{
LST_Day_1km : 12345,
LST_Night_1km : 11223,
system:index : "2019-01-01"
},
{
LST_Day_1km : null,
LST_Night_1km : 11223,
system:index : "2019-01-02"
}
...
];
I tried ImageCollection.aggregate_array(property) but it allows only one parameter at one time.
The problem is that the length of "LST_Day_1km" is different from the length of "system:index" because "LST_Day_1km" includes empty values, so it's hard to combine arrays after get them separately.
Thanks in advance!
Whenever you want to extract data from a collection in Earth Engine, it is often a straightforward and efficient strategy to first arrange for the data to be present as a single property on the features/images of that collection, using map.
var wanted = ['LST_Day_1km', 'LST_Night_1km', 'system:index'];
var augmented = imageCollection.map(function (image) {
return image.set('dict', image.toDictionary(wanted));
});
Then, as you're already familiar with, just use aggregate_array to extract that property's values:
var list = augmented.aggregate_array('dict');
print(list);
Runnable complete example:
var imageCollection = ee.ImageCollection('MODIS/006/MOD11A1')
.filterDate('2019-01-01', '2019-01-07')
.map(function (image) {
// Fake values to match the question
return image.set('LST_Day_1km', 1).set('LST_Night_1km', 2)
});
print(imageCollection);
// Add a single property whose value is a dictionary containing
// all the properties we want.
var wanted = ['LST_Day_1km', 'LST_Night_1km', 'system:index'];
var augmented = imageCollection.map(function (image) {
return image.set('dict', image.toDictionary(wanted));
});
print(augmented.first());
// Extract that property.
var list = augmented.aggregate_array('dict');
print(list);
https://code.earthengine.google.com/ffe444339d484823108e23241db04629

Flowtype return value depending on input

I think my question is easy, but nonetheless I could not find an answer anywhere.
I want to typecheck a function, but what I cannot seem to do is bind the return type to the input type.
Say I have a deck of cards that is typed, and I want a (imaginairy) return type that depends on the input given an existing mapping.
The deck with the function:
type Suit = "diamonds" | "clubs" | "hearts" | "spades"
const suitMapping = {
"diamonds": ["are", "forever"],
"clubs": ["fabric", "fuse"],
"hearts": ["she", "loves", "me"],
"spades": ["lemmy", "loud"]
}
const suitToList = (suit: Suit) => {
return suitMapping[suit]
}
So for instance, I know that suitToList("diamonds") will return ["are", "forever"]. And the mapping in the object is fixed and computer generated. But I would love it if there would be a way to typespec the mapping with Flow. That way, if somewhere down the road someone wants to add "motorhead" to "spades", the typecheck would fail at first, so the functions depending on the output could be checked.
For now, I have tests for it, but somewhere I feel this could be possible with Flow too.
I find a way to typecheck this, but with usage of any. Not too clean way, but I think it's a flow bug. See https://github.com/facebook/flow/issues/2057#issuecomment-395412981
type Suit = "diamonds" | "clubs" | "hearts" | "spades"
type SuitMapping = {
diamonds: string,
clubs: number,
hearts: Array<string>,
spades: Array<string>,
}
const suitMapping: SuitMapping = {
"diamonds": '',
"clubs": 1,
"hearts": ["she", "loves", "me"],
"spades": ["lemmy", "loud"]
}
const suitToList = <K: Suit>(suit: K): $ElementType<SuitMapping, K> => {
return (suitMapping[suit]: any);
}
// suitToList('xxx'); // error
// const x: number = suitToList('diamonds'); // error
const y: string = suitToList('diamonds'); // works
See on flow try

Saving scraped data to mysql database through phantomjs and casperjs

Hi I am working on a web scraper, first I was trying to scrape using php CURL, but then I faced a problem that I wasn't able to scrape the sites which loads through AJAX and then I shifted to 'phantom JS' and 'casper JS`.
Now I have successfully installed the webkit and can scrape the data from any website, but I am unable to save the data for long use in a database. Simply, for later use. What I want to do is, whatever data I have scraped I want to save that to mySql database.
Is there any way I can achieve such functionality? I have tried sending Ajax request to send the data to the database but failed.
I came up with one another solution for instance, that is when I scrape the data from the specified website, I push the data to an array called data[] and then I write that data to a .json file. Where each bunch of data is saved in array of objects form which is get from JSON.stringify(data).
Now, I don't know if how can I get that file data and save it in database? Is it possible that, whenever the scraping is finished, right after I grab data from that .json file and save it to database.
For now just take this code as an example
var casper = require('casper').create();
var file = require('fs');
var data = [];
casper.start('http://casperjs.org/', function() {
data.push(this.getTitle());
file.write("file.json", JSON.stringify(data), "a");
});
casper.run();
A Proof Of Concept, using jq :
#!/bin/bash
casperjs script.js
[[ -s file.json ]] || exit 1
jq '"UPDATE ROW SET XXX = "+ .[] + " WHERE FOO=BAR;"' file.json | mysql -D DB_name
The file.json :
[
"foo",
"bar",
"base"
]
jq output :
jq -r '"UPDATE ROW SET XXX = "+ .[] + " WHERE FOO=BAR;"' file.json
UPDATE ROW SET XXX = foo WHERE FOO=BAR;
UPDATE ROW SET XXX = bar WHERE FOO=BAR;
UPDATE ROW SET XXX = base WHERE FOO=BAR;
Check https://stedolan.github.io/jq/
Simple solution I found is to make ajax request to the server, inside the evaluate function :
casper.then(function() {
details = this.evaluate(function() {
var elDet = document.getElementsByClassName("job-description-column")[0];
var detLen = elDet.children[2].children[0].children.length;
var details = elDet.children[2].children[0].children;
var linkedData = [];
for (var i = 0; i < detLen; i++) {
if (details[i].nodeName == "H3" && details[i].id != "if-this-sounds-like-you,-apply") {
linkedData.push({
head: details[i].textContent,
description: details[i + 1].textContent,
title: elDet.children[0].children[0].children[0].textContent,
loc: elDet.children[0].children[0].children[1].textContent,
date: elDet.children[0].children[0].children[2].textContent
})
i++;
} else {
linkedData.push({
head: "No Head",
description: details[i].textContent,
title: elDet.children[0].children[0].children[0].textContent,
loc: elDet.children[0].children[0].children[1].textContent,
date: elDet.children[0].children[0].children[2].textContent
})
}
}
var s = JSON.stringify(linkedData);
console.log(linkedData);
$.ajax({
method: "POST",
url: "http://localhost/fiverr/Crawl%20The%20Jobs/modal_scripts.php",
data: "add_jobdets=true&job_details=" + s,
async: false
})
return linkedData;
})
})

Pick one of union

I am trying to use the type ImageURISource which is here - https://github.com/facebook/react-native/blob/26684cf3adf4094eb6c405d345a75bf8c7c0bf88/Libraries/Image/ImageSource.js#L15
type ImageURISource = {
uri?: string,
bundle?: string,
method?: string,
headers?: Object,
body?: string,
cache?: 'default' | 'reload' | 'force-cache' | 'only-if-cached',
width?: number,
height?: number,
scale?: number,
};
export type ImageSource = ImageURISource | number | Array<ImageURISource>;
However we see that it is exported as a union along with 2 other things. Is it possible to pick from a union just one?
I was hoping to do:
$Pick<ImageSource, ImageURISource>
It's not very pretty, but you could use refinement to specifically refine the type that you want out of it by doing something like this:
var source: ImageSource = {}
if (typeof source === "number" || Array.isArray(source)) throw new Error();
var uriSource = source;
type ImageURISource = typeof uriSource;
The downside here is that if the add more types to the union, your code would start failing again.
It seems like you'd be best off making a PR to react-native to expose that type.

How to pre-select an option in a dropdown knockout js

I've looked at this other question, but can't get my select box to work correctly:
Binding initial/default value of dropdown (select) list
I've got the following Game object:
function Game(visitingTeamDetails, homeTeamDetails, game) {
if (arguments.length > 0) {
this.VisitingTeamDetails = visitingTeamDetails;
this.HomeTeamDetails = homeTeamDetails;
this.GameId = ko.observable(game.GameId);
this.HomeTeamName = ko.observable(game.HomeTeamName);
this.VisitingTeamName = ko.observable(game.VisitingTeamName);
this.SportTypeName = ko.observable(game.SportTypeName);
this.HomeAccountName = ko.observable(game.HomeAccountName);
this.VisitingAccountName = ko.observable(game.VisitingAccountName);
this.GameDateString = ko.observable(game.GameDateString);
this.GameTimeString = ko.observable(game.GameTimeString);
this.AvailableSportTypes = ko.observableArray(game.Sports);
this.sportTypeFunction = function () {
for (sportType in this.AvailableSportTypes()) {
if (this.AvailableSportTypes()[sportType].Name == this.SportTypeName()) {
return this.AvailableSportTypes()[sportType];
}
}
return null;
};
this.SportType = ko.observable(game.SportType);
}
}
SportType is an object with Name and SportTypeId.
I have the following template:
<td rowspan="3"><select data-bind="options: AvailableSportTypes, value: SportType, optionsText:'Name', optionsCaption: 'Choose...'" class="sportType"></select></td>
AvailableSportTypes is a list of SportType.
The list is coming in with the names of the SportTypes in the drop down list, but I can't make the initial selection be SportType. I wrote sportTypeFunction to show myself that the data was coming in correctly, and it would select the correct value, but changing my selection in the drop down would not update SportType.
I'm sure I'm doing something wrong. Anyone see it?
Thanks
When game.SportType gets passed in, it needs to be a reference to the an item in the game.AvailableSportTypes and not just an object that looks the same.
Basically two objects are not equal unless they are actually a reference to the same object.
var a = { name: "test" },
b = { name: "test" };
alert(a === b); //false
So, you would need to call your function to locate the correct object in the array and set it as the value of your observable.
Not that it is way better, but in KO 1.3 you can extend .fn of observables, observableArrays, and dependentObservables to add additional functionality.
Here is a sample: http://jsfiddle.net/rniemeyer/ZP79w

Resources