text:
// Copyright 2014 The Oppia Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS-IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview These functions are used to build defaultData.js. In future
    they should be made available to exploration editors to change the data
    used in an instance of the LogicProof interaction.
 * @author Jacob Davis (jacobdavis11@gmail.com)
 */

var logicProofTeacher2 = (function() {
  // LINE TEMPLATES

  // Ensures that lineTemplate has all its operators of a matchable kind
  // occuring in a non-substituted instance so that matching a line against
  // the template will be possible, and that all other operators occur in the
  // given list. Also checks line_template is well-typed.
  var requireValidLineTemplate = function(lineTemplate, language, vocabulary) {
    // Collect expressionTemplates to check.
    var expressionTemplates = [];

    // Counts the number of expressionTemplates for which values are actually
    // provided by the student (i.e. those in the 'reader_view' entry.)
    var numAccessible = 0;
    for (var i = 0; i < lineTemplate.reader_view.length; i++) {
      if (lineTemplate.reader_view[i].format === 'expression') {
        expressionTemplates.push(lineTemplate.reader_view[i].content);
        numAccessible++;
      }
    }
    for (var i = 0; i < lineTemplate.antecedents.length; i++) {
      expressionTemplates.push(lineTemplate.antecedents[i]);
    }
    for (var i = 0; i < lineTemplate.results.length; i++) {
      expressionTemplates.push(lineTemplate.results[i]);
    }
    if (lineTemplate.hasOwnProperty('error')) {
      for (var j = 0; j < lineTemplate.error.length; j++) {
        for (var i = 0; i < lineTemplate.error[j].length; i++) {
          if (lineTemplate.error[j][i].format === 'expression') {
            expressionTemplates.push(lineTemplate.error[j][i].content);
          }
        }
      }
    }
    // Collect expressions to check.
    // 'visible' expressions are those occurring in the reader_view line with no
    // substitutions performed on them, and which are thus available to help
    // determine what the variables and atoms have been instantiated as when
    // matching against a student's line. The others are all 'invisible'. We
    // require that any element occurring invisibly also occurs visibly, so
    // that it will be possible to determine its instantiation just from what
    // the student types.
    var checkees = [];
    var types = [];
    var visible = [];
    var invisible = [];
    for (var i = 0; i < expressionTemplates.length; i++) {
      checkees.push(expressionTemplates[i].expression);
      types.push(expressionTemplates[i].type);
      if (expressionTemplates[i].substitutions.length === 0 &&
          i < numAccessible) {
        visible.push(expressionTemplates[i].expression);
      } else {
        invisible.push(expressionTemplates[i].expression);
      }
      for (var j = 0; j < expressionTemplates[i].substitutions.length; j++) {
        for (var key in expressionTemplates[i].substitutions[j]) {
          var LHS = {
            top_operator_name: key,
            top_kind_name: 'variable',
            arguments: [],
            dummies: []
          };
          var RHS = expressionTemplates[i].substitutions[j][key];
          checkees.push(LHS);
          types.push('element');
          checkees.push(RHS);
          types.push('element');
          invisible.push(LHS);
          if (i < numAccessible) {
            // FUTURE (Jacob): change back to visible (for single
            // substitutions) after writing seekSubstitute.
            invisible.push(RHS);
          } else {
            invisible.push(RHS);
          }
        }
      }
    }
    for (var i = 0; i < lineTemplate.variables.length; i++) {
      checkees.push(lineTemplate.variables[i]);
      types.push('element');
      invisible.push(lineTemplate.variables[i]);
    }

    // 1. Vocab checking
    requireNoWordsUsed(checkees, language.operators, vocabulary);
    // 2. Type checking
    var typeCheck = logicProofShared.assignTypesToExpressionArray(
      checkees, types, language, ['variable', 'atom'], true);
    if (typeCheck.length > 1) {
      throw new logicProofShared.UserError('ambiguous_typing', {});
    }
    // 3. Matchability checking
    var visibleOperators = logicProofShared.getOperatorsFromExpressionArray(
      visible);
    var hiddenOperators = logicProofShared.getOperatorsFromExpressionArray(
      invisible);
    for (var i = 0; i < hiddenOperators.length; i++) {
      if (!language.operators.hasOwnProperty(hiddenOperators[i]) &&
          visibleOperators.indexOf(hiddenOperators[i]) === -1) {
        throw new logicProofShared.UserError('hidden_operator', {
          operator: hiddenOperators[i]
        });
      }
    }
  };

  /**
   * @param {string} nameString - The name of the template, provided by the
   *        teacher.Multiple templates can have the same name. These names are
   *        then available to refer to in the MistakeTable.
   * @param {string} readerViewString - A string from the teacher that describes
   *        what lines of this form should look like when the student writes
   *        them.
   * @param {string} antecedentsString - A string from the teacher describing
   *        the antecedents a line of this form should have. These can then be
   *        referred to in the MistakeTable to check, for example, that every
   *        antecedent needed was proved on an earlier line.
   * @param {string} resultsString - Similar
   * @param {string} variablesString - Similar
   * @param {Array.<String>} errorStrings - If this LineTemplate is an instance
   *        of an incorrect deduction then the teacher supplies a list of
   *        possible critiques to show to the student. They are supplied as
   *        strings which here will be converted into LineMessages.
   * @param {Language} language - A Language object, giving the student's
   *        language.
   * @param {Vocabulary} vocabulary - A Vocabulary object giving the phrases
   *        that can be used within lines (so here within the readerViewString)
   * @return {LineTemplate}
   * @throws If the strings cannot be parsed, or the expressions in them are
   *         incorrectly typed, or they contain words reserved for use in
   *         phrases, or there is a an expression (generally in the results,
   *         antecendents or variables) that it will not be possible to deduce
   *         from what the student is required to write.
   */
  var buildLineTemplate = function(nameString, readerViewString,
      antecedentsString, resultsString, variablesString, errorStrings,
      language, vocabulary) {
    var possibleReaderViews = logicProofShared.parseLineString(
      readerViewString, language.operators, vocabulary, true);
    if (possibleReaderViews.length > 1) {
      throw new logicProofShared.UserError('ambiguous_parsing', {
        field: 'reader view'
      });
    }
    readerView = possibleReaderViews[0];
    try {
      var antecedents = logicProofParser.parse(
        antecedentsString.replace(/ /g, ''), 'listOfBooleanTemplates');
    } catch (err) {
      throw new logicProofShared.UserError('unparseable', {
        field: 'antecedents'
      });
    }
    try {
      var results = logicProofParser.parse(
        resultsString.replace(/ /g, ''), 'listOfBooleanTemplates');
    } catch (err) {
      throw new logicProofShared.UserError('unparseable', {
        field: 'results'
      });
    }
    try {
      var variables = logicProofParser.parse(
        variablesString.replace(/ /g, ''), 'listOfVariables');
    } catch (err) {
      throw new logicProofShared.UserError('unparseable', {
        field: 'variables'
      });
    }
    var errors = [];
    for (var i = 0; i < errorStrings.length; i++) {
      errors.push(parseMessage(errorStrings[i], 'line'));
    }
    var lineTemplate = {
      name: nameString,
      reader_view: readerView,
      antecedents: antecedents,
      results: results,
      variables: variables,
      error: errors
    };
    requireValidLineTemplate(lineTemplate, language, vocabulary);
    return lineTemplate;
  };

  var displayExpressionTemplate = function(template, operators) {
    var output = logicProofShared.displayExpression(
      template.expression, operators);
    for (var i = 0; i < template.substitutions.length; i++) {
      var newOutput = [];
      for (key in template.substitutions[i]) {
        newOutput.push(key + '->' + logicProofShared.displayExpression(
          template.substitutions[i][key], operators, 0));
      }
      output = output + '[' + newOutput.join(', ') + ']';
    }
    return output;
  };

  var displayExpressionTemplateArray = function(array, operators) {
    var displayedArray = [];
    for (var i = 0; i < array.length; i++) {
      displayedArray.push(displayExpressionTemplate(array[i], operators));
    }
    return displayedArray.join(', ');
  };

  // The template as seen by the teacher
  var displayLineFragmentTemplate = function(template, operators, vocabulary) {
    if (template.format === 'phrase') {
      return vocabulary[template.content][0];
    } else if (template.content.type === 'element') {
      return template.content.hasOwnProperty('kind') ?
        '{{' + displayExpressionTemplate(template.content, operators) +
          '|variable}}' :
        '{{' + displayExpressionTemplate(template.content, operators) +
          '|element}}';
    } else {
      return displayExpressionTemplate(template.content, operators);
    }
  };

  // Just gives the 'reader_view' part of the template, not the other
  // parameters like antecedents
  var displayLineTemplateReaderView = function(
      readerView, operators, vocabulary) {
    var displayedFragments = [];
    for (i = 0; i < readerView.length; i++) {
      displayedFragments.push(displayLineFragmentTemplate(
        readerView[i], operators, vocabulary));
    }
    return displayedFragments.join(' ');
  };

  // The message as seen by the teacher
  var displayMessage = function(message, operators) {
    var output = '';
    for (i = 0; i < message.length; i++) {
      if (message[i].format === 'expression') {
        if (message[i].content.type === 'element') {
          output += (message[i].content.hasOwnProperty('kind') ?
            '{{' + displayExpressionTemplate(message[i].content, operators) +
              '|variable}}' :
            '{{' + displayExpressionTemplate(message[i].content, operators) +
              '|element}}');
        } else {
          output += (
            '{{' + displayExpressionTemplate(message[i].content, operators) +
            '}}');
        }
      } else {
        output = output + message[i].content;
      }
    }
    return output;
  };

  var displayLineTemplate = function(template, operators, vocabulary) {
    var displayedMessages = [];
    for (var i = 0; i < template.error.length; i++) {
      displayedMessages.push(displayMessage(template.error[i], operators));
    }
    return {
      name: template.name,
      reader_view: displayLineTemplateReaderView(
        template.reader_view, operators, vocabulary),
      antecedents: displayExpressionTemplateArray(
        template.antecedents, operators),
      results: displayExpressionTemplateArray(
        template.results, operators),
      variables: logicProofShared.displayExpressionArray(
        template.variables, operators),
      error: displayedMessages
    };
  };

  /**
   * @param {Array} stringTable - an array of dictionaries of the form {
   *          name: a string from the teacher giving the name
   *          reader_view: likewise
   *          antecedents: likewise
   *          results: likewise
   *          variables: likewise
   *          error: an array of strings
   *        }
   * @param {Vocabulary} vocabulary - a Vocabulary object
   * @return {Array.<LineTemplate>} An array of LineTemplates
   * @throws If any line makes an error in buildLineTemplate() then we throw an
   *         array of the error messages for each line (blank if a line is
   *         fine).
   */
  var buildLineTemplateTable = function(stringTable, vocabulary) {
    var table = [];
    var failed = false;
    var failures = [];
    for (var i = 0; i < stringTable.length; i++) {
      try {
        table.push(
          buildLineTemplate(
            stringTable[i].name, stringTable[i].reader_view,
            stringTable[i].antecedents, stringTable[i].results,
            stringTable[i].variables, stringTable[i].error,
            logicProofData.BASE_STUDENT_LANGUAGE, vocabulary));
        failures.push('');
      } catch (err) {
        failed = true;
        failures.push(
          logicProofShared.renderError(
            err, logicProofTeacher.TEACHER_ERROR_MESSAGES,
            logicProofData.BASE_STUDENT_LANGUAGE));
      }
    }
    if (failed) {
      throw failures;
    } else {
      return table;
    }
  };

  var displayLineTemplateTable = function(table, vocabulary) {
    var output = [];
    for (var i = 0; i < table.length; i++) {
      output.push(
        displayLineTemplate(
          table[i],
          logicProofData.BASE_STUDENT_LANGUAGE.operators,
          vocabulary));
    }
    return output;
  };

  // MISTAKE TABLE

  /**
   * @param {MistakeEntry variation} mistakeEntry - a MistakeEntry object (but
   *        with Expressions in place of TypedExpressions) which we are to
   *        check and assign types to.
   * @param {Language} language - a Language object giving the control language.
   * @return {MistakeEntry} a proper MistakeEntry object, with
   *         TypedExpressions.
   * @throws if the mistake entry contains incorrect typings.
   */
  var validateAndTypeMistakeEntry = function(mistakeEntry, language) {
    var availableOperators = [];
    for (key in language.operators) {
      availableOperators[key] = language.operators[key];
    }
    // This is available to refer to the line number
    availableOperators.n = {
      kind: 'variable',
      typing: [{
        arguments: [],
        dummies: [],
        output: 'integer'
      }]
    };
    newLanguage = {
      operators: availableOperators,
      types: language.types,
      kinds: language.kinds
    };
    // Other than the line number, no new operators can be used.
    var typeCheck = logicProofShared.assignTypesToExpression(
      mistakeEntry.occurs, ['boolean'], newLanguage, ['constant']);
    if (typeCheck.length > 1) {
      throw new logicProofShared.UserError('ambiguous_typing', {});
    }
    mistakeEntry.occurs = typeCheck[0].typedExpression;
    for (var i = 0; i < mistakeEntry.message.length; i++) {
      for (var j = 0; j < mistakeEntry.message[i].length; j++) {
        if (mistakeEntry.message[i][j].format === 'expression') {
          var expression = mistakeEntry.message[i][j].content;
          var typeCheck = logicProofShared.assignTypesToExpression(
            expression,
            ['integer', 'string', 'formula', 'set_of_formulas', 'boolean'],
            newLanguage, ['constant']);
          if (typeCheck.length > 1) {
            throw new logicProofShared.UserError('ambiguous_typing', {});
          }
          mistakeEntry.message[i][j].content = typeCheck[0].typedExpression;
        }
      }
    }
    return mistakeEntry;
  };

  /**
   * @param {string} nameString - A string provided by the teacher giving the
   *        name of the entry; this is not used for anything but is convenient
   *        for the teacher when writing the table.
   * @param {string} occursString - A string from the teacher that represents
   *        an expression in the control language determining whether the
   *        mistake has been made by the student.
   * @param {Array.<string>} messageStrings - An array of string written by the
   *        teacher, each of which represents a possible message to give the
   *        student if they make the mistake in question.
   * @param {Language} controlLanguage - A Language object giving the control
   *        language (that which is used to write formulas describing when
   *        mistakes occur).
   * @returns {MistakeEntry}
   * @throws If the inputs are unparseable or badly typed.
   */
  var buildMistakeEntry = function(
      nameString, occursString, messageStrings, controlLanguage) {
    try {
      var occurs = logicProofParser.parse(
        occursString.replace(/ /g, ''), 'expression');
    } catch (err) {
      throw new logicProofShared.UserError('unparseable', {
        field: 'description of when this mistake occurs'
      });
    }
    var messages = [];
    for (var i = 0; i < messageStrings.length; i++) {
      messages.push(parseMessage(messageStrings[i], 'control'));
    }
    var mistakeEntry = {
      name: nameString,
      occurs: occurs,
      message: messages
    };
    return validateAndTypeMistakeEntry(mistakeEntry, controlLanguage);
  };

  // The teacher's version; the operators should be those from the control
  // language.
  var displayControlMessage = function(message, operators) {
    var output = '';
    for (var i = 0; i < message.length; i++) {
      if (message[i].format === 'string') {
        output += message[i].content;
      } else {
        output += '{{' +
          logicProofShared.displayExpression(message[i].content, operators) +
          '}}';
      }
    }
    return output;
  };

  var displayMistakeEntry = function(mistakeEntry, operators) {
    var displayedMessages = [];
    for (var i = 0; i < mistakeEntry.message.length; i++) {
      displayedMessages.push(
        displayControlMessage(mistakeEntry.message[i], operators));
    }
    return {
      name: mistakeEntry.name,
      occurs: logicProofShared.displayExpression(
        mistakeEntry.occurs, operators),
      message: displayedMessages
    };
  };

  /**
   * @param {string} name - the name of the section (e.g. layout, target)
   * @param {Array.<object>} entryStrings - an array of dictionaries of the
   *        form: {
   *          name: name string,
   *          occurs: occurs string,
   *          message: an array of message strings
   *        }
   * @param {Array} controlFunctions
   * @return {MistakeSection}
   * @throws an array of error messages, one per entry.
   */
  var buildMistakeSection = function(name, entryStrings, controlFunctions) {
    var controlLanguage = angular.copy(logicProofData.BASE_CONTROL_LANGUAGE);
    for (var i = 0; i < controlFunctions.length; i++) {
      controlLanguage.operators[controlFunctions[i].name] = {
        kind: 'prefix_function',
        typing: controlFunctions[i].typing
      };
    }

    var failed = false;
    var failures = [];
    var entries = [];
    for (var i = 0; i < entryStrings.length; i++) {
      try {
        entries.push(
          buildMistakeEntry(
            entryStrings[i].name, entryStrings[i].occurs,
            entryStrings[i].message, controlLanguage));
        failures.push('');
      } catch (err) {
        failed = true;
        failures.push(
          logicProofShared.renderError(
            err, logicProofTeacher.TEACHER_ERROR_MESSAGES, controlLanguage));
      }
    }
    if (failed) {
      throw failures;
    } else {
      return {
        name: name,
        entries: entries
      };
    }
  };

  var displayMistakeSection = function(mistakeSection, operators) {
    var displayedEntries = [];
    for (var i = 0; i < mistakeSection.entries.length; i++) {
      displayedEntries.push(
        displayMistakeEntry(mistakeSection.entries[i], operators));
    }
    return {
      name: mistakeSection.name,
      entries: displayedEntries
    };
  };

  var displayMistakeTable = function(mistakeTable) {
    var displayedSections = [];
    for (var i = 0; i < mistakeTable.length; i++) {
      displayedSections.push(
        displayMistakeSection(
          mistakeTable[i], logicProofData.BASE_CONTROL_LANGUAGE.operators));
    }
    return displayedSections;
  };

  // CONTROL FUNCTIONS

  /**
   * @param {Expression} formulaLHS - an Expression representing the
   *        left-hand-side of the definition of a formula - e.g. f(n,m).
   * @param {Expression} formulaRHS - an Expression representing the
   *        right-hand-side of such a definition - e.g. n + g(m).
   * @param {Language} language - a Language object representing the control
   *        language (the one used to describe when a student has made a
   *        mistake) including all of the previously-defined control functions.
   * @returns {Object} with the following keys:
   *   - typing: a length-1 array of the TypingRule that the function being
   *       defined has been deduced to have.
   *   - typedDefinition: a TypedExpression that is the given formulaRHS but
   *       now with types added.
   * @throws If the teacher makes a mistake such as re-using a function name or
   *         assigning invalid types.
   */
  var validateAndTypeControlFunction = function(
      formulaLHS, formulaRHS, language) {
    if (language.operators.hasOwnProperty(formulaLHS.top_operator_name)) {
      throw new logicProofShared.UserError('duplicate_function_name', {
        function: formulaLHS.top_operator_name
      });
    }
    if (formulaLHS.top_operator_name === 'n') {
      throw new logicProofShared.UserError('function_name_is_n', {});
    }

    var availableOperators = {};
    for (var key in language.operators) {
      availableOperators[key] = language.operators[key];
    }
    for (var i = 0; i < formulaLHS.arguments.length; i++) {
      if (language.operators.hasOwnProperty(
          formulaLHS.arguments[i].top_operator_name)) {
        throw new logicProofShared.UserError(
          'argument_is_function_name', {
            argument: formulaLHS.arguments[i].top_operator_name
          });
      } else if (availableOperators.hasOwnProperty(
          formulaLHS.arguments[i].top_operator_name)) {
        throw new logicProofShared.UserError(
          'duplicate_argument', {
            argument: formulaLHS.arguments[i].top_operator_name
          });
      } else if (
          logicProofShared.getOperatorsFromExpression(formulaRHS).indexOf(
            formulaLHS.arguments[i].top_operator_name) === -1) {
        throw new logicProofShared.UserError(
          'unused_argument', {
            argument: formulaLHS.arguments[i].top_operator_name
          });
      } else {
        availableOperators[formulaLHS.arguments[i].top_operator_name] = {
          kind: 'variable',
          // We can't tell the types of the arguments yet, but they should be
          // deducible from the RHS.
          typing: [{
            arguments: [],
            dummies: [],
            output: 'integer'
          }, {
            arguments: [],
            dummies: [],
            output: 'string'
          }, {
            arguments: [],
            dummies: [],
            output: 'formula'
          }, {
            arguments: [],
            dummies: [],
            output: 'set_of_formulas'
          }]
        };
      }
    }
    // The RHS cannot use any operator not found on the LHS or in the given list
    var typeCheck = logicProofShared.assignTypesToExpression(formulaRHS, [
      'boolean', 'integer', 'string', 'formula', 'set_of_formulas'
    ], {
      operators: availableOperators,
      kinds: language.kinds,
      types: language.types
    }, ['constant']);
    if (typeCheck.length > 1) {
      throw new logicProofShared.UserError('ambiguous_typing', {});
    }
    // Now we can work out what the typing of the formula actually is
    var argumentTypes = [];
    for (var i = 0; i < formulaLHS.arguments.length; i++) {
      argumentTypes.push({
        type: logicProofShared.seekTypeInExpression(
          typeCheck[0].typedExpression,
          formulaLHS.arguments[i].top_operator_name),
        arbitrarily_many: false
      });
    }
    return {
      typing: [{
        arguments: argumentTypes,
        dummies: [],
        output: typeCheck[0].typedExpression.type
      }],
      typedDefinition: typeCheck[0].typedExpression
    };
  };

  /**
   * @param {string} LHSstring - a string from the teacher representing the
   *        left-hand-side of the function definition.
   * @param {string} RHSstring - likewise for the right-hand-side.
   * @param {string} descriptionString - a description of what the function is
   *        supposed to mean; this is not used by the code but is convenient
   *        for the user.
   * @param {Language} controlLanguage - a Language object representing the
   *        language used to write descriptions of mistakes, and also functions
   *        such as these that help to describe mistakes.
   * @return {object} a dictionary {
   *            name: the name of the function, deduced from the LHSstring
   *            variables: the free variables in the function definition,
   *              deduced from the LHSstring.
   *            typing: a length-1 array of the TypingRule for the new function
   *            definition: a TypedExpression deduced from the RHSstring, but
   *              with types added
   *            description: the descriptionString
   *          }
   * @throws If the input cannot be parsed, or is incorrect as in
   *         validateAndTypeControlFunction().
   */
  var buildControlFunction = function(
      LHSstring, RHSstring, descriptionString, controlLanguage) {
    try {
      var formulaLHS = logicProofParser.parse(
        LHSstring.replace(/ /g, ''), 'formulaLHS');
    } catch (err) {
      throw new logicProofShared.UserError('unparseable', {
        field: 'left-hand side'
      });
    }
    try {
      var formulaRHS = logicProofParser.parse(
        RHSstring.replace(/ /g, ''), 'expression');
    } catch (err) {
      throw new logicProofShared.UserError('unparseable', {
        field: 'right-hand side'
      });
    }
    var validation = validateAndTypeControlFunction(
      formulaLHS, formulaRHS, controlLanguage);
    return {
      name: formulaLHS.top_operator_name,
      variables: formulaLHS.arguments,
      typing: validation.typing,
      definition: validation.typedDefinition,
      description: descriptionString
    };
  };

  /**
   * @param {object} controlFunction - a dictionary such as
   *        buildControlFunction() returns
   * @param {object} operators - the operators key from the control language
   * @return {
   *   LHS: the left-hand side of the formula
   *   RHS: the right-hand side
   *   description: the description
   * }
   */
  var displayControlFunction = function(controlFunction, operators) {
    var LHSExpression = {
      top_kind_name: 'prefix_function',
      top_operator_name: controlFunction.name,
      arguments: controlFunction.variables,
      dummies: []
    };
    return {
      LHS: logicProofShared.displayExpression(LHSExpression, operators),
      RHS: logicProofShared.displayExpression(
        controlFunction.definition, operators),
      description: controlFunction.description
    };
  };

  /**
   * We got through the list of control functions in turn, validating them and
   * adding them to to the list of operators and model; if one fails validation
   * we abort.
   * @param {Array.<object>} controlFunctionStrings - an array of dictionaries
   *        of the form {
   *          LHS: string representing the function LHS,
   *          RHS: string representing the function RHS,
   *          description: string describing the function
   *        }
   * @return {Array.<object>} an array of dictionaries of the kind
   *         buildControlFunction returns
   * @throws the first Error found in the table, with an additonal key 'line'
   *         that gives the number of the line in the table where this error
   *         occurred.
   */
  var buildControlFunctionTable = function(controlFunctionStrings) {
    // Copy the old control operators and model.
    var operators = {};
    for (var key in logicProofData.BASE_CONTROL_LANGUAGE.operators) {
      operators[key] = logicProofData.BASE_CONTROL_LANGUAGE.operators[key];
    }
    var controlLanguage = {
      types: logicProofData.BASE_CONTROL_LANGUAGE.types,
      kinds: logicProofData.BASE_CONTROL_LANGUAGE.kinds,
      operators: operators
    };
    var table = [];

    for (var i = 0; i < controlFunctionStrings.length; i++) {
      try {
        var built = buildControlFunction(
          controlFunctionStrings[i].LHS, controlFunctionStrings[i].RHS,
          controlFunctionStrings[i].description, controlLanguage);
      } catch (err) {
        throw {
          message: logicProofShared.renderError(
            err, logicProofTeacher.TEACHER_ERROR_MESSAGES,
            logicProofData.BASE_CONTROL_LANGUAGE),
          line: i
        };
      }
      controlLanguage.operators[built.name] = {
        kind: 'prefix_function',
        typing: built.typing
      };
      table.push(built);
    }
    return table;
  };

  var displayControlFunctionTable = function(table) {
    var displayedEntries = [];
    for (var i = 0; i < table.length; i++) {
      displayedEntries.push(displayControlFunction(
        table[i], logicProofData.BASE_CONTROL_LANGUAGE.operators));
    }
    return displayedEntries;
  };

  // UTILITIES

  var parseMessageStringFragment = function(fragmentString, typeOfMessage) {
    return (typeOfMessage === 'general') ? {
      isFixed: true,
      content: fragmentString
    } : {
      format: 'string',
      content: fragmentString
    };
  };

  var parseMessageParameterFragment = function(fragmentString, typeOfMessage) {
    if (typeOfMessage === 'general') {
      return {
        isFixed: false,
        content: fragmentString.slice(2, fragmentString.length - 2)
      };
    } else {
      try {
        return {
          format: 'expression',
          content: (typeOfMessage === 'line') ?
            logicProofParser.parse(
              fragmentString.replace(/ /g, ''), 'expressionTemplate2') :
            logicProofParser.parse(
              fragmentString.slice(2, fragmentString.length - 2).replace(
                / /g, ''),
              'expression')
        };
      } catch (err) {
        throw new logicProofShared.UserError('unparseable_fragment', {
          fragment: fragmentString
        });
      }
    }
  };

  var parseMessage = function(messageString, typeOfMessage) {
    var message = [];
    var index = 0;
    while (index < messageString.length) {
      if (messageString.slice(index, index + 2) === '{{') {
        var newIndex = messageString.indexOf('}}', index) + 2;
        if (newIndex === 1) {
          throw new logicProofShared.UserError('unmatched_{{', {});
        }
        if (messageString[newIndex] === '}') {
          newIndex++;
        }
        message.push(
          parseMessageParameterFragment(
            messageString.slice(index, newIndex), typeOfMessage));
      } else {
        var newIndex = messageString.indexOf('{{', index);
        var newIndex = (newIndex === -1) ? messageString.length : newIndex;
        message.push(
          parseMessageStringFragment(
            messageString.slice(index, newIndex), typeOfMessage));
      }
      index = newIndex;
    }
    return message;
  };

  // Checks that a given expression array contains any multi-character words
  // that are used in phrases; if so it throws an error.
  var requireNoWordsUsed = function(
      expressionArray, knownOperators, vocabulary) {
    var vocabularyWords = [];
    for (var key in vocabulary) {
      for (var i = 0; i < vocabulary[key].length; i++) {
        for (var j = 0; j < vocabulary[key][i].split(' ').length; j++) {
          if (vocabularyWords.indexOf(
                vocabulary[key][i].split(' ')[j]) === -1) {
            vocabularyWords.push(vocabulary[key][i].split(' ')[j]);
          }
        }
      }
    }
    var operatorsToCheck = logicProofShared.getOperatorsFromExpressionArray(
      expressionArray);
    for (var i = 0; i < operatorsToCheck.length; i++) {
      if (vocabularyWords.indexOf(operatorsToCheck[i]) !== -1 &&
          operatorsToCheck[i].length > 1 &&
          !knownOperators.hasOwnProperty(operatorsToCheck[i])) {
        throw new logicProofShared.UserError('forbidden_word', {
          word: operatorsToCheck[i]
        });
      }
    }
  };

  return {
    buildLineTemplate: buildLineTemplate,
    displayLineTemplate: displayLineTemplate,
    buildLineTemplateTable: buildLineTemplateTable,
    displayLineTemplateTable: displayLineTemplateTable,
    buildMistakeEntry: buildMistakeEntry,
    displayControlMessage: displayControlMessage,
    displayMistakeEntry: displayMistakeEntry,
    buildMistakeSection: buildMistakeSection,
    displayMistakeSection: displayMistakeSection,
    displayMistakeTable: displayMistakeTable,
    buildControlFunction: buildControlFunction,
    displayControlFunction: displayControlFunction,
    buildControlFunctionTable: buildControlFunctionTable,
    displayControlFunctionTable: displayControlFunctionTable,
    parseMessage: parseMessage
  };
})();


text:
package com.helger.xml.xpath;

import java.util.Map;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;
import javax.xml.namespace.QName;
import javax.xml.xpath.XPathVariableResolver;

import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.collection.impl.CommonsHashMap;
import com.helger.commons.collection.impl.ICommonsMap;
import com.helger.commons.equals.EqualsHelper;
import com.helger.commons.hashcode.HashCodeGenerator;
import com.helger.commons.lang.ICloneable;
import com.helger.commons.state.EChange;
import com.helger.commons.string.ToStringGenerator;

/**
 * Class is used in conjunction with {@link javax.xml.xpath.XPathExpression} to
 * resolve variable values used in XPath queries at runtime. The local part of
 * the QName to resolve is used as the key in the map. The namespace is ignored
 * in this class.
 *
 * @author Philip Helger
 * @see MapBasedXPathVariableResolverQName
 */
@NotThreadSafe
public class MapBasedXPathVariableResolver implements XPathVariableResolver, ICloneable <MapBasedXPathVariableResolver>
{
  private final ICommonsMap <String, Object> m_aMap;

  /**
   * Default ctor.
   */
  public MapBasedXPathVariableResolver ()
  {
    this ((Map <String, ?>) null);
  }

  /**
   * Ctor taking another map.
   *
   * @param aVars
   *        Variables to re-use. May be null.
   */
  public MapBasedXPathVariableResolver (@Nullable final Map <String, ?> aVars)
  {
    m_aMap = new CommonsHashMap <> (aVars);
  }

  /**
   * Copy constructor
   *
   * @param aOther
   *        Object to copy data from
   */
  public MapBasedXPathVariableResolver (@Nonnull final MapBasedXPathVariableResolver aOther)
  {
    ValueEnforcer.notNull (aOther, "Other");
    m_aMap = aOther.m_aMap.getClone ();
  }

  /**
   * Add a new variable.
   *
   * @param sName
   *        The name (=local part) of the variable
   * @param aValue
   *        The value to be used.
   * @return {@link EChange}
   */
  @Nonnull
  public EChange addUniqueVariable (@Nonnull final String sName, @Nonnull final Object aValue)
  {
    ValueEnforcer.notNull (sName, "Name");
    ValueEnforcer.notNull (aValue, "Value");

    if (m_aMap.containsKey (sName))
      return EChange.UNCHANGED;
    m_aMap.put (sName, aValue);
    return EChange.CHANGED;
  }

  /**
   * Add all variables from the other variable resolver into this resolver.
   *
   * @param aOther
   *        The variable resolver to import the variable from. May not be
   *        null.
   * @param bOverwrite
   *        if true existing variables will be overwritten with the
   *        new variables, otherwise the old variables are kept.
   * @return {@link EChange}
   */
  @Nonnull
  public EChange addAllFrom (@Nonnull final MapBasedXPathVariableResolver aOther, final boolean bOverwrite)
  {
    ValueEnforcer.notNull (aOther, "Other");
    EChange eChange = EChange.UNCHANGED;
    for (final Map.Entry <String, Object> aEntry : aOther.m_aMap.entrySet ())
      if (bOverwrite || !m_aMap.containsKey (aEntry.getKey ()))
      {
        m_aMap.put (aEntry.getKey (), aEntry.getValue ());
        eChange = EChange.CHANGED;
      }
    return eChange;
  }

  /**
   * Add all variables from the other variable resolver into this resolver. This
   * methods takes only the local part of the QName and loses the namespace URI.
   *
   * @param aOther
   *        The variable resolver to import the variable from. May not be
   *        null.
   * @param bOverwrite
   *        if true existing variables will be overwritten with the
   *        new variables, otherwise the old variables are kept.
   * @return {@link EChange}
   */
  @Nonnull
  public EChange addAllFrom (@Nonnull final MapBasedXPathVariableResolverQName aOther, final boolean bOverwrite)
  {
    ValueEnforcer.notNull (aOther, "Other");
    EChange eChange = EChange.UNCHANGED;
    for (final Map.Entry <QName, ?> aEntry : aOther.getAllVariables ().entrySet ())
    {
      // QName to local part only
      final String sKey = aEntry.getKey ().getLocalPart ();
      if (bOverwrite || !m_aMap.containsKey (sKey))
      {
        m_aMap.put (sKey, aEntry.getValue ());
        eChange = EChange.CHANGED;
      }
    }
    return eChange;
  }

  /**
   * Remove the variable with the specified name.
   *
   * @param sName
   *        The name to be removed. May be null.
   * @return {@link EChange}
   */
  @Nonnull
  public EChange removeVariable (@Nullable final String sName)
  {
    if (sName == null)
      return EChange.UNCHANGED;
    return m_aMap.removeObject (sName);
  }

  /**
   * Remove multiple variables at once.
   *
   * @param aNames
   *        The names to be removed. May be null.
   * @return {@link EChange#CHANGED} if at least one variable was removed.
   */
  @Nonnull
  public EChange removeVariables (@Nullable final Iterable <String> aNames)
  {
    EChange eChange = EChange.UNCHANGED;
    if (aNames != null)
      for (final String sName : aNames)
        eChange = eChange.or (removeVariable (sName));
    return eChange;
  }

  /**
   * @return A mutable copy of all contained variables. Never null
   *         but maybe empty.
   */
  @Nonnull
  @ReturnsMutableCopy
  public ICommonsMap <String, ?> getAllVariables ()
  {
    return m_aMap.getClone ();
  }

  /**
   * @return The number of contained variables. Always ≥ 0.
   */
  @Nonnegative
  public int getVariableCount ()
  {
    return m_aMap.size ();
  }

  /**
   * Remove all variables at once.
   *
   * @return {@link EChange#CHANGED} if at least one variable was removed.
   */
  @Nonnull
  public EChange clear ()
  {
    return m_aMap.removeAll ();
  }

  /**
   * Set multiple variables at once.
   *
   * @param aVars
   *        The variables to be set. May be null.
   */
  public void setAllVariables (@Nullable final Map <String, ?> aVars)
  {
    m_aMap.setAll (aVars);
  }

  @Nullable
  public Object resolveVariable (@Nonnull final QName aVariableName)
  {
    ValueEnforcer.notNull (aVariableName, "VariableName");

    final String sLocalName = aVariableName.getLocalPart ();
    return m_aMap.get (sLocalName);
  }

  @Nonnull
  @ReturnsMutableCopy
  public MapBasedXPathVariableResolver getClone ()
  {
    return new MapBasedXPathVariableResolver (this);
  }

  @Override
  public boolean equals (final Object o)
  {
    if (o == this)
      return true;
    if (o == null || !getClass ().equals (o.getClass ()))
      return false;
    final MapBasedXPathVariableResolver rhs = (MapBasedXPathVariableResolver) o;
    return EqualsHelper.equals (m_aMap, rhs.m_aMap);
  }

  @Override
  public int hashCode ()
  {
    return new HashCodeGenerator (this).append (m_aMap).getHashCode ();
  }

  @Override
  public String toString ()
  {
    return new ToStringGenerator (this).append ("map", m_aMap).getToString ();
  }
}

redpajama_set_name: RedPajamaGithub


text:
/**
 *
 */
package es.predictia.util.backoff;

public interface Runnable{
	void run() throws Exception;
}


text:
<!DOCTYPE html>

    <meta http-equiv="refresh" content="0;URL=fn.displacement.html">

Redirecting to fn.displacement.html...


text:
module Kawaii
  # Mixins for starting a self-contained server. To be included in a class
  # derived from {Base}.
  # @note At the moment hard-coded to use WEBrick.
  module ServerMethods
    WEBRICK = 'WEBrick'

    # Starts serving the app.
    # @param port [Fixnum] port number to bind to
    def start!(port) # @todo Support other handlers http://www.rubydoc.info/github/rack/rack/Rack/Handler
      Rack::Handler.get(WEBRICK).run(self, Port: port) do |s|
        @server = s
        at_exit { stop! }
        [:INT, :TERM].each do |signal|
          old = trap(signal) do
            stop!
            old.call if old.respond_to?(:call)
          end
        end
      end
    end

    # Stops serving the app.
    def stop!
      @server.stop if @server # NOTE: WEBrick-specific
    end

    # Returns true if the server is running.
    def running?
      !@server.nil?
    end
  end
end


text:
package com.google.api.codegen.configgen.transformer;

import com.google.api.codegen.config.FieldModel;
import com.google.api.codegen.config.InterfaceModel;
import com.google.api.codegen.config.MethodModel;
import com.google.api.codegen.configgen.viewmodel.FieldNamePatternView;
import com.google.api.codegen.configgen.viewmodel.FlatteningGroupView;
import com.google.api.codegen.configgen.viewmodel.FlatteningView;
import com.google.api.codegen.configgen.viewmodel.MethodView;
import com.google.api.codegen.configgen.viewmodel.PageStreamingRequestView;
import com.google.api.codegen.configgen.viewmodel.PageStreamingResponseView;
import com.google.api.codegen.configgen.viewmodel.PageStreamingView;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/** Generates method view objects from an API interface and collection name map. */
public class MethodTransformer {
  private final InputSpecificMethodTransformer helperTransformer;

  public MethodTransformer(InputSpecificMethodTransformer helperTransformer) {
    this.helperTransformer = helperTransformer;
  }

  // Do not apply flattening if the parameter count exceeds the threshold.
  // TODO(shinfan): Investigate a more intelligent way to handle this.
  private static final int FLATTENING_THRESHOLD = 4;

  private static final int REQUEST_OBJECT_METHOD_THRESHOLD = 1;

  public List<MethodView> generateMethods(
      InterfaceModel apiInterface, Map<String, String> collectionNameMap) {
    ImmutableList.Builder<MethodView> methods = ImmutableList.builder();
    for (MethodModel method : apiInterface.getMethods()) {
      MethodView.Builder methodView = MethodView.newBuilder();
      methodView.name(method.getRawName());
      generateField(method, methodView);
      generatePageStreaming(method, methodView);
      generateRetry(method, methodView);
      generateFieldNamePatterns(method, methodView, collectionNameMap);
      methodView.timeoutMillis("60000");
      methods.add(methodView.build());
    }
    return methods.build();
  }

  private void generateField(MethodModel method, MethodView.Builder methodView) {
    List<String> parameterList = new ArrayList<>();
    List<FieldModel> fieldList = new ArrayList<>();
    Iterable<FieldModel> inputFields = method.getInputFields();
    for (FieldModel field : inputFields) {
      String fieldName = field.getSimpleName();
      if (field.getOneof() == null
          && !helperTransformer.getPagingParameters().getIgnoredParameters().contains(fieldName)) {
        parameterList.add(fieldName);
        fieldList.add(field);
      }
    }

    List<String> parameters = filteredInputFields(method, fieldList);

    if (parameters.size() > 0 && parameters.size() <= FLATTENING_THRESHOLD) {
      methodView.flattening(generateFlattening(parameters));
    }

    methodView.requiredFields(parameters);
    // use all fields for the following check; if there are ignored fields for flattening
    // purposes, the caller still needs a way to set them (by using the request object method).
    methodView.requestObjectMethod(
        (Iterators.size(inputFields.iterator()) > REQUEST_OBJECT_METHOD_THRESHOLD
                || Iterators.size(inputFields.iterator()) != parameterList.size())
            && !method.getRequestStreaming());
    methodView.resourceNameTreatment(helperTransformer.getResourceNameTreatment(method));
  }

  /** Get the filtered input fields for a model, from a list of candidates. */
  private List<String> filteredInputFields(MethodModel method, List<FieldModel> candidates) {
    List<String> parameterNames = new ArrayList<>();
    List<FieldModel> parametersForResourceNameMethod = method.getInputFieldsForResourceNameMethod();
    for (FieldModel field : candidates) {
      if (parametersForResourceNameMethod.contains(field)) {
        parameterNames.add(field.getNameAsParameter());
      }
    }
    return parameterNames;
  }

  private FlatteningView generateFlattening(List<String> parameterList) {
    return FlatteningView.newBuilder()
        .groups(
            ImmutableList.of(FlatteningGroupView.newBuilder().parameters(parameterList).build()))
        .build();
  }

  private void generatePageStreaming(MethodModel method, MethodView.Builder methodView) {
    PageStreamingRequestView request = generatePageStreamingRequest(method);
    if (request == null) {
      return;
    }

    PageStreamingResponseView response = helperTransformer.generatePageStreamingResponse(method);
    if (response == null) {
      return;
    }

    methodView.pageStreaming(
        PageStreamingView.newBuilder().request(request).response(response).build());
  }

  private PageStreamingRequestView generatePageStreamingRequest(MethodModel method) {
    PageStreamingRequestView.Builder requestBuilder = PageStreamingRequestView.newBuilder();

    for (FieldModel field : method.getInputFields()) {
      String fieldName = field.getSimpleName();
      if (fieldName.equals(helperTransformer.getPagingParameters().getNameForPageToken())) {
        requestBuilder.tokenField(fieldName);
      } else if (fieldName.equals(helperTransformer.getPagingParameters().getNameForPageSize())) {
        requestBuilder.pageSizeField(fieldName);
      }
    }

    PageStreamingRequestView request = requestBuilder.build();
    return request.tokenField() == null && request.pageSizeField() == null ? null : request;
  }

  private void generateRetry(MethodModel method, MethodView.Builder methodView) {
    methodView.retryCodesName(
        method.isIdempotent()
            ? RetryTransformer.RETRY_CODES_IDEMPOTENT_NAME
            : RetryTransformer.RETRY_CODES_NON_IDEMPOTENT_NAME);
    methodView.retryParamsName(RetryTransformer.RETRY_PARAMS_DEFAULT_NAME);
  }

  private void generateFieldNamePatterns(
      MethodModel method, MethodView.Builder methodView, Map<String, String> nameMap) {
    ImmutableList.Builder<FieldNamePatternView> fieldNamePatterns = ImmutableList.builder();
    Map<String, String> resourcePatternNameMap = method.getResourcePatternNameMap(nameMap);
    for (String resourcePattern : resourcePatternNameMap.keySet()) {
      fieldNamePatterns.add(
          FieldNamePatternView.newBuilder()
              .pathTemplate(resourcePattern)
              .entityName(resourcePatternNameMap.get(resourcePattern))
              .build());
    }

    methodView.fieldNamePatterns(fieldNamePatterns.build());
  }
}


text:
    <md-content flex id="main-content">
    	<md-content class="md-padding trans-back">
    	    <md-tabs md-dynamic-height md-swipe-content md-center-tabs md-selected="0">
    	        <md-tab label="Welcome">

    	      	</md-tab>
    	      	<md-tab label="Projects">

    	      	</md-tab>
    	      	<md-tab label="{{resume}}">

    	      	</md-tab>
    	      	<md-tab label="Contact Me">

    	      	</md-tab>

    	    </md-tabs>
    	</md-content>
    </md-content>


text:
/** EXTENDED MODEL **/
(function() {
	if (!('ClusterClearCacheJob' in Garp.dataTypes)) {
		return;
	}
	Garp.dataTypes.ClusterClearCacheJob.on('init', function(){
	});
})();


text:
import threading
import time as mod_time
import uuid
from redis.exceptions import LockError, WatchError
from redis.utils import dummy
from redis._compat import b

class Lock(object):
    """
    通过Redis实现一个分布式的锁
    A shared, distributed Lock. Using Redis for locking allows the Lock
    to be shared across processes and/or machines.

    It's left to the user to resolve deadlock issues and make sure
    multiple clients play nicely together.
    """
    def __init__(self, redis, name, timeout=None, sleep=0.1,
                 blocking=True, blocking_timeout=None, thread_local=True):
        """
        Create a new Lock instance named ``name`` using the Redis client
        supplied by ``redis``.

        ``timeout`` indicates a maximum life for the lock.
        By default, it will remain locked until release() is called.
        ``timeout`` can be specified as a float or integer, both representing
        the number of seconds to wait.

        ``sleep`` indicates the amount of time to sleep per loop iteration
        when the lock is in blocking mode and another client is currently
        holding the lock.

        ``blocking`` indicates whether calling ``acquire`` should block until
        the lock has been acquired or to fail immediately, causing ``acquire``
        to return False and the lock not being acquired. Defaults to True.
        Note this value can be overridden by passing a ``blocking``
        argument to ``acquire``.

        ``blocking_timeout`` indicates the maximum amount of time in seconds to
        spend trying to acquire the lock. A value of ``None`` indicates
        continue trying forever. ``blocking_timeout`` can be specified as a
        float or integer, both representing the number of seconds to wait.

        ``thread_local`` indicates whether the lock token is placed in
        thread-local storage. By default, the token is placed in thread local
        storage so that a thread only sees its token, not a token set by
        another thread. Consider the following timeline:

            time: 0, thread-1 acquires `my-lock`, with a timeout of 5 seconds.
                     thread-1 sets the token to "abc"
            time: 1, thread-2 blocks trying to acquire `my-lock` using the
                     Lock instance.
            time: 5, thread-1 has not yet completed. redis expires the lock
                     key.
            time: 5, thread-2 acquired `my-lock` now that it's available.
                     thread-2 sets the token to "xyz"
            time: 6, thread-1 finishes its work and calls release(). if the
                     token is *not* stored in thread local storage, then
                     thread-1 would see the token value as "xyz" and would be
                     able to successfully release the thread-2's lock.

        In some use cases it's necessary to disable thread local storage. For
        example, if you have code where one thread acquires a lock and passes
        that lock instance to a worker thread to release later. If thread
        local storage isn't disabled in this case, the worker thread won't see
        the token set by the thread that acquired the lock. Our assumption
        is that these cases aren't common and as such default to using
        thread local storage.
        """
        self.redis = redis
        self.name = name
        self.timeout = timeout
        self.sleep = sleep
        self.blocking = blocking
        self.blocking_timeout = blocking_timeout
        self.thread_local = bool(thread_local)
        self.local = threading.local() if self.thread_local else dummy()
        self.local.token = None
        if self.timeout and self.sleep > self.timeout:
            raise LockError("'sleep' must be less than 'timeout'")

    def __enter__(self):
        # force blocking, as otherwise the user would have to check whether
        # the lock was actually acquired or not.
        self.acquire(blocking=True)
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        self.release()

    def acquire(self, blocking=None, blocking_timeout=None):
        """
        Use Redis to hold a shared, distributed lock named ``name``.
        Returns True once the lock is acquired.

        If ``blocking`` is False, always return immediately. If the lock
        was acquired, return True, otherwise return False.

        ``blocking_timeout`` specifies the maximum number of seconds to
        wait trying to acquire the lock.
        """
        sleep = self.sleep
        token = b(uuid.uuid1().hex)
        if blocking is None:
            blocking = self.blocking
        if blocking_timeout is None:
            blocking_timeout = self.blocking_timeout
        stop_trying_at = None
        if blocking_timeout is not None:
            stop_trying_at = mod_time.time() + blocking_timeout
        while 1:
            if self.do_acquire(token):
                self.local.token = token
                return True
            if not blocking:
                return False
            if stop_trying_at is not None and mod_time.time() > stop_trying_at:
                return False
            mod_time.sleep(sleep)

    def do_acquire(self, token):
        if self.redis.setnx(self.name, token):
            if self.timeout:
                # convert to milliseconds
                timeout = int(self.timeout * 1000)
                self.redis.pexpire(self.name, timeout)
            return True
        return False

    def release(self):
        "Releases the already acquired lock"
        expected_token = self.local.token
        if expected_token is None:
            raise LockError("Cannot release an unlocked lock")
        self.local.token = None
        self.do_release(expected_token)

    def do_release(self, expected_token):
        name = self.name

        def execute_release(pipe):
            lock_value = pipe.get(name)
            if lock_value != expected_token:
                raise LockError("Cannot release a lock that's no longer owned")
            pipe.delete(name)

        self.redis.transaction(execute_release, name)

    def extend(self, additional_time):
        """
        Adds more time to an already acquired lock.

        ``additional_time`` can be specified as an integer or a float, both
        representing the number of seconds to add.
        """
        if self.local.token is None:
            raise LockError("Cannot extend an unlocked lock")
        if self.timeout is None:
            raise LockError("Cannot extend a lock with no timeout")
        return self.do_extend(additional_time)

    def do_extend(self, additional_time):
        pipe = self.redis.pipeline()
        pipe.watch(self.name)
        lock_value = pipe.get(self.name)
        if lock_value != self.local.token:
            raise LockError("Cannot extend a lock that's no longer owned")
        expiration = pipe.pttl(self.name)
        if expiration is None or expiration < 0:
            # Redis evicted the lock key between the previous get() and now
            # we'll handle this when we call pexpire()
            expiration = 0
        pipe.multi()
        pipe.pexpire(self.name, expiration + int(additional_time * 1000))

        try:
            response = pipe.execute()
        except WatchError:
            # someone else acquired the lock
            raise LockError("Cannot extend a lock that's no longer owned")
        if not response[0]:
            # pexpire returns False if the key doesn't exist
            raise LockError("Cannot extend a lock that's no longer owned")
        return True

class LuaLock(Lock):
    """
    A lock implementation that uses Lua scripts rather than pipelines
    and watches.
    """
    lua_acquire = None
    lua_release = None
    lua_extend = None

    # KEYS[1] - lock name
    # ARGV[1] - token
    # ARGV[2] - timeout in milliseconds
    # return 1 if lock was acquired, otherwise 0
    LUA_ACQUIRE_SCRIPT = """
        if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then
            if ARGV[2] ~= '' then
                redis.call('pexpire', KEYS[1], ARGV[2])
            end
            return 1
        end
        return 0
    """

    # KEYS[1] - lock name
    # ARGS[1] - token
    # return 1 if the lock was released, otherwise 0
    LUA_RELEASE_SCRIPT = """
        local token = redis.call('get', KEYS[1])
        if not token or token ~= ARGV[1] then
            return 0
        end
        redis.call('del', KEYS[1])
        return 1
    """

    # KEYS[1] - lock name
    # ARGS[1] - token
    # ARGS[2] - additional milliseconds
    # return 1 if the locks time was extended, otherwise 0
    LUA_EXTEND_SCRIPT = """
        local token = redis.call('get', KEYS[1])
        if not token or token ~= ARGV[1] then
            return 0
        end
        local expiration = redis.call('pttl', KEYS[1])
        if not expiration then
            expiration = 0
        end
        if expiration < 0 then
            return 0
        end
        redis.call('pexpire', KEYS[1], expiration + ARGV[2])
        return 1
    """

    def __init__(self, *args, **kwargs):
        super(LuaLock, self).__init__(*args, **kwargs)
        LuaLock.register_scripts(self.redis)

    @classmethod
    def register_scripts(cls, redis):
        if cls.lua_acquire is None:
            cls.lua_acquire = redis.register_script(cls.LUA_ACQUIRE_SCRIPT)
        if cls.lua_release is None:
            cls.lua_release = redis.register_script(cls.LUA_RELEASE_SCRIPT)
        if cls.lua_extend is None:
            cls.lua_extend = redis.register_script(cls.LUA_EXTEND_SCRIPT)

    def do_acquire(self, token):
        timeout = self.timeout and int(self.timeout * 1000) or ''
        return bool(self.lua_acquire(keys=[self.name],
                                     args=[token, timeout],
                                     client=self.redis))

    def do_release(self, expected_token):
        if not bool(self.lua_release(keys=[self.name],
                                     args=[expected_token],
                                     client=self.redis)):
            raise LockError("Cannot release a lock that's no longer owned")

    def do_extend(self, additional_time):
        additional_time = int(additional_time * 1000)
        if not bool(self.lua_extend(keys=[self.name],
                                    args=[self.local.token, additional_time],
                                    client=self.redis)):
            raise LockError("Cannot extend a lock that's no longer owned")
        return True


text:
!SLIDE title
# More on Models

!SLIDE bullets
# It all starts with a migration.

* [Active Record Migrations](http://guides.rubyonrails.org/migrations.html)
* What's it again?
    * A DSL for writing SQL to change your DB.
    * A way to version your DB.
    * A changelog for your DB.
    * A way to recreate your DB, wherever.

!SLIDE bullets
# Tidbits

* On failed migrations...

> On databases that support transactions with statements that change the schema,
> migrations are wrapped in a transaction. If the database does not support this
> then when a migration fails the parts of it that succeeded will not be rolled
> back. You will have to rollback the changes that were made by hand.

!SLIDE bullets
# `change`

* For easy stuff, Rails knows how to roll forward and backward.
* [This](https://github.com/turboladen/flockr/blob/master/db/migrate/20130911051010_create_photos.rb)
  could've been written like:

  ```ruby
      class CreatePhotos < ActiveRecord::Migration
        def up
          create_table :photos do |t|
            t.string :file_name
            t.string :path

            t.timestamps
          end
        end

        def down
          remove_table :photos
        end
      end
  ```

!SLIDE incremental bullets
# What's with those filenames again?

* Our first Flockr migration file: `20130911051010_create_photos.rb`
* Timestamp tells Rails order to apply migrations.
    * One reason to use the migration generator.
* `create_photos` maps to the name of the new migration class:

    ```ruby
    class CreatePhotos < ActiveRecord::Migration
    ```
    * Errors if duplicate class names, so think first!

!SLIDE
# Generating Migrations

> If the migration name is of the form "AddXXXToYYY" or "RemoveXXXFromYYY" and
> is followed by a list of column names and types then a migration containing
> the appropriate add_column and remove_column statements will be created.

Thus, `rake g migration AddUsernameToUser username:string` ->
[AddUsernameToUser](https://github.com/turboladen/flockr/blob/master/db/migrate/20130912204904_add_username_to_user.rb).

!SLIDE
# Generating Migrations (cont.)

> If the migration name is of the form "CreateXXX" and is followed by a list of
> column names and types then a migration creating the table XXX with the
> columns listed will be generated.

Thus, `rake g migration CreateUsers email:string` ->
[CreateUsers](https://github.com/turboladen/flockr/blob/master/db/migrate/20130912063809_create_users.rb).

!SLIDE
# Generating Migrations (cont.)

> Also, the generator accepts column type as references(also available as
> belongs_to).

* Remember?

    ```bash
    rake g migration create_comments body:string user:references photo:references`
    ```
* That could've been:

    ```bash
    rake g migration create_comments body:string user:belongs_to photo:belongs_to`
    ```
* Note that `references` and `belongs_to` creates the FK, but also creates an index.

!SLIDE
# Generating Migrations (cont.)

* [Supported Type Modifiers](http://guides.rubyonrails.org/migrations.html#supported-type-modifiers).

!SLIDE
# Creating Tables

> By default, `create_table` will create a primary key called `id`. You can change
> the name of the primary key with the `:primary_key` option (don't forget to
> update the corresponding model) or, if you don't want a primary key at all,
> you can pass the option `id: false`. If you need to pass database specific
> options you can place an SQL fragment in the `:options` option.

!SLIDE
# Kick it OG style

> If the helpers provided by Active Record aren't enough you can use the execute
> method to execute arbitrary SQL:

```ruby
Products.connection.execute('UPDATE `products` SET `price`=`free` WHERE 1')
```

!SLIDE bullets
# More `change`

* You can do these things when `change`ing:
    * add_column
    * add_index
    * add_reference
    * add_timestamps
    * create_table
    * create_join_table
    * drop_table (must supply a block)
    * drop_join_table (must supply a block)
    * remove_timestamps
    * rename_column
    * rename_index
    * remove_reference
    * rename_table

!SLIDE incremental
# Running Migrations

* `rake db:migrate` runs `change` or `up` for all migrations that haven't been run,
  in timestamp order.
* `rake db:migrate` invokes `db:schema:dump`, which is what updates `db/schema.rb`.
* Run migrations up to a point in time?

    ```bash
    $ rake db:migrate VERSION=20130912063809
    ```
    * will migrate `up` or `down`, depending on where you're at.

!SLIDE incremental bullets
# Rolling Back

* Just go back 1 step:

    ```bash
    $ rake db:rollback
    ```
* Go back 3 steps:

    ```bash
    $ rake db:rollback STEP=3
    ```
* Go back, then forward 3 steps:

    ```bash
    $ rake db:migrate:redo STEP=3
    ```

!SLIDE
# Reset?

* `rake db:reset` will drop, recreate, and load the current schema (from `db/schema.rb`).
* Or create your own...

   ```ruby
   namespace :db do
     desc 'Shortcut for db:drop && db:create && db:migrate'
     task :clean do
       Rake::Task['db:drop'].invoke
       Rake::Task['db:create'].invoke
       Rake::Task['db:migrate'].invoke
     end
   end
   ```

!SLIDE
# More on Schema Files

* `db/schema.rb` is the authoritative source for your DB schema--not migrations.

> There is no need (and it is error prone) to deploy a new instance of an app
> by replaying the entire migration history. It is much simpler and faster to
> just load into the database a description of the current schema.

!SLIDE bullets incremental
# More on Schema Files (cont.)

* `db/schema.rb` is like the summary of your migrations.
* It's created by inspecting the DB and expressing its state.
* It's DB independent!
* When dumping to `.rb` it can't express:
    * foreign key constraints
    * triggers
    * stored procedures
* So use Rails' ability to dump to `.sql` if you need those.
    * `rake db:structure:dump` -> `db/structure.sql`

!SLIDE questions center
# Questions?

!SLIDE title
# ActiveRecord Querying

!SLIDE bullets
# It's how we get the data.

* [Active Record Query Interface](http://guides.rubyonrails.org/active_record_querying.html)

!SLIDE title
# Active Record Associations

!SLIDE bullets
# It's how we tie data together.

* [Active Record Associations](http://guides.rubyonrails.org/association_basics.html)

!SLIDE center questions
# Questions?


text:
# Specific Constructors for Open Generics

As described in the [main open generic constructor injection topic](generics.md), Rezolver is able to bind
dynamically to the best-matched constructor for a particular closed generic when built from an open generic
registration.

However, it's also possible (starting from 1.3.2) to instruct Rezolver to use a *specific* constructor when
creating an instance from an open generic registration.

Use cases for this are, of course, pretty niche - especially if your own classes typically stick to the standard
pattern of only having a single constructor (as is enforced by some IOC containers).  But the reality is there will
always be types which legitimately have multiple constructors (take a lot of .Net collection types, for example)
which you might also want to create via constructor injection.

## When you might need to use this

The most likely scenario for needing to be able to provide a specific constructor to be used when creating an
instance from an open generic is to disambiguate between constructors when a generic type argument might
can cause a conflict with the concrete type of an argument on one or more constructors.

For example, consider the `List<T>` type, which has the following constructors:

- `List<T>()`
- `List<T>(IEnumerable<T>)`
- `List<T>(int)`

> [!TIP]
> `List<T>` is a type that, by default, Rezolver [can build automatically for you](../arrays-lists-collections/lists.md)
> by extending its own support for [enumerables](../enumerables.md).
> ***
> In fact, the scenario described here is taken specifically from how Rezolver handles the `List<T>` type.

Now, if you were to explicitly register the `List<T>` type for constructor injection (after disabling Rezolver's
own support for it of course), Rezolver will happily bind to the `IEnumerable<T>` constructor for all types of `T`
except one: `int`.

When you request a `List<int>`, Rezolver immediately hits a problem - unless you've not got any `int` registrations
(which presumably you would have if you're requesting a list of `int`!) - because it sees *two* constructors that
could be satisfied.  It doesn't *know* that you could only ever want the `IEnumerable<T>` one - how could it? - so
instead of getting a shiny new list to play with, you get an exception.

So how do we get around it?

What we need to be able to do, of course, is to instruct Rezolver to use the `IEnumerable<T>` constructor for all
`T`.

Thankfully, there are a couple of ways to do that.

## The `RegisterGenericConstructor` overload

When registering targets into the @Rezolver.IRootTargetContainer, you can use one of these two methods:

- Rezolver.TargetContainerExtensions.RegisterGenericConstructor``1(Rezolver.ITargetContainer,System.Linq.Expressions.Expression{System.Func{``0}},Rezolver.IMemberBindingBehaviour)
- Rezolver.TargetContainerExtensions.RegisterGenericConstructor``2(Rezolver.ITargetContainer,System.Linq.Expressions.Expression{System.Func{``0}},Rezolver.IMemberBindingBehaviour)

Both functions expect an expression in which you provide a 'model' constructor call to the generic type whose
constructor you want to bind.  The actual constructor arguments you pass are not important - only that the
expression binds to the correct constructor.

Now, clearly, if you try to do this over the *open* generic, your code won't compile - e.g:

```cs
class MyGeneric<T, U> {
    public MyGeneric(T t) { }
    public MyGeneric(T t, U u) { }
    public MyGeneric(T t, U u, string s) { }
}

// ...

targets.RegisterGenericConstructor(() => new MyGeneric<,>(null, null));
```

Because using the `MyGeneric<>` type in this way requires the type arguments to be provided.

Instead, you stub out the type arguments with any types you want, and Rezolver will match the constructor with its
definition on the open generic type:

```cs
targets.RegisterGenericConstructor(() => new MyGeneric<object, object>(null, null))
```

This will create a registration in the container which, for any closed `MyGeneric<,>` will explicitly bind to
the two-parameter constructor, even if registrations exist which satisfy the `s` parameter on the 3-parameter
version.

### Example 1

Here's a tested example with a type which extends the `List<T>` scenario:

[!code-csharp[HasAmbiguousGenericCtor.cs](../../../../../test/Rezolver.Tests.Examples/Types/HasAmbiguousGenericCtor.cs#example)]

In this case, if we want to resolve an `HasAmbiguousGenericCtor<string>`, Rezolver will, by default, use the
[best-match rule](index.md#best-match-examples), meaning that the last `string` we registered will be used both
as the last item in the enumerable but also as the argument for the single `string` parameter.

But that's not a problem with the `RegisterGenericConstructor` function:

[!code-csharp[ConstructorExamples.cs](../../../../../test/Rezolver.Tests.Examples/ConstructorExamples.cs#example200)]

### Example 2 - Different 'service' type

When we register a type for constructor injection normally, we can also tell the container to create an instance
of one type when another type is requested - e.g:

```cs
// construct a Foo whenever we want an IFoo
container.RegisterType<Foo, IFoo>();

// construct a Foo<T> whenever we want an IFoo<T>
container.RegisterType(typeof(Foo<>), typeof(IFoo<>));
```

We can do the same with the other `RegisterGenericConstructor` overload which accepts two type arguments.  In
this case, you'll have noticed that our `HasAmbiguousGenericCtor<T>` generic also implements `IGeneric<T>` - so
let's bind a specific constructor *and* register it to be used for a generic service type:

[!code-csharp[ConstructorExamples.cs](../../../../../test/Rezolver.Tests.Examples/ConstructorExamples.cs#example201)]

As the comment says, it's somewhat unfortunate that we have to use specify those generic arguments - just remember
that the `RegisterGenericConstructor` method is specifically looking to bind an open generic.

## Alternatives

The `RegisterGenericConstructor` overload is merely a wrapper for one of the many overloads
of the @Rezolver.Target.ForConstructor* factory method, which creates targets from a @System.Reflection.ConstructorInfo.

This overload will create a @Rezolver.Targets.GenericConstructorTarget if the `ConstructorInfo` passed belongs to
an open generic type.  After creating the target, you can then register it directly into the container using the
normal @Rezolver.ITargetContainer.Register* function or one of its overloads.

The same is also true of the @Rezolver.TargetContainerExtensions.RegisterConstructor* overload.

Be aware, though - in all cases, it's not possible to provide named constructor argument bindings, either by dictionary
or as an object, because of the inherent difficulty of providing a single target for one or more arguments whose type
comes from a generic type argument.


text:
* Changed
  * Migrate doc to terra-core-docs.

## 3.42.0 - (November 2, 2021)

* Changed
  * Minor dependency version bump

## 3.41.0 - (September 21, 2021)

* Changed
  * Updated WDIO Screenshots due to webpack-config-terra sass upgrade.

## 3.40.0 - (August 25, 2021)

* Changed
  * Minor dependency version bump

## 3.39.0 - (April 6, 2021)

* Changed
  * Removed unnecessary `wdio.conf.js` file
  * Updated to terra-functional-testing
  * Updated Jest command

## 3.38.0 - (January 5, 2021)

* Fixed
  * Fixed broken links in documentation.

## 3.37.0 - (December 8, 2020)

* Changed
  * Minor dependency version bump

## 3.36.0 - (November 17, 2020)

* Changed
  * Update wdio tests to remove deprecated Terra.it helpers

## 3.35.0 - (October 13, 2020)

* Changed
  * Remove reference to terra-doc-template

## 3.34.0 - (August 4, 2020)

* Changed
  * Minor dependency version bump

## 3.33.0 - (July 29, 2020)

* Changed
  * Update changelog formatting

## 3.32.0 - (July 7, 2020)

* Changed
  * Minor dependency version bump

## 3.31.0 - (June 23, 2020)

* Changed
  * Minor dependency version bump

## 3.30.0 - (June 9, 2020)

* Changed
  * Minor file changes to comply with eslint rules
  * Update wdio test configuration to use root wdio config

## 3.29.0 - (May 12, 2020)

* Changed
  * Minor dependency version bump

## 3.28.0 - (April 28, 2020)

* Changed
  * Removed "View Component Source Code" from docs in favour of source code badge
* Added
  * Added clinical-lowlight-theme wdio screenshots

## 3.27.0 - (April 22, 2020)

* Changed
  * Added Usage section
  * Updated docs for documentation link and expanded `PropTypes` for Props Table
  * Removed extra lines from README
  * Apply themes by context and directly include packaged themes.

## 3.26.0 - (March 10, 2020)

* Changed
  * Minor dependency version bump

## 3.25.0 - (February 18, 2020)

* Added
  * Added clinical-lowlight-theme theming files

## 3.24.0 - (February 4, 2020)

* Changed
  * Update docs to use mdx syntax.

## 3.23.0 - (January 7, 2020)

* Changed
  * Minor dependency version bump

## 3.22.0 - (December 3, 2019)

* Added
  * Added orion-fusion-theme and generated the respective reference wdio screenshots.

## 3.21.0 - (October 30, 2019)

* Fixed
  * Fixed lint warnings for multiple empty lines

## 3.20.0 - (October 3, 2019)

* Changed
  * Minor dependency version bump

## 3.19.0 - (September 19, 2019)

* Changed
  * Removed `details` tag from doc-site.

## 3.18.0 - (September 6, 2019)

* Added
  * Props table markdown file import added to doc site page

* Removed
  * Removed `inherit` fallback for `--terra-card-color` CSS custom property

## 3.17.0 - (August 21, 2019)

* Changed
  * Import for package version from package.json added to doc page
  * Cleaned up imports in examples and test files

## 3.16.0 - (August 14, 2019)

* Changed
  * updated package.json test scripts

## 3.15.0 - (July 30, 2019)

* Changed
  * Minor dependency version bump

## 3.14.0 - (July 24, 2019)

* Changed
  * Minor dependency version bump

## 3.13.0 - (July 16, 2019)

* Added
  * Added documentation on required peerDependencies

## 3.12.0  - (July 11, 2019)

* Changed
  * Update tests to use `Terra.describeViewports` for setting viewports

## 3.11.0 - (July 9, 2019)

* Changed
  * Minor dependency version bump

## 3.10.0 - (June 28, 2019)

* Changed
  * Minor dependency version bump

## 3.9.0 - (June 18, 2019)

* Changed
  * Removed all inline styles from Dev-site components and implemented the same styles using external css.

## 3.8.0 - (June 11, 2019)

* Removed
  * Removed node_modules from .npmignore

* Changed
  * Made required updates to consume terra-toolkit v5 and terra-dev-site v5

## 3.7.0 - (May 1, 2019)

* Changed
  * Minor dependency version bump

## 3.6.0 - (April 16, 2019)

* Changed
  * Minor dependency version bump

## 3.5.0 - (March 26, 2019)

* Changed
  * Update react/react-dom peer-dependency to latest stable minor release

* Removed
  * Removed peer dependency on terra-base
  * Removed baseStyles import from terra-base

## 3.4.0 - (March 21, 2019)

* Changed
  * Minor dependency version bump

## 3.3.0 - (February 26, 2019)

* Changed
  * Minor dependency version bump
  * Removed stylelint overrides in CardBody.module.scss

## 3.2.0 - (February 12, 2019)

* Changed
  * Minor dependency version bump

## 3.1.0 - (February 5, 2019)

* Changed
  * Minor dependency version bump

## 3.0.0 - (January 22, 2019)

* Changed
  * Updated theme variables

## 2.33.0 - (January 22, 2019)

* Changed
  * Updated dependencies to fix major version bump issues

## 2.32.0 - (January 8, 2019)

* Changed
  * Minor dependency version bump

## 2.31.0 - (January 2, 2019)

* Changed
  * Minor dependency version bump

## 2.30.0 - (November 19, 2018)

* Changed
  * Minor dependency version bump

## 2.29.0 - (November 13, 2018)

* Changed
  * Minor dependency version bump

## 2.28.0 - (November 9, 2018)

* Changed
  * Minor dependency version bump

## 2.27.0 - (October 30, 2018)

* Changed
  * Minor dependency version bump

## 2.26.0 - (October 24, 2018)

* Changed
  * Minor dependency version bump

## 2.25.0 - (October 16, 2018)

* Changed
  * Minor dependency version bump

## 2.24.0 - (October 8, 2018)

* Changed
  * Minor dependency version bump

## 2.23.0 - (October 2, 2018)

* Changed
  * Made main container an article to improve accessibility

* Added
  * Added prop for VisuallyHiddenText

## 2.22.0 - (September 25, 2018)

* Changed
  * Minor dependency version bump

## 2.21.1 - (September 6, 2018)

* Changed
  * Patch dependency version bump

## 2.21.0 - (September 5, 2018)

* Changed
  * Bumped minimum react peerDependency version from ^16.2.0 to ^16.4.2
  * Bumped minimum react-dom peerDependency version from ^16.2.0 to ^16.4.2

## 2.20.0 - (September 4, 2018)

* Changed
  * Minor dependency version bump

## 2.19.0 - (August 29, 2018)

* Changed
  * Minor dependency version bump

## 2.18.0 - (August 1, 2018)

* Changed
  * Minor dependency version bump

## 2.17.0 - (July 19, 2018)

* Changed
  * Add .module extension to SCSS file(s)

## 2.16.0 - (July 17, 2018)

* Changed
  * Minor dependency version bump
  * Formatting changes per eslint v4 update

## 2.15.0 - (July 10, 2018)

* Changed
  * Minor dependency version bump

## 2.14.0 - (June 28, 2018)

* Changed
  * Minor dependency version bump

* Added
  * Added change log to the documentation on terra-dev-site

## 2.13.0 - (June 22, 2018)

* Changed
  * Moved terra-base from dependency to peerDependency

## 2.12.0 - (June 12, 2018)

* Changed
  * Updated "test:jest" script to work on windows.

## 2.11.0 - (May 30, 2018)

* Changed
  * Updated structure to match terra-dev-site 1.0 and moved doc examples internal.

## 2.10.0 - (May 23, 2018)

* Changed
  * Minor dependency version bump

## 2.9.0 - (May 16, 2018)

* Changed
  * Minor dependency version bump

## 2.8.0 - (May 9, 2018)

* Added
  * New prop called variant used to flex to different card styles for new use cases. Falls back to default. Currently only adds the option for raised which adds a new css custom attribute for the box shadow.

## 2.7.0 - (May 2, 2018)

* Changed
  * Minor dependency version bump

## 2.6.0 - (April 20, 2018)

* Changed
  * Minor dependency version bump

## 2.5.0 - (April 15, 2018)

* Changed
  * Minor dependency version bump

## 2.4.0 - (April 5, 2018)

* Changed
  * Minor dependency version bump

## 2.3.0 - (March 30, 2018)

* Removed
  * Removed unused terra-mixins package
  * Removed out-dated theme mixin

## 2.2.0 - (March 6, 2018)

* Changed
  * Added new prop isContentCentered in CardBody to center content

* Removed
  * Removed props-table script from package.json

## 2.1.0 - (February 26, 2018)

* Changed
  * Minor dependency version bump

## 2.0.1 - (February 13, 2018)

* Changed
  * Updated peerDependencies

## 2.0.0 - (February 12, 2018)

* Changed
  * Updated to use React 16

## 1.11.0 - (February 1, 2018)

* Changed
  * Minor dependency version bump

## 1.10.0 - (January 18, 2018)

* Changed
  * Minor dependency version bump

## 1.9.0 - (January 5, 2018)

* Changed
  * Minor dependency version bump

## 1.8.0 - (November 28, 2017)

* Changed
  * Minor dependency version bump

## 1.7.0 - (November 16, 2017)

* Changed
  * Minor dependency version bump

## 1.6.0 - (October 6, 2017)

* Changed
  * Minor dependency version bump

## 1.5.0 - (September 26, 2017)

* Added
  * Added a variable for color of card

* Removed
  * Remove stylelint-disable selector-class-pattern

## 1.4.0 - (September 19, 2017)

* Changed
  * Minor dependency version bump

## 1.3.0 - (September 12, 2017)

* Changed
  * Minor dependency version bump

## 1.2.0 - (September 7, 2017)

* Changed
  * Minor dependency version bump

## 1.1.0 - (September 5, 2017)

* Changed
  * Update nightwatch tests and test scripts.

## 1.0.0 - (August 31, 2017)

Initial stable release


text:
<?xml version="1.0" encoding="UTF-8"?>
<ldswebml type="image" uri="/media-library/images/food-drink#pumpkins-762467" xml:lang="eng" locale="eng" status="publish">
  <search-meta>
      <uri-title its:translate="no" xmlns:its="http://www.w3.org/2005/11/its">pumpkins-762467</uri-title>
      <source>pumpkins-762467</source>
      <publication-type its:translate="no" xmlns:its="http://www.w3.org/2005/11/its">image</publication-type>
      <media-type its:translate="no" xmlns:its="http://www.w3.org/2005/11/its">image</media-type>
      <publication value="ldsorg">LDS.org</publication>
      <publication-date value="2012-04-09">2012-04-09</publication-date>
      <title/>
      <description/>
      <collections>
          <collection its:translate="no" xmlns:its="http://www.w3.org/2005/11/its">global-search</collection>
          <collection its:translate="no" xmlns:its="http://www.w3.org/2005/11/its">media</collection>
          <collection its:translate="no" xmlns:its="http://www.w3.org/2005/11/its">images</collection>
      </collections>
      <subjects>
          <subject>Food</subject>
          <subject>Pumpkins</subject>
          <subject>Plants</subject>
      </subjects>
  </search-meta>
  <no-search>
      <path>http://media.ldscdn.org/images/media-library/food-drink/pumpkins-762467-gallery.jpg</path>
      <images>
          http://media.ldscdn.org/images/media-library/food-drink/pumpkins-762467-thumbnail.jpg
      </images>
          <download-urls>
              <download-url>
                  Mobile
                  <size>163 KB</size>
                  <path>http://media.ldscdn.org/images/media-library/food-drink/pumpkins-762467-mobile.jpg</path>
              </download-url>
              <download-url>
                  Tablet
                  <size>221 KB</size>
                  <path>http://media.ldscdn.org/images/media-library/food-drink/pumpkins-762467-tablet.jpg</path>
              </download-url>
              <download-url>
                  Print
                  <size>481 KB</size>
                  <path>http://media.ldscdn.org/images/media-library/food-drink/pumpkins-762467-print.jpg</path>
              </download-url>
          </download-urls>
  </no-search>
<ldse-meta its:translate="no" xmlns="http://lds.org/code/lds-edit" xmlns:its="http://www.w3.org/2005/11/its"><document id="pumpkins-762467" locale="eng" uri="/media-library/images/food-drink#pumpkins-762467" status="publish" site="ldsorg" source="chq" words="92" tgp="0.3217"/><created username="lds-edit" userid=""/><last-modified date="2012-05-10T12:26:23.573084-06:00" username="lds-edit" userid=""/></ldse-meta></ldswebml>


text:
(function() {
  'use strict';

  function Clone() {}

  RAML.Utils = {
    clone: function(object) {
      Clone.prototype = object;
      return new Clone();
    },

    isEmpty: function(object) {
      if (object) {
        return Object.keys(object).length === 0;
      } else {
        return true;
      }
    }
  };
})();


text:
--------------------------------
--  Set the original target, since target can be nil.

-- Is the target that were used to run the action. Unless you are doing something complex, like ActionManager, you should NOT call this method.

-- The target is 'assigned', it is not 'retained'.

-- since v0.8.2
-- @function [parent=#Action] setOriginalTarget
-- @param self
-- @param #cc.Node originalTarget

--------------------------------
--  returns a clone of action
-- @function [parent=#Action] clone
-- @param self
-- @return Action#Action ret (return value: cc.Action)

--------------------------------
--
-- @function [parent=#Action] getOriginalTarget
-- @param self
-- @return Node#Node ret (return value: cc.Node)

--------------------------------
-- called after the action has finished. It will set the 'target' to nil.

-- IMPORTANT: You should never call "[action stop]" manually. Instead, use: "target->stopAction(action);"
-- @function [parent=#Action] stop
-- @param self

--------------------------------
-- called once per frame. time a value between 0 and 1

-- For example:

-- - 0 means that the action just started

-- - 0.5 means that the action is in the middle

-- - 1 means that the action is over
-- @function [parent=#Action] update
-- @param self
-- @param #float time

--------------------------------
--
-- @function [parent=#Action] getTarget
-- @param self
-- @return Node#Node ret (return value: cc.Node)

--------------------------------
--  called every frame with it's delta time. DON'T override unless you know what you are doing.
-- @function [parent=#Action] step
-- @param self
-- @param #float dt

--------------------------------
--
-- @function [parent=#Action] setTag
-- @param self
-- @param #int tag

--------------------------------
--
-- @function [parent=#Action] getTag
-- @param self
-- @return int#int ret (return value: int)

--------------------------------
--  The action will modify the target properties.
-- @function [parent=#Action] setTarget
-- @param self
-- @param #cc.Node target

--------------------------------
--  return true if the action has finished
-- @function [parent=#Action] isDone
-- @param self
-- @return bool#bool ret (return value: bool)

--------------------------------
--  returns a new action that performs the exactly the reverse action
-- @function [parent=#Action] reverse
-- @param self
-- @return Action#Action ret (return value: cc.Action)

return nil


text:
{% extends "layout.html" %}
{% block body %}
{% from "_formhelpers.html" import render_field %}
<form method=post action="/register">
<dl>
    {{ render_field(form.username) }}
    {{ render_field(form.email) }}
    {{ render_field(form.password) }}
    {{ render_field(form.confirm) }}
</dl>
<p><input type=submit value=Register>
</form>
{% endblock %}


text:
package io.github.repir.Repository.Pig;

import io.github.repir.Repository.EntityStoredFeature;
import io.github.repir.Repository.Pig.PigTermDoc.File;
import io.github.repir.Repository.Pig.PigTermDoc.Tuple;
import io.github.repir.Repository.Repository;
import io.github.repir.Repository.StoredFeature;
import io.github.htools.io.Datafile;
import io.github.htools.lib.Log;
import io.github.htools.io.struct.StructuredTextFile;
import io.github.htools.io.struct.StructuredTextPig;
import io.github.htools.io.struct.StructuredTextPigTuple;

/**
 * Can store one literal String per Document, e.g. collection ID, title, url.
 * @see EntityStoredFeature
 * @author jer
 */
public class PigTermDoc extends PigFeatureField<File, Tuple>  {

   public static Log log = new Log(PigTermDoc.class);

   private PigTermDoc(Repository repository, String field) {
      super(repository, field);
   }

   public static PigTermDoc get(Repository repository, String field) {
       String label = canonicalName(PigTermDoc.class, field);
       PigTermDoc pigtermdoc = (PigTermDoc) StoredFeature.getStoredFeature(repository, label);
       if (pigtermdoc == null) {
          pigtermdoc = new PigTermDoc(repository, field);
          StoredFeature.storeFeature(repository, label, pigtermdoc);
       }
       return pigtermdoc;
   }

   @Override
   public File createFile(Datafile datafile) {
      return new File(datafile);
   }

   @Override
   public Tuple getValue() {
      if (getFile().nextRecord()) {
         return new Tuple(file);
      } else {
         return null;
      }
   }

   @Override
   public void write(Tuple value) {
      getFile().write(value);
   }

   public static class File extends StructuredTextPig {
      public IntField docid = this.addInt("docid");
      public IntField docpartition = this.addInt("docpartition");
      public IntField tf = this.addInt("tf");

      public File(Datafile df) {
         super(df);
      }
   }

   public static class Tuple extends StructuredTextPigTuple<File> {
      public int docid;
      public int partition;
      public int tf;

      public Tuple() {}

      protected Tuple(File file) {
         docid = file.docid.get();
         partition = file.docpartition.get();
         tf = file.tf.get();
      }

      @Override
      public void write(File file) {
         file.docid.set(docid);
         file.docpartition.set(partition);
         file.tf.set(tf);
         file.write();
      }
   }
}


text:
package ru.job4j.userservlet;

import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;

/**
 * DispatchPattern class.
 *
 * @author Kuzmin Danila (mailto:bus1d0@mail.ru)
 * @version $Id$
 * @since 0.1.0
 */
public class DispatchPattern {
    /**
     * Contains destinations.
     */
    private final Map<Action.StoreAction, BiFunction<ValidateService, User, Boolean>> dispatch = new HashMap<>();

    /**
     * toAdd method.
     *
     * @return functional interface <ValidateService, User, Boolean>.
     */
    public BiFunction<ValidateService, User, Boolean> toAdd() {
        return (validateService, user) -> {
            validateService.add(user);
            return true;
        };
    }

    /**
     * toDelete method.
     *
     * @return functional interface <ValidateService, User, Boolean>.
     */
    public BiFunction<ValidateService, User, Boolean> toDelete() {
        return (validateService, user) -> {
            validateService.delete(user);
            return true;
        };
    }

    /**
     * toUpdate method.
     *
     * @return functional interface <ValidateService, User, Boolean>.
     */
    public BiFunction<ValidateService, User, Boolean> toUpdate() {
        return (validateService, user) -> {
            //validateService.update(user);
            return true;
        };
    }

    /**
     * Initialise dispatch methods.
     *
     * @return current object.
     */
    public DispatchPattern init() {
        this.load(Action.StoreAction.ADD, this.toAdd());
        this.load(Action.StoreAction.UPDATE, this.toUpdate());
        this.load(Action.StoreAction.DELETE, this.toDelete());
        return this;
    }

    /**
     * load method.
     * Created for loading possible methods.
     *
     * @param storeAction - possible action.
     * @param handle - bifunction interface.
     */
    public void load(Action.StoreAction storeAction, BiFunction<ValidateService, User, Boolean> handle) {
        this.dispatch.put(storeAction, handle);
    }

    /**
     * action method.
     *
     * Make action on logic layout(validate service).
     *
     * @param storeAction - actions.
     * @param validateService - validate service.
     * @param user - user.
     * @return boolean.
     */
    public boolean action(final Action storeAction, final ValidateService validateService, final User user) {
        return this.dispatch.get(
                storeAction.type()).apply(validateService, user);
    }

}