Sum of max values inside a repeat

546
4
Jump to solution
10-11-2021 01:38 PM
newwollyka
New Contributor III

I have a form that has a question asking about the total number of  upper floors and lower floors in a building. So If a building has 4 floors and 2 underground floors then the enumerator should enter 4 in the upper floor question and 2 in the lower floor question.

Then the enumerator should list the units/households in each floor. So for each unit, I created a repeat. Inside each repeat, the enumerator should put the floor number of the unit that he is interviewing. So for unit number 1, the floor could be 1, the unit number 5, the floor could be 2 etc.. However, it is possible that the unit exist in a floor that is underground, so for unit number 6, the floor is -1.

I want to put a constraint that compares the sum of the upper and lower floors (4+2 = 6 in the above example) and the sum of the max of the floors that the enumerator entered in the repeat. So in the above example, if the enumerator entered the info for units in floor 2 and floor -1, then we should add 2 + 1 = 3 and compare 3 to 6. Since they are different then a message should appear that the enumerator didn't visit all the floors.

How can I do that?

Thanks

Edit: I added a screenshot of the form

0 Kudos
2 Solutions

Accepted Solutions
DeonLengton
Esri Contributor

Hi

I accepted your challenge (in part) and came up with one possible solution:

Hopefully your survey is not a public survey, then you can use JavaScript to achieve your requirement:

DeonLengton_0-1634115018408.png

I'm not sure if you will have a floor zero but in any case, your solution could be similar.

Basically I made a list of all the floors visited and passed it to a JavaScript function to remove duplicates, sort the floors entered, and comma separate the list:

pulldata("@javascript", "functions.js", "CapturedFloors", ${floor_number})

Where floor_number is the floor entered into your repeat...

function CapturedFloors (floors)

{

var uniq_floors = [...new Set(floors)];

var sort_floors = uniq_floors.sort();

return sort_floors.join(",");

}

Next I used the floor numbers indicated to create a similar comma separated floor list:

pulldata("@javascript", "functions.js", "FloorList", ${floor_lower}, ${floor_upper})

function CapturedFloors (floors)

{

var uniq_floors = [...new Set(floors)];

var sort_floors = uniq_floors.sort();

return sort_floors.join(",");

}

I would then compare the two lists with each other and they should be similar when a fieldworker has visited all the floors of the building:

DeonLengton_1-1634115300838.png

 

I hope this helps!

 

View solution in original post

DeonLengton
Esri Contributor

EDIT: I enhance our code 🙂

function MissingFloorList(lower,upper,floors)
{
let arr = [];
for (let i = lower; i <= upper; i++) {
arr.push(i);
}

var all_uniq_floors = [...new Set(arr)];
var visited_floors = [...new Set(floors)];
return all_uniq_floors.filter(x => visited_floors.indexOf(x) === -1);
}

Now you can just call one function to retrieve the missing floors and show them in red:

pulldata("@javascript", "functions.js", "MissingFloorList", ${floor_lower}, ${floor_upper},${floor_number})

Show it in a note field with HTML formatting:

<div style="text-align:center; font-size:large; font-weight: bold; color:red"; >Missing floors: ${missingfloors}</div>

DeonLengton_0-1634191403019.png

 

 

View solution in original post

4 Replies
DeonLengton
Esri Contributor

Hi

I accepted your challenge (in part) and came up with one possible solution:

Hopefully your survey is not a public survey, then you can use JavaScript to achieve your requirement:

DeonLengton_0-1634115018408.png

I'm not sure if you will have a floor zero but in any case, your solution could be similar.

Basically I made a list of all the floors visited and passed it to a JavaScript function to remove duplicates, sort the floors entered, and comma separate the list:

pulldata("@javascript", "functions.js", "CapturedFloors", ${floor_number})

Where floor_number is the floor entered into your repeat...

function CapturedFloors (floors)

{

var uniq_floors = [...new Set(floors)];

var sort_floors = uniq_floors.sort();

return sort_floors.join(",");

}

Next I used the floor numbers indicated to create a similar comma separated floor list:

pulldata("@javascript", "functions.js", "FloorList", ${floor_lower}, ${floor_upper})

function CapturedFloors (floors)

{

var uniq_floors = [...new Set(floors)];

var sort_floors = uniq_floors.sort();

return sort_floors.join(",");

}

I would then compare the two lists with each other and they should be similar when a fieldworker has visited all the floors of the building:

DeonLengton_1-1634115300838.png

 

I hope this helps!

 

newwollyka
New Contributor III

Great Solution.. Thanks for that.

I think the second function should named FloorList (floors) and its definition should be different.

I guess something like the below

function FloorList(lower,upper)

{

let arr = [];

for (let i = lower; i <= upper; i++) {

arr.push(i);

}

var uniq_floors = [...new Set(arr)];

return uniq_floors.join(",");

}

0 Kudos
newwollyka
New Contributor III

Btw, Is there a way to highlight or put in a note just the missing floors?

EDIT: I enhance your codeimage.png

/*
* JavaScript functions for Survey123
*/

function CapturedFloors (floors)

{

var uniq_floors = [...new Set(floors)];

var sort_floors = uniq_floors.sort();

return sort_floors.join(",");

}

function FloorList(lower,upper)
{
let arr = [];
for (let i = lower; i <= upper; i++) {
arr.push(i);
}

var uniq_floors = [...new Set(arr)];

return uniq_floors.join(",");
}

function GetMissingFloors (visitedFloors,lower, upper)
{
let arr = [];

if(!Array.isArray(visitedFloors)){
return; }

for (let i = lower; i <= upper; i++) {
arr.push(i);
}

let completeFloors = [...new Set(arr)];

let missingFloors = completeFloors.filter(e => !visitedFloors.includes(e))

return missingFloors.join(", ");
}

0 Kudos
DeonLengton
Esri Contributor

EDIT: I enhance our code 🙂

function MissingFloorList(lower,upper,floors)
{
let arr = [];
for (let i = lower; i <= upper; i++) {
arr.push(i);
}

var all_uniq_floors = [...new Set(arr)];
var visited_floors = [...new Set(floors)];
return all_uniq_floors.filter(x => visited_floors.indexOf(x) === -1);
}

Now you can just call one function to retrieve the missing floors and show them in red:

pulldata("@javascript", "functions.js", "MissingFloorList", ${floor_lower}, ${floor_upper},${floor_number})

Show it in a note field with HTML formatting:

<div style="text-align:center; font-size:large; font-weight: bold; color:red"; >Missing floors: ${missingfloors}</div>

DeonLengton_0-1634191403019.png