text:
import { flatten, get } from '@antv/util';
import { Coordinate, getCoordinate } from '@antv/coord';
import { Chart } from '../../../../src';
import Interval from '../../../../src/geometry/interval';
import IntervalLabel from '../../../../src/geometry/label/interval';
import { getTheme } from '../../../../src/theme/';
import { createCanvas, createDiv } from '../../../util/dom';
import { createScale } from '../../../util/scale';
import { positiveNegativeData } from '../../../data/positive-negative';
import { Point } from '../../../../src/interface';
import { near } from '../../../util/math';

const Theme = getTheme('default');
const CartesianCoordinate = getCoordinate('rect');

describe('interval labels', () => {
  const div = createDiv();
  const canvas = createCanvas({
    container: div,
    width: 1000,
    height: 300,
  });

  const coord = new CartesianCoordinate({
    start: { x: 0, y: 200 },
    end: { x: 200, y: 0 },
  });

  const transposedCoord = new CartesianCoordinate({
    start: { x: 50, y: 250 },
    end: { x: 250, y: 50 },
  });
  transposedCoord.transpose();

  const data = [
    { country: 'A', year: '1750', value: 502, percent: 0.5169927909371782 },
    { country: 'A', year: '1800', value: 635, percent: 0.5545851528384279 },
  ];
  const scaleDefs = {
    year: {
      range: [0.25, 0.75],
    },
    country: {
      range: [0.25, 0.75],
    },
    percent: {
      formatter: (val) => val.toFixed(4) * 100 + '%',
    },
    value: {
      nice: true,
    },
  };

  const scales = {
    year: createScale('year', data, scaleDefs),
    value: createScale('value', data, scaleDefs),
    percent: createScale('percent', data, scaleDefs),
    country: createScale('country', data, scaleDefs),
  };

  describe('cartesion', () => {
    const interval = new Interval({
      data,
      scales,
      container: canvas.addGroup(),
      labelsContainer: canvas.addGroup(),
      coordinate: coord,
      scaleDefs,
    });
    interval.position('year*value').size(30).label('percent', {
      position: 'middle',
      offset: 0,
    });
    interval.init({
      theme: Theme,
    });
    interval.paint();

    // 生成映射数据
    // @ts-ignore
    const beforeMappingData = interval.beforeMappingData;
    // @ts-ignore
    const dataArray = interval.beforeMapping(beforeMappingData);

    let mappingArray = [];
    for (const eachGroup of dataArray) {
      // @ts-ignore
      const mappingData = interval.mapping(eachGroup);
      mappingArray.push(mappingData);
    }
    mappingArray = flatten(mappingArray);

    const gLabels = new IntervalLabel(interval);
    const [data1, data2] = mappingArray;

    it('single label position middle', () => {
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe(data1.x);
      expect(item1.y).toBe((data1.y + coord.y.start) / 2);
      expect(item1.textAlign).toBe('center');
      expect(item2.x).toBe(data2.x);
      expect(item2.y).toBe((data2.y + coord.y.start) / 2);
      expect(item2.textAlign).toBe('center');
    });

    it('single label position left', () => {
      interval.label('percent', {
        position: 'left',
        offset: 0,
      });
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe(data1.x - 15);
      expect(item1.y).toBe((data1.y + coord.y.start) / 2);
      expect(item1.textAlign).toBe('left');
      expect(item2.x).toBe(data2.x - 15);
      expect(item2.y).toBe((data2.y + coord.y.start) / 2);
      expect(item2.textAlign).toBe('left');
    });

    it('single label position right', () => {
      interval.label('percent', {
        position: 'right',
        offset: 0,
      });

      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe(data1.x + 15);
      expect(item1.y).toBe((data1.y + coord.y.start) / 2);
      expect(item1.textAlign).toBe('left');
      expect(item2.x).toBe(data2.x + 15);
      expect(item2.y).toBe((data2.y + coord.y.start) / 2);
      expect(item2.textAlign).toBe('left');
    });

    it('single label position top', () => {
      interval.label('percent', {
        position: 'top',
        offset: 0,
      });

      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe(data1.x);
      expect(item1.y).toBe(data1.y);
      expect(item1.textAlign).toBe('center');
      expect(item1.textBaseline).toBe('bottom');
      expect(item2.x).toBe(data2.x);
      expect(item2.y).toBe(data2.y);
      expect(item2.textAlign).toBe('center');
      expect(item2.textBaseline).toBe('bottom');
    });

    it('single label position bottom', () => {
      interval.label('percent', {
        position: 'bottom',
        offset: 0,
      });
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe(data1.x);
      expect(item1.y).toBe(coord.y.start);
      expect(item1.textAlign).toBe('center');
      expect(item1.textBaseline).toBe('bottom');
      expect(item2.x).toBe(data2.x);
      expect(item2.y).toBe(coord.y.start);
      expect(item2.textAlign).toBe('center');
      expect(item2.textBaseline).toBe('bottom');
    });
  });

  describe('transposed coordinate', () => {
    const interval = new Interval({
      data,
      scales,
      container: canvas.addGroup(),
      labelsContainer: canvas.addGroup(),
      coordinate: transposedCoord,
      scaleDefs,
    });
    interval.position('country*value').color('year').adjust('stack').label('percent', {
      position: 'middle',
      offset: 0,
    });
    interval.init({
      theme: Theme,
    });
    interval.paint();

    // 生成映射数据
    // @ts-ignore
    const beforeMappingData = interval.beforeMappingData;
    // @ts-ignore
    const dataArray = interval.beforeMapping(beforeMappingData);

    let mappingArray = [];
    for (const eachGroup of dataArray) {
      // @ts-ignore
      const mappingData = interval.mapping(eachGroup);
      mappingArray.push(mappingData);
    }
    mappingArray = flatten(mappingArray);

    const gLabels = new IntervalLabel(interval);
    const [data1, data2] = mappingArray;
    it('single label position middle', () => {
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe((data1.x[0] + data1.x[1]) / 2);
      expect(item1.y).toBe(200);
      expect(item1.textAlign).toBe('center');
      expect(item2.x).toBe((data2.x[0] + data2.x[1]) / 2);
      expect(item2.y).toBe(200);
      expect(item2.textAlign).toBe('center');
    });

    it('single label position left', () => {
      interval.label('percent', {
        position: 'left',
        offset: 0,
      });
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe(data1.x[0]);
      expect(item1.y).toBe(200);
      expect(item1.textAlign).toBe('left');
      expect(item2.x).toBe(data2.x[0]);
      expect(item2.y).toBe(200);
      expect(item2.textAlign).toBe('left');
    });

    it('single label position right', () => {
      interval.label('percent', {
        position: 'right',
        offset: 0,
      });
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe(data1.x[1]);
      expect(item1.y).toBe(200);
      expect(item1.textAlign).toBe('left');
      expect(item2.x).toBe(data2.x[1]);
      expect(item2.y).toBe(200);
      expect(item2.textAlign).toBe('left');
    });

    it('single label position top', () => {
      interval.label('percent', {
        position: 'top',
        offset: 0,
      });
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe((data1.x[0] + data1.x[1]) / 2);
      expect(item1.y).toBe(150);
      expect(item1.textAlign).toBe('center');
      expect(item1.textBaseline).toBe('bottom');
      expect(item2.x).toBe((data2.x[0] + data2.x[1]) / 2);
      expect(item2.y).toBe(150);
      expect(item2.textAlign).toBe('center');
      expect(item2.textBaseline).toBe('bottom');
    });

    it('single label position bottom', () => {
      interval.label('percent', {
        position: 'bottom',
        offset: 0,
      });
      const [item1, item2] = gLabels.getLabelItems(mappingArray);
      expect(item1.x).toBe((data1.x[0] + data1.x[1]) / 2);
      expect(item1.y).toBe(250);
      expect(item1.textAlign).toBe('center');
      expect(item1.textBaseline).toBe('bottom');
      expect(item2.x).toBe((data2.x[0] + data2.x[1]) / 2);
      expect(item2.y).toBe(250);
      expect(item2.textAlign).toBe('center');
      expect(item2.textBaseline).toBe('bottom');
    });
  });
});

describe('interval position', () => {
  const getIntervalSize = (coordinate: Coordinate, shapePoints: Point[]) => {
    const transposed = coordinate.isTransposed;
    const point0 = coordinate.convert(shapePoints[0]);
    const point2 = coordinate.convert(shapePoints[2]);
    const top = Math.min(point2.y, point0.y);
    const bottom = Math.max(point2.y, point0.y);
    const right = point2.x;
    const left = point0.x;

    return {
      top,
      bottom,
      right,
      left,
    };
  };

  it('position bottom', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(positiveNegativeData);
    chart.scale('value', {
      nice: true,
    });
    const interval = chart.interval().position('type*value').label('value', {
      position: 'bottom',
    });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(positiveNegativeData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { bottom } = getIntervalSize(chart.getCoordinate(), element.getModel().points as Point[]);
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe(dir > 0 ? 'bottom' : 'top');
      expect(near(labelTextShape.attr('y'), dir > 0 ? bottom - 12 : bottom + 12)).toBe(true);
    });
  });

  it('position middle', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(positiveNegativeData);
    chart.scale('value', {
      nice: true,
    });
    const interval = chart.interval().position('type*value').label('value', {
      position: 'middle',
    });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(positiveNegativeData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { top, bottom } = getIntervalSize(chart.getCoordinate(), element.getModel().points as Point[]);
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('y'), (top + bottom) / 2)).toBe(true);
    });
  });

  it('position top', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(positiveNegativeData);
    chart.scale('value', {
      nice: true,
    });
    const interval = chart.interval().position('type*value').label('value', {
      position: 'top',
    });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(positiveNegativeData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { top } = getIntervalSize(chart.getCoordinate(), element.getModel().points as Point[]);
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe(dir > 0 ? 'bottom' : 'top');
      expect(near(labelTextShape.attr('y'), top + -dir * 12)).toBe(true);
    });
  });

  it('transposed position left', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(positiveNegativeData);
    chart.coordinate().transpose();
    chart.scale('value', {
      nice: true,
    });
    const interval = chart.interval().position('type*value').label('value', {
      position: 'left',
    });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(positiveNegativeData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { left } = getIntervalSize(chart.getCoordinate(), element.getModel().points as Point[]);
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe(dir > 0 ? 'left' : 'right');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('x'), dir > 0 ? left + 12 : left - 12)).toBe(true);
    });
  });

  it('transposed position middle', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(positiveNegativeData);
    chart.coordinate().transpose();
    chart.scale('value', {
      nice: true,
    });
    const interval = chart.interval().position('type*value').label('value', {
      position: 'middle',
    });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(positiveNegativeData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { left, right } = getIntervalSize(chart.getCoordinate(), element.getModel().points as Point[]);
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('x'), (left + right) / 2)).toBe(true);
    });
  });

  it('transposed position right', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(positiveNegativeData);
    chart.coordinate().transpose();
    chart.scale('value', {
      nice: true,
    });
    const interval = chart.interval().position('type*value').label('value', {
      position: 'right',
    });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(positiveNegativeData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { right } = getIntervalSize(chart.getCoordinate(), element.getModel().points as Point[]);
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe(dir > 0 ? 'left' : 'right');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('x'), right + dir * 12)).toBe(true);
    });
  });
});

describe('funnel position', () => {
  const funnelData = [
    { action: '浏览网站', pv: 50000 },
    { action: '放入购物车', pv: 35000 },
    { action: '生成订单', pv: 25000 },
    { action: '支付订单', pv: 15000 },
    { action: '完成交易', pv: 8000 },
  ];
  const getIntervalSize = (coordinate: Coordinate, mappingData) => {
    const transposed = coordinate.isTransposed;
    let top;
    let right;
    let bottom;
    let left;
    const nextPoints = get(mappingData, 'nextPoints');
    const points = get(mappingData, 'points');
    const point0 = coordinate.convert(points[0]);
    const point2 = coordinate.convert(points[2]);
    if (nextPoints) {
      // 非漏斗图底部
      const p0 = coordinate.convert(points[0] as Point);
      const p1 = coordinate.convert(points[1] as Point);
      const nextP0 = coordinate.convert(nextPoints[0] as Point);
      const nextP1 = coordinate.convert(nextPoints[1] as Point);

      // TODO: 使用包围盒的计算方法
      if (transposed) {
        top = Math.min(nextP0.y, p0.y);
        bottom = Math.max(nextP0.y, p0.y);
        right = (p1.x + nextP1.x) / 2;
        left = (p0.x + nextP0.x) / 2;
      } else {
        top = Math.min((p1.y + nextP1.y) / 2, (p0.y + nextP0.y) / 2);
        bottom = Math.max((p1.y + nextP1.y) / 2, (p0.y + nextP0.y) / 2);
        right = nextP1.x;
        left = p0.x;
      }
    } else {
      top = Math.min(point2.y, point0.y);
      bottom = Math.max(point2.y, point0.y);
      right = point2.x;
      left = point0.x;
    }

    return {
      top,
      bottom,
      right,
      left,
    };
  };

  it('position bottom', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(funnelData);
    chart.axis(false);
    chart.coordinate('rect').scale(1, -1);
    chart.tooltip({
      showMarkers: false,
    });
    const interval = chart
      .interval()
      .adjust('symmetric')
      .position('action*pv')
      .shape('funnel')
      .color('action')
      .label('pv', {
        position: 'bottom',
      });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(funnelData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { bottom } = getIntervalSize(chart.getCoordinate(), element.getModel());
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe(dir > 0 ? 'bottom' : 'top');
      expect(near(labelTextShape.attr('y'), bottom + 12)).toBe(true);
    });
  });

  it('position middle', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(funnelData);
    chart.axis(false);
    chart.coordinate('rect').scale(1, -1);
    chart.tooltip({
      showMarkers: false,
    });
    const interval = chart
      .interval()
      .adjust('symmetric')
      .position('action*pv')
      .shape('funnel')
      .color('action')
      .label('pv', {
        position: 'middle',
      });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(funnelData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { top, bottom } = getIntervalSize(chart.getCoordinate(), element.getModel());
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('y'), (top + bottom) / 2)).toBe(true);
    });
  });

  it('position top', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(funnelData);
    chart.axis(false);
    chart.coordinate('rect').scale(1, -1);
    chart.tooltip({
      showMarkers: false,
    });
    const interval = chart
      .interval()
      .adjust('symmetric')
      .position('action*pv')
      .shape('funnel')
      .color('action')
      .label('pv', {
        position: 'top',
      });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(funnelData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { top } = getIntervalSize(chart.getCoordinate(), element.getModel());
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe(dir > 0 ? 'bottom' : 'top');
      expect(near(labelTextShape.attr('y'), top + 12)).toBe(true);
    });
  });

  it('transposed position left', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(funnelData);
    chart.axis(false);
    chart.coordinate('rect').transpose().scale(1, -1);
    chart.tooltip({
      showMarkers: false,
    });
    const interval = chart
      .interval()
      .adjust('symmetric')
      .position('action*pv')
      .shape('funnel')
      .color('action')
      .label('pv', {
        position: 'left',
      });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(funnelData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { left } = getIntervalSize(chart.getCoordinate(), element.getModel());
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe(dir > 0 ? 'left' : 'right');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('x'), dir > 0 ? left + 12 : left - 12)).toBe(true);
    });
  });

  it('transposed position middle', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(funnelData);
    chart.axis(false);
    chart.coordinate('rect').transpose().scale(1, -1);
    chart.tooltip({
      showMarkers: false,
    });
    const interval = chart
      .interval()
      .adjust('symmetric')
      .position('action*pv')
      .shape('funnel')
      .color('action')
      .label('pv', {
        position: 'middle',
      });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(funnelData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { left, right } = getIntervalSize(chart.getCoordinate(), element.getModel());
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe('center');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('x'), (left + right) / 2)).toBe(true);
    });
  });

  it('transposed position right', () => {
    const chart = new Chart({
      container: createDiv(),
      width: 600,
      height: 500,
    });
    chart.data(funnelData);
    chart.axis(false);
    chart.coordinate('rect').transpose().scale(1, -1);
    chart.tooltip({
      showMarkers: false,
    });
    const interval = chart
      .interval()
      .adjust('symmetric')
      .position('action*pv')
      .shape('funnel')
      .color('action')
      .label('pv', {
        position: 'right',
      });

    chart.render();

    const { elements } = interval;

    expect(elements).toHaveLength(funnelData.length);

    elements.forEach((element) => {
      const dir = element.getData().value < 0 ? -1 : 1;
      const { right } = getIntervalSize(chart.getCoordinate(), element.getModel());
      const labelTextShape = element.labelShape[0]?.find((el) => el.get('type') === 'text');
      expect(labelTextShape.attr('textAlign')).toBe(dir > 0 ? 'left' : 'right');
      expect(labelTextShape.attr('textBaseline')).toBe('middle');
      expect(near(labelTextShape.attr('x'), right + dir * 12)).toBe(true);
    });
  });
});


text:
from pybrain.rl.environments.shipsteer.shipsteer import ShipSteeringEnvironment
from pybrain.rl.environments.shipsteer.northwardtask import GoNorthwardTask

redpajama_set_name: RedPajamaGithub


text:
package cluster

import (
	"encoding/binary"
	"fmt"
	"io"
	"math"
	"net"
	"net/url"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/docker/docker/api/types"
	"github.com/docker/docker/api/types/container"
	"github.com/docker/docker/api/types/network"
	"github.com/docker/docker/client"
	"github.com/docker/docker/pkg/jsonmessage"
	"github.com/docker/go-connections/nat"
	isatty "github.com/mattn/go-isatty"
	"github.com/pkg/errors"
	"golang.org/x/net/context"

	"github.com/cockroachdb/cockroach/pkg/util/log"
)

const matchNone = "^$"

// Retrieve the IP address of docker itself.
func dockerIP() net.IP {
	host := os.Getenv("DOCKER_HOST")
	if host == "" {
		host = client.DefaultDockerHost
	}
	u, err := url.Parse(host)
	if err != nil {
		panic(err)
	}
	if u.Scheme == "unix" {
		return net.IPv4(127, 0, 0, 1)
	}
	h, _, err := net.SplitHostPort(u.Host)
	if err != nil {
		panic(err)
	}
	return net.ParseIP(h)
}

// Container provides the programmatic interface for a single docker
// container.
type Container struct {
	id      string
	name    string
	cluster *LocalCluster
}

// Name returns the container's name.
func (c Container) Name() string {
	return c.name
}

func hasImage(ctx context.Context, l *LocalCluster, ref string) bool {
	name := strings.Split(ref, ":")[0]
	images, err := l.client.ImageList(ctx, types.ImageListOptions{MatchName: name})
	if err != nil {
		log.Fatal(ctx, err)
	}
	for _, image := range images {
		for _, repoTag := range image.RepoTags {
			// The Image.RepoTags field contains strings of the form <repo>:<tag>.
			if ref == repoTag {
				return true
			}
		}
	}
	for _, image := range images {
		for _, tag := range image.RepoTags {
			log.Infof(ctx, "ImageList %s %s", tag, image.ID)
		}
	}
	return false
}

func pullImage(
	ctx context.Context, l *LocalCluster, ref string, options types.ImagePullOptions,
) error {
	// HACK: on CircleCI, docker pulls the image on the first access from an
	// acceptance test even though that image is already present. So we first
	// check to see if our image is present in order to avoid this slowness.
	if hasImage(ctx, l, ref) {
		log.Infof(ctx, "ImagePull %s already exists", ref)
		return nil
	}

	log.Infof(ctx, "ImagePull %s starting", ref)
	defer log.Infof(ctx, "ImagePull %s complete", ref)

	rc, err := l.client.ImagePull(ctx, ref, options)
	if err != nil {
		return err
	}
	defer rc.Close()
	out := os.Stderr
	outFd := out.Fd()
	isTerminal := isatty.IsTerminal(outFd)

	return jsonmessage.DisplayJSONMessagesStream(rc, out, outFd, isTerminal, nil)
}

// createContainer creates a new container using the specified
// options. Per the docker API, the created container is not running
// and must be started explicitly. Note that the passed-in hostConfig
// will be augmented with the necessary settings to use the network
// defined by l.createNetwork().
func createContainer(
	ctx context.Context,
	l *LocalCluster,
	containerConfig container.Config,
	hostConfig container.HostConfig,
	containerName string,
) (*Container, error) {
	hostConfig.NetworkMode = container.NetworkMode(l.networkID)
	// Disable DNS search under the host machine's domain. This can
	// catch upstream wildcard DNS matching and result in odd behavior.
	hostConfig.DNSSearch = []string{"."}
	resp, err := l.client.ContainerCreate(ctx, &containerConfig, &hostConfig, nil, containerName)
	if err != nil {
		return nil, err
	}
	return &Container{
		id:      resp.ID,
		name:    containerName,
		cluster: l,
	}, nil
}

func maybePanic(err error) {
	if err != nil {
		panic(err)
	}
}

// Remove removes the container from docker. It is an error to remove a running
// container.
func (c *Container) Remove(ctx context.Context) error {
	return c.cluster.client.ContainerRemove(ctx, c.id, types.ContainerRemoveOptions{
		RemoveVolumes: true,
		Force:         true,
	})
}

// Kill stops a running container, without removing it.
func (c *Container) Kill(ctx context.Context) error {
	// Paused containers cannot be killed. Attempt to unpause it first
	// (which might fail) before killing.
	_ = c.Unpause(ctx)
	if err := c.cluster.client.ContainerKill(ctx, c.id, "9"); err != nil && !strings.Contains(err.Error(), "is not running") {
		return err
	}
	c.cluster.expectEvent(c, eventDie)
	return nil
}

// Start starts a non-running container.
//
// TODO(pmattis): Generalize the setting of parameters here.
func (c *Container) Start(ctx context.Context) error {
	return c.cluster.client.ContainerStart(ctx, c.id, types.ContainerStartOptions{})
}

// Pause pauses a running container.
func (c *Container) Pause(ctx context.Context) error {
	return c.cluster.client.ContainerPause(ctx, c.id)
}

// TODO(pmattis): Container.Pause is neither used or tested. Silence unused
// warning.
var _ = (*Container).Pause

// Unpause resumes a paused container.
func (c *Container) Unpause(ctx context.Context) error {
	return c.cluster.client.ContainerUnpause(ctx, c.id)
}

// Restart restarts a running container.
// Container will be killed after 'timeout' seconds if it fails to stop.
func (c *Container) Restart(ctx context.Context, timeout *time.Duration) error {
	var exp []string
	if ci, err := c.Inspect(ctx); err != nil {
		return err
	} else if ci.State.Running {
		exp = append(exp, eventDie)
	}
	if err := c.cluster.client.ContainerRestart(ctx, c.id, timeout); err != nil {
		return err
	}
	c.cluster.expectEvent(c, append(exp, eventRestart)...)
	return nil
}

// Stop a running container.
func (c *Container) Stop(ctx context.Context, timeout *time.Duration) error {
	if err := c.cluster.client.ContainerStop(ctx, c.id, timeout); err != nil {
		return err
	}
	c.cluster.expectEvent(c, eventDie)
	return nil
}

// TODO(pmattis): Container.Stop is neither used or tested. Silence unused
// warning.
var _ = (*Container).Stop

// Wait waits for a running container to exit.
func (c *Container) Wait(ctx context.Context) error {
	exitCode, err := c.cluster.client.ContainerWait(ctx, c.id)
	if err == nil && exitCode != 0 {
		err = errors.Errorf("non-zero exit code: %d", exitCode)
	}
	if err != nil {
		if err := c.Logs(ctx, os.Stderr); err != nil {
			log.Warning(ctx, err)
		}
	}
	return err
}

// Logs outputs the containers logs to the given io.Writer.
func (c *Container) Logs(ctx context.Context, w io.Writer) error {
	rc, err := c.cluster.client.ContainerLogs(ctx, c.id, types.ContainerLogsOptions{
		ShowStdout: true,
		ShowStderr: true,
	})
	if err != nil {
		return err
	}
	defer rc.Close()
	// The docker log output is not quite plaintext: each line has a
	// prefix consisting of one byte file descriptor (stdout vs stderr),
	// three bytes padding, four byte length. We could use this to
	// disentangle stdout and stderr if we wanted to output them into
	// separate streams, but we don't really care.
	for {
		var header uint64
		if err := binary.Read(rc, binary.BigEndian, &header); err == io.EOF {
			break
		} else if err != nil {
			return err
		}
		size := header & math.MaxUint32
		if _, err := io.CopyN(w, rc, int64(size)); err != nil {
			return err
		}
	}
	return nil
}

// Inspect retrieves detailed info about a container.
func (c *Container) Inspect(ctx context.Context) (types.ContainerJSON, error) {
	return c.cluster.client.ContainerInspect(ctx, c.id)
}

// Addr returns the TCP address to connect to.
func (c *Container) Addr(ctx context.Context, port nat.Port) *net.TCPAddr {
	containerInfo, err := c.Inspect(ctx)
	if err != nil {
		log.Error(ctx, err)
		return nil
	}
	bindings, ok := containerInfo.NetworkSettings.Ports[port]
	if !ok || len(bindings) == 0 {
		return nil
	}
	portNum, err := strconv.Atoi(bindings[0].HostPort)
	if err != nil {
		log.Error(ctx, err)
		return nil
	}
	return &net.TCPAddr{
		IP:   dockerIP(),
		Port: portNum,
	}
}

// resilientDockerClient handles certain recoverable Docker usage errors.
//
// For example, `ContainerCreate` will fail if a container with the requested
// name already exists. resilientDockerClient will catch this, delete the
// existing container and try again.
type resilientDockerClient struct {
	client.APIClient
}

func (cli resilientDockerClient) ContainerCreate(
	ctx context.Context,
	config *container.Config,
	hostConfig *container.HostConfig,
	networkingConfig *network.NetworkingConfig,
	containerName string,
) (container.ContainerCreateCreatedBody, error) {
	response, err := cli.APIClient.ContainerCreate(ctx, config, hostConfig, networkingConfig, containerName)
	if err != nil && strings.Contains(err.Error(), "already in use") {
		log.Infof(ctx, "unable to create container %s: %v", containerName, err)
		containers, cerr := cli.ContainerList(ctx, types.ContainerListOptions{
			All:   true,
			Limit: -1, // no limit, see docker/docker/client/container_list.go
		})
		if cerr != nil {
			log.Infof(ctx, "unable to list containers: %v", cerr)
			return container.ContainerCreateCreatedBody{}, err
		}
		for _, c := range containers {
			for _, n := range c.Names {
				// The container names begin with a "/".
				n = strings.TrimPrefix(n, "/")
				if n != containerName {
					continue
				}
				log.Infof(ctx, "trying to remove %s", c.ID)
				options := types.ContainerRemoveOptions{
					RemoveVolumes: true,
					Force:         true,
				}
				if rerr := cli.ContainerRemove(ctx, c.ID, options); rerr != nil {
					log.Infof(ctx, "unable to remove container: %v", rerr)
					return container.ContainerCreateCreatedBody{}, err
				}
				return cli.ContainerCreate(ctx, config, hostConfig, networkingConfig, containerName)
			}
		}
		log.Warningf(ctx, "error indicated existing container %s, "+
			"but none found:\nerror: %s\ncontainers: %+v",
			containerName, err, containers)
		// We likely raced with a previous (late) removal of the container.
		// Return a timeout so a higher level can retry and hopefully
		// succeed (or get stuck in an infinite loop, at which point at
		// least we'll have gathered an additional bit of information).
		return response, context.DeadlineExceeded
	}
	return response, err
}

func (cli resilientDockerClient) ContainerRemove(
	ctx context.Context, container string, options types.ContainerRemoveOptions,
) error {
	return cli.APIClient.ContainerRemove(ctx, container, options)
}

// retryingDockerClient proxies the Docker client api and retries problematic
// calls.
//
// Sometimes http requests to the Docker server, on circleci in particular, will
// hang indefinitely and non-deterministically. This leads to flaky tests. To
// avoid this, we wrap some of them in a timeout and retry loop.
type retryingDockerClient struct {
	// Implements client.APIClient, but we use that it's resilient.
	resilientDockerClient
	attempts int
	timeout  time.Duration
}

// retry invokes the supplied function with time-limited contexts as long as
// returned error is a context timeout. When needing more than one attempt to
// get a (non-timeout) result, any errors matching retryErrorsRE are swallowed.
//
// For example, retrying a container removal could fail on the second attempt
// if the first request timed out (but still executed).
func retry(
	ctx context.Context,
	attempts int,
	timeout time.Duration,
	name string,
	retryErrorsRE string,
	f func(ctx context.Context) error,
) error {
	for i := 0; i < attempts; i++ {
		timeoutCtx, _ := context.WithTimeout(ctx, timeout)
		err := f(timeoutCtx)
		if err != nil {
			if err == context.DeadlineExceeded {
				continue
			} else if i > 0 && retryErrorsRE != matchNone {
				if regexp.MustCompile(retryErrorsRE).MatchString(err.Error()) {
					log.Infof(ctx, "%s: swallowing expected error after retry: %v",
						name, err)
					return nil
				}
			}
		}
		return err
	}
	return fmt.Errorf("%s: exceeded %d tries with a %s timeout", name, attempts, timeout)
}

func (cli retryingDockerClient) ContainerCreate(
	ctx context.Context,
	config *container.Config,
	hostConfig *container.HostConfig,
	networkingConfig *network.NetworkingConfig,
	containerName string,
) (container.ContainerCreateCreatedBody, error) {
	var ret container.ContainerCreateCreatedBody
	err := retry(ctx, cli.attempts, cli.timeout,
		"ContainerCreate", matchNone,
		func(timeoutCtx context.Context) error {
			var err error
			ret, err = cli.resilientDockerClient.ContainerCreate(timeoutCtx, config, hostConfig, networkingConfig, containerName)
			_ = ret // silence incorrect unused warning
			return err
		})
	return ret, err
}

func (cli retryingDockerClient) ContainerStart(
	ctx context.Context, container string, options types.ContainerStartOptions,
) error {
	return retry(ctx, cli.attempts, cli.timeout, "ContainerStart", matchNone,
		func(timeoutCtx context.Context) error {
			return cli.resilientDockerClient.ContainerStart(timeoutCtx, container, options)
		})
}

func (cli retryingDockerClient) ContainerRemove(
	ctx context.Context, container string, options types.ContainerRemoveOptions,
) error {
	return retry(ctx, cli.attempts, cli.timeout, "ContainerRemove", "No such container",
		func(timeoutCtx context.Context) error {
			return cli.resilientDockerClient.ContainerRemove(timeoutCtx, container, options)
		})
}

func (cli retryingDockerClient) ContainerKill(ctx context.Context, container, signal string) error {
	return retry(ctx, cli.attempts, cli.timeout, "ContainerKill",
		"Container .* is not running",
		func(timeoutCtx context.Context) error {
			return cli.resilientDockerClient.ContainerKill(timeoutCtx, container, signal)
		})
}

func (cli retryingDockerClient) ContainerWait(ctx context.Context, container string) (int64, error) {
	var ret int64
	return ret, retry(ctx, cli.attempts, cli.timeout, "ContainerWait", matchNone,
		func(timeoutCtx context.Context) error {
			var err error
			ret, err = cli.resilientDockerClient.ContainerWait(timeoutCtx, container)
			_ = ret // silence incorrect unused warning
			return err
		})
}

func (cli retryingDockerClient) ImageList(
	ctx context.Context, options types.ImageListOptions,
) ([]types.ImageSummary, error) {
	var ret []types.ImageSummary
	return ret, retry(ctx, cli.attempts, cli.timeout, "ImageList", matchNone,
		func(timeoutCtx context.Context) error {
			var err error
			ret, err = cli.resilientDockerClient.ImageList(timeoutCtx, options)
			_ = ret // silence incorrect unused warning
			return err
		})
}

func (cli retryingDockerClient) ImagePull(
	ctx context.Context, ref string, options types.ImagePullOptions,
) (io.ReadCloser, error) {
	// Image pulling is potentially slow. Make sure the timeout is sufficient.
	timeout := cli.timeout
	if minTimeout := 2 * time.Minute; timeout < minTimeout {
		timeout = minTimeout
	}
	var ret io.ReadCloser
	return ret, retry(ctx, cli.attempts, timeout, "ImagePull", matchNone,
		func(timeoutCtx context.Context) error {
			var err error
			ret, err = cli.resilientDockerClient.ImagePull(timeoutCtx, ref, options)
			_ = ret // silence incorrect unused warning
			return err
		})
}


text:
package common

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"syscall"
	"time"

	"github.com/gravitational/teleport/lib/client"
	"github.com/gravitational/teleport/lib/defaults"
	"github.com/gravitational/teleport/lib/services"
	"github.com/gravitational/teleport/lib/session"
	"github.com/gravitational/teleport/lib/teleagent"
	"github.com/gravitational/teleport/lib/utils"
	"github.com/gravitational/trace"

	"github.com/Sirupsen/logrus"
	"github.com/buger/goterm"
	gops "github.com/google/gops/agent"
)

// CLIConf stores command line arguments and flags:
type CLIConf struct {
	// UserHost contains "[login]@hostname" argument to SSH command
	UserHost string
	// Commands to execute on a remote host
	RemoteCommand []string
	// Username is the Teleport user's username (to login into proxies)
	Username string
	// Proxy keeps the hostname:port of the SSH proxy to use
	Proxy string
	// TTL defines how long a session must be active (in minutes)
	MinsToLive int32
	// SSH Port on a remote SSH host
	NodePort int16
	// Login on a remote SSH host
	NodeLogin string
	// InsecureSkipVerify bypasses verification of HTTPS certificate when talking to web proxy
	InsecureSkipVerify bool
	// IsUnderTest is set to true for unit testing
	IsUnderTest bool
	// AgentSocketAddr is address for agent listeing socket
	AgentSocketAddr utils.NetAddrVal
	// Remote SSH session to join
	SessionID string
	// Src:dest parameter for SCP
	CopySpec []string
	// -r flag for scp
	RecursiveCopy bool
	// -L flag for ssh. Local port forwarding like 'ssh -L 80:remote.host:80 -L 443:remote.host:443'
	LocalForwardPorts []string
	// --local flag for ssh
	LocalExec bool
	// SiteName specifies remote site go login to
	SiteName string
	// Interactive, when set to true, launches remote command with the terminal attached
	Interactive bool
	// Quiet mode, -q command (disables progress printing)
	Quiet bool
	// Namespace is used to select cluster namespace
	Namespace string
	// NoCache is used to turn off client cache for nodes discovery
	NoCache bool
	// LoadSystemAgentOnly when set to true will cause tsh agent to load keys into the system agent and
	// then exit. This is useful when calling tsh agent from a script (for example ~/.bash_profile)
	// to load keys into your system agent.
	LoadSystemAgentOnly bool
	// BenchThreads is amount of concurrent threads to run
	BenchThreads int
	// BenchDuration is a duration for the benchmark
	BenchDuration time.Duration
	// BenchRate is a requests per second rate to mantain
	BenchRate int
	// Context is a context to control execution
	Context context.Context
	// Gops starts gops agent on a specified address
	// if not specified, gops won't start
	Gops bool
	// GopsAddr specifies to gops addr to listen on
	GopsAddr string
}

// Run executes TSH client. same as main() but easier to test
func Run(args []string, underTest bool) {
	var (
		cf CLIConf
	)
	cf.IsUnderTest = underTest
	utils.InitLogger(utils.LoggingForCLI, logrus.WarnLevel)

	// configure CLI argument parser:
	app := utils.InitCLIParser("tsh", "TSH: Teleport SSH client").Interspersed(false)
	app.Flag("login", "Remote host login").Short('l').Envar("TELEPORT_LOGIN").StringVar(&cf.NodeLogin)
	localUser, _ := client.Username()
	app.Flag("nocache", "do not cache cluster discovery locally").Hidden().BoolVar(&cf.NoCache)
	app.Flag("user", fmt.Sprintf("SSH proxy user [%s]", localUser)).Envar("TELEPORT_USER").StringVar(&cf.Username)
	app.Flag("cluster", "Specify the cluster to connect").Envar("TELEPORT_SITE").StringVar(&cf.SiteName)
	app.Flag("proxy", "SSH proxy host or IP address").Envar("TELEPORT_PROXY").StringVar(&cf.Proxy)
	app.Flag("ttl", "Minutes to live for a SSH session").Int32Var(&cf.MinsToLive)
	app.Flag("insecure", "Do not verify server's certificate and host name. Use only in test environments").Default("false").BoolVar(&cf.InsecureSkipVerify)
	app.Flag("namespace", "Namespace of the cluster").Default(defaults.Namespace).StringVar(&cf.Namespace)
	app.Flag("gops", "Start gops endpoint on a given address").Hidden().BoolVar(&cf.Gops)
	app.Flag("gops-addr", "Specify gops addr to listen on").Hidden().StringVar(&cf.GopsAddr)
	debugMode := app.Flag("debug", "Verbose logging to stdout").Short('d').Bool()
	app.HelpFlag.Short('h')
	ver := app.Command("version", "Print the version")
	// ssh
	ssh := app.Command("ssh", "Run shell or execute a command on a remote SSH node")
	ssh.Arg("[user@]host", "Remote hostname and the login to use").Required().StringVar(&cf.UserHost)
	ssh.Arg("command", "Command to execute on a remote host").StringsVar(&cf.RemoteCommand)
	ssh.Flag("port", "SSH port on a remote host").Short('p').Int16Var(&cf.NodePort)
	ssh.Flag("forward", "Forward localhost connections to remote server").Short('L').StringsVar(&cf.LocalForwardPorts)
	ssh.Flag("local", "Execute command on localhost after connecting to SSH node").Default("false").BoolVar(&cf.LocalExec)
	ssh.Flag("", "Allocate TTY").Short('t').BoolVar(&cf.Interactive)
	// join
	join := app.Command("join", "Join the active SSH session")
	join.Arg("session-id", "ID of the session to join").Required().StringVar(&cf.SessionID)
	// play
	play := app.Command("play", "Replay the recorded SSH session")
	play.Arg("session-id", "ID of the session to play").Required().StringVar(&cf.SessionID)
	// scp
	scp := app.Command("scp", "Secure file copy")
	scp.Arg("from, to", "Source and destination to copy").Required().StringsVar(&cf.CopySpec)
	scp.Flag("recursive", "Recursive copy of subdirectories").Short('r').BoolVar(&cf.RecursiveCopy)
	scp.Flag("port", "Port to connect to on the remote host").Short('P').Int16Var(&cf.NodePort)
	scp.Flag("quiet", "Quiet mode").Short('q').BoolVar(&cf.Quiet)
	// ls
	ls := app.Command("ls", "List remote SSH nodes")
	ls.Arg("labels", "List of labels to filter node list").StringVar(&cf.UserHost)
	// clusters
	clusters := app.Command("clusters", "List available Teleport clusters")
	clusters.Flag("quiet", "Quiet mode").Short('q').BoolVar(&cf.Quiet)
	// agent (SSH agent listening on unix socket)
	agent := app.Command("agent", "Start SSH agent on unix socket")
	agent.Flag("socket", "SSH agent listening socket address, e.g. unix:///tmp/teleport.agent.sock").SetValue(&cf.AgentSocketAddr)
	agent.Flag("load", "When set to true, the tsh agent will load the external system agent and then exit.").BoolVar(&cf.LoadSystemAgentOnly)

	// login logs in with remote proxy and obtains a "session certificate" which gets
	// stored in ~/.tsh directory
	login := app.Command("login", "Log in to the cluster and store the session certificate to avoid login prompts")

	// logout deletes obtained session certificates in ~/.tsh
	logout := app.Command("logout", "Delete a cluster certificate")

	// bench
	bench := app.Command("bench", "Run shell or execute a command on a remote SSH node").Hidden()
	bench.Arg("[user@]host", "Remote hostname and the login to use").Required().StringVar(&cf.UserHost)
	bench.Arg("command", "Command to execute on a remote host").Required().StringsVar(&cf.RemoteCommand)
	bench.Flag("port", "SSH port on a remote host").Short('p').Int16Var(&cf.NodePort)
	bench.Flag("threads", "Concurrent threads to run").Default("10").IntVar(&cf.BenchThreads)
	bench.Flag("duration", "Test duration").Default("1s").DurationVar(&cf.BenchDuration)
	bench.Flag("rate", "Requests per second rate").Default("10").IntVar(&cf.BenchRate)

	// parse CLI commands+flags:
	command, err := app.Parse(args)
	if err != nil {
		utils.FatalError(err)
	}

	// apply -d flag:
	if *debugMode {
		utils.InitLogger(utils.LoggingForCLI, logrus.DebugLevel)
	}

	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		exitSignals := make(chan os.Signal, 1)
		signal.Notify(exitSignals, syscall.SIGTERM, syscall.SIGINT)

		select {
		case sig := <-exitSignals:
			logrus.Debugf("signal: %v", sig)
			cancel()
		}
	}()
	cf.Context = ctx

	if cf.Gops {
		logrus.Debugf("starting gops agent")
		err = gops.Listen(&gops.Options{Addr: cf.GopsAddr})
		if err != nil {
			logrus.Warningf("failed to start gops agent %v", err)
		}
	}

	switch command {
	case ver.FullCommand():
		onVersion()
	case ssh.FullCommand():
		onSSH(&cf)
	case bench.FullCommand():
		onBenchmark(&cf)
	case join.FullCommand():
		onJoin(&cf)
	case scp.FullCommand():
		onSCP(&cf)
	case play.FullCommand():
		onPlay(&cf)
	case ls.FullCommand():
		onListNodes(&cf)
	case clusters.FullCommand():
		onListSites(&cf)
	case agent.FullCommand():
		onAgentStart(&cf)
	case login.FullCommand():
		refuseArgs(login.FullCommand(), args)
		onLogin(&cf)
	case logout.FullCommand():
		refuseArgs(logout.FullCommand(), args)
		onLogout(&cf)
	}
}

// onPlay replays a session with a given ID
func onPlay(cf *CLIConf) {
	tc, err := makeClient(cf, true)
	if err != nil {
		utils.FatalError(err)
	}
	if err := tc.Play(context.TODO(), cf.Namespace, cf.SessionID); err != nil {
		utils.FatalError(err)
	}
}

// onLogin logs in with remote proxy and gets signed certificates
func onLogin(cf *CLIConf) {
	tc, err := makeClient(cf, true)
	if err != nil {
		utils.FatalError(err)
	}
	if _, err := tc.Login(); err != nil {
		utils.FatalError(err)
	}
	tc.SaveProfile("")

	if tc.SiteName != "" {
		fmt.Printf("\nYou are now logged into %s as %s\n", tc.SiteName, tc.Username)
	} else {
		fmt.Printf("\nYou are now logged in\n")
	}
}

// onLogout deletes a "session certificate" from ~/.tsh for a given proxy
func onLogout(cf *CLIConf) {
	client.UnlinkCurrentProfile()

	// logout from all
	if cf.Proxy == "" {
		client.LogoutFromEverywhere(cf.Username)
	} else {
		tc, err := makeClient(cf, true)
		if err != nil {
			utils.FatalError(err)
		}
		if err = tc.Logout(); err != nil {
			if trace.IsNotFound(err) {
				utils.FatalError(trace.Errorf("you are not logged into proxy '%s'", cf.Proxy))
			}
			utils.FatalError(err)
		}
		fmt.Printf("%s has logged out of %s\n", tc.Username, cf.SiteName)
	}
}

// onListNodes executes 'tsh ls' command
func onListNodes(cf *CLIConf) {
	tc, err := makeClient(cf, true)
	if err != nil {
		utils.FatalError(err)
	}
	servers, err := tc.ListNodes(context.TODO())
	if err != nil {
		utils.FatalError(err)
	}
	nodesView := func(nodes []services.Server) string {
		t := goterm.NewTable(0, 10, 5, ' ', 0)
		printHeader(t, []string{"Node Name", "Node ID", "Address", "Labels"})
		if len(nodes) == 0 {
			return t.String()
		}
		for _, n := range nodes {
			fmt.Fprintf(t, "%v\t%v\t%v\t%v\n", n.GetHostname(), n.GetName(), n.GetAddr(), n.LabelsString())
		}
		return t.String()
	}
	fmt.Printf(nodesView(servers))
}

// onListSites executes 'tsh sites' command
func onListSites(cf *CLIConf) {
	tc, err := makeClient(cf, true)
	if err != nil {
		utils.FatalError(err)
	}
	proxyClient, err := tc.ConnectToProxy()
	if err != nil {
		utils.FatalError(err)
	}
	defer proxyClient.Close()

	sites, err := proxyClient.GetSites()
	if err != nil {
		utils.FatalError(err)
	}
	sitesView := func() string {
		t := goterm.NewTable(0, 10, 5, ' ', 0)
		printHeader(t, []string{"Cluster Name", "Status"})
		if len(sites) == 0 {
			return t.String()
		}
		for _, site := range sites {
			fmt.Fprintf(t, "%v\t%v\n", site.Name, site.Status)
		}
		return t.String()
	}
	quietSitesView := func() string {
		names := make([]string, 0)
		for _, site := range sites {
			names = append(names, site.Name)
		}
		return strings.Join(names, "\n")
	}
	if cf.Quiet {
		sitesView = quietSitesView
	}
	fmt.Printf(sitesView())
}

// onSSH executes 'tsh ssh' command
func onSSH(cf *CLIConf) {
	tc, err := makeClient(cf, false)
	if err != nil {
		utils.FatalError(err)
	}

	tc.Stdin = os.Stdin
	if err = tc.SSH(context.TODO(), cf.RemoteCommand, cf.LocalExec); err != nil {
		// exit with the same exit status as the failed command:
		if tc.ExitStatus != 0 {
			fmt.Fprintln(os.Stderr, utils.UserMessageFromError(err))
			os.Exit(tc.ExitStatus)
		} else {
			utils.FatalError(err)
		}
	}
}

// onBenchmark executes benchmark
func onBenchmark(cf *CLIConf) {
	tc, err := makeClient(cf, false)
	if err != nil {
		utils.FatalError(err)
	}
	result, err := tc.Benchmark(cf.Context, client.Benchmark{
		Command:  cf.RemoteCommand,
		Threads:  cf.BenchThreads,
		Duration: cf.BenchDuration,
		Rate:     cf.BenchRate,
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, utils.UserMessageFromError(err))
		os.Exit(255)
	}
	fmt.Printf("\n")
	fmt.Printf("* Requests originated: %v\n", result.RequestsOriginated)
	fmt.Printf("* Requests failed: %v\n", result.RequestsFailed)
	if result.LastError != nil {
		fmt.Printf("* Last error: %v\n", result.LastError)
	}
	fmt.Printf("\nHistogram\n\n")
	t := goterm.NewTable(0, 10, 5, ' ', 0)
	printHeader(t, []string{"Percentile", "Duration"})
	for _, quantile := range []float64{25, 50, 75, 90, 95, 99, 100} {
		fmt.Fprintf(t, "%v\t%v ms\n", quantile, result.Histogram.ValueAtQuantile(quantile))
	}

	fmt.Fprintf(os.Stdout, t.String())
	fmt.Printf("\n")
}

// onJoin executes 'ssh join' command
func onJoin(cf *CLIConf) {
	tc, err := makeClient(cf, true)
	if err != nil {
		utils.FatalError(err)
	}
	sid, err := session.ParseID(cf.SessionID)
	if err != nil {
		utils.FatalError(fmt.Errorf("'%v' is not a valid session ID (must be GUID)", cf.SessionID))
	}
	if err = tc.Join(context.TODO(), cf.Namespace, *sid, nil); err != nil {
		utils.FatalError(err)
	}
}

// onSCP executes 'tsh scp' command
func onSCP(cf *CLIConf) {
	tc, err := makeClient(cf, false)
	if err != nil {
		utils.FatalError(err)
	}
	if err := tc.SCP(context.TODO(), cf.CopySpec, int(cf.NodePort), cf.RecursiveCopy, cf.Quiet); err != nil {
		// exit with the same exit status as the failed command:
		if tc.ExitStatus != 0 {
			os.Exit(tc.ExitStatus)
		} else {
			utils.FatalError(err)
		}
	}
}

// onAgentStart start ssh agent on a socket
func onAgentStart(cf *CLIConf) {
	// create a client, a side effect of this is that it creates a client.LocalAgent.
	// creation of a client.LocalAgent has a side effect of loading all keys into
	// client.LocalAgent and the system agent.
	tc, err := makeClient(cf, true)
	if err != nil {
		utils.FatalError(err)
	}

	// check if we are only loading keys and exiting. this is useful
	// when calling tsh agent from a script like ~/.bash_profile.
	if cf.LoadSystemAgentOnly {
		return
	}

	// we're starting tsh agent, build the socket address
	socketAddr := utils.NetAddr(cf.AgentSocketAddr)
	pid := os.Getpid()
	if socketAddr.IsEmpty() {
		socketAddr = utils.NetAddr{
			AddrNetwork: "unix",
			Addr:        filepath.Join(os.TempDir(), fmt.Sprintf("teleport-%d.socket", pid)),
		}
	}

	// This makes teleport agent behave exactly like ssh-agent command,
	// the output and behavior matches the openssh behavior,
	// so users can do 'eval $(tsh agent --proxy=<addr>&)
	fmt.Printf(`# Keep this agent process running in the background.
# Set these environment variables:
export SSH_AUTH_SOCK=%v;
export SSH_AGENT_PID=%v

# you can redirect this output into a file and call 'source' on it
`, socketAddr.Addr, pid)

	// create a new teleport agent and start listening
	agentServer := teleagent.AgentServer{
		Agent: tc.LocalAgent(),
	}
	if err := agentServer.ListenAndServe(socketAddr); err != nil {
		utils.FatalError(err)
	}
}

// makeClient takes the command-line configuration and constructs & returns
// a fully configured TeleportClient object
func makeClient(cf *CLIConf, useProfileLogin bool) (tc *client.TeleportClient, err error) {
	// apply defaults
	if cf.MinsToLive == 0 {
		cf.MinsToLive = int32(defaults.CertDuration / time.Minute)
	}

	// split login & host
	hostLogin := cf.NodeLogin
	var labels map[string]string
	if cf.UserHost != "" {
		parts := strings.Split(cf.UserHost, "@")
		if len(parts) > 1 {
			hostLogin = parts[0]
			cf.UserHost = parts[1]
		}
		// see if remote host is specified as a set of labels
		if strings.Contains(cf.UserHost, "=") {
			labels, err = client.ParseLabelSpec(cf.UserHost)
			if err != nil {
				return nil, err
			}
		}
	}
	fPorts, err := client.ParsePortForwardSpec(cf.LocalForwardPorts)
	if err != nil {
		return nil, err
	}

	// 1: start with the defaults
	c := client.MakeDefaultConfig()

	// 2: override with `./tsh` profiles (but only if no proxy is given via the CLI)
	if cf.Proxy == "" {
		if err = c.LoadProfile(""); err != nil {
			fmt.Printf("WARNING: Failed loading tsh profile.\n%v\n", err)
		}
	}

	// 3: override with the CLI flags
	if cf.Namespace != "" {
		c.Namespace = cf.Namespace
	}
	if cf.Username != "" {
		c.Username = cf.Username
	}
	if cf.Proxy != "" {
		c.ProxyHostPort = cf.Proxy
	}
	if len(fPorts) > 0 {
		c.LocalForwardPorts = fPorts
	}
	if cf.SiteName != "" {
		c.SiteName = cf.SiteName
	}
	// if host logins stored in profiles must be ignored...
	if !useProfileLogin {
		c.HostLogin = ""
	}
	if hostLogin != "" {
		c.HostLogin = hostLogin
	}
	c.Host = cf.UserHost
	c.HostPort = int(cf.NodePort)
	c.Labels = labels
	c.KeyTTL = time.Minute * time.Duration(cf.MinsToLive)
	c.InsecureSkipVerify = cf.InsecureSkipVerify
	c.Interactive = cf.Interactive
	if !cf.NoCache {
		c.CachePolicy = &client.CachePolicy{}
	}
	return client.NewClient(c)
}

func onVersion() {
	utils.PrintVersion()
}

func printHeader(t *goterm.Table, cols []string) {
	dots := make([]string, len(cols))
	for i := range dots {
		dots[i] = strings.Repeat("-", len(cols[i]))
	}
	fmt.Fprint(t, strings.Join(cols, "\t")+"\n")
	fmt.Fprint(t, strings.Join(dots, "\t")+"\n")
}

// refuseArgs helper makes sure that 'args' (list of CLI arguments)
// does not contain anything other than command
func refuseArgs(command string, args []string) {
	if len(args) == 0 {
		return
	}
	lastArg := args[len(args)-1]
	if lastArg != command {
		utils.FatalError(trace.BadParameter("%s does not expect arguments", command))
	}
}


text:
(function() {

  $('html').on('keypress click input keyup', function(){

    var length = $('div.typeable').text().length;
    $('.char-count').text(length);
    if (length === 365) {
      $('.char-count').css('color', '#5becf5');
      $('.char-count').css('font-weight', 'bold');
    } else if (length >= 365) {
      $('.char-count').css('color', 'red');
      $('.char-count').css('font-weight', 'normal');
    } else {
      $('.char-count').css('color', 'grey');
      $('.char-count').css('font-weight', 'normal');
    }

  });

  function charactersleft(tweet) {
    var url, i, lenUrlArr;
    var virtualTweet = tweet;
    var filler = "01234567890123456789";
    var extractedUrls = twttr.txt.extractUrlsWithIndices(tweet);
    var remaining = 140;
    lenUrlArr = extractedUrls.length;
    if ( lenUrlArr > 0 ) {
        for (var i = 0; i < lenUrlArr; i++) {
            url = extractedUrls[i].url;
            virtualTweet = virtualTweet.replace(url,filler);
        }
    }
    remaining = remaining - virtualTweet.length;
    return remaining;
  }

  $('.emoji-wysiwyg-editor').on('click', function(){
    console.log("enter");
  });

  $('.submit-button').on('click', function() {
    console.log($('.char-count').text());
  });

  var timeStarted = false;

})();


text:
<!-- demographics.html -->
<div>
    <label for="characterName">Name: </label>
    <input type="text" ng-model="sheet.character.demographics.name"></input>
    {{sheet.character.demographics.name}}
</div>


text:
from ezmailer.utils import *

import ezmailer.cmp_syntax
from ezmailer.api import Renderer, TreeComponent, TextComponent, TrancludeMarker, Transclusion
from ezmailer.api.components import *
from treeprinter import TreePrinter
from lxml import etree

rd = Renderer()
text_parent = "<parent><head>{}</head><foot>{}</foot></parent>".format(TrancludeMarker("head"), TrancludeMarker("foot"))
text_child = "<child>{}</child>".format(TrancludeMarker())
text_grand_child = "<grandchild></grandchild>"

tp = TreePrinter("getchildren", "tag")

# cp = Component(text_parent)
# cp_child = Component(text_child)
# cp_grand_child = Component(text_grand_child)
# res = cp_child.transclude(__root__= cp_grand_child)
# tp.pprint(cp_child.tree)

def get_tree_children(obj):
    if isinstance(obj, Transclusion):
        return list(obj.children.items())
    elif isinstance(obj, tuple):
        return obj[1]

def get_tree_tag(obj):
    if isinstance(obj, Transclusion):
        return str(obj.component)
    elif isinstance(obj, tuple):
        return obj[0]

tpt = TreePrinter(get_tree_children, get_tree_tag)

# tree_comp = (
#     TreeComponent.fromstring(text_parent) > {
#         "foot": P() > TreeComponent.fromstring(text_grand_child),
#         "head": Cell() > Link() > [
#             "Ceci est du texte",
#             TreeComponent.fromstring(text_grand_child),
#             "Ceci aussi"
#         ]
#     }
# )
with open("bootstrap.min.css", 'r') as style_file:
    style = style_file.read()
tree_comp = Email(style) > Box() > [
    Row() > [
        Cell() > Button() > "Button 1",
        Cell() > '',
        Cell() > Button() > "Button 2"
    ],
    Row() > [
        Cell() > '',
        Cell() > Button() > "Button 3",
    ],
]
#print(tree_comp)
tpt.pprint(tree_comp)
html = etree.tostring(rd.render(tree_comp), pretty_print=True).decode('utf-8')
print(html)
with open("example.html", 'w') as f:
    f.write(html)


text:
package com.amazonaws.services.codedeploy.model;

import java.io.Serializable;
import javax.annotation.Generated;

/**
 *

 * Represents the output of a DeleteDeploymentGroup operation.
 *

 *
 * @see AWS
 *      API Documentation
 */
@Generated("com.amazonaws:aws-java-sdk-code-generator")
public class DeleteDeploymentGroupResult extends com.amazonaws.AmazonWebServiceResult<com.amazonaws.ResponseMetadata> implements Serializable, Cloneable {

    /**
     *

     * If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling group,
     * CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the Amazon EC2
     * instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove some Auto Scaling
     * lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     *

     */
    private com.amazonaws.internal.SdkInternalList<AutoScalingGroup> hooksNotCleanedUp;

    /**
     *

     * If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling group,
     * CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the Amazon EC2
     * instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove some Auto Scaling
     * lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     *

     *
     * @return If the output contains no data, and the corresponding deployment group contained at least one Auto
     *         Scaling group, CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from
     *         the Amazon EC2 instances in the Auto Scaling group. If the output contains data, CodeDeploy could not
     *         remove some Auto Scaling lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     */

    public java.util.List<AutoScalingGroup> getHooksNotCleanedUp() {
        if (hooksNotCleanedUp == null) {
            hooksNotCleanedUp = new com.amazonaws.internal.SdkInternalList<AutoScalingGroup>();
        }
        return hooksNotCleanedUp;
    }

    /**
     *

     * If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling group,
     * CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the Amazon EC2
     * instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove some Auto Scaling
     * lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     *

     *
     * @param hooksNotCleanedUp
     *        If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling
     *        group, CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the
     *        Amazon EC2 instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove
     *        some Auto Scaling lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     */

    public void setHooksNotCleanedUp(java.util.Collection<AutoScalingGroup> hooksNotCleanedUp) {
        if (hooksNotCleanedUp == null) {
            this.hooksNotCleanedUp = null;
            return;
        }

        this.hooksNotCleanedUp = new com.amazonaws.internal.SdkInternalList<AutoScalingGroup>(hooksNotCleanedUp);
    }

    /**
     *

     * If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling group,
     * CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the Amazon EC2
     * instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove some Auto Scaling
     * lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     *

     *

     * NOTE: This method appends the values to the existing list (if any). Use
     * {@link #setHooksNotCleanedUp(java.util.Collection)} or {@link #withHooksNotCleanedUp(java.util.Collection)} if
     * you want to override the existing values.
     *

     *
     * @param hooksNotCleanedUp
     *        If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling
     *        group, CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the
     *        Amazon EC2 instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove
     *        some Auto Scaling lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     * @return Returns a reference to this object so that method calls can be chained together.
     */

    public DeleteDeploymentGroupResult withHooksNotCleanedUp(AutoScalingGroup... hooksNotCleanedUp) {
        if (this.hooksNotCleanedUp == null) {
            setHooksNotCleanedUp(new com.amazonaws.internal.SdkInternalList<AutoScalingGroup>(hooksNotCleanedUp.length));
        }
        for (AutoScalingGroup ele : hooksNotCleanedUp) {
            this.hooksNotCleanedUp.add(ele);
        }
        return this;
    }

    /**
     *

     * If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling group,
     * CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the Amazon EC2
     * instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove some Auto Scaling
     * lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     *

     *
     * @param hooksNotCleanedUp
     *        If the output contains no data, and the corresponding deployment group contained at least one Auto Scaling
     *        group, CodeDeploy successfully removed all corresponding Auto Scaling lifecycle event hooks from the
     *        Amazon EC2 instances in the Auto Scaling group. If the output contains data, CodeDeploy could not remove
     *        some Auto Scaling lifecycle event hooks from the Amazon EC2 instances in the Auto Scaling group.
     * @return Returns a reference to this object so that method calls can be chained together.
     */

    public DeleteDeploymentGroupResult withHooksNotCleanedUp(java.util.Collection<AutoScalingGroup> hooksNotCleanedUp) {
        setHooksNotCleanedUp(hooksNotCleanedUp);
        return this;
    }

    /**
     * Returns a string representation of this object. This is useful for testing and debugging. Sensitive data will be
     * redacted from this string using a placeholder value.
     *
     * @return A string representation of this object.
     *
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        if (getHooksNotCleanedUp() != null)
            sb.append("HooksNotCleanedUp: ").append(getHooksNotCleanedUp());
        sb.append("}");
        return sb.toString();
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;

        if (obj instanceof DeleteDeploymentGroupResult == false)
            return false;
        DeleteDeploymentGroupResult other = (DeleteDeploymentGroupResult) obj;
        if (other.getHooksNotCleanedUp() == null ^ this.getHooksNotCleanedUp() == null)
            return false;
        if (other.getHooksNotCleanedUp() != null && other.getHooksNotCleanedUp().equals(this.getHooksNotCleanedUp()) == false)
            return false;
        return true;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int hashCode = 1;

        hashCode = prime * hashCode + ((getHooksNotCleanedUp() == null) ? 0 : getHooksNotCleanedUp().hashCode());
        return hashCode;
    }

    @Override
    public DeleteDeploymentGroupResult clone() {
        try {
            return (DeleteDeploymentGroupResult) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new IllegalStateException("Got a CloneNotSupportedException from Object.clone() " + "even though we're Cloneable!", e);
        }
    }

}


text:
echo 3 > /proc/sys/kernel/printk
insmod /opt/logger/zynq_logger_main.ko
LD_LIBRARY_PATH=/opt/server/ /opt/server/server


text: print('aaaaweretyrtyuy')


text:
<script>
    if (window.testRunner) {
        testRunner.dumpAsText();
        testRunner.dumpChildFrames();
    }
</script>
<iframe src="resources/plain-text-document.txt">


text: My Todos


text:
package org.kie.workbench.common.stunner.project.backend.service;

import org.guvnor.common.services.shared.metadata.model.Metadata;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.kie.workbench.common.stunner.project.diagram.editor.ProjectDiagramResource;
import org.kie.workbench.common.stunner.project.diagram.editor.impl.ProjectDiagramResourceImpl;
import org.kie.workbench.common.stunner.project.diagram.impl.ProjectDiagramImpl;
import org.kie.workbench.common.stunner.project.service.ProjectDiagramService;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.uberfire.backend.vfs.Path;
import org.uberfire.ext.editor.commons.backend.service.SaveAndRenameServiceImpl;
import org.uberfire.ext.editor.commons.service.RenameService;

import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)
public class ProjectDiagramResourceServiceImplTest {

    @Mock
    private ProjectDiagramService projectDiagramService;

    @Mock
    private RenameService renameService;

    @Mock
    private SaveAndRenameServiceImpl<ProjectDiagramResource, Metadata> saveAndRenameService;

    private ProjectDiagramResourceServiceImpl service;

    @Before
    public void setup() {
        service = new ProjectDiagramResourceServiceImpl(projectDiagramService, renameService, saveAndRenameService);
    }

    @Test
    public void testInit() {

        service.init();

        verify(saveAndRenameService).init(service);
    }

    @Test
    public void testSaveWhenResourceIsProjectDiagram() {

        final Path path = mock(Path.class);
        final Metadata metadata = mock(Metadata.class);
        final ProjectDiagramImpl projectDiagram = mock(ProjectDiagramImpl.class);
        final Path expectedPath = mock(Path.class);
        final ProjectDiagramResourceImpl resource = new ProjectDiagramResourceImpl(projectDiagram);
        final String comment = "comment";

        when(projectDiagramService.save(path, projectDiagram, metadata, comment)).thenReturn(expectedPath);

        final Path actualPath = service.save(path, resource, metadata, comment);

        assertSame(expectedPath, actualPath);
    }

    @Test
    public void testSaveWhenResourceIsXML() {

        final Path path = mock(Path.class);
        final Metadata metadata = mock(Metadata.class);
        final Path expectedPath = mock(Path.class);
        final String diagramXml = "<xml>";
        final ProjectDiagramResourceImpl resource = new ProjectDiagramResourceImpl(diagramXml);
        final String comment = "comment";

        when(projectDiagramService.saveAsXml(path, diagramXml, metadata, comment)).thenReturn(expectedPath);

        final Path actualPath = service.save(path, resource, metadata, comment);

        assertSame(expectedPath, actualPath);
    }

    @Test
    public void testRename() {

        final Path path = mock(Path.class);
        final String newName = "newName";
        final String comment = "comment";

        service.rename(path, newName, comment);

        verify(renameService).rename(path, newName, comment);
    }

    @Test
    public void testSaveAndRename() {

        final Path path = mock(Path.class);
        final Metadata metadata = mock(Metadata.class);
        final ProjectDiagramResourceImpl resource = mock(ProjectDiagramResourceImpl.class);
        final String newName = "newName";
        final String comment = "comment";

        service.saveAndRename(path, newName, metadata, resource, comment);

        verify(saveAndRenameService).saveAndRename(path, newName, metadata, resource, comment);
    }
}


text:
module RuboCop
  module Cop
    module Performance
      # This cop identifies the use of `Regexp#match` or `String#match`, which
      # returns `#<MatchData>`/`nil`. The return value of `=~` is an integral
      # index/`nil` and is more performant.
      #
      # @example
      #   # bad
      #   do_something if str.match(/regex/)
      #   while regex.match('str')
      #     do_something
      #   end
      #
      #   # good
      #   method(str =~ /regex/)
      #   return value unless regex =~ 'str'
      class RedundantMatch < Base
        extend AutoCorrector

        MSG = 'Use `=~` in places where the `MatchData` returned by ' \
              '`#match` will not be used.'

        # 'match' is a fairly generic name, so we don't flag it unless we see
        # a string or regexp literal on one side or the other
        def_node_matcher :match_call?, <<~PATTERN
          {(send {str regexp} :match _)
           (send !nil? :match {str regexp})}
        PATTERN

        def_node_matcher :only_truthiness_matters?, <<~PATTERN
          ^({if while until case while_post until_post} equal?(%0) ...)
        PATTERN

        def on_send(node)
          return unless match_call?(node) &&
                        (!node.value_used? || only_truthiness_matters?(node)) &&
                        !(node.parent && node.parent.block_type?)

          add_offense(node) do |corrector|
            autocorrect(corrector, node)
          end
        end

        private

        def autocorrect(corrector, node)
          # Regexp#match can take a second argument, but this cop doesn't
          # register an offense in that case
          return unless node.first_argument.regexp_type?

          new_source = "#{node.receiver.source} =~ #{node.first_argument.source}"

          corrector.replace(node.source_range, new_source)
        end
      end
    end
  end
end


text:
// THIS SOURCE CODE IS SUPPLIED "AS IS" WITHOUT WARRANTY OF ANY KIND, AND ITS AUTHOR AND THE JOURNAL OF MACHINE LEARNING RESEARCH (JMLR) AND JMLR'S PUBLISHERS AND DISTRIBUTORS, DISCLAIM ANY AND ALL WARRANTIES, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, AND ANY WARRANTIES OR NON INFRINGEMENT. THE USER ASSUMES ALL LIABILITY AND RESPONSIBILITY FOR USE OF THIS SOURCE CODE, AND NEITHER THE AUTHOR NOR JMLR, NOR JMLR'S PUBLISHERS AND DISTRIBUTORS, WILL BE LIABLE FOR DAMAGES OF ANY KIND RESULTING FROM ITS USE. Without lim- iting the generality of the foregoing, neither the author, nor JMLR, nor JMLR's publishers and distributors, warrant that the Source Code will be error-free, will operate without interruption, or will meet the needs of the user.
//
// --------------------------------------------------------------------------
//
// Copyright 2011 Stephen Piccolo
//
// This file is part of ML-Flex.
//
// ML-Flex is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// ML-Flex 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ML-Flex. If not, see <http://www.gnu.org/licenses/>.

package mlflex.ensemblelearners;

/** This class represents an ensemblelearners/combiner approach that computes the combined prediction according to the class probabilities that were assigned for each individual prediction. This particular approach uses the mean across the probabilities, weighted by the AUC attained in the inner cross-validation folds, to compute the combined prediction.
 * @author Stephen Piccolo
 */
public class WeightedMeanProbabilityEnsembleLearner extends MeanProbabilityEnsembleLearner
{
    /** Pass-through constructor
     */
    public WeightedMeanProbabilityEnsembleLearner()
    {
        super(true);
    }
}


text:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Language" content="zh-CN">
<meta name="Keywords" content="">
<meta name="Description" content="">
<title>Super Slide</title>

<link href="../default.css" rel="stylesheet" type="text/css">
<link href="../demo.css" rel="stylesheet" type="text/css">

效果图1

效果图2

效果图3

			js调用:jQuery(".picBtnTop").slide( { mainCell:".bd ul",effect:"topLoop",autoPlay:true } );

			css代码:

/* 图片按钮(上)滚动 - 公用类 */

.picBtnTop{ width:500px; height:214px; border:1px solid #ccc; padding:5px;  position:relative;  overflow:hidden;  zoom:1;   }

.picBtnTop .hd{ width:98px;  height:214px; position:absolute; right:5px;}

.picBtnTop .hd ul li{ width:93px; padding:0 0 5px 5px;  text-align:center; line-height:0px;  }

.picBtnTop .hd ul li img{ width:85px; height:60px; border:4px solid #ddd; cursor:pointer;  }

.picBtnTop .hd ul li.on{ background:url("images/icoleft.gif") no-repeat 0 28px; }

.picBtnTop .hd ul li.on img{ border-color:#f60;  }

.picBtnTop .bd{ width:400px;  height:214px; position:relative;  }

.picBtnTop .bd img{ width:400px; height:214px;  }

.picBtnTop .bd li{ position:relative; zoom:1; }

.picBtnTop .bd li .pic{ position:relative; z-index:0; line-height:0px;  }

.picBtnTop .bd li .bg{ width:400px; height:30px; position:absolute; left:0; bottom:0; z-index:1;  background:#000; filter:alpha(opacity=60);opacity:0.6;    }

.picBtnTop .bd li .title{ width:400px; height:30px; line-height:30px; left:0; bottom:0;   position:absolute; z-index:2;  }

.picBtnTop .bd li .title a{ color:#fff;  }


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<TITLE>
main.java.edu.sagado.genAlg
</TITLE>

<META NAME="date" CONTENT="2012-08-13">

<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../../../stylesheet.css" TITLE="Style">

      Package
      Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV PACKAGE
 NEXT PACKAGE

  FRAMES
 NO FRAMES

  All Classes

Package main.java.edu.sagado.genAlg

Class Summary

Chromo<T>
A Chromo is the basic unit of the genetic population.

Population<T>
The Population class holds the array of chromos and run
 the properly update operations on it

      Package
      Class
      Use
      Tree
      Deprecated
      Index
      Help

 PREV PACKAGE
 NEXT PACKAGE

  FRAMES
 NO FRAMES

  All Classes


text:
<!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-->

User Management
--------------------------------------------------------------------------------

### JCR User Management

JCR itself doesn't come with a dedicated user management API. The only method
related and ultimately used for user management tasks is `Session.getUserID()`.
Therefore an API for user and group management has been defined as part of the
extensions present with Jackrabbit API.

### Jackrabbit User Management API

The Jackrabbit API provides the user management related extensions that are
missing in JCR. The relevant interfaces are defined in the
`org.apache.jackrabbit.api.security.user' package space:

- `UserManager`
- `Authorizable`
    - `User`
    - `Group`
- `Impersonation`
- `QueryBuilder`
    - `Query`

### Oak User Management Implementation

The default user management implementation stores user/group information in the
content repository. In contrast to Jackrabbit 2.x, which by default used a single,
dedicated workspace for user/group data, this data will as of Oak 1.0 be stored
separately for each JCR workspace.

Consequently the `UserManager` associated with the editing sessions, performs
all actions with this editing session. This corresponds to the behavior as defined
the alternative implementation present with Jackrabbit 2.x ((see Jackrabbit 2.x `UserPerWorkspaceUserManager`).

#### General
* The Oak implementation is build on the Oak API. This allows for double usage as
  extension to the JCR API as well as within the Oak layer (aka SPI).
* The `UserManager` is always associated with the same JCR workspace as the editing
  `Session` from which the class has been obtained.
* Changes made to the user management API are always transient and require `Session#save()` to be persisted.
* In case of any failure during user management related write operations the API
  consumer is in charge of specifically revert pending or invalid transient modifications
  or calling `Session#refresh(false)`.

#### Differences wrt Jackrabbit 2.x

A summary of all changes with respect to the former implementation present with
Jackrabbit 2.x is present in the corresponding [section](user/differences.html).

#### Built-in Users and Special Groups

The setup of builtin user and group accounts is triggered by the configured `WorkspaceInitializer`
associated with the user management configuration (see Configuration section below).

The default user management implementation in OAK comes with an initializer that
creates the following builtin user accounts:

##### Administrator
The admin user is always being created. The ID of this user is retrieved from the
user configuration parameter `PARAM_ADMIN_ID`, which defaults to `admin`.

As of OAK 1.0 however the administrator user might be created without initial
password forcing the application to set the password upon start (see `PARAM_OMIT_ADMIN_PW`
configuration parameter).

##### Anonymous User
In contrast to Jackrabbit 2.x the anonymous (or guest) user is optional. Creation
will be skipped if the value of the `PARAM_ANONYMOUS_ID` configuration parameter
is `null` or empty.

Note, that the anonymous user will always be created without specifying a password
in order to prevent regular login with `SimpleCredentials`.
The proper way to obtain a guest session is:

    Repository#login(new GuestCredentials(), wspName);

See section [Authentication](authentication.html) for further information about
guest login.

##### Everyone Group

The default user management implementation in Oak contains special handling for
the optional group that represents _everyone_, which is marked by the reserved
name [everyone] and corresponds to the `EveryonePrincipal`.

This special group always contains all Authorizable as member and cannot be edited
with user management API. As of OAK this fact is consistently reflected in all
group membership related methods. See also [Principal Management](principal.html).

#### Reading Authorizables

##### Handling of the Authorizable ID
* As of Oak the node type definition of `rep:Authorizable` defines a new property `rep:authorizableId` which is intended to store the ID of a user or group.
* The default implementation comes with a dedicated property index for `rep:authorizableId` which asserts the uniqueness of that ID.
* `Authorizable#getID` returns the string value contained in `rep:authorizableID` and for backwards compatibility falls back on the node name in case the ID property is missing.
* The name of the authorizable node is generated based on a configurable implementation of the `AuthorizableNodeName` interface (see configuration section below). By default it uses the ID as name hint and includes a conversion to a valid JCR node name.

##### equals() and hashCode()
The implementation of `Object#equals()` and `Object#hashCode()` for user and
groups slightly differs from Jackrabbit 2.x. It no longer relies on the _sameness_
of the underlaying JCR node but only compares IDs and the user manager instance.

#### Creating Authorizables
* The `rep:password` property is no longer defined to be mandatory. Therefore a new user might be created without specifying a password. Note however, that `User#changePassword` does not allow to remove the password property.
* `UserManager#createGroup(Principal)` will no longer generate a groupID in case the principal name collides with an existing user or group ID. This has been considered redundant as the Jackrabbit API in the mean time added `UserManager#createGroup(String groupID)`.
* Since OAK is designed to scale with flat hierarchies the former configuration options `autoExpandTree` and `autoExpandSize` are no longer supported.

#### Query

See section [Searching Users and Groups](user/query.html) for details.

#### Group Membership

See section [Group Membership](user/membership.html) for details.

#### Autosave Behavior
Due to the nature of the UserManager (see above) we decided to drop the auto-save
behavior in the default implementation present with OAK. Consequently,

* `UserManager#autoSave(boolean)` throws `UnsupportedRepositoryOperationException`
* `UserManager#isAutoSave()` always returns `false`

See also `PARAM_SUPPORT_AUTOSAVE` below; while this should not be needed if
application code has been written against the Jackrabbit API (and thus testing if
auto-save mode is enabled or not) this configuration option can be used as last resort.

#### User/Group Representation in the Repository

The following block lists the built-in node types related to user management tasks:

    [rep:Authorizable] > mix:referenceable, nt:hierarchyNode
      abstract
      + * (nt:base) = nt:unstructured VERSION
      - rep:principalName  (STRING) protected mandatory
      - rep:authorizableId (STRING) protected /* @since oak 1.0 */
      - * (UNDEFINED)
      - * (UNDEFINED) multiple

    [rep:Group] > rep:Authorizable, rep:MemberReferences
      + rep:members (rep:Members) = rep:Members multiple protected VERSION /* @deprecated */
      + rep:membersList (rep:MemberReferencesList) = rep:MemberReferencesList protected COPY

    /** @since oak 1.0 */
    [rep:MemberReferences]
      - rep:members (WEAKREFERENCE) protected multiple < 'rep:Authorizable'

    /** @since oak 1.0 */
    [rep:MemberReferencesList]
      + * (rep:MemberReferences) = rep:MemberReferences protected COPY

    /** @deprecated since oak 1.0 */
    [rep:Members]
      orderable
      + * (rep:Members) = rep:Members protected multiple
      - * (WEAKREFERENCE) protected < 'rep:Authorizable'

<a name="validation"/>
##### Validation

The consistency of this content structure is asserted by a dedicated `UserValidator`.
The corresponding errors are all of type `Constraint` with the following codes:

| Code              | Message                                                  |
|-------------------|----------------------------------------------------------|
| 0020              | Admin user cannot be disabled                            |
| 0021              | Invalid jcr:uuid for authorizable (creation)             |
| 0022              | Changing Id, principal name after creation               |
| 0023              | Invalid jcr:uuid for authorizable (mod)                  |
| 0024              | Password may not be plain text                           |
| 0025              | Attempt to remove id, principalname or pw                |
| 0026              | Mandatory property rep:principalName missing             |
| 0027              | The admin user cannot be removed                         |
| 0028              | Attempt to create outside of configured scope            |
| 0029              | Intermediate folders not rep:AuthorizableFolder          |
| 0030              | Missing uuid for group (check for cyclic membership)     |
| 0031              | Cyclic group membership                                  |
| 0032              | Attempt to set password with system user                 |
| 0033              | Attempt to add rep:pwd node to a system user             |

#### XML Import
As of Oak 1.0 user and group nodes can be imported both with Session and Workspace
import. Other differences compared to Jackrabbit 2.x:

* Importing an authorizable to another tree than the configured user/group node will only failed upon save (-> see `UserValidator` during the `Root#commit`). With Jackrabbit 2.x core it used to fail immediately.
* The `BestEffort` behavior is now also implemented for the import of impersonators (was missing in Jackrabbit /2.x).

### API Extensions
The Oak project introduces the following user management related public
interfaces and classes:

#### Authorizable Actions

The former internal Jackrabbit interface `AuthorizableAction` has been slightly
adjusted to match Oak requirements and is now part of the public Oak SPI interfaces.
In contrast to Jackrabbit-core the AuthorizableAction(s) now operate directly on
the Oak API, which eases the handling of implementation specific tasks such as
writing protected items.

See section [Authorizable Actions](user/authorizableaction.html) for further
details and examples.

#### Node Name Generation

The default user management implementation with Oak 1.0 allows to specify how
the name of a new authorizable node is being generated.

See section [Authorizable Node Name](user/authorizablenodename.html) for further
details and examples.

#### Password Expiry and Force Initial Password Change

Since Oak 1.1.0 the default user management and authentication implementation
provides password expiry and initial password change.

By default these features are disabled. The corresponding configuration options
are

- `PARAM_PASSWORD_MAX_AGE`: number of days until the password expires.
- `PARAM_PASSWORD_INITIAL_CHANGE`: boolean flag to enable this feature.

See section [Password Expiry and Force Initial Password Change](user/expiry.html)
for details.

#### Password History

Since Oak 1.3.3 the default user management implementation provides password
history support.

By default this feature is disabled. The corresponding configuration option is

- `PARAM_PASSWORD_HISTORY_SIZE`: number of changed passwords to remember.

See section [Password History](user/history.html) for details.

#### Utilities

`org.apache.jackrabbit.oak.spi.security.user.*`

- `AuthorizableType` : Ease handling with the different authorizable types.
- `UserConstants` : Constants (NOTE: OAK names/paths)

`org.apache.jackrabbit.oak.spi.security.user.util.*`

- `PasswordUtil` : Utilities for password generation. This utility corresponds
  to the internal jackrabbit utility.
  As of OAK it also supports Password-Based Key Derivation Function 2 (PBKDF2)
  function for password generation.
- `UserUtil` : Utilities related to general user management tasks.

### Configuration

The following user management specific methods are present with the [UserConfiguration]
as of OAK 1.0:

* getUserManager: Obtain a new user manager instance

#### Configuration Parameters supported by the default implementation

| Parameter                           | Type    | Default                                      |
|-------------------------------------|---------|----------------------------------------------|
| `PARAM_ADMIN_ID`                    | String  | "admin"                                      |
| `PARAM_OMIT_ADMIN_PW`               | boolean | false                                        |
| `PARAM_ANONYMOUS_ID`                | String  | "anonymous" (nullable)                       |
| `PARAM_USER_PATH`                   | String  | "/rep:security/rep:authorizables/rep:users"  |
| `PARAM_GROUP_PATH`                  | String  | "/rep:security/rep:authorizables/rep:groups" |
| `PARAM_DEFAULT_DEPTH`               | int     | 2                                            |
| `PARAM_PASSWORD_HASH_ALGORITHM`     | String  | "SHA-256"                                    |
| `PARAM_PASSWORD_HASH_ITERATIONS`    | int     | 1000                                         |
| `PARAM_PASSWORD_SALT_SIZE`          | int     | 8                                            |
| `PARAM_AUTHORIZABLE_NODE_NAME`      | AuthorizableNodeName | AuthorizableNodeName#DEFAULT    |
| `PARAM_AUTHORIZABLE_ACTION_PROVIDER`| AuthorizableActionProvider | DefaultAuthorizableActionProvider |
| `PARAM_SUPPORT_AUTOSAVE`            | boolean | false                                        |
| `PARAM_IMPORT_BEHAVIOR`             | String ("abort", "ignore", "besteffort") | "ignore"    |
| `PARAM_PASSWORD_MAX_AGE`            | int     | 0                                            |
| `PARAM_PASSWORD_INITIAL_CHANGE`     | boolean | false                                        |
| `PARAM_PASSWORD_HISTORY_SIZE`       | int (upper limit: 1000) | 0                            |
| `PARAM_CACHE_EXPIRATION`            | long    | 0                                            |
| | | |

The following configuration parameters present with the default implementation in Jackrabbit 2.x are no longer supported and will be ignored:

* `compatibleJR16`
* `autoExpandTree`
* `autoExpandSize`
* `groupMembershipSplitSize`

The optional `cacheExpiration` configuration option listed above is discussed in
detail in section [Caching Results of Principal Resolution](principal/cache.html).
It is not related to user management s.str. but affects the implementation
specific `PrincipalProvider` implementation exposed by `UserConfiguration.getUserPrincipalProvider`.

### Pluggability

The default security setup as present with Oak 1.0 is able to provide custom
implementation on various levels:

1. The complete user management implementation can be changed by plugging a different
   `UserConfiguration` implementations. In OSGi-base setup this is achieved by making
   the configuration a service. In a non-OSGi-base setup the custom configuration
   must be exposed by the `SecurityProvider` implementation.
2. Within the default user management implementation the following parts can be
   change/extended at runtime by providing corresponding OSGi services or passing
   appropriate configuration parameters exposing the custom implementations:
       - `AuthorizableActionProvider`: Defines the authorizable actions, see [Authorizable Actions](user/authorizableaction.html).
       - `AuthorizableNodeName`: Defines the generation of the authorizable node names
          in case the user management implementation stores user information in the repository.
          See [Authorizable Node Name Generation](user/authorizablenodename.html).

### Further Reading

- [Differences wrt Jackrabbit 2.x](user/differences.html)
- [Group Membership](user/membership.html)
- [Authorizable Actions](user/authorizableaction.html)
- [Authorizable Node Name](user/authorizablenodename.html)
- [Searching Users and Groups](user/query.html)
- [Password Expiry and Force Initial Password Change](user/expiry.html)
- [Password History](user/history.html)

<!-- hidden references -->
[everyone]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/principal/EveryonePrincipal.html#NAME
[UserConfiguration]: /oak/docs/apidocs/org/apache/jackrabbit/oak/spi/security/user/UserConfiguration.html
[OAK-118]: https://issues.apache.org/jira/browse/OAK-118
[OAK-482]: https://issues.apache.org/jira/browse/OAK-482
[OAK-793]: https://issues.apache.org/jira/browse/OAK-793
[OAK-949]: https://issues.apache.org/jira/browse/OAK-949
[OAK-1183]: https://issues.apache.org/jira/browse/OAK-1183


text:
package ru.majo.bsutimetable.ui.view;

import java.util.ArrayList;

import ru.majo.bsutimetable.base.BaseView;
import ru.majo.bsutimetable.model.MonthWithDays;

/**
 * Created by Majo on 25.01.2016.
 */
public interface TimetableView extends BaseView{
    void showFullTimeTimetable();
    void showPartTimeTimetable(ArrayList<MonthWithDays> months);
}


text:
import { BehaviorSubject } from 'rxjs/Rx';
import { FilesPageService } from './files-page.service';
import { FilesService } from '../../core/files/files.service';
import { DECRYPT_ALGO } from '../../utils/crypto';
import { DatagridActionBar } from 'clarity-angular';
import { AppState } from '../../app.reducers';
import * as FoldersActions from '../../core/folders/folders.actions';

import {
  AfterViewInit,
  ChangeDetectionStrategy,
  Component,
  OnInit,
  ViewChild
} from '@angular/core';
import { Router } from '@angular/router';
import { ActivatedRoute } from '@angular/router';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';

const renderMedia = require('render-media');
const PartialDecryptStream = require('cbc-partial-decrypt');

@Component({
  selector: 'ax-files-page',
  templateUrl: './files-page.component.html',
  styleUrls: ['./files-page.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class FilesPageComponent implements OnInit, AfterViewInit {

  private currentFolder$ = this.filesPageService.currentFolder$;
  private authenticated$ = this.filesPageService.authenticated$;
  // private downloadData$ = this.store.select(state => state.downloadData);
  // private nameFormModal$ = this.store.select(state => state.modals.nameForm);
  // private player$ = this.store.select(state => state.player);

  private hasBaseDropZoneOver = false;

  private selected = null;

  // @ViewChild('renderMedia') renderMedia;
  // @ViewChild('renderMediaTest') renderMediaTest;

  @ViewChild('sidenav') sidenav;

  /**
   * Styling properties.
   * @todo : Look for a pure CSS solution, if possible.
   * Keeps the size of the breadcrumb in sync with sidenav width
   */
  @ViewChild('subnavRightButtons') subnavRightButtons;

  // Values being pushed through events in html.
  sidenavWidth$: BehaviorSubject<number>;

  breadcrumbSize$: Observable<number>;
  /**
   * End styling properties
   */

  downloadsBadge$ = this.filesPageService.downloadingList$.map(state => state.files.length)
  uploadsBadge$ = this.filesPageService.uploadingList$.map(state => state.files.length)

  downloadsBadgeColor$ = this.filesPageService.downloadingList$
    .map(downloading => {
      return ((downloading.progress === 100) || (downloading.progress === 0)) &&
        downloading.files.length > 0 ?
        'badge-success' :
        'badge-orange';
    })
  uploadsBadgeColor$ = this.filesPageService.uploadingList$
    .map(uploading => uploading.progress)
    .map(progress => progress === 100 ? 'badge-success' : 'badge-orange');

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    // public uploaderService: UploaderService,
    // public downloaderService: DownloaderService,
    private store: Store<AppState>,
    // private filesApi: FilesService,
    private filesPageService: FilesPageService
  ) { };

  ngOnInit() {
    this.route.params.subscribe(params => {
      this.filesPageService.goToFolder(params['id']);
    });
  }

  ngAfterViewInit() {

  }

  public fileOverDragArea (e: any): void {
    this.hasBaseDropZoneOver = e;
  }
}