Skip to content
Jim Klo edited this page Dec 10, 2011 · 1 revision

UNDER THE HOOD

AMPS works with an enhanced Learning Registry node implementation. So far the only enhancements done to a node is:

  1. Add an additional custom CouchDB map/reduce view.

  2. Modify NGINX configuration to allow public read access to that view.

BASIC WORKFLOW

MAP/REDUCE

Finding resources with alignment data within Dublin Core metadata

function(doc) {
	// Only look at resource data envelopes with inline resource_data
	if (doc.doc_type == "resource_data" && doc.resource_data && doc.resource_locator) {
		
		// Use E4X to try and parse resource_data as XML. Then assume a Dublin Core Terms
		// namespace to search for the <dct:conformsTo> which usually contains alignment
		// to standards information.  If the exists some elements anywhere in the payload,
		// emit and use envelope resource_locator as means for mapping resource to standard.
		try {
			var nsdl = eval(doc.resource_data);
			var dct = new Namespace("http://purl.org/dc/terms/");

			var stds = nsdl..dct::conformsTo
			for (idx in stds) {
				emit([doc.resource_locator, stds[idx].toString()],null);
			}	

  			
		} catch (error) {
			log("error:"+error);
		}
	}
}

This could be expanded upon to add more ways of processing the resource_data to incorporate other methods of storing alignment data within envelope records.

Finding resources with activity data for resources

function(doc) {
	// Only look at envelopes that are paradata.
	if (doc.doc_type == "resource_data" && doc.resource_data_type == "paradata" &&
			doc.resource_data && doc.resource_locator) {
		try {
			// determine if paradata envelope is of type LR Paradata 1.0
			var res = doc.resource_data;
			var action = res.verb.action;
			var isparadata = false;
			for (var i=0; i < doc.payload_schema.length; i++) {
				if (doc.payload_schema[i] === "LR Paradata 1.0") {
					try {
						if (res.content) {
							isparadata = true;
						}
						break;
					} catch (e0) {}
				}
			}

			// If this is paradata that we expect we need to link all relevant URL's found
			// as keys, however ensure that no two duplicate keys are emitted to save space.
			if (isparadata) {
				var emitted = {};
				emit([doc.resource_locator, action, res.content], null);
				emitted[doc.resource_locator] = true;
				
				try {
					if (!emitted[res.verb.context.id]) {
						emit([res.verb.context.id, action, res.content],null);
						emitted[res.verb.context.id] = true;
					}
				} catch (e1) {}

				try {
					if (!emitted[res.object.id]) {
						emit([res.object.id, action, res.content],null);
						emitted[res.object.id] = true;
					}
				} catch (e1) {}

			}
  			
		} catch (error) {
			log("error:"+error);
		}
	}
}

This could be expanded to focus more on specific kinds of paradata, like purely only paradata regarding alignment to standards. Some paradata records have differing resource_urls from the object.id; this is usually when the resource engaged with is the same resource as the canonical resource_url but located or embedded at a different URL. Adding both URL's allows us to also crosswalk a relationship from a copy to the original resource.

Distilling alignment information

For this demo, I was working with the folks at Jes & Co, hence this is currently focused on incorporating their added data. This could be easily expanded upon to use other sources without much effort.

function queryJesAndCo(id, asn) {
    var baseUrl = 'http://asn.jesandco.org/api/1/taxon';

    // Using Lawnchair here to be friendly to guys at Jes & Co. Anything we query from them
    // we cache so we don't have to waste resources and look it up again, since their resources
    // if they exist should be relatively static.
    var lc = Lawnchair(function(){});
       lc.get(asn, function(keyExists){
            if (keyExists && keyExists.value.statementNotation != "") {
                chrome_mustache("std", keyExists.value, function(html) {
                    if (html && html != "") {
                        $("div#learnreg-"+id+" div.data").append(html);
                        lc.get("opt_.learning-registry.standards", function(obj){
                            if (obj && obj.value) {
                                $("div#learnreg-"+id+".hidden").removeClass("hidden");
                            } else {
                                $("div#learnreg-"+id).addClass("hidden");
                            }
                        });
                        // console.log("cached data for: "+id+" "+html);
                    }
                });

            } else {
              
                // Since the service we're using with Jes & Co is alpha - the data is mapped
                // slightly differently - so if we find a scheme://purl.org/ASN, change it to
                // scheme://asn.jesandco.org
                var aurl = asn.replace("//purl.org/ASN", "//asn.jesandco.org");
                console.log(aurl);
        
                var data = {
                    "uri": aurl
                };

                // Handle the response from Jes & Co here.  Essentially there are a few
                // shortcuts taken here, like educationLevel - the value returned should
                // technically be resolved via RDF - which is possible, but for now, since
                // most will recognize the numerical educationLevel out of the URI, we cheat
                // and just take that.
                var callback = function(response, status, jqXHR) {
                    var jesurl = aurl;
                    var info = {
                        "identifier": asn,
                        "category": "",
                        "educationLevel": [],
                        "standard":[],
                        "statementNotation":[]
                    }

                    try {
                        var statement = response[jesurl];

                        // Try finding the umbrella category that the standard belongs to.
                        // Could be Common Core, but could be any other standard as well.
                        try {
                            var isPartOf = statement["http://purl.org/dc/terms/isPartOf"]

                            for (var i=0; i<isPartOf.length; i++) {
                                var asn_id = isPartOf[i].value.replace(/^.*\//, "");
                                if (asn_id.match(/^D[A-Z0-9]+$/)) {
                                    var doc = response[isPartOf[i].value];
                                    try {
                                        info["category"] = doc["http://purl.org/dc/elements/1.1/title"][0].value;
                                    } catch (e1) {
                                        try {
                                            info["category"] = doc["http://purl.org/dc/terms/description"][0].value;
                                        } catch (e2) { }
                                    }

                                }
                                
                            }
                        } catch (e) { }

                        function value(obj) {
                            return obj.value;
                        }

                        function strip(url) {
                            try {
                                return url.value.replace(/^.*\//, '');
                            } catch (Error) {
                                return "";   
                            }
                        }


                        // Try getting the actual standard info out of the response
                        try {
                            info["standard"] = statement["http://purl.org/dc/terms/description"].map(value);
                        } catch (e) { }

                        try {
                            info["educationLevel"] = statement["http://purl.org/dc/terms/educationLevel"].map(strip);
                        } catch (e) { }

                        try {
                            info["statementNotation"] = statement["http://purl.org/ASN/schema/core/statementNotation"].map(value);
                        } catch (e) { }


                        // info.category = info.category.map(strip).join(", ");
                        info.standard = info.standard.join(", ");
                        info.educationLevel = info.educationLevel.join(", ");
                        info.statementNotation = info.statementNotation.join(", ");

                    } catch (Error) {
                        console.log(Error);
                    }

                    // Save it using Lawnchair, keyed by the ASN URL, so if we come across it again
                    // on another resource, we don't have pester Jes & Co's service again.
                    Lawnchair(function() {
                        this.save({"key":asn, "value":info});
                    });

                    // We're going to get a bit snobbish.  Not all the alignment information has
                    // statement notations. Since this is currently important to us, we're going to
                    // discard anything that's currently missing that.
                    if (info.statementNotation != "") {
                        chrome_mustache("std", info, function(html) {
                            if (html && html != "") {
                                $("div#learnreg-"+id+" div.data").append(html);
                                // console.log("data for: "+id+" "+html);
                            }
                        });
                    }                    
                }

                data["callback"] = "foo";

                var params = {
                    "url": baseUrl,
                    "dataType": "json",
                    "data": data,
                    "success": callback,
                    "cache": false,
                    "jsonp": "callback"
                };

                chrome_ajax(params);


          }
           
       }); 


   
}

As noted this only is using Jes & Co ASNs. It's been observed that other alignment data does exist in the LR, however it doesn't use Jes & Co ASNs. One example is Florida CPALMS, whose alignement information is contained as free text within the Dublin Core Terms <dct:conformsTo> element. Sany other ones, some have added in, the FL folks, have “free text” that describe the standard.