What causing this error Immer only supports setting array indices and the 'length' property - redux

I am new to redux. I am now going to select movies to be pinned to another page. I can passed the id selected to the reducer. Then i will change the one of the variable so that it can be display on the other page. Once I checked the checkbox, I encounter this problem
My reducer
showSelectedPinnedMovie: function(state,action){
alert(action.payload);
if(action.payload) {
state.count++
state.movieId.push(action.payload)
};
if(state.count >= 6){
alert("You cannot pinned more than 5")
}
for(let c=0; c < state.value.length; c++ ){
state.value.selecttobepinned = false;
}
for(let i=0; i< state.value.length; i++ ){
for(let c=0; c< state.selectedPinnedId.length; c++){
if(state.value[i].id !== state.selectedPinnedId[c]){
return Object.assign({},state.value[i],{ "selecttobepinned" : true});
}
}
return state.value;
}
for(let i=0; i< state.value.length; i++ ){
for(let c=0; c< state.selectedPinnedId.length; c++){
if(state.value[i].id === state.selectedPinnedId[c]){
return Object.assign({},state.value[i],{ "selecttobepinned" : true});
}
}
return state.value;
}
state.count =0;
state.selectedPinnedId = [];
},
My initial data
initialState: {
value: [
{ "id": 1,"movie name" : "Ticket to Paradise","display":true,"description":"Academy Award® winners George Clooney and Julia Roberts reunite on the big screen as exes who find themselves on a shared mission to stop their lovestruck daughter from making the same mistake they once made","genre" :"Comedy", "lead actor": ["George Clooney", "Julia Roberts"],"rating":5,"displayOneMovie":false,"selecttobepinned":false,"language":"english"},
{ "id": 2, "movie name": "Black Panter","display":true,"description":"Queen Ramonda (Angela Bassett), Shuri (Letitia Wright), M’Baku (Winston Duke), Okoye (Danai Gurira) and the Dora Milaje (including Florence Kasumba), fight to protect their nation from intervening world powers in the wake of King T’Challa’s death.","genre":"Action","lead actor":["Angela Bassett","Letitia Wright"],"rating":6,"displayOneMovie":false,"selecttobepinned":false,"language":"english"},
{ "id":3, "movie name": "Smile","display":true,"description":"After witnessing a bizarre, traumatic incident involving a patient, Dr. Rose Cotter (Sosie Bacon) starts experiencing frightening occurrences that she can't explain.","genre":"Drama","lead actor":["Sosie Bacon","Jessie T. Usher"],"rating":6,"displayOneMovie":false,"selecttobepinned":false,"language":"english"},
{"id":4,"movie name":"Come Back Home","display":true,"description":"In the cold winter, a group of Shenzhen tourist families take a trip to the northeast Changbai Mountain. It was originally intended to be a happy and harmonious holiday, but due to the negligence of his father, an 8-year-old boy is unfortunately lost.","genre":"Mistery","lead actor":["Donnie Yen", "Han Xue"],"rating":6,"displayOneMovie":false,"selecttobepinned":false,"language":"mandarian"},
{"id":5,"movie name":"Ajoomma","display":true,"description":"Auntie (Hong Huifang), is a middle-aged Singaporean woman who has dedicated the best years of her life to caring for her family. Now widowed with her grown up son, Sam (Shane Pow) about to fly the roost, Auntie is left to contend with a whole new identity beyond her roles of daughter, wife, and mother.","genre":"Drama","lead actor":["Hong Huifang", "Jung Dong-Hwan"],"rating":4,"displayOneMovie":false,"selecttobepinned":false,"language":"mandarian"},
{"id":6,"movie name":"The King Of Musang King","display":true,"description":"Mao Shan (Jack Neo) is an ambitious durian farmer who wishes to expand his sales overseas, against pressures from the “Three Heavenly Kings” of the business. He helps Mei Lian (Yeo Yann Yann), his neighbour and sole supporter, to improve her durian farm harvests, and develops feelings for her in the process.","genre":"Comedy","lead actor":["Mark Lee","Henry Thia"],"rating":4,"displayOneMovie":false,"selecttobepinned":false,"language":"mandarian"}
],
movieId: [],
count: 0,// No records initially
},
I don't know whether I am updateing the state correctly. Can anyone solve this problem for me?

Related

Firebase - Querying in flattened data with Two Way Relationship

I currently have a Firebase database with the following structure
// Tracking two-way relationships between users and groups {
" users": {
"mchen": {
"name": "Mary Chen",
"groups": {
"alpha": true,
"charlie": true
}
},
...
}, "groups": {
"alpha": {
"name": "Alpha Group",
"members": {
"mchen": true,
"donald": true
}
}, "bravo": {
"name": "Bravo Group",
"members": {
"mickey": true,
"donald": true
}
},
...
}
}
How do I write a query to show me all the groups a given set of users have in common. i.e. show me all groups where Mickey and Donald both registered.
I don't think that is possible with a single query, and multiple equalTo are not supported.
I would restructure your database as such
root
L users
L groups
L groupName
L ...
L groupMembers
L groupName
L userName:true
Then query like
Query is reference.child('groupMembers').orderByChild('Donald').equalTo(true);
Then go through the results
List resultList
for all DataSnapshot's as snapshot in dataSnapshot's Children
if snapshot.child('Mickey') is not null
add to resultList key of snapshot
// resultList now contains all group keys/names which Donald and Mickey are both appart of.
That would be one way to solve your problem, but you would initially be downloading groups which Mickey might not be apart of. this may or may not be what you want (security etc..).
If you wanted to only get groups which they are both appart of without any clientside filtering, you would have to restructure your database to something like this.
root
L users ...
L groups ...
L groupPairs
L groupName
L DonaldMickey:true
Your query would look similar, adding/removing a user from a group would be more elaborate. You would have to make sure that every possible pair is under the groupName. You could reduce the amount of pairs by setting a criteria like for example: Donald before Mickey because D is before M, or something like that.

Is there a way to do this in FullCalendar jquery

You can make description that says Kids Art School Day in April 12 to April 17th. It will make a bar across from that date like this"Kids Art School Day". How do you make each day show the same thing like a tradition paper calendar. April 12 says "Kids Art School Day", April 13 says "Kids Art School Day", April 14 says "Kids Art School Day", ........ all saying the same thing? I can do it in the events ,like this
'title': 'Kids Art School Day ',
'start': '2015-04-13',
'end': '2015-07-13',
'color': '#FFFFFF',
'textColor': '#3300FF'
'title': 'Kids Art School Day ',
'start': '2015-04-14',
'end': '2015-07-14',
'color': '#FFFFFF',
'textColor': '#3300FF'
I did a range but they want it to show each box the same thing..beats me.. ideas? In the calendar there is a lot of them.. making this json readable will be too much...
This isn't directly supported and so the solution is a little tricky.
Essentially, you break up the events into single day events when they are loaded. Use the function event source for this.
events: function (start, end, timezone, callback) {
//Get the events with an ajax call or whatever.
//Here, they're just declared globally as 'events'
var chunkedEvents = [];
for (var i = 0; i < events.length; i++) {
var days = moment(events[i].end).diff(events[i].start, 'days'); //length of event
if (typeof events[i].end !== "undefined" && days > 0) {
for (var j = 0; j <= days; j++) {
chunkedEvents.push($.extend({}, events[i], {
start: moment(events[i].start).subtract(j, 'days'),
end: moment(events[i].end).subtract(days + j, 'days')
}))
}
} else {
chunkedEvents.push(events[i]);
}
}
callback(chunkedEvents);
}
JSFiddle

Crossfilter reduce :: find number of uniques

I am trying to create a custom reduce function for a dataset attribute group that would sum a number of unique values for another attribute.
For example, my dataset looks like a list of actions on projects by team members:
{ project:"Website Hosting", teamMember:"Sam", action:"email" },
{ project:"Website Hosting", teamMember:"Sam", action:"phoneCall" },
{ project:"Budjet", teamMember:"Joe", action:"email" },
{ project:"Website Design", teamMember:"Joe", action:"design" },
{ project:"Budget", teamMember:"Sam", action:"email" }
So, team members work on a variable number of projects by performing one action per line. I have a dimension by team member, and would like to reduce it by the number of projects (uniques).
I tried the below (storing project in a uniques array) without success (sorry, this might hurt your eyes):
var teamMemberDimension = dataset.dimension(function(d) {
return d.teamMember;
});
var teamMemberDimensionGroup = teamMemberDimension.group().reduce(
// add
function(p,v) {
if( p.projects.indexOf(v.project) == -1 ) {
p.projects.push(v.project);
p.projectsCount += 1;
}
return p;
},
// remove
function(p,v) {
if( p.projects.indexOf(v.projects) != -1 ) {
p.projects.splice(p.projects.indexOf(v.projects), 1);
p.projectsCount -= 1;
}
return p;
},
// init
function(p,v) {
return { projects:[], projectsCount:0 }
}
);
Thanks a lot!
Edit after DJ Martin's answer ::
So, to be clearer, I would like to get the numbers I am after here would be:
-----------
Sam : 2 (projects he is workin on, no matter the number of actions)
Joe : 2 (projects he is workin on, no matter the number of actions)
-----------
The answer provided by DJ Martin gets me there. But rather than hard coding a table, I would like to find a way to use these numbers for my DC.JS bar chart. When I was only using the number of actions (so just a reduceCount() ), I did it like below:
teamMemberChart.width(270)
.height(220)
.margins({top: 5, left: 10, right: 10, bottom: 20})
.dimension(teamMemberDimension)
.group(teamMemberDimensionGroup)
.colors(d3.scale.category20())
.elasticX(true)
.xAxis().ticks(4);
I guess there might be something to change in the group().
UPDATED ANSWER
Sorry I misunderstood the question... you are actually on the right track. You'll just need to maintain a count of each project so that your subtract function can know when to remove the value.
teamMemberGroup = teamMemberDimension.group().reduce(
function (p, d) {
if( d.project in p.projects)
p.projects[d.project]++;
else p.projects[d.project] = 1;
return p;
},
function (p, d) {
p.projects[d.project]--;
if(p.projects[d.project] === 0)
delete p.projects[d.project];
return p;
},
function () {
return {projects: {}};
});
Here is an updated fiddle: http://jsfiddle.net/djmartin_umich/3LyhL/

Google Places Autocomplete suggestions with Unit No/Subpremise is not coming in the response array

I am using Google places API to auto-complete addresses using javascript
When I type the unit number and street number of address in the input box it shows the results in suggestion drop-down but when I select the address the listener for action 'place_changed' event don't have any address with address_component with type 'subpremise' even the formatted_address property don't have the unit number in it.Though it does contain other details from 'street number','city','country' etc
For example : If I type "1403/648 Bourke Street" with a country restriction to Australia. It shows me 5 results in the dropdown with first one as "1403/648 Bourke street, Melbourne,Australia" but when I select this option all I get in the place_change event listener is "648 Bourke street, Melbourne, Australia"
This issue is intermittent though, it works for some unit addresses but fail for other.Any suggestion will be highly appreciated!!
It seems to me like Google is validating that the address is real (well atleast real when they last updated their places database - I guess with government records). The problem is that subdivisions are happening all the time where new "subpremise" addresses are created, and a look up on these seems to be br0ken more often. It's strange that they allow a "non-valid" address as an autocomplete suggestion but then limit the result.
A look up on the Sydney address below will return "subpremise" and "street_number"
"9/321 Pitt Street, Sydney, New South Wales, Australia"
Where the Melbourne address below only gets as accurate as "route"
"2/321 Pitt Street, Brunswick, Victoria, Australia"
The biggest problem is that the result doesn't return the unit or street number anywhere in the reply.
I have hacked together the following JS to compare the user-entered address with the returned result. If the "numbers" are missing, they are added. You can customise as you need to fit with your code.
if (addressType == 'route') {
var regex = RegExp('^(.*)'+GPLACESSTREET.split(' ',1)[0]), // get all the user entered values before a match with the first word from the Google result
result = regex.exec(INPUTFEILD.value);
if ( Array.isArray(result) ) {
FULLSTREETADDRESS = result[1]+''+GPLACESSTREET; // add the street name to the user-entered unit & street number
}
}
The Places Autocomplete API is not designed to support 'subpremise' results. This was reported and answered some time ago in the public issue tracker at https://issuetracker.google.com/35830389
Australian addresses for subpremise results look "close enough" to those of street_address/premise results (they start with mostly digits). This is currently resulting in Place Autocomplete returning what may look like a subpremise result, however note that the type is still "route":
http://maps.googleapis.com/maps/api/place/autocomplete/json?input=9/321%20Pitt%20Street,%20Sydney
description: "9/321 Pitt Street, Sydney NSW, Australia",
place_id: "Eig5LzMyMSBQaXR0IFN0cmVldCwgU3lkbmV5IE5TVywgQXVzdHJhbGlh",
types: ["route","geocode",],
Place Details (and Geocoding) requests with this place_id will in fact find the correct subpremise result:
https://maps.googleapis.com/maps/api/place/details/json?placeid=Eig5LzMyMSBQaXR0IFN0cmVldCwgU3lkbmV5IE5TVywgQXVzdHJhbGlh
"result" : {
"address_components" : [
{
"long_name" : "9",
"short_name" : "9",
"types" : [ "subpremise" ]
},
{
"long_name" : "321",
"short_name" : "321",
"types" : [ "street_number" ]
},
...
"formatted_address" : "9/321 Pitt St, Sydney NSW 2000, Australia",
"types" : [ "subpremise" ],
However, this is not guaranteed to work for all subpremise queries, or even for this particular one in the long term.
A more reliable approach would be to use the Geocoding API to search for the prediction's "description":
https://maps.googleapis.com/maps/api/geocode/json?&address=9%2F321%20Pitt%20St%2C%20Sydney%20NSW%202000%2C%20Australia
"results" : [
{
"address_components" : [
{
"long_name" : "9",
"short_name" : "9",
"types" : [ "subpremise" ]
},
{
"long_name" : "321",
"short_name" : "321",
"types" : [ "street_number" ]
},
...
],
"formatted_address" : "9/321 Pitt St, Sydney NSW 2000, Australia",
"place_id" : "Eik5LzMyMSBQaXR0IFN0LCBTeWRuZXkgTlNXIDIwMDAsIEF1c3RyYWxpYSIdGhsKFgoUChIJkyPU0z2uEmsR-pmiK6UvZUASATk",
"types" : [ "subpremise" ]
Google doesn't support it, but you cant stop customers doing it!
Here is a complete function inspired by #MountainAsh's & #Randell's code:
/* Add the unit number (+ fix the street number) if required.
*
* Idea from https://stackoverflow.com/questions/17936689/google-places-autocomplete-suggestions-with-unit-no-subpremise-is-not-coming-in
*
* Test cases:
* 9/321 Pitt Street, Sydney, New South Wales, Australia <-- Google throws away the unit number
* 2/321 Pitt Street, Brunswick, Victoria, Australia <-- Google says street number = 2
* 1b/123 Clayton Road, Clayton, Victoria, Australia <-- Google says street number = 1
*/
function autofillUnitNumber(txtAutocomplete, txtUnitNumber, txtStreetNumber, txtStreetName) {
var regex = RegExp("^(.*?)\/(.*?) " + txtStreetName.value); // get all the user entered values before a match with the street name; group #1 = unit number, group #2 = street number
var results = regex.exec(txtAutocomplete.value);
if (Array.isArray(results)) { // it was in unit number/street number format
var unitNumber = results[1]; // group #1
var streetNumber = results[2]; // group #2
txtUnitNumber.value = unitNumber;
txtStreetNumber.value = streetNumber;
}
}
Just call it after you have used Google autocomplete to autofill your other form fields eg:
autofillUnitNumber(
document.getElementById("txtAutocomplete"),
document.getElementById("txtUnitNumber"),
document.getElementById("txtStreetNumber"),
document.getElementById("txtStreetName"));
Since I just wanted to collect the Unit number and prepend it to the Street Number, my solution is:
const place = this.AutoComplete.getPlace();
if (isNullOrUndefined(place)) return;
const parts = place.address_components;
const getAddressPart = part => {
const found = parts.find(p => p.types.indexOf(part) > -1);
if (found) {
return found.long_name;
}
return null;
};
const address = this.Input.current.value; // input[text] value
let streetNumber = getAddressPart("street_number");
// Regex Match associated
if (streetNumber) {
const regex = RegExp(`[^\\s,]*(${streetNumber})[^\\s,]*`);
const foundStreetNumber = regex.exec(address);
streetNumber = foundStreetNumber[0];
}
const Address = {
FullAddress: address,
StreetNumber: streetNumber,
Street: getAddressPart("route"),
Suburb: getAddressPart("sublocality"),
City: getAddressPart("locality"),
Country: getAddressPart("country"),
PostCode: getAddressPart("postal_code")
};
This will improve the street number data from the Google Places API, catering for addresses such as:
4/33 Mokoia Rd, Birkenhead, Auckland 0626, New Zealand
Proletarska ulica 3/25, Kidričevo, Slovenia (An address might not have the Street Number first).
It will also not do any work if there is no street number, and the value will be the same if there is no unit number.
A slight modification from #MountainAsh's code:
if (addressType == 'route') {
var regex = RegExp('^(.*?)'+GPLACESSTREET.split(' ',1)[0]), // get all the user entered values before a match with the first word from the Google result
result = regex.exec(INPUTFEILD.value);
if ( Array.isArray(result) ) {
FULLSTREETADDRESS = result[1]+''+GPLACESSTREET; // add the street name to the user-entered unit & street number
}
}
Notice the additional ? in RegExp, which makes the search non-greedy to cover cases where the Street Name starts with the same Suburb name (e.g. 123 Clayton Rd, Clayton).

Pathfinding issues

Ok I am trying to make a dynamic pathing system so the player can move from point A to point B without having predefined paths. Note this game is all text based no graphics. The player can move in 10 directions: up, down, n, e, s, w, sw, se, nw and ne.
The map of the entire world is in a database, each row of the database contains a room or a node, each room/node has directions it's capable of going. The room may not be sequential persay. An Example:
Map Number, Room Number, Direction_N, Direction_S, Direction_E, Direction_W, etc.
1 1 1/3 1/100 1/1381 1/101
The Direction_N indicates it goes to Map 1 Room 3, Direction_S Map 1 Room 100, etc...
Ok, I reworked the code with suggestions (thank you guys by the way!) here is revised code. It seems to find the rooms now, even vast distances! But now the issue is finding the shortest path to the destination, I tried traversing the collection but the path is not coming out right...
In the image link below, I have start point in red square in center and stop point at red square at upper left. This returns visitedStartRooms = 103 and visitedStopRooms = 86, when it's only about 16 rooms.
Quess my missing piece of the puzzle is I am not sure how to sort out the rooms in those collection to gain the true shortest route.
Example of map
Here is the new code
public void findRoute(ROOM_INFO startRoom, ROOM_INFO destinationRoom)
{
Dictionary<ROOM_INFO, bool> visitedStartRooms = new Dictionary<ROOM_INFO, bool>();
Dictionary<ROOM_INFO, bool> visitedStopRooms = new Dictionary<ROOM_INFO, bool>();
List<string> directions = new List<string>();
startQueue.Enqueue(startRoom); // Queue up the initial room
destinationQueue.Enqueue(destinationRoom);
visitedStartRooms.Add(startRoom, true);// say we have been there, done that
visitedStopRooms.Add(destinationRoom, true);
string direction = "";
bool foundRoom = false;
while (startQueue.Count != 0 || destinationQueue.Count != 0)
{
ROOM_INFO currentStartRoom = startQueue.Dequeue(); // remove room from queue to check out.
ROOM_INFO currentDestinationRoom = destinationQueue.Dequeue();
ROOM_INFO startNextRoom = new ROOM_INFO();
ROOM_INFO stopNextRoom = new ROOM_INFO();
if (currentStartRoom.Equals(destinationRoom))
{
break;
}
else
{
// Start from destination and work to Start Point.
foreach (string exit in currentDestinationRoom.exitData)
{
stopNextRoom = extractMapRoom(exit); // get adjacent room
if (stopNextRoom.Equals(startRoom))
{
visitedStopRooms.Add(stopNextRoom, true);
foundRoom = true;
break;
}
if (stopNextRoom.mapNumber != 0 && stopNextRoom.roomNumber != 0)
{
if (!visitedStopRooms.ContainsKey(stopNextRoom))
{
if (visitedStartRooms.ContainsKey(stopNextRoom))
{
foundRoom = true;
}
else
{
destinationQueue.Enqueue(stopNextRoom);
visitedStopRooms.Add(stopNextRoom, true);
}
}
}
}
if (foundRoom)
{
break;
}
}
// start from the start and work way to destination point
foreach (string exit in currentStartRoom.exitData)
{
startNextRoom = extractMapRoom(exit); // get adjacent room
if (startNextRoom.Equals(destinationRoom))
{
visitedStartRooms.Add(startNextRoom, true);
foundRoom = true;
break;
}
if (startNextRoom.mapNumber != 0 && startNextRoom.roomNumber != 0)
{
if (!visitedStartRooms.ContainsKey(startNextRoom))
{
if (visitedStopRooms.ContainsKey(startNextRoom))
{
foundRoom = true;
break;
}
else
{
startQueue.Enqueue(startNextRoom);
visitedStartRooms.Add(startNextRoom, true);
}
}
}
}
if (foundRoom)
{
break;
}
}
}
You have a good start. There are a few basic improvements that will help. First, to be able to reconstruct your path, you should create a new data structure to store visited rooms. But for each entry, you want to store the room, plus the previous room in the path back to the starting point. A good data structure for this would be a dictionary where the key is the room identifier, and the value is the previous room identifier. To know if you've visited a room, you look to see if it exists in that data structure, not your openList queue. With this new structure, you can properly check if you've visited a room, and you can reconstruct the path back by repeatedly looking up the previous room in the same structure until you get to the origination.
The second improvement will increase the performance quite a bit. Instead of just doing a breadth-first search from the start point until you bump into the destination, as you currently do, instead create matching data structures like you have for the start room search, but have them be for the destination room. After you've looked one room away from the start, look one room away from the destination. Repeat this...two rooms away from start, then two rooms away from destination.. etc., working your way out, until you discover a room that has been visited by both your search from start and your search from destination. Build the path from this room back to the start, and back to the destination, and that will be your shortest path.
The problem you are trying to solve is the shortest path problem with unweighted edges or where the weights of all edges are equal. The weight of an edge is the time/cost to move from one room to another. If the cost to move from one room to another varies depending on which pair of rooms you're talking about, then the problem is more complicated, and the algorithm you started with and for which I've suggested modifications, will not work as it is. Here are some links about it:
Shortest path (fewest nodes) for unweighted graph
http://en.wikipedia.org/wiki/Shortest_path_problem
You may also be interested in the A* algorithm which uses a different approach. It uses a hueristic approach to concentrate the search in a subset of the solution space more likely to contain the shortest path. http://en.wikipedia.org/wiki/A%2a_search_algorithm
But A* is probably overkill in your case since the weight of all edges is the same between all rooms.

Resources