text:
/**
 *
 */
package br.com.dlp.framework.jsf;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.faces.model.SelectItem;

import org.apache.commons.collections.CollectionUtils;

import br.com.dlp.framework.dao.ExtraArgumentsDTO;
import br.com.dlp.framework.exception.JazzBusinessException;
import br.com.dlp.framework.vo.IBaseVO;

/**
 * TODO: Corrigir problema das tabelas editaveis (QuestionnaireCRUD), onde os campos do submodulo não atualizando o bean se não for via ajax:support.
 * Implementação abstrata de JSF Bean, com suporte à paginação
 * @author dpacifico
 */
public abstract class AbstractPaginatedJSFBeanImpl<B extends IBaseVO<? extends Serializable>> extends AbstractJSFBeanImpl<B> implements IJazzDataProvider<B> {
	private static final long serialVersionUID = -5770083259678219532L;

	private List<B> resultadosPesquisa= new ArrayList<B>(0);

	/**
	 * Executar pesquisa em banco de dados
	 * @param extraArgumentsDTO
	 * @return
	 */
	public abstract List<B> actionPesquisar(ExtraArgumentsDTO extraArgumentsDTO);

	/**
	 * Avalia estado do cache e determina se a pesquisa em banco de dados deve ser executada ou não
	 */
	public final List<B> actionPesquisarCached(ExtraArgumentsDTO extraArgumentsDTO) {

		if(!isValidRowCountCache()){
			this.resultadosPesquisa = actionPesquisar(extraArgumentsDTO);
		}

		return resultadosPesquisa;
	}

	/**
	 * Instância de JazzDataModel para paginação
	 */
	private JazzDataModel<B> jazzDataModel;
	private Collection<SelectItem> opcoesQtdLinhas;
	private Integer linhasPorPagina=10;
	private Long linhasTotais=null;

	/**
	 * Sobrescreve método salvar apenas para invalidar cache de contagem de registros
	 * @see br.com.dlp.framework.jsf.AbstractJSFBeanImpl#actionSalvar()
	 */
	@Override
	public String actionSalvar() throws JazzBusinessException {
		invalidateRowCountCache();
		return super.actionSalvar();
	}

	/**
	 * Sobrescreve o método delete apenas para invalidar cache de contagem de registros
	 * @see br.com.dlp.framework.jsf.AbstractJSFBeanImpl#actionDelete(br.com.dlp.framework.vo.IBaseVO)
	 */
	@Override
	public String actionDelete(final B voBean) {
		return super.actionDelete(voBean);
	}

	/**
	 * Action para confirma exclusao do registro selecionado
	 * @see br.com.dlp.framework.jsf.AbstractJSFBeanImpl#deleteConfirm()
	 */
	@Override
	public String deleteConfirm() {
		invalidateRowCountCache();
		return super.deleteConfirm();
	}

	/**
	 * Mantem a contagem de registros em cache, invalidando o mesmo apenas caso os argumentos de pesquisa mudem.
	 * @see br.com.dlp.framework.jsf.IJazzDataProvider#cachedRowCount()
	 */
	@Override
	public Long cachedRowCount() {
		if(!isValidRowCountCache()){
			this.linhasTotais = rowCount();
		}
		return this.linhasTotais;
	}

	/**
	 * Testa se o cache de contagem de registros é válido
	 * @return
	 */
	@Override
	public boolean isValidRowCountCache() {
		return linhasTotais!=null && CollectionUtils.isNotEmpty(this.resultadosPesquisa) ;
	}

	/**
	 * Invalida o último valor cacheado de contagem de registros.
	 * Na solução de design proposta, o cache é válido até que os argumentos de pesquisa sejam modificados.
	 * Caso os argumentos de pesquisa mudem, executar este método.
	 * @return
	 */
	public String invalidateRowCountCache() {
		linhasTotais=null;
		this.resultadosPesquisa=null;
		return null;
	}

	/**
	 * Implementar contagem de registros resultantes da consulta.
	 * Este valor será armazenado em cache até que o cache seja invalidado.
	 * Na solução de design proposta, o cache é válido até que os argumentos de pesquisa sejam modificados.
	 * @return
	 */
	protected abstract Long rowCount();

	/* (non-Javadoc)
	 * @see br.com.dlp.framework.jsf.IJazzDataProvider#isRowAvailable(java.io.Serializable)
	 */
	@Override
	public boolean isRowAvailable(Serializable currentPk) {
		return currentPk!=null;
		//throw new RuntimeException("método isRowAvailable nao implementado !!!!!!!!!!!!!!!!!");
	}

	/**
	 * Retorna a especialização de ExtendedDataModel do RichFaces; JazzDataModel
	 * @return JazzDataModel
	 */
	public JazzDataModel<B> getDataModel(){
		if(this.jazzDataModel==null){
			this.jazzDataModel = new JazzDataModel<B>(this);
		}

		return this.jazzDataModel;
	}

	@Override
	public List<B> getResultados() {
		JazzDataModel<B> dataModel = getDataModel();

		List<B> resultados = dataModel.getResultados();

		return resultados;
	}

	/**
	 * Retorna as opções para quantidades de linhas para resultados de pesquisa
	 * @return
	 */
	public Collection<SelectItem> getOpcoesQtdLinhas() {
		if(opcoesQtdLinhas==null){
			opcoesQtdLinhas = new ArrayList<SelectItem>();

			opcoesQtdLinhas.add(new SelectItem(5, "5"));
			opcoesQtdLinhas.add(new SelectItem(10, "10"));
			opcoesQtdLinhas.add(new SelectItem(15, "15"));
			opcoesQtdLinhas.add(new SelectItem(25, "25"));
			opcoesQtdLinhas.add(new SelectItem(40, "40"));
		}
		return opcoesQtdLinhas;
	}

	public void setOpcoesQtdLinhas(Collection<SelectItem> opcoesQtdLinhas) {
		this.opcoesQtdLinhas = opcoesQtdLinhas;
	}

	public Integer getLinhasPorPagina() {
		return this.linhasPorPagina;
	}

	public void setLinhasPorPagina(Integer linhasPorPagina) {
		this.linhasPorPagina=linhasPorPagina;
	}

	/**
	 * Método pesquisar não pode ser utilizado em AbstractPaginatedJSFBeanImpl
	 */
	@Override
	public String actionPesquisar() {

		if(log.isDebugEnabled()){
			log.debug("O uso do método actionPesquisar em AbstractPaginatedJSFBeanImpl"+
					" não é autorizada para não quebrar o mecanismo de paginação."+
			" Verifique a solução de design aplicável para pesquisa utilizando JazzDataModel!");
		}
		return null;
	}

	/**
	 * Limpa os critérios de pesquisa do módulo. Logo após, invalida o cache de contagem de registros retornados
	 *
	 * @return
	 */
	@Override
	public String actionLimparPesquisa(){
		invalidateRowCountCache();
		return super.actionLimparPesquisa();
	}

	public Long getLinhasTotais() {
		return linhasTotais;
	}

	public void setLinhasTotais(Long linhasTotais) {
		this.linhasTotais = linhasTotais;
	}
}


text:
<ng-include src="'views/header.html'"></ng-include>

 Who we are

 Mikko, Mohit, Clément and Giovanna: HCID students at KTH

 How we built it

 We used Angular JS as front-end framework. We also used Yeoman for scaffolding and the CSS preprocessor SASS. The back-end is in PhP and the database in MySql.

Front End

Angular for frontend framework

SCSS for styling

Yeoman for scaffolding

Back End

Lumen

PhP

Design Collabration

Invision

redpajama_set_name: RedPajamaGithub


text:
package org.apache.spark.scheduler

import scala.collection.mutable.HashMap

import org.apache.spark.annotation.DeveloperApi
import org.apache.spark.executor.TaskMetrics
import org.apache.spark.storage.RDDInfo

/**
 * :: DeveloperApi ::
 * Stores information about a stage to pass from the scheduler to SparkListeners.
 */
@DeveloperApi
class StageInfo(
    val stageId: Int,
    private val attemptId: Int,
    val name: String,
    val numTasks: Int,
    val rddInfos: Seq[RDDInfo],
    val parentIds: Seq[Int],
    val details: String,
    val taskMetrics: TaskMetrics = null,
    private[spark] val taskLocalityPreferences: Seq[Seq[TaskLocation]] = Seq.empty,
    private[spark] val shuffleDepId: Option[Int] = None,
    val resourceProfileId: Int) {
  /** When this stage was submitted from the DAGScheduler to a TaskScheduler. */
  var submissionTime: Option[Long] = None
  /** Time when the stage completed or when the stage was cancelled. */
  var completionTime: Option[Long] = None
  /** If the stage failed, the reason why. */
  var failureReason: Option[String] = None

  /**
   * Terminal values of accumulables updated during this stage, including all the user-defined
   * accumulators.
   */
  val accumulables = HashMap[Long, AccumulableInfo]()

  def stageFailed(reason: String): Unit = {
    failureReason = Some(reason)
    completionTime = Some(System.currentTimeMillis)
  }

  // This would just be the second constructor arg, except we need to maintain this method
  // with parentheses for compatibility
  def attemptNumber(): Int = attemptId

  private[spark] def getStatusString: String = {
    if (completionTime.isDefined) {
      if (failureReason.isDefined) {
        "failed"
      } else {
        "succeeded"
      }
    } else {
      "running"
    }
  }
}

private[spark] object StageInfo {
  /**
   * Construct a StageInfo from a Stage.
   *
   * Each Stage is associated with one or many RDDs, with the boundary of a Stage marked by
   * shuffle dependencies. Therefore, all ancestor RDDs related to this Stage's RDD through a
   * sequence of narrow dependencies should also be associated with this Stage.
   */
  def fromStage(
      stage: Stage,
      attemptId: Int,
      numTasks: Option[Int] = None,
      taskMetrics: TaskMetrics = null,
      taskLocalityPreferences: Seq[Seq[TaskLocation]] = Seq.empty,
      resourceProfileId: Int
    ): StageInfo = {
    val ancestorRddInfos = stage.rdd.getNarrowAncestors.map(RDDInfo.fromRdd)
    val rddInfos = Seq(RDDInfo.fromRdd(stage.rdd)) ++ ancestorRddInfos
    val shuffleDepId = stage match {
      case sms: ShuffleMapStage => Option(sms.shuffleDep).map(_.shuffleId)
      case _ => None
    }
    new StageInfo(
      stage.id,
      attemptId,
      stage.name,
      numTasks.getOrElse(stage.numTasks),
      rddInfos,
      stage.parents.map(_.id),
      stage.details,
      taskMetrics,
      taskLocalityPreferences,
      shuffleDepId,
      resourceProfileId)
  }
}


text:
{% extends 'blog/base.html' %}
{% block title %}Contact us{% endblock %}
{% block content %}

Contact us

<form role="form" action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Submit</button>
</form>
{% endblock %}


text:
/* global define, module, require, exports */

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(['jquery',
                'nf.Client',
                'nf.Birdseye',
                'nf.Graph',
                'nf.CanvasUtils',
                'nf.ErrorHandler',
                'nf.Dialog',
                'nf.Common'],
            function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon) {
                return (nf.ng.TemplateComponent = factory($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon));
            });
    } else if (typeof exports === 'object' && typeof module === 'object') {
        module.exports = (nf.ng.TemplateComponent =
            factory(require('jquery'),
                require('nf.Client'),
                require('nf.Birdseye'),
                require('nf.Graph'),
                require('nf.CanvasUtils'),
                require('nf.ErrorHandler'),
                require('nf.Dialog'),
                require('nf.Common')));
    } else {
        nf.ng.TemplateComponent = factory(root.$,
            root.nf.Client,
            root.nf.Birdseye,
            root.nf.Graph,
            root.nf.CanvasUtils,
            root.nf.ErrorHandler,
            root.nf.Dialog,
            root.nf.Common);
    }
}(this, function ($, nfClient, nfBirdseye, nfGraph, nfCanvasUtils, nfErrorHandler, nfDialog, nfCommon) {
    'use strict';

    return function (serviceProvider) {
        'use strict';

        /**
         * Instantiates the specified template.
         *
         * @argument {string} templateId        The template id.
         * @argument {object} pt                The point that the template was dropped.
         */
        var createTemplate = function (templateId, pt) {
            var instantiateTemplateInstance = {
                'templateId': templateId,
                'originX': pt.x,
                'originY': pt.y
            };

            // create a new instance of the new template
            $.ajax({
                type: 'POST',
                url: serviceProvider.headerCtrl.toolboxCtrl.config.urls.api + '/process-groups/' + encodeURIComponent(nfCanvasUtils.getGroupId()) + '/template-instance',
                data: JSON.stringify(instantiateTemplateInstance),
                dataType: 'json',
                contentType: 'application/json'
            }).done(function (response) {
                // populate the graph accordingly
                nfGraph.add(response.flow, {
                    'selectAll': true
                });

                // update component visibility
                nfGraph.updateVisibility();

                // update the birdseye
                nfBirdseye.refresh();
            }).fail(nfErrorHandler.handleAjaxError);
        };

        function TemplateComponent() {

            this.icon = 'icon icon-template';

            this.hoverIcon = 'icon icon-template-add';

            /**
             * The template component's modal.
             */
            this.modal = {

                /**
                 * Gets the modal element.
                 *
                 * @returns {*|jQuery|HTMLElement}
                 */
                getElement: function () {
                    return $('#instantiate-template-dialog');
                },

                /**
                 * Initialize the modal.
                 */
                init: function () {
                    // configure the instantiate template dialog
                    this.getElement().modal({
                        scrollableContentStyle: 'scrollable',
                        headerText: 'Add Template'
                    });
                },

                /**
                 * Updates the modal config.
                 *
                 * @param {string} name             The name of the property to update.
                 * @param {object|array} config     The config for the `name`.
                 */
                update: function (name, config) {
                    this.getElement().modal(name, config);
                },

                /**
                 * Show the modal.
                 */
                show: function () {
                    this.getElement().modal('show');
                },

                /**
                 * Hide the modal.
                 */
                hide: function () {
                    this.getElement().modal('hide');
                }
            };
        }

        TemplateComponent.prototype = {
            constructor: TemplateComponent,

            /**
             * Gets the component.
             *
             * @returns {*|jQuery|HTMLElement}
             */
            getElement: function () {
                return $('#template-component');
            },

            /**
             * Enable the component.
             */
            enabled: function () {
                this.getElement().attr('disabled', false);
            },

            /**
             * Disable the component.
             */
            disabled: function () {
                this.getElement().attr('disabled', true);
            },

            /**
             * Handler function for when component is dropped on the canvas.
             *
             * @argument {object} pt        The point that the component was dropped.
             */
            dropHandler: function (pt) {
                this.promptForTemplate(pt);
            },

            /**
             * The drag icon for the toolbox component.
             *
             * @param event
             * @returns {*|jQuery|HTMLElement}
             */
            dragIcon: function (event) {
                return $('

');
            },

            /**
             * Prompts the user to select a template.
             *
             * @argument {object} pt        The point that the template was dropped.
             */
            promptForTemplate: function (pt) {
                var templateComponent = this;
                $.ajax({
                    type: 'GET',
                    url: serviceProvider.headerCtrl.toolboxCtrl.config.urls.api + '/flow/templates',
                    dataType: 'json'
                }).done(function (response) {
                    var templates = response.templates;
                    if (nfCommon.isDefinedAndNotNull(templates) && templates.length > 0) {
                        // sort the templates
                        templates = templates.sort(function (one, two) {
                            var oneDate = nfCommon.parseDateTime(one.template.timestamp);
                            var twoDate = nfCommon.parseDateTime(two.template.timestamp);

                            // newest templates first
                            return twoDate.getTime() - oneDate.getTime();
                        });

                        var options = [];
                        $.each(templates, function (_, templateEntity) {
                            if (templateEntity.permissions.canRead === true) {
                                options.push({
                                    text: templateEntity.template.name,
                                    value: templateEntity.id,
                                    description: nfCommon.escapeHtml(templateEntity.template.description)
                                });
                            }
                        });

                        // configure the templates combo
                        $('#available-templates').combo({
                            maxHeight: 300,
                            options: options
                        });

                        // update the button model
                        templateComponent.modal.update('setButtonModel', [{
                            buttonText: 'Add',
                            color: {
                                base: '#728E9B',
                                hover: '#004849',
                                text: '#ffffff'
                            },
                            handler: {
                                click: function () {
                                    // get the type of processor currently selected
                                    var selectedOption = $('#available-templates').combo('getSelectedOption');
                                    var templateId = selectedOption.value;

                                    // hide the dialog
                                    templateComponent.modal.hide();

                                    // instantiate the specified template
                                    createTemplate(templateId, pt);
                                }
                            }
                        },
                            {
                                buttonText: 'Cancel',
                                color: {
                                    base: '#E3E8EB',
                                    hover: '#C7D2D7',
                                    text: '#004849'
                                },
                                handler: {
                                    click: function () {
                                        templateComponent.modal.hide();
                                    }
                                }
                            }]);

                        // show the dialog
                        templateComponent.modal.show();
                    } else {
                        nfDialog.showOkDialog({
                            headerText: 'Instantiate Template',
                            dialogContent: 'No templates have been loaded into this NiFi.'
                        });
                    }

                }).fail(nfErrorHandler.handleAjaxError);
            }
        }

        var templateComponent = new TemplateComponent();
        return templateComponent;
    };
}));


text:
'format es6';

import Controller from './movie-detail-state-controller';
import { LogSpy, LogDummy } from 'test-doubles-log-service';
import { RejectingMovieServiceSpy, ResolvingMovieServiceSpy, MovieServiceDummy }
  from '../../services/test-doubles/movie-service-spy.td';
import { StateDummy, StateSpy, CtxStub, CtxDummy } from 'test-doubles-angular';

describe( 'MovieDetailStateController', () => {
  let controller;
  let stateDummy;
  let logDummy;
  let movieServiceDummy;
  let ctxStub;

  beforeEach(() => {
    stateDummy = new StateDummy();
    logDummy = new LogDummy();
    movieServiceDummy = new MovieServiceDummy();
    ctxStub = new CtxStub();
  });

  describe( 'given a movie', () => {
    let movie;

    beforeEach(() => {
      movie = { id : 1337, images : [] };
    });

    describe( 'when instatiating', () => {
      let ctxDummy;

      beforeEach(() => {
        ctxDummy = new CtxDummy();
        controller = new Controller( ctxDummy, stateDummy, logDummy,
          movieServiceDummy, movie );
      });

      it( 'should keep a reference to the movie', () => {
        expect( controller.data )
          .to.deep.equal( movie, 'must keep a reference to the movie' );
      });

      it( 'should not be in create mode', () => {
        expect( controller.isCreateMode() )
          .to.equal( false, 'must not be in create mode' );
      });
    });

    describe( 'and given a movieService that rejects with an error', () => {
      let movieServiceError;
      let rejectingMovieServiceSpy;
      let logSpy;

      beforeEach(() => {
        movieServiceError = 'fake webservice is down!';
        rejectingMovieServiceSpy = new RejectingMovieServiceSpy(
          Error( movieServiceError )
        );
        logSpy = new LogSpy();
      });

      describe( 'when calling saveMovie()', () => {
        beforeEach( done => {
          controller = new Controller( ctxStub, stateDummy, logSpy,
            rejectingMovieServiceSpy, movie );

          controller.saveMovie( movie ).catch(() => {
            done();
          });
        });

        it( 'should log error "Could not save movie."', () => {
          expect( logSpy.errorCalledWith( 'Could not save movie.',
            movieServiceError )).to.equal( true, 'must log error' );
        });
      });
    });

    describe( 'and given a non-failing movieService', () => {
      let resolvingMovieServiceSpy;

      beforeEach(() => {
        resolvingMovieServiceSpy = new ResolvingMovieServiceSpy();
      });

      describe( 'when calling saveMovie() with an existing movie', () => {
        beforeEach( done => {
          controller = new Controller( ctxStub, stateDummy, logDummy,
            resolvingMovieServiceSpy, movie );

          controller.saveMovie( movie ).then(() => {
            done();
          });
        });

        it( 'should call movieService update() with the movie', () => {
          expect( resolvingMovieServiceSpy.updateMovieCalledWith( movie ))
            .to.equal( true, 'movieService.createMovie() must be called' +
            ' with the existing movie' );
        });
      });
    });

    describe( 'and given a stateProvider', () => {
      let stateSpy;
      beforeEach(() => {
        stateSpy = new StateSpy();
      });

      describe( 'when calling saveMovie()', () => {
        beforeEach( done => {
          controller = new Controller( ctxStub, stateSpy, logDummy,
            movieServiceDummy, movie );

          controller.saveMovie( movie ).then(() => {
            done();
          });
        });

        it( 'should navigate to the movie list afterwrards.', () => {
          const stateName = 'root.movie.list';

          expect( stateSpy.transitionTo.CalledWith( stateName )).to.equal(
            true, 'state.transitionTo must be called with ' + stateName );
        });
      });
    });

    describe( 'and given a fileReaderService and an image file', () => {
      let fileReaderStub;
      let imageFile;
      let expectedCount;

      beforeEach(() => {
        fileReaderStub = new FileReaderStub();
        imageFile = { name : 'foo.jpg', size : 123456, type: 'image/png' };
      });

      describe( 'when adding an image', () => {
        beforeEach( done => {
          expectedCount = movie.images.length + 1;
          controller = new Controller( ctxStub, stateDummy, logDummy,
            movieServiceDummy, movie, fileReaderStub );

          controller.addImage( imageFile ).then(() => {
            done();
          });
        });

        it( 'should add the image to the image collection', () => {
          expect( controller.data.images.length ).to.equal( expectedCount,
            'must add image to the image collection' );
        });
      });

      describe( 'and given the image to add already exists', () => {
        beforeEach(() => {
          movie.images.push( 'data:' + imageFile.type +
            ';base64,iVBORw0KGgoAA' );
        });

        describe( 'when adding a duplicate image', () => {
          beforeEach( done => {
            expectedCount = movie.images.length;
            controller = new Controller( ctxStub, stateDummy, logDummy,
              movieServiceDummy, movie, fileReaderStub );

            controller.addImage( imageFile ).then(() => {
              done();
            });
          });

          it( 'should not add the image to the image collection', () => {
            expect( controller.data.images.length ).to.equal( expectedCount,
              'must add image to the image collection' );
          });
        });

        describe( 'and given a logService', () => {
          let logSpy;

          beforeEach(() => {
            logSpy = new LogSpy();
          });

          describe( 'when adding a duplicate image', () => {
            beforeEach( done => {
              controller = new Controller( ctxStub, stateDummy, logSpy,
                movieServiceDummy, movie, fileReaderStub );

              controller.addImage( imageFile ).then(() => {
                done();
              });
            });

            it( 'should notify the user about the duplicate image', () => {
              expect( logSpy.infoCalledWith( 'Image alredy exists.' ))
                .to.equal( true, 'must log user info' );
            });
          });
        });
      });
    });

    describe( 'and given a failing fileReaderService, an image file and a' +
      ' log service',
    () => {
      let rejectingFileReaderStub;
      let logSpy;
      let imageFile;

      beforeEach(() => {
        rejectingFileReaderStub = new RejectingFileReaderStub();
        logSpy = new LogSpy();
        imageFile = { name : 'foo.jpg', size : 123456, type: 'image/png' };
      });

      describe( 'when adding an image', () => {
        beforeEach( done => {
          controller = new Controller( ctxStub, stateDummy, logSpy,
            movieServiceDummy, movie, rejectingFileReaderStub );

          controller.addImage( imageFile ).catch(() => {
            done();
          });
        });

        it( 'should log an error"Could not read image."', () => {
          expect( logSpy.errorCalledWith( 'Could not read image.' ))
            .to.equal( true, 'must log error' );
        });
      });
    });
  });

  describe( 'given a new movie', () => {
    let movie;

    beforeEach(() => {
      movie = {};
    });

    describe( 'when instatiating', () => {
      beforeEach(() => {
        controller = new Controller( ctxStub, stateDummy, logDummy,
          movieServiceDummy, movie );
      });

      it( 'should be in create mode', () => {
        expect( controller.isCreateMode() )
          .to.equal( true, 'must not be in create mode' );
      });
    });

    describe( 'and given a movieService that rejects with an error', () => {
      let movieServiceError;
      let rejectingMovieServiceSpy;
      let logSpy;

      beforeEach(() => {
        movieServiceError = 'fake webservice is down!';
        rejectingMovieServiceSpy = new RejectingMovieServiceSpy(
          Error( movieServiceError )
        );
        logSpy = new LogSpy();
      });

      describe( 'when calling saveMovie() with a new movie', () => {
        beforeEach( done => {
          controller = new Controller( ctxStub, stateDummy, logSpy,
            rejectingMovieServiceSpy, movie );

          controller.saveMovie( movie ).catch(() => {
            done();
          });
        });

        it( 'should log error "Could not save movie."', () => {
          expect( logSpy.errorCalledWith( 'Could not save movie.',
            movieServiceError )).to.equal( true, 'must log error' );
        });
      });
    });

    describe( 'and given a non-failing movieService', () => {
      let resolvingMovieServiceSpy;

      beforeEach(() => {
        resolvingMovieServiceSpy = new ResolvingMovieServiceSpy();
      });

      describe( 'when calling saveMovie() with a new movie', () => {
        let newMovie;

        beforeEach( done => {
          newMovie = { title: 'foo' };
          controller = new Controller( ctxStub, stateDummy, logDummy,
            resolvingMovieServiceSpy, movie );

          controller.saveMovie( newMovie ).then(() => {
            done();
          });
        });

        it( 'should call movieService create() with the newMovie', () => {
          expect( resolvingMovieServiceSpy.createMovieCalledWith( newMovie ))
            .to.equal( true, 'movieService.createMovie() must be called' +
            ' with the correct newMovie' );
        });
      });
    });

    describe( 'and given a stateProvider', () => {
      let stateSpy;

      beforeEach(() => {
        stateSpy = new StateSpy();
      });

      describe( 'when calling saveMovie()', () => {
        beforeEach( done => {
          controller = new Controller( ctxStub, stateSpy, logDummy,
            movieServiceDummy, movie );

          controller.saveMovie().then(() => {
            done();
          });
        });

        it( 'should navigate to the movie list afterwrards.', () => {
          const stateName = 'root.movie.list';

          expect( stateSpy.transitionTo.CalledWith( stateName )).to.equal(
            true, 'state.transitionTo must be called with ' + stateName );
        });
      });
    });
  });
});

class FileReaderStub {
  readAsDataUrl ( file ) {
    return Promise.resolve( 'data:' + file.type + ';base64,iVBORw0KGgoAA' );
  }
}

class RejectingFileReaderStub {
  readAsDataUrl () {
    return Promise.reject();
  }
}


text:
import {Component, Input, OnDestroy} from 'angular2/core';
import {MissionService} from './mission.service';
import {Subscription}   from 'rxjs/Subscription';
@Component({
    selector: 'my-astronaut',
    template: `

      {{astronaut}}: {{mission}}
      <button
        (click)="confirm()"
        [disabled]="!announced || confirmed">
        Confirm
      </button>

  `
})
export class AstronautComponent implements OnDestroy {
    @Input() astronaut: string;
    mission = "<no mission announced>";
    confirmed = false;
    announced = false;
    subscription: Subscription;
    constructor(private missionService: MissionService) {
        this.subscription = missionService.missionAnnounced$.subscribe(
            mission => {
                this.mission = mission;
                this.announced = true;
                this.confirmed = false;
            })
    }
    confirm() {
        this.confirmed = true;
        this.missionService.confirmMission(this.astronaut);
    }
    ngOnDestroy() {
        // prevent memory leak when component destroyed
        this.subscription.unsubscribe();
    }
}


text:
<?php

//require_once 'Hamcrest/Core/IsTypeOf.php';

/**
 * Tests whether the value is a resource.
 */
class Hamcrest_Type_IsResource extends Hamcrest_Core_IsTypeOf
{

  /**
   * Creates a new instance of IsResource
   */
  public function __construct()
  {
    parent::__construct('resource');
  }

  /**
   * Is the value a resource?
   *
   * @factory
   */
  public static function resourceValue()
  {
    return new self;
  }

}


text:
package com.omearac.shared

import akka.util.Timeout
import com.omearac.shared.EventMessages.FailedMessageConversion
import com.omearac.shared.KafkaMessages.{
  ExampleAppEvent,
  KafkaMessage,
  Stock,
  CollectorStatus
}
import play.api.libs.json.Json
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import spray.json._
import scala.concurrent.duration._

/**
  *
  */
object JsonMessageConversion {
  implicit val resolveTimeout = Timeout(3 seconds)

  trait Conversion[T] {
    def convertFromJson(msg: String): Either[FailedMessageConversion, T]
    def convertToJson(msg: T): String
  }

  object Conversion extends SprayJsonSupport with DefaultJsonProtocol {

    implicit object KafkaMessageConversions extends Conversion[KafkaMessage] {
      implicit val json3 = jsonFormat3(KafkaMessage)

      /**
        * Converts the JSON string from the CommittableMessage to KafkaMessage case class
        * @param msg is the json string to be converted to KafkaMessage case class
        * @return either a KafkaMessage or Unit (if conversion fails)
        */
      def convertFromJson(
          msg: String): Either[FailedMessageConversion, KafkaMessage] = {
        try {
          Right(msg.parseJson.convertTo[KafkaMessage])
        } catch {
          case e: Exception =>
            Left(FailedMessageConversion("kafkaTopic", msg, "to: KafkaMessage"))
        }
      }
      def convertToJson(msg: KafkaMessage) = {
        implicit val writes = Json.writes[KafkaMessage]
        Json.toJson(msg).toString
      }
    }

    implicit object ExampleAppEventConversion
        extends Conversion[ExampleAppEvent] {
      implicit val json3 = jsonFormat3(ExampleAppEvent)

      /**
        * Converts the JSON string from the CommittableMessage to ExampleAppEvent case class
        * @param msg is the json string to be converted to ExampleAppEvent case class
        * @return either a ExampleAppEvent or Unit (if conversion fails)
        */
      def convertFromJson(
          msg: String): Either[FailedMessageConversion, ExampleAppEvent] = {
        try {
          Right(msg.parseJson.convertTo[ExampleAppEvent])
        } catch {
          case e: Exception =>
            Left(
              FailedMessageConversion("kafkaTopic", msg, "to: ExampleAppEvent"))
        }
      }
      def convertToJson(msg: ExampleAppEvent) = {
        implicit val writes = Json.writes[ExampleAppEvent]
        Json.toJson(msg).toString
      }
    }

    implicit object StockConversion extends Conversion[Stock] {
      implicit val json2 = jsonFormat2(Stock)
      def convertFromJson(
          msg: String): Either[FailedMessageConversion, Stock] = {
        try {
          Right(msg.parseJson.convertTo[Stock])
        } catch {
          case e: Exception =>
            Left(FailedMessageConversion("kafkaTopic", msg, "to: Stock"))
        }
      }
      def convertToJson(msg: Stock) = {
        implicit val writes = Json.writes[Stock]
        Json.toJson(msg).toString
      }
    }

    /**
      * case class CollectorStatus(time: String, stocks: List[Stock], eventType: String)
      */
    implicit object CollectorStatusConversion
        extends Conversion[CollectorStatus] {
      implicit val stockFormat = jsonFormat2(Stock.apply)
      implicit val statusFormat: RootJsonFormat[CollectorStatus] = rootFormat(
        jsonFormat1(CollectorStatus))

      def convertFromJson(
          msg: String): Either[FailedMessageConversion, CollectorStatus] = {
        try {
          Right(msg.parseJson.convertTo[CollectorStatus])
        } catch {
          case e: Exception =>
            Left(
              FailedMessageConversion("kafkaTopic", msg, "to: CollectorStatus"))
        }
      }
      def convertToJson(msg: CollectorStatus) = {
        implicit val stock = Json.writes[Stock]
        implicit val collectorStatus = Json.writes[CollectorStatus]
        Json.toJson(msg).toString
      }
    }

    //Adding some sweet sweet syntactic sugar
    def apply[T: Conversion]: Conversion[T] = implicitly
  }

}


text:
namespace onnxruntime {
namespace cuda {

// assumptions:
// - dY, X, dX have input_size elements
// - B has bias_size elements
// - input_size % bias_size == 0
template <typename T, typename GeluComputationMode>
void LaunchBiasGeluGradDxKernel(
    cudaStream_t stream,
    int64_t input_size, int64_t bias_size,
    const T* dY, const T* X, const T* B, T* dX);

}  // namespace cuda
}  // namespace onnxruntime


text:
import sqlite3
import urllib
import re
from urllib.request import urlopen
from bs4 import BeautifulSoup
from phyllo.phyllo_logger import logger

def main():
# Case 1: Sections split by numbers (Roman or not) followed by a period, or bracketed. Subsections split by <p> tags
    def parsecase1(ptags, c, colltitle, title, author, date, URL):
        # ptags contains all <p> tags. c is the cursor object.
        chapter = '-1'
        verse = 1
        # entry deletion is done in main()
        for p in ptags:
            # make sure it's not a paragraph without the main text
            try:
                if p['class'][0].lower() in ['border', 'pagehead', 'shortborder', 'smallboarder', 'margin',
                                             'internal_navigation']:  # these are not part of the main t
                    continue
            except:
                pass
            passage = ''
            text = p.get_text().strip()
            # Skip empty paragraphs.
            if len(text) <= 0 or text.startswith('Cicero\n'):
                continue
            if url.endswith('nd3.shtml'):  # isolate nd3 so we don't accidentally bug out the others
                text = re.split('^([IVX]+)\.\s|^([0-9]+)\.\s|^\[([IVXL]+)\]|^\[([0-9]+)\]\s', text)
            else:
                text = re.split(
                    '^([IVX]+)\.\s|^([0-9]+)\.\s|^\[([IVXL]+)\]\s|^\[([0-9]+)\]\s|^\[\s([0-9]+)\]|^\[([0-9]+)',
                    text)
            for element in text:
                if element is None or element == '' or element.isspace():
                    text.remove(element)
            # The split should not alter sections with no prefixed roman numeral.
            if len(text) > 1:
                i = 0
                while text[i] is None:
                    i+=1
                if chapter == 'FRAGMENTA':
                    verse = text[i]
                else:
                    chapter = text[i]
                i+=1
                while text[i] is None:
                    i+=1
                passage = text[i].strip()
                if chapter == 'FRAGMENTA':
                    pass
                else:
                    verse = 1
            else:
                passage = text[0]
                if chapter == 'FRAGMENTA':
                    pass
                else:
                    verse+=1
            if passage.startswith("Cicero"):
                continue
            if passage.startswith("FRAGMENTA"):
                chapter = 'FRAGMENTA'
                continue
            c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                      (None, colltitle, title, 'Latin', author, date, chapter,
                       verse, passage.strip(), URL, 'prose'))

# Case 2: Sections are split by <p> tags and subsections by un/bracketed numbers.
    def parsecase2(ptags, c, colltitle, title, author, date, URL):
        # ptags contains all <p> tags. c is the cursor object.
        chapter = 0
        verse = '-1'
        # entry deletion is done in main()
        for p in ptags:
            # make sure it's not a paragraph without the main text
            try:
                if p['class'][0].lower() in ['border', 'pagehead', 'shortborder', 'smallboarder', 'margin',
                                             'internal_navigation']:  # these are not part of the main t
                    continue
            except:
                pass
            passage = ''
            text = p.get_text().strip()
            if text.startswith("Cicero\n"):
                continue
            # Skip empty paragraphs.
            if len(text) <= 0:
                continue
            text = re.split('([IVX]+)\.\s|([0-9]+)\.\s|\[([IVXL]+)\]\s|\[([0-9]+)\]\s', text)
            for element in text:
                if element is None or element == '' or element.isspace():
                    text.remove(element)
            chapter +=1
            for count, item in enumerate(text):
                if item is None:
                    continue
                if item.isnumeric() or len(item) < 5:
                    verse = item
                else:
                    passage = item
                    c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                              (None, colltitle, title, 'Latin', author, date, chapter,
                               verse, passage.strip(), URL, 'prose'))

# Case 3: Chapters separated by un/bracketed numbers, similarly to sentences.
    def parsecase3(ptags, c, colltitle, title, author, date, URL):
        chapter = '-1'
        verse = -1
        isnumeral = case3isNumeral(ptags)
        for p in ptags:
            # make sure it's not a paragraph without the main text
            try:
                if p['class'][0].lower() in ['border', 'pagehead', 'shortborder', 'smallboarder', 'margin',
                                             'internal_navigation']:  # these are not part of the main t
                    continue
            except:
                pass
            passage = ''
            text = p.get_text().strip()
            # Skip empty paragraphs.
            if len(text) <= 0:
                continue
            text = re.split('([IVXL]+)\.\s|([0-9]+)\.\s|\[([IVXL]+)\]\s|\[([0-9]+)\]\s', text)
            for item in text:
                if item is None:
                    continue
                item = item.strip()
                if item.isspace() or item == '' or item.startswith("Cicero\n"):
                    continue
                if item.isdigit() and not isnumeral:
                    chapter = item
                elif item.isdigit() and isnumeral:
                    verse = item
                elif len(item) < 5 and isnumeral:
                    chapter = item
                else:
                    passage = item
                    # Remove brackets if they have been picked up.
                    if chapter.startswith('['):
                        chapter = chapter[:-1]
                        chapter = chapter[1:]
                    if passage.startswith('['):
                        passage = passage[:-1]
                        passage = passage[1:]
                    if passage == chapter:
                        continue
                    else: # chapter/passage correction
                        chaptertest = chapter + 'I'
                        chaptertest2 = chapter[:-2] + 'V'
                        chaptertest3 = chapter[:-3] + 'V'
                        chaptertest4 = chapter[:-4] + 'IX'
                        chaptertest5 = chapter[:-2] + 'X'
                        if (chapter == 'LXIX' or chapter == 'LXX') and passage == 'L':
                            continue
                        if passage == chaptertest or passage == chaptertest2 or passage == chaptertest3\
                                or passage == chaptertest4 or passage == chaptertest5:
                            chapter = passage
                            continue
                    c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                              (None, colltitle, title, 'Latin', author, date, chapter,
                               verse, passage.strip(), URL, 'prose'))

# this function checks if the work uses Roman Numerals or numerical values for chapters.
    def case3isNumeral(ptags):
        for p in ptags:
            # make sure it's not a paragraph without the main text
            try:
                if p['class'][0].lower() in ['border', 'pagehead', 'shortborder', 'smallboarder', 'margin',
                                             'internal_navigation']:  # these are not part of the main t
                    continue
            except:
                pass
            if p.get_text().strip() is None or p.get_text().strip() == '':
                continue
            firstp = p.get_text().strip()
            break
        firstp = re.split('^([IVX]+)\.\s|^([0-9]+)\.\s|^\[([IVXL]+)\]\s|^\[([0-9]+)\]\s', firstp)
        if firstp[0] is not None:
            if firstp[0].isdigit():
                return False
            else:
                return True
        elif firstp[1] is not None:
            if firstp[1].isdigit():
                return False
            else:
                return True
        elif firstp[2] is not None:
            if firstp[2].isdigit():
                return False
            else:
                return True

    def parsespecial(ptags, c, colltitle, title, author, date, URL):
        chapter = -1
        verse = -1
        isnumeral = case3isNumeral(ptags)
        for p in ptags:
            # make sure it's not a paragraph without the main text
            try:
                if p['class'][0].lower() in ['border', 'pagehead', 'shortborder', 'smallborder', 'margin',
                                             'internal_navigation']:  # these are not part of the main t
                    continue
            except:
                pass
            passage = ''
            if title.endswith('FONTEIO') or title.endswith('FLACCO'):
                potentialchap = p.find('I') # chapters italicized #always returns none for some reason.
                text = p.get_text()
                if text is None:
                    continue
                text = text.strip()
                if p.i is not None or p.center is not None: # this also is never true for some reason.
                    chapter = text
                    continue
                if potentialchap is not None:
                    potentialchap = None
                    chapter = p.get_text().strip()
                    continue
                else:
                    # read in verse number and passage
                    text = re.split('\[([0-9]+)\]', text)
                    for element in text:
                        if element is None:
                            continue
                        if element == '' or element.isspace():
                            continue
                        element = element.strip()
                        if element.isdigit():
                            verse = element
                        else:
                            passage = element
                            if passage.startswith("Cicero\n"):
                                continue
                            c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                                      (None, colltitle, title, 'Latin', author, date, chapter,
                                       verse, passage, URL, 'prose'))
            elif title.endswith('Paradoxica'):
                potentialchap = p.find('B') # chapters bolded

                if potentialchap is not None:
                    chapter = potentialchap.find(text=True)
                    continue
                else:
                    # read in verse number and passage
                    text = p.get_text()
                    if text is None:
                        continue
                    text = re.split('\[([0-9]+)\]', text)
                    for element in text:
                        if element is None:
                            continue
                        if element == '' or element.isspace():
                            continue
                        element = element.strip()
                        if element.isdigit():
                            verse = element
                        else:
                            passage = element
                            c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                                      (None, colltitle, title, 'Latin', author, date, chapter,
                                       verse, passage, URL, 'prose'))
            elif title.endswith('Partitione'):
                # chapter split by paragraph, verse by speaker
                text = p.get_text()
                if text is None:
                    continue
                text = text.strip()
                text = re.split('\[([0-9]+)\]', text)
                chaptext = ''
                for item in text:
                    if item.isspace() or item == '' or item is None:
                        continue
                    elif item.isnumeric():
                        chapter = item
                        continue
                    else:
                        chaptext += item
                        if item.startswith('Cicero\n'):
                            continue
                        try:
                            chaptext = re.split('\[([0-9]+)\]|(CICERO FILIUS)\.\s|(CICERO PATER)\.\s|(C\.F\.)\s|(C\.P\.)\s', chaptext)
                            for piece in chaptext:
                                if piece is None:
                                    continue
                                if piece == '' or piece.isspace():
                                    continue
                                piece = piece.strip()
                                if piece.startswith('CI') or piece.startswith("C."):
                                    verse = piece
                                    continue
                                elif piece.isnumeric():
                                    chapter = piece
                                else:
                                    passage = piece
                                    c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                                              (None, colltitle, title, 'Latin', author, date, chapter,
                                               verse, passage, URL, 'prose'))
                        except:
                            c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                                      (None, colltitle, title, 'Latin', author, date, chapter,
                                       verse, item.strip(), URL, 'prose'))

    # This case parses poetry
    def parsePoem(ptags, c, colltitle, title, author, date, url):
        chapter = -1
        verse = 0
        for p in ptags:
            # make sure it's not a paragraph without the main text
            try:
                if p['class'][0].lower() in ['border', 'pagehead', 'shortborder', 'smallboarder', 'margin',
                                             'internal_navigation']:  # these are not part of the main t
                    continue
            except:
                pass
            # find chapter
            chapter_f = p.find('b')
            if chapter_f is not None:
                chapter = p.get_text().strip()
                verse = 0
                continue
            else:
                brtags = p.findAll('br')
                verses = []
                try:
                    try:
                        firstline = brtags[0].previous_sibling.strip()
                    except:
                        firstline = brtags[0].previous_sibling.previous_sibling.strip()
                    verses.append(firstline)
                except:
                    pass
                for br in brtags:
                    try:
                        text = br.next_sibling.next_sibling.strip()
                    except:
                        text = br.next_sibling.strip()
                    if text is None or text == '' or text.isspace():
                        continue
                    verses.append(text)
            for v in verses:
                # verse number assignment.
                verse += 1
                c.execute("INSERT INTO texts VALUES (?,?,?,?,?,?,?, ?, ?, ?, ?)",
                          (None, colltitle, title, 'Latin', author, date, chapter,
                           verse, v, url, 'poetry'))

    def getBooks(soup):
        textsURL = []
        # get links to books in the collection
        for a in soup.find_all('a', href=True):
            link = a['href']
            textsURL.append("{}/{}".format(siteURL, a['href']))

        # remove unnecessary URLs
        while ("http://www.thelatinlibrary.com/index.html" in textsURL):
            textsURL.remove("http://www.thelatinlibrary.com/index.html")
            textsURL.remove("http://www.thelatinlibrary.com/classics.html")
        logger.info("\n".join(textsURL))
        return textsURL

    # for nested hyperlinked works
    def altgetbook(soup):
        textsURL = []
        siteURL = "http://www.thelatinlibrary.com/cicero"
        # get links to books in the collection
        for a in soup.find_all('a', href=True):
            link = a['href']
            textsURL.append("{}/{}".format(siteURL, a['href']))

        # remove unnecessary URLs
        while ("http://www.thelatinlibrary.com/cicero//index.html" in textsURL):
            textsURL.remove("http://www.thelatinlibrary.com/cicero//index.html")
            textsURL.remove("http://www.thelatinlibrary.com/cicero//cic.html")
            textsURL.remove("http://www.thelatinlibrary.com/cicero//classics.html")
        logger.info("\n".join(textsURL))
        return textsURL

# main code
    siteURL = 'http://www.thelatinlibrary.com'
    ciceroURL = 'http://www.thelatinlibrary.com/cic.html'
    ciceroOpen = urllib.request.urlopen(ciceroURL)
    ciceroSOUP = BeautifulSoup(ciceroOpen, 'html5lib')
    author = ciceroSOUP.title.string.strip()
    colltitle = ciceroSOUP.h1.string.strip()
    date = ciceroSOUP.h2.contents[0].strip().replace('(', '').replace(')', '').replace(u"\u2013", '-')

    textsURL = getBooks(ciceroSOUP)

# pro ligario (case 1) needs to be moved to case 3
# pro Deitario is weird.
    caseOneList = ['http://www.thelatinlibrary.com/cicero/quinc.shtml',
                   'http://www.thelatinlibrary.com/cicero/imp.shtml',
                   'http://www.thelatinlibrary.com/cicero/murena.shtml',
                   'http://www.thelatinlibrary.com/cicero/sulla.shtml',
                   'http://www.thelatinlibrary.com/cicero/arch.shtml',
                   'http://www.thelatinlibrary.com/cicero/postreditum.shtml',
                   'http://www.thelatinlibrary.com/cicero/postreditum2.shtml',
                   'http://www.thelatinlibrary.com/cicero/cael.shtml',
                   'http://www.thelatinlibrary.com/cicero/piso.shtml',
                   'http://www.thelatinlibrary.com/cicero/marc.shtml',
                   'http://www.thelatinlibrary.com/cicero/lig.shtml',
                   'http://www.thelatinlibrary.com/cicero/deio.shtml',
                   'http://www.thelatinlibrary.com/cicero/fato.shtml',
                   'http://www.thelatinlibrary.com/cicero/brut.shtml',
                   'http://www.thelatinlibrary.com/cicero/acad.shtml',
                   'http://www.thelatinlibrary.com/cicero/amic.shtml',
                   'http://www.thelatinlibrary.com/cicero/compet.shtml'
                   ]
    caseTwoList = ['http://www.thelatinlibrary.com/cicero/sex.rosc.shtml',
                   'http://www.thelatinlibrary.com/cicero/rosccom.shtml',
                   'http://www.thelatinlibrary.com/cicero/caecina.shtml',
                   'http://www.thelatinlibrary.com/cicero/rabirio.shtml',
                   'http://www.thelatinlibrary.com/cicero/domo.shtml',
                   'http://www.thelatinlibrary.com/cicero/haruspicum.shtml',
                   'http://www.thelatinlibrary.com/cicero/balbo.shtml',
                   'http://www.thelatinlibrary.com/cicero/milo.shtml',
                   'http://www.thelatinlibrary.com/cicero/topica.shtml',
                     'http://www.thelatinlibrary.com/cicero/scauro.shtml'
                   ]
    caseThreeList = ['http://www.thelatinlibrary.com/cicero/cluentio.shtml',
                     'http://www.thelatinlibrary.com/cicero/plancio.shtml',
                     'http://www.thelatinlibrary.com/cicero/sestio.shtml',
                     'http://www.thelatinlibrary.com/cicero/vatin.shtml',
                     'http://www.thelatinlibrary.com/cicero/prov.shtml',
                     'http://www.thelatinlibrary.com/cicero/rabiriopost.shtml'
                     'http://www.thelatinlibrary.com/cicero/optgen.shtml',
                     'http://www.thelatinlibrary.com/cicero/orator.shtml',
                     'http://www.thelatinlibrary.com/cicero/senectute.shtml'
                     ]
    specialcases = ['http://www.thelatinlibrary.com/cicero/flacco.shtml',
                    'http://www.thelatinlibrary.com/cicero/fonteio.shtml',
                    'http://www.thelatinlibrary.com/cicero/paradoxa.shtml',
                    'http://www.thelatinlibrary.com/cicero/partitione.shtml'
                    ]
    getURLList = ['http://www.thelatinlibrary.com/cicero/legagr.shtml',
                  'http://www.thelatinlibrary.com/cicero/ver.shtml',
                  'http://www.thelatinlibrary.com/cicero/cat.shtml',
                  'http://www.thelatinlibrary.com/cicero/phil.shtml',
                  'http://www.thelatinlibrary.com/cicero/inventione.shtml',
                  'http://www.thelatinlibrary.com/cicero/oratore.shtml',
                  'http://www.thelatinlibrary.com/cicero/leg.shtml',
                  'http://www.thelatinlibrary.com/cicero/fin.shtml',
                  'http://www.thelatinlibrary.com/cicero/tusc.shtml',
                  'http://www.thelatinlibrary.com/cicero/nd.shtml',
                  'http://www.thelatinlibrary.com/cicero/divinatione.shtml',
                  'http://www.thelatinlibrary.com/cicero/off.shtml'
                  ]
    #notes: repub uses parenthesis instead of brackets; apparently there are two repub.shtml
    # leg is some kind of play
    # tusc has numbers by itself.
    # divinatione is truly a nightmare
    # caecilium, phillipic, oratore, milone and/or cluentio-oratio, plancio, sestio might/n't need a new case

    poemList = ['http://www.thelatinlibrary.com/cicero/repub.shtml']

    with sqlite3.connect('texts.db') as db:
        c = db.cursor()
        c.execute(
        'CREATE TABLE IF NOT EXISTS texts (id INTEGER PRIMARY KEY, title TEXT, book TEXT,'
        ' language TEXT, author TEXT, date TEXT, chapter TEXT, verse TEXT, passage TEXT,'
        ' link TEXT, documentType TEXT)')
        c.execute("DELETE FROM texts WHERE author='Cicero'")

        for url in getURLList:
            openu = urllib.request.urlopen(url)
            soup = BeautifulSoup(openu, 'html5lib')
            urltexts = getBooks(soup)
            for urlt in urltexts:
                openurl = urllib.request.urlopen(url)
                textsoup = BeautifulSoup(openurl, 'html5lib')
                try:
                    title = textsoup.title.string.split(':')[1].strip()
                except:
                    title = textsoup.title.string.strip()
                getp = textsoup.find_all('p')
                # url refers to the url of the collection's  collection. urlt is the url that the text/passages are found
                if url.endswith("legagr.shtml") or urlt.endswith("caecilium.shtml") or url.endswith("cat.shtml") \
                        or url.endswith('phil.shtml') or url.endswith('oratore.shtml') or urlt.endswith("fin1.shtml") \
                        or urlt.endswith('fin2.shtml') or urlt.endswith('fin3.shtml') \
                        or (url.endswith('nd.shtml') and not urlt.endswith('nd3.shtml')):
                    parsecase2(getp, c, colltitle, title, author, date, urlt)
                elif (url.endswith("ver.shtml") and not urlt.endswith('caecilium.shtml')) \
                        or url.endswith('inventione.shtml') or urlt.endswith('nd3.shtml') or url.endswith('off.shtml') \
                        or url.endswith('inventione.shtml') or url.endswith('leg.shtml') or url.endswith('tusc.shtml'):
                    parsecase1(getp, c, colltitle, title, author, date, urlt)
                elif urlt.endswith('fin4.shtml') or urlt.endswith('fin5.shtml') or url.endswith('divinatione.shtml'):
                    parsecase3(getp, c, colltitle, title, author, date, urlt)

        for url in textsURL:
            openurl = urllib.request.urlopen(url)
            textsoup = BeautifulSoup(openurl, 'html5lib')
            try:
                title = textsoup.title.string.split(':')[1].strip()
            except:
                title = textsoup.title.string.strip()
            getp = textsoup.find_all('p')
            if url in caseOneList:
                parsecase1(getp, c, colltitle, title, author, date, url)
            elif url in caseTwoList:
                parsecase2(getp, c, colltitle, title, author, date, url)
            elif url in caseThreeList:
                parsecase3(getp, c, colltitle, title, author, date, url)
            elif url in specialcases:
                parsespecial(getp, c, colltitle, title, author, date, url)
            elif url in poemList:
                parsePoem(getp, c, colltitle, title, author, date, url)

    logger.info("Program runs successfully.")

if __name__ == '__main__':
    main()


text:
layout:     post
title:      "PBR Cloth&Fabric"
date:       2018-06-25
author:     "ChenYong"
header-img: "img/post-bg-fabric.jpg"
tags:
    - Unity
    - PBR
    - Fabric
    - 原创
---

### 物理性质

现实中的布料织物大概可分为表面粗糙和光滑两类。表面粗糙的织物有棉布、亚麻布等,表面光滑的织物有丝绸、天鹅绒等。
棉布类织物表面主要为较淡的织物颜色组成的漫反射,丝绸类织物表面有类金属的反射,而且会有多种的高光颜色。
观察还发现棉布类织物纤维周围有一圈很细的绒毛,丝绸类织物的纤维绒毛很少。
![这里写图片描述](/img/in-post/fabric/2.png)
现实织物的物理表现
这些物理特性中的主体表面部分适合用PBR的metalic和Rougthness来描述,绒毛和多种高光部分需增加一个Fabric Scatter模型(详细见下文)来描述。
下图为参考文献1的作者给出的描述不同布料织物的PBR**经验**参数:
![这里写图片描述](/img/in-post/fabric/1.png)
模拟织物的PBR参数
注意上图中的velvet(天鹅绒)的rougthness和metalic都为1,这符合天鹅绒表面粗糙,看起来很黑(漫反射很弱)的物理特性。

### Microfiber Model

#### Inverted Gaussian
布料织物有其特有的光照反射模型。以天鹅绒为例,它的高光位置不是灯光和视线的正对区域,而是边缘位置。
![这里写图片描述](/img/in-post/fabric/3.jpg)
理想高光反射与实际织物的反射对比

标准PBR的Microfacet GGX分布在0角度下(法线、灯光和视线同向)获得最大的高光强度,然后随着角度的增大做正太(Gaussian)分布,
而天鹅绒高光分布与GGX刚好相反,可见GGX的分布模型并不适合某些布料的模拟。

*The Order:1886* 游戏采用Inverted Gaussian模型做为布料的高光分布模型,参考文献1的作者在此基础上进一步简化得到:
![这里写图片描述](/img/in-post/fabric/4.jpg)
GGX分布曲线与自定义分布曲线对比

shader代码:
```
inline float FabricD (float NdotH, float roughness)
{
    return 0.96 * pow(1 - NdotH, 2) + 0.057;
}
```

用FabricD替换掉UnityStandardBRDF.cginc的BRDF1_Unity_PBS函数的GGXTerm。

![这里写图片描述](/img/in-post/fabric/6.jpg)
Roughness为1时GGXTerm与FabricD结果对比

#### Fabric Scatter
布料织物的绒毛效果可由边缘光来模拟,再综合丝绸的高光颜色,参考文献1的作者给出一个Fabric Scatter**经验**模型:

1.修改标准PBR的Fresnel term,用4倍pow值代替标准的5倍pow值,用于增大Fresnel的范围;

2.再叠加一层跟视角相关的范围更大的,可调的Fresnel颜色用于更好的模拟织物表面的高光;

3.去掉标准PBR的间接光反射,使得metallic-like的布料不那么metallic。

shader代码:
```
inline half FabricScatterFresnelLerp(half nv, half scale)
{
    half t0 = Pow4 (1 - nv);
    half t1 = 0.4 * (1 - nv);
    return (t1 - t0) * scale + t0;
}
```

BRDF1_Unity_PBS函数返回颜色:
```
half3 color =   diffColor * (gi.diffuse + light.color * diffuseTerm)
                + specularTerm * light.color * FresnelTerm (specColor, lh)
                + _FabricScatterColor * (nl*0.5 + 0.5) * FabricScatterFresnelLerp(nv, _FabricScatterScale);
```

### 结果1
![这里写图片描述](/img/in-post/fabric/5.jpg)
标准PBR和自定义实现的天鹅绒效果对比

### 结果2
![这里写图片描述](/img/in-post/fabric/cloth.jpg)
自定义实现的棉布和丝绸效果

### 附
完整FABRIC_BRDF_PBS代码:
```
#if _FABRIC
inline float FabricD (float NdotH, float roughness)
{
    return 0.96 * pow(1 - NdotH, 2) + 0.057;
}

inline half FabricScatterFresnelLerp(half nv, half scale)
{
    half t0 = Pow4 (1 - nv);
    half t1 = 0.4 * (1 - nv);
    return (t1 - t0) * scale + t0;
}

half4 FABRIC_BRDF_PBS (half3 diffColor, half3 specColor, half oneMinusReflectivity, half smoothness,
    float3 normal, float3 viewDir,
    UnityLight light, UnityIndirect gi)
{
    float perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
    float3 halfDir = Unity_SafeNormalize (float3(light.dir) + viewDir);

// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
// Following define allow to control this. Set it to 0 if ALU is critical on your platform.
// This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
// Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
#define UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV 0

#if UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV
    // The amount we shift the normal toward the view vector is defined by the dot product.
    half shiftAmount = dot(normal, viewDir);
    normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
    // A re-normalization should be applied here but as the shift is small we don't do it to save ALU.
    //normal = normalize(normal);

    half nv = saturate(dot(normal, viewDir)); // TODO: this saturate should no be necessary here
#else
    half nv = abs(dot(normal, viewDir));    // This abs allow to limit artifact
#endif

    half nl = saturate(dot(normal, light.dir));
    float nh = saturate(dot(normal, halfDir));

    half lv = saturate(dot(light.dir, viewDir));
    half lh = saturate(dot(light.dir, halfDir));

    // Diffuse term
    half diffuseTerm = DisneyDiffuse(nv, nl, lh, perceptualRoughness) * nl;

    // Specular term
    // HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
    // BUT 1) that will make shader look significantly darker than Legacy ones
    // and 2) on engine side "Non-important" lights have to be divided by Pi too in cases when they are injected into ambient SH
    float roughness = PerceptualRoughnessToRoughness(perceptualRoughness);
    roughness = max(roughness, 0.002);
    half V = SmithJointGGXVisibilityTerm (nl, nv, roughness);
    float D = GGXTerm (nh, roughness);

    float VxD= roughness > 0.99 ? 1 * FabricD (nh, roughness) : V * D;

    half specularTerm = VxD * UNITY_PI; // Torrance-Sparrow model, Fresnel is applied later

#ifdef UNITY_COLORSPACE_GAMMA
    specularTerm = sqrt(max(1e-4h, specularTerm));
#endif

    // specularTerm * nl can be NaN on Metal in some cases, use max() to make sure it's a sane value
    specularTerm = max(0, specularTerm * nl);
#if defined(_SPECULARHIGHLIGHTS_OFF)
    specularTerm = 0.0;
#endif

    // surfaceReduction = Int D(NdotH) * NdotH * Id(NdotL>0) dH = 1/(roughness^2+1)
    half surfaceReduction;
#ifdef UNITY_COLORSPACE_GAMMA
        surfaceReduction = 1.0-0.28*roughness*perceptualRoughness;      // 1-0.28*x^3 as approximation for (1/(x^4+1))^(1/2.2) on the domain [0;1]
#else
        surfaceReduction = 1.0 / (roughness*roughness + 1.0);           // fade \in [0.5;1]
#endif

    // To provide true Lambert lighting, we need to be able to kill specular completely.
    specularTerm *= any(specColor) ? 1.0 : 0.0;

    half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
    half3 color =   diffColor * (gi.diffuse + light.color * diffuseTerm)
                    + specularTerm * light.color * FresnelTerm (specColor, lh)
                    + _FabricScatterColor * (nl*0.5 + 0.5) * FabricScatterFresnelLerp(nv, _FabricScatterScale);

    return half4(color, 1);
}
#endif
```

参考文献:

https://www.slideshare.net/jalnaga/custom-fabric-shader-for-unreal-engine-4

http://gennyx.blogspot.com/2009/11/its-material-world_11.html

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.105.1847&rep=rep1&type=pdf

http://blog.selfshadow.com/publications/s2013-shading-course/rad/s2013_pbs_rad_notes.pdf


text:
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Diagnostics.Contracts;
using System;

// Disable the "this variable is not used" warning as every field would imply it.
#pragma warning disable 0414
// Disable the "this variable is never assigned to".
#pragma warning disable 0067
// Disable the "this event is never assigned to".
#pragma warning disable 0649
// Disable the "this variable is never used".
#pragma warning disable 0169
// Disable the "new keyword not required" warning.
#pragma warning disable 0109
// Disable the "extern without DllImport" warning.
#pragma warning disable 0626
// Disable the "could hide other member" warning, can happen on certain properties.
#pragma warning disable 0108

namespace System.Runtime.InteropServices.ComTypes
{
  public partial interface IDataObject
  {
    #region Methods and constructors
    int DAdvise(ref FORMATETC pFormatetc, ADVF advf, IAdviseSink adviseSink, out int connection);

    void DUnadvise(int connection);

    int EnumDAdvise(out IEnumSTATDATA enumAdvise);

    IEnumFORMATETC EnumFormatEtc(DATADIR direction);

    int GetCanonicalFormatEtc(ref FORMATETC formatIn, out FORMATETC formatOut);

    void GetData(ref FORMATETC format, out STGMEDIUM medium);

    void GetDataHere(ref FORMATETC format, ref STGMEDIUM medium);

    int QueryGetData(ref FORMATETC format);

    void SetData(ref FORMATETC formatIn, ref STGMEDIUM medium, bool release);
    #endregion
  }
}


text:
#include "config.h"
#include "MonthInputType.h"

#include "DateComponents.h"
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "InputTypeNames.h"
#include <wtf/CurrentTime.h>
#include <wtf/DateMath.h>
#include <wtf/MathExtras.h>
#include <wtf/PassOwnPtr.h>

#if ENABLE(INPUT_TYPE_MONTH)

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
#include "DateTimeFieldsState.h"
#include "LocalizedStrings.h"
#include "PlatformLocale.h"
#include <wtf/text/WTFString.h>
#endif

namespace WebCore {

using namespace HTMLNames;

static const int monthDefaultStep = 1;
static const int monthDefaultStepBase = 0;
static const int monthStepScaleFactor = 1;

PassOwnPtr<InputType> MonthInputType::create(HTMLInputElement* element)
{
    return adoptPtr(new MonthInputType(element));
}

const AtomicString& MonthInputType::formControlType() const
{
    return InputTypeNames::month();
}

DateComponents::Type MonthInputType::dateType() const
{
    return DateComponents::Month;
}

double MonthInputType::valueAsDate() const
{
    DateComponents date;
    if (!parseToDateComponents(element()->value(), &date))
        return DateComponents::invalidMilliseconds();
    double msec = date.millisecondsSinceEpoch();
    ASSERT(isfinite(msec));
    return msec;
}

String MonthInputType::serializeWithMilliseconds(double value) const
{
    DateComponents date;
    if (!date.setMillisecondsSinceEpochForMonth(value))
        return String();
    return serializeWithComponents(date);
}

Decimal MonthInputType::defaultValueForStepUp() const
{
    double current = currentTimeMS();
    double utcOffset = calculateUTCOffset();
    double dstOffset = calculateDSTOffset(current, utcOffset);
    int offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute);
    current += offset * msPerMinute;

    DateComponents date;
    date.setMillisecondsSinceEpochForMonth(current);
    double months = date.monthsSinceEpoch();
    ASSERT(isfinite(months));
    return Decimal::fromDouble(months);
}

StepRange MonthInputType::createStepRange(AnyStepHandling anyStepHandling) const
{
    DEFINE_STATIC_LOCAL(const StepRange::StepDescription, stepDescription, (monthDefaultStep, monthDefaultStepBase, monthStepScaleFactor, StepRange::ParsedStepValueShouldBeInteger));

    const Decimal stepBase = parseToNumber(element()->fastGetAttribute(minAttr), Decimal::fromDouble(monthDefaultStepBase));
    const Decimal minimum = parseToNumber(element()->fastGetAttribute(minAttr), Decimal::fromDouble(DateComponents::minimumMonth()));
    const Decimal maximum = parseToNumber(element()->fastGetAttribute(maxAttr), Decimal::fromDouble(DateComponents::maximumMonth()));
    const Decimal step = StepRange::parseStep(anyStepHandling, stepDescription, element()->fastGetAttribute(stepAttr));
    return StepRange(stepBase, minimum, maximum, step, stepDescription);
}

Decimal MonthInputType::parseToNumber(const String& src, const Decimal& defaultValue) const
{
    DateComponents date;
    if (!parseToDateComponents(src, &date))
        return defaultValue;
    double months = date.monthsSinceEpoch();
    ASSERT(isfinite(months));
    return Decimal::fromDouble(months);
}

bool MonthInputType::parseToDateComponentsInternal(const UChar* characters, unsigned length, DateComponents* out) const
{
    ASSERT(out);
    unsigned end;
    return out->parseMonth(characters, length, 0, end) && end == length;
}

bool MonthInputType::setMillisecondToDateComponents(double value, DateComponents* date) const
{
    ASSERT(date);
    return date->setMonthsSinceEpoch(value);
}

bool MonthInputType::isMonthField() const
{
    return true;
}

#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
String MonthInputType::formatDateTimeFieldsState(const DateTimeFieldsState& dateTimeFieldsState) const
{
    if (!dateTimeFieldsState.hasMonth() || !dateTimeFieldsState.hasYear())
        return emptyString();
    return String::format("%04u-%02u", dateTimeFieldsState.year(), dateTimeFieldsState.month());
}

void MonthInputType::setupLayoutParameters(DateTimeEditElement::LayoutParameters& layoutParameters, const DateComponents& date) const
{
    layoutParameters.dateTimeFormat = layoutParameters.locale.monthFormat();
    layoutParameters.fallbackDateTimeFormat = "MM/yyyy";
    layoutParameters.minimumYear = fullYear(element()->fastGetAttribute(minAttr));
    layoutParameters.maximumYear = fullYear(element()->fastGetAttribute(maxAttr));
    layoutParameters.placeholderForMonth = "--";
    layoutParameters.placeholderForYear = "----";
}
#endif
} // namespace WebCore

#endif


text:
"""
Lino's comments framework.  See :doc:`/specs/comments`.

"""

from lino import ad, _

class Plugin(ad.Plugin):
    "See :doc:`/dev/plugins`."
    verbose_name = _("Comments")

    site_js_snippets = ['comments/comments.js']

    needs_plugins = ['lino.modlib.office', 'lino.modlib.memo']

    # emotion_range = "social"
    emotion_range = "business"
    """Which range of emotion icons to provide. Either "business" or "social".
    """

    private_default = True
    """Whether comments are private by default.

    The default value for the :attr:`lino.modlib.comments.Comment.private`
    field.

    """

    def setup_main_menu(self, site, user_type, m):
        mg = site.plugins.office
        m = m.add_menu(mg.app_label, mg.verbose_name)
        m.add_action('comments.MyComments')
        # if self.user_must_publish:
        #     m.add_action('comments.MyPendingComments')
        m.add_action('comments.RecentComments')

    def setup_config_menu(self, site, user_type, m):
        mg = site.plugins.office
        m = m.add_menu(mg.app_label, mg.verbose_name)
        m.add_action('comments.CommentTypes')

    def setup_explorer_menu(self, site, user_type, m):
        mg = site.plugins.office
        m = m.add_menu(mg.app_label, mg.verbose_name)
        m.add_action('comments.AllComments')
        m.add_action('comments.Mentions')
        m.add_action('comments.Reactions')

    def get_dashboard_items(self, user):
        # if self.user_must_publish:
        #     yield self.site.models.comments.MyPendingComments
        yield self.site.models.comments.RecentComments


text:
FactoryBot.define do
  factory :user_detail do
    user
    job_title { 'VP of Sales' }
  end
end


text:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-comp-1646',
  templateUrl: './comp-1646.component.html',
  styleUrls: ['./comp-1646.component.css']
})
export class Comp1646Component implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}


text:
class CXFA_TraverseStrategy_PageAreaContainerLayoutItem {
 public:
  static inline CXFA_ContainerLayoutItem* GetFirstChild(
      CXFA_ContainerLayoutItem* pLayoutItem) {
    if (pLayoutItem->m_pFormNode->GetClassID() == XFA_ELEMENT_PageSet) {
      return (CXFA_ContainerLayoutItem*)pLayoutItem->m_pFirstChild;
    }
    return NULL;
  }
  static inline CXFA_ContainerLayoutItem* GetNextSibling(
      CXFA_ContainerLayoutItem* pLayoutItem) {
    return (CXFA_ContainerLayoutItem*)pLayoutItem->m_pNextSibling;
  }
  static inline CXFA_ContainerLayoutItem* GetParent(
      CXFA_ContainerLayoutItem* pLayoutItem) {
    return (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent;
  }
};
class CXFA_TraverseStrategy_ContentAreaContainerLayoutItem {
 public:
  static inline CXFA_ContainerLayoutItem* GetFirstChild(
      CXFA_ContainerLayoutItem* pLayoutItem) {
    for (CXFA_LayoutItem* pChildItem = pLayoutItem->m_pFirstChild; pChildItem;
         pChildItem = pChildItem->m_pNextSibling) {
      if (CXFA_ContainerLayoutItem* pContainer =
              pChildItem->AsContainerLayoutItem()) {
        return pContainer;
      }
    }
    return nullptr;
  }
  static inline CXFA_ContainerLayoutItem* GetNextSibling(
      CXFA_ContainerLayoutItem* pLayoutItem) {
    for (CXFA_LayoutItem* pChildItem = pLayoutItem->m_pNextSibling; pChildItem;
         pChildItem = pChildItem->m_pNextSibling) {
      if (CXFA_ContainerLayoutItem* pContainer =
              pChildItem->AsContainerLayoutItem()) {
        return pContainer;
      }
    }
    return nullptr;
  }
  static inline CXFA_ContainerLayoutItem* GetParent(
      CXFA_ContainerLayoutItem* pLayoutItem) {
    return (CXFA_ContainerLayoutItem*)pLayoutItem->m_pParent;
  }
};
class CXFA_TraverseStrategy_ContentLayoutItem {
 public:
  static inline CXFA_ContentLayoutItem* GetFirstChild(
      CXFA_ContentLayoutItem* pLayoutItem) {
    return (CXFA_ContentLayoutItem*)pLayoutItem->m_pFirstChild;
  }
  static inline CXFA_ContentLayoutItem* GetNextSibling(
      CXFA_ContentLayoutItem* pLayoutItem) {
    return (CXFA_ContentLayoutItem*)pLayoutItem->m_pNextSibling;
  }
  static inline CXFA_ContentLayoutItem* GetParent(
      CXFA_ContentLayoutItem* pLayoutItem) {
    return (CXFA_ContentLayoutItem*)pLayoutItem->m_pParent;
  }
};
FX_DWORD XFA_GetRelevant(CXFA_Node* pFormItem, FX_DWORD dwParentRelvant);
void XFA_ReleaseLayoutItem(CXFA_LayoutItem* pLayoutItem);
#endif


text:
import sys

if sys.version < "3.2":
	print("Konstrukteur requires Python 3.2 or higher")
	sys.exit(1)

# Prefer setuptools (aka distribute) over distutils
# - Distutils comes with Python3 but is not capable of installing requires, extras, etc.
# - Distribute is a fork of the Setuptools project (http://packages.python.org/distribute/)
try:
	from setuptools import setup
	uses = "distribute"
except ImportError:
	print("Konstrukteur prefers distribute over distutils for installing dependencies!")
	from distutils.core import setup
	uses = "distutils"

if uses == "distribute":

	extra = {

		#"test_suite" : "jasy.test",

		"install_requires" : [
			"jasy==1.5-beta7",
			"pystache>=0.5.3",
			"beautifulsoup4>=4.3.2",
			"misaka>=1.0.2",

			# Requirements of watchdog lib
			"pathtools>=0.1.1",
			"PyYAML>=3.09",
			"argh>=0.8.1",
			"unidecode>=0.4.14",
			"python-dateutil>=2.2"
		]

	}

else:

	extra = {}

# Integrate batch script for win32 only
extra["scripts"] = [ "bin/konstrukteur" ]
if sys.platform == "win32":
	extra["scripts"] += [ "bin/konstrukteur.bat" ]

# Import konstrukteur for version info etc.
import konstrukteur

# Run setup
setup(
	name = 'konstrukteur',
	version = konstrukteur.__version__,

	author = 'Sebastian Software',
	author_email = 'team@sebastian-software.de',

	maintainer = 'Sebastian Software',
	maintainer_email = 'team@sebastian-software.de',

	url = 'http://github.com/fastner/konstrukteur',
	download_url = "http://pypi.python.org/packages/source/k/konstrukteur/konstrukteur-%s.zip" % konstrukteur.__version__,

	license = "MIT",
	platforms = 'any',

	description = "Static website generator",
	long_description = """Konstrukteur is a static website generator based upon jasy.""",

	# Via: http://pypi.python.org/pypi?%3Aaction=list_classifiers
	classifiers = [
		'Development Status :: 4 - Beta',
		'Environment :: Console',
		'Intended Audience :: Developers',
		'License :: OSI Approved :: MIT License',
		'License :: Freely Distributable',
		'Operating System :: OS Independent',
		'Programming Language :: Python',
		'Programming Language :: Python :: 3',
		'Programming Language :: Python :: 3.2',
		'Programming Language :: Python :: 3.3',
		'Programming Language :: Python :: 3.4',
		'Topic :: Software Development :: Code Generators',
		'Topic :: Software Development :: Internationalization',
		"Topic :: Internet :: WWW/HTTP"
	],

	packages = [
		"konstrukteur",
		"konstrukteurlibs/watchdog/src/watchdog",
		"konstrukteurlibs/watchdog/src/watchdog/utils",
		"konstrukteurlibs/watchdog/src/watchdog/observers",
	],

	data_files = [
		("konstrukteur", [
				"LICENSE.md",
				"README.md"
			]
		)
	],

	**extra
)


text:
class BudgetsController < ApplicationController

  add_breadcrumb 'Budgets'

  def users
    @users = User.all.order(:last_name, :first_name)
    @title = 'Budget par intervenant'
    add_breadcrumb 'Intervenants'
  end

  def teaching_modules
    @semesters = Semester.all
    @title = 'Budget par module'
    add_breadcrumb 'Modules'
  end
end


text:
[![Build Status](https://travis-ci.org/urschrei/lonlat_bng.png?branch=master)](https://travis-ci.org/urschrei/lonlat_bng) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/urschrei/lonlat_bng?branch=master&svg=true)](https://ci.appveyor.com/project/urschrei/lonlat-bng) [![Coverage Status](https://coveralls.io/repos/github/urschrei/lonlat_bng/badge.svg?branch=master)](https://coveralls.io/github/urschrei/lonlat_bng?branch=master) [![](https://img.shields.io/crates/v/lonlat_bng.svg)](https://crates.io/crates/lonlat_bng) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](license.txt) [![DOI](https://zenodo.org/badge/3657/urschrei/lonlat_bng.svg)](https://zenodo.org/badge/latestdoi/3657/urschrei/lonlat_bng)

# Introduction

A Rust library with FFI bindings for fast conversion between WGS84 longitude and latitude and British National Grid ([epsg:27700](http://spatialreference.org/ref/epsg/osgb-1936-british-national-grid/)) coordinates, using a Rust binary. Conversions use a standard 7-element Helmert transform with the addition of OSTN15 corrections for [accuracy](#accuracy).

# Motivation
Python (etc.) is relatively slow; this type of conversion is usually carried out in bulk, so an order-of-magnitude improvement using FFI saves both time and energy.
[Convertbng](https://github.com/urschrei/convertbng) is an example Python Wheel which uses this binary via `ctypes` and `cython`.

# Accuracy
Conversions which solely use Helmert transforms are accurate to within around 5 metres, and are **not suitable** for calculations or conversions used in e.g. surveying. Thus, we use the OSTN15 transform, which adjusts for local variation within the Terrestrial Reference Frame by incorporating OSTN15 data. [See here](http://www.ordnancesurvey.co.uk/business-and-government/help-and-support/navigation-technology/os-net/surveying.html) for more information.

# Library Use
## As a Rust Library
Add the following to your `Cargo.toml` (the latest version is displayed on the fourth badge at the top of this screen)

    lonlat_bng = "x.x.x"

Full library documentation is available [here](http://urschrei.github.io/lonlat_bng/)

**Note that `lon`, `lat` coordinates outside the [UK bounding box](http://spatialreference.org/ref/epsg/27700/) will be transformed to `(NAN, NAN)`, which cannot be mapped.**

The functions exposed by the library can be found [here](http://urschrei.github.io/lonlat_bng/lonlat_bng/index.html#functions)

## FFI
The FFI C-compatible functions exposed by the library are:
`convert_to_bng_threaded(Array, Array) -> Array`
`convert_to_lonlat_threaded(Array, Array) -> Array`

`convert_to_osgb36_threaded(Array, Array) -> Array`
`convert_to_etrs89_threaded(Array, Array) -> Array)`
`convert_osgb36_to_ll_threaded(Array, Array) -> Array`
`convert_etrs89_to_ll_threaded(Array, Array) -> Array`

`convert_etrs89_to_osgb36_threaded(Array, Array) -> Array`
`convert_osgb36_to_etrs89_threaded(Array, Array) -> Array`

`convert_epsg3857_to_wgs84_threaded(Array, Array) -> Array`

### FFI and Memory Management
The library does not allocate memory using new vectors or arrays; the longitude and latitude arrays you pass to it via FFI are converted into mutable [slices](https://doc.rust-lang.org/std/slice/) (an inherently [`unsafe`](https://doc.rust-lang.org/std/slice/fn.from_raw_parts_mut.html) operation), then mutated in-place before being passed back across the FFI boundary as C-compatible arrays. Thus, the calling code retains ownership of the allocated memory at all times – it is up to the calling program to ensure that the data passed to `lonlat_bng` live long enough, and are correctly freed (in practice, they will be freed automatically if using a dynamic language).

### Building the Shared Library
Running `cargo build --release` will build an artefact called `liblonlat_bng.dylib` on OSX, and `liblonlat_bng.a` on `*nix` systems. Note that you'll have to generate `liblonlat_bng.so` for `*nix` hosts using the following steps:

- `ar -x target/release/liblonlat_bng.a`
- `gcc -shared *.o -o target/release/liblonlat_bng.so -lrt`

## As a Python Package
`convert_bng` is [available](https://pypi.python.org/pypi/convertbng/) from PyPI for OSX, Windows, and *nix:
`pip install convertbng`
More information is available in its [repository](https://github.com/urschrei/convertbng)

# Benchmark
A CProfile [benchmark](remote_bench.py) was run, comparing 50 runs of converting 1m random lon, lat pairs in NumPy arrays.

## Methodology
- 4 [Amazon EC2 C4](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/c4-instances.html) (compute-optimised) systems were tested
- The system was first calibrated by taking the mean of five calibration runs of 100,000 repeats
- A benchmark program was then run for each of the three configurations. See the [benches](benches) directory for details
- The five slowest function calls for each benchmark were then displayed.

## Results

| EC2 Instance Type    | Processors (vCPU) | Rust Ctypes (s) | Rust Cython (s) | Pyproj (s) | Ctypes vs Pyproj | Cython vs Pyproj |
|:----------|:----------:|:----------:|:----------:|:----------:|:----------:|----------:|
| c4.xlarge            | 4                 | 14.782          | 11.714          |  9.379     |   58.36%         |   24.97%         |
| c4.2xlarge           | 8                 | 8.647           | 6.421           |  9.256     |  -6.57%          |  -30.62%         |
| c4.4xlarge           | 16                | 6.470           | 3.716           |  9.398     |  -31.49%         |  -60.25%         |
| c4.8xlarge           | 36                | 4.913           | 2.501           |  9.308     |  -48.05%         |  -73.35%         |

## Conclusion
Rust is faster than PROJ.4 on an 8-CPU system – even using `ctypes` – and outperforms it by greater margins as the number of CPUs increase: at 36 CPUs, Rust + Cython is over 3.7x faster.

# Comparing Crossbeam and Rayon
Comparing how varying threads and weights affects overall speed, using [`cargo bench`](benches/benchmarks.rs)
On both 2- and 8-core i7 machines, running `convert_bng_threaded_vec` using one thread per core gives optimum performance, whereas Rayon does a good job at choosing its own optimum weight.

# License
[MIT](license.txt)

This software makes use of OSTN15 data, which is © Crown copyright, Ordnance Survey and the Ministry of Defence (MOD) 2016. All rights reserved. Provided under the BSD 2-clause [license](OSTN15_license.txt).


text:
/*
 *
 * Handle client hooks
 *
 */

var debug = true, initHM = true, initDelay=0, lineNumber=-1;
var ep_activity = new Array();

// Gets called when DOM line is written
exports.acePostWriteDomLineHTML = function(hook_name, args, cb) {
  var lineId = args.node.id.substring(10);
  if (debug) console.log("acePostWriteDomLineHTML");

  // Pre init process
  if (initHM) {
    lineNumber++;
  }
  // Init process
  else if (initDelay>0) {
    lineNumber++;
    initDelay--;//
    createLineArray(lineId);
    if (debug) console.log("init lineId ("+lineId+") lineNumber("+lineNumber+")");
    if (initDelay===0) { console.log("Init done: ep_activity=\n"); console.table(ep_activity); }
  }

  // All DOMline changes after init process -->
  else {
    console.log("changed: lineId("+lineId+")");

    // update array and increment activity here

  }
  return cb();
}

// Helper function: new line added -> update ep_activity
function addedLine(position, divid) {
  ep_activity.splice(position, 0, new Array(divid, 0));
}

// Helper function: line dropped -> update ep_activity
function droppedLine(position) {
  ep_activity.splice(position, 1); // splice(index, count_to_remove, addelement1, addelement2, ...)
}

// Helper function for init process
function createLineArray(lineId) {
  var lineArray = new Array(lineId, 0); // lineArray[last_divid, activity]
  ep_activity.push(lineArray);
}

// Gets called when "pre-init" is done
exports.postAceInit = function(hook_name, args, cb) {
  if (debug) console.log("postAceInit-event");
  if (debug) console.log("delay: "+lineNumber); // changeset used for init
  initDelay = lineNumber;
  lineNumber = -1;
  initHM=false;
  return cb();
}

// Gets called every second
exports.aceEditEvent = function(hook_name, args, cb) {

  // Decay of activity
  // check if the event is the idleWorkTimer,
  // so we only change the ep_activity table once per second

  if (args.callstack.type === "idleWorkTimer") {
      for(var i=0; i<ep_activity.length; i++) {
          if (ep_activity[i][1]>0) {
              var temp_debug = ep_activity[i][1];
              ep_activity[i][1] = Math.max( 0, ep_activity[i][1]-Math.max(0.01, 0.05*ep_activity[i][1]) );
          }
      }
  }

  return cb();
}