text:
package com.juanan.pocs.web.mibarrio.biblioeventos.dao.impl;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import com.juanan.pocs.web.mibarrio.biblioeventos.dao.BiblioEventoDAO;
import com.juanan.pocs.web.mibarrio.biblioeventos.dto.BiblioEventoDTO;
import com.juanan.pocs.web.mibarrio.biblioeventos.dto.InstalacionDTO;
import com.juanan.pocs.web.mibarrio.biblioeventos.entity.BiblioEventoEntity;
import com.juanan.pocs.web.mibarrio.biblioeventos.entity.InstalacionEntity;
import com.juanan.pocs.web.mibarrio.biblioeventos.handler.BiblioEventosHandler;
import com.juanan.pocs.web.mibarrio.persistence.HibernateUtils;
import com.juanan.pocs.web.mibarrio.voluntarios.handler.VoluntariosHandler;

public class BiblioEventoDAOImpl implements BiblioEventoDAO{

	private SessionFactory sessionFactory = HibernateUtils.getSessionFactory();

	private static final Logger log = Logger.getLogger(VoluntariosHandler.class);

	@Override
	public boolean createNuevoBiblioEvento(BiblioEventoDTO biblioEventoDTO) {

		boolean newBiblioEventoDTO = false;
		if (biblioEventoDTO != null && biblioEventoDTO.getInstalacionDTO() != null && getBiblioEventoById(biblioEventoDTO.getId()) == null) {
			Session session = sessionFactory.openSession();
			if (getInstalacionById(biblioEventoDTO.getInstalacionDTO().getId()) == null) {
				InstalacionEntity instalacionEntity = BiblioEventosHandler.getInstalacionEntityFromInstalacionDTO(biblioEventoDTO.getInstalacionDTO());
				session.save(instalacionEntity);
				session.flush();
			}
			BiblioEventoEntity biblioEventoEntity = BiblioEventosHandler.getBiblioEventoEntityFromBiblioEventoDTO(biblioEventoDTO);
			session.save(biblioEventoEntity);
			session.flush();
			session.close();
			newBiblioEventoDTO = true;
		}

		return newBiblioEventoDTO;
	}

	@Override
	public BiblioEventoDTO getBiblioEventoById(Integer idBiblioEvento) {

		BiblioEventoDTO biblioEventoDTO = null;
		if (idBiblioEvento != null) {
			Session session = sessionFactory.openSession();
			Criteria criteriaBiblioEventos = session.createCriteria(BiblioEventoEntity.class);
			criteriaBiblioEventos.add(Restrictions.eq("id", idBiblioEvento));
			List<BiblioEventoEntity> listBiblioEventoEntity = criteriaBiblioEventos.list();
			session.close();
			if (listBiblioEventoEntity != null && listBiblioEventoEntity.size() == 1) {
				biblioEventoDTO = BiblioEventosHandler.getBiblioEventoDTOFromBiblioEventoEntity(listBiblioEventoEntity.get(0));
			}
		}

		return biblioEventoDTO;
	}

	@Override
	public InstalacionDTO getInstalacionById(Integer idInstalacion) {

		InstalacionDTO instalacionDTO = null;
		if (idInstalacion != null) {
			Session session = sessionFactory.openSession();
			Criteria criteriaInstalacion = session.createCriteria(InstalacionEntity.class);
			criteriaInstalacion.add(Restrictions.eq("id", idInstalacion));
			List<InstalacionEntity> listInstalacionEntity = criteriaInstalacion.list();
			session.close();
			if (listInstalacionEntity != null && listInstalacionEntity.size() == 1) {
				instalacionDTO = BiblioEventosHandler.getInstalacionDTOFromInstalacionEntity(listInstalacionEntity.get(0));
			}
		}

		return instalacionDTO;
	}

	@Override
	public int getNumBiblioEventos(int idInstalacion) {

		int numTotalBiblioEventos = 0;
		Session session = sessionFactory.openSession();
		Criteria criteriaBiblioEventos = session.createCriteria(BiblioEventoEntity.class, "biblioEventoEntity");
		if (idInstalacion > -1){
			criteriaBiblioEventos.add(Restrictions.eq("biblioEventoEntity.instalacionEntity.id", idInstalacion));
		}
		List<BiblioEventoEntity> listBiblioEventoEntity = criteriaBiblioEventos.list();
		if (listBiblioEventoEntity != null){
			numTotalBiblioEventos = listBiblioEventoEntity.size();
		}
		session.close();

		return numTotalBiblioEventos;
	}

	@Override
	public List<BiblioEventoDTO> getBiblioEventos(int idInstalacion, int offset, int limit) {

		int numTotalBiblioEventos = 0;
		Session session = sessionFactory.openSession();
		Criteria criteriaBiblioEventos = session.createCriteria(BiblioEventoEntity.class, "biblioEventoEntity");
		if (idInstalacion > -1){
			criteriaBiblioEventos.add(Restrictions.eq("biblioEventoEntity.instalacionEntity.id", idInstalacion));
		}
		criteriaBiblioEventos.addOrder(Order.asc("biblioEventoEntity.fechaInicio"));
		List<BiblioEventoEntity> listBiblioEventoEntity = criteriaBiblioEventos.list();
		if (listBiblioEventoEntity != null){
			numTotalBiblioEventos = listBiblioEventoEntity.size();
			if (numTotalBiblioEventos > offset + limit){
				criteriaBiblioEventos.setMaxResults(limit);
			}
			criteriaBiblioEventos.setFirstResult(offset);
			listBiblioEventoEntity = criteriaBiblioEventos.list();
		}
		session.close();
		List<BiblioEventoDTO> listBiblioEventoDTO = BiblioEventosHandler.getListBiblioEventoDTOFromListBiblioEventoEntity(listBiblioEventoEntity);

		return listBiblioEventoDTO;
	}

	@Override
	public List<InstalacionDTO> getInstalaciones() {

		Session session = sessionFactory.openSession();
		List<InstalacionEntity> listInstalacionEntity = session.createCriteria(InstalacionEntity.class).list();
		session.close();
		List<InstalacionDTO> listInstalacionDTO = BiblioEventosHandler.getListInstalacionDTOFromListInstalacionEntity(listInstalacionEntity);

		return listInstalacionDTO;
	}

}


text:
<!DOCTYPE html><title>public/assets/js/admin/i18n/locale-es</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"><meta name="groc-relative-root" content="../../../../../"><meta name="groc-document-path" content="public/assets/js/admin/i18n/locale-es"><meta name="groc-project-path" content="public/assets/js/admin/i18n/locale-es.js"><link rel="stylesheet" type="text/css" media="all" href="../../../../../assets/style.css">

public/assets/js/admin/i18n/locale-es.js

'use strict';

angular.module("ngLocale", [], ["$provide", function($provide) {
    var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
    $provide.value("$locale", {
        "DATETIME_FORMATS": {
            "AMPMS": [
                "a.m.",
                "p.m."
            ],
            "DAY": [
                "domingo",
                "lunes",
                "martes",
                "mi\u00e9rcoles",
                "jueves",
                "viernes",
                "s\u00e1bado"
            ],
            "MONTH": [
                "enero",
                "febrero",
                "marzo",
                "abril",
                "mayo",
                "junio",
                "julio",
                "agosto",
                "septiembre",
                "octubre",
                "noviembre",
                "diciembre"
            ],
            "SHORTDAY": [
                "dom",
                "lun",
                "mar",
                "mi\u00e9",
                "jue",
                "vie",
                "s\u00e1b"
            ],
            "SHORTMONTH": [
                "ene",
                "feb",
                "mar",
                "abr",
                "may",
                "jun",
                "jul",
                "ago",
                "sep",
                "oct",
                "nov",
                "dic"
            ],
            "fullDate": "EEEE, d 'de' MMMM 'de' y",
            "longDate": "d 'de' MMMM 'de' y",
            "medium": "dd/MM/yyyy HH:mm:ss",
            "mediumDate": "dd/MM/yyyy",
            "mediumTime": "HH:mm:ss",
            "short": "dd/MM/yy HH:mm",
            "shortDate": "dd/MM/yy",
            "shortTime": "HH:mm"
        },
        "NUMBER_FORMATS": {
            "CURRENCY_SYM": "\u20ac",
            "DECIMAL_SEP": ",",
            "GROUP_SEP": ".",
            "PATTERNS": [
                {
                    "gSize": 3,
                    "lgSize": 3,
                    "macFrac": 0,
                    "maxFrac": 3,
                    "minFrac": 0,
                    "minInt": 1,
                    "negPre": "-",
                    "negSuf": "",
                    "posPre": "",
                    "posSuf": ""
                },
                {
                    "gSize": 3,
                    "lgSize": 3,
                    "macFrac": 0,
                    "maxFrac": 2,
                    "minFrac": 2,
                    "minInt": 1,
                    "negPre": "-",
                    "negSuf": "\u00a0\u00a4",
                    "posPre": "",
                    "posSuf": "\u00a0\u00a4"
                }
            ]
        },
        "id": "es",
        "pluralCat": function (n) {  if (n == 1) {   return PLURAL_CATEGORY.ONE;  }  return PLURAL_CATEGORY.OTHER;}
    });
}]);

redpajama_set_name: RedPajamaGithub


text:
cask 'manager' do
  version '18.7.80'
  sha256 'e6f9b33ea810f72dc58aabb7a3906523b17de1fbbc8407e92484d3f3228bff3e'

  # d2ap5zrlkavzl7.cloudfront.net was verified as official when first introduced to the cask
  url "https://d2ap5zrlkavzl7.cloudfront.net/#{version}/Manager.dmg"
  appcast 'https://www.manager.io/desktop/download/'
  name 'Manager'
  homepage 'https://www.manager.io/'

  app 'Manager.app'
end


text:
import { useMemo, memo } from 'react'
import { ScaleValue, AnyScale, TicksSpec } from '@nivo/scales'
import { GridLines } from './GridLines'
import { computeGridLines } from '../compute'

export const Grid = memo(
    <X extends ScaleValue, Y extends ScaleValue>({
        width,
        height,
        xScale,
        yScale,
        xValues,
        yValues,
    }: {
        width: number
        height: number
        xScale?: AnyScale | null
        xValues?: TicksSpec<X>
        yScale?: AnyScale | null
        yValues?: TicksSpec<Y>
    }) => {
        const xLines = useMemo(() => {
            if (!xScale) return false

            return computeGridLines({
                width,
                height,
                scale: xScale,
                axis: 'x',
                values: xValues,
            })
        }, [xScale, xValues, width, height])

        const yLines = useMemo(() => {
            if (!yScale) return false

            return computeGridLines({
                width,
                height,
                scale: yScale,
                axis: 'y',
                values: yValues,
            })
        }, [height, width, yScale, yValues])

        return (
            <>
                {xLines && <GridLines lines={xLines} />}
                {yLines && <GridLines lines={yLines} />}
            </>
        )
    }
)


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

/* eslint max-statements:[0, 99] */
'use strict';

var bufrw = require('bufrw');
var inherits = require('util').inherits;
var errors = require('./errors');

// RW a thrift map to an array of [k, v] entries

// ktype:1 vtype:1 length:4 (k... v...){length}

function MapEntriesRW(ktype, vtype) {
    var self = this;
    self.ktype = ktype;
    self.vtype = vtype;

    if (self.ktype.rw.width && self.vtype.rw.width) {
        self.byteLength = self.mapFixFixbyteLength;
    } else if (self.ktype.rw.width) {
        self.byteLength = self.mapFixVarbyteLength;
    } else if (self.vtype.rw.width) {
        self.byteLength = self.mapVarFixbyteLength;
    }
}
inherits(MapEntriesRW, bufrw.Base);

MapEntriesRW.prototype.byteLength =
function mapVarVarByteLength(entries) {
    var self = this;
    var len = 6; // static overhead

    for (var i = 0; i < entries.length; i++) {
        var res = self.ktype.rw.byteLength(entries[i][0]);
        // istanbul ignore if
        if (res.err) return res;
        len += res.length;

        res = self.vtype.rw.byteLength(entries[i][1]);
        // istanbul ignore if
        if (res.err) return res;
        len += res.length;
    }

    return new bufrw.LengthResult(null, len);
};

MapEntriesRW.prototype.mapVarFixbyteLength =
function mapVarFixByteLength(entries) {
    var self = this;
    var len = 6 + entries.length * self.vtype.rw.width;
    for (var i = 0; i < entries.length; i++) {
        var res = self.ktype.rw.byteLength(entries[i][0]);
        // istanbul ignore if
        if (res.err) return res;
        len += res.length;
    }
    return new bufrw.LengthResult(null, len);
};

MapEntriesRW.prototype.mapFixVarbyteLength =
function mapFixVarByteLength(entries) {
    var self = this;
    var len = 6 + entries.length * self.ktype.rw.width;
    for (var i = 0; i < entries.length; i++) {
        var res = self.vtype.rw.byteLength(entries[i][1]);
        // istanbul ignore if
        if (res.err) return res;
        len += res.length;
    }
    return new bufrw.LengthResult(null, len);
};

MapEntriesRW.prototype.mapFixFixbyteLength =
function mapFixFixByteLength(entries) {
    var self = this;
    var len = 6 +
        entries.length * self.ktype.rw.width +
        entries.length * self.vtype.rw.width;
    return new bufrw.LengthResult(null, len);
};

MapEntriesRW.prototype.writeInto =
function writeInto(entries, buffer, offset) {
    var self = this;

    // ktype:1
    var res = bufrw.UInt8.writeInto(self.ktype.typeid, buffer, offset);
    // istanbul ignore if
    if (res.err) return res;
    offset = res.offset;

    // vtype:1
    res = bufrw.UInt8.writeInto(self.vtype.typeid, buffer, offset);
    // istanbul ignore if
    if (res.err) return res;
    offset = res.offset;

    // length:4
    res = bufrw.UInt32BE.writeInto(entries.length, buffer, offset);
    // istanbul ignore if
    if (res.err) return res;
    offset = res.offset;

    // (k... v...){length}
    for (var i = 0; i < entries.length; i++) {
        var pair = entries[i];

        // k...
        res = self.ktype.rw.writeInto(pair[0], buffer, offset);
        // istanbul ignore if
        if (res.err) return res;
        offset = res.offset;

        // v...
        res = self.vtype.rw.writeInto(pair[1], buffer, offset);
        // istanbul ignore if
        if (res.err) return res;
        offset = res.offset;
    }

    return new bufrw.WriteResult(null, offset);
};

MapEntriesRW.prototype.readFrom = function readFrom(buffer, offset) {
    var self = this;

    // ktype:1
    var res = bufrw.UInt8.readFrom(buffer, offset);
    // istanbul ignore if
    if (res.err) return res;
    offset = res.offset;
    var ktypeid = res.value;

    if (ktypeid !== self.ktype.typeid) {
        return new bufrw.ReadResult(errors.MapKeyTypeIdMismatch({
            encoded: ktypeid,
            expected: self.ktype.name,
            expectedId: self.ktype.typeid
        }), offset);
    }

    // vtype:1
    res = bufrw.UInt8.readFrom(buffer, offset);
    // istanbul ignore if
    if (res.err) return res;
    offset = res.offset;
    var vtypeid = res.value;

    if (vtypeid !== self.vtype.typeid) {
        return new bufrw.ReadResult(errors.MapValTypeIdMismatch({
            encoded: vtypeid,
            expected: self.vtype.name,
            expectedId: self.vtype.typeid
        }), offset);
    }

    // length:4
    res = bufrw.UInt32BE.readFrom(buffer, offset);
    // istanbul ignore if
    if (res.err) return res;
    offset = res.offset;
    var length = res.value;

    // (k... v...){length}
    var entries = [];
    for (var i = 0; i < length; i++) {

        // k...
        res = self.ktype.rw.readFrom(buffer, offset);
        // istanbul ignore if
        if (res.err) return res;
        offset = res.offset;
        var key = res.value;

        // v...
        res = self.vtype.rw.readFrom(buffer, offset);
        // istanbul ignore if
        if (res.err) return res;
        offset = res.offset;
        var val = res.value;

        entries.push([key, val]);
    }

    return new bufrw.ReadResult(null, offset, entries);
};

module.exports.MapEntriesRW = MapEntriesRW;


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
null

#### Original name
Eurotiopsis foliicola P. Karst.

### Remarks
null


text:
package org.pentaho.pedis;

import java.io.IOException;
import javax.servlet.http.HttpServletResponse;

import org.pentaho.platform.api.engine.IParameterProvider;
import org.pentaho.platform.api.engine.IContentGenerator;

class PedisException extends Exception {
  protected int code;

  PedisException(String message, int code) {
    super(message);
    setCode(code);
  }

  PedisException(String message, int code, Throwable cause) {
    super(message, cause);
    setCode(code);
  }

  public void setCode(int code) {
    this.code = code;
  }

  public int getCode() {
    return code;
  }

  public String getMessage() {
    String message = super.getMessage();
    Throwable cause = getCause();
    if (cause != null) {
      message += " " + cause.getMessage();
    }
    return message;
  }

  public void sendError(HttpServletResponse response) throws IOException {
    response.sendError(getCode(), getMessage());
  }
}


text: Homepage layout test using HTML5 and CSS3


text:
ScreenRecorder
==============
Capturing a screen as videos on iOS devices for user testing.

## Features
* Screen capture
* Show touch pointer
* Autosave and file rotation
* Change FPS

## Setup

###1. Add the files
Copy the files you need to your project folder, and add them to your Xcode project.
  * Lib/SRScreenRecorder.h
  * Lib/SRScreenRecorder.m
  * Vendor/KTouchPointerWindow.h
  * Vendor/KTouchPointerWindow.m

###2. Link with the frameworks
  * QuartzCore.framework
  * CoreVideo.framework
  * CoreMedia.framework
  * AVFoundation.framework

## Usage
###Basic
```objective-c
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [[SRScreenRecorder sharedInstance] startRecording];
    return YES;
}
 ```

In default settings,
* save movie file automatically on enter background
* and auto rotate save files every 10 minutes
* movie file saved at document directory, named 'TIMESTAMP.mov'
* 30 FPS
* shows touch pointer

###Customize
```objective-c
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    SRScreenRecorder *recorder = [SRScreenRecorder sharedInstance];
    recorder.frameInterval = 1; // 60 FPS
    recorder.autosaveDuration = 1800; // 30 minutes
    recorder.showsTouchPointer = NO; // hidden touch pointer
    recorder.filenameBlock = ^(void) {
        return @"screencast.mov";
    }; // change filename

    [recorder startRecording];

    return YES;
}
 ```

###When submit to AppStore if includes this library, define APPSTORE_SAFE macro to eliminate using undocumented API
```objective-c
#define APPSTORE_SAFE 1
 ```

## 3rd party libraries

**KTouchPointerWindow**
[https://github.com/itok/KTouchPointerWindow](https://github.com/itok/KTouchPointerWindow)

[Apache]: http://www.apache.org/licenses/LICENSE-2.0
[MIT]: http://www.opensource.org/licenses/mit-license.php
[GPL]: http://www.gnu.org/licenses/gpl.html
[BSD]: http://opensource.org/licenses/bsd-license.php

## License

ScreenRecorder is available under the [MIT license][MIT]. See the LICENSE file for more info.


text:
package com.thingtrack.konekti.service.impl.internal;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.thingtrack.konekti.domain.Area;
import com.thingtrack.konekti.domain.ProductUnit;
import com.thingtrack.konekti.dao.api.ProductUnitDao;
import com.thingtrack.konekti.service.api.ProductUnitService;

/**
 * @author Thingtrack S.L.
 *
 */
public class ProductUnitServiceImpl implements ProductUnitService {
	@Autowired
	private ProductUnitDao productUnitDao;

	@Override
	public List<ProductUnit> getAll(Area area) throws Exception {
		return this.productUnitDao.getAll(area);

	}

	@Override
	public ProductUnit get(Integer productUnitId) throws Exception {
		return this.productUnitDao.get(productUnitId);

	}

	@Override
	public ProductUnit getByCode(Area area, String code) throws Exception {
		return this.productUnitDao.getByCode(area, code);

	}

	@Override
	public ProductUnit save(ProductUnit productUnit) throws Exception {
		return this.productUnitDao.save(productUnit);

	}

	@Override
	public void delete(ProductUnit productUnit) throws Exception {
		this.productUnitDao.delete(productUnit);

	}

}


text:
<?php
header('Access-Control-Allow-Origin: *');

	mysql_connect("10.0.210.173", "moha","moha") or die(mysql_error()); //Connect to server
	mysql_select_db("db_e_adv") or die("Cannot connect to database"); //Connect to database

if(isset($_POST['id_chef_produit']) ){
$id_chef_produit=$_POST['id_chef_produit'];
//echo=$idDelegue;
/*$condition=" and id_user='$idDelegue'";*/
	$query="select * from user u, role r, attrib_role_user atRU, produit p, att_produit_chef atPC
where atRU.id_user=u.id_user and atRU.id_role=r.id_role
and p.id_Produit=atPC.id_Produit and atPC.id_user=u.id_user
and atRU.id_role=4 and atPC.id_user='$id_chef_produit' order by u.id_user desc";
	$reqExec=mysql_query($query);

 $users;

 while($users[]=mysql_fetch_assoc($reqExec)){

 }

$jsonEncode  = json_encode($users);
// echo "$jsonEncode";
echo "{"."\"d\"".":".$jsonEncode."}";
} else {echo "data missed";}
?>


text:
docker stop es1
docker rm es1


text:
has($name) ? 'validate invalid' : ''}} {{isset($attributes['is_required']) ? 'required' : ''}}" data-error="{{$errors->first($name)}}">{{$label}}

        @foreach ($values as $key => $value)

                {{ \Form::CheckBox($name, $key, $key===$selected_value ? true : false,array_merge($attributes,['id'=>$name.$key]))}}
                {{ \Form::label($name.$key, $value.' ') }}

        @endforeach


text:
title: "Deploy Sensu"
description: "Deploy Sensu, the flexible observability pipeline built to ease operator burden and meet the challenges of monitoring multi-cloud and ephemeral infrastructure."
product: "Sensu Go"
version: "6.3"
weight: 10
layout: "single"
toc: true
menu:
  sensu-go-6.3:
    parent: operations
    identifier: deploy-sensu
---

Use the information and instructions in the Deploy Sensu category to plan, install, configure, and deploy Sensu's flexible monitoring and observability pipeline.

## Plan your Sensu deployment

Find Sensu agent and backend requirements and networking and cloud recommendations in the [hardware requirements][1].

[Deployment architecture for Sensu][2] describes planning considerations and recommendations for a production-ready Sensu deployment, along with communication security details and diagrams showing single, clustered, and large-scale deployment architectures.

## Install Sensu

When you're ready to start using Sensu, the pathway you follow will depend on your monitoring and observability needs.
No matter which pathway you choose, you should begin with the [Install Sensu][3] guide.
If you just want to use Sensu locally, you can do that by installing Sensu according to the steps in the guide.
You can also use the Install Sensu guide to set up proof-of-concept and testing in a development environment.

## Deploy Sensu in production

To deploy Sensu for use outside of a local development environment, [install Sensu][3] and follow these guides to achieve a production-ready installation:

1. [Generate certificates][4], which you will need to secure a Sensu cluster and its agents.
2. [Secure your Sensu installation][5] using the certificates you generate to make Sensu production-ready.
3. [Run a Sensu cluster][6], a group of three or more sensu-backend nodes connected to a shared database, to improve Sensu's availability, reliability, and durability.
4. [Reach multi-cluster visibility][7] with federation so you can gain visibility into the health of your infrastructure and services across multiple distinct Sensu instances within a single web UI and mirror your changes in one cluster to follower clusters.

Read the [etcd replicators reference][9] to learn how the etcd-replicators datatype in the enterprise/federation/v1 API allows you to manage role-based access control (RBAC) resources in one place and mirror your changes to follower clusters.

## Scale your Sensu implementation

As the number of entities and checks in your Sensu implementation grows, so does the rate of events being written to the datastore.
In clustered etcd deployments, each event must be replicated to each cluster member, which increases network and disk IO utilization.

Sensu's Enterprise datastore allows you to configure an external PostgreSQL instance for event storage so you can [scale your monitoring and observability workflows][13] beyond etcd's 8GB limit.
Scale your Sensu implementation to many thousands of events per second, achieve much higher rates of event processing, and minimize the replication communication between etcd peers.

Read the [datastore reference][14] for the Enterprise datastore requirements and specifications.

For deployments at scale, [configuration management tools][12] can help ensure repeatable Sensu deployments and consistent configuration among Sensu backends.
Ansible, Chef, and Puppet have well-defined Sensu modules to help you get started.

[1]: hardware-requirements/
[2]: deployment-architecture/
[3]: install-sensu/
[4]: generate-certificates/
[5]: secure-sensu/
[6]: cluster-sensu/
[7]: use-federation/
[8]: scale-event-storage/
[9]: etcdreplicators/
[12]: configuration-management/
[13]: scale-event-storage/
[14]: datastore/


text:
<?php

namespace Symfony\Component\Messenger\Bridge\Redis\Transport;

/**
 * Allow to delay connection to Redis Cluster.
 *
 * @author Johann Pardanaud <johann@pardanaud.com>
 *
 * @internal
 */
class RedisClusterProxy
{
    private ?\RedisCluster $redis;
    private \Closure $initializer;
    private bool $ready = false;

    public function __construct(?\RedisCluster $redis, \Closure $initializer)
    {
        $this->redis = $redis;
        $this->initializer = $initializer;
    }

    public function __call(string $method, array $args)
    {
        if (!$this->ready) {
            $this->redis = $this->initializer->__invoke($this->redis);
            $this->ready = true;
        }

        return $this->redis->{$method}(...$args);
    }
}


text:
[![Build Status](https://img.shields.io/travis/docksal/docksal.svg?style=flat-square)](https://travis-ci.org/docksal/docksal)
[![Docs](https://readthedocs.org/projects/docksal/badge?version=master&style=flat-square)](http://docksal.readthedocs.io/en/master)
[![Gitter](https://img.shields.io/gitter/room/docksal/community-support.svg?style=flat-square)](https://gitter.im/docksal/community-support)

Docker and Docker Compose based environments for web development.

    Docksal is still under active development. Breaking changes and outdated docs are very possible.
    Please help us by testing, submitting issues and PRs. Thanks!

Running a complete LAMP stack with Drupal, WordPress or a pure HTML/PHP base website is two commands away!*

```
git clone <sample-project-repo>
fin init
```

Try one of the preconfigured projects:

- [Drupal 7 sample project](https://github.com/docksal/drupal7)
- [Drupal 8 sample project](https://github.com/docksal/drupal8)
- [WordPress sample project](https://github.com/docksal/wordpress)

*Once you are done with a one-time [Docksal environment setup](/docs/env-setup.md)

## Docksal Setup

Please review [system requirements](/docs/system-requirements.md) before proceeding with the setup.

**1. [Install required software](/docs/env-setup.md)**

**2. [Create a Docksal powered project](/docs/project-setup.md)**

## Docksal Fin and stack

Docksal Fin is a command line tool to control Docksal's stack. `fin` runs natively on Mac and Linux and requires [Babun Shell](http://babun.github.io) on Windows.

Each project contains at least 3 services:

- `web` - holds your webserver (nginx/apache/etc.)
- `db` - holds database server (MySQL)
- `cli` - container that is meant to serve as a single console access point to all necessary command line tools. You can access it with `fin bash`. For the list of tools available inside **cli** check [CLI image docs](https://github.com/docksal/service-cli)

[Docksal Stack documentation](/docs/docksal-stack.md)

## Updating Docksal

```
fin update
```

[How to update from Drude to Docksal](/docs/update-dde.md)

## Tutorials

### Advanced configuration
- [Running multiple projects](/docs/multiple-projects.md)
- [Drupal settings (database, file permissions)](/docs/drupal-settings.md)
- [MySQL DB access for external tools](/docs/db-access.md)
- [Overriding default PHP/MySQL/etc. settings](/docs/settings.md)
- [Automatic database import](docs/db-import.md)
- [DB sandbox mode](/docs/db-sandbox.md)
- [Extending fin with custom commands](/docs/custom-commands.md)
- [Increasing vm memory (RAM)](/docs/vm.md)
- [Exposing any Docker container's port](/docs/expose-port.md)
- [Using Docker for Mac/Win](/docs/env-setup-native.md)
- [Customize project configuration or switch PHP/MySQL version](/docs/project-customize.md)

### Utililies
- [Debugging with Xdebug and PhpStorm](/docs/xdebug.md)
- [Using custom ssh keys (with or without passwords) via ssh-agent](/docs/ssh-agent.md)
- [Sending and capturing e-mail](/docs/mail.md)
- [SASS/Compass](/docs/sass.md)
- [PHP Code Sniffer (phpcs, phpcbf)](/docs/phpcs.md)
- [Varnish](/docs/varnish.md)
- [Memcached](/docs/memcached.md)
- [Apache Solr](/docs/apache-solr.md)
- [Blackfire profiler](/docs/blackfire.md)
- [Behat](/docs/behat.md)
- [Public access via ngrok](/docs/public-access.md)

## Troubleshooting

If something went wrong, first try these quick fix steps in the order listed below.
Check if the issue has cleared out **after each step**.

- Update Docksal to the latest version. See [updates](#updates) section.
- (Mac and Windows) Restart the Docksal VM: `fin vm restart`
- Reset Docksal system services with `fin reset system` and restart projects containers with `fin up`
- Reboot the host (your computer or remote server)
- (Mac and Windows) Re-create Docksal VM: `fin vm remove` then `fin vm start` (**WARNING**: backup your DB data before doing this)

If quick fixes above did not help, try:

- checking [troubleshooting doc](docs/troubleshooting.md) for rare problems that might occur
- searching the [GitHub issue queue](https://github.com/docksal/docksal/issues). Others may have experienced same or a similar issue and have already found a solution or a workaround.
- asking community for support in our Gitter room [![Gitter](https://img.shields.io/gitter/room/docksal/community-support.svg?style=flat-square)](https://gitter.im/docksal/community-support)

Create a new issue if your problem is still not resolved.

## Uninstallation

The steps below will remove the Docksal VM and cleanup Docksal stuff.

```
fin vm remove
rm -rf ~/.docksal
rm -f /usr/local/bin/fin
```

Docker for Mac/Windows and VirtualBox are not automatically removed. You can remove them manually on Mac or use uninstaller on Windows.

To remove Docker on Ubuntu Linux you need to:

1. Follow [Docker Uninstallation](https://docs.docker.com/engine/installation/linux/ubuntulinux/#/uninstallation) instruction
2. Cleanup tools:
```
sudo rm /usr/local/bin/docker-compose
sudo rm /usr/local/bin/docker-machine
```


text:
module Integration where

import TestImport
import IntegrationImport

main :: IO ()
main = hspec spec

spec :: Spec
spec = do
    user <- runIO $ runApp $ \app -> do
        wipeDB app
        runDBWithApp app $ createUser "1"

    describe "logging in to create a comment" $ session "" $ using Firefox $ do
        it "loads carnival" $ runWD $ do
            openPage "http://localhost:3000"

            clickOn $ ByCSS ".carnival-comment-indicator"
            clickOn $ ByCSS ".carnival-create"

            inModal $
                submit =<< fillIn (ByName "ident") (userIdent $ entityVal user)

            submit =<< fillIn (ByCSS ".carnival-body") "a comment"

            openPage "http://localhost:3000"
            clickOn $ ByCSS ".carnival-comment-indicator"
            clickOn $ ByCSS ".carnival-create"

            waitForText (ByCSS ".carnival-comment .carnival-body")
                `shouldReturn` "a comment"


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

@Component({
  selector: 'page-not-found',
  styles: [`

  `],
  template: `

404 - Page Not Found

  `
})
export class NotFoundPageComponent  {

}


text:
using Acme.Helpers.Core.Extensions;
using Acme.Helpers.Core.Library;
using System;
using System.Collections.Generic;

namespace Acme.Helpers.Demo.Internal
{
    /// <exclude />
    internal static class ShieldGenerator
    {
        /// <exclude />
        private static IDictionary<ShieldType, string> GithubForkmeMask
        {
            get
            {
                return new Dictionary<ShieldType, string>()
                {
                    { ShieldType.BowerVersion, "https://img.shields.io/bower/v/{subject}.svg" },
                    { ShieldType.NodeVersion, "https://img.shields.io/node/v/{subject}.svg" },
                    { ShieldType.GithubTag, "https://img.shields.io/github/tag/{subject}.{image}" },
                    { ShieldType.GithubRelease, "https://img.shields.io/github/release/{subject}.{image}" },
                    { ShieldType.NugetVersion, "https://img.shields.io/nuget/v/{subject}.{image}" },
                    { ShieldType.NugetPreRelease, "https://img.shields.io/nuget/vpre/{subject}.{image}" },
                    { ShieldType.GithubIssues, "https://img.shields.io/github/issues/{subject}.{image}" },
                    { ShieldType.GithubForks, "https://img.shields.io/github/forks/{subject}.{image}" },
                    { ShieldType.GithubStars, "https://img.shields.io/github/stars/{subject}.{image}" },
                    { ShieldType.GithubFollowers, "https://img.shields.io/github/stars/{subject}.{image}" },
                };
            }
        }

        /// <exclude />
        public static FluentTagBuilder GenerateShieldMarkup(string subject, ShieldType? type = null, string status = null, ShieldColor color = ShieldColor.Green, ShieldStyle style = ShieldStyle.Flat, ShieldImage image = ShieldImage.Png)
        {
            string url;
            subject = subject.Split(' ')[0];
            if (type == null)
                url = Substitute("https://img.shields.io/badge/{subject}-{status}-{color}.{image}", subject.Replace("-", ""), status, color, image, style);
            else
                url = Substitute(GithubForkmeMask[(ShieldType)type], subject, status, color, image, style);

            return new FluentTagBuilder().Tag("img", null, new { src = url });
        }

        /// <exclude />
        private static string Substitute(string url, string subject, string status, ShieldColor? color, ShieldImage? image, ShieldStyle? style)
        {
            var newUrl = url
                .Replace("{subject}", subject as string)
                .Replace("{status}", status as string)
                .Replace("{color}", color.ToStr())
                .Replace("{image}", image.ToStr());
            if (style != ShieldStyle.Flat)
                newUrl += string.Format("?style={0}", style.ToStr());
            return newUrl;
        }

        /// <exclude />
        private static string ToStr(this Enum e)
        {
            if (e == null) return string.Empty;
            return Enum.GetName(e.GetType(), e).SplitCamelCaseLower();
        }
    }
}


text:
layout: post
title: dropit小游戏实现
date: 2016-10-9
categories: blog
tags: [IOS]
description: IOS之dropit小游戏
---

**本文主要包括以下内容**

1. Unwind Segues, Alerts, Timers
2. Dynamic Animation
3. dropit小游戏实例

#### Unwind Segues, Alerts, Timers

**Unwind**
Unwind Segue不会像其他Segue一样创建一个新的MVC

**Alerts/Action Sheets**
如何添加Alerts/Action Sheets

1.创建button
2.调用UIAlertController
3.addAction
4.调用presentViewController显示Alerts/Action Sheets

这次在之前CassiniDEMO中加入了Alerts和Action Sheets.
点进Cassini后点击"Redeploy"弹出Action Sheets.
在Action Sheets中"Orbit Saturn"栏中实现了点击跳出Alerts的功能

```
具体代码如下:

    @IBOutlet weak var redeploy: UIBarButtonItem!
    @IBAction func redeploy(sender: UIBarButtonItem) {
        //创建actionSheet
        let actionSheet = UIAlertController(title: "Redeploy", message: "Issue commands to Cassini'sguidance system.", preferredStyle: UIAlertControllerStyle.ActionSheet)
        //添加Action
        actionSheet.addAction(UIAlertAction(title: "Orbit Saturn", style: UIAlertActionStyle.Default, handler: { (action: UIAlertAction) -> Void in
            //此处实现了,点击Orbit Saturn后跳出Alert
            let alert1 = UIAlertController(title: "Login Required", message: "Please enter your Cassini guidance system...", preferredStyle: UIAlertControllerStyle.Alert)//创建Alert
            //添加Action
            alert1.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
            alert1.addAction(UIAlertAction(title: "Login", style: UIAlertActionStyle.Default, handler: nil))
            //给Alert添加一个TextField
            alert1.addTextFieldWithConfigurationHandler { (textField) in
                textField.placeholder = "Guidance System Password"
            }

            //显示TextField
            self.presentViewController(alert1, animated: true, completion: nil)

        }))

        actionSheet.addAction(UIAlertAction(title: "Explore Titan", style: UIAlertActionStyle.Default, handler: nil))

        actionSheet.addAction(UIAlertAction(title: "Closeup of Sun", style: UIAlertActionStyle.Destructive, handler: nil))

        actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))

        //以下三行代码用于iPad已POPover的形式显示ActionSheets.在iPhone上不需要
        actionSheet.modalPresentationStyle = .Popover
        let ppc = actionSheet.popoverPresentationController
        ppc?.barButtonItem = redeploy

        //显示actionSheet
        presentViewController(actionSheet, animated: true, completion: nil)
    }

```

#### Animation

**iOS中动画的分类**

1.UIView Animation(视图属性的动画)
2.Animation of View Controller transitions(viewController转场动画)
3.Core Animation
4.Dynamic Animation(基于物理引擎的动画)

**UIView Animation**

- 在其中我们主要能够使用三种属性,分别为:frame(意味着可移动);transform(意味着可旋转);alpha(意味着可改变透明度)
- 使用:class func animateWithDuration(durationL NSTimeInterval, delay: NSTimerInterval, options: UIViewAnimationOptions, animations: () -> Void, completion: ((finished: Bool) -> Void)?)

**Dynamic Animation**

如何使用Dynamic Animation
1.创建UIDynamicAnimator实例 var animator = UIDynamicAnimator(referenceView: UIView)
2.添加UIDynamicBehaviors,如gravity,collisions等 let gravity = UIGravityBehavior()
animation.addBehavior(gravity)
3.添加UIDynamicItem let item1: UIDynamicItem = ...// usually a UIView
gravity.addItem(item1)

**Behaviors**
1.UIGravityBehavior有两个重要属性var angle: CGFloat  //重力的角度     var magnitude: CGFloat  //重力加速度
2.UIAttachmentBehavior
3.UICollisionBehavior碰撞效果
4.UISnapBehavior震荡效果
5.UIPushBehavior把物体推向特定角度,速度恒定,可食一次性的效果,也可是持续效果
6.UIDynamicItemBehavior控制对象之间如何交互

#### DropitDEMO

![](https://raw.githubusercontent.com/whuhan2013/ImageRepertory/master/ios/p16.png)

```
import UIKit

class dropitViewController: UIViewController,UIDynamicAnimatorDelegate {

    @IBOutlet weak var gameView: BezierPathsView!

    //创建DynamicAnimator
    lazy var animator: UIDynamicAnimator = {
        let lazilyCreatedDynamicAnimator = UIDynamicAnimator(referenceView: self.gameView)
        lazilyCreatedDynamicAnimator.delegate = self
        return lazilyCreatedDynamicAnimator
    }()

    //创建集成了三个Behavior的DropBehavior的实例
    var dropitBehavior = DropBehavior()

    var attachment: UIAttachmentBehavior? {
        willSet {
            animator.removeBehavior(attachment!)
            gameView.setPath(nil, named: PathNames.Attachment)
        }
        didSet {
            if attachment != nil {
                animator.addBehavior(attachment!)
                attachment?.action = { [unowned self] in
                    if let attacheView = self.attachment?.items.first as? UIView {
                        let path = UIBezierPath()
                        path.moveToPoint(self.attachment!.anchorPoint)
                        path.addLineToPoint(attacheView.center)
                        self.gameView.setPath(path, named: PathNames.Attachment)
                    }
                }
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        animator.addBehavior(dropitBehavior)
    }

    struct PathNames {
        static let MiddleBarrier = "Middle Barrier"
        static let Attachment = "Attachment"
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let barrierSize = dropSize
        let barrierOrigin = CGPoint(x: gameView.bounds.midX - barrierSize.width / 2, y: gameView.bounds.midY - barrierSize.height / 2)
        //设置圆圈的边界
        let path = UIBezierPath(ovalInRect: CGRect(origin: barrierOrigin, size: barrierSize))
        dropitBehavior.addBarrier(path, named: PathNames.MiddleBarrier)

        gameView.setPath(path, named: PathNames.MiddleBarrier)
    }

    //UIDynamicAnimatorDelegate中的方法,当动画停止时
    func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
        removeCompletedRow()
    }

    var dropsPerRow = 10
    //设置方块的形状
    var dropSize: CGSize {
        let size = gameView.bounds.width / CGFloat(dropsPerRow)
        return CGSize(width: size, height: size)
    }

    //设置手势
    @IBAction func drop(sender: UITapGestureRecognizer) {
        drop()
    }

    var lastDroppedView: UIView?

    //掉落方法
    func drop() {
        //设置方块的初始位置及大小
        var frame = CGRect(origin: CGPointZero, size: dropSize)
        frame.origin.x = CGFloat.random(dropsPerRow) * dropSize.width

        //创建方块视图,并设置其颜色
        let dropView = UIView(frame: frame)
        dropView.backgroundColor = UIColor.random

        lastDroppedView = dropView

        dropitBehavior.addDrop(dropView)
    }

    @IBAction func grabDrop(sender: UIPanGestureRecognizer) {
        let gesturePoint = sender.locationInView(gameView)

        switch sender.state {
        case .Began:
            if let viewToAttachTo = lastDroppedView {
                attachment = UIAttachmentBehavior(item: viewToAttachTo, attachedToAnchor: gesturePoint)
                lastDroppedView = nil
            }
        case .Changed:
            attachment?.anchorPoint = gesturePoint
        case .Ended:
            attachment = nil
        default: break
        }

    }

    //当满行后消除方块
    func removeCompletedRow() {
        var dropsToRemove = [UIView]()
        var dropFrame = CGRect(x: 0, y: gameView.frame.maxY, width: dropSize.width, height: dropSize.height)

        repeat {
            dropFrame.origin.y -= dropSize.height
            dropFrame.origin.x = 0
            var dropsFound = [UIView]()
            var rowIsComplete = true
            for _ in 0 ..< dropsPerRow {
                if let hitView = gameView.hitTest(CGPoint(x: dropFrame.midX, y: dropFrame.midY), withEvent: nil) {
                    if hitView.superview == gameView {
                        dropsFound.append(hitView)
                    } else {
                        rowIsComplete = false
                    }
                }
                dropFrame.origin.x += dropSize.width            }
            if rowIsComplete {
                dropsToRemove += dropsFound
            }
        } while dropsToRemove.count == 0 && dropFrame.origin.y > 0

        for drop in dropsToRemove {
            dropitBehavior.removeDrop(drop)
        }
    }

}

private extension CGFloat {
    static func random(max:Int) -> CGFloat {
        return CGFloat(arc4random() % UInt32(max))
    }
}

private extension UIColor {
    class var random:UIColor {
        switch arc4random() % 5 {
        case 0: return UIColor.greenColor()
        case 1: return UIColor.blueColor()
        case 2: return UIColor.orangeColor()
        case 3: return UIColor.redColor()
        case 4: return UIColor.purpleColor()
        default: return UIColor.blackColor()
        }
    }
}
```

```
import UIKit

class dropitViewController: UIViewController,UIDynamicAnimatorDelegate {

    @IBOutlet weak var gameView: BezierPathsView!

    //创建DynamicAnimator
    lazy var animator: UIDynamicAnimator = {
        let lazilyCreatedDynamicAnimator = UIDynamicAnimator(referenceView: self.gameView)
        lazilyCreatedDynamicAnimator.delegate = self
        return lazilyCreatedDynamicAnimator
    }()

    //创建集成了三个Behavior的DropBehavior的实例
    var dropitBehavior = DropBehavior()

    var attachment: UIAttachmentBehavior? {
        willSet {
            animator.removeBehavior(attachment!)
            gameView.setPath(nil, named: PathNames.Attachment)
        }
        didSet {
            if attachment != nil {
                animator.addBehavior(attachment!)
                attachment?.action = { [unowned self] in
                    if let attacheView = self.attachment?.items.first as? UIView {
                        let path = UIBezierPath()
                        path.moveToPoint(self.attachment!.anchorPoint)
                        path.addLineToPoint(attacheView.center)
                        self.gameView.setPath(path, named: PathNames.Attachment)
                    }
                }
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        animator.addBehavior(dropitBehavior)
    }

    struct PathNames {
        static let MiddleBarrier = "Middle Barrier"
        static let Attachment = "Attachment"
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let barrierSize = dropSize
        let barrierOrigin = CGPoint(x: gameView.bounds.midX - barrierSize.width / 2, y: gameView.bounds.midY - barrierSize.height / 2)
        //设置圆圈的边界
        let path = UIBezierPath(ovalInRect: CGRect(origin: barrierOrigin, size: barrierSize))
        dropitBehavior.addBarrier(path, named: PathNames.MiddleBarrier)

        gameView.setPath(path, named: PathNames.MiddleBarrier)
    }

    //UIDynamicAnimatorDelegate中的方法,当动画停止时
    func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
        removeCompletedRow()
    }

    var dropsPerRow = 10
    //设置方块的形状
    var dropSize: CGSize {
        let size = gameView.bounds.width / CGFloat(dropsPerRow)
        return CGSize(width: size, height: size)
    }

    //设置手势
    @IBAction func drop(sender: UITapGestureRecognizer) {
        drop()
    }

    var lastDroppedView: UIView?

    //掉落方法
    func drop() {
        //设置方块的初始位置及大小
        var frame = CGRect(origin: CGPointZero, size: dropSize)
        frame.origin.x = CGFloat.random(dropsPerRow) * dropSize.width

        //创建方块视图,并设置其颜色
        let dropView = UIView(frame: frame)
        dropView.backgroundColor = UIColor.random

        lastDroppedView = dropView

        dropitBehavior.addDrop(dropView)
    }

    @IBAction func grabDrop(sender: UIPanGestureRecognizer) {
        let gesturePoint = sender.locationInView(gameView)

        switch sender.state {
        case .Began:
            if let viewToAttachTo = lastDroppedView {
                attachment = UIAttachmentBehavior(item: viewToAttachTo, attachedToAnchor: gesturePoint)
                lastDroppedView = nil
            }
        case .Changed:
            attachment?.anchorPoint = gesturePoint
        case .Ended:
            attachment = nil
        default: break
        }

    }

    //当满行后消除方块
    func removeCompletedRow() {
        var dropsToRemove = [UIView]()
        var dropFrame = CGRect(x: 0, y: gameView.frame.maxY, width: dropSize.width, height: dropSize.height)

        repeat {
            dropFrame.origin.y -= dropSize.height
            dropFrame.origin.x = 0
            var dropsFound = [UIView]()
            var rowIsComplete = true
            for _ in 0 ..< dropsPerRow {
                if let hitView = gameView.hitTest(CGPoint(x: dropFrame.midX, y: dropFrame.midY), withEvent: nil) {
                    if hitView.superview == gameView {
                        dropsFound.append(hitView)
                    } else {
                        rowIsComplete = false
                    }
                }
                dropFrame.origin.x += dropSize.width            }
            if rowIsComplete {
                dropsToRemove += dropsFound
            }
        } while dropsToRemove.count == 0 && dropFrame.origin.y > 0

        for drop in dropsToRemove {
            dropitBehavior.removeDrop(drop)
        }
    }

}

private extension CGFloat {
    static func random(max:Int) -> CGFloat {
        return CGFloat(arc4random() % UInt32(max))
    }
}

private extension UIColor {
    class var random:UIColor {
        switch arc4random() % 5 {
        case 0: return UIColor.greenColor()
        case 1: return UIColor.blueColor()
        case 2: return UIColor.orangeColor()
        case 3: return UIColor.redColor()
        case 4: return UIColor.purpleColor()
        default: return UIColor.blackColor()
        }
    }
}
```

```
import UIKit

class BezierPathsView: UIView {

    private var bezierPath = [String: UIBezierPath]()

    func setPath(path: UIBezierPath?, named name: String) {
        bezierPath[name] = path
        setNeedsDisplay()
    }

    override func drawRect(rect: CGRect) {
        for (_,path) in bezierPath {
            path.stroke()
        }
    }

}
```

**参考链接:**[Stanford CS193p iOS开发课程笔记(十)](http://www.jianshu.com/p/3ac404544928)

**源码:** [Dropit](https://github.com/whuhan2013/IOSProject/tree/master/Dropit)

**效果如下**

![](https://raw.githubusercontent.com/whuhan2013/ImageRepertory/master/ios/p17.png)

![](https://raw.githubusercontent.com/whuhan2013/ImageRepertory/master/ios/p18.png)


text:
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('workshops', '0009_auto_20161017_0059'),
    ]

    operations = [
        migrations.AlterField(
            model_name='workshop',
            name='number_of_volunteers',
            field=models.PositiveSmallIntegerField(default=0, null=True, blank=True),
        ),
    ]


text:
namespace {

// Mode of size 6x4.
const drmModeModeInfo kDefaultMode =
    {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}};

const gfx::AcceleratedWidget kDefaultWidgetHandle = 1;
const uint32_t kDefaultCrtc = 1;
const uint32_t kDefaultConnector = 2;
const uint32_t kSecondaryCrtc = 3;
const uint32_t kSecondaryConnector = 4;
const size_t kPlanesPerCrtc = 1;

}  // namespace

class DrmOverlayValidatorTest : public testing::Test {
 public:
  DrmOverlayValidatorTest() {}

  void SetUp() override;
  void TearDown() override;

  void OnSwapBuffers(gfx::SwapResult result) {
    on_swap_buffers_count_++;
    last_swap_buffers_result_ = result;
  }

  scoped_refptr<ui::ScanoutBuffer> ProcessBuffer(const gfx::Size& size,
                                                 uint32_t format) {
    gfx::BufferFormat buffer_format =
        ui::GetBufferFormatFromFourCCFormat(format);
    return buffer_generator_->Create(drm_, buffer_format, size);
  }

  scoped_refptr<ui::ScanoutBuffer> ReturnNullBuffer(const gfx::Size& size,
                                                    uint32_t format) {
    return nullptr;
  }

 protected:
  scoped_ptr<base::MessageLoop> message_loop_;
  scoped_refptr<ui::MockDrmDevice> drm_;
  scoped_ptr<ui::MockScanoutBufferGenerator> buffer_generator_;
  scoped_ptr<ui::ScreenManager> screen_manager_;
  scoped_ptr<ui::DrmDeviceManager> drm_device_manager_;
  ui::MockHardwareDisplayPlaneManager* plane_manager_;
  ui::DrmWindow* window_;
  scoped_ptr<ui::DrmOverlayValidator> overlay_validator_;
  std::vector<ui::OverlayCheck_Params> overlay_params_;
  ui::OverlayPlaneList plane_list_;
  ui::OverlayPlane::ProcessBufferCallback process_buffer_handler_;

  int on_swap_buffers_count_;
  gfx::SwapResult last_swap_buffers_result_;
  gfx::Rect overlay_rect_;
  gfx::Rect primary_rect_;

 private:
  DISALLOW_COPY_AND_ASSIGN(DrmOverlayValidatorTest);
};

void DrmOverlayValidatorTest::SetUp() {
  on_swap_buffers_count_ = 0;
  last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED;
  process_buffer_handler_ = base::Bind(&DrmOverlayValidatorTest::ProcessBuffer,
                                       base::Unretained(this));

  message_loop_.reset(new base::MessageLoopForUI);
  std::vector<uint32_t> crtcs;
  crtcs.push_back(kDefaultCrtc);
  drm_ = new ui::MockDrmDevice(false, crtcs, kPlanesPerCrtc);
  buffer_generator_.reset(new ui::MockScanoutBufferGenerator());
  screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get()));
  screen_manager_->AddDisplayController(drm_, kDefaultCrtc, kDefaultConnector);
  screen_manager_->ConfigureDisplayController(
      drm_, kDefaultCrtc, kDefaultConnector, gfx::Point(), kDefaultMode);

  drm_device_manager_.reset(new ui::DrmDeviceManager(nullptr));

  scoped_ptr<ui::DrmWindow> window(new ui::DrmWindow(
      kDefaultWidgetHandle, drm_device_manager_.get(), screen_manager_.get()));
  window->Initialize(buffer_generator_.get());
  window->SetBounds(
      gfx::Rect(gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay)));
  screen_manager_->AddWindow(kDefaultWidgetHandle, std::move(window));
  plane_manager_ =
      static_cast<ui::MockHardwareDisplayPlaneManager*>(drm_->plane_manager());
  window_ = screen_manager_->GetWindow(kDefaultWidgetHandle);
  overlay_validator_.reset(
      new ui::DrmOverlayValidator(window_, buffer_generator_.get()));

  overlay_rect_ =
      gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2);

  primary_rect_ = gfx::Rect(0, 0, kDefaultMode.hdisplay, kDefaultMode.vdisplay);

  ui::OverlayCheck_Params primary_candidate;
  primary_candidate.buffer_size = primary_rect_.size();
  primary_candidate.display_rect = primary_rect_;
  overlay_params_.push_back(primary_candidate);

  ui::OverlayCheck_Params overlay_candidate;
  overlay_candidate.buffer_size = overlay_rect_.size();
  overlay_candidate.display_rect = overlay_rect_;
  overlay_candidate.plane_z_order = 1;
  overlay_params_.push_back(overlay_candidate);

  scoped_refptr<ui::DrmDevice> drm =
      window_->GetController()->GetAllocationDrmDevice();
  for (const auto& param : overlay_params_) {
    scoped_refptr<ui::ScanoutBuffer> scanout_buffer =
        buffer_generator_->Create(drm, param.format, param.buffer_size);
    ui::OverlayPlane plane(std::move(scanout_buffer), param.plane_z_order,
                           param.transform, param.display_rect, param.crop_rect,
                           process_buffer_handler_);
    plane_list_.push_back(plane);
  }
}

void DrmOverlayValidatorTest::TearDown() {
  scoped_ptr<ui::DrmWindow> window =
      screen_manager_->RemoveWindow(kDefaultWidgetHandle);
  window->Shutdown();
  message_loop_.reset();
}

TEST_F(DrmOverlayValidatorTest, WindowWithNoController) {
  // We should never promote layers to overlay when controller is not
  // present.
  ui::HardwareDisplayController* controller = window_->GetController();
  window_->SetController(nullptr);
  std::vector<ui::OverlayCheck_Params> validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  EXPECT_EQ(false, validated_params.front().is_overlay_candidate);
  EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
  window_->SetController(controller);
}

TEST_F(DrmOverlayValidatorTest, DontPromoteMoreLayersThanAvailablePlanes) {
  std::vector<ui::OverlayCheck_Params> validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  EXPECT_EQ(true, validated_params.front().is_overlay_candidate);
  EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
}

TEST_F(DrmOverlayValidatorTest, DontCollapseOverlayToPrimaryInFullScreen) {
  // Overlay Validator should not collapse planes during validation.
  overlay_params_.back().buffer_size = primary_rect_.size();
  overlay_params_.back().display_rect = primary_rect_;
  plane_list_.back().display_bounds = primary_rect_;

  std::vector<ui::OverlayCheck_Params> validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  // Second candidate should be marked as Invalid as we have only one plane
  // per CRTC.
  EXPECT_EQ(true, validated_params.front().is_overlay_candidate);
  EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
}

TEST_F(DrmOverlayValidatorTest, ClearCacheOnReset) {
  // This test checks if we invalidate cache when Reset is called.
  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;
  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};

  ui::FakePlaneInfo primary_plane_info(
      100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
  ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());

  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_UYVY,
            plane_list.back().buffer->GetFramebufferPixelFormat());
  // Check if ClearCache actually clears the cache.
  overlay_validator_->ClearCache();
  plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  // There should be no entry in cache for this configuration and should return
  // default value of DRM_FORMAT_XRGB8888.
  EXPECT_EQ(DRM_FORMAT_XRGB8888,
            plane_list.back().buffer->GetFramebufferPixelFormat());
}

TEST_F(DrmOverlayValidatorTest, OptimalFormatForOverlayInFullScreen_XRGB) {
  // Optimal format for Overlay configuration should be XRGB, when primary plane
  // supports only XRGB and overlay obscures primary.
  overlay_params_.back().buffer_size = primary_rect_.size();
  overlay_params_.back().display_rect = primary_rect_;
  plane_list_.back().display_bounds = primary_rect_;

  // Check optimal format for Overlay.
  ui::FakePlaneInfo primary_plane_info(
      100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};
  ui::FakePlaneInfo plane_info(101, 1 << 0, xrgb_yuv_packed_formats);

  std::vector<ui::FakePlaneInfo> planes{primary_plane_info, plane_info};
  plane_manager_->SetPlaneProperties(planes);
  overlay_validator_->ClearCache();

  overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_XRGB8888,
            plane_list.back().buffer->GetFramebufferPixelFormat());
}

TEST_F(DrmOverlayValidatorTest, OptimalFormatForOverlayInFullScreen_YUV) {
  overlay_params_.back().buffer_size = primary_rect_.size();
  overlay_params_.back().display_rect = primary_rect_;
  plane_list_.back().display_bounds = primary_rect_;
  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};

  // We should prefer YUV when primary can support it.
  ui::FakePlaneInfo primary_plane_info(100, 1 << 0, xrgb_yuv_packed_formats);
  ui::FakePlaneInfo plane_info(101, 1 << 0, xrgb_yuv_packed_formats);

  std::vector<ui::FakePlaneInfo> planes{primary_plane_info, plane_info};
  plane_manager_->SetPlaneProperties(planes);
  overlay_validator_->ClearCache();

  overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
#if defined(USE_DRM_ATOMIC)
  EXPECT_EQ(DRM_FORMAT_UYVY,
            plane_list.back().buffer->GetFramebufferPixelFormat());
#else
  // If Atomic support is disabled, ensure we choose DRM_FORMAT_XRGB8888 as the
  // optimal format even if other packed formats are supported by Primary.
  EXPECT_EQ(DRM_FORMAT_XRGB8888,
            plane_list.back().buffer->GetFramebufferPixelFormat());
#endif
}

TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat_YUV) {
  plane_manager_->ResetPlaneCount();
  // This test checks for optimal format in case of non full screen video case.
  // Prefer YUV as optimal format when Overlay supports it.
  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;

  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};
  ui::FakePlaneInfo primary_plane_info(
      100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
  ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  std::vector<ui::OverlayCheck_Params> validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());

  for (const auto& param : validated_params)
    EXPECT_EQ(true, param.is_overlay_candidate);

  EXPECT_EQ(5, plane_manager_->plane_count());

  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_UYVY,
            plane_list.back().buffer->GetFramebufferPixelFormat());
}

TEST_F(DrmOverlayValidatorTest, OverlayPreferredFormat_XRGB) {
  plane_manager_->ResetPlaneCount();
  // This test checks for optimal format in case of non full screen video case.
  // This should be XRGB when overlay doesn't support YUV.
  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;

  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};
  ui::FakePlaneInfo primary_plane_info(100, 1 << 0, xrgb_yuv_packed_formats);
  ui::FakePlaneInfo overlay_info(101, 1 << 0,
                                 std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  std::vector<ui::OverlayCheck_Params> validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_XRGB8888,
            plane_list.back().buffer->GetFramebufferPixelFormat());
  EXPECT_EQ(3, plane_manager_->plane_count());
  for (const auto& param : validated_params)
    EXPECT_EQ(true, param.is_overlay_candidate);
}

TEST_F(DrmOverlayValidatorTest, RejectYUVBuffersIfNotSupported) {
  plane_manager_->ResetPlaneCount();
  // Check case where buffer storage format is already UYVY but planes dont
  // support it.
  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;

  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};
  ui::FakePlaneInfo primary_plane_info(100, 1 << 0, xrgb_yuv_packed_formats);
  ui::FakePlaneInfo overlay_info(101, 1 << 0,
                                 std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  std::vector<ui::OverlayCheck_Params> validated_params = overlay_params_;
  validated_params.back().format = gfx::BufferFormat::UYVY_422;
  plane_manager_->ResetPlaneCount();
  validated_params = overlay_validator_->TestPageFlip(validated_params,
                                                      ui::OverlayPlaneList());

  EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
}

TEST_F(DrmOverlayValidatorTest,
       RejectYUVBuffersIfNotSupported_MirroredControllers) {
  std::vector<uint32_t> crtcs{kDefaultCrtc, kSecondaryCrtc};
  plane_manager_->SetCrtcInfo(crtcs);

  std::vector<uint32_t> only_rgb_format{DRM_FORMAT_XRGB8888};
  std::vector<uint32_t> xrgb_yuv_packed_formats{DRM_FORMAT_XRGB8888,
                                                DRM_FORMAT_UYVY};
  ui::HardwareDisplayController* controller = window_->GetController();
  controller->AddCrtc(scoped_ptr<ui::CrtcController>(
      new ui::CrtcController(drm_.get(), kSecondaryCrtc, kSecondaryConnector)));
  ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
      new ui::MockScanoutBuffer(primary_rect_.size())));
  EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode));

  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;

  ui::FakePlaneInfo primary_crtc_primary_plane(100, 1 << 0, only_rgb_format);
  ui::FakePlaneInfo primary_crtc_overlay(101, 1 << 0, xrgb_yuv_packed_formats);
  ui::FakePlaneInfo secondary_crtc_primary_plane(102, 1 << 1, only_rgb_format);
  ui::FakePlaneInfo secondary_crtc_overlay(103, 1 << 1,
                                           xrgb_yuv_packed_formats);

  std::vector<ui::FakePlaneInfo> planes_info{
      primary_crtc_primary_plane, primary_crtc_overlay,
      secondary_crtc_primary_plane, secondary_crtc_overlay};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  std::vector<ui::OverlayCheck_Params> validated_params = overlay_params_;
  validated_params.back().format = gfx::BufferFormat::UYVY_422;
  plane_manager_->ResetPlaneCount();
  validated_params = overlay_validator_->TestPageFlip(validated_params,
                                                      ui::OverlayPlaneList());

  EXPECT_EQ(true, validated_params.back().is_overlay_candidate);

  // Both controllers have Overlay which support DRM_FORMAT_UYVY, hence this
  // should be picked as the optimal format.
  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_UYVY,
            plane_list.back().buffer->GetFramebufferPixelFormat());

  // This configuration should not be promoted to Overlay when either of the
  // controllers dont support UYVY format.

  // Check case where we dont have support for packed formats in Mirrored CRTC.
  planes_info.back().allowed_formats = only_rgb_format;
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  validated_params = overlay_validator_->TestPageFlip(validated_params,
                                                      ui::OverlayPlaneList());
  EXPECT_EQ(false, validated_params.back().is_overlay_candidate);

  // Check case where we dont have support for packed formats in primary
  // display.
  planes_info.back().allowed_formats = xrgb_yuv_packed_formats;
  planes_info[1].allowed_formats = only_rgb_format;
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  validated_params = overlay_validator_->TestPageFlip(validated_params,
                                                      ui::OverlayPlaneList());
  EXPECT_EQ(false, validated_params.back().is_overlay_candidate);
  controller->RemoveCrtc(drm_, kSecondaryCrtc);
}

TEST_F(DrmOverlayValidatorTest, OptimalFormatYUV_MirroredControllers) {
  std::vector<uint32_t> crtcs{kDefaultCrtc, kSecondaryCrtc};
  plane_manager_->SetCrtcInfo(crtcs);
  overlay_validator_->ClearCache();

  ui::HardwareDisplayController* controller = window_->GetController();
  controller->AddCrtc(scoped_ptr<ui::CrtcController>(
      new ui::CrtcController(drm_.get(), kSecondaryCrtc, kSecondaryConnector)));
  ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
      new ui::MockScanoutBuffer(primary_rect_.size())));
  EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode));

  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;
  std::vector<uint32_t> only_rgb_format = {DRM_FORMAT_XRGB8888};
  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};

  ui::FakePlaneInfo primary_crtc_primary_plane(100, 1 << 0, only_rgb_format);
  ui::FakePlaneInfo primary_crtc_overlay(101, 1 << 0, xrgb_yuv_packed_formats);
  ui::FakePlaneInfo secondary_crtc_primary_plane(102, 1 << 1, only_rgb_format);
  ui::FakePlaneInfo secondary_crtc_overlay(103, 1 << 1,
                                           xrgb_yuv_packed_formats);

  std::vector<ui::FakePlaneInfo> planes_info{
      primary_crtc_primary_plane, primary_crtc_overlay,
      secondary_crtc_primary_plane, secondary_crtc_overlay};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  plane_manager_->ResetPlaneCount();
  std::vector<ui::OverlayCheck_Params> validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());

  EXPECT_EQ(true, validated_params.back().is_overlay_candidate);
  // Both controllers have Overlay which support DRM_FORMAT_UYVY, hence this
  // should be picked as the optimal format.
  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_UYVY,
            plane_list.back().buffer->GetFramebufferPixelFormat());

  // DRM_FORMAT_XRGB8888 should be the preferred format when either of the
  // controllers dont support UYVY format.

  // Check case where we dont have support for packed formats in Mirrored CRTC.
  planes_info.back().allowed_formats = only_rgb_format;
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  EXPECT_EQ(true, validated_params.back().is_overlay_candidate);

  plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_XRGB8888,
            plane_list.back().buffer->GetFramebufferPixelFormat());

  // Check case where we dont have support for packed formats in primary
  // display.
  planes_info.back().allowed_formats = xrgb_yuv_packed_formats;
  planes_info[1].allowed_formats = only_rgb_format;
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  validated_params =
      overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());
  EXPECT_EQ(true, validated_params.back().is_overlay_candidate);

  plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_XRGB8888,
            plane_list.back().buffer->GetFramebufferPixelFormat());
  controller->RemoveCrtc(drm_, kSecondaryCrtc);
}

TEST_F(DrmOverlayValidatorTest, OptimizeOnlyIfProcessingCallbackPresent) {
  // This test checks that we dont manipulate overlay buffers in case Processing
  // callback is not present.
  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;
  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};

  ui::FakePlaneInfo primary_plane_info(
      100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
  ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());

  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_UYVY,
            plane_list.back().buffer->GetFramebufferPixelFormat());
  plane_list_.back().processing_callback.Reset();
  plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(plane_list_.back().buffer->GetFramebufferPixelFormat(),
            plane_list.back().buffer->GetFramebufferPixelFormat());
  plane_list_.back().processing_callback = process_buffer_handler_;
}

TEST_F(DrmOverlayValidatorTest, DontResetOriginalBufferIfProcessedIsInvalid) {
  // This test checks that we dont manipulate overlay buffers in case Processing
  // callback is not present.
  overlay_params_.back().buffer_size = overlay_rect_.size();
  overlay_params_.back().display_rect = overlay_rect_;
  plane_list_.back().display_bounds = overlay_rect_;
  std::vector<uint32_t> xrgb_yuv_packed_formats = {DRM_FORMAT_XRGB8888,
                                                   DRM_FORMAT_UYVY};

  ui::FakePlaneInfo primary_plane_info(
      100, 1 << 0, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888));
  ui::FakePlaneInfo overlay_info(101, 1 << 0, xrgb_yuv_packed_formats);
  std::vector<ui::FakePlaneInfo> planes_info{primary_plane_info, overlay_info};
  plane_manager_->SetPlaneProperties(planes_info);
  overlay_validator_->ClearCache();

  overlay_validator_->TestPageFlip(overlay_params_, ui::OverlayPlaneList());

  ui::OverlayPlaneList plane_list =
      overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(DRM_FORMAT_UYVY,
            plane_list.back().buffer->GetFramebufferPixelFormat());
  plane_list_.back().processing_callback = base::Bind(
      &DrmOverlayValidatorTest::ReturnNullBuffer, base::Unretained(this));

  plane_list = overlay_validator_->PrepareBuffersForPageFlip(plane_list_);
  EXPECT_EQ(plane_list_.back().buffer->GetFramebufferPixelFormat(),
            plane_list.back().buffer->GetFramebufferPixelFormat());
  plane_list_.back().processing_callback = base::Bind(
      &DrmOverlayValidatorTest::ProcessBuffer, base::Unretained(this));
}


text:
package utils

import (
	"testing"

	"gopkg.in/h2non/gock.v1"
)

// TestInvokeUpdateImageAPI tests InvokeUpdateImageAPI function.
func TestInvokeUpdateImageAPI(t *testing.T) {
	// Mock the endpoint.
	gock.New("http://mock.caicloud.com").
		Post("/InvokeUpdateImageAPI").
		Reply(200)

	defer gock.Off()

	applicationName := "applicationName"
	partitionName := "partitionName"
	clusterName := "clusterName"
	containerName := "containerName"
	imageName := "imageName"
	userID := "caicloud"
	endpoint := "http://mock.caicloud.com/InvokeUpdateImageAPI"

	if err := InvokeUpdateImageAPI(userID, applicationName, clusterName, partitionName, containerName, imageName, endpoint); err != nil {
		t.Error("Expect error to be nil")
	}
}

// TestInvokeCheckDeployStateAPI tests InvokeCheckDeployStateAPI function.
func TestInvokeCheckDeployStateAPI(t *testing.T) {
	// Mock the endpoint.
	gock.New("http://mock.caicloud.com").
		Post("/InvokeCheckDeployStateAPI").
		Reply(200).
		JSON(map[string]int{
		"code": codeDeployReady,
	})

	defer gock.Off()

	jsonStr := []byte{}
	endpoint := "http://mock.caicloud.com/InvokeCheckDeployStateAPI"

	if result, err := InvokeCheckDeployStateAPI(jsonStr, endpoint); result != true || err != nil {
		t.Error("Expect error to be nil")
	}
}


text:
package com.auth0.client.mgmt;

import com.auth0.json.mgmt.RulesConfig;
import com.auth0.net.CustomRequest;
import com.auth0.net.Request;
import com.auth0.net.VoidRequest;
import com.auth0.utils.Asserts;
import com.fasterxml.jackson.core.type.TypeReference;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;

import java.util.List;

/**
 * Class that provides an implementation of the Rules Configs methods of the Management API as defined in See https://auth0.com/docs/api/management/v2#!/Rules_Configs/
 *

 * This class is not thread-safe.
 *
 * @see ManagementAPI
 */
@SuppressWarnings("WeakerAccess")
public class RulesConfigsEntity extends BaseManagementEntity {

    RulesConfigsEntity(OkHttpClient client, HttpUrl baseUrl, String apiToken) {
        super(client, baseUrl, apiToken);
    }

    /**
     * Request all the Rules Configs. A token with scope read:rules_configs is needed.
     * See https://auth0.com/docs/api/management/v2#!/Rules_Configs/get_rules_configs
     *

     * Note: For security, config variable values cannot be retrieved outside rule execution.
     *
     * @return a Request to execute.
     */
    public Request<List<RulesConfig>> list() {
        HttpUrl.Builder builder = baseUrl
                .newBuilder()
                .addPathSegments("api/v2/rules-configs");
        String url = builder.build().toString();
        CustomRequest<List<RulesConfig>> request = new CustomRequest<>(client, url, "GET", new TypeReference<List<RulesConfig>>() {
        });
        request.addHeader("Authorization", "Bearer " + apiToken);
        return request;
    }

    /**
     * Delete an existing Rules Config. A token with scope delete:rules_configs is needed.
     * See https://auth0.com/docs/api/management/v2#!/Rules_Configs/delete_rules_configs_by_key
     *
     * @param rulesConfigKey the rules config key
     * @return a Request to execute.
     */
    public Request delete(String rulesConfigKey) {
        Asserts.assertNotNull(rulesConfigKey, "rules config key");

        String url = baseUrl
                .newBuilder()
                .addPathSegments("api/v2/rules-configs")
                .addPathSegment(rulesConfigKey)
                .build()
                .toString();
        VoidRequest request = new VoidRequest(client, url, "DELETE");
        request.addHeader("Authorization", "Bearer " + apiToken);
        return request;
    }

    /**
     * Update an existing Rules Config. A token with scope update:rules_configs is needed.
     * See https://auth0.com/docs/api/management/v2#!/Rules_Configs/put_rules_configs_by_key
     *
     * @param rulesConfigKey the rules config key
     * @param rulesConfig    the rules config data to set. It can't include key.
     * @return a Request to execute.
     */
    public Request<RulesConfig> update(String rulesConfigKey, RulesConfig rulesConfig) {
        Asserts.assertNotNull(rulesConfigKey, "rules config key");
        Asserts.assertNotNull(rulesConfig, "rules config");

        String url = baseUrl
                .newBuilder()
                .addPathSegments("api/v2/rules-configs")
                .addPathSegment(rulesConfigKey)
                .build()
                .toString();
        CustomRequest<RulesConfig> request = new CustomRequest<>(this.client, url, "PUT", new TypeReference<RulesConfig>() {
        });
        request.addHeader("Authorization", "Bearer " + apiToken);
        request.setBody(rulesConfig);
        return request;
    }
}


text:
nz-mps-popolo
=============

[![Build
Status](https://travis-ci.org/nzherald/nz-mps-popolo.svg)](https://travis-ci.org/nzherald/nz-mps-popolo)

Scraper and parser for New Zealand MPs into Popolo format

## Requirements

This project currently expects Ruby 2.0 or higher

## Current status

This project is a work in progress. It is currently alpha quality and
not yet ready for production.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'nz_mps_popolo', github: 'nzherald/nz-mps-popolo'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install nz_mps_popolo

## Usage

TODO: Write usage instructions here

## Contributing

1. Fork it ( https://github.com/[my-github-username]/nz_mps_popolo/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create a new Pull Request


text:
"""Draw white lines where wide boxes would be split.

This encourages Tesseract to split these letter itself, by forcing them into
separate connected components.
"""

import os.path
import sys

from PIL import Image, ImageDraw
import numpy as np

from split_wide_boxes import split_box
from box import BoxLine, load_box_file

if __name__ == '__main__':
    _, box_path, image_path = sys.argv
    im = Image.open(image_path)
    w, h = im.size
    boxes = load_box_file(box_path)
    draw = ImageDraw.Draw(im)

    px = np.asarray(im)

    line_count = 0
    for box in boxes:
        y1 = h - box.top
        y2 = h - box.bottom
        x1 = box.left
        x2 = box.right

        # reinforce existing vertical splits
        # draw.line((x1, y2, x2, y2), fill='white')

        splits = split_box(box)
        if len(splits) == 1:
            continue

        # Draw white lines in all the boundary pixels.
        for subbox in splits[1:]:
            x1 = subbox.left
            x2 = subbox.right
            # TODO: Optimization: draw the line @ the least dark x-value
            counts = [(-np.sum(px[y1:y2+1, x1 + dx]), x1 + dx) for dx in (-2, -1, 0, 1, 2)]
            #print '%d, %d, %d %r' % (x, y1, y2, counts)
            counts.sort()
            x = counts[0][1]
            draw.line((x, y2, x, y1), fill='rgb(246,246,246)')
            line_count += 1

    base, ext = os.path.splitext(image_path)
    out_path = base + '.separated' + ext
    im.save(out_path)

    print 'Drew %d separating lines in %s' % (line_count, out_path)


text:
from resources import *

if __name__ == '__main__':
    unittest.main()


text:
<?php

namespace Alcaeus\MongoDbAdapter\Tests;

/**
 * @author alcaeus <alcaeus@alcaeus.org>
 */
class MongoDBRefTest extends TestCase
{
    public function testCreate()
    {
        $id = new \MongoId();
        $ref = \MongoDBRef::create('foo', $id);
        $this->assertSame(['$ref' => 'foo', '$id' => $id], $ref);
    }

    public function testCreateWithDatabase()
    {
        $id = new \MongoId();
        $ref = \MongoDBRef::create('foo', $id, 'database');
        $this->assertSame(['$ref' => 'foo', '$id' => $id, '$db' => 'database'], $ref);
    }

    /**
     * @dataProvider dataCreateThroughMongoDB
     */
    public function testCreateThroughMongoDB($expected, $document_or_id)
    {
        $ref = $this->getDatabase()->createDBRef('test', $document_or_id);

        $this->assertEquals($expected, $ref);
    }

    public static function dataCreateThroughMongoDB()
    {
        $id = new \MongoId();
        $validRef = ['$ref' => 'test', '$id' => $id, '$db' => 'mongo-php-adapter'];

        $object = new \stdClass();
        $object->_id = $id;

        return [
            'simpleId' => [$validRef, $id],
            'arrayWithIdProperty' => [$validRef, ['_id' => $id]],
            'objectWithIdProperty' => [$validRef, $object],
            'arrayWithoutId' => [null, []],
            'objectWithoutId' => [null, new \stdClass()],
        ];
    }

    /**
     * @dataProvider dataIsRef
     */
    public function testIsRef($expected, $ref)
    {
        $this->assertSame($expected, \MongoDBRef::isRef($ref));
    }

    public static function dataIsRef()
    {
        $objectRef = new \stdClass();
        $objectRef->{'$ref'} = 'coll';
        $objectRef->{'$id'} = 'id';

        return [
            'validRef' => [true, ['$ref' => 'coll', '$id' => 'id']],
            'validRefWithDatabase' => [true, ['$ref' => 'coll', '$id' => 'id', '$db' => 'db']],
            'refMissing' => [false, ['$id' => 'id']],
            'idMissing' => [false, ['$ref' => 'coll']],
            'objectRef' => [true, $objectRef],
            'int' => [false, 5],
        ];
    }

    public function testGet()
    {
        $id = new \MongoId();

        $db = $this->getDatabase();

        $document = ['_id' => $id, 'foo' => 'bar'];
        $db->selectCollection('test')->insert($document);

        $fetchedRef = \MongoDBRef::get($db, ['$ref' => 'test', '$id' => $id]);
        $this->assertInternalType('array', $fetchedRef);
        $this->assertEquals($document, $fetchedRef);
    }

    public function testGetThroughMongoDB()
    {
        $id = new \MongoId();

        $db = $this->getDatabase();

        $document = ['_id' => $id, 'foo' => 'bar'];
        $db->selectCollection('test')->insert($document);

        $fetchedRef = $db->getDBRef(['$ref' => 'test', '$id' => $id]);
        $this->assertInternalType('array', $fetchedRef);
        $this->assertEquals($document, $fetchedRef);
    }

    public function testGetWithNonExistingDocument()
    {
        $db = $this->getDatabase();

        $this->assertNull(\MongoDBRef::get($db, ['$ref' => 'test', '$id' => 'foo']));
    }

    public function testGetWithInvalidRef()
    {
        $db = $this->getDatabase();

        $this->assertNull(\MongoDBRef::get($db, []));
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/umeng_comm_user_center_title_color" >

    <RelativeLayout
        android:id="@+id/umeng_comm_clip_title"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_alignParentTop="true" >

        <ImageButton
            android:id="@+id/umeng_comm_clip_back"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_alignParentLeft="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="8dp"
            android:background="@drawable/umeng_comm_back"
            tools:ignore="ContentDescription" />

        <TextView
            android:id="@+id/umeng_comm_clip_save"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="16dp"
            android:text="@string/umeng_comm_save"
            android:textSize="@dimen/text_big16_size"
            android:textColor="@color/umeng_comm_text_topic_light_color" />
    </RelativeLayout>

    <com.umeng.commm.ui.widgets.ClipImageLayout
        android:id="@+id/umeng_comm_clip_layout"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@id/umeng_comm_clip_title" />

</RelativeLayout>


text:
<?php

/**
 * Auto generated by MySQL Workbench Schema Exporter.
 * Version 3.0.3 (doctrine2-zf2inputfilterannotation) on 2019-01-20 12:32:01.
 * Goto https://github.com/johmue/mysql-workbench-schema-exporter for more
 * information.
 */

namespace Base\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Zend\InputFilter\InputFilter;
use Zend\InputFilter\Factory as InputFactory;
use Zend\InputFilter\InputFilterAwareInterface;
use Zend\InputFilter\InputFilterInterface;

/**
 * Base\Entity\PageTag
 *
 * @ORM\Entity
 * @ORM\Table(name="page_tag")
 */
class PageTag implements InputFilterAwareInterface
{
    /**
     * Instance of InputFilterInterface.
     *
     * @var InputFilter
     */
    private $inputFilter;

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=45, nullable=true)
     */
    protected $tag_name;

    /**
     * @ORM\ManyToMany(targetEntity="Page", mappedBy="pageTags")
     */
    protected $pages;

    public function __construct()
    {
        $this->pages = new ArrayCollection();
    }

    /**
     * Set the value of id.
     *
     * @param integer $id
     * @return \Base\Entity\PageTag
     */
    public function setId($id)
    {
        $this->id = $id;

        return $this;
    }

    /**
     * Get the value of id.
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set the value of tag_name.
     *
     * @param string $tag_name
     * @return \Base\Entity\PageTag
     */
    public function setTagName($tag_name)
    {
        $this->tag_name = $tag_name;

        return $this;
    }

    /**
     * Get the value of tag_name.
     *
     * @return string
     */
    public function getTagName()
    {
        return $this->tag_name;
    }

    /**
     * Add Page entity to collection.
     *
     * @param \Base\Entity\Page $page
     * @return \Base\Entity\PageTag
     */
    public function addPage(Page $page)
    {
        $this->pages[] = $page;

        return $this;
    }

    /**
     * Remove Page entity from collection.
     *
     * @param \Base\Entity\Page $page
     * @return \Base\Entity\PageTag
     */
    public function removePage(Page $page)
    {
        $this->pages->removeElement($page);

        return $this;
    }

    /**
     * Get Page entity collection.
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getPages()
    {
        return $this->pages;
    }

    /**
     * Not used, Only defined to be compatible with InputFilterAwareInterface.
     *
     * @param \Zend\InputFilter\InputFilterInterface $inputFilter
     * @throws \Exception
     */
    public function setInputFilter(InputFilterInterface $inputFilter)
    {
        throw new \Exception("Not used.");
    }

    /**
     * Return a for this entity configured input filter instance.
     *
     * @return InputFilterInterface
     */
    public function getInputFilter()
    {
        if ($this->inputFilter instanceof InputFilterInterface) {
            return $this->inputFilter;
        }
        $factory = new InputFactory();
        $filters = array(
            array(
                'name' => 'id',
                'required' => true,
                'filters' => array(),
                'validators' => array(),
            ),
            array(
                'name' => 'tag_name',
                'required' => false,
                'filters' => array(),
                'validators' => array(),
            ),
        );
        $this->inputFilter = $factory->createInputFilter($filters);

        return $this->inputFilter;
    }

    /**
     * Populate entity with the given data.
     * The set* method will be used to set the data.
     *
     * @param array $data
     * @return boolean
     */
    public function populate(array $data = array())
    {
        foreach ($data as $field => $value) {
            $setter = sprintf('set%s', ucfirst(
                str_replace(' ', '', ucwords(str_replace('_', ' ', $field)))
            ));
            if (method_exists($this, $setter)) {
                $this->{$setter}($value);
            }
        }

        return true;
    }

    /**
     * Return a array with all fields and data.
     * Default the relations will be ignored.
     *
     * @param array $fields
     * @return array
     */
    public function getArrayCopy(array $fields = array())
    {
        $dataFields = array('id', 'tag_name');
        $relationFields = array();
        $copiedFields = array();
        foreach ($relationFields as $relationField) {
            $map = null;
            if (array_key_exists($relationField, $fields)) {
                $map = $fields[$relationField];
                $fields[] = $relationField;
                unset($fields[$relationField]);
            }
            if (!in_array($relationField, $fields)) {
                continue;
            }
            $getter = sprintf('get%s', ucfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $relationField)))));
            $relationEntity = $this->{$getter}();
            $copiedFields[$relationField] = (!is_null($map))
                ? $relationEntity->getArrayCopy($map)
                : $relationEntity->getArrayCopy();
            $fields = array_diff($fields, array($relationField));
        }
        foreach ($dataFields as $dataField) {
            if (!in_array($dataField, $fields) && !empty($fields)) {
                continue;
            }
            $getter = sprintf('get%s', ucfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $dataField)))));
            $copiedFields[$dataField] = $this->{$getter}();
        }

        return $copiedFields;
    }

    public function __sleep()
    {
        return array('id', 'tag_name');
    }
}


text:
package dagr

import "time"

// timeSource is primarily here as a test facility, since it's necessary to override time.Now for testing, as otherwise
// we never receive a consistent time.
type timeSource interface {
	Now() time.Time
}

type defaultClock struct{}

func (defaultClock) Now() time.Time { return time.Now() }

// This is set to a fixed time in time_test.go
var clock timeSource = defaultClock{}


text:
@interface PodsDummy_Pods_ABBadgeButton_Example : NSObject
@end
@implementation PodsDummy_Pods_ABBadgeButton_Example
@end


text:
package com.nordnetab.cordova.ul.parser;

import android.content.Context;

import com.nordnetab.cordova.ul.model.ULHost;
import com.nordnetab.cordova.ul.model.ULPath;

import org.apache.cordova.ConfigXmlParser;
import org.xmlpull.v1.XmlPullParser;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Nikolay Demyankov on 09.09.15.
 * <p/>
 * Parser for config.xml. Reads only plugin-specific preferences.
 */
public class ULConfigXmlParser extends ConfigXmlParser {

    private final Context context;
    private List<ULHost> hostsList;

    private boolean isInsideMainTag;
    private boolean didParseMainBlock;
    private boolean isInsideHostBlock;
    private ULHost processedHost;

    // region Public API

    /**
     * Constructor
     *
     * @param context application context
     */
    public ULConfigXmlParser(Context context) {
        this.context = context;
    }

    /**
     * Parse config.xml
     *
     * @return list of hosts, defined in the config file
     */
    public List<ULHost> parse() {
        resetValuesToDefaultState();
        super.parse(context);

        return hostsList;
    }

    // endregion

    // region XML processing

    @Override
    public void handleStartTag(XmlPullParser xml) {
        if (didParseMainBlock) {
            return;
        }

        final String name = xml.getName();
        if (!isInsideMainTag && XmlTags.MAIN_TAG.equals(name)) {
            isInsideMainTag = true;
            return;
        }

        if (!isInsideMainTag) {
            return;
        }

        if (!isInsideHostBlock && XmlTags.HOST_TAG.equals(name)) {
            isInsideHostBlock = true;
            processHostBlock(xml);
            return;
        }

        if (isInsideHostBlock && XmlTags.PATH_TAG.equals(name)) {
            processPathBlock(xml);
        }
    }

    @Override
    public void handleEndTag(XmlPullParser xml) {
        if (didParseMainBlock) {
            return;
        }

        final String name = xml.getName();

        if (isInsideHostBlock && XmlTags.HOST_TAG.equals(name)) {
            isInsideHostBlock = false;
            hostsList.add(processedHost);
            processedHost = null;
            return;
        }

        if (XmlTags.MAIN_TAG.equals(name)) {
            isInsideMainTag = false;
            didParseMainBlock = true;
        }
    }

    /**
     * Parse <host />
     */
    private void processHostBlock(XmlPullParser xml) {
        final String hostName = xml.getAttributeValue(null, XmlTags.HOST_NAME_ATTRIBUTE);
        final String eventName = xml.getAttributeValue(null, XmlTags.HOST_EVENT_ATTRIBUTE);
        final String scheme = xml.getAttributeValue(null, XmlTags.HOST_SCHEME_ATTRIBUTE);

        processedHost = new ULHost(hostName, scheme, eventName);
    }

    /**
     * Parse <path />
     */
    private void processPathBlock(XmlPullParser xml) {
        final String url = xml.getAttributeValue(null, XmlTags.PATH_URL_TAG);
        // skip wildcard urls
        if ("*".equals(url) || ".*".equals(url)) {
            return;
        }

        String event = xml.getAttributeValue(null, XmlTags.PATH_EVENT_TAG);
        if (event == null) {
            event = processedHost.getEvent();
        }

        ULPath path = new ULPath(url, event);
        processedHost.getPaths().add(path);
    }

    // endregion

    // region Private API

    private void resetValuesToDefaultState() {
        hostsList = new ArrayList<ULHost>();
        isInsideMainTag = false;
        didParseMainBlock = false;
        isInsideHostBlock = false;
        processedHost = null;
    }

    // endregion
}