Download sdkman
$ $ curl -s get.sdkman.io | bash
Initialize sdkman
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
If unsuccessful make sure you have Java installed
Confirm installation
$ sdk version
Download grails, gradle, and groovy
$ sdk install grails 3.0.11
$ sdk install groovy
$ sdk install gradle
Clone the repository
$ git clone https://github.com/uwcse481h2016/AppForLiteracy
$ cd AppForLiteracy
Run the application!
$ grails run-app
The tasks we laid out to accomplish in our task analysis:
- Patient takes an assessment
- Patient performs an exercise
- Researcher views patient progress
- Researcher modifies assigned modules
- Researcher adds new patient
- Researcher adds new module
After additional meetings with our stakeholders, we combined the "Patient takes an assessment" and the "Patient performs an exercise" into one task, which we will refer to as "Patient performs a module", which serves the purpose of both previous tasks.
Additionally, the task "Researcher modified assigned modules", has been further fleshed out to become "Researcher assigns module with individualized content".
###Patient performs a module
- Patient logs in using the username and password assigned to them by the researcher. The log-in for a test user is as follows: Email: [email protected] Password: password
- The Patient chooses the module they wish to play and presses the play button.
- Patient performs the module as directed by the module.
###Researcher views patient progress
- Researcher logs in. The log-in for a test user is as follows: Email: [email protected] Password: password
- The Researcher identifies the patient whose progress they wish to view and chooses the "View Progress" button listed under that patient's name.
- The Researcher identifies the Module and Date they wish to examine and downloads the data file associated with those variables.
###Researcher assigns a modules with individualized content
- Researcher logs in. The log-in for a test user is as follows: Email: [email protected] Password: password
- The Researcher identifies the patient to whom they wish to assign a module and chooses the "Assign Module" button listed under that patient's name.
- The Researcher chooses the module they wish to assign from the list of modules.
- The Researcher uploads the individualized content in a JSON file. The content for the test module is listed as "simple.txt".
- The Researcher chooses the "Assign" button.
- The Researcher can choose between two labeled buttons to assign more modules or return to the homepage.
###Researcher adds new patient
- Researcher logs in. The log-in for a test user is as follows: Email: [email protected] Password: password
- The Researcher chooses the "Learners" option from the top navigation bar.
- The Researcher enters the appropriate information about the learner into the text boxes in the "Add a Learner" section.
- The Researcher chooses the "Save" button.
###Researcher adds new module This process is outlined in detail below.
Herafter this name will be referred to as TYPE
Use the following command to have Grails generate scaffolding code for your new plugin:
$ grails create-plugin TYPE
repositories {
...
maven { url "http://dl.bintray.com/osreadplugins/plugins" }
}
dependencies {
...
compile "org.grails.plugins:MetaFunctionality:0.1"
...
}
In the domains folder create a domain class with name TYPE
This domain class must do the following:
-
extend the ModuleInput class
-
define the module input data as fields in the domain
-
This is where you are able to define the input you want to take in when the module is assigned
Example:
class FirstExample extends ModuleInput {
static hasMany = [words: String]
List words
}
In the services folder create a new service named FetchInputHeadersService.
Within this service define a method that returns a Map<String, String> that represents a mapping from the fields defined in the domain class to their respective data types.
The following data types are accepted as input:
- String
- Integer
- Double
- Boolean
or any arrays of the above types:
- [String]
- [Integer]
- [Double]
- [Boolean]
Example:
class FetchInputHeadersService {
def getHeaders () {
Map<String, String> headers = new LinkedHashMap<>()
headers.put("words", "[String]")
return headers
}
}
Create a controller to serve as the entry point of the module.
This controller must be named TYPEController.
The controller must have a method start()
This method will be passed the moduleID of the module through params.id which can be used to get the associated Module object by calling Module.findByModuleID(params.id)
Example:
import firstexample.FirstExample
import metafunctionality.Module
import metafunctionality.ModuleOutput
class FirstExampleController {
def start() {
String inputID = Module.findByModuleId(params.id).inputID
FirstExample input = FirstExample.findByModuleDataID(inputID)
List<String> rc = input.words
//Store Module in saveModuleService
[words: words]
}
}
At the end of the module you must save the output that you wish to pass out of the module with the Module object that was passed in.
To do so you must create a ModuleOutput object and store within it the desired headers and rows of comma-separated values.
Finally store the ModuleDataID of the ModuleOutput object in the Module object.
This ModuleOutput object will be translated into a .CSV file with the associated headers and comma-separated rows of data.
Example:
def submit() {
List<String> valueRows = new ArrayList<String>()
ModuleOutput output = new ModuleOutput()
output.headers = ["word", "accuracy"]
output.valueRows = params.data
Module m = //load from saveModuleService
if (m.outputIDs != null) {
m.outputIDs.add(output.moduleDataID)
} else {
m.outputIDs = [output.moduleDataID]
}
output.type = "FirstExample"
m.save(flush: true)
output.save(flush: true)
//redirect to learner home
redirect(controller: "appforliteracy.FileOutput", action: "output", params: [id: output.moduleDataID])
}
Once you have completed your module you must publish it to the Maven repository.
There are several steps to do this:
plugins {
...
id "com.jfrog.bintray" version "1.2"
}
bintray {
user = "username"
key = "apikey"
publications = ['maven']
publish = true
pkg {
userOrg = 'osreadplugins'
name = "TYPE"
issueTrackerUrl = "https://github.com/username/TYPE/issues"
vcsUrl = "https://github.com/username/grails-TYPE"
version {
attributes = ['grails-plugin': "org.osread:TYPE"]
name = 0.1
}
}
}
Your API Key can be found under 'Edit your profile'
Enter the following command at your project root:
$ grails gradle bintrayUpload
You should now be able to navigate to https://bintray.com/osreadplugins/plugins and see your plugin!
Once you have published your plugin to the Maven repository you are now ready to integrate it into the main application!
Two things are required to do this:
Add the following line to the AppForLiteracy/build.gradle file:
dependencies {
...
compile "org.grails.plugins:TYPE:version" //version is specified in the build.gradle file of your plugin under the name field of version
...
}
class ModuleListService {
static List<String> getModuleNames() {
List<String> names = new ArrayList<>()
names.add("FirstExample")
names.add("TYPE")
//TODO: Add additional module names here
return names
}
}
You're new module should be completely functional! Test it by assigning the module with a module input file that matches your specified input plus name and type fields. Example:
{
"type": "FirstExample",
"name": "Example Input",
"words": [
"Reading",
"is",
"cool!"
]
}