<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/hw-checker-r-appscripts-google-forms/"></div></div><div><a data-url="https://www.r-bloggers.com/hw-checker-r-appscripts-google-forms/" data-counturl="https://www.r-bloggers.com/hw-checker-r-appscripts-google-forms/" data-count="horizontal" data-text="HW Checker: R, AppScripts, &amp; Google Forms" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://data-steve.github.io/build-homework-checker-pt1/"> data_steve</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p><img alt="" src="https://i0.wp.com/data-steve.github.io/images/appscripts_r.png?w=456" data-recalc-dims="1"></p>
<p><a data-style="mega" target="_blank" href="https://github.com/data-steve/googleformr" data-icon="octicon-star">googleformr</a></p>
<p>For the past few months I’ve been toying with the idea of using googleformr to empower data science-oriented instructors to use data science in their workflow. In this 2-part series of posts, I’ll show how to AppScripts and R to turn Google Forms into a homework checker.</p>
<p>I was encouraged along this path by <a target="_blank" href="https://twitter.com/mhawksey">Martin Hawksey’s</a> post <a target="_blank" href="https://mashe.hawksey.info/2012/01/tags-r/">on AppScripts and R</a> as well as by his direct help in considering some email triggering options with AppScripts.</p>
<div>
<img src="https://i2.wp.com/data-steve.github.io/images/hwchecker_form.png?w=300" data-recalc-dims="1">
</div>
<h2>Toy example</h2>
<p>The most basic example I thought worth sharing was an app that had the following:</p>
<ul>
<li>some security (in the form of a password),</li>
<li>an email to direct feedback to and to confirm student identity, and</li>
<li>a place to push homework submissions to.</li>
</ul>
<p>With these 3 inputs you can pretty much insure that only your students can use this form, so that keeps out spam and the such.</p>
<h4>Password</h4>
<p>Google Forms provides some rather nifty data validation tools that are specific to each data type. I used short answer for my password data type, and I leverage the data validation as password validation. In the toy example below, I just used <code>aaa</code> as the required password. You can add these elements to a form item by clicking on the triple dot settings option at bottom right of item space.</p>
<p><img alt="" src="https://i0.wp.com/data-steve.github.io/images/hwchecker_pwd_regex.png?w=456" data-recalc-dims="1"></p>
<p>While this password validation will work if you are directly inputing answers by hand into the web form directly, it won’t work with googleformr because googleformr bypasses the form elements and posts directly to the input node in the form. Still it is going to be helpful in keeping out people who aren’t your students, austensibly the only ones with the password. But to be extra careful, you may want to create your own homework function that has password validation directly, as seen below.</p>
<div>
<pre><code>homework_submit &lt;- function(pwd=NULL, email=NULL, answer){
  try(if(is.null(pwd)) stop(&quot;Please enter a password.&quot;))
  if(pwd!=&quot;aaa&quot;) stop(&quot;That is not the correct password.&quot;)
  ....
}
</code></pre>
</div>
<p>I don’t wrap the password test in <code>try</code> because when it errors it gives the password condition in the error message.</p>
<h4>Email</h4>
<p>I suppose I could have done some fancy email validation in Google Forms, but if I really wanted that, I’d just create a function for submitting homework that gave me more control over email validation at the source. If you’d like to do that, the email validator would look like so:</p>
<div>
<pre><code>is_email &lt;- function(x) {
  grepl(&quot;([_+a-z0-9-]+(\\.[_+a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,14}))&quot;
    , x, ignore.case = TRUE)
}
</code></pre>
</div>
<p>You could also make it have special school email flavors by changing the <code>school</code> suboption to whatever your school email is after <code>@</code> sign.</p>
<div>
<pre><code>is_school_email &lt;- function(x, school=NULL) {
  if (is.null(school)){
    is_email(x)
  } else {
    grepl(paste0(&quot;([_+a-z0-9-]+(\\.[_+a-z0-9-]+)*@&quot;,school,&quot;)&quot;)
            , x, ignore.case = TRUE)
  }
}
</code></pre>
</div>
<p>So the end product could look like this:</p>
<div>
<pre><code>homework_submit &lt;- function(pwd=NULL, email=NULL, answer){
  try(if(is.null(pwd)) stop(&quot;Please use class password.&quot;))
  if(pwd!=&quot;aaa&quot;) stop(&quot;That is not the correct password.&quot;)
  try(if(!is_email(email)) stop(&quot;Please use real email address.&quot;))
  ....
}
</code></pre>
</div>
<p>But the other reason I don’t do this is that I want students to give me a specific email that I can associate with their identity for recordkeeping and grading. This would need to be collected independently from this form.</p>
<p>In the back end of Google Forms, I have an AppScript that handles email identity checking. If the email is one that my student has registered with me, then it proceeds with checking the value of #1 against my tests. If it isn’t, it automatically emails the student, informing her that she’ll need to resubmit the homework and reminding them to use the email address they’ve registered with me.</p>
<p>After you’ve created your form to collect the homework answers you want from your students, you can use <strong>googleformr</strong> to build your function to allow students to programmatically submit their answers directly to your google form. This code chunk below serves as a template.</p>
<div>
<pre><code>library(googleformr)
url &lt;- &quot;your_google_form_url&quot;
</code></pre>
</div>
<p>Using the <code>get_form_str</code> function you can confirm that the structure of the form is the structure of the input entry nodes you get back from googleformr.</p>
<div>
<pre><code>get_form_str(url)

    	Order your post content
	according to the Questions on Form
     entry.qs  entry.ids         
[1,] &quot;pwd *&quot;   &quot;entry.1089329191&quot;
[2,] &quot;Email *&quot; &quot;entry.2028747629&quot;
[3,] &quot;#1 *&quot;    &quot;entry.1639114256&quot;
</code></pre>
</div>
<p>Once you are satisfied, you can create the function hwchecker with <code>googleformr::gformr</code> handling all the linking and function construction. The resulting function will expect a vector of inputs in the same order as <code>get_form_str</code> displayed.</p>
<div>
<pre><code>hwchecker &lt;- gformr(url, custom_reply=&quot;HW being checked!&quot;)
hwchecker(c(&quot;aaa&quot;,&quot;not a real email@some_email_provider.com&quot;,&quot;yes&quot;)) 
</code></pre>
</div>
<p>My last post explored the details of posting multiple answers to a <a target="_blank" href="http://data-steve.github.io/post-multiple-answers-to-google-forms">google form with googleformr</a>. The main thing I re-emphasize here is that functions created with gformr expect a vector of answers as long as and in the same order as the form entries.</p>
<h4>Answer #1</h4>
<p>In this one example, I’ve simply put <code>yes</code> as an answer, the correct answer in this case. However, I’ve shown in <a target="_blank" href="http://data-steve.github.io/post-multiple-answers-to-google-forms">my previous post on googleformr</a> that you can put almost anything into a form item of the data type short answer, including a dataframe. And the chosen form of feedback I offer in this toy example is that if the student posts an answer other than <code>yes</code>, namely <code>no</code>, then they’re told their answer is <code>too low</code> in the spirit of <code>TRUE=1</code> and <code>FALSE=0</code>.</p>
<p>The possibility of feedback is as flexible as the person developing the app is at writing tests. Even though AppScripts is an extension of JavaScript, the loop and conditional logic structures they use are quite familiar to R developers with any experience.</p>
<h4>Make your hwsubmit function</h4>
<p>So now, your custom <code>hwsubmit</code> function has password protection, email validation, and a direct link to your google form. We can even throw in a verification that they didn’t forget to include their answers.</p>
<p>Now to create <code>hwsubmit</code>, simply create all the prereqs above and then change the <code>NULL</code> values on the suboptions <code>pswd</code> and <code>school</code> in the function below to set the password and school-email specific parameters for your needs. It will return a function that has all the parameters set.</p>
<div>
<pre><code>hwsubmit &lt;- function(pswd = NULL,school=NULL){
  try(if(is.null) stop(&quot;Assign the school email suffix.&quot;))
  
  function(pwd=NULL, email=NULL , answer=NULL, school=NULL){
    # error handling
    try(if(is.null(pwd)) stop(&quot;Please use class password.&quot;))
    if(pwd!=pswd) stop(&quot;That is not the correct password.&quot;) 
    if(!is_school_email(email,school)) stop(&quot;Please use school email.&quot;))
    try(if(is.null(answer)) stop(&quot;Don't forget to include your answers.&quot;))
    
    if (!is.null(pwd) &amp; pwd==pswd &amp; 
        is_school_email(email,school) &amp; !is.null(answer)){
      hwchecker(c(pwd, email,answer))
    } else {
      message(&quot;Check your inputs to homework_submit&quot;)
    }
  }
}
</code></pre>
</div>
<p>When this function is saved into a package and distributed to your students, they will be able to submit their homework as easily as</p>
<div>
<pre><code>hwsubmit(pwd    = &quot;aaa&quot;
       , email  = &quot;not a real email@some_email_provider.com&quot;
       , answer = &quot;yes&quot;)
</code></pre>
</div>
<p>Notice that with <code>hwsubmit</code>, each part has its own parameter for checking, and then is concantenated into a vector inside <code>hwchecker</code>. Of course, if you have multiple answers to submit, you will need to put them in order and wrap them up in <code>c()</code> as a vector.</p>
<h2>Wrap Up and Pt.2</h2>
<p>In the next post, I’ll detail some of the AppScript choices that I made, which are easily extensible. I personally found using AppScripts to be an interesting opportunity to do some practical javascript work without having to build all the website stuff.</p>
<p>Some of the options related to setting event triggers do take some thought, but there are good examples to follow – hopefully, mine included.</p>
<p>Using AppScripts, the possibilities of how to use Google Apps to do some many tasks is quite impressive. All the more so because it is free.</p>
<p><a target="_blank" class="twitter-share-button" data-via="data_steve" data-size="large" data-hashtags="rstats,appscripts,GAS" data-dnt="true" href="https://twitter.com/share">Tweet</a><a data-style="mega" target="_blank" href="https://github.com/data-steve/googleformr" data-icon="octicon-star">googleformr</a></p>
<p><div><div><div><div data-width="55" data-show-faces="false" data-send="true" data-layout="box_count" data-height="62" data-href="https://www.r-bloggers.com/hw-checker-r-appscripts-google-forms/"></div></div><div><a data-url="https://www.r-bloggers.com/hw-checker-r-appscripts-google-forms/" data-counturl="https://www.r-bloggers.com/hw-checker-r-appscripts-google-forms/" data-count="vertical" data-text="HW Checker: R, AppScripts, &amp; Google Forms" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://data-steve.github.io/build-homework-checker-pt1/"> data_steve</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/?s=data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/?s=Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/?s=map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/?s=animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/?s=sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/?s=LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/?s=SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/?s=git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/?s=hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/?s=Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/?s=PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/?s=time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/?s=trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/esdA7B5ZP5Y"></a></div>