text:
layout: default
description: >-
  This chapter describes the JavaScript interface for creating and modifying EnterpriseGraphs
---
# EnterpriseGraphs Management

An EnterpriseGraph is a specialized version of a SmartGraph, which
means that both modules work similarly. The major difference is that
EnterpriseGraphs rely on a special automated sharding of the underlying
collections and hence can only work with collections that are created
through the EnterpriseGraph itself. EnterpriseGraphs cannot overlap.

To generally understand the concept of this module please read the chapter
about [General Graph Management](graphs-general-graphs-management.html) first,
and continue with [SmartGraph Management](graphs-smart-graphs-management.html).

## Create a Graph

EnterpriseGraphs require edge relations to be created. The format of the
relations is identical to the format used for General Graphs.
The only difference is that all collections used within
the relations to create a new EnterpriseGraph must not exist yet. You have to let
the EnterpriseGraph module create the Graph collections for you, so that it can
enforce the correct sharding.

`graph_module._create(graphName, edgeDefinitions, orphanCollections, smartOptions)`

- `graphName` (string):
  Unique identifier of the graph.
- `edgeDefinitions` (array):
  List of relation definition objects, may be empty.
- `orphanCollections` (array):
  List of additional vertex collection names, may be empty.
- `smartOptions` (object):
  A JSON object having the following keys:
  - `numberOfShards` (number):
    The number of shards that are created for each collection. To maintain
    the correct sharding, all collections need an identical number of shards.
    This cannot be modified after the creation of the graph.
  - `isSmart` (bool):
    Mandatory parameter that needs to be set to `true` to create an EnterpriseGraph.
  - `satellites` (array, _optional_):
    An array of collection names that is used to create
    [SatelliteCollections](satellites.html) for an EnterpriseGraph.
    Each array element must be a string and a valid collection name.
    The collection type cannot be modified later.

The creation of a graph requires the name and some SmartGraph options.
Due to the API, `edgeDefinitions` and `orphanCollections` have to be given but
both can be empty arrays and be added later.

The `edgeDefinitions` can be created using the convenience method `_relation`
known from the `general-graph` module, which is also available here.

`orphanCollections` again is just a list of additional vertex collections which
are not yet connected via edges but should follow the same sharding to be
connected later on. Note that these collections are not necessarily orphans in
the graph theoretic sense: it is possible to add edges having one end in a collection
that has been declared as orphan.

All collections used within the creation process are newly created.
The process fails if one of them already exists, unless they have the
correct sharding already. All newly created collections are immediately
dropped again in the failure case.

### Examples

Create a graph without relations. Edge definitions can be added later:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphCreate1_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphCreate1_cluster}
      var graph_module = require("@arangodb/enterprise-graph");
      var graph = graph_module._create("myGraph", [], [], {isSmart: true, numberOfShards: 9});
      graph_module._graph("myGraph");
     ~graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphCreate1_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

Create a graph using an edge collection `edges` and a single vertex collection
`vertices` as relation:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphCreate2_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphCreate2_cluster}
      var graph_module = require("@arangodb/enterprise-graph");
      var edgeDefinitions = [ graph_module._relation("edges", "vertices", "vertices") ];
      var graph = graph_module._create("myGraph", edgeDefinitions, [], {isSmart: true, numberOfShards: 9});
      graph_module._graph("myGraph");
     ~graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphCreate2_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

Create a graph with edge definitions and orphan collections:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphCreate3_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphCreate3_cluster}
      var graph_module = require("@arangodb/enterprise-graph");
      var edgeDefinitions = [ graph_module._relation("myRelation", ["male", "female"], ["male", "female"]) ];
      var graph = graph_module._create("myGraph", edgeDefinitions, ["sessions"], {isSmart: true, numberOfShards: 9});
      graph_module._graph("myGraph");
     ~graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphCreate3_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

## Modify a graph definition at runtime

After you have created an EnterpriseGraph, its definition is not immutable. You can
still add or remove relations. This is again identical to General Graphs.

However, there is one important difference: you can only add collections that
either *do not exist*, or that have been created by this graph earlier. The
latter can be the case if you, for example, remove an orphan collection from this
graph, without dropping the collection itself. When after some time you decide
to add it to the graph again, you can do it. This is because the enforced sharding is still
applied to this vertex collection.

## Remove a vertex collection

Remove a vertex collection from the graph:

`graph._removeVertexCollection(vertexCollectionName, dropCollection)`

- `vertexCollectionName` (string):
  Name of vertex collection.
- `dropCollection` (bool, _optional_):
  If `true`, the collection is dropped if it is not used in any other graph.
  Default: `false`.

In most cases, this function works identically to the General Graph one.
However, there is one special case: the first vertex collection added to the graph
(either orphan or within a relation) defines the sharding for all collections
within the graph. Every other collection has its `distributeShardsLike` attribute set to the
name of the initial collection. This collection cannot be dropped as long as
other collections follow its sharding (i.e. they need to be dropped first).

### Examples

Create an EnterpriseGraph and list its orphan collections:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphModify1_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphModify1_cluster}
      var graph_module = require("@arangodb/enterprise-graph");
      var relation = graph_module._relation("edges", "vertices", "vertices");
      var graph = graph_module._create("myGraph", [relation], ["other"], {isSmart: true, numberOfShards: 9});
      graph._orphanCollections();
     ~graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphModify1_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

Remove the orphan collection from the EnterpriseGraph and drop the collection:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphModify2_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphModify2_cluster}
     ~var graph_module = require("@arangodb/enterprise-graph");
     ~var relation = graph_module._relation("edges", "vertices", "vertices");
     ~var graph = graph_module._create("myGraph", [relation], ["other"], {isSmart: true, numberOfShards: 9});
      graph._removeVertexCollection("other", true);
      graph_module._graph("myGraph");
     ~graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphModify2_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

Attempting to remove a non-orphan collection results in an error:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphModify3_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphModify3_cluster}
     ~var graph_module = require("@arangodb/enterprise-graph");
     ~var relation = graph_module._relation("edges", "vertices", "vertices");
     ~var graph = graph_module._create("myGraph", [relation], [], {isSmart: true, numberOfShards: 9});
      graph._removeVertexCollection("vertices"); // xpError(ERROR_GRAPH_NOT_IN_ORPHAN_COLLECTION)
     ~graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphModify3_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

You cannot drop the initial collection (`vertices`) as long as it defines the
sharding for other collections (`edges`).

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphModify4_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphModify4_cluster}
      var graph_module = require("@arangodb/enterprise-graph");
      var relation = graph_module._relation("edges", "vertices", "vertices");
      var graph = graph_module._create("myGraph", [relation], [], {isSmart: true, numberOfShards: 9});
      graph._deleteEdgeDefinition("edges");
      graph._removeVertexCollection("vertices");
      db._drop("vertices"); // xpError(ERROR_CLUSTER_MUST_NOT_DROP_COLL_OTHER_DISTRIBUTESHARDSLIKE)
     ~graph_module._drop("myGraph", true);
     ~db._drop("edges");
     ~db._drop("vertices");
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphModify4_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

You may drop the complete graph including the underlying collections by setting
the second argument in the call to `_drop()` to `true`. This only drops
collections that are in the graph definition at that point. Remember to manually
drop collections that you might have removed from the graph beforehand.

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphModify5_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphModify5_cluster}
      var graph_module = require("@arangodb/enterprise-graph");
      var relation = graph_module._relation("edges", "vertices", "vertices");
      var graph = graph_module._create("myGraph", [relation], [], {isSmart: true, numberOfShards: 9});
      graph._deleteEdgeDefinition("edges");      // Remove edge collection from graph definition
      graph._removeVertexCollection("vertices"); // Remove vertex collection from graph definition
      graph_module._drop("myGraph", true);       // Does not drop any collections because none are left in the graph definition
      db._drop("edges"); // Manually clean up the collections that were left behind, drop 'edges' before sharding-defining 'vertices' collection
      db._drop("vertices");
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphModify5_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

Alternatively, you can `truncate()` all collections of the graph if you just
want to get rid of the data but keep the collections and graph definition.

## Remove an edge collection

Delete an edge definition from the graph:

`graph._deleteEdgeDefinition(edgeCollectionName, dropCollection)`

- `edgeCollectionName` (string):
  Name of edge collection.
- `dropCollection` (bool, _optional_):
  If `true`, the collection is dropped if it is not used in any other graph.
  Default: `false`.

### Examples

Create an EnterpriseGraph, then delete the edge definition and drop the edge collection:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphModify6_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphModify6_cluster}
      var graph_module = require("@arangodb/enterprise-graph");
      var relation = graph_module._relation("edges", "vertices", "vertices");
      var graph = graph_module._create("myGraph", [relation], [], {isSmart: true, numberOfShards: 9});
      graph._deleteEdgeDefinition("edges", true);
      graph_module._graph("myGraph");
     ~graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphModify6_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

It is allowed to remove the vertex collection `vertices` if it is not used in
any relation (i.e. after the deletion of the edge definition):

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphModify7_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphModify7_cluster}
     ~var graph_module = require("@arangodb/enterprise-graph");
     ~var relation = graph_module._relation("edges", "vertices", "vertices");
     ~var graph = graph_module._create("myGraph", [relation], [], {isSmart: true, numberOfShards: 9});
      graph._deleteEdgeDefinition("edges");
      graph._removeVertexCollection("vertices");
     ~graph_module._drop("myGraph", true);
     ~db._drop("edges");
     ~db._drop("vertices");
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphModify7_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

Keep in mind that you cannot drop the `vertices` collection until no other
collection references it anymore (`distributeShardsLike` collection property).

## Remove a Graph

Remove a SmartGraph:

`graph_module._drop(graphName, dropCollections)`

- `graphName` (string):
  Name of the Graph.
- `dropCollections` (bool, _optional_):
  Define if collections should be dropped. Default: `false`.

### Examples

Delete an EnterpriseGraph and drop its collections:

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphRemove1_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphRemove1_cluster}
     ~var graph_module = require("@arangodb/enterprise-graph");
     ~var relation = graph_module._relation("edges", "vertices", "vertices");
     ~var graph = graph_module._create("myGraph", [relation], ["other"], {isSmart: true, numberOfShards: 9});
      graph_module._drop("myGraph", true);
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphRemove1_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}

Note that removing a Graph with the option to drop the collections fails if
you removed collections from the Graph but did not drop these collections.
This is because their `distributeShardsLike` attribute still references
collections that are part of the Graph. Dropping collections while others
point to them in this way is not allowed. Make sure to drop the referencing
collections first.

    {% arangoshexample examplevar="examplevar" script="script" result="result" %}
    @startDocuBlockInline enterpriseGraphRemove2_cluster
    @EXAMPLE_ARANGOSH_OUTPUT{enterpriseGraphRemove2_cluster}
     ~var graph_module = require("@arangodb/enterprise-graph");
     ~var relation = graph_module._relation("edges", "vertices", "vertices");
     ~var graph = graph_module._create("myGraph", [relation], ["other"], {isSmart: true, numberOfShards: 9});
      graph._removeVertexCollection("other");
      graph_module._drop("myGraph", true); // xpError(ERROR_CLUSTER_MUST_NOT_DROP_COLL_OTHER_DISTRIBUTESHARDSLIKE)
     ~db._drop("other");
     ~db._drop("vertices");
    @END_EXAMPLE_ARANGOSH_OUTPUT
    @endDocuBlock enterpriseGraphRemove2_cluster
    {% endarangoshexample %}
    {% include arangoshexample.html id=examplevar script=script result=result %}


text:
function wc = center(map,wc)
%CENTER Conformal center of Schwarz-Christoffel disk map.
%   CENTER(M) returns the conformal center (image of 0) of the
%   Schwarz-Christoffel disk map represented by M.
%
%   CENTER(M,WC) computes a map conformally equivalent to M but with
%   conformal center WC (provided WC is inside the polygon of M), and
%   returns the new map. If WC is empty, you will be asked to select it
%   graphically.
%
%   See also DISKMAP.

%   Copyright 1998 by Toby Driscoll.
%   $Id: center.m 196 2002-09-10 19:12:38Z driscoll $

if nargin == 1
  % Return center
  wc = map.center;
  if isempty(wc)
    p = polygon(map);
    wc = rsmap(0,vertex(p),angle(p)-1,...
        map.prevertex,map.prebranch,map.constant,map.qdata);
  end

else
  % Set center
  error('Recentering of RIESURF maps not supported.')
end

redpajama_set_name: RedPajamaGithub


text:
import sys
import wave
import audioop
import os

# this script prints the rms value (audio power) of an entire audio file.
# this requires .wav files...
# execute: python waverms.py file.mp3 1024

wavefile=sys.argv[1]
samples=int(sys.argv[2])
if(os.path.exists(wavefile)):

    h=wave.open(wavefile, 'r');
    for i in range(samples):

        a=h.readframes(h.getnframes()/samples);
        w=h.getsampwidth()*h.getnchannels();
        o=audioop.rms(a,w);
        print(o);


text:
import { expect } from 'chai'
import { Context } from '../../../src/context/context'
import { HTMLToken } from '../../../src/tokens/html-token'
import { Render } from '../../../src/render/render'
import { HTML } from '../../../src/template/html'
import { SimpleEmitter } from '../../../src/emitters/simple-emitter'
import { toPromise } from '../../../src/util/async'
import { Tag } from '../../../src/template/tag/tag'
import { TagToken } from '../../../src/types'

describe('render', function () {
  let render: Render
  before(function () {
    render = new Render()
  })

  describe('.renderTemplates()', function () {
    it('should render html', async function () {
      const scope = new Context()
      const token = { getContent: () => '
' } as HTMLToken
      const html = await toPromise(render.renderTemplates([new HTML(token)], scope, new SimpleEmitter()))
      return expect(html).to.equal('
')
    })
  })

  describe('.renderTemplatesToNodeStream()', function () {
    it('should render to html stream', function (done) {
      const scope = new Context()
      const tpls = [
        new HTML({ getContent: () => '
' } as HTMLToken),
        new HTML({ getContent: () => '
' } as HTMLToken)
      ]
      const stream = render.renderTemplatesToNodeStream(tpls, scope)
      let result = ''
      stream.on('data', (data) => {
        result += data
      })
      stream.on('end', () => {
        expect(result).to.equal('

')
        done()
      })
    })
    it('should render to html stream asyncly', function (done) {
      const scope = new Context()
      const tpls = [
        new HTML({ getContent: () => '
' } as HTMLToken),
        new Tag({ content: 'foo', args: '', name: 'foo' } as TagToken, [], {
          tags: {
            get: () => ({
              render: () => new Promise(
                resolve => setTimeout(() => resolve('async tag'), 10)
              )
            })
          }
        } as any),
        new HTML({ getContent: () => '
' } as HTMLToken)
      ]
      const stream = render.renderTemplatesToNodeStream(tpls, scope)
      let result = ''
      stream.on('data', (data) => {
        result += data
      })
      stream.on('end', () => {
        expect(result).to.equal('
async tag
')
        done()
      })
    })
  })
})


text:
ActiveModel::Serializer.root = false

# Disable for ArraySerializer
ActiveModel::ArraySerializer.root = false


text:
{% extends 'oscar/dashboard/layout.html' %}
{% load i18n %}

{% block title %}
    {{ title }} | {{ block.super }}
{% endblock %}

{% block body_class %}{{ block.super }} create-page{% endblock %}

{% block navbar %}
{% if not is_popup %}
    {{ block.super }}
{% endif %}
{% endblock %}

{% block dashboard_nav %}
{% if not is_popup %}
    {{ block.super }}
{% endif %}
{% endblock %}

{% block breadcrumbs %}
{% if not is_popup %}

{% trans "Dashboard" %}

                {% trans "Options" %}

{{ title }}

{% endif %}
{% endblock %}

{% block headertext %}{{ title }}{% endblock %}

{% block dashboard_content %}
    <form class="form-stacked wysiwyg fixed-actions" method="post" data-behaviour="tab-nav-errors">
        {% csrf_token %}

            {% if is_popup %}<input type="hidden" name="{{ is_popup_var }}" value="{{ is_popup }}" />{% endif %}
            {% if to_field %}<input type="hidden" name="{{ to_field_var }}" value="{{ to_field }}" />{% endif %}

                    {% block option_details %}

{% trans "Option details" %}

                                {% comment %}
                                    If the Option form has field_errors, partials/form_fields.html
                                    will render an error message.
                                    This means that there'll be 2 error messages,
                                    one from the partial and one from the view. Perhaps there should be
                                    an option allowing hiding of the error message in the template.
                                    For now we copy paste what we need from the template.
                                {% endcomment %}

                                {% if form.non_field_errors %}
                                    {% for error in form.non_field_errors %}

                                             {{ error }}

                                    {% endfor %}
                                {% endif %}

                                {% for field in form %}
                                    {% include 'oscar/dashboard/partials/form_field.html' with field=field %}
                                {% endfor %}

                    {% endblock %}

        {% block fixed_actions_group %}

                            {% trans "Cancel" %}

                        {% trans "or" %}
                        <button class="btn btn-primary" type="submit">
                            {% trans "Save" %}
                        </button>

        {% endblock fixed_actions_group %}
    </form>

{% endblock dashboard_content %}


text:
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    >

    <uses-permission tools:node="remove" android:name="android.permission.SYSTEM_ALERT_WINDOW" />
</manifest>


text:
global.expect = require('chai').expect;
global.Plugin = require('../lib');


text:
require_relative 'spec_helper'

describe UsuarioDesconocido do
  before(:all) do
    @db = Sequel.connect(ENV['URL_DATABASE_TRAVIS'])
    @profesor_desconocido = UsuarioDesconocido.new(1111, 'pepito grillo')
    #    @db[:curso].insert(:id_moodle => 5, :nombre_curso => "curso 5")
    #    @db[:curso].insert(:id_moodle => 6, :nombre_curso => "curso 6")
    #    @db[:curso].insert(:id_moodle => 7, :nombre_curso => "curso 7")
    @profesor_desconocido.email = 'email@desconocido.com'
    @profesor_desconocido.nombre_usuario = 'desconocido'
    @profesor_desconocido.rol = 'profesor'
    @profesor_desconocido.id_moodle = '11111'
    @profesor_desconocido.token = 'abcd1234'
    @profesor_desconocido.cursos << Curso.new(5, 'curso 5')
    @profesor_desconocido.cursos << Curso.new(6, 'curso 6')

    @estudiante_desconocido = UsuarioDesconocido.new(2222, 'nebraska')
    @estudiante_desconocido.email = 'alumno@desconocido.com'
    @estudiante_desconocido.nombre_usuario = 'alumno desconocido'
    @estudiante_desconocido.rol = 'estudiante'
    @estudiante_desconocido.id_moodle = '22222'
    @estudiante_desconocido.token = '1234abcd'
    @estudiante_desconocido.cursos << Curso.new(5, 'curso 5')
    @estudiante_desconocido.cursos << Curso.new(7, 'curso 7')
    @db.disconnect
  end

  after(:all) do
    @db = Sequel.connect(ENV['URL_DATABASE_TRAVIS'])
    @db[:usuario_telegram].delete
    @db[:usuarios_moodle].delete
    @db[:tutoria].delete
    @db[:respuestas].delete
    @db.disconnect
  end

  it 'Debe poder registrarse en el sistema como profesor junto con los cursos de los que es responsable' do
    expect(@db[:curso].where(id_moodle: 5, nombre_curso: 'curso 5').to_a.size).to be 0
    expect(@db[:curso].where(id_moodle: 6, nombre_curso: 'curso 6').to_a.size).to be 0
    @profesor_desconocido.rol = 'profesor'
    @profesor_desconocido.registrarme_en_el_sistema
    expect(@db[:usuario_telegram].where(id_telegram: 1111, nombre_usuario: 'desconocido').to_a.size).to be 1
    expect(@db[:usuarios_moodle].where(id_telegram: 1111, email: 'email@desconocido.com').to_a.size).to be 1
    expect(@db[:datos_moodle].where(email: 'email@desconocido.com', token: 'abcd1234', id_moodle: 11_111).to_a.size).to be 1
    expect(@db[:profesor].where(id_telegram: 1111).to_a.size).to be 1
    expect(@db[:profesor_curso].where(id_profesor: 1111, id_moodle_curso: 5).to_a.size).to be 1
    expect(@db[:profesor_curso].where(id_profesor: 1111, id_moodle_curso: 6).to_a.size).to be 1
    expect(@db[:curso].where(id_moodle: 5, nombre_curso: 'curso 5').to_a.size).to be 1
    expect(@db[:curso].where(id_moodle: 6, nombre_curso: 'curso 6').to_a.size).to be 1
  end

  it 'Debe poder registrarse en el sistema como estudiante en los cursos en los que es reponsable un profesor dado de alta en el sistema' do
    @estudiante_desconocido.registrarme_en_el_sistema
    expect(@db[:usuario_telegram].where(id_telegram: 2222, nombre_usuario: 'alumno desconocido').to_a.size).to be 1
    expect(@db[:usuarios_moodle].where(id_telegram: 2222, email: 'alumno@desconocido.com').to_a.size).to be 1
    expect(@db[:datos_moodle].where(email: 'alumno@desconocido.com', token: '1234abcd', id_moodle: 22_222).to_a.size).to be 1
    expect(@db[:estudiante].where(id_telegram: 2222).to_a.size).to be 1
    expect(@db[:estudiante_curso].where(id_estudiante: 2222, id_moodle_curso: 5).to_a).to_not be_empty
    expect(@db[:estudiante_curso].where(id_estudiante: 2222, id_moodle_curso: 6).to_a).to be_empty
    expect(@db[:estudiante_curso].where(id_estudiante: 2222, id_moodle_curso: 7).to_a).to be_empty
  end
end


text:
namespace media {

class DecoderBuffer;
class VideoDecoderConfig;
class VideoFrame;

scoped_refptr<VideoFrame> GetVideoFrameFromMemory(
    scoped_refptr<DecoderBuffer> buffer,
    const VideoDecoderConfig& config);

}  // namespace media

#endif  // PLATFORM_MEDIA_RENDERER_DECODERS_VIDEO_FRAME_TRANSFORMER_H_


text:
    <meta http-equiv="Content-Type" content="text/html; charset=Windows-1252" />
    <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5" />
    <title>MultiSearcher.SubSearcher Method</title>
    <xml>
    </xml>
    <link rel="stylesheet" type="text/css" href="MSDN.css" />

            Apache Lucene.Net 2.4.0 Class Library API

MultiSearcher.SubSearcher Method

Returns index of the searcher for document
n
 in the array used to construct this searcher.

public virtual int SubSearcher(
   int n
);

See Also

        MultiSearcher Class | Lucene.Net.Search Namespace

      <object type="application/x-oleobject" classid="clsid:1e2a7bd0-dab9-11d0-b93a-00c04fc99f9e" viewastext="true" style="display: none;">
        <param name="Keyword" value="SubSearcher method">
        </param>
        <param name="Keyword" value="SubSearcher method, MultiSearcher class">
        </param>
        <param name="Keyword" value="MultiSearcher.SubSearcher method">
        </param>
      </object>

Generated from assembly Lucene.Net [2.4.0.2]


text:
package ref.sdfe.gpslogsheet2;

import android.Manifest;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.preference.PreferenceManager;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v4.app.FragmentTabHost;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutCompat;
import android.support.v7.widget.Toolbar;

import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;

import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextWatcher;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TabHost;
import android.widget.TextView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import static android.R.layout.simple_list_item_1;

public class ProjectActivity extends AppCompatActivity {

    private SharedPreferences prefs;
    public static Integer lastOpenedProject;
    public Context mContext;
    public static List<Integer> projectsListIDs;
    public static List<String> projectsListStrings;
    private DataBaseHandler db;
    static public ProjectEntry project;
    static public ProjectEntry project_backup; // so that changes can be discarded.
    static public Boolean save = false; // should the project be saved
    static public Boolean projectNameError = true; // Is project name invalid

    // Local variables for the text fields
    private static String current_projectName;
    private static String current_projectOperator;
    private static String current_projectDate;
    private static String current_projectModDate;
    private static String current_projectEndDate;
    private static String projectTextTemplate;
    private static InputFilter nameFilter;
    private static InputFilter numberFilter;

    public static Boolean locationPermitted;

    // Setups
    public static String current_setup;
    public ArrayAdapter setupsAdapter;
    public List<Integer> setupsListIDs;
    public List<String> setupsListStrings;
    public HashMap<Integer, ProjectEntry.Setup> setupsList;

    // Lists
    static public List<Double> eastings = new ArrayList<>();
    static public List<Double> northings = new ArrayList<>();
    static public List<String> gpsNames = new ArrayList<>();
    static public List<String> hsNames = new ArrayList<>();
    static public List<String> antennaNames = new ArrayList<>();
    static public List<String> alarmNames = new ArrayList<>();
    static public List<String> instrumentNames = new ArrayList<>();

    static public List<FixedpointEntry> fixedpointEntries;
    static public List<AlarmEntry> alarmEntries;
    static public List<AntennaEntry> antennaEntries;
    static public List<InstrumentEntry> instrumentEntries;

    //Buttons and views
    //static public Button endDate_button;
    //static public TextView projectTextView;

    // String
    static public String batchRecipeString;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_project);

        // Get application context
        mContext = getApplicationContext();

        projectTextTemplate = getResources().getString(R.string.projectTextTemplate);

        //Get shared preferences
        prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
        //Create editor
        final SharedPreferences.Editor editor = prefs.edit();

        // Get readable database in order to get a list of projects
        db = DataBaseHandler.getInstance(getApplicationContext());
        getData();

        //Get list of projects
        List<ProjectEntry> projectsList = db.getAllProjectEntries();
        projectsListIDs = new ArrayList<>();
        projectsListStrings = new ArrayList<>();
        // get project ID's and name
        for (int i = 0; i < db.getProjectsCount(); i++) {
            projectsListIDs.add(projectsList.get(i).getId());
            projectsListStrings.add(projectsList.get(i).getName());
        }

        //Check for open/selected project
        lastOpenedProject = prefs.getInt("lastOpenedProject", 0);
        if (lastOpenedProject > 0) {
            project = db.getProjectEntry(lastOpenedProject);
            Log.i("ProjectActivity", "Project loaded, id: " + lastOpenedProject.toString());
            projectNameError = false;

            try {
                project_backup = (ProjectEntry) project.clone();
            } catch (CloneNotSupportedException e) {
                Log.i("ProjectActivity", "Cloning not supported :/");
            }

        } else {
            //generate new id number for project.
            Integer id;
            try {
                id = Collections.max(projectsListIDs) + 1;
            } catch (NoSuchElementException e) {
                id = 1;
            }
            project = new ProjectEntry(id);
            Log.i("ProjectActivity", "New Project, id: " + id.toString());
            try {
                project_backup = (ProjectEntry) project.clone();
            } catch (CloneNotSupportedException e) {
                Log.i("ProjectActivity", "Cloning not supported :/");
            }
            project.setName("");
            projectNameError = true;
        }

        // Load project data into local variables
        current_projectName = project.getName();
        Log.i("ProjectActivity", current_projectName);
        current_projectOperator = project.getOperator();

        // Get project dates and convert them to strings
        long start_date_long = project.getStartDate();
        Date start_date = new Date(start_date_long);
        current_projectDate = start_date.toString();
        long mod_date_long = project.getModDate();
        Date mod_date = new Date(mod_date_long);
        current_projectModDate = mod_date.toString();

        setupsListIDs = new ArrayList<>();
        setupsListStrings = new ArrayList<>();
        populateSetupsList();

        //If there are no setups, add an empty one
        if (setupsListIDs.isEmpty()) {
            project.addSetup(0);
            populateSetupsList();
        }
        setupsAdapter = new ArrayAdapter<>(this, simple_list_item_1, setupsListStrings);

        //LOCATION
        // Check for permission
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            locationPermitted = false;
            Log.i("ProjectActivity", "Location not permitted.");
        } else {
            locationPermitted = true;
            Log.i("ProjectActivity", "Location permitted.");
        }

        //Start location service "LocationHandler"
        if (locationPermitted) {
            mContext.startService(new Intent(mContext, LocationHandler.class));
        }

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(false);
        //toolbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        SectionsPagerAdapter mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        ViewPager mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        // EMAIL BUTTON
        FloatingActionButton fab_email = (FloatingActionButton) findViewById(R.id.fab_email);
        fab_email.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "TODO: Email current project.", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
                // TODO: Email
                // Make this fab button appear only when project has an observation
                // Generate .batch files
                // send email with relevant files.
            }
        });

        // CLOSE BUTTON
        FloatingActionButton fab_close = (FloatingActionButton) findViewById(R.id.fab_close);
        fab_close.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (projectNameError) {
                    // Project has invalid name
                    Log.i("ProjectActivity", "back pressed! Name Error!");
                    final Dialog dialog = new Dialog(ProjectActivity.this);
                    LayoutInflater inflater = getLayoutInflater();
                    View convertView = inflater.inflate(R.layout.discard_dialog, new LinearLayoutCompat(mContext), false);
                    dialog.setContentView(convertView);
                    dialog.setCancelable(true);
                    dialog.setTitle(R.string.invalid_name_query);

                    Button cancel_button = (Button) dialog.findViewById(R.id.cancel_button);
                    Button discard_button = (Button) dialog.findViewById(R.id.discard_button);

                    cancel_button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // CANCEL CODE HERE
                            dialog.dismiss();
                        }
                    });

                    discard_button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // DISCARD CODE HERE
                            save = false;
                            editor.apply();

                            // Close activity
                            dialog.dismiss();
                            finish();
                        }
                    });

                    dialog.show();

                } else {

                    final Dialog dialog = new Dialog(ProjectActivity.this);
                    LayoutInflater inflater = getLayoutInflater();
                    View convertView = inflater.inflate(R.layout.close_dialog, new LinearLayoutCompat(mContext), false);
                    dialog.setContentView(convertView);
                    dialog.setCancelable(true);
                    dialog.setTitle(R.string.close_project_title);

                    Button save_button = (Button) dialog.findViewById(R.id.save_button);
                    Button discard_button = (Button) dialog.findViewById(R.id.discard_button);

                    save_button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // SAVE CODE HERE
                            save = true;

                            // Clear lastOpenedProject from sharedprefs
                            editor.putInt("lastOpenedProject", -1);
                            editor.apply();

                            // Close activity
                            dialog.dismiss();
                            finish();
                        }
                    });

                    discard_button.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            // DISCARD CODE HERE
                            save = false;

                            // Clear lastOpenedProject from sharedprefs
                            editor.putInt("lastOpenedProject", -1);
                            editor.apply();

                            // Close activity
                            dialog.dismiss();
                            finish();
                        }
                    });
                    dialog.show();
                }
            }
        });

        // Input filters for the text fields
        nameFilter = new InputFilter() {
            @Override
            public CharSequence filter(CharSequence source, int start, int end,
                                       Spanned dest, int dstart, int dend) {

                if (source instanceof SpannableStringBuilder) {
                    SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder) source;
                    for (int i = end - 1; i >= start; i--) {
                        char currentChar = source.charAt(i);
                        if (!Character.isLetterOrDigit(currentChar) &&
                                !(currentChar == '_') &&
                                !(currentChar == '-')) {
                            sourceAsSpannableBuilder.delete(i, i + 1);
                        }
                    }
                    return source;
                } else {
                    StringBuilder filteredStringBuilder = new StringBuilder();
                    for (int i = start; i < end; i++) {
                        char currentChar = source.charAt(i);
                        if (Character.isLetterOrDigit(currentChar) ||
                                (currentChar == '_') ||
                                (currentChar == '-')) {
                            filteredStringBuilder.append(currentChar);
                        }
                    }
                    return filteredStringBuilder.toString();
                }
            }
        };
        numberFilter = new InputFilter() {
            @Override
            public CharSequence filter(CharSequence source, int start, int end,
                                       Spanned dest, int dstart, int dend) {

                if (source instanceof SpannableStringBuilder) {
                    SpannableStringBuilder sourceAsSpannableBuilder = (SpannableStringBuilder) source;
                    for (int i = end - 1; i >= start; i--) {
                        char currentChar = source.charAt(i);
                        if (!Character.isDigit(currentChar) &&
                                !(currentChar == '.')) {
                            sourceAsSpannableBuilder.delete(i, i + 1);
                        }
                    }
                    return source;
                } else {
                    StringBuilder filteredStringBuilder = new StringBuilder();
                    for (int i = start; i < end; i++) {
                        char currentChar = source.charAt(i);
                        if (Character.isDigit(currentChar) ||
                                (currentChar == '.')) {
                            filteredStringBuilder.append(currentChar);
                        }
                    }
                    return filteredStringBuilder.toString();
                }
            }
        };

    }

    // TODO: setups list, and adapter to display them in the project activity.
    public void populateSetupsList() {
        setupsListIDs.clear();
        setupsListStrings.clear();
        setupsList = project.getSetups();

        for (Map.Entry<Integer, ProjectEntry.Setup> entry : setupsList.entrySet()) {
            Integer id = entry.getKey();
            setupsListIDs.add(id);
            setupsListStrings.add(entry.getValue().getFixedPoint());
        }
        try {
            setupsAdapter.notifyDataSetChanged();
        } catch (NullPointerException e) {
            Log.i("ProjectActivity","PopulateSetupsList, NPE");

        }
    }

    @Override
    public void onBackPressed() {
        Log.i("ProjectActivity", "back pressed!");
        Log.i("ProjectActivity", "projectNameError = " + projectNameError.toString());
        final SharedPreferences.Editor editor = prefs.edit();

        if (project_backup.getModDate() == project.getModDate()) {
            // No changes detected
            Log.i("ProjectActivity", "No changes detected.");
            finish();
        } else if (projectNameError) {
            // Project has invalid name
            Log.i("ProjectActivity", "back pressed! Name Error!");
            final Dialog dialog = new Dialog(ProjectActivity.this);
            LayoutInflater inflater = getLayoutInflater();
            View convertView = inflater.inflate(R.layout.discard_dialog, new LinearLayoutCompat(mContext), false);
            dialog.setContentView(convertView);
            dialog.setCancelable(true);
            dialog.setTitle("Project name error, do you want to Discard changes?");

            Button cancel_button = (Button) dialog.findViewById(R.id.cancel_button);
            Button discard_button = (Button) dialog.findViewById(R.id.discard_button);

            cancel_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // CANCEL CODE HERE
                    // Close activity
                    dialog.dismiss();
                    //Move focus to projectNameField

                    //TODO: Move focus to project name field, the below does not work.
                    //getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
                    //projectNameField.requestFocus();
                }
            });

            discard_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // DISCARD CODE HERE
                    // read backup project.
                    save = false;
                    dialog.dismiss();
                    finish();
                }
            });

            dialog.show();

        } else {
            Log.i("ProjectActivity", "back pressed! Dialog coming up!");
            final Dialog dialog = new Dialog(ProjectActivity.this);
            LayoutInflater inflater = getLayoutInflater();
            View convertView = inflater.inflate(R.layout.close_dialog, new LinearLayoutCompat(mContext), false);
            dialog.setContentView(convertView);
            dialog.setCancelable(true);
            dialog.setTitle("Save or Discard changes?");

            Button save_button = (Button) dialog.findViewById(R.id.save_button);
            Button discard_button = (Button) dialog.findViewById(R.id.discard_button);

            save_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // SAVE CODE HERE
                    save = true;

                    // Close activity
                    dialog.dismiss();
                    finish();
                }
            });

            discard_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // DISCARD CODE HERE
                    save = false;

                    // Close activity
                    dialog.dismiss();
                    finish();
                }
            });

            dialog.show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        //TODO: save project to database
        if (save) {
            // Get application context
            mContext = getApplicationContext();

            //Log.i("ProjectActivity", "Project JSON: " + project.getJsonString());

            // Get readable database in order to get a list of projects
            //db = DataBaseHandler.getInstance(mContext);

            //If project ID already in database
            if (db.getAllProjectIDs().contains(project.getId())) {
                db.updateProjectEntry(project);
            } else {
                // else it is a new project
                if (db.getAllProjectNames().contains(project.getName())) {
                    Log.i("SQL", "Tried to save new project with non-unique name");
                } else {
                    db.addProjectEntry(project);
                }
            }
        }
        db.close();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_project, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            Log.i("Toolbar", "Options pressed");
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);
            return true;
        }
        if (id == R.id.action_delete) {
            Log.i("Toolbar", "Delete pressed");
            //TODO: create popup with warning to delete

            final Dialog delete_dialog = new Dialog(ProjectActivity.this);
            LayoutInflater inflater = getLayoutInflater();
            View convertView = inflater.inflate(R.layout.delete_dialog, new LinearLayoutCompat(mContext), false);
            delete_dialog.setContentView(convertView);
            delete_dialog.setCancelable(true);
            delete_dialog.setTitle("WARNING!");

            Button cancel_button = (Button) delete_dialog.findViewById(R.id.cancel_button);
            final Button delete_button = (Button) delete_dialog.findViewById(R.id.delete_button);

            //Switch that toggles delete button
            Switch editSwitch = (Switch) delete_dialog.findViewById(R.id.delete_switch);
            editSwitch.setChecked(false);
            editSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (isChecked) {
                        delete_button.setEnabled(true);
                        Log.i("ProjectActivity", "Delete switch on :O !");
                    } else {
                        delete_button.setEnabled(false);
                        Log.i("ProjectActivity", "Delete switch off!");
                    }
                }
            });

            cancel_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    delete_dialog.dismiss();
                }
            });
            delete_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    // DELETE CODE HERE
                    Log.i("ProjectActivity", "TODO: DELETION");
                    db.deleteProject(project);
                    delete_dialog.dismiss();
                    final SharedPreferences.Editor editor = prefs.edit();
                    editor.putInt("lastOpenedProject", -1);
                    editor.commit();
                    save = false;
                    finish();
                }
            });

            delete_dialog.show();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    // A

    public static class ProjectSettingsFragment extends Fragment {
        /**
         * Project setting fragment
         */
        Button endDate_button;
        TextView projectTextView;
        private static final String ARG_SECTION_NUMBER = "1";
        private FragmentTabHost setupsTabHost;
        //private List<Fragment> setupsFragmentsList;
        private View rootView;

        public ProjectSettingsFragment() {

        }

        /**
         * Returns a new instance of this fragment for the given section
         * number.
         */
        public static ProjectSettingsFragment newInstance(int sectionNumber) {
            Log.i("ProjectSettingsFragment", "newInstance");
            ProjectSettingsFragment fragment = new ProjectSettingsFragment();
            Bundle args = new Bundle();
            args.putInt(ARG_SECTION_NUMBER, sectionNumber);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            // OLDJO: Inflate the layout
            Log.i("ProjectSettingsFragment", "onCreateView");
            rootView = inflater.inflate(R.layout.fragment_project, container, false);

            //Make this listen for changes in floating action button
            FloatingActionButton fcb = (FloatingActionButton) rootView.findViewById(R.id.floatingCameraButton);
            fcb.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {

                }
            });

            final DatePickerDialog.OnDateSetListener endDatePickerListener = new DatePickerDialog.OnDateSetListener() {

                // when dialog box is closed, below method will be called.
                public void onDateSet(DatePicker view, int selectedYear,
                                      int selectedMonth, int selectedDay) {
                    Log.i("datePicker","onDateSet called");
                    GregorianCalendar cal = new GregorianCalendar();
                    cal.set(selectedYear, selectedMonth, selectedDay);
                    // If end date is after start date,
                    if (cal.getTimeInMillis() > project.getStartDate()){
                        project.setEndDate(cal.getTimeInMillis());
                    }else{
                        //TODO: Alert dialog or Toast telling user the logical fallacy of having enddate < startdate
                        //Set end date to one week after start date:
                        project.setEndDate(project.getStartDate() + (7*24*3600*1000));
                        String alertString = "End Date must come after Start Date, set to one week after by default.";
                        int duration = Toast.LENGTH_LONG;
                        Toast toast = Toast.makeText(view.getContext(), alertString, duration);
                        toast.show();
                    }
                    current_projectEndDate = DateFormat.format("dd/MM/yyyy", new Date(project.getEndDate())).toString();
                    projectTextView.setText(String.format(projectTextTemplate,
                            current_projectDate, current_projectModDate, current_projectEndDate));
                    endDate_button.setText("Change End Date");
                }
            };

            // Input Text fields
            final EditText projectNameField = (EditText) rootView.findViewById(R.id.editProjectName);
            projectNameField.setText(current_projectName);
            if (current_projectName.isEmpty()) {
                projectNameField.setError("Please enter a project name");
                projectNameError = true;
            }
            projectNameField.setFilters(new InputFilter[]{nameFilter});
            projectNameField.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    //setModDate should perhaps be private to ProjectEntry
                    //project.setModDate();

                }

                @Override
                public void afterTextChanged(Editable s) {
                    // If the project list contain the name, but not the current project, e.g. non-unique.
                    if (projectsListStrings.contains(projectNameField.getText().toString())) {
                        if (lastOpenedProject > 0) {
                            //int pos = projectsListIDs.
                            if (!projectsListIDs.get(projectsListStrings.indexOf(projectNameField.getText().toString())).equals(lastOpenedProject)) {
                                //if (!projectNameField.getText().toString().toLowerCase().equals(current_projectName.toLowerCase())) {
                                projectNameField.setError("Project name must be unique.");
                                projectNameError = true;
                            }
                        } else {
                            projectNameField.setError("Project name must be unique.");
                            projectNameError = true;
                        }

                        //projectNameError = false;
                    } else if (projectNameField.getText().toString().isEmpty()) {
                        projectNameField.setError("Project name cannot be empty.");
                        projectNameError = true;
                    } else {
                        projectNameError = false;
                    }
                    if (projectNameField.getText().toString().equals(current_projectName)) {

                    } else {
                        project.setName(projectNameField.getText().toString());
                        current_projectName = projectNameField.getText().toString();
                    }

                }
            });
            projectNameField.setFocusable(false);

            final EditText operatorNameField = (EditText) rootView.findViewById(R.id.editOperator);
            operatorNameField.setText(current_projectOperator);
            operatorNameField.setFilters(new InputFilter[]{nameFilter});
            operatorNameField.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
                }

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                    //project.setModDate();
                }

                @Override
                public void afterTextChanged(Editable s) {
                    if (operatorNameField.getText().toString().equals(current_projectOperator)) {

                    } else {
                        project.setOperator(operatorNameField.getText().toString());
                        current_projectOperator = operatorNameField.getText().toString();

                    }

                }
            });
            operatorNameField.setFocusable(false);

            Button addSetupButton = (Button) rootView.findViewById(R.id.add_tab);
            addSetupButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // LOCADE CODE HERE
                    Log.i("ProjectSettingsFragment", "Add Setup Button pressed!");
                    addSetupTab();
                }
            });

            //Switch that toggles editing
            Switch editSwitch = (Switch) rootView.findViewById(R.id.edit_switch);
            editSwitch.setChecked(false);
            editSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if (isChecked) {
                        projectNameField.setFocusableInTouchMode(true);
                        operatorNameField.setFocusableInTouchMode(true);
                        Log.i("ProjectSettings", "switch on!");
                    } else {
                        operatorNameField.setFocusable(false);
                        projectNameField.setFocusable(false);
                        Log.i("ProjectSettings", "switch off!");
                    }
                }
            });

            //If new project start with edit on, else edit off.
            if (current_projectName.isEmpty()) {
                editSwitch.setChecked(true);
                projectNameField.requestFocus();
            } else {
                editSwitch.setChecked(false);
            }

            // Text fields

            projectTextView = (TextView) rootView.findViewById(R.id.projectTextView);

            // Get project end date or display not set if the value is null.
            if (Long.valueOf(project.getEndDate()).toString().equals("0")) {
                current_projectEndDate = "Not set.";
            } else {
                current_projectEndDate = DateFormat.format("dd/MM/yyyy", new Date(project.getEndDate())).toString();
            }
            current_projectModDate = DateFormat.format("dd/MM/yyyy", new Date(project.getModDate())).toString();
            current_projectDate = DateFormat.format("dd/MM/yyyy", new Date(project.getStartDate())).toString();

            projectTextView.setText(String.format(projectTextTemplate,
                    current_projectDate, current_projectModDate, current_projectEndDate));

            initSetupTabHost(rootView);

            endDate_button = (Button) rootView.findViewById(R.id.endDate_button);
            endDate_button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //
                    Log.i("ProjectSettingsFragment", "End Date Button pressed!");
                    Calendar cal=Calendar.getInstance();

                    int year=cal.get(Calendar.YEAR);
                    int month=cal.get(Calendar.MONTH);
                    int day=cal.get(Calendar.DATE);

                    new DatePickerDialog(getContext(), endDatePickerListener,year ,month ,day).show();  //Call this on button click

                }
            });

            return rootView;
        }

        // Tabs with setups
        private void initSetupTabHost(View view) {
            // Setups
            setupsTabHost = (FragmentTabHost) view.findViewById(android.R.id.tabhost);
            setupsTabHost.setup(getActivity(), getChildFragmentManager(), android.R.id.tabcontent);
            setupsTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
                @Override
                public void onTabChanged(String tabId) {
                    //Set current setup
                    current_setup = tabId;
                    Log.i("ProjectActivity", "Current setup: " + tabId);
                    //ObservationsFragment.fragmentChanged();
                    //((ArrayAdapter) ObservationsFragment.observationsList.getAdapter()).notifyDataSetChanged();

                    //TODO: Make this change the current setup in ObservationsFragment

                }

            });

            populateSetupTabHost();
        }

        private void populateSetupTabHost() {
            //Are there any setups
            if (project.getSetupsCount() > 0) {
                HashMap<Integer, ProjectEntry.Setup> setups = project.getSetups();
                List<ProjectEntry.Setup> setupsSorted = new ArrayList<>(setups.values());

                // Sort
                Collections.sort(setupsSorted, new Comparator<ProjectEntry.Setup>() {
                    @Override
                    public int compare(ProjectEntry.Setup o1, ProjectEntry.Setup o2) {
                        return o1.getId() - o2.getId();
                    }
                });

                for (ProjectEntry.Setup s : setupsSorted){
                    Integer id = s.getId();
                    Bundle bundle = new Bundle();
                    bundle.putInt("Id", id);
                    setupsTabHost.addTab(setupsTabHost.newTabSpec(id.toString()).setIndicator(id.toString()), SetupsFragment.class, bundle);
                }
            }
        }

        // Add empty setup
        private void addSetupTab() {
            //Get the setups from the project.
            HashMap<Integer, ProjectEntry.Setup> setups = project.getSetups();
            // Find maximum ID and add one
            Integer id;
            if (setups.isEmpty()){
                id = 0;
            }else{
                id = Collections.max(setups.keySet()) + 1;
            }
            project.addSetup(id);
            Bundle bundle = new Bundle();
            bundle.putInt("Id", id);
            setupsTabHost.addTab(setupsTabHost.newTabSpec(id.toString()).setIndicator(id.toString()), SetupsFragment.class, bundle);
            setupsTabHost.setCurrentTab(id);
        }

        public void refreshSetupTab() {
            setupsTabHost.clearAllTabs();
            populateSetupTabHost();
        }

    }

    private void getData() {

        //Clear old values
        try {
            gpsNames.clear();
            hsNames.clear();
            eastings.clear();
            northings.clear();
            alarmNames.clear();
            antennaNames.clear();
            instrumentNames.clear();
        } catch (NullPointerException e) {
            Log.i("ProjectActivity","getData(): Empty lists");
        }

        //Get batchRecipe from sharedPrefs
        batchRecipeString = prefs.getString("batch_recipe_string","");

        //Get readable database in order to get a list of projects
        //db = DataBaseHandler.getInstance(getApplicationContext());
        fixedpointEntries = db.getAllFixedpointEntries();
        alarmEntries = db.getAllAlarmEntries();
        antennaEntries = db.getAllAntennaEntries();
        instrumentEntries = db.getAllInstrumentEntries();

        //Add dummies so spinner can show empty
        fixedpointEntries.add(new FixedpointEntry(-1,"","",0,0));
        alarmEntries.add(new AlarmEntry(-1,""));
        antennaEntries.add(new AntennaEntry(-1,"",""));
        instrumentEntries.add(new InstrumentEntry(-1,""));

        //Sorting
        Collections.sort(fixedpointEntries, new Comparator<FixedpointEntry>() {
            @Override
            public int compare(FixedpointEntry o1, FixedpointEntry o2) {
                return o1.getGPSName().compareTo(o2.getGPSName());
            }
        });
        Collections.sort(alarmEntries, new Comparator<AlarmEntry>() {
            @Override
            public int compare(AlarmEntry o1, AlarmEntry o2) {
                return o1.alarm_id - o2.alarm_id;
            }
        });
        Collections.sort(antennaEntries, new Comparator<AntennaEntry>() {
            @Override
            public int compare(AntennaEntry o1, AntennaEntry o2) {
                return o1.antenna_id - o2.antenna_id;
            }
        });
        Collections.sort(instrumentEntries, new Comparator<InstrumentEntry>() {
            @Override
            public int compare(InstrumentEntry o1, InstrumentEntry o2) {
                return o1.instrument_id - o2.instrument_id;
            }
        });

        //Fixedpoints
        for (int i = 0; i < db.getFixedpointsCount(); i++) {
            gpsNames.add(i, fixedpointEntries.get(i).getGPSName());
            hsNames.add(i, fixedpointEntries.get(i).getHSName());
            eastings.add(i, fixedpointEntries.get(i).getEasting());
            northings.add(i, fixedpointEntries.get(i).getNorthing());
        }

        for (int i = 0; i < db.getAlarmsCount(); i++) {
            alarmNames.add(i, alarmEntries.get(i).getName());
        }
        for (int i = 0; i < db.getAntennaeCount(); i++) {
            antennaNames.add(i, antennaEntries.get(i).getName());
        }
        for (int i = 0; i < db.getInstrumentsCount(); i++) {
            instrumentNames.add(i, instrumentEntries.get(i).getName());
        }
        Log.i("SetupsFragment", "Loaded " + instrumentNames.size() + " instruments, "
                + alarmNames.size() + " alarms, and "
                + gpsNames.size() + " fixedpoints");
    }

}


text:
package de.atrsoft.successorofoak.utilities.logging.atrshmlog.tests;

/**
 * We import our jni test layer.
 */
import de.atrsoft.successorofoak.utilities.logging.atrshmlog.ATRSHMLOG;

import de.atrsoft.successorofoak.utilities.logging.atrshmlog.ATRSHMLOG.atrshmlog_error;

import de.atrsoft.successorofoak.utilities.logging.atrshmlog.ATRSHMLOG.atrshmlog_counter;

import de.atrsoft.successorofoak.utilities.logging.atrshmlog.ATRSHMLOG.atrshmlog_strategy;

public class ATRSHMLOGTestAttach {

    ///////////////////////////////////////////////////////
    // we start here and execute as a demo
    public static void main(String args[]) {
	ATRSHMLOG theLog = new ATRSHMLOG();

	int result = theLog.attach();

	System.out.println("ATRSHMLOGTestAttach : " + result + " : ");

	System.out.println("Shmid : " + theLog.getShmid() + " : ");

	System.out.println("AcquireCount : " + theLog.getAcquireCount() + " : ");
	System.out.println("BufferId : " + theLog.getBufferId() + " : ");

	System.out.println("InitBuffersInAdvance : " + theLog.getInitBuffersInAdvance() + " : ");

	System.out.println("BufferSize : " + theLog.getBufferSize() + " : ");

	System.out.println("PreallocBufferCount : " + theLog.getPreallocBufferCount() + " : ");

	System.out.println("FListBufferSlaveCount : " + theLog.getFListBufferSlaveCount() + " : ");

	System.out.println("FListBufferSlaveWait : " + theLog.getFListBufferSlaveWait() + " : ");

	System.out.println("WaitForSlaves : " + theLog.getWaitForSlaves() + " : ");

	System.out.println("StrategyProcess : " + theLog.getStrategyProcess() + " : ");

	System.out.println("AutoflushProcess : " + theLog.getAutoflushProcess() + " : ");

	System.out.println("Checksum : " + theLog.getChecksum() + " : ");

	System.out.println("ThreadFence1 : " + theLog.getThreadFence1() + " : ");
	System.out.println("ThreadFence2 : " + theLog.getThreadFence2() + " : ");
	System.out.println("ThreadFence3 : " + theLog.getThreadFence3() + " : ");
	System.out.println("ThreadFence4 : " + theLog.getThreadFence4() + " : ");
	System.out.println("ThreadFence5 : " + theLog.getThreadFence5() + " : ");
	System.out.println("ThreadFence6 : " + theLog.getThreadFence6() + " : ");
	System.out.println("ThreadFence7 : " + theLog.getThreadFence7() + " : ");
	System.out.println("ThreadFence8 : " + theLog.getThreadFence8() + " : ");
	System.out.println("ThreadFence9 : " + theLog.getThreadFence9() + " : ");
	System.out.println("ThreadFence10 : " + theLog.getThreadFence10() + " : ");
	System.out.println("ThreadFence11 : " + theLog.getThreadFence11() + " : ");
	System.out.println("ThreadFence12 : " + theLog.getThreadFence12() + " : ");
	System.out.println("ThreadFence13 : " + theLog.getThreadFence13() + " : ");

	System.out.println("InittimeTscBefore : " + theLog.getInittimeTscBefore() + " : ");
	System.out.println("InittimeTscAfter : " + theLog.getInittimeTscAfter() + " : ");

	long[] inittime = new long[2];

	theLog.getInittime(inittime);

	System.out.println("Inittime : " + inittime[0] + " " + inittime[1] + " : ");

	System.out.println("EventLocksMax : " + theLog.getEventLocksMax() + " : ");

	System.out.println("ClockId : " + theLog.getClockId() + " : ");

	System.out.println("Version : " + theLog.getVersion() + " : ");

	System.out.println("MinorVersion : " + theLog.getMinorVersion() + " : ");

	System.out.println("PatchVersion : " + theLog.getPatchVersion() + " : ");

	System.out.println("BufferMaxSize : " + theLog.getBufferMaxSize() + " : ");

	System.out.println(" ");
    }

}

/* end of file */


text:
<?xml version="1.0" encoding="UTF-8"?>
<project
	xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
>

	<modelVersion>4.0.0</modelVersion>
	<artifactId>maven-overrides</artifactId>
	<packaging>pom</packaging>

	<parent>
		<groupId>blade</groupId>
		<artifactId>maven</artifactId>
		<version>1.0.0</version>
		<relativePath>../pom.xml</relativePath>
	</parent>

	<modules>
		<module>login-web-resource-bundle-override</module>
		<module>module-jsp-override</module>
		<module>portlet-form-taglib-override</module>
	</modules>
</project>


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
J. Wash. Acad. Sci. 40: 52 (1950)

#### Original name
Nowakowskiella atkinsii Sparrow, 1950

### Remarks
null


text:
import collections
import json
import os.path
import re
import sys

file_name = None
description = ''

primitiveTypes = ['integer', 'number', 'boolean', 'string', 'object', 'any', 'array']

def assignType(item, type, isArray=False):
    if isArray:
        item['type'] = 'array'
        item['items'] = collections.OrderedDict()
        assignType(item['items'], type)
        return

    if type == 'enum':
        type = 'string'
    if type in primitiveTypes:
        item['type'] = type
    else:
        item['$ref'] = type

def createItem(d, experimental, deprecated, name=None):
    result = collections.OrderedDict(d)
    if name:
        result['name'] = name
    global description
    if description:
        result['description'] = description.strip()
    if experimental:
        result['experimental'] = True
    if deprecated:
        result['deprecated'] = True
    return result

def parse(data):
    protocol = collections.OrderedDict()
    protocol['version'] = collections.OrderedDict()
    protocol['domains'] = []
    domain = None
    item = None
    subitems = None
    nukeDescription = False
    global description
    lines = data.split('\n')
    for i in range(0, len(lines)):
        if nukeDescription:
            description = ''
            nukeDescription = False
        line = lines[i]
        trimLine = line.strip()

        if trimLine.startswith('#'):
            if len(description):
              description += '\n'
            description += trimLine[2:]
            continue
        else:
            nukeDescription = True

        if len(trimLine) == 0:
            continue

        match = re.compile('^(experimental )?(deprecated )?domain (.*)').match(line)
        if match:
            domain = createItem({'domain' : match.group(3)}, match.group(1), match.group(2))
            protocol['domains'].append(domain)
            continue

        match = re.compile('^  depends on ([^\s]+)').match(line)
        if match:
            if 'dependencies' not in domain:
                domain['dependencies'] = []
            domain['dependencies'].append(match.group(1))
            continue

        match = re.compile('^  (experimental )?(deprecated )?type (.*) extends (array of )?([^\s]+)').match(line)
        if match:
            if 'types' not in domain:
                domain['types'] = []
            item = createItem({'id': match.group(3)}, match.group(1), match.group(2))
            assignType(item, match.group(5), match.group(4))
            domain['types'].append(item)
            continue

        match = re.compile('^  (experimental )?(deprecated )?(command|event) (.*)').match(line)
        if match:
            list = []
            if match.group(3) == 'command':
                if 'commands' in domain:
                    list = domain['commands']
                else:
                    list = domain['commands'] = []
            else:
                if 'events' in domain:
                    list = domain['events']
                else:
                    list = domain['events'] = []

            item = createItem({}, match.group(1), match.group(2), match.group(4))
            list.append(item)
            continue

        match = re.compile('^      (experimental )?(deprecated )?(optional )?(array of )?([^\s]+) ([^\s]+)').match(line)
        if match:
            param = createItem({}, match.group(1), match.group(2), match.group(6))
            if match.group(3):
                param['optional'] = True
            assignType(param, match.group(5), match.group(4))
            if match.group(5) == 'enum':
                enumliterals = param['enum'] = []
            subitems.append(param)
            continue

        match = re.compile('^    (parameters|returns|properties)').match(line)
        if match:
            subitems = item[match.group(1)] = []
            continue

        match = re.compile('^    enum').match(line)
        if match:
            enumliterals = item['enum'] = []
            continue

        match = re.compile('^version').match(line)
        if match:
            continue

        match = re.compile('^  major (\d+)').match(line)
        if match:
            protocol['version']['major'] = match.group(1)
            continue

        match = re.compile('^  minor (\d+)').match(line)
        if match:
            protocol['version']['minor'] = match.group(1)
            continue

        match = re.compile('^    redirect ([^\s]+)').match(line)
        if match:
            item['redirect'] = match.group(1)
            continue

        match = re.compile('^      (  )?[^\s]+$').match(line)
        if match:
            # enum literal
            enumliterals.append(trimLine)
            continue

        print 'Error in %s:%s, illegal token: \t%s' % (file_name, i, line)
        sys.exit(1)
    return protocol

def main(argv):
    if len(argv) < 2:
        sys.stderr.write("Usage: %s <protocol.pdl> <protocol.json>\n" % sys.argv[0])
        return 1
    global file_name
    file_name = os.path.normpath(argv[0])
    input_file = open(file_name, "r")
    pdl_string = input_file.read()
    protocol = parse(pdl_string)
    output_file = open(argv[0].replace('.pdl', '.json'), 'wb')
    json.dump(protocol, output_file, indent=4, separators=(',', ': '))
    output_file.close()

    output_file = open(os.path.normpath(argv[1]), 'wb')
    json.dump(protocol, output_file, indent=4, separators=(',', ': '))
    output_file.close()

if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))


text:
package org.kuali.kra.institutionalproposal.printing.service;

import org.kuali.coeus.propdev.impl.person.ProposalPerson;

import java.util.List;

/**
 * These class have different methods to provide service like pass proposal
 * number get the list of proposal persons.
 */
public interface InstitutionalProposalPersonService {
	/**
	 * This method will return the list of proposal persons if proposal person
	 * find in development proposal.
	 *
	 * @param proposalNumber
	 *            is a number used to get the proposal persons for this proposal
	 *            number.
	 * @return list of proposal persons
	 */
	public List<ProposalPerson> getInvestigatorsFromDevelopmentProposal(
			String proposalNumber);

}


text:
/* global define, app */
define([
	"react",
	"map/Controller"
], function (React, MapController) {
	'use strict';

	return React.createClass({

		componentDidMount: function () {
			// app is only variable in global namespace, attach map to it
			MapController.init(this.props.options);
		},

		render: function () {
			return (
				React.DOM.div({'className': 'map-panel', 'id': this.props.id },
					React.DOM.div({'className': 'map', 'id': 'map'},
						React.DOM.div({'className': 'settings-icon', 'onClick': this.props.clickToggle })
					)
				)
			);
		}

	});

});


text:
package server

import (
	"fmt"
	"io/ioutil"
	"os"
	"strconv"
	"sync"
	"sync/atomic"
	"testing"
	"time"

	"github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
	"github.com/hyperledger/fabric/orderer/common/localconfig"
	perf "github.com/hyperledger/fabric/orderer/common/performance"
	cb "github.com/hyperledger/fabric/protos/common"
	"github.com/stretchr/testify/assert"
)

// USAGE
//
//  BENCHMARK=true go test -run=TestOrdererBenchmark[Solo|Kafka][Broadcast|Deliver]
//
// You can specify a specific test permutation by specifying the complete subtest
// name corresponding to the permutation you would like to run. e.g:
//
//  TestOrdererBenchmark[Solo|Kafka][Broadcast|Deliver]/10ch/10000tx/10kb/10bc/0dc/10ord
//
// (The permutation has to be valid as defined in the source code)
//
// RUNNING KAFKA ORDERER BENCHMARKS
//
// A Kafka cluster is required to run the Kafka-based benchmark. The benchmark
// expects to find a seed broker is listening on localhost:9092.
//
// A suitable Kafka cluster is provided as a docker compose application defined
// in the docker-compose.yml file provided with this package. To run the Kafka
// benchmarks with the provided Kafaka cluster:
//
//    From this package's directory, first run:
//
//       docker-compose up -d
//
//    Then execute:
//
//       BENCHMARK=true go test -run TestOrdererBenchmarkKafkaBroadcast
//
// If you are not using the Kafka cluster provided in the docker-compose.yml,
// the list of seed brokers can be adjusted by setting the value of
// x_ORDERERS_KAFKA_BROKERS in the `envvars` map below.
//
// DESCRIPTION
//
// Benchmark test makes [ch] channels, creates [bc] clients per channel per orderer. There
// are [ord] orderer instances in total. A client ONLY interacts with ONE channel and ONE
// orderer, so the number of client in total is [ch * bc * ord]. Note that all clients
// execute concurrently.
//
// The test sends [tx] transactions of size [kb] in total. These tx are evenly distributed
// among all clients, which gives us [tx / (ch * bc * ord)] tx per client.
//
// For example, given following configuration:
//
// channels          [ch]: 4 (CH0, CH1, CH2, CH3)
// broadcast clients [bc]: 5
// orderers         [ord]: 2 (ORD0, ORD1)
// transactions      [tx]: 200
//
// We will spawn 4 * 5 * 2 = 40 simultaneous broadcast clients in total, 20 clients per
// orderer. For each orderer, there will be 5 clients per channel. Each client will send
// 200 / 40 = 5 transactions. Pseudo-code would be:
//
// for each one of [ord] orderers:
//     for each one of [ch] channels:
//         for each one of [bc] clients:
//             go send [tx / (ch * bc * ord)] tx
//
// Additionally, [dc] deliver clients per channel per orderer seeks all the blocks in
// that channel. It would 'predict' the last block number, and seek from the oldest to
// that. In this manner, we could reliably assert that all transactions we send are
// ordered. This is important for evaluating elapsed time of async broadcast operations.
//
// Again, each deliver client only interacts with one channel and one orderer, which
// results in [ch * dc * ord] deliver clients in total.
//
// ch  -> channelCounts
// bc  -> broadcastClientPerChannel
// tx  -> totalTx
// kb  -> messagesSizes
// ord -> numOfOrderer
// dc  -> deliverClientPerChannel
//
// If `multiplex` is true, broadcast and deliver are running simultaneously. Otherwise,
// broadcast is run before deliver. This is useful when testing deliver performance only,
// as deliver is effectively retrieving pre-generated blocks, so it shouldn't be choked
// by slower broadcast.
//

const (
	MaxMessageCount = 10

	// This is the hard limit for all types of tx, including config tx, which is normally
	// larger than 13 KB. Therefore, for config tx not to be rejected, this value cannot
	// be less than 13 KB.
	AbsoluteMaxBytes  = 15 // KB
	PreferredMaxBytes = 10 // KB
)

var envvars = map[string]string{
	"ORDERER_GENERAL_GENESISPROFILE":                            localconfig.SampleDevModeSoloProfile,
	"ORDERER_GENERAL_LEDGERTYPE":                                "file",
	"ORDERER_GENERAL_LOGLEVEL":                                  "error",
	"ORDERER_KAFKA_VERBOSE":                                     "false",
	localconfig.Prefix + "_ORDERER_BATCHSIZE_MAXMESSAGECOUNT":   strconv.Itoa(MaxMessageCount),
	localconfig.Prefix + "_ORDERER_BATCHSIZE_ABSOLUTEMAXBYTES":  strconv.Itoa(AbsoluteMaxBytes) + " KB",
	localconfig.Prefix + "_ORDERER_BATCHSIZE_PREFERREDMAXBYTES": strconv.Itoa(PreferredMaxBytes) + " KB",
	localconfig.Prefix + "_ORDERER_KAFKA_BROKERS":               "[localhost:9092]",
}

type factors struct {
	numOfChannels             int // number of channels
	totalTx                   int // total number of messages
	messageSize               int // message size in KB
	broadcastClientPerChannel int // concurrent broadcast clients
	deliverClientPerChannel   int // concurrent deliver clients
	numOfOrderer              int // number of orderer instances (Kafka ONLY)
}

// This is to give each test run a better name. The output
// would be something like '4ch/100tx/5kb/100bc/100dc/5ord'
func (f factors) String() string {
	return fmt.Sprintf(
		"%dch/%dtx/%dkb/%dbc/%ddc/%dord",
		f.numOfChannels,
		f.totalTx,
		f.messageSize,
		f.broadcastClientPerChannel,
		f.deliverClientPerChannel,
		f.numOfOrderer,
	)
}

// As benchmark tests are skipped by default, we put this test here to catch
// potential code changes that might break benchmark tests. If this test fails,
// it is likely that benchmark tests need to be updated.
func TestOrdererBenchmarkSolo(t *testing.T) {
	for key, value := range envvars {
		os.Setenv(key, value)
		defer os.Unsetenv(key)
	}

	t.Run("Benchmark Sample Test (Solo)", func(t *testing.T) {
		benchmarkOrderer(t, 1, 5, PreferredMaxBytes, 1, 0, 1, true)
	})
}

// Benchmark broadcast API in Solo mode
func TestOrdererBenchmarkSoloBroadcast(t *testing.T) {
	if os.Getenv("BENCHMARK") == "" {
		t.Skip("Skipping benchmark test")
	}

	for key, value := range envvars {
		os.Setenv(key, value)
		defer os.Unsetenv(key)
	}

	var (
		channelCounts             = []int{1, 10, 50}
		totalTx                   = []int{10000}
		messagesSizes             = []int{1, 2, 10}
		broadcastClientPerChannel = []int{1, 10, 50}
		deliverClientPerChannel   = []int{0} // We are not interested in deliver performance here
		numOfOrderer              = []int{1}

		args = [][]int{
			channelCounts,
			totalTx,
			messagesSizes,
			broadcastClientPerChannel,
			deliverClientPerChannel,
			numOfOrderer,
		}
	)

	for factors := range combinations(args) {
		t.Run(factors.String(), func(t *testing.T) {
			benchmarkOrderer(
				t,
				factors.numOfChannels,
				factors.totalTx,
				factors.messageSize,
				factors.broadcastClientPerChannel,
				factors.deliverClientPerChannel,
				1, // For solo orderer, we should always have exactly one instance
				true,
			)
		})
	}
}

// Benchmark deliver API in Solo mode
func TestOrdererBenchmarkSoloDeliver(t *testing.T) {
	if os.Getenv("BENCHMARK") == "" {
		t.Skip("Skipping benchmark test")
	}

	for key, value := range envvars {
		os.Setenv(key, value)
		defer os.Unsetenv(key)
	}

	var (
		channelCounts             = []int{1, 10, 50}
		totalTx                   = []int{10000}
		messagesSizes             = []int{1, 2, 10}
		broadcastClientPerChannel = []int{100}
		deliverClientPerChannel   = []int{1, 10, 50}
		numOfOrderer              = []int{1}

		args = [][]int{
			channelCounts,
			totalTx,
			messagesSizes,
			broadcastClientPerChannel,
			deliverClientPerChannel,
			numOfOrderer,
		}
	)

	for factors := range combinations(args) {
		t.Run(factors.String(), func(t *testing.T) {
			benchmarkOrderer(
				t,
				factors.numOfChannels,
				factors.totalTx,
				factors.messageSize,
				factors.broadcastClientPerChannel,
				factors.deliverClientPerChannel,
				1, // For solo orderer, we should always have exactly one instance
				false,
			)
		})
	}
}

// Benchmark broadcast API in Kafka mode
func TestOrdererBenchmarkKafkaBroadcast(t *testing.T) {
	if os.Getenv("BENCHMARK") == "" {
		t.Skip("Skipping benchmark test")
	}

	for key, value := range envvars {
		os.Setenv(key, value)
		defer os.Unsetenv(key)
	}

	os.Setenv("ORDERER_GENERAL_GENESISPROFILE", localconfig.SampleDevModeKafkaProfile)
	defer os.Unsetenv("ORDERER_GENERAL_GENESISPROFILE")

	var (
		channelCounts             = []int{1, 10}
		totalTx                   = []int{10000}
		messagesSizes             = []int{1, 2, 10}
		broadcastClientPerChannel = []int{1, 10, 50}
		deliverClientPerChannel   = []int{0} // We are not interested in deliver performance here
		numOfOrderer              = []int{1, 5, 10}

		args = [][]int{
			channelCounts,
			totalTx,
			messagesSizes,
			broadcastClientPerChannel,
			deliverClientPerChannel,
			numOfOrderer,
		}
	)

	for factors := range combinations(args) {
		t.Run(factors.String(), func(t *testing.T) {
			benchmarkOrderer(
				t,
				factors.numOfChannels,
				factors.totalTx,
				factors.messageSize,
				factors.broadcastClientPerChannel,
				factors.deliverClientPerChannel,
				factors.numOfOrderer,
				true,
			)
		})
	}
}

// Benchmark deliver API in Kafka mode
func TestOrdererBenchmarkKafkaDeliver(t *testing.T) {
	if os.Getenv("BENCHMARK") == "" {
		t.Skip("Skipping benchmark test")
	}

	for key, value := range envvars {
		os.Setenv(key, value)
		defer os.Unsetenv(key)
	}

	os.Setenv("ORDERER_GENERAL_GENESISPROFILE", localconfig.SampleDevModeKafkaProfile)
	defer os.Unsetenv("ORDERER_GENERAL_GENESISPROFILE")

	var (
		channelCounts             = []int{1, 10}
		totalTx                   = []int{10000}
		messagesSizes             = []int{1, 2, 10}
		broadcastClientPerChannel = []int{50}
		deliverClientPerChannel   = []int{1, 10, 50}
		numOfOrderer              = []int{1, 5, 10}

		args = [][]int{
			channelCounts,
			totalTx,
			messagesSizes,
			broadcastClientPerChannel,
			deliverClientPerChannel,
			numOfOrderer,
		}
	)

	for factors := range combinations(args) {
		t.Run(factors.String(), func(t *testing.T) {
			benchmarkOrderer(
				t,
				factors.numOfChannels,
				factors.totalTx,
				factors.messageSize,
				factors.broadcastClientPerChannel,
				factors.deliverClientPerChannel,
				factors.numOfOrderer,
				false,
			)
		})
	}
}

func benchmarkOrderer(
	t *testing.T,
	numOfChannels int,
	totalTx int,
	msgSize int,
	broadcastClientPerChannel int,
	deliverClientPerChannel int,
	numOfOrderer int,
	multiplex bool,
) {
	// Calculate intermediate variables used internally. See the comment at the beginning
	// of this file for the purpose of these vars.
	txPerClient := totalTx / (broadcastClientPerChannel * numOfChannels * numOfOrderer)
	// In case total tx cannot be fully divided, txPerClient is actually round-down value.
	// So we need to calculate the actual number of transactions to be sent. However, this
	// number should be very close to demanded number of tx, as it's fairly big.
	totalTx = txPerClient * broadcastClientPerChannel * numOfChannels * numOfOrderer

	// Estimate number of tx per block, which is used by deliver client to seek for.
	txPerChannel := totalTx / numOfChannels
	// Message size consists of payload and signature
	msg := perf.MakeNormalTx("abcdefghij", msgSize)
	actualMsgSize := len(msg.Payload) + len(msg.Signature)
	// max(1, x) in case a block can only contain exactly one tx
	txPerBlk := min(MaxMessageCount, max(1, PreferredMaxBytes*perf.Kilo/actualMsgSize))
	// Round-down here is ok because we don't really care about trailing tx
	blkPerChannel := txPerChannel / txPerBlk

	var txCount uint64 // Atomic counter to keep track of actual tx sent

	// Initialization shared by all orderers
	conf := config.Load()
	initializeLoggingLevel(conf)
	initializeLocalMsp(conf)
	perf.InitializeServerPool(numOfOrderer)

	// Generate a random system channel id for each test run,
	// so it does not recover ledgers from previous run.
	systemchannel := "system-channel-" + perf.RandomID(5)
	conf.General.SystemChannel = systemchannel

	// Spawn orderers
	for i := 0; i < numOfOrderer; i++ {
		// If we are using json or file ledger, we should use temp dir for ledger location
		// because default location "/var/hyperledger/production/orderer" in sample config
		// isn't always writable. Also separate dirs are created for each orderer instance
		// as leveldb cannot share the same dir. These temp dirs are cleaned up after each
		// test run.
		//
		// We need to make a copy of config here so that multiple orderers won't refer to
		// the same config object by address.
		localConf := config.TopLevel(*conf)
		if localConf.General.LedgerType != "ram" {
			tempDir, err := ioutil.TempDir("", "fabric-benchmark-test-")
			assert.NoError(t, err, "Should be able to create temp dir")
			localConf.FileLedger.Location = tempDir
			defer os.RemoveAll(tempDir)
		}

		go Start("benchmark", &localConf)
	}

	defer perf.OrdererExec(perf.Halt)

	// Wait for server to boot and systemchannel to be ready
	perf.OrdererExec(perf.WaitForService)
	perf.OrdererExecWithArgs(perf.WaitForChannels, systemchannel)

	// Create channels
	benchmarkServers := perf.GetBenchmarkServerPool()
	channelIDs := make([]string, numOfChannels)
	txs := make(map[string]*cb.Envelope)
	for i := 0; i < numOfChannels; i++ {
		id := perf.CreateChannel(benchmarkServers[0]) // We only need to create channel on one orderer
		channelIDs[i] = id
		txs[id] = perf.MakeNormalTx(id, msgSize)
	}

	// Wait for all the created channels to be ready
	perf.OrdererExecWithArgs(perf.WaitForChannels, stoi(channelIDs)...)

	// Broadcast loop
	broadcast := func(wg *sync.WaitGroup) {
		perf.OrdererExec(func(server *perf.BenchmarkServer) {
			var broadcastWG sync.WaitGroup
			// Since the submission and ordering of transactions are async, we need to
			// spawn a deliver client to track the progress of ordering. So there are
			// x broadcast clients and 1 deliver client per channel, so we should be
			// waiting for (numOfChannels * (x + 1)) goroutines here
			broadcastWG.Add(numOfChannels * (broadcastClientPerChannel + 1))

			for _, channelID := range channelIDs {
				go func(channelID string) {
					// Spawn a deliver instance per channel to track the progress of broadcast
					go func() {
						deliverClient := server.CreateDeliverClient()
						status, err := perf.SeekAllBlocks(deliverClient, channelID, uint64(blkPerChannel))
						assert.Equal(t, cb.Status_SUCCESS, status, "Expect deliver reply to be SUCCESS")
						assert.NoError(t, err, "Expect deliver handler to exist normally")

						broadcastWG.Done()
					}()

					for c := 0; c < broadcastClientPerChannel; c++ {
						go func() {
							broadcastClient := server.CreateBroadcastClient()
							defer func() {
								broadcastClient.Close()
								err := <-broadcastClient.Errors()
								assert.NoError(t, err, "Expect broadcast handler to shutdown gracefully")
							}()

							for i := 0; i < txPerClient; i++ {
								atomic.AddUint64(&txCount, 1)
								broadcastClient.SendRequest(txs[channelID])
								assert.Equal(t, cb.Status_SUCCESS, broadcastClient.GetResponse().Status, "Expect enqueue to succeed")
							}
							broadcastWG.Done()
						}()
					}
				}(channelID)
			}

			broadcastWG.Wait()
		})

		if wg != nil {
			wg.Done()
		}
	}

	// Deliver loop
	deliver := func(wg *sync.WaitGroup) {
		perf.OrdererExec(func(server *perf.BenchmarkServer) {
			var deliverWG sync.WaitGroup
			deliverWG.Add(deliverClientPerChannel * numOfChannels)
			for g := 0; g < deliverClientPerChannel; g++ {
				go func() {
					for _, channelID := range channelIDs {
						go func(channelID string) {
							deliverClient := server.CreateDeliverClient()
							status, err := perf.SeekAllBlocks(deliverClient, channelID, uint64(blkPerChannel))
							assert.Equal(t, cb.Status_SUCCESS, status, "Expect deliver reply to be SUCCESS")
							assert.NoError(t, err, "Expect deliver handler to exist normally")

							deliverWG.Done()
						}(channelID)
					}
				}()
			}
			deliverWG.Wait()
		})

		if wg != nil {
			wg.Done()
		}
	}

	var wg sync.WaitGroup
	var btime, dtime time.Duration

	if multiplex {
		// Parallel
		start := time.Now()

		wg.Add(2)
		go broadcast(&wg)
		go deliver(&wg)
		wg.Wait()

		btime = time.Since(start)
		dtime = time.Since(start)
	} else {
		// Serial
		start := time.Now()
		broadcast(nil)
		btime = time.Since(start)

		start = time.Now()
		deliver(nil)
		dtime = time.Since(start)
	}

	// Assert here to guard against programming error caused by miscalculation of message count.
	// Experiment shows that atomic counter is not bottleneck.
	assert.Equal(t, uint64(totalTx), txCount, "Expected to send %d msg, but actually sent %d", uint64(totalTx), txCount)

	ordererProfile := os.Getenv("ORDERER_GENERAL_GENESISPROFILE")

	fmt.Printf(
		"Messages: %6d  Message Size: %3dKB  Channels: %3d Orderer (%s): %2d | "+
			"Broadcast Clients: %3d  Write tps: %5.1f tx/s Elapsed Time: %0.2fs | "+
			"Deliver clients: %3d  Read tps: %8.1f blk/s Elapsed Time: %0.2fs\n",
		totalTx,
		msgSize,
		numOfChannels,
		ordererProfile,
		numOfOrderer,
		broadcastClientPerChannel*numOfChannels*numOfOrderer,
		float64(totalTx)/btime.Seconds(),
		btime.Seconds(),
		deliverClientPerChannel*numOfChannels*numOfOrderer,
		float64(blkPerChannel*deliverClientPerChannel*numOfChannels)/dtime.Seconds(),
		dtime.Seconds())
}

func combinations(args [][]int) <-chan factors {
	ch := make(chan factors)
	go func() {
		defer close(ch)
		for c := range combine(args) {
			ch <- factors{
				numOfChannels:             c[0],
				totalTx:                   c[1],
				messageSize:               c[2],
				broadcastClientPerChannel: c[3],
				deliverClientPerChannel:   c[4],
				numOfOrderer:              c[5],
			}
		}
	}()
	return ch
}

// this generates all combinations of elements in arrays.
// for example,
// given
// [[A, B],
//  [C, D]],
// the result should be
// [A, C]
// [A, D]
// [B, C]
// [B, D]
func combine(args [][]int) <-chan []int {
	ch := make(chan []int)
	go func() {
		defer close(ch)
		if len(args) == 1 {
			for _, i := range args[0] {
				ch <- []int{i}
			}
		} else {
			for _, i := range args[0] {
				for j := range combine(args[1:]) {
					ch <- append([]int{i}, j...)
				}
			}
		}
	}()
	return ch
}

func min(x, y int) int {
	if x > y {
		return y
	}
	return x
}

func max(x, y int) int {
	if x > y {
		return x
	}
	return y
}

func stoi(s []string) (ret []interface{}) {
	ret = make([]interface{}, len(s))
	for i, d := range s {
		ret[i] = d
	}
	return
}