text:
[![Build Status](https://travis-ci.org/evilmartians/fias.svg)](http://travis-ci.org/evilmartians/fias)
[![Code Climate](https://codeclimate.com/github/evilmartians/fias/badges/gpa.svg)](https://codeclimate.com/github/evilmartians/fias)
[![Test Coverage](https://codeclimate.com/github/evilmartians/fias/badges/coverage.svg)](https://codeclimate.com/github/evilmartians/fias)

Ruby wrapper for the Russian [ФИАС](http://fias.nalog.ru) database.

Designed for usage with Ruby on Rails and a PostgreSQL backend.

Think twice before you decide to use a standalone copy of FIAS database in your project. [КЛАДР в облаке](https://kladr-api.ru/) could also be a solution.

![Мухосраново](http://i.imgur.com/JCwgqjL.jpg) ![Марс](http://i.imgur.com/j8WPtOI.jpg)

## Installation

Add this line to your application's `Gemfile`:

```ruby
gem 'fias'
```

And then execute:

    $ bundle

Or install it yourself:

    $ gem install fias

## Import into PostgreSQL

**Warning!** You should not run the import in a 32-bit operating system, because you're likely to get a Memory Limit exception

    $ mkdir -p tmp/fias && cd tmp/fias
    $ bundle exec rake fias:download | xargs wget
    $ unrar e fias_dbf.rar
    $ bundle exec rake fias:create_tables fias:import DATABASE_URL=postgres://localhost/fias

If you get an error "Errno::EMFILE: Too many open files @ rb_sysopen" please set ulimit 512 or more before starting rake tasks:

    ulimit -S -n 512

The rake task accepts options through ENV variables:

* `TABLES` to specify a comma-separated list of tables to import or create. See `Fias::Import::Dbf::TABLES` for the list of key names. Use `houses` as an alias for HOUSE* tables and `nordocs` for NORDOC* tables. In most cases you'll need only the  `address_objects` table.
* `PREFIX` for database tables prefix ('fias_' by default).
* `FIAS_PATH` to specify DBF files location ('tmp/fias' by default).
* `DATABASE_URL` to set database credentials (required explicitly even with a Ruby on Rails project).

This gem uses `COPY FROM STDIN BINARY` to import data. At the moment it works with PostgreSQL only.

## Notes about FIAS

1. FIAS address objects table contains a lot of fields which are useless in most cases (tax office ID, legal document ID, etc.).
2. Address objects table contains a lot of historical records (more than 50%, in fact), which are useless in most cases.
3. Every record in the address object table could have multiple parents. For example, "Nevsky prospekt" in Saint Petersburg has two parents: Saint Petersburg (active) and Leningrad (historical name of the city, inactive). Most hierarchy libraries do accept just one parent for a record.
4. Using UUID type field as a primary key as it used in FIAS is not a good idea if you want to use `ancestry` or `closure_tree` gems to navigate through record tree.
5. Typical SQL production server settings are optimized for reading, so the import process in production environment could take a dramatically long time.

## Notes on initial import workflow

1. Use raw FIAS tables just as a temporary data source for creating/updating primary address objects table for your application.
2. The only requirement is to keep AOGUID, PARENTGUID and AOID fields in target table. You will need them for updating.
3. Keep your addressing object table immutable. This will give you an ability to work with huge amounts of addressing data locally. Send the result to production environment via a SQL dump.
4. FIAS contains some duplicates. Duplicates are records which have different UUIDs but equal names, abbrevations and nesting level. It is up to you to decide on how to deal with it: completely remove them or just mark as hidden. Krasnodar city has a lot of equally named streets situated in different districts.
5. [closure_tree](https://github.com/mceachen/closure_tree) works great as a hierarchy backend. Use [pg_closure_tree_rebuild](https://github.com/gzigzigzeo/pg_closure_tree_rebuild) to rebuild the hierarchy table from scratch.

[See example](examples/create.rb).

## Toponyms

Every FIAS address object has two fields: `formalname`, which holds the toponym (the name of a geographical object) and `shortname`, which holds its type (street, city, etc.). FIAS contains the list of all available `shortname` values and their corresponding long forms in the `address_object_types` table (SOCRBASE.DBF).

### Canonical forms

In real life people use a lot of type name variations. For example, 'проспект' can be written as 'пр' or 'пр-кт'.

You can convert any variation to a canonical form:

```ruby
Fias::Name::Canonical.canonical('поселок')
# => [
#  'поселок', # FIAS canonical full name
#  'п',       # FIAS canonical short name (as in address_objects table)
#  'п.',      # Short name with dot if needed
#  'пос',     # Alias
#  'посёлок'  # Alias
# ]
```

See [fias.rb](lib/fias.rb) for a list of settings.

### Append type to toponym

Use `Fias::Name::Append` to build toponym names in conformity with the rules of grammar:

```ruby
Fias::Name::Append.append('Санкт-Петербург', 'г')
# => ['г. Санкт-Петербург', 'город Санкт-Петербург']

Fias::Name::Append.append('Невский', 'пр')
# => ['Невский пр-кт', 'Невский проспект']

Fias::Name::Append.append('Чечня', 'республика')
# => ['Респ. Чечня', 'Республика Чечня']

Fias::Name::Append.append('Чеченская', 'республика')
# => ['Чеченская Респ.', 'Чеченская Республика']
```

You can pass any form of type name: full, short, an alias, with or without the dot.

### Extract a toponym

Sometimes you need to extract a toponym and its type from a plain string:

```ruby
Fias::Name::Extract.extract('Город Санкт-Петербург')
# => ['Санкт-Петербург', 'город', 'г', 'г.']

Fias::Name::Extract.extract('ул. Казачий Вал')
# => ['Казачий Вал', 'улица', 'ул', 'ул.']
```

### Extract house number

Sometimes street names come mixed up with house numbers, and you need to extract the house number from a string to clean it up for indexing:

```ruby
Fias::Name::HouseNumber.extract('Ново-Садовая ул,303а')
# => ['Ново-Садовая ул', '303а']

Fias::Name::HouseNumber.extract('пр.Энергетиков 72/2')
# => ['пр.Энергетиков', '72/2']
```

## Searching

Given you have a set of structured addresses:

```ruby
[
  { region: 'Еврейская АОбл', city: 'г. Биробиджан', street: 'Шолом-Алейхема' },
  { city: 'Санкт-Петербург', street: 'Лермонтовский проспект' }
]
```

You need to find a FIAS item for each address in set.

Your project may use a full-text search engine (Sphinx, ElasticSearch) or just a SQL database. Search principles are the same, but the implementation would differ. This library contains helpful modules and base classes to facilitate searching.

### Indexing

Each toponym consists of words; some of them are considered "special". Said "special" words could have synonyms or different forms, they could be skipped by user or could be written differently in FIAS database itself.

Examples:

* "50 лет Октября" == "50-летия Октября"
* "1-ая Советская" == "1 Советская" || "Советская 1-я"
* "Большой Проспект П.С." == "Большой Проспект Петроградской"
* "имени Максима Горького" == "им. Горького" || "Горького"
* "ул. Цюрупы" == "Цурюпы" || "Цюрупа" || "Цорюпы" || "Цорупа" (that's my favorite!)

You should trait them as equal when performing search.

Note that we are talking about toponym names with types extracted (see type extraction above).

#### Splitting the words

Words are split according to a set of simple rules aimed to simplify disclosure of synonyms and determination of optional parts.

```ruby
Addressing::Name::Split.split("50 лет Октября")
# => ["50 лет", "октября"]

Addressing::Name::Split.split("Ю.Р.Г.Эрвье")
# => ["ю.р.г.", "эрвье"]
```

#### Finding synonyms and optional words

Given we have a street named `им. академика И.П.Павлова` in FIAS, most people will reference it as just `Павлова` street, some will write it as `имени Павлова`, and some - `академика Павлова`. Basically, nobody except the FIAS database would reference it by the exact original name.

```ruby
Addressing::Name::Synonyms.expand('им. академика И.П.Павлова')

# => [["им", "имени", "им.", ""],
# ["ак.", "академика", ""],
# ["и.п.", ""],
# ["павлова"]]
```

Will return all possible forms for each word. Empty strings here mark optional words.

```ruby
Addressing::Name::Synonyms.tokens('им. академика И.П.Павлова')

# => ["им", "имени", "им.", "ак.", "академика", "и.п.", "павлова"]
```

Will return flat array with all words.

You can also calculate all possible name combinations:

```ruby
Addressing::Name::Synonyms.forms('им. И.П.Павлова')
# => [
#   'и.п. им павлова',
#   'им павлова',
#   'и.п. имени павлова',
#   'имени павлова',
#   'и.п. им. павлова',
#   'им. павлова',
#   'и.п. павлова',
#   'павлова'
# ]
```

#### Generating search index

In search index you need:
* name tokens (result of `Fias::Name::Synonyms.tokens`)
* name forms (result of `Fias::Name::Synonyms.forms`)
* ancestor ids

See [indexing example](examples/generate_index.rb).

### Querying

Performing a search will execute these three steps:

1. Preparation: sanitizing request values, splitting toponym name and type, etc.
2. Querying: finding possible candidates in addressing object tree.
3. Decision: determining the most suitable result depending on similarity with request.

#### Defining an in-app query class

We'll use the `sequel` gem in this example.

```ruby
class Query
  include Fias::Query

  def find(tokens)
    return [] if tokens.blank? # Empty array has no type, Sequel fails.

    op = Sequel.pg_array_op(:tokens)

    DB[:address_objects]
      .select(:id, :name, :abbr, :parent_id, :ancestry, :forms, :tokens)
      .where(op.overlaps(tokens))
      .to_a
  end
end
```

`#find` accepts splitted object name (a result of `Fias::Name::Split.split`). It searches all address objects with their tokens matching a given set of tokens. It returns an array of hashes with keys you can see above.

* `:abbr` - FIAS shortname value.
* `:ancestry` - array of ancestor IDs.
* `:forms` - object name forms (`Fias::Name::Synonyms.forms`)
* `:tokens` - object name tokens (`Fias::Name::Synonyms.tokens`)

#### Query params

```ruby
query = Query.new(
  region: 'Еврейская АОбл', city: 'г. Биробиджан', street: 'Шолом-Алейхема'
)

query.params.sanitized
# => {
#   :region => ["Еврейская", "автономная область", "Аобл", "Аобл"],
#   :city   => ["Биробиджан", "город", "г", "г."],
#   :street => ["Шолом-Алейхема"]
# }
```

Allowed params are: `%i(region district city subcity street)`

#### Result

```ruby
query.perform
#
# [[13213, {:id=>72344, :name=>"Шолом-Алейхема", :abbr=>"ул", :parent_id=>184027, :ancestry=>[184027, 12550], :forms=>["шолом-
# алейхема"], :tokens=>["шолом-алейхема"], :key=>:street}]]
```

Result is array.

* Each element of array contains two values: factor of equality and found object.
* If there are more then one row in array it means that query results are ambigous. All elements will have same factors.
* Array is empty if nothing found.

## Notes

1. People make mistakes. Search requests can have mistakes. Our goal is to minimize mistake's impact. Everything above (name forms, synonyms, etc.) is made to better understand humans. Over 50K of different real addresses written by humans was used to collect type of mistakes and deduce that rules.
2. That's why requests are slow.
3. In real applications there could be a lot of similar queries. It's okay to cache request results in database to prevent repeated queries. Cached items do not need TTL because FIAS changes rarely.
4. In many cases human can resolve ambigous results or try to find result manually. It could be wise to have some kind of admin interface in your app to do that.

## Contributors

* Victor Sokolov (@gzigzigzeo)
* Vlad Bokov (@razum2um)

Special thanks to @gazay.

## Contributing

1. Fork it ( https://github.com/evilmartians/fias/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

## License

The MIT License


text:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#pragma warning(disable:4995)
#pragma warning(disable:4996)

#include "sutil.h"
#include "GuiTui.h"
#include "dxstdafx.h"

#define MAXMESSAGE 8

static ID3DXFont*              g_pFont = NULL;         // Font for drawing text
static ID3DXFont*              g_pLargeFont = NULL;    // Font for drawing text
static ID3DXSprite*            g_pTextSprite = NULL;   // Sprite for batching draw text calls
static ID3DXFont*              g_pTinyFont=0;          // Font for drawing text

#include "cparser.h"
#include "tui.h"
#include "log.h"
#include "PhysX.h"
#include "MyGlobals.h"

extern float gFPS;

int gWINDOW_WIDE=1024;
int gWINDOW_TALL=768;

#define STATIC_ID_START 10000

static CDXUTDialog * gConsole = 0;
static CDXUTDialog * gDialog = 0;

//==================================================================================
void CALLBACK gOnUIPageEvent( UINT nEvent, int nControlID, CDXUTControl* pControl,void *pUserContext )
{
	CDXUTDialog *dialog = pControl->m_pDialog;

	void *userdata = dialog->GetUserData();
	if ( userdata )
	{
		TuiElement *page = (TuiElement *) userdata;
		TextUserInterface *tui = gAllGlobals.gTui.ref();

		if ( page )
		{
			TuiElement *ret = page->GetElement( nControlID-1 );

			switch ( ret->GetType() )
			{
				case TT_MULTI_SELECT:
					if ( 1 )
					{
						switch( nEvent )
						{
							case EVENT_LISTBOX_ITEM_DBLCLK:
							{
								DXUTListBoxItem *pItem = ((CDXUTListBox *)pControl)->GetItem( ((CDXUTListBox *)pControl)->GetSelectedIndex( -1 ) );
								break;
							}
							case EVENT_LISTBOX_SELECTION:
							{
								CDXUTListBox *pListBox = (CDXUTListBox *)pControl;
								TuiChoiceVector &choices = ret->GetChoices();
								int count = (int)choices.size();
								for (int i=0; i<count; i++)
								{
									DXUTListBoxItem *item = pListBox->GetItem(i);
									TuiChoice  &choice = choices[i];
									assert(item);
									if ( item )
									{
										if ( choice.GetState() != item->bSelected )
										{
											choice.SetState(item->bSelected);
											const char *args[2];
											args[0] = choice.GetArg().Get();

											if ( choice.GetState() )
												args[1] = "true";
											else
												args[1] = "false";

											page->ExecuteElement( nControlID-1, 2, args, tui );
										}
									}
								}

							}
						}
					}
					break;
				case TT_SLIDER:
					if ( 1 )
					{
						CDXUTSlider *slider = (CDXUTSlider *) pControl;
						int v = slider->GetValue();
						float fv = ret->GetSliderValue(v);
						char scratch[512];
  						sprintf(scratch,"%0.3f", fv );

						const char *args[1];
						args[0] = scratch;
						page->ExecuteElement( nControlID-1, 1, args, tui );
					}
					break;
				case TT_COMBO:
					if ( 1 )
					{
						CDXUTComboBox *combo = (CDXUTComboBox *) pControl;
						DXUTComboBoxItem *pItem = combo->GetSelectedItem();
						wchar_t *string = pItem->strText;
						char scratch[512];
						wcstombs(scratch, string, 512 );
						const char *args[1];
						args[0] = scratch;
						page->ExecuteElement( nControlID-1, 1, args,tui );

 						// now, do we need to hide any items (or show them)?
 						page->OnComboBoxChange( scratch, nControlID-1 );
					}
					break;
				case TT_BUTTON:
				case TT_PAGE:
					page->ExecuteElement( nControlID-1, 0, 0, tui );
					break;
				case TT_CHECKBOX:
					if ( 1 )
					{
						CDXUTCheckBox *pCheck = (CDXUTCheckBox *)pControl;
						bool state = pCheck->GetChecked();
						const char *args[1];
						if ( state )
						{
							args[0] = "true";
						}
						else
						{
							args[0] = "false";
						}
						page->ExecuteElement( nControlID-1, 1, args, tui );

 						// now, do we need to hide any items (or show them)?
 						page->OnCheckboxChange( state, nControlID-1 );
					}
					break;
			}
			if ( tui )
			{
				if ( ret && ret->GetType() == TT_PAGE )
				{
					// tell the last page it is now exiting
					TuiElement *exitingPage = tui->GetPage();
					if ( exitingPage )
					{
						exitingPage->OnExit( exitingPage );
					}

					tui->SetPage(ret);

					// tell new page it is now loading
					TuiElement *loadingPage = tui->GetPage();
					if ( loadingPage )
					{
						loadingPage->OnLoad( loadingPage );
					}
				}
			}
		}
	}
	else
	{
		// it's for the console
		CDXUTEditBox *edit = (CDXUTEditBox *) pControl;
		switch ( nEvent )
		{
			case EVENT_EDITBOX_STRING:
				if ( 1 )
				{
					LPCWSTR text = edit->GetText();
					char scratch[1024];
					WideToChar(text,scratch,1024);
					gAllGlobals.gLog.ref()->Display("%s\r\n", scratch);
					CPARSER.Parse("%s",scratch);
					edit->SetText(L"",true);
				}
				break;
			case EVENT_EDITBOX_CHANGE:
				break;
			default:
				break;
		}
	}

}

//==================================================================================
GuiTui::GuiTui(void *device,void *hwnd,void *instance,CDXUTDialogResourceManager *pManager) :
	mConsoleKeyDown( false )
{
	mConsoleIndex = 0;
	mShowConsole = false;
	mCapture     = false;
	mDtime       = 1.0f / 60.0f;
	mDialogResourceManager = pManager;
	if ( device )
	{
		IDirect3DDevice9 *pd3dDevice = (IDirect3DDevice9 *) device;
		D3DXCreateSprite( pd3dDevice, &g_pTextSprite );
		D3DXCreateFont(pd3dDevice,  9, 0, 0,       1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Courier",     &g_pTinyFont );
		D3DXCreateFont(pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial",       &g_pFont );
		D3DXCreateFont(pd3dDevice, 26, 0, 0,       1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Arial Black", &g_pLargeFont );

	  mWidth = 1024;
	  mHeight = 768;

		gAllGlobals.gGuiTui.set(this);
	}
}

//==================================================================================
GuiTui::~GuiTui(void)
{
	SAFE_RELEASE(g_pFont);
	SAFE_RELEASE(g_pLargeFont);
	SAFE_RELEASE(g_pTextSprite);
	SAFE_RELEASE(g_pTinyFont);
	delete gConsole;
	gConsole = 0;
	delete gDialog;
	gDialog = 0;
}

//==================================================================================
int GuiTui::CommandCallback(int token,int count,const char **arglist)
{
	int ret = 0;

	return ret;
}

//==================================================================================
bool GuiTui::HasCursorFocus()
{
	return true;
}

//==================================================================================
void GuiTui::HideAllGuiForTuiPages()
{
}

//==================================================================================
bool GuiTui::MsgProc(void *hwnd,unsigned int msg,unsigned int wparam,unsigned int lparam)
{
	bool ret = false;

	TextUserInterface *tui = gAllGlobals.gTui.ref();

	if ( tui && tui->GetShowGraphics() )
	{
		TuiElement *page = tui->GetPage();
		if ( page )
		{
			#if defined(WIN32)
			CDXUTDialog *dialog = (CDXUTDialog *)page->GetUserPtr();
			if ( dialog )
			{
				ret = dialog->MsgProc( (HWND) hwnd, (UINT) msg,(WPARAM) wparam, (LPARAM) lparam );
			}
			#endif
		}
	}

	if ( gConsole )
	{
		bool ignore = false;

		if ( msg == WM_KEYDOWN )
		{
			if ( (wparam == 126 || wparam == 96 || wparam == 9 ) )
			{
				ignore = true;

				if ( !mConsoleKeyDown )
				{
					mConsoleKeyDown = true;
					if ( mShowConsole )
					{
						mShowConsole = false;
					}
					else
					{
						mShowConsole = true;

						// indicate I handled this msg.
						ret = true;
					}
				}
			}
			if ( wparam == VK_F1 )
			{
				gAllGlobals.gTui.ref()->ToggleShowGraphics();
			}
		}
		else if ( msg == WM_KEYUP )
		{
			if ( (wparam == 126 || wparam == 96 || wparam == 9 ) )
			{
				ignore = true;
				mConsoleKeyDown = false;
			}
		}

		// if the user didn't hit one of the "special" keys, put key hit in the console
		if ( !ignore && mShowConsole )
		{
 			ret = gConsole->MsgProc( (HWND) hwnd, (UINT) msg,(WPARAM) wparam, (LPARAM) lparam );
		}
	}

	return ret;
}

//==================================================================================
void GuiTui::OnMouseDown(unsigned int uiX, unsigned int uiY, unsigned int uiButtons)
{
}

//==================================================================================
void GuiTui::OnMouseMove(unsigned int uiX, unsigned int uiY, unsigned int uiButtons)
{
}

//==================================================================================
void GuiTui::OnMouseUp(unsigned int uiX, unsigned int uiY, unsigned int uiButtons)
{
}

//==================================================================================
void GuiTui::PrintText(const char *str,int x,int y,unsigned int color)
{
	if ( str )
	{
		TextUserInterface *tui = 0;

		if( tui )
		{
			if ( g_pTinyFont && g_pTextSprite )
			{
				CDXUTTextHelper txtHelper( g_pTinyFont, g_pTextSprite, 30 );

				txtHelper.Begin();
				txtHelper.SetInsertionPos( x, y );
				txtHelper.SetForegroundColor( color );

				wchar_t wfoo[1024];
				CharToWide(str,wfoo,1024);

				txtHelper.DrawTextLine(wfoo);

				txtHelper.End();
			}
		}
	}
}

//==================================================================================
//*** The DirectX GUI version
//==================================================================================
void GuiTui::Render(void)
{
	int fontSize = 16;

	if (gAllGlobals.gGuiTui.ref() == 0 )
		return;

	if ( mCapture )
		return;

  if ( gAllGlobals.gLog.ref() )
  {
		const char *msg = gAllGlobals.gLog.ref()->GetLogMessage();
		if ( msg )
		{
			AddConsoleMessage(msg);
		}
  }

	if ( 1 )
	{

		if ( gConsole == 0 )
		{
			gConsole = new  CDXUTDialog;
			gConsole->Init(mDialogResourceManager);
			gConsole->SetCallback( gOnUIPageEvent );
			gConsole->SetUserData(0);
			gConsole->AddEditBox( 1, L"", 0, gWINDOW_TALL-26*2, 1000, 36, true, 0 );
		}

 		if ( mShowConsole )
 		{

 			CDXUTEditBox *edit = gConsole->GetEditBox(1);

 			if ( edit )
 			{
			  edit->SetFocused();
 			}

			gConsole->OnRender( mDtime );

  		if ( g_pTinyFont && g_pTextSprite )
 			{
 		  	CDXUTTextHelper txtHelper( g_pTinyFont, g_pTextSprite, fontSize );

 				txtHelper.Begin();
   			txtHelper.SetForegroundColor( 0xFFFFFF00 );

				int maxPos		= mHeight - 2*fontSize - 2;
				int addAmt		= fontSize;
				int menuHeight  = fontSize;
				int startPos	= maxPos - addAmt * CONSOLE_LINES - menuHeight;

				// ok..print console text!
 				for (int i=0; i<CONSOLE_LINES; i++)
 				{
 					const char *msg = GetConsoleMessage(i);
					if ( !msg )
						break;
   				wchar_t wfoo[1024];
 	  			CharToWide(msg,wfoo,1024);
					txtHelper.SetInsertionPos( 0, startPos );
					startPos += addAmt;
   				txtHelper.DrawTextLine(wfoo);
 				}
 		  	txtHelper.End();
 			}
 		}
 		else
 		{
  		if ( g_pTinyFont && g_pTextSprite )
 			{
	  		CDXUTTextHelper txtHelper( g_pTinyFont, g_pTextSprite, fontSize );

 				txtHelper.Begin();
 				txtHelper.SetForegroundColor( 0xFFD0D0D0 );

   				// ok..print console text!

				int maxPos		= mHeight - fontSize;
				int addAmt		= fontSize;
				int startPos	= maxPos - addAmt * 5;

 				for (int i=(CONSOLE_LINES-5); i<CONSOLE_LINES; i++)
 				{
 					const char *msg = GetConsoleMessage(i);
					if ( !msg )
						break;
  				wchar_t wfoo[1024];
	  			CharToWide(msg,wfoo,1024);
					txtHelper.SetInsertionPos( 0, startPos );
 					txtHelper.DrawTextLine(wfoo);
					startPos += addAmt;
 				}
	  		txtHelper.End();
 			}
 		}

		TextUserInterface *tui = gAllGlobals.gTui.ref();

		if ( tui && tui->GetShowGraphics() && !mShowConsole )
		{
			TuiElement *page = tui->GetPage();

			if ( page )
			{
				CDXUTDialog *dialog = (CDXUTDialog *)page->GetUserPtr();

 				bool dialogExists = ( dialog != 0 );

 				// k, if the dialog doesn't exist or the page needs updating, go in
 				if ( !dialogExists || page->GetNeedsUpdating() )
 				{
 					// first, let it figure out what is now visible
 					page->DetermineVisibleElements( 0, -1 );

 					// if the dialog does not exist, have it determine rescripted items
 					if ( !dialogExists )
 					{
 						page->DetermineRescriptedItems( 0, -1 );
 					}
 					else if ( page->GetNeedsUpdating() )
 					{
 						dialogExists = false;
 						page->SetUserPtr( 0 );
 						page->SetNeedsUpdating( false );
 						delete dialog;
						gDialog = 0;
 					}
 				}

 				if ( dialogExists == false )
				{
					dialog = new  CDXUTDialog;
			        dialog->Init(mDialogResourceManager);
					dialog->SetCallback( gOnUIPageEvent );
					dialog->SetUserData(page);
					gDialog = dialog;

					const PageLayout &pl   = page->getPageLayout();

					int bwidth             = pl.mButtonWidth;
					int lmargin            = pl.mLayoutLeftMargin;
					int layout_width       = pl.mLayoutWidth;
					int button_spacing     = pl.mButtonSpacing;
					int bhit               = pl.mButtonHeight;
					int checkbox_spacing   = DFLT_CHECKBOX_SPACING;

					int text_spacing       = pl.mTextSpacing;
					int slider_spacing     = pl.mSliderSpacing;
					int slider_text_width  = pl.mSliderTextWidth;
					int slider_height      = pl.mSliderHeight;
					int slider_width       = pl.mSliderWidth;

					int combo_width        = pl.mComboWidth;
					int combo_spacing      = pl.mComboSpacing;
					int combo_height       = pl.mComboHeight;
					int combo_dropdown     = pl.mComboDropdown;

					int list_width         = pl.mListWidth;

					int xloc     = lmargin;
					int yloc     = 10;
					int id       = 0;
					int staticId = STATIC_ID_START;

					page->SetUserPtr(dialog);

					TuiElementVector &elements = page->GetElements();
					TuiElementVector::iterator i;

					for (i=elements.begin(); i!=elements.end(); ++i)
					{
						++id;

						TuiElement *tui = (*i);
 						if ( tui && tui->IsVisible() )
						{
							switch ( tui->GetType() )
							{
								case TT_TEXT:
								{
									wchar_t scratch[512];
									mbstowcs(scratch, tui->GetText(), 512 );
									if ( xloc != lmargin )
									{
										xloc = lmargin;
										yloc+= text_spacing;
									}
									dialog->AddStatic( staticId, scratch, xloc, yloc, 500, 20, 0 );

									// k, now make sure it is justified to the left
									CDXUTControl *ctrl = dialog->GetControl( staticId );
									if ( ctrl && ( ctrl->GetType() == DXUT_CONTROL_STATIC ) )
									{
										// set color
										ctrl->SetUserData( (void *)tui->GetTextColor() );

										CDXUTElement *element = ctrl->GetElement( 0 );
										if ( element )
										{
											// make sure it is left-justified, and vertically centered
											element->dwTextFormat = (DT_LEFT | DT_VCENTER);
										}
									}

									// move next element down
									yloc += text_spacing;

									// increment static id
									++staticId;
								}
								break;

								case TT_CHECKBOX:
									if ( 1 )
									{
										wchar_t scratch[512];
										mbstowcs(scratch, tui->GetName().Get(), 512 );
										dialog->AddCheckBox( id, scratch, xloc, yloc, bwidth, bhit, tui->GetState(), 0);
										xloc+=(bwidth+10);
										if ( xloc > (layout_width-(bwidth+10)) )
										{
											xloc = lmargin;
											yloc += checkbox_spacing;
										}
									}
									break;
								case TT_SLIDER:
									if ( 1 )
									{
										if ( xloc != lmargin )
										{
											xloc = lmargin;
											yloc += slider_spacing;
										}
										wchar_t scratch[512];
										mbstowcs(scratch, tui->GetName().Get(), 512 );
										dialog->AddStatic(0, scratch, xloc, yloc, slider_text_width, slider_height, 0 );
										dialog->AddSlider(id, xloc+slider_text_width+10, yloc, slider_width, slider_height, 0, 1000, 0, false, 0);
										dialog->AddStatic(id+1000, L"10mhz", xloc+slider_text_width+10+slider_width+10, yloc, slider_text_width, slider_height, 0 );
										xloc = lmargin;
										yloc += slider_spacing;
									}
									break;
								case TT_COMBO:
									if ( 1 )
									{
										if ( xloc != lmargin )
										{
											xloc = lmargin;
											yloc += combo_spacing;
										}
										wchar_t scratch[512];
										mbstowcs(scratch, tui->GetName().Get(), 512 );
										dialog->AddStatic(0, scratch, xloc, yloc, combo_width, combo_height, 0 );
										CDXUTComboBox *pCombo;
										dialog->AddComboBox(id, xloc, yloc+combo_height, combo_width, combo_height, 0, false, &pCombo);
										if ( pCombo )
										{
											// ok..populate the combo box now..
											TuiChoiceVector &choices = tui->GetChoices();
											TuiChoiceVector::iterator i;
											int index = 0;
											for (i=choices.begin(); i!=choices.end(); ++i)
											{
												wchar_t scratch[512];
												mbstowcs(scratch, (*i).GetChoice().Get(), 512 );
												pCombo->AddItem( scratch, (LPVOID) index );
												index++;
											}

											pCombo->SetDropHeight(combo_dropdown);

										}
										xloc = lmargin;
										yloc += combo_spacing;
									}
									break;
								case TT_MULTI_SELECT:
									if ( 1 )
									{
										if ( xloc != lmargin )
										{
											xloc = lmargin;
											yloc+=30;
										}
										TuiChoiceVector &choices = tui->GetChoices();

										int list_height = choices.size()*15;

										if ( (yloc+list_height) > 700 )
										{
											list_height = 700-yloc;
										}

										wchar_t scratch[512];
										mbstowcs(scratch, tui->GetName().Get(), 512 );
										dialog->AddStatic(0, scratch, xloc, yloc, 180, 20, 0 );
										dialog->AddListBox(id, xloc, yloc+26, list_width, list_height, CDXUTListBox::MULTISELECTION );
										CDXUTListBox *pListBox = dialog->GetListBox(id);
										if(pListBox)
										{
											// ok..populate the combo box now..
											TuiChoiceVector::iterator i;
											int index = 0;
											for (i=choices.begin(); i!=choices.end(); ++i)
											{
												wchar_t scratch[512];
												mbstowcs(scratch, (*i).GetChoice().Get(), 512 );
												pListBox->AddItem( scratch, (LPVOID) index );
												index++;
											}
										}
										xloc = lmargin;
										yloc+=list_height;
									}
									break;
								case TT_BUTTON:
								case TT_PAGE:
									if ( 1 )
									{
										wchar_t scratch[512];
										mbstowcs(scratch, tui->GetName().Get(), 512 );
										dialog->AddButton( id, scratch, xloc, yloc, bwidth, 20, 0);
										xloc += (bwidth+button_spacing);

										if ( xloc > (layout_width-(bwidth+button_spacing)) )
										{
											xloc = lmargin;
											yloc+=24;
										}
									}
									break;
							}
						}
					}
				}

				// SRM : do this only when dialog exists
 				if ( dialogExists )
				{
					// static's that are just static's have id's of 10000+
					int id = STATIC_ID_START;

					CDXUTControl *ctrl = dialog->GetControl( id++ );
					while ( ctrl )
					{
						if ( ctrl->GetType() == DXUT_CONTROL_STATIC )
						{
							CDXUTElement *element = ctrl->GetElement( 0 );
							void *userData        = ctrl->GetUserData();
							if ( element && userData )
							{
								//element->FontColor.Current = D3DCOLOR_ARGB(255, 255, 255, 0);
								element->FontColor.Current = (unsigned)( userData );
							}
						}
						ctrl = dialog->GetControl( id++ );
					}
				}

				dialog->OnRender(mDtime);

			}
		}

		if( 1 )
		{

      if ( tui /*&& tui->GetShowGraphics()*/ )
			{

				CDXUTTextHelper txtHelper( g_pFont, g_pTextSprite, 15 );

				// Output statistics
				txtHelper.Begin();
				txtHelper.SetInsertionPos( 5, 5 );
				txtHelper.SetForegroundColor( D3DXCOLOR( 0.8f, 0.8f, 0.8f, 0.8f ) );
				txtHelper.DrawTextLine( DXUTGetFrameStats() );
				txtHelper.DrawTextLine( DXUTGetDeviceStats() );

				wchar_t scratch[512];
				const char *stats = 0;

				if (stats )
				{
					mbstowcs(scratch, stats, 512);
					txtHelper.DrawTextLine( scratch );
				}

				if ( 1 )
				{
  				txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );

  				// Draw help
  				txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );

					wchar_t temp[512];
					if(px_paused())
						StringCchPrintf(temp,512, L"FPS: %3d (Paused)!", (int)gFPS);
					else
						StringCchPrintf(temp,512, L"FPS: %3d", (int)gFPS);
  				txtHelper.DrawTextLine(temp);

  				txtHelper.DrawTextLine( L"Press F1 to toggle UI" );
  				if ( gAllGlobals.gTui.ref()->GetShowGraphics() )
  				{
	  				txtHelper.DrawTextLine( L"Press ESC to exit" );
	  				txtHelper.DrawTextLine( L"Press TAB for Console" );
	  				txtHelper.DrawTextLine( L"Press HOME camera back to default position" );
						txtHelper.DrawTextLine( L"Press R to reset scene" );
						txtHelper.DrawTextLine( L"Press P to pause/unpause physics" );
						txtHelper.DrawTextLine( L"Press 0-9 to control camera speed" );
						txtHelper.DrawTextLine( L"Press SPACE to fire sphere" );
						txtHelper.DrawTextLine( L"Press B to toggle graphics/physics view" );
						txtHelper.DrawTextLine( L"Press F7 to toggle backface culling" );
						txtHelper.DrawTextLine( L"Mouse wheel zoom in/out" );
						txtHelper.DrawTextLine( L"Mouse wheel while dragging move object in/out" );
						txtHelper.DrawTextLine( L"Left Mouse rotate view" );
						txtHelper.DrawTextLine( L"Right Mouse rotate object" );
						txtHelper.DrawTextLine( L"SHIFT+Left Mouse delete tetrahedron" );
						txtHelper.DrawTextLine( L"SHIFT+Right Mouse un-delete tetrahedron" );
					}

  			}

				txtHelper.SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );

				txtHelper.End();
			}
		}

	}
}

//==================================================================================
// Update the UI's state.
//==================================================================================
void GuiTui::Update(void)
{
	TextUserInterface *tui = gAllGlobals.gTui.ref();
	if(!tui)
		return;

	TuiElement *page       = tui->GetPage();
	if(!page)
		return;

#if defined(WIN32)
	CDXUTDialog *dialog    = (CDXUTDialog *)page->GetUserPtr();
	if(!dialog)
		return;
#endif

	// SRM : k, here we ask the globals if anything changed
	// and if so, we may need to update some elements!!!

	int id   = 0;
	TuiElementVector &elements = page->GetElements();
	TuiElementVector::iterator i;
	for (i=elements.begin(); i!=elements.end(); ++i)
	{
		id++;
		TuiElement *tui = (*i);
		if ( tui )
		{
			switch ( tui->GetType() )
			{
				case TT_CHECKBOX:
				{
					bool state = tui->GetState();
					CDXUTCheckBox *checkbox = dialog->GetCheckBox(id);
					if ( checkbox )
					{
						checkbox->SetChecked( state );
					}
					break;
				}
				case TT_SLIDER:
				{
					char actualVal[128], displayVal[128];
					tui->GetArg( 0, displayVal );
					tui->GetArg_Actual( 0, actualVal );
					CDXUTSlider *pslider = dialog->GetSlider(id);
					CDXUTStatic *label  = dialog->GetStatic(id+1000);
					if ( pslider && label )
					{
						float v = (float) atof(actualVal);
						int slider = tui->GetSliderTick(v); // convert the slider value into a tick point 0-1000

						wchar_t wvalue[512];
						CharToWide( displayVal, wvalue, 512 );
						label->SetText( wvalue );
						pslider->SetValue( slider );
					}
					break;
				}
				case TT_COMBO:
				{
					char value[128];
					tui->GetArg( 0, value );
					CDXUTComboBox *combo = dialog->GetComboBox(id);
					if(combo && !combo->IsOpened())
					{
						bool found = false;
						size_t len = strlen(value);
						wchar_t wvalue[512];
						CharToWide(value,wvalue,512);
						//combo->SetSelectedByText(wvalue);
						UINT numItems = combo->GetNumItems();
						for(UINT index=0; index<numItems; index++)
						{
							DXUTComboBoxItem *item = combo->GetItem(index);
							if(item && !wcsnicmp(wvalue, item->strText, len))
							{
								combo->SetSelectedByIndex(index);
								found = true;
								break;
							}
						}
						//if(!found) combo->SetSelectedByIndex(0); // select none?
					}
					break;
				}
				case TT_MULTI_SELECT:
				{
					CDXUTListBox *listbox = dialog->GetListBox(id);
					assert(listbox);
					break;
				}
				case TT_BUTTON:
				case TT_PAGE:
				{
					break;
				}
			}
		}
	}
}

//==================================================================================
void GuiTui::SetWindow(void* hwnd)
{
}

//==================================================================================
bool GuiTui::ToggleUI(void)
{
	bool ret = false;
	TextUserInterface *tui = gAllGlobals.gTui.ref();
	if ( tui )
		ret = tui->ToggleShowGraphics();

	return ret;
}

//==================================================================================
void GuiTui::NotifyWindowResized( unsigned newWidth, unsigned newHeight )
{
	mWidth	= newWidth;
	mHeight	= newHeight;

	// update our pages
	TextUserInterface *tui = gAllGlobals.gTui.ref();
	if ( tui )
	{
		tui->NotifyAllPagesOfNewDimensions( newWidth, newHeight );
	}

	if ( gConsole )
	{
		CDXUTEditBox *edit = gConsole->GetEditBox( 1 );
		if ( edit )
		{
			// modify the console's position as well
			edit->SetLocation( 0, newHeight - DFLT_CONSOLE_HEIGHT );
			edit->SetSize( newWidth, DFLT_CONSOLE_HEIGHT );
		}
	}
}

//==================================================================================
void GuiTui::NotifySceneTypeChanged( bool hardwareOn )
{
	// k, now we need to go through and items that need to be disabled when
	// they need to know about the scene type turning on/off hardware
	TextUserInterface *tui = gAllGlobals.gTui.ref();
	if ( tui )
	{
		// in addition, let it know so it can go through
		// and enable/disable appropriate items for visibility
		tui->NotifyHardwareStatus( hardwareOn );

		if ( hardwareOn )
		{
			// k, now we need to make sure that it is checked appropriately
			TuiElement *page = tui->GetElementOfTypeWithName( TT_PAGE, "Physics" );
			if ( page )
			{
				int index = page->GetElementIndexOfTypeWithName( TT_CHECKBOX, "Always Use 6DOF" );
				if ( index >= 0 )
				{
					const char *args[1] = { "true" };
					page->ExecuteElement( index, 1, args, tui );
				}
			}
		}
	}
}

//==================================================================================
void PageLayout::Modify( unsigned newScreenWidth, unsigned newScreenHeight )
{
	// k, we are being told what the new screen width and height is, so we might need
	// to adjust ourselves
	mLayoutWidth		= newScreenWidth;
    mLayoutLeftMargin	= newScreenWidth - 3*(DFLT_BUTTON_WIDTH+DFLT_BUTTON_SPACING) - DFLT_LAYOUT_RIGHT_MARGIN;
}

void GuiTui::onLostDevice(void)
{
	if ( g_pFont )      g_pFont->OnLostDevice();
	if ( g_pLargeFont ) g_pLargeFont->OnLostDevice();
	if ( g_pTinyFont )  g_pTinyFont->OnLostDevice();
	if ( g_pTextSprite ) g_pTextSprite->OnLostDevice();
}

void GuiTui::onResetDevice(void *device)
{
	if ( g_pFont )      g_pFont->OnResetDevice();
	if ( g_pLargeFont ) g_pLargeFont->OnResetDevice();
	if ( g_pTinyFont )  g_pTinyFont->OnResetDevice();
	if ( g_pTextSprite ) g_pTextSprite->OnResetDevice();
}

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace RulerZ\Executor;

use Elastica\Search;
use Elastica\SearchableInterface;
use FOS\ElasticaBundle\Finder\TransformedFinder;
use Hoa\Ruler\Model;

use RulerZ\Context\ExecutionContext;
use RulerZ\Visitor\ElasticsearchVisitor;

/**
 * Execute a rule on an Elastica client.
 */
class ElasticaExecutor implements ExtendableExecutor
{
    use Polyfill\ExtendableExecutor;
    use Polyfill\FilterBasedSatisfaction;

    /**
     * Constructs the Elasticsearch executor.
     *
     * @param array $operators A list of custom operators to register.
     */
    public function __construct(array $operators = [])
    {
        $this->registerOperators($operators);
    }

    /**
     * {@inheritDoc}
     */
    public function filter($target, Model $rule, array $parameters, ExecutionContext $context)
    {
        $searchQuery = $this->buildSearchQuery($rule, $parameters);

        if ($target instanceof SearchableInterface || $target instanceof Search) {
            return $target->search(['query' => $searchQuery]);
        }

        return $target->find(['query' => $searchQuery]);
    }

    /**
     * {@inheritDoc}
     */
    public function supports($target, $mode)
    {
        return $target instanceof SearchableInterface || $target instanceof TransformedFinder || $target instanceof Search;
    }

    /**
     * Builds the search query for the given rule.
     *
     * @param Model $rule       The rule to apply.
     * @param array $parameters The search parameters.
     *
     * @return array The search.
     */
    private function buildSearchQuery(Model $rule, array $parameters)
    {
        $searchBuilder = new ElasticsearchVisitor();
        $searchBuilder->setOperators($this->getOperators());
        $searchBuilder->setParameters($parameters);

        return $searchBuilder->visit($rule);
    }
}


text:
package grapeNet

import (
	"bufio"
	"context"
	"encoding/binary"
	"fmt"
	"io"
	"net"
	"sync"
	"sync/atomic"
	"time"

	cm "github.com/koangel/grapeNet/ConnManager"
	logger "github.com/koangel/grapeNet/Logger"
	stream "github.com/koangel/grapeNet/Stream"

	utils "github.com/koangel/grapeNet/Utils"
)

type TcpConn struct {
	cm.Conn
	ownerNet *TCPNetwork
	TConn    net.Conn    // tcp连接
	UserData interface{} // 用户对象
	LastPing time.Time

	send    chan []byte
	process chan *cm.QPackItem // 单独的一个数据包

	CryptKey []byte

	IsClosed int32

	removeOnce sync.Once
	closeSock  sync.Once

	remoteAddr string

	ReadTime  time.Duration
	WriteTime time.Duration
}

const (
	ReadWaitPing = 65 * time.Second
	WriteTicker  = 45 * time.Second

	queueCount    = 2048
	maxPacketSize = 6 * 1024 * 1024 // 6兆数据包最大
)

const (
	RMStream     = iota // 使用流算法读写数据包
	RMReadFull          // 使用固定算法读写数据包 固定算法 包头4字节为固定长度,其余位置为数据包payload
	RMStringLine        // 通过使用\n来进行文本拆分
)

//////////////////////////////////////
// 创建新连接

func EmptyConn(ctype int) *TcpConn {
	newConn := &TcpConn{
		LastPing: time.Now(),
		IsClosed: 0,

		CryptKey: []byte{},

		send:    make(chan []byte, queueCount),
		process: make(chan *cm.QPackItem, queueCount),

		WriteTime: WriteTicker,
		ReadTime:  ReadWaitPing,
	}

	newConn.Ctx, newConn.Cancel = context.WithCancel(context.Background())
	newConn.Once = new(sync.Once)
	newConn.Wg = new(sync.WaitGroup)
	newConn.SessionId = cm.CreateUUID(ctype)
	newConn.Type = ctype

	return newConn
}

func NewConn(tn *TCPNetwork, conn net.Conn, UData interface{}) *TcpConn {
	newConn := EmptyConn(cm.ESERVER_TYPE)

	newConn.TConn = conn
	newConn.ownerNet = tn
	newConn.UserData = UData
	newConn.remoteAddr = conn.RemoteAddr().String()

	return newConn
}

func NewDial(tn *TCPNetwork, addr string, UData interface{}) (conn *TcpConn, err error) {
	err = nil
	conn = nil
	dconn, derr := net.DialTimeout("tcp", addr, time.Second*30)
	if derr != nil {
		logger.ERRORV(derr)
		err = derr
		return
	}

	tcpConn, ok := dconn.(*net.TCPConn)
	if ok {
		tcpConn.SetKeepAlive(true)
	}

	conn = EmptyConn(cm.ECLIENT_TYPE)
	conn.ownerNet = tn
	conn.TConn = dconn
	conn.UserData = UData
	conn.remoteAddr = dconn.RemoteAddr().String()

	return
}

//////////////////////////////////////////////
// 成员函数
func (c *TcpConn) SetReadTime(d time.Duration) {
	c.ReadTime = d
}

func (c *TcpConn) SetWriteTime(w time.Duration) {
	c.WriteTime = w
}

func (c *TcpConn) SetUserData(user interface{}) {
	c.UserData = user
}

func (c *TcpConn) GetUserData() interface{} {
	return c.UserData
}

func (c *TcpConn) GetNetConn() net.Conn {
	return c.TConn
}

func (c *TcpConn) RemoteAddr() string {
	return c.remoteAddr
}

func (c *TcpConn) startProc() {

	go c.writePump()

	switch c.ownerNet.RecvMode {
	case RMReadFull:
		go c.recvPumpFull()
	case RMStringLine:
		go c.recvPumpString()
	default:
		go c.recvPump()
	}

	if HandlerProc > 0 {
		go c.handlerPump()
	}
}

func (c *TcpConn) handlerPump() {
	defer func() {
		if p := recover(); p != nil {
			stacks := utils.PanicTrace(4)
			panic := fmt.Sprintf("recover panics: %v call:%v", p, string(stacks))
			logger.ERROR(panic)

			if c.ownerNet.Panic != nil {
				c.ownerNet.Panic(c, panic)
			}
		}

		c.Wg.Done()
		logger.INFOV("addr:", c.remoteAddr, ",", c.SessionId, " handle full Pump defer done!!!")
	}()

	c.Wg.Add(1)
	for {
		select {
		case <-c.Ctx.Done():
			logger.INFO("%v %v session handler done...", c.remoteAddr, c.SessionId)
			return
		case item := <-c.process:
			{
				if atomic.LoadInt32(&c.IsClosed) == 1 {
					return
				}

				if c.ownerNet.OnHandler != nil {
					c.ownerNet.OnHandler(c, item.Payload)
				}
			}
		}
	}
}

func (c *TcpConn) recvPump() {
	defer func() {
		if p := recover(); p != nil {
			stacks := utils.PanicTrace(4)
			panic := fmt.Sprintf("recover panics: %v call:%v", p, string(stacks))
			logger.ERROR(panic)

			if c.ownerNet.Panic != nil {
				c.ownerNet.Panic(c, panic)
			}
		}

		c.Cancel() // 结束
		c.Wg.Wait()
		c.Close() // 关闭SOCKET
		if c.ownerNet != nil {
			c.ownerNet.RemoveSession(c.SessionId) // 删除
		}
		logger.INFOV("addr:", c.remoteAddr, ",", c.SessionId, " read Pump defer done!!!")
	}()

	var buffer = make([]byte, 65535)
	var lStream stream.BufferIO

	for {
		c.TConn.SetReadDeadline(time.Now().Add(c.ReadTime))
		if atomic.LoadInt32(&c.IsClosed) == 1 {
			return
		}

		rn, err := c.TConn.Read(buffer)
		if err != nil {
			logger.ERROR("Session %v %v Recv Error:%v", c.remoteAddr, c.SessionId, err)
			return
		}

		if rn == 0 {
			logger.ERROR("Session %v %v Recv Len:%v", c.remoteAddr, c.SessionId, rn)
			return
		}

		if c.ownerNet.OnHandler == nil {
			logger.ERROR("%v Handler is Null,Closed...", c.remoteAddr)
			return
		}

		if lStream.Write(buffer, rn) == -1 {
			logger.ERROR("Session %v %v Recv Error:Packet size is too big...", c.remoteAddr, c.SessionId)
			return
		}

		upak, err := c.ownerNet.Unpackage(c, &lStream) // 调用解压行为
		if err == nil {
			for _, v := range upak {
				if c.ownerNet.SendPong(c, v) {
					continue
				}

				if HandlerProc <= 0 {
					if c.ownerNet.OnHandler != nil {
						c.ownerNet.OnHandler(c, v[4:])
					}
				} else {
					if c.process != nil {
						c.process <- &cm.QPackItem{
							Length:  int32(len(v[4:])),
							Payload: v[4:],
						}
					}
				}
			}
		}
	}
}

func (c *TcpConn) recvPumpString() {
	defer func() {
		if p := recover(); p != nil {
			stacks := utils.PanicTrace(4)
			panic := fmt.Sprintf("recover panics: %v call:%v", p, string(stacks))
			logger.ERROR(panic)

			if c.ownerNet.Panic != nil {
				c.ownerNet.Panic(c, panic)
			}
		}

		c.Cancel() // 结束
		c.Wg.Wait()
		c.Close() // 关闭SOCKET
		if c.ownerNet != nil {
			c.ownerNet.RemoveSession(c.SessionId) // 删除
		}

		logger.INFOV("addr:", c.remoteAddr, ",", c.SessionId, " read string Pump defer done!!!")
	}()

	readerLine := bufio.NewScanner(c.TConn)
	readerLine.Split(bufio.ScanLines)
	for readerLine.Scan() {
		c.TConn.SetReadDeadline(time.Now().Add(c.ReadTime))
		if atomic.LoadInt32(&c.IsClosed) == 1 {
			return
		}

		if c.ownerNet.OnHandler == nil {
			logger.ERROR("%v Handler is Null,Closed...", c.remoteAddr)
			return
		}

		payload := c.ownerNet.Decrypt(readerLine.Bytes(), c.CryptKey)
		if c.ownerNet.SendPong(c, payload) {
			continue
		}

		if HandlerProc <= 0 {
			if c.ownerNet.OnHandler != nil {
				c.ownerNet.OnHandler(c, payload)
			}
		} else {
			if c.process != nil {
				c.process <- &cm.QPackItem{
					Length:  int32(len(payload)),
					Payload: payload,
				}
			}
		}
	}
}

func (c *TcpConn) recvPumpFull() {
	defer func() {
		if p := recover(); p != nil {
			stacks := utils.PanicTrace(4)
			panic := fmt.Sprintf("recover panics: %v call:%v", p, string(stacks))
			logger.ERROR(panic)

			if c.ownerNet.Panic != nil {
				c.ownerNet.Panic(c, panic)
			}
		}

		c.Cancel() // 结束
		c.Wg.Wait()
		c.Close() // 关闭SOCKET
		if c.ownerNet != nil {
			c.ownerNet.RemoveSession(c.SessionId) // 删除
		}

		logger.INFOV("addr:", c.remoteAddr, ",", c.SessionId, " read full Pump defer done!!!")
	}()

	for {
		c.TConn.SetReadDeadline(time.Now().Add(c.ReadTime))
		if atomic.LoadInt32(&c.IsClosed) == 1 {
			return
		}

		lenBytes := make([]byte, 4)
		rn, err := io.ReadFull(c.TConn, lenBytes)
		if err != nil {
			logger.ERROR("Session %v %v Recv Error:%v", c.remoteAddr, c.SessionId, err)
			return
		}

		if rn == 0 {
			logger.ERROR("Session %v %v Recv Len:%v", c.remoteAddr, c.SessionId, rn)
			return
		}

		headerLen := binary.LittleEndian.Uint32(lenBytes)
		payload := make([]byte, headerLen)
		rn, err = io.ReadFull(c.TConn, payload)
		if err != nil {
			logger.ERROR("Session %v %v Recv Error:%v", c.remoteAddr, c.SessionId, err)
			return
		}

		if rn == 0 {
			logger.ERROR("Session %v %v Recv Len:%v", c.remoteAddr, c.SessionId, rn)
			return
		}

		if c.ownerNet.OnHandler == nil {
			logger.ERROR("%v Handler is Null,Closed...", c.remoteAddr)
			return
		}

		payload = c.ownerNet.Decrypt(payload, c.CryptKey)
		if c.ownerNet.SendPong(c, payload) {
			continue
		}

		if HandlerProc <= 0 {
			if c.ownerNet.OnHandler != nil {
				c.ownerNet.OnHandler(c, payload)
			}
		} else {
			if c.process != nil {
				c.process <- &cm.QPackItem{
					Length:  int32(headerLen),
					Payload: payload,
				}
			}
		}
	}
}

func (c *TcpConn) writePump() {
	heartbeat := time.NewTicker(30 * time.Second)
	c.Wg.Add(1)
	defer func() {
		if p := recover(); p != nil {
			stacks := utils.PanicTrace(4)
			panic := fmt.Sprintf("writePump panics: %v call:%v", p, string(stacks))
			logger.ERROR(panic)

			if c.ownerNet.Panic != nil {
				c.ownerNet.Panic(c, panic)
			}
		}

		heartbeat.Stop()
		c.Wg.Done()
		logger.INFOV("addr:", c.remoteAddr, ",", c.SessionId, " write Pump defer done!!!")
	}()

	for {
		select {
		case <-c.Ctx.Done():
			logger.INFO("%v %v session write done...", c.remoteAddr, c.SessionId)
			return
		case bData, ok := <-c.send:
			if !ok {
				return
			}

			if atomic.LoadInt32(&c.IsClosed) == 1 {
				return
			}

			c.TConn.SetWriteDeadline(time.Now().Add(c.WriteTime))
			if _, err := c.TConn.Write(bData); err != nil {
				logger.ERROR("%v write Pump error:%v !!!", c.remoteAddr, err)
				return
			}
			break
		case <-heartbeat.C:
			if atomic.LoadInt32(&c.IsClosed) == 1 {
				return
			}

			c.TConn.SetWriteDeadline(time.Now().Add(c.WriteTime))
			c.SendDirect([]byte("ping")) // 发送心跳
			break
		}
	}
}

func (c *TcpConn) Send(data []byte) int {
	if atomic.LoadInt32(&c.IsClosed) == 1 {
		return -1
	}

	var (
		encode []byte
		err    error
	)

	if (c.ownerNet.RecvMode == RMReadFull || c.ownerNet.UseHeaderLen) && c.ownerNet.RecvMode != RMStringLine {
		encode, err = stream.PackerOnce(data, c.ownerNet.Encrypt, c.CryptKey)
		if err != nil {
			return -1
		}
	} else {
		encode = c.ownerNet.Encrypt(data, c.CryptKey)
	}

	select {
	case c.send <- encode:
		return len(data)
	case <-time.After(3 * time.Second):
		break
	default:
		break
	}

	return -1
}

func (c *TcpConn) SendPak(val interface{}) int {
	if atomic.LoadInt32(&c.IsClosed) == 1 {
		return -1
	}

	if c.ownerNet.Package == nil {
		logger.ERROR("%v Package Func Error,Can't Send...", c.remoteAddr)
		return -1
	}

	pack, err := c.ownerNet.Package(val)
	if err != nil {
		return -1
	}

	return c.Send(pack)
}

func (c *TcpConn) SendDirect(data []byte) int {
	if atomic.LoadInt32(&c.IsClosed) == 1 {
		return -1
	}

	var (
		encode []byte
		err    error
	)

	if (c.ownerNet.RecvMode == RMReadFull || c.ownerNet.UseHeaderLen) && c.ownerNet.RecvMode != RMStringLine {
		encode, err = stream.PackerOnce(data, c.ownerNet.Encrypt, c.CryptKey)
		if err != nil {
			return -1
		}
	} else {
		encode = c.ownerNet.Encrypt(data, c.CryptKey)
	}

	retry := c.ownerNet.SendRetry
	if retry <= 0 {
		retry = 1
	}

	for i := 0; i < retry; i++ {
		c.TConn.SetWriteDeadline(time.Now().Add(c.WriteTime))
		wn, err := c.TConn.Write(encode)
		if err != nil {
			logger.ERRORV(err)
			continue
		}

		return wn
	}

	return -1
}

func (c *TcpConn) SendPakDirect(val interface{}) int {
	if atomic.LoadInt32(&c.IsClosed) == 1 {
		return -1
	}

	if c.ownerNet.Package == nil {
		logger.ERROR("%v Package Func Error,Can't Send...", c.remoteAddr)
		return -1
	}

	pack, err := c.ownerNet.Package(val)
	if err != nil {
		return -1
	}

	return c.SendDirect(pack)
}

func (c *TcpConn) CloseSocket() {
	c.closeSock.Do(func() {
		c.Cancel()
		atomic.StoreInt32(&c.IsClosed, 1)
		c.TConn.Close() // 关闭连接
	})
}

func (c *TcpConn) Close() {
	c.Once.Do(func() {
		// 都没连上怎么关
		if c.TConn == nil {
			return
		}

		if atomic.LoadInt32(&c.IsClosed) == 0 {
			c.ownerNet.OnClose(c)
			c.CloseSocket()
		}
	})
}

func (c *TcpConn) RemoveData() {
	c.removeOnce.Do(func() {
		if atomic.LoadInt32(&c.IsClosed) == 1 {
			if c.send != nil {
				close(c.send)
				c.send = nil
			}

			if c.process != nil {
				close(c.process)
				c.process = nil
			}
		}
	})
}

func (c *TcpConn) InitData() {

}


text:
import Route from '@ember/routing/route';
import Wow from 'dummy/models/wow';

export default Route.extend({
    model: function() {
        return Wow.create();
    }
});


text:
/*
 * Created on Nov 7, 2004
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package org.cfeclipse.cfml.views.explorer;

import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;

class DirectorySorter extends ViewerSorter {
    public int compare(Viewer viewer, Object e1, Object e2) {
    	String[] item1 = e1.toString().split("/");
        String[]  item2 = e2.toString().split("/");
        String dir1 = item1[item1.length-1];
        String dir2 = item2[item2.length-1];
        return dir1.compareToIgnoreCase(dir2);
    }
}


text:
<?php

namespace Boris\Loader\Provider;

class EzPublish extends AbstractProvider
{
    public $name = 'ezpublish';

    public function assertDir($dir)
    {
        return is_file("$dir/ezpublish/bootstrap.php.cache")
            && is_file("$dir/ezpublish/EzPublishKernel.php");
    }

    public function initialize(\Boris\Boris $boris, $dir)
    {
        parent::initialize($boris, $dir);

        require "$dir/ezpublish/bootstrap.php.cache";
        require_once "$dir/ezpublish/EzPublishKernel.php";

        $kernel = new \EzPublishKernel('dev', true);
        $kernel->loadClassCache();
        $kernel->boot();

        $boris->onStart(function ($worker, $vars) use ($kernel) {
            $worker->setLocal('kernel', $kernel);
            $worker->setLocal('container', $kernel->getContainer());
        });
    }

}


text:
package org.liquidengine.legui.component.misc.listener.text;

import org.liquidengine.legui.component.TextComponent;
import org.liquidengine.legui.component.misc.listener.TextComponentShortcutUtil;
import org.liquidengine.legui.event.KeyEvent;
import org.liquidengine.legui.event.KeyboardEvent;
import org.liquidengine.legui.input.KeyAction;
import org.liquidengine.legui.input.KeyCode;
import org.liquidengine.legui.input.KeyMod;
import org.liquidengine.legui.input.Keyboard;
import org.liquidengine.legui.listener.EventListener;

import static org.liquidengine.legui.input.KeyCode.KEY_C;

/**
 * Key event listener. Used to provide some text operations by keyboard.
 */
public class CopyTextEventListener implements EventListener<KeyboardEvent>  {

    /**
     * Used to handle {@link KeyEvent}.
     *
     * @param event event to handle.
     */
    public void process(KeyboardEvent event) {
        boolean pressed = event.getAction() != KeyAction.RELEASE;
        if (!pressed) {
            return;
        }

        KeyCode copyKey = Keyboard.getCopyShortcut().getKey();
        KeyCode keyCode = event.getKey().getKeyCode();
        if (event.getMods().contains(KeyMod.CONTROL)
                && (copyKey != null && keyCode == copyKey || keyCode == KEY_C)) {
            TextComponentShortcutUtil.copy((TextComponent) event.getTargetComponent());
        }
    }

}


text:
<?php

/**
 * Advanced search form
 *
 * @author      Magento Core Team <core@magentocommerce.com>
 */
namespace Magento\CatalogSearch\Block\Advanced;

use Magento\CatalogSearch\Model\Advanced;
use Magento\Directory\Model\CurrencyFactory;
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
use Magento\Framework\Data\Collection\Db;
use Magento\Framework\View\Element\AbstractBlock;
use Magento\Framework\View\Element\BlockInterface;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

class Form extends Template
{
    /**
     * Currency factory
     *
     * @var CurrencyFactory
     */
    protected $_currencyFactory;

    /**
     * Catalog search advanced
     *
     * @var Advanced
     */
    protected $_catalogSearchAdvanced;

    /**
     * @param Context $context
     * @param Advanced $catalogSearchAdvanced
     * @param CurrencyFactory $currencyFactory
     * @param array $data
     */
    public function __construct(
        Context $context,
        Advanced $catalogSearchAdvanced,
        CurrencyFactory $currencyFactory,
        array $data = []
    ) {
        $this->_catalogSearchAdvanced = $catalogSearchAdvanced;
        $this->_currencyFactory = $currencyFactory;
        parent::__construct($context, $data);
    }

    /**
     * @return AbstractBlock
     */
    public function _prepareLayout()
    {
        // add Home breadcrumb
        if ($breadcrumbs = $this->getLayout()->getBlock('breadcrumbs')) {
            $breadcrumbs->addCrumb(
                'home',
                [
                    'label' => __('Home'),
                    'title' => __('Go to Home Page'),
                    'link' => $this->_storeManager->getStore()->getBaseUrl()
                ]
            )->addCrumb(
                'search',
                ['label' => __('Catalog Advanced Search')]
            );
        }
        return parent::_prepareLayout();
    }

    /**
     * Retrieve collection of product searchable attributes
     *
     * @return Db
     */
    public function getSearchableAttributes()
    {
        $attributes = $this->getModel()->getAttributes();
        return $attributes;
    }

    /**
     * Retrieve attribute label
     *
     * @param AbstractAttribute $attribute
     * @return string
     */
    public function getAttributeLabel($attribute)
    {
        return $attribute->getStoreLabel();
    }

    /**
     * Retrieve attribute input validation class
     *
     * @param AbstractAttribute $attribute
     * @return string
     */
    public function getAttributeValidationClass($attribute)
    {
        return $attribute->getFrontendClass();
    }

    /**
     * Retrieve search string for given field from request
     *
     * @param AbstractAttribute $attribute
     * @param string|null $part
     * @return mixed|string
     */
    public function getAttributeValue($attribute, $part = null)
    {
        $value = $this->getRequest()->getQuery($attribute->getAttributeCode());
        if ($part && $value) {
            if (isset($value[$part])) {
                $value = $value[$part];
            } else {
                $value = '';
            }
        }

        return $value;
    }

    /**
     * Retrieve the list of available currencies
     *
     * @return array
     */
    public function getAvailableCurrencies()
    {
        $currencies = $this->getData('_currencies');
        if (is_null($currencies)) {
            $currencies = [];
            $codes = $this->_storeManager->getStore()->getAvailableCurrencyCodes(true);
            if (is_array($codes) && count($codes)) {
                $rates = $this->_currencyFactory->create()->getCurrencyRates(
                    $this->_storeManager->getStore()->getBaseCurrency(),
                    $codes
                );

                foreach ($codes as $code) {
                    if (isset($rates[$code])) {
                        $currencies[$code] = $code;
                    }
                }
            }

            $this->setData('currencies', $currencies);
        }
        return $currencies;
    }

    /**
     * Count available currencies
     *
     * @return int
     */
    public function getCurrencyCount()
    {
        return count($this->getAvailableCurrencies());
    }

    /**
     * Retrieve currency code for attribute
     *
     * @param AbstractAttribute $attribute
     * @return string
     */
    public function getCurrency($attribute)
    {
        return $this->_storeManager->getStore()->getCurrentCurrencyCode();

        $baseCurrency = $this->_storeManager->getStore()->getBaseCurrency()->getCurrencyCode();
        return $this->getAttributeValue(
            $attribute,
            'currency'
        ) ? $this->getAttributeValue(
            $attribute,
            'currency'
        ) : $baseCurrency;
    }

    /**
     * Retrieve attribute input type
     *
     * @param AbstractAttribute $attribute
     * @return  string
     */
    public function getAttributeInputType($attribute)
    {
        $dataType = $attribute->getBackend()->getType();
        $imputType = $attribute->getFrontend()->getInputType();
        if ($imputType == 'select' || $imputType == 'multiselect') {
            return 'select';
        }

        if ($imputType == 'boolean') {
            return 'yesno';
        }

        if ($imputType == 'price') {
            return 'price';
        }

        if ($dataType == 'int' || $dataType == 'decimal') {
            return 'number';
        }

        if ($dataType == 'datetime') {
            return 'date';
        }

        return 'string';
    }

    /**
     * Build attribute select element html string
     *
     * @param AbstractAttribute $attribute
     * @return string
     */
    public function getAttributeSelectElement($attribute)
    {
        $extra = '';
        $options = $attribute->getSource()->getAllOptions(false);

        $name = $attribute->getAttributeCode();

        // 2 - avoid yes/no selects to be multiselects
        if (is_array($options) && count($options) > 2) {
            $extra = 'multiple="multiple" size="4"';
            $name .= '[]';
        } else {
            array_unshift($options, ['value' => '', 'label' => __('All')]);
        }

        return $this->_getSelectBlock()->setName(
            $name
        )->setId(
            $attribute->getAttributeCode()
        )->setTitle(
            $this->getAttributeLabel($attribute)
        )->setExtraParams(
            $extra
        )->setValue(
            $this->getAttributeValue($attribute)
        )->setOptions(
            $options
        )->setClass(
            'multiselect'
        )->getHtml();
    }

    /**
     * Retrieve yes/no element html for provided attribute
     *
     * @param AbstractAttribute $attribute
     * @return string
     */
    public function getAttributeYesNoElement($attribute)
    {
        $options = [
            ['value' => '', 'label' => __('All')],
            ['value' => '1', 'label' => __('Yes')],
            ['value' => '0', 'label' => __('No')],
        ];

        $name = $attribute->getAttributeCode();
        return $this->_getSelectBlock()->setName(
            $name
        )->setId(
            $attribute->getAttributeCode()
        )->setTitle(
            $this->getAttributeLabel($attribute)
        )->setExtraParams(
            ""
        )->setValue(
            $this->getAttributeValue($attribute)
        )->setOptions(
            $options
        )->getHtml();
    }

    /**
     * @return BlockInterface
     */
    protected function _getSelectBlock()
    {
        $block = $this->getData('_select_block');
        if (is_null($block)) {
            $block = $this->getLayout()->createBlock('Magento\Framework\View\Element\Html\Select');
            $this->setData('_select_block', $block);
        }
        return $block;
    }

    /**
     * @return BlockInterface|mixed
     */
    protected function _getDateBlock()
    {
        $block = $this->getData('_date_block');
        if (is_null($block)) {
            $block = $this->getLayout()->createBlock('Magento\Framework\View\Element\Html\Date');
            $this->setData('_date_block', $block);
        }
        return $block;
    }

    /**
     * Retrieve advanced search model object
     *
     * @return Advanced
     */
    public function getModel()
    {
        return $this->_catalogSearchAdvanced;
    }

    /**
     * Retrieve search form action url
     *
     * @return string
     */
    public function getSearchPostUrl()
    {
        return $this->getUrl('*/*/result');
    }

    /**
     * Build date element html string for attribute
     *
     * @param AbstractAttribute $attribute
     * @param string $part
     * @return string
     */
    public function getDateInput($attribute, $part = 'from')
    {
        $name = $attribute->getAttributeCode() . '[' . $part . ']';
        $value = $this->getAttributeValue($attribute, $part);

        return $this->_getDateBlock()->setName(
            $name
        )->setId(
            $attribute->getAttributeCode() . ($part == 'from' ? '' : '_' . $part)
        )->setTitle(
            $this->getAttributeLabel($attribute)
        )->setValue(
            $value
        )->setImage(
            $this->getViewFileUrl('Magento_Core::calendar.gif')
        )->setDateFormat(
            $this->_localeDate->getDateFormat(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::FORMAT_TYPE_SHORT)
        )->setClass(
            'input-text'
        )->getHtml();
    }
}


text:
import { StringType } from './types';
import { filter } from './utils/arrays'
import { px } from "./units";

const delimited = (delimiter: string) => {
  return function () {
    return filter(arguments, s => s || s === 0)
      .map(s => typeof s === 'number' ? px(s) : s.toString())
      .join(delimiter);
  }
};

export const params = delimited(' ') as (...parameters: (undefined | number | string | StringType<string>)[]) => string;
export const list = delimited(',') as (...items: (undefined | number | string | StringType<string>)[]) => string;


text:
begin
  require 'tokyocabinet'
rescue LoadError
  raise StandardError,
    "can't require 'tokyocabinet' library or gem, " \
    "please check it out and try again later"
end

require 'forwardable'

module Shkuph::TokyoCabinet # :nodoc:
end

class Shkuph::TokyoCabinet::Table < Shkuph::Base # :nodoc:
  include TokyoCabinet
  extend Forwardable

  def initialize(filename, configuration = {})
    super(filename, configuration)

    @shkuph = TDB.new

    table_mode = if :manage == options[:mode]
      TDB::OWRITER | TDB::OCREAT
    else
      TDB::OREADER | TDB::ONOLCK
    end

    if !@shkuph.open(filename, table_mode)
      ecode = @shkuph.ecode
      raise @shkuph.errmsg(ecode)
    end
  end

  def get(key)
    value_load(
      @shkuph[key_dump(key)]
    )
  end

  def set(key, value)
    @shkuph[key_dump(key)] = value_dump(value)
  end

  def each(&block)
    return [] unless @shkuph.iterinit
    while (iterkey = @shkuph.iternext)
      key = key_load(iterkey)
      value = value_load(
        @shkuph[key]
      )
      block.call(key, value)
    end
  end

  # Performes a query to Table Database using
  # standard Tokyo Cabinet queries.
  #
  # ==== Parameters
  def query(query_proc, &block)
    TDBQRY.new(@shkuph).
      tap(&query_proc).
      search.each_with_index do |record, index|
        key = key_load(record)
        value = value_load(@shkuph[record])
        block.call([ key, value ], index)
      end
  end

  def key?(key)
    @shkuph.has_key? key_dump(key)
  end

  def delete(key)
    if value = self[key]
      @shkuph.delete key_dump(key)
      value
    end
  end

  def clear
    @shkuph.vanish
  end

  def_delegators :@shkuph, :close
end


text:
from midonetclient import vendor_media_type
from midonetclient.dhcp_host import DhcpHost
from midonetclient.resource_base import ResourceBase

class DhcpSubnet(ResourceBase):

    media_type = vendor_media_type.APPLICATION_DHCP_SUBNET_JSON

    def __init__(self, uri, dto, auth):
        super(DhcpSubnet, self).__init__(uri, dto, auth)

    def get_default_gateway(self):
        return self.dto['defaultGateway']

    def get_server_addr(self):
        return self.dto['serverAddr']

    def get_dns_server_addrs(self):
        return self.dto['dnsServerAddrs']

    def get_subnet_prefix(self):
        return self.dto['subnetPrefix']

    def get_subnet_length(self):
        return self.dto['subnetLength']

    def get_interface_mtu(self):
        return self.dto['interfaceMTU']

    def get_opt121_routes(self):
        return self.dto['opt121Routes']

    def is_enabled(self):
        return self.dto["enabled"]

    def default_gateway(self, gw):
        self.dto['defaultGateway'] = gw
        return self

    def server_addr(self, addr):
        self.dto['serverAddr'] = addr
        return self

    def dns_server_addrs(self, addrs):
        self.dto['dnsServerAddrs'] = addrs
        return self

    def subnet_prefix(self, prefix):
        self.dto['subnetPrefix'] = prefix
        return self

    def subnet_length(self, length):
        self.dto['subnetLength'] = length
        return self

    def interface_mtu(self, mtu):
        self.dto['interfaceMTU'] = mtu
        return self

    def opt121_routes(self, routes):
        self.dto['opt121Routes'] = routes
        return self

    def enabled(self, enabled):
        self.dto['enabled'] = enabled
        return self

    def get_dhcp_hosts(self):
        query = {}
        headers = {'Accept':
                   vendor_media_type.APPLICATION_DHCP_HOST_COLLECTION_JSON}
        return self.get_children(self.dto['hosts'], query, headers,
                                 DhcpHost)

    def get_dhcp_host(self, ip_addr, mac):
        """
        Given the IP address and mac, returns DhcpHost object
        """
        for dh in self.get_dhcp_hosts():
            if dh.get_ip_addr() == ip_addr and dh.get_mac_addr() == mac:
                return dh
        return None

    def add_dhcp_host(self):
        return DhcpHost(self.dto['hosts'], {}, self.auth)


text:
<html><head>
    <meta name="go-import" content="istio.io/pkg git https://github.com/istio/pkg">
    <meta name="go-source" content="istio.io/pkg     https://github.com/istio/pkg https://github.com/istio/pkg/tree/master{/dir} https://github.com/istio/pkg/blob/master{/dir}/{file}#L{line}">
</head></html>


text:
#ifndef __PU_VORTEX_AFFECTOR_TOKENS_H__
#define __PU_VORTEX_AFFECTOR_TOKENS_H__

#include "ParticleUniversePrerequisites.h"
#include "ParticleUniverseAffectorTokens.h"

namespace ParticleUniverse
{
	/** The VortexAffectorTranslator parses 'VortexAffector' tokens
	*/
	class _ParticleUniverseExport VortexAffectorTranslator : public ScriptTranslator
	{
		public:
			VortexAffectorTranslator(void){};
			~VortexAffectorTranslator(void){};
			virtual bool translateChildProperty(ScriptCompiler* compiler, const AbstractNodePtr &node);
			virtual bool translateChildObject(ScriptCompiler* compiler, const AbstractNodePtr &node);
	};
	//-------------------------------------------------------------------------
	//-------------------------------------------------------------------------
	//-------------------------------------------------------------------------

	/**
    */
	class _ParticleUniverseExport VortexAffectorWriter : public ParticleAffectorWriter
	{
		public:

			VortexAffectorWriter(void) {};
			virtual ~VortexAffectorWriter(void) {};

			/** @see
				ScriptWriter::write
			*/
			virtual void write(ParticleScriptSerializer* serializer , const IElement* element);
	};

}
#endif


text:
package springfox.test.contract.swagger.data.rest;

import org.springframework.data.repository.CrudRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;

@RepositoryRestResource(path = "tags")
public interface TagRepository extends CrudRepository<Tag, Long> {
}


text:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="bc.css">

Forge DA4R IFC Support and Snoop Enhancements

Let's close this eventful week with two important enhancements added to the Forge Design Automation API for Revit and our beloved RevitLookup tool:

IFC Support in the Design Automation for Revit API

RevitLookup Snoop Enhancements

 IFC Support in the Design Automation for Revit API

Ryan Duell, Project Manager in The Factory just announced IFC support now added to
the Forge Design Automation API for Revit, stating:

We recently added IFC support to Design Automation for Revit.  The supported functionality for each Revit version is as follows:

Revit 2018

Open IFC

Export IFC

Revit 2019

Open IFC

Export IFC

Link IFC

Revit 2020 (coming soon)

Open IFC

Export IFC

Link IFC

Additional documentation will be added asap.

Revit 2018 does not support link IFC functionality at this time.

This support will come in handy for my IfcSpaceZoneBoundaries project.

It needs to link in an IFC file into a Revit project to generate certain room and space information.

That was previously not possible in the Forge DA4R environment, and now it is.

Many thanks to Ryan and The Factory for this important step forward!

Please refer to The Building Coder topic group
for more information on DA4R.

 RevitLookup Snoop Enhancements

Alexander @CADBIMDeveloper Ignatovich, aka Александр Игнатович,
shared several useful improvements for the RevitLookup snoop commands in
his pull request #52; he explains:

I added some improvements that I require in
the RevitLookup tool during
my development process. So here they are :-)

Added to the main results data window:

Dependent elements

View filter overrides and visibility

Element state in different phases

First of all, I added the results of calling the GetDependentElements method to the main tool window.
I faced the situation when I explored the dependent elements of the dependent element (e.g., the dependency tree).
It was also useful to explore the dependent elements of the results by collecting the database elements using the lookup method in the Revit Iron Python Shell.

Further, I worked a lot with view filter overrides and visibility. I wanted to see these in the lookup tool. So, I added the View.GetFilterOverrides and View.GetFilterVisibility method results to the objects window.

For the last improvement, I explored the element statuses in different phases, so I also added this functionality as well.

Here is the complete list of changes:

allow RevitLookup to snoop dependent elements via main interface

preserve alphabetical methods order and simplify the code

the first step to allow create "Objects" form elements with predefined titles

introduce snoopable object wrapper to simplify the code

extract method

extract methods

extract data factory and simplify the code of ElementMethodsStream class

snoop view filter overrides settings

colour components are not available for invalid colour values

allow to snoop view filters visibility values

snoop Element.GetPhaseStatus

rename class

Some of these enhancement are hosted in new C# snooping modules:

Snoop/CollectorExts

DataFactory.cs

Snoop/Data

ElementPhaseStatuses.cs

SnoopableObjectWrapper.cs

ViewFiltersOverrideGraphicSettings.cs

ViewFiltersVisibilitySettings.cs

Here is a sample model containing a wall with two dependent elements, a door and a window:

Snooping the wall data lists the two dependent elements:

Clicking on the list enables us to jump straight into the dependent element data:

Many thanks to Alex for his clean implementation and kind sharing of these powerful enhancements!

The new enhancements are integrated
in RevitLookup release 2020.0.0.1.


text:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using DTcms.Common;

namespace DTcms.Web.admin.goods
{
    public partial class handling_mode_edit : Web.UI.ManagePage
    {
        private string action = DTEnums.ActionEnum.Add.ToString(); //操作类型
        private int id = 0;

        protected void Page_Load(object sender, EventArgs e)
        {
            //取到操作类型
            string _action = DTRequest.GetQueryString("action");
            if (!string.IsNullOrEmpty(_action) && _action == DTEnums.ActionEnum.Edit.ToString())
            {
                this.action = DTEnums.ActionEnum.Edit.ToString();//修改类型
                this.id = DTRequest.GetQueryInt("id");
                if (this.id == 0)
                {
                    JscriptMsg("传输参数不正确!", "back");
                    return;
                }
                if (!new BLL.HandlingMode().Exists(this.id))
                {
                    JscriptMsg("装卸方式不存在或已被删除!", "back");
                    return;
                }
            }
            if (!Page.IsPostBack)
            {
                ChkAdminLevel("handling_mode", DTEnums.ActionEnum.View.ToString()); //检查权限
                if (action == DTEnums.ActionEnum.Edit.ToString()) //修改
                {
                    ShowInfo(this.id);
                }
            }
        }

        #region 赋值操作=================================
        private void ShowInfo(int _id)
        {
            BLL.HandlingMode bll = new BLL.HandlingMode();
            Model.HandlingMode model = bll.GetModel(_id);
            txtName.Text = model.Name;
            txtRemark.Text = model.Remark;
        }
        #endregion

        #region 增加操作=================================
        private bool DoAdd()
        {
            bool result = false;
            Model.HandlingMode model = new Model.HandlingMode();
            BLL.HandlingMode bll = new BLL.HandlingMode();

            model.Name = txtName.Text;
            model.Remark = txtRemark.Text;
            if (bll.Add(model))
            {
                AddAdminLog(DTEnums.ActionEnum.Add.ToString(), "添加装卸方式:" + model.Name); //记录日志
                result = true;
            }
            return result;
        }
        #endregion

        #region 修改操作=================================
        private bool DoEdit(int _id)
        {
            bool result = false;
            BLL.HandlingMode bll = new BLL.HandlingMode();
            Model.HandlingMode model = bll.GetModel(_id);

            model.Name = txtName.Text;
            model.Remark = txtRemark.Text;
            if (bll.Update(model))
            {
                AddAdminLog(DTEnums.ActionEnum.Edit.ToString(), "修改装卸方式:" + model.Name); //记录日志
                result = true;
            }

            return result;
        }
        #endregion

        // 提交保存
        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            if (action == DTEnums.ActionEnum.Edit.ToString()) //修改
            {
                ChkAdminLevel("handling_mode", DTEnums.ActionEnum.Edit.ToString()); //检查权限
                if (!DoEdit(this.id))
                {
                    JscriptMsg("保存过程中发生错误!", "");
                    return;
                }
                JscriptMsg("修改装卸方式成功!", "handling_mode_list.aspx");
            }
            else //添加
            {
                ChkAdminLevel("handling_mode", DTEnums.ActionEnum.Add.ToString()); //检查权限
                if (!DoAdd())
                {
                    JscriptMsg("保存过程中发生错误!", "");
                    return;
                }
                JscriptMsg("添加装卸方式成功!", "handling_mode_list.aspx");
            }
        }

    }
}


text:
import { Application } from '@nativescript/core'
import { warn } from 'core/util/index'
import { patch } from './patch'
import { mountComponent } from 'core/instance/lifecycle'
import { compileToFunctions } from '../compiler/index'
import { mustUseProp, isReservedTag, isUnknownElement } from '../util/index'
import { registerElement, getElementMap } from '../element-registry'

import Vue from 'core/index'
import DocumentNode from '../renderer/DocumentNode'
import platformDirectives from './directives/index'

Vue.config.mustUseProp = mustUseProp
Vue.config.isReservedTag = isReservedTag
Vue.config.isUnknownElement = isUnknownElement

Vue.$document = Vue.prototype.$document = new DocumentNode()

Vue.compile = compileToFunctions
Vue.registerElement = registerElement

Object.assign(Vue.options.directives, platformDirectives)

Vue.prototype.__patch__ = patch

Vue.prototype.$mount = function (el, hydrating) {
  const options = this.$options
  // resolve template/el and convert to render function
  if (!options.render) {
    let template = options.template
    if (template && typeof template !== 'string') {
      warn('invalid template option: ' + template, this)
      return this
    }

    if (template) {
      const { render, staticRenderFns } = compileToFunctions(
        template,
        {
          delimiters: options.delimiters,
          comments: options.comments
        },
        this
      )
      options.render = render
      options.staticRenderFns = staticRenderFns
    }
  }

  return mountComponent(this, el, hydrating)
}

Vue.prototype.$start = function () {
  let self = this
  const AppConstructor = Vue.extend(this.$options)

  // register NS components into Vue
  Object.values(getElementMap()).forEach(entry => {
    Vue.component(entry.meta.component.name, entry.meta.component)
  })

  Application.run({
    create() {
      if (self.$el) {
        self.$destroy()
        self = new AppConstructor()
      }

      self.$mount()
      return self.$el.nativeView
    }
  })
}

// Define a `nativeView` getter in every NS vue instance
Object.defineProperty(Vue.prototype, 'nativeView', {
  get() {
    return this.$el ? this.$el.nativeView : undefined
  }
})

export default Vue


text:
set langue to arabic hard coded
edit this file `/app/Http/Middleware/Custom/Locale.php`
where
```
$language = Session::get('language', Config::get('app.locale'));
```
to
```
$language = Session::get('language', 'ar');
```
also add the arabic language to the language table


text:
package com.easyjf.web.components.form;

import com.easyjf.beans.BeanWrapper;
import com.easyjf.web.components.BoxComponent;
/**
 *
 * @author 大峡
 *
 */
public abstract class Field extends BoxComponent {
	private Boolean disabled;
	private String fieldLabel;
	private Boolean hideLabel;
	private String inputType;
	private String labelSeparator;
	private String name;
	private Boolean readOnly;
	private Integer tabIndex;
	private String value;

	private String invalidText;
	public Field() {

	}

	public Field(String name, String label) {
		this(name, label, null, null);
	}

	public Field(String name, String label, Object value) {
		this(name, label, value, null);
	}

	public Field(String name, String label, Object value, Integer width) {
		this.name = name;
		this.fieldLabel = label;
		this.value = (value == null ? "" : value.toString());
		this.setWidth(width);
	}

	public String clz() {
		return "Ext.form.Field";
	}

	/**
	 * 把字段与某一对象进行绑定
	 *
	 * @param object
	 * @param property
	 */
	public void bind(Object object, String property) {
		if (this.fieldLabel == null && !this.hideLabel) {
			this.fieldLabel = property;
		}
		BeanWrapper wrapper = new BeanWrapper(object);
		Object value = wrapper.getPropertyValue(property);
		this.value = (value == null ? "" : value.toString());
	}

	public Boolean getDisabled() {
		return disabled;
	}

	public void setDisabled(Boolean disabled) {
		this.disabled = disabled;
	}

	public Boolean getHideLabel() {
		return hideLabel;
	}

	public void setHideLabel(Boolean hideLabel) {
		this.hideLabel = hideLabel;
	}

	public String getInputType() {
		return inputType;
	}

	public void setInputType(String inputType) {
		this.inputType = inputType;
	}

	public String getLabelSeparator() {
		return labelSeparator;
	}

	public void setLabelSeparator(String labelSeparator) {
		this.labelSeparator = labelSeparator;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Boolean getReadOnly() {
		return readOnly;
	}

	public void setReadOnly(Boolean readOnly) {
		this.readOnly = readOnly;
	}

	public Integer getTabIndex() {
		return tabIndex;
	}

	public void setTabIndex(Integer tabIndex) {
		this.tabIndex = tabIndex;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}

	public String getFieldLabel() {
		return fieldLabel;
	}

	public void setFieldLabel(String fieldLabel) {
		this.fieldLabel = fieldLabel;
	}

	public String getInvalidText() {
		return invalidText;
	}

	public void setInvalidText(String invalidText) {
		this.invalidText = invalidText;
	}

}


text:
<idea-plugin version="2">
    <id>com.microsoftopentechnologies.intellij</id>
    <name>MSOpenTech Tools</name>
    <version>0.1.36</version>
    <vendor email="msopentech@microsoft.com" logo="/com/microsoftopentechnologies/intellij/icons/logo.png" url="http://msopentech.com">Microsoft Open Technologies, Inc.</vendor>

    <description><![CDATA[
  Tools for easy development of apps connected to Microsoft Services. Current SDKs and management tools covers the following:

Microsoft Azure Mobile Services for storage, authentication and custom scripts for IntelliJ IDEA and Android Studio

Push Notification for IntelliJ IDEA and Android Studio

Office 365 Outlook Services for IntelliJ IDEA and Android Studio

Office 365 File Services for IntelliJ IDEA and Android Studio

Office 365 SharePoint Lists for IntelliJ IDEA and Android Studio

Azure Tools for Java for IntelliJ IDEA

   License

   By installing the MS Open Tech Tools  plugin, you agree to this license.
   Third party notices: http://go.microsoft.com/fwlink/?LinkId=517840
  ]]></description>

    <change-notes><![CDATA[
      First version.

      ]]>
    </change-notes>

    <idea-version since-build="135.1"/>

    <resource-bundle>com.microsoftopentechnologies.intellij.ui.messages.messages</resource-bundle>

    <depends optional="true">AntSupport</depends>
    <depends>com.intellij.modules.java</depends>
    <depends>com.intellij.modules.lang</depends>
    <depends>org.jetbrains.plugins.gradle</depends>

    <extensions defaultExtensionNs="com.intellij">
        <toolWindow
                anchor="left"
                factoryClass="com.microsoftopentechnologies.intellij.components.ServerExplorerToolWindowFactory"
                id="Service Explorer"
                canCloseContents="false"
                icon="/com/microsoftopentechnologies/intellij/icons/azure.png"/>
        <toolWindow
                anchor="bottom"
                factoryClass="com.microsoftopentechnologies.intellij.activitylog.ActivityLogToolWindowFactory"
                id="Azure Activity Log"
                canCloseContents="true"
                icon="/icons/RoleFolder.gif"
                conditionClass="com.microsoftopentechnologies.intellij.activitylog.ActivityLogToolWindowFactoryCondition"/>
        <moduleType id="AZURE_MODULE"
                    implementationClass="com.microsoftopentechnologies.intellij.module.AzureModuleType"/>
        <moduleConfigurationEditorProvider
                implementation="com.microsoftopentechnologies.intellij.module.AzureModuleConfigurationEditorProvider"/>
        <projectConfigurable instance="com.microsoftopentechnologies.intellij.AzureConfigurable"/>
        <iconProvider implementation="com.microsoftopentechnologies.intellij.AzureIconProvider"
                      order="before javaDirectory"/>
        <projectService serviceInterface="com.microsoftopentechnologies.intellij.AzureSettings"
                        serviceImplementation="com.microsoftopentechnologies.intellij.AzureSettings"/>
    </extensions>

    <application-components>
        <component>
            <implementation-class>com.microsoftopentechnologies.intellij.components.MSOpenTechToolsApplication</implementation-class>
        </component>
        <component>
            <implementation-class>com.microsoftopentechnologies.intellij.AzureActionsComponent</implementation-class>
        </component>
    </application-components>

    <project-components>
        <component>
            <implementation-class>com.microsoftopentechnologies.intellij.AzurePlugin</implementation-class>
            <loadForDefaultProject/>
        </component>
        <component>
            <implementation-class>com.microsoftopentechnologies.intellij.components.MSOpenTechToolsProject</implementation-class>
            <loadForDefaultProject/>
        </component>
    </project-components>

    <module-components>
    </module-components>

    <actions>
        <action id="Actions.RunInEmulatorAction"
                class="com.microsoftopentechnologies.intellij.actions.RunInEmulatorAction" text="Run in Azure Emulator"
                description="Run in Azure Emulator" icon="/icons/RunEmulatorIcon.png"/>
        <action id="Actions.ResetEmulatorAction"
                class="com.microsoftopentechnologies.intellij.actions.ResetEmulatorAction" text="Reset Azure Emulator"
                description="Reset Azure Emulator" icon="/icons/ResetEmulatorIcon.png"/>
        <action id="Actions.PackageAction" class="com.microsoftopentechnologies.intellij.actions.PackageAction"
                text="Package for Azure"
                description="Package for Azure" icon="/icons/small/cloudService.png"/>
        <action id="Actions.DeployAction" class="com.microsoftopentechnologies.intellij.actions.DeployAction"
                text="Publish to Azure"
                description="Publish to Azure Cloud" icon="/icons/publish.png"/>
        <action id="Actions.UnpublishAction" class="com.microsoftopentechnologies.intellij.actions.UnpublishAction"
                text="Unpublish"
                description="Unpublish" icon="/icons/unpublish.png"/>
        <action id="Actions.BuildPackageAction"
                class="com.microsoftopentechnologies.intellij.actions.BuildPackageAction"
                text="Build Cloud Package for Azure"
                description="Build Cloud Package for Azure" icon="/icons/BuildToCloudIcon.png"/>
        <action id="Actions.RolePropertiesAction"
                class="com.microsoftopentechnologies.intellij.actions.RolePropertiesAction" text="Role Properties"
                description="Role Properties"/>
        <action id="Actions.ModulePropertiesAction"
                class="com.microsoftopentechnologies.intellij.actions.ModulePropertiesAction" text="Properties..."
                description="Properties..." icon="/icons/small/cloudService.png"/>

        <group id="AzurePopupGroup" text="Azure" description="Azure" icon="/icons/small/windowsAzure.png" popup="true"
               class="com.microsoftopentechnologies.intellij.actions.AzurePopupGroup">
            <reference ref="Actions.PackageAction"/>
            <separator/>
            <reference ref="Actions.DeployAction"/>
            <reference ref="Actions.UnpublishAction"/>
            <reference ref="Actions.RolePropertiesAction"/>
            <separator/>
            <reference ref="Actions.ModulePropertiesAction"/>
        </group>

        <group id="AzureToolbarGroup" text="Azure" description="Azure">
            <reference ref="Actions.RunInEmulatorAction"/>
            <reference ref="Actions.ResetEmulatorAction"/>
            <reference ref="Actions.BuildPackageAction"/>
            <reference ref="Actions.PackageAction"/>
            <reference ref="Actions.DeployAction"/>
            <reference ref="Actions.UnpublishAction"/>
        </group>
    </actions>

    <helpset file="msopentech-tools-help.jar" path="/helpset.hs"/>
</idea-plugin>


text:
package pl.bukkit.team.protocols;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.bukkit.Bukkit;

public final class Reflection {

	public interface ConstructorInvoker {
		public Object invoke(Object... arguments);
	}

	public interface MethodInvoker {
		public Object invoke(Object target, Object... arguments);
	}

	public interface FieldAccessor<T> {
		public T get(Object target);

		public void set(Object target, Object value);

		public boolean hasField(Object target);
	}

	private static String OBC_PREFIX = Bukkit.getServer().getClass()
			.getPackage().getName();
	private static String NMS_PREFIX = OBC_PREFIX.replace(
			"org.bukkit.craftbukkit", "net.minecraft.server");
	private static String VERSION = OBC_PREFIX.replace(
			"org.bukkit.craftbukkit", "").replace(".", "");

	private static Pattern MATCH_VARIABLE = Pattern.compile("\\{([^\\}]+)\\}");

	private Reflection() {
	}

	public static <T> FieldAccessor<T> getField(Class<?> target, String name,
			Class<T> fieldType) {
		return getField(target, name, fieldType, 0);
	}

	public static <T> FieldAccessor<T> getField(String className, String name,
			Class<T> fieldType) {
		return getField(getClass(className), name, fieldType, 0);
	}

	public static <T> FieldAccessor<T> getField(Class<?> target,
			Class<T> fieldType, int index) {
		return getField(target, null, fieldType, index);
	}

	public static <T> FieldAccessor<T> getField(String className,
			Class<T> fieldType, int index) {
		return getField(getClass(className), fieldType, index);
	}

	private static <T> FieldAccessor<T> getField(Class<?> target, String name,
			Class<T> fieldType, int index) {
		for (final Field field : target.getDeclaredFields()) {
			if ((name == null || field.getName().equals(name))
					&& fieldType.isAssignableFrom(field.getType())
					&& index-- <= 0) {
				field.setAccessible(true);

				return new FieldAccessor<T>() {

					@Override
					@SuppressWarnings("unchecked")
					public T get(Object target) {
						try {
							return (T) field.get(target);
						} catch (IllegalAccessException e) {
							throw new RuntimeException(
									"Cannot access reflection.", e);
						}
					}

					@Override
					public void set(Object target, Object value) {
						try {
							field.set(target, value);
						} catch (IllegalAccessException e) {
							throw new RuntimeException(
									"Cannot access reflection.", e);
						}
					}

					@Override
					public boolean hasField(Object target) {
						return field.getDeclaringClass().isAssignableFrom(
								target.getClass());
					}
				};
			}
		}

		if (target.getSuperclass() != null)
			return getField(target.getSuperclass(), name, fieldType, index);

		throw new IllegalArgumentException("Cannot find field with type "
				+ fieldType);
	}

	public static MethodInvoker getMethod(String className, String methodName,
			Class<?>... params) {
		return getTypedMethod(getClass(className), methodName, null, params);
	}

	public static MethodInvoker getMethod(Class<?> clazz, String methodName,
			Class<?>... params) {
		return getTypedMethod(clazz, methodName, null, params);
	}

	public static MethodInvoker getTypedMethod(Class<?> clazz,
			String methodName, Class<?> returnType, Class<?>... params) {
		for (final Method method : clazz.getDeclaredMethods()) {
			if ((methodName == null || method.getName().equals(methodName))
					&& (returnType == null)
					|| method.getReturnType().equals(returnType)
					&& Arrays.equals(method.getParameterTypes(), params)) {
				method.setAccessible(true);

				return new MethodInvoker() {

					@Override
					public Object invoke(Object target, Object... arguments) {
						try {
							return method.invoke(target, arguments);
						} catch (Exception e) {
							throw new RuntimeException("Cannot invoke method "
									+ method, e);
						}
					}

				};
			}
		}

		if (clazz.getSuperclass() != null)
			return getMethod(clazz.getSuperclass(), methodName, params);

		throw new IllegalStateException(String.format(
				"Unable to find method %s (%s).", methodName,
				Arrays.asList(params)));
	}

	public static ConstructorInvoker getConstructor(String className,
			Class<?>... params) {
		return getConstructor(getClass(className), params);
	}

	public static ConstructorInvoker getConstructor(Class<?> clazz,
			Class<?>... params) {
		for (final Constructor<?> constructor : clazz.getDeclaredConstructors()) {
			if (Arrays.equals(constructor.getParameterTypes(), params)) {
				constructor.setAccessible(true);

				return new ConstructorInvoker() {

					@Override
					public Object invoke(Object... arguments) {
						try {
							return constructor.newInstance(arguments);
						} catch (Exception e) {
							throw new RuntimeException(
									"Cannot invoke constructor " + constructor,
									e);
						}
					}

				};
			}
		}

		throw new IllegalStateException(String.format(
				"Unable to find constructor for %s (%s).", clazz,
				Arrays.asList(params)));
	}

	public static Class<Object> getUntypedClass(String lookupName) {
		@SuppressWarnings({ "rawtypes", "unchecked" })
		Class<Object> clazz = (Class) getClass(lookupName);
		return clazz;
	}

	public static Class<?> getClass(String lookupName) {
		return getCanonicalClass(expandVariables(lookupName));
	}

	public static Class<?> getNewClass(String lookupName) {
		return getCanonicalClass(lookupName);
	}

	public static Class<?> getMinecraftClass(String name) {
		return getCanonicalClass(NMS_PREFIX + "." + name);
	}

	public static Class<?> getCraftBukkitClass(String name) {
		return getCanonicalClass(OBC_PREFIX + "." + name);
	}

	private static Class<?> getCanonicalClass(String canonicalName) {
		try {
			return Class.forName(canonicalName);
		} catch (ClassNotFoundException e) {
			throw new IllegalArgumentException("Cannot find " + canonicalName,
					e);
		}
	}

	private static String expandVariables(String name) {
		StringBuffer output = new StringBuffer();
		Matcher matcher = MATCH_VARIABLE.matcher(name);

		while (matcher.find()) {
			String variable = matcher.group(1);
			String replacement = "";

			if ("nms".equalsIgnoreCase(variable))
				replacement = NMS_PREFIX;
			else if ("obc".equalsIgnoreCase(variable))
				replacement = OBC_PREFIX;
			else if ("version".equalsIgnoreCase(variable))
				replacement = VERSION;
			else
				throw new IllegalArgumentException("Unknown variable: "
						+ variable);

			if (replacement.length() > 0 && matcher.end() < name.length()
					&& name.charAt(matcher.end()) != '.')
				replacement += ".";
			matcher.appendReplacement(output,
					Matcher.quoteReplacement(replacement));
		}

		matcher.appendTail(output);
		return output.toString();
	}
}