A way to tick off which features / waypoints have been recorded?

202
7
Jump to solution
01-08-2020 08:47 AM
DataOfficer
Occasional Contributor III

Hi,
Relatively new Survey123 user here. I'm working on a species recording form for a wildlife monitoring programme. The surveyor selects a survey site from a multiple choice list, for which there are associated survey waypoints. When the user selects the site, a choice filter restricts the survey waypoints to those present in that site (e.g. Site 1 contains waypoints 1-20). During the survey, the surveyor should visit every waypoint, and record if any species were found at it or not. At the end of the survey, I want to include a note that warns them they have not recorded species presence/absence at every available waypoint for that site if they have not done so. This will be dependent on whether all waypoints have been selected during the form, using a relevant function that must compare the number of waypoints surveyed to the number available at that site. Is there a way I can get the Survey123 form to:

  1. Keep track of which of the waypoint choices at the selected site have or have not been selected?
  2. Count the number (e.g. 18 out of 20 choices) of waypoints that have been selected?

I have considered I could use an if statement combined followed by a count function to log when each waypoint is selected throughout the form repeats, but for this monitoring scheme there could eventually be 100's of sites, with 1000's of waypoints which makes this unsuitable (I may instead store these in an external_select, rather than storing these in the choice tab of the XLSForm). The other part of this potential workaround would be to use pulldata to identify the number of waypoints associated with a site, but I don't know how I would pull off the if statement issue with such a large number of waypoint options.

Any suggestions?

Thanks in advance.

Rob

#Survey123

Reply
0 Kudos
1 Solution

Accepted Solutions
DataOfficer
Occasional Contributor III

So after some testing and discussions with an ESRI consultant, we came up with a solution. Sharing here in case anyone else has the same issue.

General background:

  1. The waypoints (artificial refugia for reptiles in this case) for each site are stored in an external select (external_choices tab of the form), with a SiteName column specifying which waypoints belong to which sites. This enables a choice_filter to be implemented based on the site selected.
  2. A separate external csv (in the media folder) stores sites and waypoints in wide format (column 1 = SiteName, column 2 = Waypoint 1 name, column 3 = Waypoint 2 name ..... column n = Waypoint n-1 name) - up to the maximum number of waypoints a site may have (e.g. 100).

Process:

  1. The user selects the site (or autopopulated from Explorer / Collector using a URL to load the form)
  2. Within a repeat:
    1. The user selects a waypoint from a select_one dropdown list, with a choice_filter controlling the list based on the site selection.
    2. A waypoint label calculate field uses the jr:choice-name calculation to store the label of that waypoint.
      name: Waypoint_label
      calculation: jr:choice-name(${Waypoints},'${Waypoints}')
  3. Outside of the repeat:
    1. A text field uses a join calculation to join the label of each waypoint surveyed so far.
      name: Waypoints_checked
      calculation: join(",",${Waypoint_label}
      This text field shows which waypoints have been checked so far.
    2. We created hidden rows up to the maximum number of waypoints at a site (e.g. 100 rows), each with a relevant function and a pulldata calculation to the external csv for each waypoint column (e.g. row 1 of 100 pulls the label of waypoint 1).
      relevant: not(contains(${Waypoint_checked}, pulldata('Waypoints','Waypoint1','SiteName',${SiteName})))
      calculation: pulldata('Waypoints','Waypoint1','SiteName',${SiteName})
    3.  For aesthetic reasons, a second set of hidden rows were created up to the maximum number of waypoints (e.g. 100 rows), which is relevant based on the string-length of the corresponding pulldata row above being >0. The calculation field then concatenates the waypoint name with a space. E.g.
      name: Waypoint_1
      relevant: string-length(${Waypoint1})>0
      calculation: concat(${Waypoint1}," ")
      This then allows concatenation below without additional commas appearing if a site did not have the maximum number of waypoints, compared to if we just concatenated the outputs from the pulldata calculation (step 3.2).
    4. Another row is used to concatenate all of the rows that were concatenated in step 3.3

      name: WaypointsNotChecked

      calculation: concat(${Waypoint_1},${Waypoint_2},${Waypoint_3},${Waypoint_4},

      1. The output of step 3.4 is then presented as a note:

        <center><b>Warning!</b> The following waypoints for ${Site_label} have not been checked: <b></center>

        <center><b><font color="red">${WaypointsNotChecked}</font></b></center>

        <center>If these are missing, please add records for these waypoints and select <i>missing</i> from <i>status</i>. <b>Only proceed if you are finished</b></center>

         The warning notes are dependent on a relevant calculation which hides them if the string length of WaypointsNotChecked is 0. 

So in summary, the user gets two outputs at the end of the survey form: a list of waypoints checked so far (Waypoints_checked), and a warning showing the waypoints which have not been checked.

Thanks Doug Browning and others for their input.

View solution in original post

Reply
0 Kudos
7 Replies
DougBrowning
MVP Frequent Contributor

Have you tried setting repeat count to 20.  Then make something required on each repeat.  They they must fill out all 20 to submit.

Reply
0 Kudos
DataOfficer
Occasional Contributor III

Unfortunately the number of waypoints is different per site so this approach wouldn't work. Furthermore the number and location of waypoints will vary over time as they are added or removed. Thanks for the suggestion though.

Get Outlook for Android<https://aka.ms/ghei36>

Reply
0 Kudos
DougBrowning
MVP Frequent Contributor

You can put a formula in repeat count.

As you said a pulldata would work.

What we do is have the Plots on Collector with a Point count.  Send that point count over to 123 via a URL into the repeat count field.  Form auto adjusts based on this.

I do this to adjust all kinds of things on the form Plot by plot.

DataOfficer
Occasional Contributor III

Thanks for the useful suggestions Doug Browning‌. I'll see if I can work out a way to make this work. One issue we have is that records are not just made at the waypoints, so the number of repeats needed would often exceed the number of waypoints, or a subset of waypoint repeats combined with non-waypoint repeats may trick the form in to thinking it has reached the allocated number of waypoints. It may be worth mentioning that this is for a reptile survey, so the waypoints will be artificial refugia / cover boards, but other records may be collected along the survey route. Furthermore as this is for a citizen science project, we are trying to reduce the need for volunteers to have to use Collector, instead using Explorer and Survey123 in the field, or just Survey123 on the desktop when they are back from the field if preferred by the user. 

Reply
0 Kudos
DougBrowning
MVP Frequent Contributor

Hmm.  Ok a few more ideas.  

Do a join() then contains(joinfield, '').  This will tell you if any blanks.  I thought about coalesce but that is just 2 values.  

I wonder if count(repeat) counts blanks or not.  Not sure.

But rereading your post you just want to count way points.  On each repeat can you have something like 

if(waypoint,1,0).  Then use count() on that field (outside the repeat) and compare it to the way point number you want.

Hope I am understanding it right.

DataOfficer
Occasional Contributor III

Hmm that could work. I'll do some testing. Thanks for the suggestions.

Reply
0 Kudos
DataOfficer
Occasional Contributor III

So after some testing and discussions with an ESRI consultant, we came up with a solution. Sharing here in case anyone else has the same issue.

General background:

  1. The waypoints (artificial refugia for reptiles in this case) for each site are stored in an external select (external_choices tab of the form), with a SiteName column specifying which waypoints belong to which sites. This enables a choice_filter to be implemented based on the site selected.
  2. A separate external csv (in the media folder) stores sites and waypoints in wide format (column 1 = SiteName, column 2 = Waypoint 1 name, column 3 = Waypoint 2 name ..... column n = Waypoint n-1 name) - up to the maximum number of waypoints a site may have (e.g. 100).

Process:

  1. The user selects the site (or autopopulated from Explorer / Collector using a URL to load the form)
  2. Within a repeat:
    1. The user selects a waypoint from a select_one dropdown list, with a choice_filter controlling the list based on the site selection.
    2. A waypoint label calculate field uses the jr:choice-name calculation to store the label of that waypoint.
      name: Waypoint_label
      calculation: jr:choice-name(${Waypoints},'${Waypoints}')
  3. Outside of the repeat:
    1. A text field uses a join calculation to join the label of each waypoint surveyed so far.
      name: Waypoints_checked
      calculation: join(",",${Waypoint_label}
      This text field shows which waypoints have been checked so far.
    2. We created hidden rows up to the maximum number of waypoints at a site (e.g. 100 rows), each with a relevant function and a pulldata calculation to the external csv for each waypoint column (e.g. row 1 of 100 pulls the label of waypoint 1).
      relevant: not(contains(${Waypoint_checked}, pulldata('Waypoints','Waypoint1','SiteName',${SiteName})))
      calculation: pulldata('Waypoints','Waypoint1','SiteName',${SiteName})
    3.  For aesthetic reasons, a second set of hidden rows were created up to the maximum number of waypoints (e.g. 100 rows), which is relevant based on the string-length of the corresponding pulldata row above being >0. The calculation field then concatenates the waypoint name with a space. E.g.
      name: Waypoint_1
      relevant: string-length(${Waypoint1})>0
      calculation: concat(${Waypoint1}," ")
      This then allows concatenation below without additional commas appearing if a site did not have the maximum number of waypoints, compared to if we just concatenated the outputs from the pulldata calculation (step 3.2).
    4. Another row is used to concatenate all of the rows that were concatenated in step 3.3

      name: WaypointsNotChecked

      calculation: concat(${Waypoint_1},${Waypoint_2},${Waypoint_3},${Waypoint_4},

      1. The output of step 3.4 is then presented as a note:

        <center><b>Warning!</b> The following waypoints for ${Site_label} have not been checked: <b></center>

        <center><b><font color="red">${WaypointsNotChecked}</font></b></center>

        <center>If these are missing, please add records for these waypoints and select <i>missing</i> from <i>status</i>. <b>Only proceed if you are finished</b></center>

         The warning notes are dependent on a relevant calculation which hides them if the string length of WaypointsNotChecked is 0. 

So in summary, the user gets two outputs at the end of the survey form: a list of waypoints checked so far (Waypoints_checked), and a warning showing the waypoints which have not been checked.

Thanks Doug Browning and others for their input.

View solution in original post

Reply
0 Kudos