text:
layout: post
title: UITableView에서 header와 footer 높이 변경하기
category: ios
tags: [ios, sdk, uitableview, header, footer, height, objective-c]
comments: true
redirect_from: /165/
disqus_identifier : http://blog.saltfactory.net/165
---

## 서론

UITableView는 iOS 기반 앱을 개발할 때 가장 많이 사용하는 UIKit 중에 하나이다. 이러한 UITableView에서는 UITable의 속성을 외부에서 (다른 클래스에서)변경하기 쉽게 하기 위해서 View의 처리를 하는 부분을 위임하는 delgate 방식을 사용한다. (물론 속성을 바로 접근해서 사용할 수 있는 것도 있다.)

<!--more-->

이 아티클에서 테스트를 하기 위해서 우리는 empty 프로젝트를 하나 만들고 UITableView 기반의 ViewController를 하나 추가하자. 이름은 SFTableViewController라고 지정했다. 편의에 맞게 다른 이름을 사용해도 상관없다. 그리고 특별히 XIB는 생성하지 않는다. 특별한 UI 구성 이외에 XIB를 사용할 일이 거의 없기 때문이다.

![](http://asset.blog.hibrainapps.net/saltfactory/images/f4bfed12-4992-4654-aeea-dba04eeae5ff)

뷰컨트롤러를 추가하고 난 다음에는 우리는 테스트를 위해서 AppDelegate에 UINavigationController에 포함되어서 가장 처음에 나타나게 rootViewController로 지정할 것이다.

```objective-c
//
//  SFAppDelegate.m
//  SFTableViewTutorial
//
//  Created by saltfactory on 8/10/12.
//  Copyright (c) 2012 saltfactory.net. All rights reserved.
//

#import "SFAppDelegate.h"
#import "SFTableViewController.h"
@implementation SFAppDelegate

@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    // Override point for customization after application launch.
    SFTableViewController *tableViewController = [[SFTableViewController alloc] init];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
    self.window.rootViewController = navigationController;

    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

.. 이하 생략
```

build 하고 실행하면 다음과 같이 비어있는 UITableView가 보이게 될 것이다.

![](http://asset.blog.hibrainapps.net/saltfactory/images/78f73d65-4ed5-4e0e-9ea5-24662a456aa3)

우리는 테스트를 위해서 HeaderView를 가질수 있게 임시 데이터를 저장해보자. 간단하게 NSMutableDictionary에 두가지 데이터를 집어넣었고 각각 First Items와 Second Items라는 Key를 가지고 저장이 되었다.

```objective-c
//
//  SFTableViewController.m
//  SFTableViewTutorial
//
//  Created by saltfactory on 8/10/12.
//  Copyright (c) 2012 saltfactory.net. All rights reserved.
//

#import "SFTableViewController.h"

@interface SFTableViewController ()
{
    NSMutableDictionary *itemsInfo;
}
@end

... 중략...
- (void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
    self.title = @"UITableView Test";
}

- (id)init
{
    self = [super initWithStyle:UITableViewStylePlain];
    if (self){
        itemsInfo = [NSMutableDictionary dictionary];

        NSArray *firstItems = [NSArray arrayWithObjects:@"date1", @"date2", @"date3", nil];
        [itemsInfo setValue:firstItems forKey:@"First Items"];

        NSArray *secondItems = [NSArray arrayWithObjects:@"items1", @"items2", @"items3", nil];
        [itemsInfo setValue:secondItems forKey:@"Second Items"];

    }
    return self;
}
... 생략 ...
```

다음에는 UITableView 가 사용하는 데이터를 어떻게 다룰건지 DataSource에 대한 UITableView의 delegate method를 구현한다. itemsInfo에서 key 갯수만큼 section을 만들고 그 section 별로 저장된 데이터를 가져와서 UITableView의  cell.textLabel에 나타날 수 있게 하였다.

```objective-c
... 생략 ...
#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return [[itemsInfo allKeys] count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    NSString *key = [[itemsInfo allKeys] objectAtIndex:section];
    return [[itemsInfo objectForKey:key] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell...
    if (cell == nil) {
        cell =[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }

    NSString *key = [[itemsInfo allKeys] objectAtIndex:indexPath.section];
    cell.textLabel.text =[[itemsInfo objectForKey:key] objectAtIndex:indexPath.row];

    return cell;
}
... 생략 ...
```

다시한번 Build하고 Run 시켜보자. 우리가 의도한 대로 데이터가 나왔는가? 우리가 의도한 UITableView의 형태는 Header를 가지고 있는 모양이다. 하지만 위의 코드는 UITableView의 cell에 대한 코드만 존재를 한다.

![](http://asset.blog.hibrainapps.net/saltfactory/images/2dda44db-ca56-489d-a540-94e85f8caa94)

우리는 Header를 만들기 위해서 다음 UITableView의 뷰 속성을 다루는 delegate method를 구현하기 위해서 다음 코드를 추가한다.

```objective-c
#pragma mark - UITableView delegate method
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return [[itemsInfo allKeys] objectAtIndex:section];
}
```

다시 build하고 run 실행해보자. 이제 우리가 의도한 header view가 나타났다. 각 섹션별로 그 섹션의 key가 나타나게 된 것이다.

![](http://asset.blog.hibrainapps.net/saltfactory/images/17720321-282e-4e91-b447-6b9c1ebeb533)

그리고 footer view를 추가하기 위해서 다음과 같이 코드를 수정해보자. 아이템별로 description을 footer에 추가한다.

```objective-c
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
    return section == 0 ? @"first items description" : @"second items description";
}
```

![](http://asset.blog.hibrainapps.net/saltfactory/images/b9b00615-b1de-4662-b6de-d5dacd053381)

UITableViewStylePlain에 모양에서 이렇게 나타나지만 UITableViewGrouped 에서는 다음과 같이 나타난다.

```objective-c
- (id)init
{
    self = [super initWithStyle:UITableViewStyleGrouped];
    if (self){
        itemsInfo = [NSMutableDictionary dictionary];

        NSArray *firstItems = [NSArray arrayWithObjects:@"date1", @"date2", @"date3", nil];
        [itemsInfo setValue:firstItems forKey:@"First Items"];

        NSArray *secondItems = [NSArray arrayWithObjects:@"items1", @"items2", @"items3", nil];
        [itemsInfo setValue:secondItems forKey:@"Second Items"];

    }
    return self;
}
```

## UITableView Header, Footer 높이조절

![](http://asset.blog.hibrainapps.net/saltfactory/images/fc1196ab-7ba8-4d53-9f38-ea0a38308162)

이제 우리가 원하는 Heade와 Footer의 높이를 조절해보자. UITableView의 view delegate를 구현하기 위해서 다음 코드를 추가한다. 높이를 확인하기 위해서 tableView의 style을 다시 UITableViewStylePlain으로 변경한다.

```objective-c
- (float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 44;
}

- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 44;
}
```

다시 build와 run을 해보면 header와 footer의 높이가 변경된 것을 확인할 수 있을 것이다.

![](http://asset.blog.hibrainapps.net/saltfactory/images/8859fa40-b9d5-404a-92c7-32d88c754afd)

만약 UITableViewController를 상속받아서 만들어서 사용하지 않고 UIViewController에 UITableView를 추가해서 사용할 경우도 동일하다. 우리는 UITableViewController를 상속받아서 만든 SFTableViewController를 UIViewController를 상속받아서 사용하는 것으로 변경할 것이다.
SFTableViewController.h 파일을 다음과 같이 수정한다.

```objective-c
//
//  SFTableViewController.h
//  SFTableViewTutorial
//
//  Created by saltfactory on 8/10/12.
//  Copyright (c) 2012 saltfactory.net. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface SFTableViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>;
@property (nonatomic, strong) UITableView *tableView;
@end
```

SFTableViewController.m 파일을 다음과 같이 수정한다.

```objective-c
//
//  SFTableViewController.m
//  SFTableViewTutorial
//
//  Created by saltfactory on 8/10/12.
//  Copyright (c) 2012 saltfactory.net. All rights reserved.
//

#import "SFTableViewController.h"

@interface SFTableViewController ()
{
    NSMutableDictionary *itemsInfo;
}
@end

@implementation SFTableViewController
@synthesize tableView;
//- (id)initWithStyle:(UITableViewStyle)style
//{
//    self = [super initWithStyle:style];
//    if (self) {
//        // Custom initialization
//    }
//    return self;
//}

- (id)init
{
//    self = [super initWithStyle:UITableViewStylePlain];
    self = [super init];
    if (self){
        itemsInfo = [NSMutableDictionary dictionary];

        NSArray *firstItems = [NSArray arrayWithObjects:@"date1", @"date2", @"date3", nil];
        [itemsInfo setValue:firstItems forKey:@"First Items"];

        NSArray *secondItems = [NSArray arrayWithObjects:@"items1", @"items2", @"items3", nil];
        [itemsInfo setValue:secondItems forKey:@"Second Items"];

    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
    self.title = @"UITableView Test";

    self.tableView  = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    [self.view addSubview:self.tableView];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.tableView = nil;

```

다른 UITableView의 data source delegate와 view delegate는 동일하게 위임해서 구현하기 때문에 변경할 필요가 없다. Build하고 Run을 실행해보면 위에서 나타난 결과와 동일하게 확인할 수 있을 것이다. 즉, UITableView의 header와 footer의 높이를 변경하기 위해서는 UITableView의 delegate 메소드인
- (float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 과 - (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section 메소를 이용해서 사용할 수 있다. 또한 다음과 같이 tableView.sectionHeaderHeight 와 tableView.sectionFooterHeight 를 이용하여 조절할 수 있다.

```objective-c
... 생략...
- (void)viewDidLoad
{
    [super viewDidLoad];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;
    self.title = @"UITableView Test";

    self.tableView  = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    self.tableView.sectionHeaderHeight = 44.0;
    self.tableView.sectionFooterHeight = 44.0;

    [self.view addSubview:self.tableView];
}
... 생략...

//- (float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
//{
//    return 44;
//}
//
//- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
//{
//    return 44;
//}
```

## 소스

* https://github.com/saltfactory/Saltfactory_iOS_Tutorial/tree/t3-uitableview

## 참고

1. http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDelegate_Protocol/Reference/Reference.html


text:
A tool for testing the [DataStax Spark Cassandra Connector](https://github.com/datastax/spark-cassandra-connector) against both [Apache
Cassandra](https://cassandra.apache.org/) (TM) and [DataStax Enterprise](http://www.datastax.com/products/datastax-enterprise) (DSE) with either bundled libraries from
DSE, Maven, or the connector built from source!

## Building

This project is built using Gradle and can be built in three exciting ways:

1. Using the Connector and Spark libraries installed by DataStax Enterprise
2. Using libraries downloaded from maven
3. Using libraries assembled fresh from your local Spark Cassandra Connector Repository

The jar can be built using

    ./gradlew jar -Pagainst=[type]

Where type is one of `dse`,`maven` or `source`

### DSE Options

DSE libraries are located by looking for the installation of DSE on your machine.
Change environment variables `DSE_HOME` and `DSE_RESOURCES` if your installation
differs from the default.

Defaults

    DSE_HOME=$HOME/dse
    DSE_RESOURCES=$HOME/dse/resources

### Maven Options

When getting libraries from Maven we need to specify the Connector version and
Spark Version libraries to compile against. Change environment variables
`CONNECTOR_VERSION` and `SPARK_VERSION` to the artifacts you would like to
use.

Defaults

    CONNECTOR_VERSION=1.2.0-rc2
    SPARK_VERSION=1.2.1

### Source Options

Gradle will attempt to clean and build the assembly jar for the Spark Connector
looking for the repository in environment variable `SPARKCC_HOME`. This will
build whatever commit the connector is currently at.

Default

    SPARKCC_HOME=$HOME/repos/spark-cassandra-connector/

## Running

There are many options which can be used to configure your run of
Spark Cassandra Stress but the two main invocations are either using
`dse spark-submit` or `spark-submit`.

See the `run.sh` script for examples or use it to launch the program.

    ./run.sh [dse|apache] --help

Will bring up the built in help.

## License

Copyright 2014-17, DataStax, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

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

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

redpajama_set_name: RedPajamaGithub


text:
<?php
$this->load->view('template_admin/head');
?>

<?php
$this->load->view('template_admin/topbar');
$this->load->view('template_admin/sidebar');
?>

        Kategori Berita
        Form Edit Kategori Berita

 Home

Berita

Edit kategori berita

                <form role="form" enctype="multipart/form-data" method="post" action="<?php echo base_url('admin/berita/proses_edit_katBer'); ?>">
                 <input type="hidden" name="id_katBer" class="form-control" id="exampleInputEmail1" placeholder="Masukkan nama kategori berita" value="<?php echo $b->row('id_katBer');?>">

                      Nama Kategori Berita
                      <input type="text" required name="nama_katBer" class="form-control" id="exampleInputEmail1" placeholder="Masukkan nama kategori berita" value="<?php echo $b->row('nama_katBer');?>">

                    <button type="submit" class="btn btn-warning">Edit</button>

                </form>

List Kategori Berita

                      No
                      Nama
                      Action

                  <?php
                    $i=1;
                    if ($data_get == NULL) {
                     echo "
Data masih kosong, tolong di isi!
";
                    }
                    else
                    {
                    foreach ($data_get as $row) {
                     ?>

                      <?php echo $i++; ?>
                      <?php echo $row->nama_katBer; ?>

                     <a href="<?php echo base_url();?>admin/berita/edit_katBer/<?php echo $row->id_katBer; ?>">
                              <button type="button" class="btn btn-warning">Edit</button>

                  <?php
                    }
                  }
                  ?>

<?php
$this->load->view('template_admin/js');
?>

<?php
$this->load->view('template_admin/foot');
?>


text:
{{ form_errors(form) }}

{{ form_widget(form._token) }}

Nombre

 {{ form_widget(form.nombre,{'attr': {'class': 'form-control'}}) }}

Apellidos

{{ form_widget(form.apellidos,{'attr': {'class': 'form-control'}}) }}

Categoría

{{ form_widget(form.categoria,{'attr': {'class': 'form-control'}}) }}

Permisos de usuario

{{ form_widget(form.roles,{'attr': {'class': 'form-control'}}) }}

Nombre corto

 {{ form_widget(form.username,{'attr': {'class': 'form-control'}}) }}

Orden

 {{ form_widget(form.orden,{'attr': {'class': 'form-control'}}) }}

Contraseña

{{ form_widget(form.password,{'attr': {'class': 'form-control'}}) }}

<button type="submit" class="btn btn-primary">Guardar</button>


text:
"Visual Template designer for PyFPDF (using wxPython OGL library)"

__author__ = "Mariano Reingart <reingart@gmail.com>"
__copyright__ = "Copyright (C) 2011 Mariano Reingart"
__license__ = "GPL 3.0"
__version__ = "1.01a"

# Based on:
#  * pySjetch.py wxPython sample application
#  * OGL.py and other wxPython demo modules

import os, sys
import wx
import wx.lib.ogl as ogl
from wx.lib.wordwrap import wordwrap

DEBUG = True

class CustomDialog(wx.Dialog):
    "A dinamyc dialog to ask user about arbitrary fields"

    def __init__(
            self, parent, ID, title, size=wx.DefaultSize, pos=wx.DefaultPosition,
            style=wx.DEFAULT_DIALOG_STYLE, fields=None, data=None,
            ):

        wx.Dialog.__init__ (self, parent, ID, title, pos, size, style)

        sizer = wx.BoxSizer(wx.VERTICAL)

        self.textctrls = {}
        for field in fields:
            box = wx.BoxSizer(wx.HORIZONTAL)
            label = wx.StaticText(self, -1, field)
            label.SetHelpText("This is the help text for the label")
            box.Add(label, 1, wx.ALIGN_CENTRE|wx.ALL, 5)
            text = wx.TextCtrl(self, -1, "", size=(80,-1))
            text.SetHelpText("Here's some help text for field #1")
            if field in data:
                text.SetValue(repr(data[field]))
            box.Add(text, 1, wx.ALIGN_CENTRE|wx.ALL, 1)
            sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 1)
            self.textctrls[field] = text

        line = wx.StaticLine(self, -1, size=(20,-1), style=wx.LI_HORIZONTAL)
        sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.RIGHT|wx.TOP, 5)

        btnsizer = wx.StdDialogButtonSizer()

        btn = wx.Button(self, wx.ID_OK)
        btn.SetHelpText("The OK button completes the dialog")
        btn.SetDefault()
        btnsizer.AddButton(btn)

        btn = wx.Button(self, wx.ID_CANCEL)
        btn.SetHelpText("The Cancel button cancels the dialog. (Cool, huh?)")
        btnsizer.AddButton(btn)
        btnsizer.Realize()

        sizer.Add(btnsizer, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        self.SetSizer(sizer)
        sizer.Fit(self)

    @classmethod
    def do_input(Class, parent, title, fields, data):
        dlg = Class(parent, -1, title, size=(350, 200),
                         style=wx.DEFAULT_DIALOG_STYLE, # & ~wx.CLOSE_BOX,
                        fields=fields, data=data
                         )
        dlg.CenterOnScreen()
        while 1:
            val = dlg.ShowModal()
            if val == wx.ID_OK:
                values = {}
                for field in fields:
                    try:
                        values[field] = eval(dlg.textctrls[field].GetValue())
                    except Exception, e:
                        msg = wx.MessageDialog(parent, unicode(e),
                               "Error in field %s" % field,
                               wx.OK | wx.ICON_INFORMATION
                               )
                        msg.ShowModal()
                        msg.Destroy()
                        break
                else:
                    return dict([(field, values[field]) for field in fields])
            else:
                return None

class MyEvtHandler(ogl.ShapeEvtHandler):
    "Custom Event Handler for Shapes"
    def __init__(self, callback):
        ogl.ShapeEvtHandler.__init__(self)
        self.callback = callback

    def OnLeftClick(self, x, y, keys=0, attachment=0):
        shape = self.GetShape()
        canvas = shape.GetCanvas()
        dc = wx.ClientDC(canvas)
        canvas.PrepareDC(dc)

        if shape.Selected() and keys & ogl.KEY_SHIFT:
            shape.Select(False, dc)
            #canvas.Redraw(dc)
            canvas.Refresh(False)
        else:
            redraw = False
            shapeList = canvas.GetDiagram().GetShapeList()
            toUnselect = []

            for s in shapeList:
                if s.Selected() and not keys & ogl.KEY_SHIFT:
                    # If we unselect it now then some of the objects in
                    # shapeList will become invalid (the control points are
                    # shapes too!) and bad things will happen...
                    toUnselect.append(s)

            shape.Select(True, dc)

            if toUnselect:
                for s in toUnselect:
                    s.Select(False, dc)
                ##canvas.Redraw(dc)
                canvas.Refresh(False)

        self.callback()

    def OnEndDragLeft(self, x, y, keys=0, attachment=0):
        shape = self.GetShape()
        ogl.ShapeEvtHandler.OnEndDragLeft(self, x, y, keys, attachment)

        if not shape.Selected():
            self.OnLeftClick(x, y, keys, attachment)

        self.callback()

    def OnSizingEndDragLeft(self, pt, x, y, keys, attch):
        ogl.ShapeEvtHandler.OnSizingEndDragLeft(self, pt, x, y, keys, attch)
        self.callback()

    def OnMovePost(self, dc, x, y, oldX, oldY, display):
        shape = self.GetShape()
        ogl.ShapeEvtHandler.OnMovePost(self, dc, x, y, oldX, oldY, display)
        self.callback()
        if "wxMac" in wx.PlatformInfo:
            shape.GetCanvas().Refresh(False)

    def OnLeftDoubleClick(self, x, y, keys = 0, attachment = 0):
        self.callback("LeftDoubleClick")

    def OnRightClick(self, *dontcare):
        self.callback("RightClick")

class Element(object):
    "Visual class that represent a placeholder in the template"

    fields = ['name', 'type',
                  'x1', 'y1', 'x2', 'y2',
                  'font', 'size',
                  'bold', 'italic', 'underline',
                  'foreground', 'background',
                  'align', 'text', 'priority',]

    def __init__(self, canvas=None, frame=None, zoom=5.0, static=False, **kwargs):
        self.kwargs = kwargs
        self.zoom = zoom
        self.frame = frame
        self.canvas = canvas
        self.static = static

        name = kwargs['name']
        kwargs['type']
        type = kwargs['type']

        x, y, w, h = self.set_coordinates(kwargs['x1'], kwargs['y1'], kwargs['x2'], kwargs['y2'])

        text = kwargs['text']

        shape = self.shape = ogl.RectangleShape(w, h)

        if not static:
            shape.SetDraggable(True, True)

        shape.SetX(x)
        shape.SetY(y)
        #if pen:    shape.SetPen(pen)
        #if brush:  shape.SetBrush(brush)
        shape.SetBrush(wx.TRANSPARENT_BRUSH)

        if type not in ('L', 'B', 'BC'):
            if not static:
                pen = wx.LIGHT_GREY_PEN
            else:
                pen = wx.RED_PEN
            shape.SetPen(pen)

        self.text = kwargs['text']

        evthandler = MyEvtHandler(self.evt_callback)
        evthandler.SetShape(shape)
        evthandler.SetPreviousHandler(shape.GetEventHandler())
        shape.SetEventHandler(evthandler)
        shape.SetCentreResize(False)
        shape.SetMaintainAspectRatio(False)

        canvas.AddShape( shape )

    @classmethod
    def new(Class, parent):
        data = dict(name='some_name', type='T',
                    x1=5.0, y1=5.0, x2=100.0, y2=10.0,
                    font="Arial", size=12,
                 bold=False, italic=False, underline=False,
                    foreground= 0x000000, background=0xFFFFFF,
                    align="L", text="", priority=0)
        data = CustomDialog.do_input(parent, 'New element', Class.fields, data)
        if data:
            return Class(canvas=parent.canvas, frame=parent, **data)

    def edit(self):
        "Edit current element (show a dialog box with all fields)"
        data = self.kwargs.copy()
        x1, y1, x2, y2 = self.get_coordinates()
        data.update(dict(name=self.name,
                         text=self.text,
                         x1=x1, y1=y1, x2=x2, y2=y2,
                       ))
        data = CustomDialog.do_input(self.frame, 'Edit element', self.fields, data)
        if data:
            self.kwargs.update(data)
            self.name = data['name']
            self.text = data['text']
            x,y, w, h = self.set_coordinates(data['x1'], data['y1'], data['x2'], data['y2'])
            self.shape.SetX(x)
            self.shape.SetY(y)
            self.shape.SetWidth(w)
            self.shape.SetHeight(h)
            self.canvas.Refresh(False)
            self.canvas.GetDiagram().ShowAll(1)

    def edit_text(self):
        "Allow text edition (i.e. for doubleclick)"
        dlg = wx.TextEntryDialog(
            self.frame, 'Text for %s' % self.name,
            'Edit Text', '')
        if self.text:
            dlg.SetValue(self.text)
        if dlg.ShowModal() == wx.ID_OK:
            self.text = dlg.GetValue().encode("latin1")
        dlg.Destroy()

    def copy(self):
        "Return an identical duplicate"
        kwargs = self.as_dict()
        element = Element(canvas=self.canvas, frame=self.frame, zoom=self.zoom, static=self.static, **kwargs)
        return element

    def remove(self):
        "Erases visual shape from OGL canvas (element must be deleted manually)"
        self.canvas.RemoveShape(self.shape)

    def move(self, dx, dy):
        "Change pdf coordinates (converting to wx internal values)"
        x1, y1, x2, y2 = self.get_coordinates()
        x1 += dx
        x2 += dx
        y1 += dy
        y2 += dy
        x, y, w, h = self.set_coordinates(x1, y1, x2, y2)
        self.shape.SetX(x)
        self.shape.SetY(y)

    def evt_callback(self, evt_type=None):
        "Event dispatcher"
        if evt_type=="LeftDoubleClick":
            self.edit_text()
        if evt_type=='RightClick':
            self.edit()

        # update the status bar
        x1, y1, x2, y2 = self.get_coordinates()
        self.frame.SetStatusText("%s (%0.2f, %0.2f) - (%0.2f, %0.2f)" %
                                        (self.name, x1, y1, x2, y2))

    def get_coordinates(self):
        "Convert from wx to pdf coordinates"
        x, y = self.shape.GetX(), self.shape.GetY()
        w, h = self.shape.GetBoundingBoxMax()
        w -= 1
        h -= 1
        x1 = x/self.zoom - w/self.zoom/2.0
        x2 = x/self.zoom + w/self.zoom/2.0
        y1 = y/self.zoom - h/self.zoom/2.0
        y2 = y/self.zoom + h/self.zoom/2.0
        return x1, y1, x2, y2

    def set_coordinates(self, x1, y1, x2, y2):
        "Convert from pdf to wx coordinates"
        x1 = x1 * self.zoom
        x2 = x2 * self.zoom
        y1 = y1 * self.zoom
        y2 = y2 * self.zoom

        # shapes seems to be centred, pdf coord not
        w = max(x1, x2) - min(x1, x2) + 1
        h = max(y1, y2) - min(y1, y2) + 1
        x = (min(x1, x2) + w/2.0)
        y = (min(y1, y2) + h/2.0)
        return x, y, w, h

    def text(self, txt=None):
        if txt is not None:
            if not isinstance(txt,str):
                txt = str(txt)
            self.kwargs['text'] = txt
            self.shape.ClearText()
            for line in txt.split('\n'):
                self.shape.AddText(unicode(line, "latin1"))
            self.canvas.Refresh(False)
        return self.kwargs['text']
    text = property(text, text)

    def set_x(self, x):
        self.shape.SetX(x)
        self.canvas.Refresh(False)
        self.evt_callback()
    def set_y(self, y):
        self.shape.SetY(y)
        self.canvas.Refresh(False)
        self.evt_callback()
    def get_x(self):
        return self.shape.GetX()
    def get_y(self):
        return self.shape.GetY()

    x = property(get_x, set_x)
    y = property(get_y, set_y)

    def selected(self, sel=None):
        if sel is not None:
            print "Setting Select(%s)" % sel
            self.shape.Select(sel)
        return self.shape.Selected()
    selected = property(selected, selected)

    def name(self, name=None):
        if name is not None:
            self.kwargs['name'] = name
        return self.kwargs['name']
    name = property(name, name)

    def __contains__(self, k):
        "Implement in keyword for searchs"
        return k in self.name.lower() or self.text and k in self.text.lower()

    def as_dict(self):
        "Return a dictionary representation, used by pyfpdf"
        d = self.kwargs
        x1, y1, x2, y2 = self.get_coordinates()
        d.update({
                'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2,
                'text': self.text})
        return d

class AppFrame(wx.Frame):
    "OGL Designer main window"
    title = "PyFPDF Template Designer (wx OGL)"

    def __init__(self):
        wx.Frame.__init__( self,
                          None, -1, self.title,
                          size=(640,480),
                          style=wx.DEFAULT_FRAME_STYLE )
        sys.excepthook  = self.except_hook
        self.filename = ""
        # Create a toolbar:
        tsize = (16,16)
        self.toolbar = self.CreateToolBar(wx.TB_HORIZONTAL | wx.NO_BORDER | wx.TB_FLAT)

        artBmp = wx.ArtProvider.GetBitmap
        self.toolbar.AddSimpleTool(
            wx.ID_NEW, artBmp(wx.ART_NEW, wx.ART_TOOLBAR, tsize), "New")
        self.toolbar.AddSimpleTool(
            wx.ID_OPEN, artBmp(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize), "Open")
        self.toolbar.AddSimpleTool(
            wx.ID_SAVE, artBmp(wx.ART_FILE_SAVE, wx.ART_TOOLBAR, tsize), "Save")
        self.toolbar.AddSimpleTool(
            wx.ID_SAVEAS, artBmp(wx.ART_FILE_SAVE_AS, wx.ART_TOOLBAR, tsize),
            "Save As...")
        #-------
        self.toolbar.AddSeparator()
        self.toolbar.AddSimpleTool(
            wx.ID_UNDO, artBmp(wx.ART_UNDO, wx.ART_TOOLBAR, tsize), "Undo")
        self.toolbar.AddSimpleTool(
            wx.ID_REDO, artBmp(wx.ART_REDO, wx.ART_TOOLBAR, tsize), "Redo")
        self.toolbar.AddSeparator()
        #-------
        self.toolbar.AddSimpleTool(
            wx.ID_CUT, artBmp(wx.ART_CUT, wx.ART_TOOLBAR, tsize), "Remove")
        self.toolbar.AddSimpleTool(
            wx.ID_COPY, artBmp(wx.ART_COPY, wx.ART_TOOLBAR, tsize), "Duplicate")
        self.toolbar.AddSimpleTool(
            wx.ID_PASTE, artBmp(wx.ART_PASTE, wx.ART_TOOLBAR, tsize), "Insert")
        self.toolbar.AddSeparator()
        self.toolbar.AddSimpleTool(
            wx.ID_FIND, artBmp(wx.ART_FIND, wx.ART_TOOLBAR, tsize), "Find")
        self.toolbar.AddSeparator()
        self.toolbar.AddSimpleTool(
            wx.ID_PRINT, artBmp(wx.ART_PRINT, wx.ART_TOOLBAR, tsize), "Print")
        self.toolbar.AddSimpleTool(
            wx.ID_ABOUT, artBmp(wx.ART_HELP, wx.ART_TOOLBAR, tsize), "About")

        self.toolbar.Realize()

        self.toolbar.EnableTool(wx.ID_SAVEAS,       False)
        self.toolbar.EnableTool(wx.ID_UNDO,         False)
        self.toolbar.EnableTool(wx.ID_REDO,         False)

        menu_handlers = [
            (wx.ID_NEW, self.do_new),
            (wx.ID_OPEN, self.do_open),
            (wx.ID_SAVE, self.do_save),
            (wx.ID_PRINT, self.do_print),
            (wx.ID_FIND, self.do_find),
            (wx.ID_CUT, self.do_cut),
            (wx.ID_COPY, self.do_copy),
            (wx.ID_PASTE, self.do_paste),
            (wx.ID_ABOUT, self.do_about),
        ]
        for menu_id, handler in menu_handlers:
            self.Bind(wx.EVT_MENU, handler, id = menu_id)

        sizer = wx.BoxSizer(wx.VERTICAL)
        # put stuff into sizer

        self.CreateStatusBar()

        canvas = self.canvas = ogl.ShapeCanvas( self )
        maxWidth  = 1500
        maxHeight = 2000
        canvas.SetScrollbars(20, 20, maxWidth/20, maxHeight/20)
        sizer.Add( canvas, 1, wx.GROW )

        canvas.SetBackgroundColour("WHITE") #

        diagram = self.diagram = ogl.Diagram()
        canvas.SetDiagram( diagram )
        diagram.SetCanvas( canvas )
        diagram.SetSnapToGrid( False )

        # apply sizer
        self.SetSizer(sizer)
        self.SetAutoLayout(1)
        self.Show(1)

        self.Bind(wx.EVT_CHAR_HOOK, self.on_key_event)
        self.elements = []

    def on_key_event(self, event):
        """ Respond to a keypress event.

            We make the arrow keys move the selected object(s) by one pixel in
            the given direction.
        """
        step = 1
        if event.ControlDown():
            step = 20

        if event.GetKeyCode() == wx.WXK_UP:
            self.move_elements(0, -step)
        elif event.GetKeyCode() == wx.WXK_DOWN:
            self.move_elements(0, step)
        elif event.GetKeyCode() == wx.WXK_LEFT:
            self.move_elements(-step, 0)
        elif event.GetKeyCode() == wx.WXK_RIGHT:
            self.move_elements(step, 0)
        elif event.GetKeyCode() == wx.WXK_DELETE:
            self.do_cut()
        else:
            event.Skip()

    def do_new(self, evt=None):
        for element in self.elements:
            element.remove()
        self.elements = []
        # draw paper size guides
        for k, (w, h) in [('legal', (216, 356)), ('A4', (210, 297)), ('letter', (216, 279))]:
            self.create_elements(
                k, 'R', 0, 0, w, h,
                size=70, foreground=0x808080, priority=-100,
                canvas=self.canvas, frame=self, static=True)
        self.diagram.ShowAll( 1 )

    def do_open(self, evt):
        dlg = wx.FileDialog(
            self, message="Choose a file",
            defaultDir=os.getcwd(),
            defaultFile="invoice.csv",
            wildcard="CSV Files (*.csv)|*.csv",
            style=wx.OPEN
            )

        if dlg.ShowModal() == wx.ID_OK:
            # This returns a Python list of files that were selected.
            self.filename = dlg.GetPaths()[0]

        dlg.Destroy()
        self.SetTitle(self.filename + " - " + self.title)

        self.do_new()
        tmp = []
        for lno, linea in enumerate(open(self.filename).readlines()):
            if DEBUG: print "processing line", lno, linea
            args = []
            for i,v in enumerate(linea.split(";")):
                if not v.startswith("'"):
                    v = v.replace(",",".")
                else:
                    v = v#.decode('latin1')
                if v.strip()=='':
                    v = None
                else:
                    v = eval(v.strip())
                args.append(v)
            tmp.append(args)

        # sort by z-order (priority)
        for args in sorted(tmp, key=lambda t: t[-1]):
            if DEBUG: print args
            self.create_elements(*args)
        self.diagram.ShowAll( 1 )                       #

        return True

    def do_save(self, evt, filename=None):
        try:
            from time import gmtime, strftime
            ts = strftime("%Y%m%d%H%M%S", gmtime())
            os.rename(self.filename, self.filename + ts + ".bak")
        except Exception, e:
            if DEBUG: print e
            pass

        def csv_repr(v, decimal_sep="."):
            if isinstance(v, float):
                return ("%0.2f" % v).replace(".", decimal_sep)
            else:
                return repr(v)

        f = open(self.filename, "w")
        for element in sorted(self.elements, key=lambda e:e.name):
            if element.static:
                continue
            d = element.as_dict()
            l = [d['name'], d['type'],
                 d['x1'], d['y1'], d['x2'], d['y2'],
                 d['font'], d['size'],
                 d['bold'], d['italic'], d['underline'],
                 d['foreground'], d['background'],
                 d['align'], d['text'], d['priority'],
                ]
            f.write(";".join([csv_repr(v) for v in l]))
            f.write("\n")
        f.close()

    def do_print(self, evt):
        # genero el renderizador con propiedades del PDF
        from template import Template
        t = Template(elements=[e.as_dict() for e in self.elements if not e.static])
        t.add_page()
        if not t['logo'] or not os.path.exists(t['logo']):
            # put a default logo so it doesn't trow an exception
            logo = os.path.join(os.path.dirname(__file__), 'tutorial','logo.png')
            t.set('logo', logo)
        try:
            t.render(self.filename +".pdf")
        except:
            if DEBUG and False:
                import pdb;
                pdb.pm()
            else:
                raise
        if sys.platform=="linux2":
            os.system("evince ""%s""" % self.filename +".pdf")
        else:
            os.startfile(self.filename +".pdf")

    def do_find(self, evt):
        # busco nombre o texto
        dlg = wx.TextEntryDialog(
            self, 'Enter text to search for',
            'Find Text', '')
        if dlg.ShowModal() == wx.ID_OK:
            txt = dlg.GetValue().encode("latin1").lower()
            for element in self.elements:
                if txt in element:
                    element.selected = True
                    print "Found:", element.name
            self.canvas.Refresh(False)
        dlg.Destroy()

    def do_cut(self, evt=None):
        "Delete selected elements"
        new_elements = []
        for element in self.elements:
            if element.selected:
                print "Erasing:", element.name
                element.selected = False
                self.canvas.Refresh(False)
                element.remove()
            else:
                new_elements.append(element)
        self.elements = new_elements
        self.canvas.Refresh(False)
        self.diagram.ShowAll( 1 )

    def do_copy(self, evt):
        "Duplicate selected elements"
        fields = ['qty', 'dx', 'dy']
        data = {'qty': 1, 'dx': 0.0, 'dy': 5.0}
        data = CustomDialog.do_input(self, 'Copy elements', fields, data)
        if data:
            new_elements = []
            for i in range(1, data['qty']+1):
                for element in self.elements:
                    if element.selected:
                        print "Copying:", element.name
                        new_element = element.copy()
                        name = new_element.name
                        if len(name)>2 and name[-2:].isdigit():
                            new_element.name = name[:-2] + "%02d" % (int(name[-2:])+i)
                        else:
                            new_element.name = new_element.name + "_copy"
                        new_element.selected = False
                        new_element.move(data['dx']*i, data['dy']*i)
                        new_elements.append(new_element)
            self.elements.extend(new_elements)
            self.canvas.Refresh(False)
            self.diagram.ShowAll( 1 )

    def do_paste(self, evt):
        "Insert new elements"
        element = Element.new(self)
        if element:
            self.canvas.Refresh(False)
            self.elements.append(element)
            self.diagram.ShowAll( 1 )

    def create_elements(self, name, type, x1, y1, x2, y2,
                   font="Arial", size=12,
                   bold=False, italic=False, underline=False,
                   foreground= 0x000000, background=0xFFFFFF,
                   align="L", text="", priority=0, canvas=None, frame=None, static=False,
                   **kwargs):
        element = Element(name=name, type=type, x1=x1, y1=y1, x2=x2, y2=y2,
                   font=font, size=size,
                   bold=bold, italic=italic, underline=underline,
                   foreground= foreground, background=background,
                   align=align, text=text, priority=priority,
                   canvas=canvas or self.canvas, frame=frame or self,
                   static=static)
        self.elements.append(element)

    def move_elements(self, x, y):
        for element in self.elements:
            if element.selected:
                print "moving", element.name, x, y
                element.x = element.x + x
                element.y = element.y + y

    def do_about(self, evt):
        info = wx.AboutDialogInfo()
        info.Name = self.title
        info.Version = __version__
        info.Copyright = __copyright__
        info.Description = (
            "Visual Template designer for PyFPDF (using wxPython OGL library)\n"
            "Input files are CSV format describing the layout, separated by ;\n"
            "Use toolbar buttons to open, save, print (preview) your template, "
            "and there are buttons to find, add, remove or duplicate elements.\n"
            "Over an element, a double left click opens edit text dialog, "
            "and a right click opens edit properties dialog. \n"
            "Multiple element can be selected with shift left click. \n"
            "Use arrow keys or drag-and-drop to move elements.\n"
            "For further information see project webpage:"
            )
        info.WebSite = ("http://code.google.com/p/pyfpdf/wiki/Templates",
                        "pyfpdf Google Code Project")
        info.Developers = [ __author__, ]

        info.License = wordwrap(__license__, 500, wx.ClientDC(self))

        # Then we call wx.AboutBox giving it that info object
        wx.AboutBox(info)

    def except_hook(self, type, value, trace):
        import traceback
        exc = traceback.format_exception(type, value, trace)
        for e in exc: wx.LogError(e)
        wx.LogError('Unhandled Error: %s: %s'%(str(type), str(value)))

app = wx.PySimpleApp()
ogl.OGLInitialize()
frame = AppFrame()
app.MainLoop()
app.Destroy()


text:
<?php

namespace ByJG\WebService;

/**
 * Classe Base com todas as funcionalidades para acessar o serviço ByJG
 */
abstract class BaseService
{
    protected $URL         = "http://www.byjg.com.br/site/webservice.php/ws/";
    protected $_username   = "";
    protected $_password   = "";
    protected $_service    = "";
    protected $_curlParams = [];

    /**
     *
     * @param string $username
     * @param string $password
     */
    public function __construct($username, $password, $curlParams = [CURLOPT_TIMEOUT => 5])
    {
        $this->_username   = $username;
        $this->_password   = $password;
        $this->_curlParams = $curlParams;
    }

    protected function conectarServer($httpmethod, $params)
    {
        $params["httpmethod"] = $httpmethod;
        $params["usuario"]    = $this->_username;
        $params["senha"]      = $this->_password;

        $url = $this->URL . $this->_service;

        $webRequest = new \ByJG\Util\WebRequest($url);

        foreach ($this->_curlParams as $param => $value) {
            $webRequest->setCurlOption($param, $value);
        }

        $response = $webRequest->post($params);

        $firstData = explode('|', $response);
        $result    = array(
            'status' => $firstData[0],
            'raw'    => $response
        );

        if (isset($firstData[1])) {
            $parsedData = explode(', ', $firstData[1]);

            if (!isset($parsedData[1])) {
                $parsedData[0] = null;
                $parsedData[1] = $firstData[1];
            }

            $result['data'] = array(
                "code" => $parsedData[0],
                "info" => $parsedData[1]
            );
        }

        return $result;
    }
}


text:
"""
Directives for document parts.
"""

__docformat__ = 'reStructuredText'

from docutils import nodes, languages
from docutils.transforms import parts
from docutils.parsers.rst import Directive
from docutils.parsers.rst import directives

class Contents(Directive):

    """
    Table of contents.

    The table of contents is generated in two passes: initial parse and
    transform.  During the initial parse, a 'pending' element is generated
    which acts as a placeholder, storing the TOC title and any options
    internally.  At a later stage in the processing, the 'pending' element is
    replaced by a 'topic' element, a title and the table of contents proper.
    """

    backlinks_values = ('top', 'entry', 'none')

    def backlinks(arg):
        value = directives.choice(arg, Contents.backlinks_values)
        if value == 'none':
            return None
        else:
            return value

    required_arguments = 0
    optional_arguments = 1
    final_argument_whitespace = True
    option_spec = {'depth': directives.nonnegative_int,
                   'local': directives.flag,
                   'backlinks': backlinks,
                   'class': directives.class_option}

    def run(self):
        if not (self.state_machine.match_titles
                or isinstance(self.state_machine.node, nodes.sidebar)):
            raise self.error('The "%s" directive may not be used within '
                             'topics or body elements.' % self.name)
        document = self.state_machine.document
        language = languages.get_language(document.settings.language_code)
        if self.arguments:
            title_text = self.arguments[0]
            text_nodes, messages = self.state.inline_text(title_text,
                                                          self.lineno)
            title = nodes.title(title_text, '', *text_nodes)
        else:
            messages = []
            if 'local' in self.options:
                title = None
            else:
                title = nodes.title('', language.labels['contents'])
        topic = nodes.topic(classes=['contents'])
        topic['classes'] += self.options.get('class', [])
        if 'local' in self.options:
            topic['classes'].append('local')
        if title:
            name = title.astext()
            topic += title
        else:
            name = language.labels['contents']
        name = nodes.fully_normalize_name(name)
        if not document.has_name(name):
            topic['names'].append(name)
        document.note_implicit_target(topic)
        pending = nodes.pending(parts.Contents, rawsource=self.block_text)
        pending.details.update(self.options)
        document.note_pending(pending)
        topic += pending
        return [topic] + messages

class Sectnum(Directive):

    """Automatic section numbering."""

    option_spec = {'depth': int,
                   'start': int,
                   'prefix': directives.unchanged_required,
                   'suffix': directives.unchanged_required}

    def run(self):
        pending = nodes.pending(parts.SectNum)
        pending.details.update(self.options)
        self.state_machine.document.note_pending(pending)
        return [pending]

class Header(Directive):

    """Contents of document header."""

    has_content = True

    def run(self):
        self.assert_has_content()
        header = self.state_machine.document.get_decoration().get_header()
        self.state.nested_parse(self.content, self.content_offset, header)
        return []

class Footer(Directive):

    """Contents of document footer."""

    has_content = True

    def run(self):
        self.assert_has_content()
        footer = self.state_machine.document.get_decoration().get_footer()
        self.state.nested_parse(self.content, self.content_offset, footer)
        return []


text:
if [[ -z "$START_TIMEOUT" ]]; then
    START_TIMEOUT=600
fi

start_timeout_exceeded=false
count=0
step=10
while netstat -lnt | awk '$4 ~ /:'$KAFKA_PORT'$/ {exit 1}'; do
    echo "waiting for kafka to be ready"
    sleep $step;
    count=$(expr $count + $step)
    if [ $count -gt $START_TIMEOUT ]; then
        start_timeout_exceeded=true
        break
    fi
done

if $start_timeout_exceeded; then
    echo "Not able to auto-create topic (waited for $START_TIMEOUT sec)"
    exit 1
fi

if [[ -n $KAFKA_CREATE_TOPICS ]]; then
    IFS=','; for topicToCreate in $KAFKA_CREATE_TOPICS; do
        echo "creating topics: $topicToCreate"
        IFS=':' read -a topicConfig <<< "$topicToCreate"
        if [ ${topicConfig[3]} ]; then
          JMX_PORT='' $KAFKA_HOME/bin/kafka-topics.sh --create --zookeeper $KAFKA_ZOOKEEPER_CONNECT --replication-factor ${topicConfig[2]} --partitions ${topicConfig[1]} --topic "${topicConfig[0]}" --config cleanup.policy="${topicConfig[3]}" --if-not-exists
        else
          JMX_PORT='' $KAFKA_HOME/bin/kafka-topics.sh --create --zookeeper $KAFKA_ZOOKEEPER_CONNECT --replication-factor ${topicConfig[2]} --partitions ${topicConfig[1]} --topic "${topicConfig[0]}" --if-not-exists
        fi
    done
fi


text:
let express = require('express'),
    router = express.Router(),
    auth = require('./../utils/auth.js'),
    api = require('./../controllers/api');

router.get('/api/tasks', api.tasks);
router.get('/api/task/:id', api.task);
router.get('/api/category/:path_name', api.category);
router.post('/api/createTask', api.createTask);
router.post('/api/createProject', api.createProject);
router.post('/api/login', api.login);
router.get('/api/checkstatus', api.checkStatus);
router.post('/api/del', api.del);
router.post('/api/signup',api.signup);

module.exports = router;


text:
"""This is rule-based deduction system for SymPy

The whole thing is split into two parts

 - rules compilation and preparation of tables
 - runtime inference

For rule-based inference engines, the classical work is RETE algorithm [1], [2]
Although we are not implementing it in full or even in some significant part,
it's still worth to read about it to get the ideas behind.

In short, every rule in a system of rules is one of two forms:

 - atom                     -> ...      (alpha rule)
 - And(atom1, atom2, ...)   -> ...      (beta rule)

The major complexity is in efficient beta-rules processing and usually for an
expert system a lot of effort goes into code that operates on beta-rules.

Here we take minimalistic approach to get something usable first.

 - (preparation)    of alpha- and beta- networks, everything except
 - (runtime)        FactRules.deduce_all_facts

             _____________________________________
            ( Kirr: I've never thought that doing )
            ( logic stuff is that difficult...    )
             -------------------------------------
                    o   ^__^
                     o  (oo)\_______
                        (__)\       )\/\
                            ||----w |
                            ||     ||

Some references on the topic
----------------------------

[1] http://en.wikipedia.org/wiki/Rete_algorithm
[2] http://reports-archive.adm.cs.cmu.edu/anon/1995/CMU-CS-95-113.pdf

http://en.wikipedia.org/wiki/Propositional_formula
http://en.wikipedia.org/wiki/Inference_rule
http://en.wikipedia.org/wiki/List_of_rules_of_inference
"""

from logic import fuzzy_not, name_not, Logic, And, Not

def list_populate(l, item, skipif=None):
    """update list with an item, but only if it is not already there"""
    if item != skipif and (item not in l):
        l.append(item)

# XXX this prepares forward-chaining rules for alpha-network

# XXX better words?
# NB: this procedure does not 'know' about not-relations
# i.e. it treats 'a' and '!a' as independent variables while deriving implications.
#
# only in the end, we check that the whole result is consitent
def deduce_alpha_implications(implications):
    """deduce all implications

       Description by example
       ----------------------

       given set of logic rules:

         a -> b
         b -> c

       we deduce all possible rules:

         a -> b, c
         b -> c

       implications: [] of (a,b)
       return:       {} of a -> [b, c, ...]
    """

    res = {} # a -> [] of implications(a)

    # NOTE: this could be optimized with e.g. toposort (?), but we need this
    # only at FactRules creation time (i.e. only once), so there is no demand
    # in further optimising this.
    for a,b in implications:
        if a==b:
            continue    # skip a->a cyclic input

        I = res.setdefault(a,[])
        list_populate(I,b)

        # UC:  -------------------------
        #     |                         |
        #     v                         |
        # a='rat' -> b='real' ==> (a_='int') -> 'real'
        for a_ in res:
            ra_ = res[a_]
            if a in ra_:
                list_populate(ra_, b, skipif=a_)

        # UC:
        # a='pos' -> b='real' && (already have b='real' -> 'complex')
        #                   ||
        #                   vv
        # a='pos' -> 'complex'
        if b in res:
            ra = res[a]
            for b_ in res[b]:
                list_populate(ra, b_, skipif=a)

    #print 'D:', res

    # let's see if the result is consistent
    for a, impl in res.iteritems():
        na = name_not(a)
        if na in impl:
            raise ValueError('implications are inconsistent: %s -> %s %s' % (a, na, impl))

    return res

def apply_beta_to_alpha_route(alpha_implications, beta_rules):
    """apply additional beta-rules (And conditions) to already-built alpha implication tables

       TODO: write about

       - static extension of alpha-chains
       - attaching refs to beta-nodes to alpha chains

       e.g.

       alpha_implications:

       a  ->  [b, !c, d]
       b  ->  [d]
       ...

       beta_rules:

       &(b,d) -> e

       then we'll extend a's rule to the following

       a  ->  [b, !c, d, e]
    """

    x_impl = {}

    for x in alpha_implications.keys():
        x_impl[x] = (alpha_implications[x][:], [])

    # let's ensure that every beta-rule has appropriate entry (maybe even
    # empty) in the table.
    for bidx, (bcond,bimpl) in enumerate(beta_rules):
        for bk in bcond.args:
            if bk in x_impl:
                continue

            x_impl[bk] = ([], [])

    # XXX maybe simplify passes logic?

    # we do it in 2 phases:
    #
    # 1st phase -- only do static extensions to alpha rules
    # 2nd phase -- attach beta-nodes which can be possibly triggered by an
    #              alpha-chain
    phase=1
    while True:
        seen_static_extension=False

        for bidx, (bcond,bimpl) in enumerate(beta_rules):
            assert isinstance(bcond, And)

            for x, (ximpls, bb) in x_impl.iteritems():
                # A: x -> a     B: &(...) -> x      (non-informative)
                if x == bimpl:  # XXX bimpl may become a list
                    continue

                # A: ... -> a   B: &(...) -> a      (non-informative)
                if bimpl in ximpls:
                    continue

                # A: x -> a     B: &(a,!x) -> ...   (will never trigger)
                if Not(x) in bcond.args:
                    continue

                # A: x -> a...  B: &(!a,...) -> ... (will never trigger)
                # A: x -> a...  B: &(...) -> !a     (will never trigger)
                maytrigger=True
                for xi in ximpls:
                    if (Not(xi) in bcond.args)  or  (Not(xi) == bimpl):
                        maytrigger=False
                        break

                if not maytrigger:
                    continue

                # A: x -> a,b   B: &(a,b) -> c      (static extension)
                #                                       |
                # A: x -> a,b,c <-----------------------+
                for barg in bcond.args:
                    if not ( (barg == x) or (barg in ximpls) ):
                        break
                else:
                    assert phase==1
                    list_populate(ximpls, bimpl)    # XXX bimpl may become a list

                    # we introduced new implication - now we have to restore
                    # completness of the whole set.
                    bimpl_impl = x_impl.get(bimpl)
                    if bimpl_impl is not None:
                        for _ in bimpl_impl[0]:
                            list_populate(ximpls, _)

                    seen_static_extension=True
                    continue

                # does this beta-rule even has a chance to be triggered ?
                if phase == 2:
                    for barg in bcond.args:
                        if (barg == x) or (barg in ximpls):
                            bb.append( bidx )
                            break

        # no static extensions was seen at this pass -- lets move to phase2
        if phase==1 and (not seen_static_extension):
            phase = 2
            continue

        # let's finish at the end of phase2
        if phase==2:
            break

    return x_impl

# XXX this is something related to backward-chaining for alpha-network (?)
# TODO adapt to handle beta nodes ?

# TODO we need to sort prerequisites somehow, so that more closer prerequisites
# would be tried first. e.g.
#
# nonzero <- [zero, integer, ..., prime], but not
# nonzero <- [prime, ...]
#
# this could be done in other place...
def rules_2prereq(rules):
    """build prerequisites table from rules

       Description by example
       ----------------------

       given set of logic rules:

         a -> b, c
         b -> c

       we build prerequisites (from what points something can be deduced):

         b <- a
         c <- a, b

       rules:   {} of a -> [b, c, ...]
       return:  {} of c <- [a, b, ...]

       Note however, that this prerequisites may be *not* enough to prove a
       fact. An example is 'a -> b' rule, where prereq(a) is b, and prereq(b)
       is a. That's because a=T -> b=T, and b=F -> a=F, but a=F -> b=?
    """

    prereq = {}
    for a, impl in rules.iteritems():
        for i in impl:
            pa = prereq.setdefault(i,[])
            pa.append(a)

    return prereq

def split_rules_tt_tf_ft_ff(rules):
    """split alpha-rules into T->T & T->F & F->T & F->F chains

       and also rewrite them to be free of not-names

       Example
       -------

       'a' -> ['b', '!c']

       will be split into

       'a' -> ['b'] # tt: a -> b
       'a' -> ['c'] # tf: a -> !c

       and
       '!a' -> ['b']

       will become

       'b' -> ['a'] # ft: !b -> a
    """

#   print 'split_rules_tt_tf_ft_ff'
#   print rules

    tt = {}
    tf = {}
    ft = {}

    for k,impl in rules.iteritems():
        # k is not not-name
        if k[:1] != '!':
            for i in impl:
                if i[:1] != '!':
                    dd = tt
                else:
                    dd = tf
                    i  = i[1:]

                I = dd.setdefault(k,[])
                list_populate(I, i)

        # k is not-name
        else:
            k = k[1:]

            for i in impl:
                if i[:1] != '!':
                    dd = ft
                else:
                    dd = tt
                    i  = i[1:]

                I = dd.setdefault(i,[])
                list_populate(I, k)

    # FF is related to TT
    ff = {}
    for k,impl in tt.iteritems():
        for i in impl:
            I = ff.setdefault(i,[])
            I.append(k)

    return tt, tf, ft, ff

################
# RULES PROVER #
################

# XXX only for debugging -- kill me ?
dbg_level = 0

class TautologyDetected(Exception):
    """(internal) Prover uses it for reporting detected tautology"""
    pass

class Prover(object):
    """ai - prover of logic rules

       given a set of initial rules, Prover tries to prove all possible rules
       which follow from given premises.

       As a result proved_rules are always either in one of two forms: alpha or
       beta:

       Alpha rules
       -----------

       This are rules of the form::

         a -> b & c & d & ...

       Beta rules
       ----------

       This are rules of the form::

         &(a,b,...) -> c & d & ...

       i.e. beta rules are join conditions that say that something follows when
       *several* facts are true at the same time.
    """

    __slots__ = ['proved_rules',    # [] of a,b     (a -> b  rule)
                 '_rules_seen',     # setof all seen rules
                ]

    def __init__(self):
        self.proved_rules = []
        self._rules_seen  = set()

    def print_proved(self, title='proved rules'):
        print '\n--- %s ---' % title
        for a,b in self.proved_rules:
            print '%s\t->  %s' % (a,b)

        print '   - - - - -   '
        print

    def print_beta(self, title='proved rules (beta)'):
        print '\n --- %s ---' % title

        for n, (a,b) in enumerate(self.rules_beta):
            print '[#%i]  %s\t->  %s' % (n,a,b)

        print '   - - - - -   '
        print

    def split_alpha_beta(self):
        """split proved rules into alpha and beta chains"""
        rules_alpha = []    # a      -> b
        rules_beta  = []    # &(...) -> b

        for a,b in self.proved_rules:
            if isinstance(a, And):
                rules_beta.append( (a,b) )
            else:
                rules_alpha.append((a,b) )

        return rules_alpha, rules_beta

    @property
    def rules_alpha(self):
        return self.split_alpha_beta()[0]

    @property
    def rules_beta(self):
        return self.split_alpha_beta()[1]

    # XXX rename?
    def process_rule(self, a, b):
        """process a -> b rule"""   # TODO write more?

        # XXX this seems to be needed, but I can't get it to work without cycles
        # XXX sigh ...
        #if isinstance(a, And):
        #    a = a.expand()
        #if isinstance(b, And):
        #    b = b.expand()

#       print ' -- %s\t->  %s' % (a,b)

        # we don't want rules whose premise is F, or who are trivial
        # skip:  F -> ...
        # skip:  ... -> F
        # skip:  ... -> T
        if (not a) or isinstance(b, bool):
            return

        # XXX can't we perform without this?
        # skip:  T -> ...
        if isinstance(a, bool):
            return

        # cycle detection: we don't want to process already seen rules
        if (a,b) in self._rules_seen:
            # already seen rule
            # XXX is it possible to design process_rule so we don't need
            # XXX this recursion detector? For me current answer is 'no'
            #                                                   -- kirr
            return
        else:
            self._rules_seen.add((a,b))

        # this is the core of processing
        try:
            self._process_rule(a, b)
        except TautologyDetected, t:
            #print 'Tautology:  %s -> %s   (%s)' % (t.args[0], t.args[1], t.args[2])
            pass

        else:
            # XXX negating here seems like the way to go. However we do
            # XXX *not* do it -- read below about why ...
            #
            # if not tautology, process negative rule as well
            # a -> b  -->  !b -> !a
        #   self.process_rule(Not(b), Not(a))

            # Unfortunately we can't handle the above negation -- in the
            # end our cycles detector is unable to catch all cycles,
            # especially ones where noise is mixed to already-known-facts,
            # e.g.
            #
            # say
            #
            #   a -> b
            #
            # is known fact, and at some point we get
            #
            #   a -> |(....., b)
            #
            # At present we are unable to detect this situation.
            #
            # I'm sorry -- I have no deep understanding of this logic
            # processing stuff and I'm very short on time ...
            #                                                  -- kirr
            pass

    # --- processing ---

    def _process_rule(self, a, b):

        # right part first
        if isinstance(b, Logic):
            # a -> b & c    -->  a -> b  ;  a -> c
            # (?) FIXME this is only correct when b & c != null !
            if   b.op == '&':
                for barg in b.args:
                    self.process_rule(a, barg)

            # a -> b | c    -->  !b & !c -> !a
            #               -->   a & !b -> c & !b
            #               -->   a & !c -> b & !c
            #
            # NB: the last two rewrites add 1 term, so the rule *grows* in size.
            # NB: without catching terminating conditions this could continue infinitely
            elif b.op == '|':
                # detect tautology first
                if not isinstance(a, Logic):    # Atom
                    # tautology:  a -> a|c|...
                    if a in b.args:
                        raise TautologyDetected(a,b, 'a -> a|c|...')

                self.process_rule(
                    And( *[Not(barg) for barg in b.args] ),
                    Not(a)
                )

                for bidx in range(len(b.args)):
                    barg = b.args[bidx]
                    brest= b.args[:bidx] + b.args[bidx+1:]

                    self.process_rule(
                        And( a, Not(barg) ),
                        And( b.__class__(*brest), Not(barg) )
                    )

            else:
                raise ValueError('unknown b.op %r' % b.op)

        # left part
        elif isinstance(a, Logic):
            # a & b -> c    -->  IRREDUCIBLE CASE -- WE STORE IT AS IS
            #                    (this will be the basis of beta-network)
            if   a.op == '&':
                # at this stage we should have right part alredy in simple form
                assert not isinstance(b, Logic)

                # tautology:  a & b -> a
                if b in a.args:
                    raise TautologyDetected(a,b, 'a & b -> a')

                self.proved_rules.append((a,b))
                # XXX NOTE at present we ignore  !c -> !a | !b

            # a | b -> c    -->  a -> c  ;  b -> c
            elif a.op == '|':

                # tautology:  a | b -> a
                if b in a.args:
                    raise TautologyDetected(a,b, 'a | b -> a')

                for aarg in a.args:
                    self.process_rule(aarg, b)

            else:
                raise ValueError('unknown a.op %r' % a.op)

        else:
            # now this is the case where both `a` and `b` are atoms
            na, nb = name_not(a), name_not(b)

            self.proved_rules.append((a,b))     # a  -> b

            # XXX one day we may not need this -- read comments about
            # XXX negation close to the end of `process_rule`
            self.proved_rules.append((nb,na))   # !b -> !a

    def dbg_process_rule_2(a, b):
        global dbg_level
        print '%s%s\t->  %s' % (' '*(2*dbg_level), a, b)
        dbg_level += 1

        try:
            old_process_rule_2(a, b)
        finally:
            dbg_level -= 1

    #old_process_rule_2 = process_rule_2
    #process_rule_2 = dbg_process_rule_2

########################################

# TODO link to RETE ?
# TODO link to proposition logic ?
class FactRules:
    """Rules that describe how to deduce facts in logic space

       When defined, this rules allow to quickly determine implications for a
       set of facts. For this precomputed deduction tables are used. see
       `deduce_all_facts`   (forward-chaining)

       Also it is possible to gather prerequisites for a fact, which is tried
       to be proven.    (backward-chaining)

       Definition Syntax
       -----------------

       a -> b       -- a=T -> b=T  (and automatically b=F -> a=F)
       a -> !b      -- a=T -> b=F
       a == b       -- a -> b & b -> a
       a -> b & c   -- a=T -> b=T & c=T
       # TODO b | c

       Internals
       ---------

       {} k -> [] of implications:

         .rel_tt      k=T -> k2=T
         .rel_tf      k=T -> k2=F
         .rel_ff      k=F -> k2=F
         .rel_ft      k=F -> k2=T

       .rel_tbeta     k=T -> [] of possibly triggering # of beta-rules
       .rel_fbeta     k=F -> ------------------//---------------------

       .rels    -- {} k -> tt, tf, ff, ft   (list of implications for k)
       .prereq  -- {} k <- [] of k's prerequisites

       .defined_facts -- set of defined fact names
    """

    def __init__(self, rules):
        """Compile rules into internal lookup tables"""

        if isinstance(rules, basestring):
            rules = rules.splitlines()

        # --- parse and process rules ---
        P = Prover()

        for rule in rules:
            # XXX `a` is hardcoded to be always atom
            a, op, b = rule.split(None, 2)

            a = Logic.fromstring(a)
            b = Logic.fromstring(b)

            if   op == '->':
                P.process_rule(a, b)
            elif op == '==':
                P.process_rule(a, b)
                P.process_rule(b, a)
            else:
                raise ValueError('unknown op %r' % op)

        #P.print_proved('RULES')
        #P.print_beta('BETA-RULES')

        # --- build deduction networks ---

        # deduce alpha implications
        impl_a = deduce_alpha_implications(P.rules_alpha)

        # now:
        # - apply beta rules to alpha chains  (static extension), and
        # - further associate beta rules to alpha chain (for inference at runtime)
        impl_ab = apply_beta_to_alpha_route(impl_a, P.rules_beta)

        if 0:
            print '\n --- ALPHA-CHAINS (I) ---'

            for a,b in impl_a.iteritems():
                print '%s\t->  α(%2i):%s' % (a,len(b),b)

            print '   - - - - -   '
            print

        if 0:
            print '\n --- ALPHA-CHAINS (II) ---'

            for a,(b,bb) in impl_ab.iteritems():
                print '%s\t->  α(%2i):%s  β(%s)' % (a,len(b),b, ' '.join(str(x) for x in bb))

            print '   - - - - -   '
            print

        # extract defined fact names
        self.defined_facts = set()

        for k in impl_ab.keys():
            if k[:1] == '!':
                k = k[1:]

            self.defined_facts.add(k)

        #print 'defined facts:  (%2i)  %s' % (len(self.defined_facts), self.defined_facts)

        # now split each rule into four logic chains
        # (removing betaidxs from impl_ab view) (XXX is this needed?)
        impl_ab_ = dict( (k,impl)  for k, (impl,betaidxs) in impl_ab.iteritems())
        rel_tt, rel_tf, rel_ft, rel_ff = split_rules_tt_tf_ft_ff(impl_ab_)

        # XXX merge me with split_rules_tt_tf_ft_ff ?
        rel_tbeta = {}
        rel_fbeta = {}

        for k, (impl,betaidxs) in impl_ab.iteritems():
            if k[:1] == '!':
                rel_xbeta = rel_fbeta
                k         = name_not(k)
            else:
                rel_xbeta = rel_tbeta

            rel_xbeta[k] = betaidxs

        self.rel_tt = rel_tt
        self.rel_tf = rel_tf
        self.rel_tbeta  = rel_tbeta
        self.rel_ff = rel_ff
        self.rel_ft = rel_ft
        self.rel_fbeta  = rel_fbeta

        self.beta_rules = P.rules_beta

        # build rels (forward chains)
        K = set (rel_tt.keys())
        K.update(rel_tf.keys())
        K.update(rel_ff.keys())
        K.update(rel_ft.keys())

        rels = {}
        empty= ()
        for k in K:
            tt = rel_tt.get(k,empty)
            tf = rel_tf.get(k,empty)
            ft = rel_ft.get(k,empty)
            ff = rel_ff.get(k,empty)

            tbeta = rel_tbeta.get(k,empty)
            fbeta = rel_fbeta.get(k,empty)

            rels[k] = tt, tf, tbeta,  ft, ff, fbeta

        self.rels = rels

        # build prereq (backward chains)
        prereq = {}
        for rel in [rel_tt, rel_tf, rel_ff, rel_ft]:
            rel_prereq = rules_2prereq(rel)
            for k,pitems in rel_prereq.iteritems():
                kp = prereq.setdefault(k,[])
                for p in pitems:
                    list_populate(kp, p)

        self.prereq = prereq

    # --- DEDUCTION ENGINE: RUNTIME CORE ---

    # TODO: add proper support for U (None), i.e.
    #       integer=U  -> rational=U  ??? (XXX i'm not sure)

    def deduce_all_facts(self, facts, base=None):
        """Deduce all facts from known facts ({} or [] of (k,v))

           *********************************************
           * This is the workhorse, so keep it *fast*. *
           *********************************************

           base  --  previously known facts (must be: fully deduced set)
                     attention: base is modified *inplace*  /optional/

           providing `base` could be needed for performance reasons -- we don't
           want to spend most of the time just re-deducing base from base
           (e.g. #base=50, #facts=2)
        """

        # keep frequently used attributes locally, so we'll avoid extra
        # attribute access overhead
        rels = self.rels
        beta_rules = self.beta_rules

        if base is not None:
            new_facts = base
        else:
            new_facts = {}

        # XXX better name ?
        def x_new_facts(keys, v):
            #print 'x_new_facts(%r,%r)' % (keys, v)
            for k in keys:
                if k in new_facts:
                    #print 'seen_fact  %s:\t %s' % (k,v)
                    assert new_facts[k] == v, ('inconsitency between facts',new_facts,k,v)
                    continue

                else:
                    #print 'new_fact   %s:\t %s' % (k,v)
                    new_facts[k] = v

        if type(facts) is dict:
            fseq = facts.iteritems()
        else:
            fseq = facts

        while True:
            beta_maytrigger = set()

            # --- alpha chains ---
            #print '**'
            for k,v in fseq:
                #print '--'

                # first, convert name to be not a not-name
                if k[:1] == '!':
                    k = name_not(k)
                    v = fuzzy_not(v)

                #new_fact(k, v)
                if k in new_facts:
                    assert new_facts[k] == v, ('inconsitency between facts',new_facts,k,v)

                    # performance-wise it is important not to fire implied rules
                    # for already-seen fact -- we already did them all.
                    continue

                else:
                    new_facts[k] = v

                # some known fact -- let's follow it's implications
                if v is not None:

                    # lookup routing tables
                    try:
                        tt, tf, tbeta,  ft, ff, fbeta = rels[k]
                    except KeyError:
                        pass
                    else:
                        # Now we have routing tables with *all* the needed
                        # implications for this k. This means we do not have to
                        # process each implications recursively!
                        # XXX this ^^^ is true only for alpha chains

                        # k=T
                        if v:
                            x_new_facts(tt, True)   # k -> i
                            x_new_facts(tf, False)  # k -> !i

                            beta_maytrigger.update(tbeta)

                        # k=F
                        else:
                            x_new_facts(ft, True)   # !k -> i
                            x_new_facts(ff, False)  # !k -> !i

                            beta_maytrigger.update(fbeta)

            # --- beta chains ---

            # if no beta-rules may trigger -- it's an end-of-story
            if not beta_maytrigger:
                break

            #print '(β) MayTrigger: %s' % beta_maytrigger

            fseq = []

            # XXX this is dumb proof-of-concept trigger -- we'll need to optimize it
            # let's see which beta-rules to trigger
            for bidx in beta_maytrigger:
                bcond,bimpl = beta_rules[bidx]

                # let's see whether bcond is satisfied
                for bk in bcond.args:
                    try:
                        if bk[:1] == '!':
                            bv = fuzzy_not(new_facts[bk[1:]])
                        else:
                            bv = new_facts[bk]
                    except KeyError:
                        break   # fact not found -- bcond not satisfied

                    # one of bcond's condition does not hold
                    if not bv:
                        break

                else:
                    # all of bcond's condition hold -- let's fire this beta rule
                    #print '(β) Trigger #%i  (%s)' % (bidx, bimpl)

                    if bimpl[:1] == '!':
                        bimpl = bimpl[1:]
                        v = False
                    else:
                        v = True

                    fseq.append( (bimpl,v) )

        return new_facts

########################################

# this was neeeded for testing -- feel free to remove this when everything
# settles.
#                                                               -- kirr
if 0:

    FF = FactRules([

        'integer        ->  rational',
        'rational       ->  real',
        'real           ->  complex',
        'imaginary      ->  complex',
        'complex        ->  commutative',

        'odd            ==  integer & !even',
        'even           ==  integer & !odd',

        'real           ==  negative | zero | positive',

        'positive       ->  real & !negative & !zero',
        'negative       ->  real & !positive & !zero',

        'nonpositive    ==  real & !positive',
        'nonnegative    ==  real & !negative',

        'zero           ->  infinitesimal & even',

        'prime          ->  integer & positive',
        'composite      ==  integer & positive & !prime',

        'irrational     ==  real & !rational',

        'imaginary      ->  !real',     # XXX new ?

        '!bounded     ==  unbounded',
        '!commutative ==  noncommutative',
        '!complex     ==  noncomplex',
    #   '!integer     ==  noninteger',
        'noninteger     ==  real & !integer',   # XXX ok?
        '!zero        ==  nonzero',
        '!homogeneous ==  inhomogeneous',

        # XXX do we need this ?
        'finite     ->  bounded',       # XXX do we need this?
        'finite     ->  !zero',         # XXX wrong?
        'infinitesimal ->  !finite',    # XXX is this ok?

        # TODO we should remove this (very seldomly used, but affect performance):
        'nni    ==  integer & nonnegative',
        'npi    ==  integer & nonpositive',
        'pi     ==  integer & positive',
        'ni     ==  integer & negative',
    ])

    """
    FF = FactRules([
        'real   == pos | npos',

        'pos    -> real & !npos',
        'npos   -> real & !pos'
    ])
    """

    """
    ff = FactRules([
        'real   ->  complex',
        'real   ==  neg | zero | pos',

        'neg    ->  real & !pos & !zero',
        'zero   ->  real & !neg & !pos',
        'pos    ->  real & !neg & !zero',

        'npos   ==  real & !pos',
        'real   ==  pos | npos' # XXX this is a workaround for bug in process_rule
    ])

    FF = ff
    """


text:
from setuptools import setup

setup(
    name='rpy2_helpers',
    description='Easier R use from Python',
    author='Ed L. Cashin',
    author_email='ed.cashin@acm.org',
    url='https://github.com/ecashin/rpy2_helpers',
    version='0.3',
    py_modules = ['rpy2_helpers'],
    install_requires=[
        'numpy',
        'rpy2',
    ],
)


text:
require 'spec_helper'

module Rectangle
  describe Rectangle do

    it 'creates rectangle' do
      expect(Rectangle.new(13, 78)).to be
    end

    it 'creates rectangle with correct width and height' do
      rectangle1 = Rectangle.new 78, 13
      rectangle2 = Rectangle.new 78, 13
      expect(rectangle1).to eq rectangle2
    end

    it 'creates different rectangles with different width and height' do
      rectangle1 = Rectangle.new 78, 13
      rectangle2 = Rectangle.new 10, 15
      expect(rectangle1).not_to eq rectangle2
    end

    it 'counts area correctly' do
      expect(Rectangle.new(13, 6).area).to eq 78
    end

    it 'counts perimeter correctly' do
      expect(Rectangle.new(13, 6).perimeter).to eq 38
    end

  end

  describe Square do
    it 'creates square' do
      expect(Square.new 78).to be
    end

    it 'is comparable to rectangle' do
      expect(Square.new 78).to eq Rectangle.new(78, 78)
      expect(Square.new 78).not_to eq Rectangle.new(78, 13)
    end

  end
end


text:
require File.expand_path('../../../../spec_helper', __FILE__)
require File.expand_path('../shared/collect', __FILE__)

describe "Enumerator::Lazy#collect" do
  it_behaves_like :enumerator_lazy_collect, :collect
end


text:
export default {
  debug: true,
  testing: false,

  API_ENDPOINT: 'http://localhost:57386/api',
};


text:
package org.codehaus.griffon.runtime.jpa;

import griffon.plugins.jpa.JpaSettings;
import griffon.plugins.jpa.JpaSettingsStorage;
import org.codehaus.griffon.runtime.core.storage.DefaultObjectStorage;

/**
 * @author Andres Almiray
 */
public class DefaultJpaSettingsStorage extends DefaultObjectStorage<JpaSettings> implements JpaSettingsStorage {
}


text:
<?php

namespace Lug\Bundle\ResourceBundle\Tests\Util;

use Lug\Bundle\ResourceBundle\Util\ClassUtils;

/**
 * @author GeLo <geloen.eric@gmail.com>
 */
class ClassUtilsTest extends \PHPUnit_Framework_TestCase
{
    /**
     * @dataProvider realNamespaceProvider
     */
    public function testRealNamespace($class, $namespace)
    {
        $this->assertSame($namespace, ClassUtils::getRealNamespace($class));
    }

    /**
     * @dataProvider namespaceProvider
     */
    public function testNamespace($object, $namespace)
    {
        $this->assertSame($namespace, ClassUtils::getNamespace($object));
    }

    public function realNamespaceProvider()
    {
        return [
            [ClassUtils::class, 'Lug\\Bundle\\ResourceBundle\\Util'],
            [\stdClass::class, null],
        ];
    }

    public function namespaceProvider()
    {
        return [
            [new ClassUtils(), 'Lug\\Bundle\\ResourceBundle\\Util'],
            [new \stdClass(), null],
        ];
    }
}


text:
package cn.huangchaosuper.toolkits;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

/**
 * Created by I311579 on 9/28/2015.
 */
public class Utils {
    public static String OPENSTEP = "step.open";
    public static String CLOSESTEP = "step.close";
    public static String CONFIGPATH = "config.path";
    public static String SIMPLETASKPACKAGE = "simpletask.package";
    private static Logger logger = LoggerFactory.getLogger(Utils.class);
    public static boolean checkConfigValue(Properties properties, String key) {
        return checkConfigValue(properties, key, null);
    }

    public static boolean checkConfigValue(Properties properties, String key, String defaultValue) {
        return checkConfigValue(properties, key, defaultValue, null);
    }

    public static String getStringConfigVaule(Properties properties, String key, String defaultValue){
        return checkConfigValue(properties, key, defaultValue)?properties.getProperty(key):null;
    }

    public static String getStringConfigVaule(Properties properties, String key){
        return getStringConfigVaule(properties, key, null);
    }

    public static Boolean getBooleanConfigVaule(Properties properties, String key){
        return Boolean.valueOf(getStringConfigVaule(properties, key, String.valueOf(false)));
    }

    public static boolean checkConfigValue(Properties properties, String key, String defaultValue, String errorMessage) {
        String value = System.getProperty(key);
        if (value == null || value.equals("")) {
            value = properties.getProperty(key, defaultValue);
            if (value == null || value.equals("")) {
                return false;
            } else {
                properties.setProperty(key, value);
                return true;
            }
        } else {
            properties.setProperty(key, value);
            return true;
        }
    }

    public static Calendar getStopTime(int date, int hour) {
        Calendar stopTime = Calendar.getInstance();
        if (stopTime.get(Calendar.HOUR_OF_DAY) < hour) {
            date--;
        }
        stopTime.add(Calendar.DATE, date);
        stopTime.set(Calendar.HOUR_OF_DAY, hour);
        stopTime.set(Calendar.MINUTE, 0);
        stopTime.set(Calendar.SECOND, 0);
        stopTime.set(Calendar.MILLISECOND, 0);
        return stopTime;
    }

    public static Calendar getStartTime(ScheduleType scheduleType, Calendar stopTime) {
        Calendar startTime = Calendar.getInstance();
        startTime.setTime(stopTime.getTime());
        ScheduleType2Date(scheduleType, startTime);
        return startTime;
    }

    private static void ScheduleType2Date(ScheduleType scheduleType, Calendar date) {
        switch (scheduleType) {
            case Daily:
                date.add(Calendar.DATE, -1);
                break;
            case Weekly:
                date.add(Calendar.DATE, -7);
                break;
            case Fortnightly:
                date.add(Calendar.DATE, -14);
                break;
            case Monthly:
                date.add(Calendar.MONTH, -1);
                break;
            default:
                break;
        }
    }

    public enum ScheduleType {
        Daily,
        Weekly,
        Fortnightly,
        Monthly,
    }

    public static String isoDateFormat(Calendar calendar) {
        TimeZone tz = TimeZone.getTimeZone("UTC");
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");
        df.setTimeZone(tz);
        return df.format(calendar.getTime());
    }

    public static String inputStream2String(InputStream is) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int i = -1;
        try {
            while ((i = is.read()) != -1) {
                baos.write(i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return baos.toString();
    }

    public static String jiraDate2String(Date date) {
        return date2String(date, "yyyy/MM/dd");
    }

    public static String logstashDate2String(Date date) {
        return date2String(date, "yyyy.MM.dd");
    }

    public static String elasticsearchDate2String(Date date) {
        return date2String(date, "yyyy-MM-dd'T'HH:mm:ss");
    }

    public static String date2String(Date date, String formatter) {
        SimpleDateFormat sdf = new SimpleDateFormat(formatter);
        return sdf.format(date);
    }

    /**
     * get all class from package
     *
     * @param pack
     * @return
     */
    public static Set<Class<?>> getClasses(String pack) {

        // The class collection
        Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
        // recursive or not
        boolean recursive = true;
        // 获取包的名字 并进行替换
        String packageName = pack;
        String packageDirName = packageName.replace('.', '/');
        // 定义一个枚举的集合 并进行循环来处理这个目录下的things
        Enumeration<URL> dirs;
        try {
            dirs = Thread.currentThread().getContextClassLoader().getResources(
                    packageDirName);
            // 循环迭代下去
            while (dirs.hasMoreElements()) {
                // 获取下一个元素
                URL url = dirs.nextElement();
                // 得到协议的名称
                String protocol = url.getProtocol();
                // 如果是以文件的形式保存在服务器上
                if ("file".equals(protocol)) {
                    System.err.println("file type scan");
                    // 获取包的物理路径
                    String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
                    // 以文件的方式扫描整个包下的文件 并添加到集合中
                    findAndAddClassesInPackageByFile(packageName, filePath,
                            recursive, classes);
                } else if ("jar".equals(protocol)) {
                    // 如果是jar包文件
                    // 定义一个JarFile
                    System.err.println("jar type scan");
                    JarFile jar;
                    try {
                        // 获取jar
                        jar = ((JarURLConnection) url.openConnection())
                                .getJarFile();
                        // 从此jar包 得到一个枚举类
                        Enumeration<JarEntry> entries = jar.entries();
                        // 同样的进行循环迭代
                        while (entries.hasMoreElements()) {
                            // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
                            JarEntry entry = entries.nextElement();
                            String name = entry.getName();
                            // 如果是以/开头的
                            if (name.charAt(0) == '/') {
                                // 获取后面的字符串
                                name = name.substring(1);
                            }
                            // 如果前半部分和定义的包名相同
                            if (name.startsWith(packageDirName)) {
                                int idx = name.lastIndexOf('/');
                                // 如果以"/"结尾 是一个包
                                if (idx != -1) {
                                    // 获取包名 把"/"替换成"."
                                    packageName = name.substring(0, idx)
                                            .replace('/', '.');
                                }
                                // 如果可以迭代下去 并且是一个包
                                if ((idx != -1) || recursive) {
                                    // 如果是一个.class文件 而且不是目录
                                    if (name.endsWith(".class")
                                            && !entry.isDirectory()) {
                                        // 去掉后面的".class" 获取真正的类名
                                        String className = name.substring(
                                                packageName.length() + 1, name
                                                        .length() - 6);
                                        try {
                                            // 添加到classes
                                            classes.add(Class
                                                    .forName(packageName + '.'
                                                            + className));
                                        } catch (ClassNotFoundException e) {
                                            // log
                                            // .error("添加用户自定义视图类错误 找不到此类的.class文件");
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            }
                        }
                    } catch (IOException e) {
                        // log.error("在扫描用户定义视图时从jar包获取文件出错");
                        e.printStackTrace();
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return classes;
    }

    /**
     * 以文件的形式来获取包下的所有Class
     *
     * @param packageName
     * @param packagePath
     * @param recursive
     * @param classes
     */
    private static void findAndAddClassesInPackageByFile(String packageName,
                                                         String packagePath, final boolean recursive, Set<Class<?>> classes) {
        // 获取此包的目录 建立一个File
        File dir = new File(packagePath);
        // 如果不存在或者 也不是目录就直接返回
        if (!dir.exists() || !dir.isDirectory()) {
            // log.warn("用户定义包名 " + packageName + " 下没有任何文件");
            return;
        }
        // 如果存在 就获取包下的所有文件 包括目录
        File[] dirfiles = dir.listFiles(new FileFilter() {
            // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
            public boolean accept(File file) {
                return (recursive && file.isDirectory())
                        || (file.getName().endsWith(".class"));
            }
        });
        // 循环所有文件
        for (File file : dirfiles) {
            // 如果是目录 则继续扫描
            if (file.isDirectory()) {
                findAndAddClassesInPackageByFile(packageName + "."
                                + file.getName(), file.getAbsolutePath(), recursive,
                        classes);
            } else {
                // 如果是java类文件 去掉后面的.class 只留下类名
                String className = file.getName().substring(0,
                        file.getName().length() - 6);
                try {
                    // 添加到集合中去
                    //classes.add(Class.forName(packageName + '.' + className));
                    //经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净
                    classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className));
                } catch (ClassNotFoundException e) {
                    // log.error("添加用户自定义视图类错误 找不到此类的.class文件");
                    e.printStackTrace();
                }
            }
        }
    }

}