local storage object named with array - angularjs

I am trying to access native storage, I just need to transfer data from one storage object to other, were i added its reference name into an array, because the same process would get repeated again and again.
shiftingSequence(){
for (var index = 0; index < this.nextMonth.length; index++) {
this.nativeStorage.getItem(this.nextMonth[index]).then(
data =>{
console.log("we have data",index,data)
console.log(this.currrentMonth[index])
this.nativeStorage.setItem(this.currrentMonth[index], data);
this.nativeStorage.remove(this.currrentMonth[index]);
},
error => {
console.log("nextMonthData",index,error)
}
)
}
}
currrentMonth = ["monthData" , "NewspaperMonthData", "MaidMonthData" ];
nextMonth = ["nextMonthData", "nextMonthNewsData", "MaidNextMonthData" ];
the problem with the above code is, every time in native it falls to error block,
If i directly use the name i am able to shift data could someone help me to fix this
this is my console

Related

update objects in array with useState (reactJS)

Go to the end of this question for the solution that worked for me!
i'm currently making my own chess game and i want to check if a position already occurred 3 times. I keep the current position in a 2d array. This is what i tried:
Initialize the useState:
const [positionList, setPositionList] = useState([])
structure of the state should look like this
[
{
position: //some 2d array,
counter: 1
},
{
position: //another 2d array,
counter: 1
}
]
Compare the positions from the array with the current position
(if the position already existed, set counter one up)
let found = false
for (let i = 0; i < positionList.length; i++) {
if (JSON.stringify(positionList[i].position) === JSON.stringify(position)) {
positionList[i].counter = positionList[i].counter + 1
found = true;
break;
}
}
if the position never occurred before, add it to the array
if (found === false) {
setPositionList([...positionList, {position: position, counter: 1}]);
}
The 2nd and 3rd code block gets executed after every move (after players turn).
But for some reason, if "found" is false, it wont add the new position to the array but replace the last object in the array. And furthermore, when i log the changes made to "positionList" with a useEffect, it gets reset after every move to the default value (basically empty array), even though im not changing the state in any other part of my code.
I log the positionList like this:
useEffect(() => {
console.log(positionList)
}, [positionList])
I just cant figure out my error, hopefully someone can help.
Thanks!
EDIT:
I decided to try another way of counting the positions. I now only have one array which contains every position that occured in the correct order. Then i just loop through the array and count the amount of times the current position is in the array. My code looks like this:
Note: I think its important to note that you need to create a copy of the array you want to push. Otherwise all entrys in the array will be completly the same and you won't get the expected output (also see here)
function checkForThreefoldRepetition () {
let counter = 0;
for (let i = 0; i < positionList.length; i++) {
if (JSON.stringify(positionList[i]) === JSON.stringify(position)) {
counter++;
}
}
if (counter === 2) {
const updateGameOver = {
gameOver: true,
reason: "threefold repetition",
winner: "draw"
}
setGameOver(updateGameOver)
}
}
useEffect(() => {
let positionCopy = [];
for (let i = 0; i < position.length; i++) {
positionCopy[i] = position[i].slice();
}
setPositionList([...positionList, positionCopy]);
checkForThreefoldRepetition()
}, [playerTurn])
I think your problem is you are modifying current state directly like this one which is not a proper way of updating state :
positionList[i].counter = positionList[i].counter + 1
So this extra render cause problems,I think.

Compare an array within an object with an array within another object - both objects within the same parent array

I have an array of objects (~12 000 objects) each object looks like:
{id: num, name: "first last", identifiers: [num, num, num, num]}
What I need to do is compare each object with each other object within the array and if two objects have a matching identifier, I need to create another object in a completely separate array linking the two object ids.
When each object only had one number as an identifier, I could do it quite easily with:
let data = [*arr with objects*];
let nodes = data;
let len = nodes.length;
let links = [];
for (let i = 0; i < len; i++) {
let arrTest = nodes.findIndex((e) => e.identifiers === data[i].identifiers);
if (arrTest !== -1) {
const newLink = new Object();
newLink.source = nodes[arrTest].id;
newLink.target = data[i].id;
links.push(newLink);
}
}
However, with identifiers now being arrays I'm lost on the logic to receive the same outcome. What seems to make it harder for some attempts I've made is that some objects still only have a single number as an identifier - throwing errors if array methods such as .length are used??
My only thought right now is to create a new array with each identifier as a separate object with the id it originated from such as:
{identifier: num, id: num}
from this, it would just be a case of iterating through that array and connecting and creating new links through a similar method as above.
Wanted to know if there was a more efficient method, my JS is fairly limited and just really started making apps with it.
Any advice would be greatly appreciated.
Cheers
You could check the type of the identifier by doing something like-
if (typeof identifier === "number") {
// do what you are already doing
} else {
// it's an array so you can loop here
}
Using a dictionary to quickly access all other (previous) items with the same identifier
let data = [* arr with objects *];
const itemsByIdentifiers = {};
let links = [];
for (let item of data) {
// get (or create) the list with the recorded items for this identifier
let others = itemsByIdentifiers[item.identifiers] ||= [];
// iterate over that list and add the links
for (let other of others) {
links.push({
source: other.id,
target: item.id
});
}
// add myself to the list, so future items can find me and link to me
others.push(item);
}

Firebase Unity - Get all children into an array/generic list after GetValueAsync?

How can I get data back as an array or generic list from a Firebase database in Unity3D without knowing ahead of time what the name (key) of the children are?
I have been trying out the new Unity Firebase plugin, and I am having an issue figuring out how to get all the children in a specific location, and put the names (the key) and the values into arrays or generic lists so that I can work on the data locally. Forgive me for being so new to Firebase and probably using bad techniques to do this, and this plugin being so new its pretty hard for me to get much outside help, as there are not a lot of docs and tutorials out there on Firebase Unity.
In this particular case I am trying to create "instant messaging" like functionality, without the use of Firebase messaging, and just using regular Firebase database stuff instead. It might have been easier to use Firebase messaging, but mostly for the sake of learning and customization I want to do this on my own with just the Firebase database.
I insert data into the database like this:
public void SendMessage(string toUser, string msg)
{
Debug.Log(String.Format("Attempting to send message from {0} to {1}", username, toUser));
DatabaseReference reference = FirebaseDatabase.DefaultInstance.GetReference("Msgs");
string date = Magnet.M.GetCurrentDate();
// send data to the DB
reference.Child(toUser).Child(username).Child(date).SetValueAsync(msg);
// user receiving message / user sending message > VALUE = "hello dude|20170119111325"
UpdateUsers();
}
And then I try and get it back like this:
public string[] GetConversation(string userA, string userB)
{
// get a conversation between two users
string[] convo = new string[0];
FirebaseDatabase.DefaultInstance.GetReference("Msgs").GetValueAsync().ContinueWith(task =>
{
Debug.Log("Getting Conversation...");
if (task.IsFaulted || task.IsCanceled)
{
Debug.LogError("ERROR: Task error in GetConversation(): " + task.Exception);
}
else if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
string[] messagesA = new string[0], messagesB = new string[0];
if(snapshot.HasChild(userA))
{
// userA has a record of a conversation with other users
if(snapshot.Child(userA).HasChild(userB)) // userB has sent messages to userA before
{
Debug.Log("Found childA");
long count = snapshot.Child(userA).Child(userB).ChildrenCount;
messagesA = new string[count];
var kids = snapshot.Child(userA).Child(userB).Children;
Debug.Log(kids);
for (int i = 0; i < count; i++)
{
// this won't work, but is how I would like to access the data
messagesA[i] = kids[i].Value.ToString(); // AGAIN.... will not work...
}
}
}
if(snapshot.HasChild(userB))
{
if(snapshot.Child(userB).HasChild(userA)) // userA sent a message to userB before
{
Debug.Log("Found childB");
long count = snapshot.Child(userB).Child(userA).ChildrenCount;
messagesA = new string[count];
var kids = snapshot.Child(userB).Child(userA).Children;
Debug.Log(kids);
// messy incomplete testing code...
}
}
// HERE I WOULD ASSIGN ALL THE MESSAGES BETWEEN A AND B AS 'convo'...
}
Debug.Log("Done Getting Conversation.");
});
return convo;
}
But obviously this won't work, because DataSnapshot won't let me access it like an array or generic list using indices, and I can't figure out how to treat the data when I don't know the names (the keys) of all the children, and just want to get them out one by one in any order... and since they are named by the date/time they are entered into the DB, I won't know ahead of time what the childrens names (keys) are, and I can't just say "GetChild("20170101010101")" because that number is generated when its sent to the DB from any client.
FYI here is what the DB looks like:
Figured out the answer to your question. Here's my code snippet. Hope this would help!
void InitializeFirebase() {
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl ("https://slol.firebaseio.com/");
FirebaseDatabase.DefaultInstance
.GetReference ("Products").OrderByChild ("category").EqualTo("livingroom")
.ValueChanged += (object sender2, ValueChangedEventArgs e2) => {
if (e2.DatabaseError != null) {
Debug.LogError (e2.DatabaseError.Message);
}
if (e2.Snapshot != null && e2.Snapshot.ChildrenCount > 0) {
foreach (var childSnapshot in e2.Snapshot.Children) {
var name = childSnapshot.Child ("name").Value.ToString ();
text.text = name.ToString();
Debug.Log(name.ToString());
//text.text = childSnapshot.ToString();
}
}
};
}
Firebase developer here.
Have you tried to use Value at the top level Snapshot? It should return to you an IDictionary where the values can also be lists or nested dictionaries. You will have to use some dynamic inspection to figure out what the values are.

Angular - Objects seem bound to eachother but arent

I have an edit page where the user can edit a file in the system, and then save it. When loading the file, I make two objects out of the result, one is bound to the view and the other I wish to keep (in its original state) until "save" is clicked, and then use it to compare vs the view-bound object, to see if any changes have been made.
So, when the page loads, this is being run
$http.get('/api/files/' + $stateParams.id)
.then(function (result) {
vm.fileTemp = result.data;
vm.fileTempCopy = result.data;
The fileTempCopy is not being touched or referenced by anything in the view or elsewhere in the controller, except in the save-method, where i check if they are alike or not. But somehow, both of them are updated when i make changes to the input fields (as if they were both used as ng-model for the inputs).
if(vm.fileTemp === vm.fileTempCopy)//in save-function
is always true, and their fields are exactly the same.
Why does this happen and how can I solve it?
Using the assignment operator, you are actually just referencing the original array. Arrays are reference types. That means, that they don't actually store values, they only store references to those values. What you where doing is copying a reference to a memory location, meaning that any changes to the memory at that location (including removing elements) will be reflected in both arrays.
So you will want to do this instead:
vm.fileTemp = angular.copy(result.data);
vm.fileTempCopy = angular.copy(result.data);
here is a very basic approach to checking an object's "value equality".
function isEquivalent(a, b) {
// Create arrays of property names
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
// If number of properties is different,
// objects are not equivalent
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
// If values of same property are not equal,
// objects are not equivalent
if (a[propName] !== b[propName]) {
return false;
}
}
// If we made it this far, objects
// are considered equivalent
return true;
}
//After your update Outputs: false
console.log(isEquivalent(vm.fileTemp, vm.fileTempCopy));

Iterating through parent entity to return array of child entities

I am trying to build an array of entities from a server query that exist in an object arrays
The diagram below illustrates my model:
In my datacontext, I've applied the following code:
function getByDboardConfig(dboardConfig) {
var busUnitDims = [];
var busUnitsTotalCount = dboardConfig.busUnits.length;
var buCount = 0;
dboardConfig.busUnits.forEach(function (busUnit) {
eq.from('BusUnitDimensions') // eq = breeze.EntityQuery
.where('busUnitId', '==', busUnit.id)
.using(em).execute() // em = EntityManager
.to$q(succeeded, failed); // using Angular, thus to$q
});
function succeeded(data) {
buCount++;
data.results.forEach(function (result) {
busUnitDims.push(result);
});
if (buCount === busUnitsTotalCount) {
console.log(busUnits.length);
return busUnitDims;
}
}
}
When I log to the console as show the length of the array, I get the correct entity count, but when I return the result of this call to my controller I get undefined. Not understanding why?
I've tried returning $q.when(busUnitDims) as well but I still get undefined.
The problem with your code is that the function is not returning anything, even if you relocate the return line outside the succeeded block
, it may return before filling the array is finished(notice you're executing the query asynchronously )
Neverthless, looking at your code; I take it you are getting the busUints and then query for each of their line items BusUnitDimensions separately;
that could mean many roundtrips to the server.
Anyways, you aim to fetching busUnits along with their related BusUnitDimensions (eager loading).
Although you didn't provide an idea of how your view model or your controller looks like; I assume you have one view for DboardConfig and another view for both related busUnits and BusUnitDimensions
so your workflow is:
Get a list of DboardConfigs
for each DboardConfig, load it's busUnits along with BusUnitDimensions
Hence, your function could be :
function getByDboardConfig(dboardConfig) {
return eq.from("busUnits")
.where("dboardConfigId", "==", dboardConfig.id)
.expand("BusUnitDimensions")
.using(em).execute() // em = EntityManager
Then inside your controller:
$Scope.getBusUnitsandDimentions = function () {
dataservice.getByDboardConfig($Scope.dboardConfig)
.then(succeeded)
.fail(failed);
};
function succeeded(data) {
$Scope.busUnits = [];
data.results.forEach(function (result) {
$Scope.busUnits.push(result);
});
}
}
}
This way, you can remove the coding for fetching busUnits since we've already fetched it with it's related child table.
Simply put:
busUnits to get your array of bus units for a specified DboardConfig
busUnits.BusUnitDimensions to get it's related dimensions

Resources