Parse JS multiple relation query - javascript

I have 3 classes (Survey, SurveyItem, VoteSurvey)
SurveyItem contain pointer to Survey
VoteSurvey contain pointer to Survey and pointer to SurveyItem
i need to include all the surveys that i haven't voted for.
//survey
var surveyQuery = new Parse.Query(Survey);
surveyQuery.equalTo("condo",pointerCondo); //essential column filter
//surveyitem
var surveyItemQuery = new Parse.Query(SurveyItem);
surveyItemQuery.matchesQuery("survey",surveyQuery);
//all survey with filter & surveyitems (return ok)
var voteQuery = new Parse.Query(VoteSurvey);
//...
can anyone help me?

It's not entirely clear what your class structure and fields are, so their might be a better way to do this. But, how about querying for all the surveys you have voted for and then finding all surveys that don't match? For example:
var voteQuery = new Parse.Query('VoteSurvey');
voteQuery.equalTo('user', user);
voteQuery.find().then(function(results) {
var alreadyVotedSurveyIds = [];
for (var i=0; i<results.length; i++) {
alreadyVotedSurveyIds.push(results[i].get('survey').id);
}
var surveyQuery = new Parse.Query('Survey');
surveyQuery.notContainedIn('objectId', alreadyVotedSurveyIds);
return surveyQuery.find();
}).then(function(notVotedSurveys) {
// notVotedSurveys is the array of surveys not voted for
});
Note: keep in mind that Parse query has a default limit of 100.

Related

Creating a google form/quiz from a google spreadsheet

I am trying to create a multiple choice question form to be created from data in a google spreadsheet. I managed to create the form of 60 questions each with 4 choices and setting the correct choice based on the information I have in the spreadsheet.
Last thing I need to do is to insert the correct feedback for each question based on column G in my spreadsheet that contains the feedback for each question.
Edit: here is a picture of how my spreadsheet & form would look like
Picture for Spreadsheet
Picture for how the form questions should look like
Picture of how the form questions look like (without a feedback)
The problem is that is not being implemented, The maximum I could was to set a fixed feedback/word for all questions, but was not possible to import the specific feedback for each question to the feedback section of each question, could anyone help with that, below is my code:
function popForm() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Sheet1');
var numberRows = sheet.getDataRange().getNumRows();
var myQuestions = sheet.getRange(1,1,numberRows,1).getValues();
var myAnswers = sheet.getRange(1,2,numberRows,1).getValues();
var myGuesses = sheet.getRange(1,2,numberRows,4).getValues();
var myfeedback = sheet.getRange(1,7,numberRows,1).getValues();
var myShuffled = myGuesses.map(shuffleEachRow);
Logger.log(myShuffled);
Logger.log(myAnswers);
// Create the form as a quiz. The resulting form's "Quiz options" are different from a manually created quiz. Be aware (and change manually if needed!
var form = FormApp.create('Fast Track Question - Domain I');
form.setIsQuiz(true);
// Write out each multiple choice question to the form.
for(var i=0;i<numberRows;i++){
if (myShuffled[i][0] == myAnswers[i][0]) {
var addItem = form.addMultipleChoiceItem();
addItem.setTitle(myQuestions[i][0])
.setPoints(1)
.setChoices([
addItem.createChoice(myShuffled[i][0],true),
addItem.createChoice(myShuffled[i][1]),
addItem.createChoice(myShuffled[i][2]),
addItem.createChoice(myShuffled[i][3])
]);
var incorrectFeedback = FormApp.createFeedback()
.setText(myfeedback[i][7])
.build();
addItem.setFeedbackForIncorrect(incorrectFeedback);
}
else if (myShuffled[i][1] == myAnswers[i][0]) {
var addItem = form.addMultipleChoiceItem();
addItem.setTitle(myQuestions[i][0])
.setPoints(1)
.setChoices([
addItem.createChoice(myShuffled[i][0]),
addItem.createChoice(myShuffled[i][1],true),
addItem.createChoice(myShuffled[i][2]),
addItem.createChoice(myShuffled[i][3])
]);
var incorrectFeedback = FormApp.createFeedback()
.setText(myfeedback[i][7])
.build();
addItem.setFeedbackForIncorrect(incorrectFeedback);
}
else if (myShuffled[i][2] == myAnswers[i][0]) {
var addItem = form.addMultipleChoiceItem();
addItem.setTitle(myQuestions[i][0])
.setPoints(1)
.setChoices([
addItem.createChoice(myShuffled[i][0]),
addItem.createChoice(myShuffled[i][1]),
addItem.createChoice(myShuffled[i][2],true),
addItem.createChoice(myShuffled[i][3])
]);
var incorrectFeedback = FormApp.createFeedback()
.setText(myfeedback[i][7])
.build();
addItem.setFeedbackForIncorrect(incorrectFeedback);
}
else if (myShuffled[i][3] == myAnswers[i][0]) {
var addItem = form.addMultipleChoiceItem();
addItem.setTitle(myQuestions[i][0])
.setPoints(1)
.setChoices([
addItem.createChoice(myShuffled[i][0]),
addItem.createChoice(myShuffled[i][1]),
addItem.createChoice(myShuffled[i][2]),
addItem.createChoice(myShuffled[i][3],true)
]);
var incorrectFeedback = FormApp.createFeedback()
.setText(myfeedback[i][7])
.build();
addItem.setFeedbackForIncorrect(incorrectFeedback);
}
}
}
// This function, called by popForm, shuffles the 5 choices.
function shuffleEachRow(array) {
var i, j, temp;
for (i = array.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
Proposed change to script
Your code was long and I found it easier to re-write it with a few extra tools such as getDataRange, push and splice and forEach.
It seemed you were calling the methods in the right way, but since you were having to repeat yourself in a few places and keep track of many arrays and indices, it is likely that a small mistake came up.
This is a working script adapted from yours:
function createQuiz() {
let file = SpreadsheetApp.getActive();
let sheet = file.getSheetByName("Sheet1");
// Instead of getting individual ranges, it is more efficient
// to get all the data in one go, and then operate on the two
// dimensional array in memory.
let range = sheet.getDataRange();
let values = range.getValues();
// Here I am using a existing form to test, but you can just
// create a new one if you want.
var form = FormApp.openById("[TESTING_ID]");
form.setIsQuiz(true);
values.shift(); // Using this to remove the first row of headers
// Going through each line using a forEach to create a
// multiple choice question
values.forEach(q => {
let choices = [q[1], q[2], q[3], q[4]];
let title = q[0];
let feedback = q[5]
// Calling function to create multiple choice question
createShuffledChoices(form, title, choices, feedback)
});
}
function createShuffledChoices(form, title, choices, feedback){
let item = form.addMultipleChoiceItem();
item.setTitle(title)
.setPoints(1)
// Setting up the array that will be passed into item.setChoices()
let shuffledChoices = [];
// Making sure that the correct answer is only marked once
let correctAnswerChosen = false;
// I found I had to shuffle the questions within the process of
// creating choices as it made it easier to maintain the spreadsheet
for (let i = choices.length; i != 0; i--) {
let rand = Math.floor(Math.random() * (i - 1));
// If the first answer is chosen, it is the correct one.
if (rand == 0 && correctAnswerChosen == false) {
// Combination of push and splice to remove from ordered array
// to the shuffled one
shuffledChoices.push(item.createChoice(choices.splice(rand, 1)[0], true));
// Marking the correct answer as chosen,
// so that no others are marked correct.
correctAnswerChosen = true;
} else {
shuffledChoices.push(item.createChoice(choices.splice(rand, 1)[0]));
}
}
// Finally setting the choices.
item.setChoices(shuffledChoices);
// Creating the feedback
let formFeedback = FormApp.createFeedback().setText(feedback).build();
item.setFeedbackForIncorrect(formFeedback);
}
The way that you were creating feedback was correct, I suspect that you were just getting mixed up with your arrays and indexes. This is why I tried to simplify your code and eliminate repeated sections.
I combined the shuffling process with the creation of the multiple choice question. This is because the shuffled array that is passed into item.setChoices has to be built of item.createChoice objects. This can't be done in another scope because item is not available.
Combining the logic for shuffling this way means that you don't need to have the letter prefixes in your questions A). You also don't need the column that has the correct answer, because the process knows that the first answer is the correct one. So your sheet can be simplified to this:
For this script to work, the data needs to be organized in this way. (Though you can adapt it anyway you like of course)
References
getDataRange
push
splice
shift
forEach

How to automatically add questions in a Google Form based on columns on Google Sheets? [duplicate]

I'm new with Google scripts and now I have to make a form with a list of choices. These choices should be picked up from the Google sheet.
So the first question is how to chose only unique values from some range of my spreadsheet?
The second is how to pass this list so that they will be the items in the list?
The code I've tried is:
function getMembranesList() {
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/......");
var itemList = ss.getSheetByName('Answers').getRange("Q1:Q").getValues();
var form = FormApp.getActiveForm();
var item = form.addListItem()
item.setTitle('test question');
item.createChoice(itemList);
}
Looking at the methods available to populate the ListItem, you have to choose one and set your data up so it matches the expected input. For my example, I chose the setChoiceValues method, which looks for an array. So I have to manipulate the items into an array.
One thing the getRange.getValues() method does NOT get you is how many non-blank items are returned in the list. I used this quick way to get a count of those items, so I have a maximum bound for my loops. Then, I formed the itemArray and added only the non-blank items to it.
After that, it's just a matter of creating the ListItem and adding the values:
function getMembranesList() {
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/...");
var itemList = ss.getSheetByName('Answers').getRange("Q1:Q").getValues();
var itemCount = itemList.filter(String).length;
var itemArray = [];
for (var i = 0; i < itemCount; i++) {
itemArray[i] = itemList[i];
}
var form = FormApp.getActiveForm();
var item = form.addListItem();
item.setTitle('test question');
item.setChoiceValues(itemArray);
}

Firebase checking if child exists, pull and update data if exists javascript

I am trying to count the number of times a certain key word (city) is searched. I have stored the data so for each new input I want to see if the child exists and if so pull the numSearched child and add 1. I can see if it exists but I can add on.
My database is a simple
file:///Users/paulamactavish/Downloads/practicaltravel-63ff1-export.json
var cityToCheck = city;
var cityRef = firebase.database().ref('travelPlans');
cityRef.once('child_added', function(snapshot) {
snapshot.forEach(function(child) {
if (snapshot.val().city==cityToCheck) {
var myJSON = JSON.stringify(snapshot);
var citySearch = JSON.parse(myJSON)
numSearchCounter = (citySearch.numSearched);
numSearchCounter++
child.ref().update({
numSearched = numSearchCounter
});
};
});
});
I have looked over lots of other responses but I cant seem to make it work as a whole. Thanks in advance!

How do you get a count of listitems of a certain content type without fetching all items

So we had a piece of code that set a few elements to display the count of all items in various lists.
Now a requirement has been added that only items of a certain content type can be counted. However, Including a caml query as seen below (The old code has been commented out) has made it far to slow for actual use. (obviously, its fetching thousands of items just to get a count).
Is there a way to count all items of a contenttype in a sharepoint list using javascript that doesn't request all items of every list?
function setCounter() {
context = new SP.ClientContext.get_current();
web = this.context.get_web();
this.lists = web.get_lists();
context.load(this.lists);
context.executeQueryAsync(
Function.createDelegate(this, function () {
var listsEnumerator = this.lists.getEnumerator();
while (listsEnumerator.moveNext()) {
var currentItem = listsEnumerator.get_current();
for (var i = 0; i < leng; i++) {
if (leng == 1) ele = listItemCount;
else ele = listItemCount[i];
if (decoded == currentItem.get_title()) {
ele.parentNode.setAttribute("class", "overview_discussions");
// var counter = currentItem.getItems();
// ele.innerText = currentItem.get_itemCount();
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml("<Where><BeginsWith><FieldRef Name='ContentTypeName'/><Value Type='Text'>Discussion</Value></BeginsWith></Where>");
var counter = currentItem.getItems(camlQuery);
context.load(counter);
context.executeQueryAsync(function () { ele.innerText = counter.get_count(); }, executeOnFailure);
break;
}
}
}
}),
Function.createDelegate(this, executeOnFailure));
}
Nope, but what you can do is minimize the data pulling by setting viewfields. Now is like you are doing a select * when you only need select id
var caml = "<View><ViewFields><FieldRef Name='Id'/></ViewFields></View><Query>your query here</Query>";
After executing the query you just need to cal get_count() as you already do
If you are familiar with jQuery, I suggest you taking a look a this library, is very easy to use and helps you improve your work with object client model. http://spservices.codeplex.com/

Dynamically construct array based on user input - Javascript/jQuery

I have a list of US regions set up as checkboxes. When a user submits the form, I need an array of associated states. This array is used for comparing to another array in my SQL tables.
Using jQuery or javascript, what's the best way to go about this?
I've got the general idea I believe:
//populate region to state arrays here
$("input[name='region']").each(function () {
if ($(this).is(':checked')) {
// ADD TO SUPER ARRAY OF ALL REGIONS
// (this is where I need help)
}
});
Thanks in advance!!
PS. I tried using the input values var regionValue = $(this).attr('value') to identify each array, but I'm having issues with dynamically named arrays since all my functions are in static classes.
Edited to reflect the new information and incorporating GenericTypeTea's comment:
Assuming the ID of each checkbox is set to the region name, how about:
var regionStates = {};
regionStates['northeast'] = ['AB', 'CD', 'EF'];
regionStates['mountains'] = ['GH', 'IJ', 'KL'];
// etc...
var selectedStates = [];
$("input[name='region']:checked").each(function () {
var region = regionStates[this.id];
for (var i = 0; i < region.length; ++i) {
selectedStates[selectedStates.length] = region[i];
}
});
Using this, selectedStates will contain all the states of all regions that are selected.
Apologies for not knowing any real US state abbreviations.

Categories