My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
ModifyTemplate  
How to modify the two base templates that all other pages in your app use.
Updated Mar 28, 2014

Modify Course Template

Course Builder uses view files as templates to determine the look and feel of all of the pages in your course. The view files are HTML files defined in the views/ directory.

The templates work together hierarchically. Every page displayed for your course starts from either the base_registration.html template (for unenrolled people) or the base.html template (for enrolled people). The two base templates define the overall HTML structure of a page.

The other views, such as activity.html, fill in more structure for a specific type of page. Finally, files outside of views may fill in the content for a particular page, such as activity-1.1.js.

For more information on the structure of these pages, see Using templates for an introduction and then check out the Jinja2 documentation.

Registration

Course Builder uses the following files to render the Registration page:

  • views/base_registration.html defines the header and footer areas. This page is used by all pages displayed to an unregistered person.
  • views/confirmation.html defines the content of the registration form.
  • views/preview.html defines the structure of the content area. This page is very similar to its registered counterpart, views/course.html.
  • views/register.html defines the content of the registration form.
  • views/summary.html provides the course description and other introductory material. This page is also used by views/course.html.
The Registration confirmation page additionally uses:
  • views/confirmation.html defines the content of the registration form.
We strongly suggest you deploy Course Builder to Google App Engine and create your course in the browser after doing so. This places the course in the Google App Engine datastore. If you wanted to change the content of the example course on disk, you would change the .csv files in the data/ directory.
  • data/unit.csv provides the actual content of the content area. This page is also used by views/course.html.

Course home page

The following files render the course home page (Course in the navigation bar):

  • views/base.html defines the header and footer areas. This page is used by all pages displayed to a registered student.
  • views/course.html defines the structure of the content area. This page is very similar to its unregistered counterpart, views/preview.html.
  • views/summary.html provides the course description and other introductory material. This page is also used by views/preview.html.

We strongly suggest you deploy Course Builder to Google App Engine and create your course in the browser after doing so. This places the course in the Google App Engine datastore. If you wanted to change the content of the example course on disk, you would change the .csv files in the data/ directory.

  • data/unit.csv provides the actual content of the content area. This page is also used by views/preview.html.

The first line describes the content of the other lines:

id,type,unit_id,title,release_date,now_available

Each line after that contains the information for an individual part of the course, such as:

1,A,Pre,Pre-course assessment,,True
2,U,1,Introduction,available July 10,True
...
11,O,http://www.youtube.com/watch?v=dwlpViuIYgU&feature=player_embedded,Hang Out with Search Experts Video,,True

If you edit the file, leave the first line as is. Replace all of the other lines with the information relevant to your course. The template files and various Python files refer to these fields when displaying course information. Each line contains the following fields:

  • id: An integer representing this item. These integers must start at 1 and be in order.
  • type: One of A, U, or O, depending on whether this line represents an assessment, a unit, or something else (such as a link to a video or to an upcoming Hangout On Air).
  • unit_id: An id for this item. Its value depends on the type:
    • For an assessment (type=A): the suffix of the corresponding assessment-SUFFIX.js file. By default, one of Pre, Mid, or Fin. See Writing assessments.
    • For a unit (type=U): an integer representing the unit number.
    • For something else (type=O): a URL pointing to that thing.
  • title: The text to describe this item.
  • release_date: When this release will be available to students. This string appears only if now_available is False. Optional.
  • now_available: A Boolean representing whether or not students can currently access this item. If False, the title is not a link. (Note that case is important in this value; it must be either True or False.)

Lesson

The following files render a lesson page:

  • views/base.html defines the first two parts of the header and defines the footer. This page is used by all pages displayed to a registered student.
  • views/unit.html defines the second two lines of the header, the vertical navigation, and the content area.

We strongly suggest you deploy Course Builder to Google App Engine and create your course in the browser after doing so. This places the course in the Google App Engine datastore. If you wanted to change the content of the example course on disk, you would change the .csv files in the data/ directory. It contains information about each lesson, such as the video's URL and the lesson's title.

  • data/lesson.csv contains the content of the content area for all lessons in your example course on disk.
The first line describes the content of the other lines:
unit_id,unit_title,lesson_id,lesson_title,lesson_activity,lesson_activity_name,lesson_notes,lesson_video_id,lesson_objectives

Each line after that contains the information for an individual lesson, such as:

3,Advanced techniques,1,Web organization,Yes,Lesson 3.1 Activity,https://docs.google.com/SOMETHING,DndOoEVCWfI,"<ul><li>Describe how operators filter results.
<li>Use the site: operator at the top-level domain and website levels.</li>
<li>Use a word you expect to appear on the target page to refine results.</li>
<li>Use the site: operator within images and news results.</li></ul>"

When you edit the file, leave the first line as is. Replace all of the other lines with the information relevant to your course. Each line contains 9 fields. The template files and various Python files refer to these fields when displaying course information. Those files use a different name for the field than does data/lesson.csv. The mapping between the two names is defined in verify.py.

data/lesson.csv field Referred to as Description
1 unit_id unit.unit_id An integer indicating which unit this lesson is part of. You must number units consecutively starting with 1.
2 unit_title unit.title The name of the unit.
3 lesson_id lesson.id An integer indicating which lesson this is. You must number lessons in each unit consecutively starting with 1.
4 lesson_title lesson.title The name of the lesson.
5 lesson_activity lesson.activity Set this value to Yes if there is an associated activity. Leave it blank if there is not.
6 lesson_activity_name lesson.activity_title The name of the associated activity, to appear as the title of the activity page.
7 lesson_notes lesson.notes URL of the text version of the lesson.
8 lesson_video_id lesson.video The id of the YouTube video associated with the lesson. For example, if the URL of the video is http://www.youtube.com/watch?v=DndOoEVCWfI, then the id is DndOoEVCWfI.
9 lesson_objectives lesson.objectives A string containing lesson objectives, to appear after the title of the lesson. The string can contain HTML elements.

The following image shows where this information appears on the screen:

Change lesson layout example

Assume that you do not want to use videos in your course. And that, for every lesson, you have associated reference material you want to provide. In this case, a typical lesson might look as follows:

For this change, all you need to do is edit the file that renders a lesson page (views/unit.html) and supply different information in data/lesson.csv. Originally, views/unit.html contains, in part:

  ...
  <div class="gcb-col-3">
    <p style="float:right; margin-top: 0px;">
      <a class="gcb-button gcb-button-primary" href="{{ lesson.notes }}" target="_blank">Text Version</a>
    </p>
  </div>
  </div><!-- /gcb-cols -->
  {% if lesson.video %}
  <p class="video-container">
    <iframe width="650px" height="400px" 
      src="http://www.youtube.com/embed/{{ lesson.video   }}?feature=player_embedded&rel=0" 
      frameborder="0" allowfullscreen></iframe>
  </p>
  {% endif %}
  ...

To make the changes suggested above, change that snippet to:

  ...
  <div class="gcb-col-3">
    <p style="float:right; margin-top: 0px;">
      <!-- DIFFERENT BUTTON LABEL -->
      <a class="gcb-button gcb-button-primary" href="{{ lesson.notes }}" target="_blank">Reference Material</a>
    </p>
  </div>
  </div><!-- /gcb-cols -->
  {% if lesson.video %}
  <!-- SIMPLER IFRAME -->
  <iframe width="95%" height="600" src="{{ lesson.video }}"></iframe>
  {% endif %}
  ...

Then, in data/lesson.csv, where you previously put the ID of a YouTube video, you instead put the URL of the file you want to appear inside the iframe. Yes, the code still calls it a "video", but it doesn't really care. That's all you need to do for this change.

Notice that in the example you changed the semantics of the lesson_video_id field in data/lesson.csv. Previously, the code expected that field to contain a part of a URL and views/unit.html supplied the rest of the URL. With this change, the code expects that field to be a complete URL.

In general, if you make changes to the semantics of the data (as we did here), you need to be very careful that you make the changes everywhere that data is used. It happens to be the case that lesson_video_id is only used in views/unit.html, so this was a safe, easy change. If you change the semantics of other data fields, you need to be sure to account for that change everywhere.

We strongly suggest that you do not change the semantics of these fields unless you thoroughly understand the Course Builder code. These fields are used in many places:

  • unit_id
  • lesson_id
  • lesson_activity

You can change the semantics of the following fields. They are used only in the template files listed here:

Field in data/lesson.csv Which templates use it
unit_title views/activity.html
views/course.html
views/unit.html
lesson_title views/unit.html
lesson_activity_name views/activity.html
lesson_notes views/activity.html
views/unit.html
lesson_video_id views/unit.html
lesson_objectives views/unit.html

You can change the look of any field in one place, without consequences in other places.

Activity

The following files render an activity page:

  • views/base.html defines the footer and the first two lines of the header; it is the same file as for lessons.
  • views/activity.html defines the second two lines of the header, the vertical navigation, and the content area. Note that these are the same parts views/unit.html defines for lessons. You probably want to be consistent in these files.

We strongly suggest you deploy Course Builder to Google App Engine and create your course in the browser after doing so. This places the course in the Google App Engine datastore. If you wanted to change the activity questions of the example course on disk, you would change the .js files in the assets/js/ directory.

  • assets/js/activity-N.M.js contains a JavaScript array that fills in the actual question and answer areas for the activity. Each activity section has its own file.

The activity for a particular lesson goes in a corresponding JavaScript file. The JavaScript filename is activity-N.M.js, where N is the unit number and M is the lesson number.

The format of the file is

var activity = [
  entry1,
  ...,
  entryN
]

The file contains a single array variable named activity. Each element in the array is arbitrary HTML, a question, or answer information.

While it looks like the questions and their answers are connected to each other, the code does not enforce this. The code just renders the elements of the array one after the other. It is up to you to make sure they are in a logical order.

Arbitrary HTML

The first choice for an array element is a string that contains a set of complete HTML elements. That is, if the string contains an open HTML tag (such as <em>), it must also have the corresponding close tag (such as </em>).

The code simply renders the HTML you enter. For example, the sample activities all start with a 1-cell table that summarizes the major points of the associated lesson. With this HTML:

'<table border="2"><tr><td><b>Search Tips:</b><p><ul><li>In the last video, you
learned how to use color filtering within image search to narrow your image results to
images made up primarily of a certain color. You do this by clicking on the
appropriate colored box in the left panel. <li>Please note that you can’t filter
by color on iPad or Android tablets, but you can answer the questions below as
if you were using a laptop or desktop computer.</ul><p></tr></td></table><br/>',

The code displays the following:

Search Tips:
  • In the last video, you learned how to use color filtering within image search to narrow your image results to images made up primarily of a certain color. You do this by clicking on the appropriate colored box in the left panel.
  • Please note that you can’t filter by color on iPad or Android tablets, but you can answer the questions below as if you were using a laptop or desktop computer.

Note: This and other example code contains line breaks inside a JavaScript string for readability. You cannot do that in your code. Each string must be on a single line.

Questions

As far as the code is concerned, there is no difference between a question and any other arbitrary HTML string. The difference is only in that you follow a question with answer information.

If you want to number your questions, you must include the numbers in your HTML. For example, with the following two HTML strings:

"<p><img src='assets/img/Image1.1a.png' height=450 width=785></p>", 
'<p><b>1.</b> You want to reread an introductory accounting textbook from
school, but you cannot remember the exact title. You recall that the cover is
yellow and has puzzle pieces on it. In the image above, where would you click to
filter the results in order to locate the book?</p>',

The code displays the following:

...the image...
1. You want to reread an introductory accounting textbook from school, but you cannot remember the exact title. You recall that the cover is yellow and has puzzle pieces on it. In the image above, where would you click to filter the results in order to locate the book?

Answer information

The final possibility for an entry in the activity array is a JavaScript object that represents answer information. Depending on the answer type, this information can have several forms. The object contains properties such as the type of question, a regular expression indicating the correct answer, or a string to show in case of either correct or incorrect answers or to show when the student asks for help.

A question can be one of three types:

Single multiple-choice question

The code for a single multiple-choice question looks like the following example:

var activity = [

  {questionType: 'multiple choice',
  choices: [
    ['[yarnbombing news article]', false, 
      'Try again. This is a risky approach, since many news articles do not call themselves \'news articles\' on the page.'],
     ['[yarnbombing] then click News in the left menu', true,
       'Correct! Using a collection of a specific type of media, like News, can help you get to the best pages faster.'],
     ['[i would like to find news articles about yarnbombing]', false,
      'Try again. We want to avoid including a lot of extra, confusing words into a query.'],
     ['[what are some recent publications about yarnbombing]', false,
      'Try again. Stating what you want in this way, introduces a lot of extra words into a query.']
    ]
  }

];

This code represents a single JavaScript object with two required attributes. The first attribute is questionType. The value 'multiple choice' indicates that this answer is for one multiple-choice question. The second attribute is choices. The value of this attribute is an array of the possible answers to the question and what to do with each.

Each element of the choices array is itself a 3-element array whose required values are:

  • The text to display for this answer.
  • A Boolean value indicating whether or not this is the correct answer.
  • The text to display if this choice is submitted.

For this question, students see the following:

Students see a list of possible answers, a button labelled Check Answer, and an empty text box. When they choose one of the answers and click on Check Answer, the code displays the string associated with that answer. In this example, if the user submits the answer [yarnbombing news article], the code displays Try again. This is a risky approach, since many news articles do not call themselves 'news articles' on the page.

If students choose the correct answer, the code also highlights the line containing that answer.

Group of multiple-choice questions

Sometimes you want to group a set of multiple-choice questions so that students can only check their answers after answering all of the questions in the group. You can do this with code that looks like the following example:

var activity = [

  {questionType: 'multiple choice group',
    questionsList: [ 
      {questionHTML: '<b>1.</b> In the United States, the state of California is known for its earthquakes. Have there been earthquakes in Iowa?<br/>',
        choices: ['Yes', 'No'],
        correctIndex: 0},
      {questionHTML: '<b>2.</b> Has there ever been an earthquake in Maine?<br/>',
        choices: ['Yes', 'No'],
        correctIndex: 0},
      {questionHTML: '<b>3.</b>Which state (Iowa or Maine) had an earthquake more recently?<br/>',
        choices: ['Iowa', 'Maine'],
        correctIndex: 1}
    ],
    allCorrectOutput: 'Hopefully you used Control-F to find the information quickly.',
    someIncorrectOutput: 'Remember, you can use Control-F to find information like this more quickly. Please try again.'
  }

];

This code represents a single JavaScript object with four required attributes:

  • questionType. The value 'multiple choice group' indicates that this answer is a group of multiple-choice questions.
  • questionsList. The value of this attribute is an ordered array of the related questions. Each element of the questionsList array is a JavaScript object representing one question and answer. Each of those objects has 3 attributes:
    • questionHTML: HTML representing the text to display for this question.
    • choices: An array of the possible answers to this question.
    • correctIndex: The index in the choices array of the correct answer. (Remember that JavaScript arrays are 0-based.)
  • allCorrectOutput. The text to display when the student correctly answers all questions in the group. Before this text, the code includes the string "All your answers are correct!"
  • someIncorrectOutput. The text to display when the student incorrectly answers at least one of the questions. In addition to this text, students see how many of their answers were incorrect.

For this example, if students answer one question correctly, they see the following:

Multiple-choice questions with multiple correct answers

You can present multiple choice questions that have more than one correct answer. The code for this question type looks like the following example:

var activity = [

  { questionType: 'multiple choice group',
    questionGroupHTML: '<p>This section will test you on colors and numbers.</p>',
    questionsList: [
          {questionHTML: 'Pick all <i>odd</i> numbers:',
           choices: ['1', '2', '3', '4', '5'], correctIndex: [0, 2, 4]},
          {questionHTML: 'Pick one <i>even</i> number:',
           choices: ['1', '2', '3', '4', '5'], correctIndex: [1, 3],
           multiSelect: false},
          {questionHTML: 'What color is the sky?',
           choices: ['#00FF00', '#00FF00', '#0000FF'], correctIndex: 2}
    ],
    allCorrectMinCount: 2,
    allCorrectOutput: 'Great job! You know the material well.',
    someIncorrectOutput: 'You must answer at least two questions correctly.'
  }

];

You can specify whether a student must choose all the answers correctly or just one, in order for the question to be correct. By default, the multiSelect: setting is true, which means that the student needs to select all the correct answers. You do not need to specify multiSelect: true since by default it is the case.

To change the default behavior, specify multiSelect: false. With multiSelect: false specified in the second question in the following example, the student receives an overall score of two out of three. Question one is incorrect while question two is correct because with question two, the student only needed to select one correct answer.

If we specified multiSelect: true (or omitted any specification) in question two and the student only selected one correct answer, then the student would have received an overall score of one out of three.

When answers are presented as checkboxes, it means that all correct choices must be selected. When answers are presented as radio buttons, it means you must select only one correct answer.

The allCorrectMinCount: setting indicates how many questions in the activity must be answered correctly for successful completion. If the students are successful, they received the message in allCorrectOutput:. Else, they receive the message in someIncorrectOutput.

Free text

The final type of answer is a free text area. Use this answer type when your question is somewhat open ended. Students type their answer into a text box of a size you specify.

The code uses a regular expression to verify the answer. Regular expressions can be notoriously difficult for a programmer to get right. For this reason, you need to be very careful with the wording of any question that takes a free text answer. Your regular expression needs to account for reasonable variations in student responses. The code for a simple free text answer looks as follows:

var activity = [

  { questionType: 'freetext',
    correctAnswerRegex: /white?/i,
    correctAnswerOutput: "Correct--Many charts, tables, and graphs have white backgrounds, so filtering for white images helps you find them faster.",
    incorrectAnswerOutput: "Try again. Consider what color would be dominant in images of charts, tables, and graphs. Look at the results above. Each of those sources is traditionally printed on paper.",
    showAnswerOutput: "Our search expert says: I would click on white in the color grid, since many charts, tables, and graphs have white backgrounds." 
  }

];

This code represents a single JavaScript object with several attributes. The first two are required; the others are optional.

  • questionType. The value 'freetext' indicates that this answer expects a string from the student.
  • correctAnswerRegex is a regular expression to use to check whether or not the student's answer is correct. In constructing a regular expression, consider come situations such as whether or not capitalization in the answer matters and how exact the wording must be. See the Mozilla docs on regular expressions for help.
  • correctAnswerOutput is the text to display when the student's answer is correct. Optional.
  • incorrectAnswerOutput is the text to display when the student's answer is not correct. Optional.
    If you do not supply both correctAnswerOutput and incorrectAnswerOutput, then the code does not display the Check Answer button. If you supply one of these, you must supply both of them.
  • showAnswerOutput is the hint to display if the user clicks on Skip & Show Answer. Optional. If you do not supply this attribute, then the code does not display the Skip & Show Answer button.
  • showAnswerPrompt is the text to display on the Skip & Show Answer button. Optional. If you do not supply this attribute, the text is (unsurprisingly) Skip & Show Answer.
  • outputHeight is the height of the text box to display. Optional; defaults to 50px (a single line of text).

Assessment

The following files render an assessment page:

  • views/base.html defines the header and footer areas. This page is used by all pages displayed to a registered student.
  • views/assessment.html defines the structure of the content area.

We strongly suggest you deploy Course Builder to Google App Engine and create your course in the browser after doing so. This places the course in the Google App Engine datastore. If you wanted to change the assessment questions of the example course on disk, you would change the .js files in the assets/js/ directory.

  • assets/js/assessment-{{SUFFIX}}}.js contains a JavaScript array that fills in the actual question and answer areas for the assessment. Each assessment has its own file.
In the Course Builder code, the example assessments are their own JavaScript file. The filenames have the form assessment-SUFFIX.js. For the sample course SUFFIX is one of Pre, Mid, or Fin. The file contains a single object named assessment. This object describes everything the code needs to know about an assessment. The attributes of the assessment object are as follows:

  • assessmentName. This attribute is optional, since the name will be taken directly from the Title field. The assessmentName attribute is a string containing a unique name for this assessment. The code uses the assessment name to determine what special processing to do for an assessment. The sample course uses "precourse", "midcourse", and "postcourse". See Assessment name.
  • preamble. A string containing text and complete HTML elements. The preamble appears as the first thing on the assessment page. See Preamble.
  • checkAnswers. A Boolean. If True, then students can check their answers before submission. (Note that case is important in this value; it must be either True or False.) See Submitting and checking answers.
  • questionsList. An ordered array, each of whose elements describes a question in the assessment. The questions appear after the preamble. See Questions.

By default, Course Builder has 3 assessments -- a precourse assessment, midterm assessment, and final assessment. The precourse assessment is not included in the overall score for the course.

You can change Course Builder to use more or fewer assessments. To do so, you need to make the following changes:

  1. Create a separate assessment-SUFFIX.js file for each assessment. Using the default suffixes of Pre, Mid, and Fin for those 3 assessments is optional. See Writing assessments for details on creating assessment files. A couple of points:
    • You need the suffix in the next step when updating data/unit.csv to include the new assessment.
    • In each assessment file, you choose a value for the assessmentName attribute. The scoring function in controllers/assessments.py uses these values.
  2. Change data/unit.csv to add your assessments to the appropriate points in your course. See Home page content for details.
  3. Update storeAssessmentData in controllers/assessments.py to consider all assessments when computing the student's overall score for the course. See Scoring.
  4. Update views/student_profile.html to display information about the assessments on the student's profile page. This file identifies which information to display using values supplied by storeAssessmentData. See Modify My Profile Tab.
  5. Update views/test_confirmation.html to display appropriate confirmation messages upon completion of each assessment. This file identifies which message to send using values supplied by storeAssessmentData.

Assessment name

For the sample course, the value of the assessmentName attribute is one of "precourse", "midcourse", or "postcourse". The code in controllers/assessments.py uses assessmentName to determine how to score assessments. See Scoring.

When students complete an assessment, they see a message about how they did. You can change the contents of these messages in views/test_confirmation.html. (See Submitting and checking answers.)

Preamble

The value of the preamble attribute is a string that contains a set of complete HTML elements. That is, if the string contains an open HTML tag (such as <em>), it must also have the corresponding close tag (such as </em>). The code simply renders the HTML you enter as the first thing on the assessment page.

Also note that the entire string must be on a single line. If you want it to render as multiple lines, you must include the appropriate HTML markup.

The following code snippet is a preamble example:

var assessment = {
  preamble: '<b>This assessment addresses content in units 1-6. You can try it as many times as you like. When you click "Check Answers," we will give you your score and give you a list of lessons to review.</b><br>',
  }

Submitting and checking answers

The bottom of an assessment page always includes a Save Answers button. When students submit an assessment by clicking on this button, they see a page such as the following:

By default, this page acknowledges that they submitted the assessment and gives them information about next steps. You can change the messages for different assessments by changing the file at views/test_confirmation.html.

Notice that this page does not tell students how they did on the assessment or give any feedback about what they might want to study some more. You can give students the option of checking their answers before submitting an assessment. If you set the checkAnswers attribute of the assessment object to True, then the assessment page has an additional Check your Answers button and an area for feedback, as shown here:

The feedback contains the student's score. If the student doesn't answer all questions correctly, the code displays which lessons the student should review to improve their score. How you specify this information is discussed in the next section.

The following code snippet is an example of turning on check settings. The boolean value is case sensitive.

var assessment = {
  checkAnswers: true  
  }

Questions

The questionsList attribute is an ordered array of JavaScript objects, each of which describes a question in the assessment.

Each question object has three attributes. Two of these are the same for all question types. Which third attribute you include determines what type of question this is.

The common attributes are:

  • questionHTML. A string containing text and complete HTML elements. This string is the text to display for this question. As with a preamble string, if this string contains an open HTML tag (such as <em>), it must also have the corresponding close tag (such as </em>). Also note that the entire string must be on a single line. If you want it to render as multiple lines, you must include the appropriate HTML markup.
  • lesson. A string representing the lesson (or lessons) that cover the material this question is about. The app displays this string if the student incorrectly answers the question and has requested the app to check answers.

A question can be one of four types, depending on the third attribute:

  • choices. A multiple-choice question. The value of the choices attribute is an array of strings and one function call. Each string represents a possible wrong answer to the question. You specify the correct answer with a function call of the form correct(string), where string is a string containing the correct answer. Students see a set of radio buttons to choose from as with multiple-choice questions in activities.
  • correctAnswerNumeric. A number. For questions with a numeric answer. The value of the attribute is the correct answer.
  • correctAnswerString. A case-insensitive exact string match. For example, if the value is "hello", then Hello and hello are both correct, but HelloWorld is incorrect. Use this attribute when your question requires a specific string answer.
  • correctAnswerRegex. Free text. The value of this attribute is a regular expression capturing the correct answer. Use this attribute when your question is more open ended than a string match can handle. In this case, the code uses a regular expression to verify the answer. Regular expressions can be notoriously difficult for a programmer to get right. For this reason, you need to be very careful with the wording of any question that takes a free text answer. Your regular expression needs to account for reasonable variations in student responses.

The following code snippet is an example of an assessment question.

var assessment = {

  questionsList: [
    {questionHTML: 'Where will the Summer Olympics of 2016 be held?',
     choices: ['Chicago', 'Tokyo', correct('Rio de Janeiro'), 'Madrid', 'I don\'t know'],
     lesson: '1.4'},

  {questionHTML: 'In the 2012 Summer Olympics, who won the women\'s 100 meter gold medal?',
     choices: ['Carmelita Jeter',
               'Veronica Campbell-Brown',
               'Blessing Okagbare',
               correct('Shelly-Ann Fraser-Pryce'),
               "I don't know"],
      lesson: '4.1'},

  {questionHTML: 'You decide to attend the Summer Olympics and find yourself surrounded by Portuguese speakers. How would you say, "Is there a cheap restaurant around here?" in Portuguese?"<br/>[this version of the question uses a case-insensitive string match]',
     correctAnswerString: 'existe um rest?',
     lesson: '4.5'},

  {questionHTML: 'You decide to attend the Summer Olympics and find yourself surrounded by Portuguese speakers. How would you say, "Is there a cheap restaurant around here?" in Portuguese?"<br/>[this version of the question uses a regular expression match]',
     correctAnswerRegex: /existe um rest?/i,
     lesson: '4.5'},

  {questionHTML: 'This is an example of a numeric freetext question. What is 3.2 + 4.7?',
     correctAnswerNumeric: 7.9,
     lesson: '99.99'},  
  ],
}

Scoring

Aspects of scoring for assessments takes place in two places in the code:

  • In assets/lib/activity-generic-1.3.js, checkOrSubmitAnswers determines the score of each assessment. The default formula is simply a percentage of the number of correct answers out of the total number of questions in that assessment.
  • In controllers/assessments.py, storeAssessmentData does a couple of scoring things:
    • It determines when to store an assessment score. By default, it stores the score either if it's the first time the student has taken this assessment or if this score is higher than the previously-stored score.
    • When storing the score for the final assessment of the course, storeAssessmentData also computes the student's score for the entire course. The default scoring for the entire course uses the mid-term assessment as 30% of the score and the final assessment as 70% of the score.

If you want the default scoring and you use the default number of assessments, you do not need to change any code.

If you have a different number of assessments, you should change how storeAssessmentData computes the overall score. Note that storeAssessmentData uses the assessmentName attribute to identify each assessment.

If you want to change the default scoring, you should specify weight directly in the assessment. For multiple choice answers, you can specify the weight of the question as well as the weight of the individual answers by specifying weight with choiceScores. For example, you can give partial credit for one answer while giving full credit for another answer.

  • weight: Indicates the number of points a particular question is worth. The number must be an integer. The default value is 1.
  • choiceScores: Indicates the weights for the answers in a particular answer group. The weights are specified through an array of floating point values between 0.0 and 1.0, inclusive. The individual value of an answer is multiplied by the integer specified in weight.

The following example specifies that the first question is worth five points while the second question is worth six points:

var assessment = {
  questionsList: [
{questionHTML: 'How many total Olympic gold medals has Carl Lewis won?',
     choiceScores: [0.2,0.4,0.6,0.8,1.0],
     weight: 5,
     choices :['4','5','7','8',correct('9')]},

    {questionHTML: 'How many Judo throws are recognized by the Kodokan Judo Institute?',
      choiceScores: [0.0,0.0,0.0,0.8,1.0],
      weight: 4,
      choices :['17','26','33','40',correct('67')]},

    {questionHTML: 'What is the last name of the Women\'s 2010 Winter Olympic snowboard half-pipe gold medal winner?',
     correctAnswerString: 'Bright',
     weight: 5}
  ]
}

Peer Review

You should create peer review assignments the same way you create Assessments.

This section discusses how to write peer reviews if you're editing the files on disk before uploading as well as some legacy settings for older versions of Course Builder. Create peer reviews, whether creating them through the Dashboard (the suggested way) or editing files on disk, as a type of assessment.

For example, here is some sample code for the question (Assessment Content in older Course Builder versions):

var assessment = {
  preamble: 'Solve the problem below by using concepts from at least three Power Search lessons. Record your experience in a Google doc.<br><br><strong>Problem</strong>: Plan a 3-day trip to a destination you have never visited. Where will you go? Why?',

  questionsList: [
    {questionHTML: 'Please write your response in a Google doc, and paste the link to the doc in the answer box below. You will need to ensure that your doc can be viewed by reviewers.',
     correctAnswerRegex: /.*/i
    },

    {questionHTML: 'How many Power Search concepts did you use in your writeup?',
     choices: ['0 - 2', '3', '4 -- 5', 'More than 5']},

    {questionHTML: 'List the Power Search concepts you used.',
     multiLine: true,
     correctAnswerRegex: /.*/i
    },
  ],

  assessmentName: 'ReviewAssessmentExample',
  checkAnswers: false
}

Here is some sample code for the feedback form (Reviewer Feedback Form in older Course Builder versions):

var assessment = {
 
  preamble: 'When you write your review, please check that the student\'s response is relevant to the question asked. If not, answer \'No\' to the first question below.',

  questionsList: [
    {questionHTML: 'Did the student answer all parts of the question?',
     choices: ['Yes', 'No']},

    {questionHTML: 'Please provide feedback for the assignment author.',
     multiLine: true,
     correctAnswerRegex: /.*/i
    }
  ],
  
  assessmentName: 'ReviewAssessmentExample',
  checkAnswers: false
}

In older Course Builder versions you needed to make a change in Assessment Details. This text box conforms to YAML indentation, so you must be careful of errant spaces. Here are the explanation of the keys and their values:

  • grader: by default this value is auto, which means Course Builder will grade it according to the course author's pre-populated answers. The other values is human, which means students will grade the reviews.
  • matcher: the only possible value is peer, which means that assignments will automatically be assigned to a pool.
  • review_due_date: The UTC (coordinated universal time) date, in yyyy-mm-dd hh:mm format, by which the review must be submitted. Reviews in the "draft" state will not count.
  • review_min_count: The minimum number of reviews a student must complete to receive credit for the assignment and to view the reviews they have received. Students can see any of the reviews they receive as soon as they have submitted the number of reviews specified in review_min_count; they do not have to wait for review_due_date.
  • review_window_mins: If a student requests a review and does not submit or put it in draft mode in this number of minutes, the review will return to the pool so that others can request to review it. The review will remain assigned to the original reviewer, however another student may request to review it before the original author gets to it.
  • submission_due_date: The date UTC (coordinated universal time), in yyyy-mm-dd hh:mm format, that the assignment is due. This date must be earlier than the review_due_date.

Here is an example of Assessment Details:

grader: human
matcher: peer
review_due_date: 2014-05-21 12:00
review_min_count: 2
review_window_mins: 60
submission_due_date: 2014-05-14 12:00

Discussion forum

The following files render the discussion page:

  • views/base.html defines the header and footer areas. This page is used by all pages displayed to a registered student.
  • views/forum.html defines the structure of the content area. It also has a link to the discussion forum. You need to change that to the link you create for your forum. See Community Discussion.

Announcements

The followinng files render the announcement page:

  • views/base.html defines the header and footer areas. This page is used by all pages displayed to a registered student.
  • views/announcements.html defines the structure of the content area and contains the actual announcements.

Student profile

The following files render the student profile page:

  • views/base.html defines the header and footer areas. This page is used by all pages displayed to a registered student.
  • views/student_profile.html defines the structure of the content area.
  • views/base_registration.html defines the header and footer areas. This page is used by all pages displayed to an unregistered person.
  • views/unenroll_confirmation_check.html defines the content of the page that asks for confirmation before unenrolling
    views/unenroll_confirmation.html defines the content of the page that confirms the student is actually unenrolled.

Deleting the Course Builder footer text

On Administrator and Dashboard pages, there is footer text that states "Powered by Course Builder." You are not obligated to keep this and you may delete it.

  • For the Administrator page, go to /modules/admin/view.html and delete the text in the HTML.
  • For the Dashboard page, go to /modules/dashboard/view.html and delete the text in the HTML.

Verify Your Code

As discussed on other pages, creating the home page, lessons, activities, and assessments requires you to create CSV files (for the home page and for lessons) and a set of JavaScript files (for activities and for assessments). Course Builder contains a tool that lets you scan these files for broken references and other errors.

Note that this verifier may not catch all errors. It is a first step, to find certain anticipated problems. You should still test your app by visiting the course pages on your local development server and checking that links and input fields work as expected.

Run the verification tool

To run this tool, open a shell or command prompt. In that window:

cd APPPATH
python tools/verify.py

where APPPATH is the directory containing your app.

What it verifies

The verification tool outputs a list of warnings and errors that indicate possible invalid data in the CSV files and incorrectly-formatted activities and assessments. For example, in CSV files it catches incorrectly numbered units or a row containing too many or too few elements.

If the tool runs with no errors, you see output similar to the following:

INFO: Started verification in: /oy/coursebuilder/tools/verify.py
INFO: Loading units from: /oy/coursebuilder/tools/../data/unit.csv
INFO: Loading lessons from: /oy/coursebuilder/tools/../data/lesson.csv
INFO: Unit 1: Pre-course assessment
INFO: Unit 2: Introduction
INFO: Lesson 1: Introduction
INFO: Lesson 2: Filter image results by color
...
INFO: Unit 9: Post-course assessment
INFO: Unit 10: Power Searching with Search Experts Video
INFO: Unit 11: Hang Out with Search Experts Video
INFO: Loading activities:
INFO: Verified activity: /oy/coursebuilder/tools/../assets/js/activity-1.2.js
INFO: Verified activity: /oy/coursebuilder/tools/../assets/js/activity-1.3.js
...
INFO: Verified activity: /oy/coursebuilder/tools/../assets/js/activity-6.3.js
INFO: Read 26 activity files
INFO: Loading assessment:
INFO: Verified assessment /oy/coursebuilder/tools/../assets/js/assessment-Pre.js
INFO: Verified assessment /oy/coursebuilder/tools/../assets/js/assessment-Mid.js
INFO: Verified assessment /oy/coursebuilder/tools/../assets/js/assessment-Fin.js
INFO: Read 3 assessment files
INFO: Read 11 units
INFO: Read 29 lessons
INFO: Completed verification: 0 warnings, 0 errors.

If the tool encounters errors, instead you see output similar to the following:

INFO: Started verification in: /oy/coursebuilder/tools/verify.py
INFO: Loading units from: /oy/coursebuilder/tools/../data/unit.csv
INFO: Loading lessons from: /oy/coursebuilder/tools/../data/lesson.csv
INFO: Unit 1: Pre-course assessment
INFO: Unit 2: Introduction
INFO: Lesson 1: Introduction
INFO: Lesson 2: Filter image results by color
...
INFO: Unit 9: Post-course assessment
INFO: Unit 10: Power Searching with Search Experts Video
INFO: Unit 11: Hang Out with Search Experts Video
WARNING: Unused lesson_id 777 (9.777.Summary)
ERROR: Lesson has unknown unit_id 9 (9.777.Summary)
INFO: Loading activities:
INFO: Verified activity: /oy/coursebuilder/tools/../assets/js/activity-1.2.js
INFO: Verified activity: /oy/coursebuilder/tools/../assets/js/activity-1.3.js
...
INFO: Verified activity: /oy/coursebuilder/tools/../assets/js/activity-6.2.js
ERROR: Missing activity: /oy/coursebuilder/tools/../assets/js/activity-9.777.js
INFO: Read 26 activity files
INFO: Loading assessment:
INFO: Verified assessment /oy/coursebuilder/tools/../assets/js/assessment-Pre.js
ERROR: Unable to parse assessment in file /oy/coursebuilder/tools/../assets/js/assessment-Mid.js
1:
2:
...
20: blah blah blah
21:
22: assessment = {
...
64: assessmentName: 'midcourse',
...
ERROR: <type 'exceptions.SyntaxError'>
ERROR: invalid syntax (<string>, line 20)
ERROR: <traceback object at 0x1ef5680>
INFO: Verified assessment /oy/coursebuilder/tools/../assets/js/assessment-Fin.js
INFO: Read 3 assessment files
INFO: Read 11 units
INFO: Read 29 lessons
INFO: Completed verification: 1 warnings, 7 errors.

You can go back and fix the errors, and run the verifier again after you finish.

Ask questions in the forum

Powered by Google Project Hosting