<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>OUseful.Info, the blog... &#187; Getting ONCourse Data Flowing into Google Spreadsheets</title>
	<atom:link href="http://blog.ouseful.info/2013/01/23/getting-oncourse-data-flowing/feed/?withoutcomments=1" rel="self" type="application/rss+xml" />
	<link>http://blog.ouseful.info</link>
	<description>Trying to find useful things to do with emerging technologies in open education</description>
	<lastBuildDate>Wed, 19 Jun 2013 23:56:51 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='blog.ouseful.info' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>OUseful.Info, the blog... &#187; Getting ONCourse Data Flowing into Google Spreadsheets</title>
		<link>http://blog.ouseful.info</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://blog.ouseful.info/osd.xml" title="OUseful.Info, the blog..." />
	<atom:link rel='hub' href='http://blog.ouseful.info/?pushpress=hub'/>
		<item>
		<title>Getting ONCourse Data Flowing into Google Spreadsheets</title>
		<link>http://blog.ouseful.info/2013/01/23/getting-oncourse-data-flowing/</link>
		<comments>http://blog.ouseful.info/2013/01/23/getting-oncourse-data-flowing/#comments</comments>
		<pubDate>Wed, 23 Jan 2013 09:59:15 +0000</pubDate>
		<dc:creator>Tony Hirst</dc:creator>
				<category><![CDATA[Project]]></category>
		<category><![CDATA[coursedata]]></category>
		<category><![CDATA[oncourse]]></category>

		<guid isPermaLink="false">http://blog.ouseful.info/?p=9603</guid>
		<description><![CDATA[One of the challenges that needs to be addressed when developing data driven applications is how to get data from a data base to the point of use. Another relates to time-relevance. For example, in one document you might want to look at figures or data relating to a specific, fixed date or period (March [&#8230;]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.ouseful.info&#038;blog=325417&#038;post=9603&#038;subd=ouseful&#038;ref=&#038;feed=1" width="1" height="1" />]]></description>
				<content:encoded><![CDATA[<p>One of the challenges that needs to be addressed when developing data driven applications is how to get data from a data base to the point of use. Another relates to time-relevance. For example, in one document you might want to look at figures or data relating to a specific, fixed date or period (March 2012, for example, or the academic years 2012-13). At other times, you might want current data: values of some indicator over the last 6 weeks for example. Where live data feeds are available, you might want them to be displayed on a dashboard. In other circumstances, you might want a more traditional printed report or Powerpoint presentation, but one that contains absolutely up to the minute information. Ideally, the report or presentation would be &#8220;self-updating&#8221; so that each time you printed it off, it contained the latest data values.</p>
<p>One common user environment for data related activities is a spreadsheet. When developing an API that produces data that might be usefully manipulated within a spreadsheet context, it can be useful to provide a set of connectors that allow data to be pulled directly from the API and inserted into the spreadsheet.</p>
<p>Here&#8217;s a quick example of how we might start to pull data into a Google Spreadsheets context from the University of Lincoln course data API. The example calls broadly reproduce those described in <a href="http://blog.ouseful.info/2013/01/18/getting-oncourse-with-course-data/">Getting ONCourse With Course Data</a>.</p>
<p>Although the new script management tools in the Google Apps environment confuse the process of defining spreadsheet specific scripts, at its heart defining custom spreadsheet functions for Google Spreadsheets is a trivial exercise: create a custom function (for example, <tt>myFunction(val)</tt>), pass in a value (such as a cell value) and return a value or array. You can can call the function using a formula, <tt>=myFunction(A3)</tt>, for example. If a single value is returned, this will be returned into the calling cell. If a one-dimensional list is returned, it will add alues to the current row. If a two dimensional array is returned, it will populate rows and columns.</p>
<p>Here are a few helper functions for calling the ONCourse data into a Google Spreadsheet:</p>
<pre class="brush: jscript; title: ; notranslate">function signed(url){
  //Use this to add the API key, for example:
  //return url+'?key='+KEYVAL 
  return url
}

function gurl(url){
  //Fetch the JSON data and parse it as such
  raw=UrlFetchApp.fetch(signed(url))
  json=Utilities.jsonParse(raw.getContentText())

  return json
}
 
function jgrabber(u){
  root='https://n2.online.lincoln.ac.uk'
  return gurl(root+u)
}

function grabModulesId(id){
  path= '/modules/id/'+id
  json= jgrabber(path )
  return json['result']
}

function grabProgrammesId(id){
  path= '/programmes/id/'+id
  json= jgrabber(path )
  return json['result']
}

function assessmentByModuleID(moduleID){
  d=grabModulesId(moduleID)
  return d['assessments']
}</pre>
<p>Let&#8217;s now see if we can pull data into the spreadsheet, and try to get a feel for whether this sort of approach looks as if it may be useful&#8230;</p>
<p>First up, how about getting a list of programmes associated with a module?</p>
<pre class="brush: jscript; title: ; notranslate">function printProgsFromModuleID(moduleID){
  d=grabModulesId(moduleID)
  var arr = [];
  c=[]
  c.push(d['title'])
  c.push(d['module_code']['code'])
  c.push(d['level']['description'])
  c.push(d['credit_rating'] + ' points')
  arr.push(c)
  arr.push([])
  c=['Programme', 'Course', 'Course Code']
  arr.push(c)
  for (var i=0;i&lt; d['module_links'].length;i++){
   r=d['module_links'][i]['programme']
   c=[ r['programme_title'], r['course_title'], r['course_code']['code'] ]
   arr.push(c)
  }
  return arr
}</pre>
<p>Here&#8217;s the result:</p>
<p><a href="http://ouseful.files.wordpress.com/2013/01/printprogsfrommoduleid.png"><img src="http://ouseful.files.wordpress.com/2013/01/printprogsfrommoduleid.png?w=700&#038;h=268" alt="printProgsFromModuleID" width="700" height="268" class="alignnone size-full wp-image-9614" /></a></p>
<p>How about learning outcomes per module (via the assessments associated with each module)?</p>
<pre class="brush: jscript; title: ; notranslate">function learningOutcomesByModuleID(moduleID){
  d=assessmentByModuleID(moduleID)
  arr=[]
  for (i=0; i&lt;d.length; i++){
    r=d[i]
    assessment=gurl(r['nucleus_url'])['result']

    c=[ assessment['module']['title'], assessment['module']['module_code']['code'], assessment['assessment_method'] ] 
    arr.push(c)

    learningOutcomes=assessment['learning_outcomes']
    for (j=0; j&lt; learningOutcomes.length; j++)
      arr.push([ '','', learningOutcomes[j]['description'] ])
  }
  return arr
}</pre>
<p>Which gives us:</p>
<p><a href="http://ouseful.files.wordpress.com/2013/01/learningoutcomesbymodule.png"><img src="http://ouseful.files.wordpress.com/2013/01/learningoutcomesbymodule.png?w=700" alt="learningOutcomesByModule"   class="alignnone size-full wp-image-9615" /></a></p>
<p>And how about programme outcomes for a particular programme, broken out into outcome types:</p>
<pre class="brush: jscript; title: ; notranslate">function programmeOutcomesByProgrammeID(id){
  d=grabProgrammesId(id)
  arr=[]
  var types= new Object();
  for (i=0;i&lt;d['programme_outcomes'].length; i++){
    r=d['programme_outcomes'][i]
    if (types[ r['category']['title'] ] == undefined ){
      types[r['category']['title']]=[]
    }
    types[r['category']['title']].push(r['description'])
  }

  for ( j in types )
    arr.push([j,types[j] ])
  return arr
}</pre>
<p>The result? A handy table:</p>
<p><a href="http://ouseful.files.wordpress.com/2013/01/programmeoutcomesbyprogrammeid.png"><img src="http://ouseful.files.wordpress.com/2013/01/programmeoutcomesbyprogrammeid.png?w=700&#038;h=244" alt="programmeOutcomesByProgrammeID" width="700" height="244" class="alignnone size-full wp-image-9616" /></a></p>
<p>Okay, so that all seems easy enough. I think that Google docs are also scriptable, so it should be possible to populate a templated &#8220;word&#8221; document using data pulled from the API (for example, using a snippet like this one of Martin Hawksey&#8217;s: <a href="https://gist.github.com/1170597">Google Apps Script to fill in a Document template with Spreadsheet data</a>).</p>
<p>One thing I realised about the API from playing with this recipe was that it is defined very much as a little-l, little-d &#8220;linked data&#8221; API that works well for <em>browsing</em> the data. The well defined URIset and use of internal unique identifiers make it easy to traverse the data space <em>once you are in it</em>. However, it&#8217;s not immediately obvious to me how I could either search my way into the data, or access it via <em>natural identifiers</em> such as programme codes or module codes.</p>
<p>[Seems I missed a trick on the API front... As described in <a href="http://coursedata.blogs.lincoln.ac.uk/2013/01/15/apms-nucleus-apis-how-why/">APMS -&gt; Nucleus -&gt; APIs. How? Why?</a>, it seems that <em>you could get details of all assessments that are the final assessment for the module, that contain group work at: <a href="https://n2.online.lincoln.ac.uk/assessments?access_token=ACCESSTOKEN&#038;group_work=1&#038;final_assessment=1" rel="nofollow">https://n2.online.lincoln.ac.uk/assessments?access_token=ACCESSTOKEN&#038;group_work=1&#038;final_assessment=1</a></em>]</p>
<p>For example, to print the programmes associated with a module, I might use the above formula <tt>=printProgsFromModuleID(97)</tt>, but the identifier I need to pass in (<tt>97</tt>) is an internal, machine generated ID. This is all well and good if you are working within the machine-ID space, but this is not the human user space. For that, it would be slightly more natural to make use of a module code, and call something like <tt>printProgsFromModuleCode('FRS2002M')</tt>. There are issues with this approach of course, with module codes being carried over from presentation to presentation, and breaking a simple bijective (one-one onto) relationship between internal module IDs and module codes. As a result, we might need to further qualify these calls with a presentation year (or by default assume the presentation from the current academic year), or whatever other arguments are required to recapture the bijectivity.</p>
<p>PS in passing, here&#8217;s another view over modules by programme, broken down into core and option modules.</p>
<p><a href="https://views.scraperwiki.com/run/oncourse_demo_tree_views_2/?progID=23"><img src="http://ouseful.files.wordpress.com/2013/01/modules-by-programme.png?w=700&#038;h=457" alt="modules by programme" width="700" height="457" class="alignnone size-full wp-image-9618" /></a></p>
<p>There are a few problems with this view &#8211; for example, the levels need ordering properly; where there are no core or no optional modules the display is not as good as it could bel the label sizing is a bit small; there is no information relating to pre-requisites for optional modules &#8211; but it&#8217;s a start, and it&#8217;s reasonably clean to look at.</p>
<p>It should also be easy enough to tweak the data generator script to allow us to use the same display script to show assessment types for each module in a programme,  as demonstrated using enclosure charts in <a href="http://blog.ouseful.info/2013/01/20/visually-revealing-gaps-in-oncourse-data/"> VIsually Revealing Gaps in ONCourse Data </a>, and maybe even learning outcomes too.</p>
<p>If I get a chance, I&#8217;ll look through the sorts of thing requested in the <a href="http://coursedata.blogs.lincoln.ac.uk/2012/03/15/focus-group-14th-march-2012/">ONCourse Focus Group – 14th March 2012</a> and try to pull out some views that match some of the requested ones. What would also be interesting would be to have a list of use cases from people who work with the data, too&#8230;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/ouseful.wordpress.com/9603/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/ouseful.wordpress.com/9603/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=blog.ouseful.info&#038;blog=325417&#038;post=9603&#038;subd=ouseful&#038;ref=&#038;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://blog.ouseful.info/2013/01/23/getting-oncourse-data-flowing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/abbd9f90565ce9ae4d065d93a81d8c03?s=96&#38;d=http%3A%2F%2F1.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Tony Hirst</media:title>
		</media:content>

		<media:content url="http://ouseful.files.wordpress.com/2013/01/printprogsfrommoduleid.png" medium="image">
			<media:title type="html">printProgsFromModuleID</media:title>
		</media:content>

		<media:content url="http://ouseful.files.wordpress.com/2013/01/learningoutcomesbymodule.png" medium="image">
			<media:title type="html">learningOutcomesByModule</media:title>
		</media:content>

		<media:content url="http://ouseful.files.wordpress.com/2013/01/programmeoutcomesbyprogrammeid.png" medium="image">
			<media:title type="html">programmeOutcomesByProgrammeID</media:title>
		</media:content>

		<media:content url="http://ouseful.files.wordpress.com/2013/01/modules-by-programme.png" medium="image">
			<media:title type="html">modules by programme</media:title>
		</media:content>
	</item>
	</channel>
</rss>
