text:
import os.path
import tempfile
import unittest

import numpy as np
from obspy import Stream, Trace, UTCDateTime as UTC

from yam.stretch import stretch
from yam.commands import write_dict, read_dicts

class TestCase(unittest.TestCase):

    def test_stretch(self):
        h = {'sampling_rate': 100}
        h['network1'] = h['network2'] = 'NET'
        h['station1'] = h['station2'] = h['network'] = h['location'] = 'STA'
        h['location1'] = h['location2'] = ''
        h['channel1'] = h['channel2'] = h['location'] = h['channel'] = 'HHZ'
        h['dist'] = h['azi'] = h['baz'] = 0
        vel_changes = [0, 1, -1]
        traces = []
        dt = 24 * 3600
        t0 = UTC()
        for i, v in enumerate(vel_changes):
            mul = 1 + v / 100
            t = np.linspace(-10 * mul, 10 * mul, 10001)
            data = np.cos(2 * np.pi * t)
            h['starttime'] = t0 + i * dt
            tr = Trace(data, header=h)
            traces.append(tr)
        d = stretch(Stream(traces), max_stretch=1.1, num_stretch=2201,
                    tw=(1, 5), sides='both', reftr=traces[0])
        expect = np.array(vel_changes)
        np.testing.assert_allclose(d['velchange_vs_time'], expect)
        np.testing.assert_allclose(d['corr_vs_time'], (1, 1, 1))
        self.assertAlmostEqual(d['velchange_values'][-1], 1.1)
        self.assertEqual(len(d['velchange_values']), 2201)
        # test writing and reading
        with tempfile.TemporaryDirectory(prefix='yam_') as tmpdir:
            fname = os.path.join(tmpdir, 'stretch.h5')
            d['attrs']['key'] = 'test'
            write_dict(d, fname)
            d2 = read_dicts(fname)[0]
            for key in d:
                if key == 'sim_mat':
                    np.testing.assert_allclose(d2[key], d[key], rtol=1e-3)
                elif isinstance(d2[key], np.ndarray):
                    np.testing.assert_equal(d2[key], d[key])
                else:
                    self.assertEqual(d2[key], d[key])
            d2['attrs']['key'] = 'test2'
            write_dict(d2, fname)

def suite():
    return unittest.makeSuite(TestCase, 'test')

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


text:
This gem adds some javascript to change the default behaviour of data-confirm processing for both Boostrap 2 and Bootstrap 3.

The normal confirm dialog shows a text with buttons 'ok' and 'cancel'. More information is needed here for a user to make the right decision. This gem therefore also adds:

* data-confirm-fade (default: false)
* data-confirm-title (default: window.top.location.origin)
* data-confirm-cancel (default: 'cancel')
* data-confirm-cancel-class (default: 'btn cancel')
* data-confirm-proceed (default: 'ok')
* data-confirm-proceed-class (default: 'btn-primary')

This behaviour is similar to that of a "regular" confirm box in ways that it uses the same title and button labels. Defaults can be changed in two ways:

Changing all default values:

    $.fn.twitter_bootstrap_confirmbox.defaults = {
        fade: false,
        title: null, // if title equals null window.top.location.origin is used
        cancel: "Cancel",
        cancel_class: "btn cancel",
        proceed: "OK",
        proceed_class: "btn proceed btn-primary"
    };

Only changing one default value:

    $.fn.twitter_bootstrap_confirmbox.defaults.proceed_class = "btn proceed btn-success";

## Installation

Add this line to your application's Gemfile:

    gem 'twitter-bootstrap-rails-confirm'

And then execute:

    $ bundle

## Usage

Add it to your application.js, anywhere after you require jquery_ujs:

    //= require twitter/bootstrap/rails/confirm

Next... nothing. There is nothing you need to do to get this working. A helper could be useful for handling large amount of destroy buttons:

    def destroy_link_to(path, options)
      link_to t('.destroy'), path,
        :method => :delete,
        :class => "btn",
        :confirm => t('.destroy_confirm.body', :item => options[:item]),
        "data-confirm-fade" => true,
        "data-confirm-title" => t('.destroy_confirm.title', :item => options[:item]),
        "data-confirm-cancel" => t('.destroy_confirm.cancel', :item => options[:item]),
        "data-confirm-cancel-class" => "btn-cancel"),
        "data-confirm-proceed" => t('.destroy_confirm.proceed', :item => options[:item]),
        "data-confirm-proceed-class" => "btn-danger"
    end

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Added some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

## Changelog

### 1.0.4 (November 25, 2014)

* [(rvanlieshout)](https://github.com/rvanlieshout) Added bootstrap 3 support

### 1.0.3 (September 4, 2014)

* [(rvanlieshout)](https://github.com/rvanlieshout) [Problems with using event constructors](https://github.com/bluerail/twitter-bootstrap-rails-confirm/issues/18)
* [(stevelacey)](https://github.com/stevelacey) [Avoid appending custom proceed class to btn-primary, refactored dialog JS](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/17)
* [(zsy056)](https://github.com/zsy056) [When message is numerical, the call replace on message will cause a TypeError](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/22)

### 1.0.2 (Oktober 11, 2013)

* [(kramerc)](https://github.com/kramerc) [Prevent the default action on the modal's buttons.](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/9)
* [(taavo)](https://github.com/taavo) [click handler returns false](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/6)
* [(stevelacey)](https://github.com/stevelacey) [Swap out new lines for br's in message](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/16)
* [(DavyCardinaal)](https://github.com/DavyCardinaal) [Confirmbox defaults: Cancel button btn-default](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/15) (Bootstrap 3 only)
* [(digitalfrost)](https://github.com/digitalfrost) [Create "click" event using an event constructor](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/14)

### 1.0.1 (April 23, 2013)

* [(kramerc)](https://github.com/kramerc) [Add an option for including the fade class](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/8)
* [(taavo)](https://github.com/taavo) [Load asap](https://github.com/bluerail/twitter-bootstrap-rails-confirm/pull/5)

### 1.0.0 (February 22, 2013)

* First 'official' release
* Many thanks to [taavo](https://github.com/taavo) for his contributions

redpajama_set_name: RedPajamaGithub


text:
//
//  $Id$
//
//  SPSQLParser.m
//  sequel-pro
//
//  Created by Rowan Beentje on January 18, 2009.
//  Copyright (c) 2009 Rowan Beentje. All rights reserved.
//
//  Permission is hereby granted, free of charge, to any person
//  obtaining a copy of this software and associated documentation
//  files (the "Software"), to deal in the Software without
//  restriction, including without limitation the rights to use,
//  copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the
//  Software is furnished to do so, subject to the following
//  conditions:
//
//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
//  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
//  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
//  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
//  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
//  OTHER DEALINGS IN THE SOFTWARE.
//
//  More info at <http://code.google.com/p/sequel-pro/>

#import "SPSQLParser.h"
#import "RegexKitLite.h"

/**
 * Include all the extern variables and prototypes required for flex (used for syntax highlighting)
 */
#import "SPSQLTokenizer.h"
extern NSInteger tolex();
extern NSInteger yyuoffset, yyuleng;
typedef struct to_buffer_state *TO_BUFFER_STATE;
void to_switch_to_buffer(TO_BUFFER_STATE);
TO_BUFFER_STATE to_scan_string (const char *);

@interface SPSQLParser (PrivateAPI)

- (unichar) _charAtIndex:(NSInteger)index;
- (void) _clearCharCache;

@end

/**
 * Please see the header files for a general description of the purpose of this class,
 * and increased overview detail for the functions below.
 */
@implementation SPSQLParser : NSMutableString

#pragma mark -
#pragma mark Parser information

/**
 * Return whether any carriage returns have been encountered during
 * parsing; quoted strings are not included.  May be used to determine
 * whether text needs to be normalised.
 */
- (BOOL)containsCarriageReturns
{
	return containsCRs;
}

#pragma mark -
#pragma mark Parser behaviour setting

/**
 * Control whether comment strings should be skipped during parsing.
 */
- (void)setIgnoreCommentStrings:(BOOL)ignoringCommentStrings
{
	ignoreCommentStrings = ignoringCommentStrings;
}

/**
 * Control whether DELIMITER commands are recognised and used to override
 * supported characters.
 * When delimiter support is enabled, many string functions will start looking
 * for the delimiter *instead* of the supplied character, assuming that use
 * is looking for line endings.  This will be improved in future versions.
 */
- (void) setDelimiterSupport:(BOOL)shouldSupportDelimiters
{
	supportDelimiters = shouldSupportDelimiters;
}

#pragma mark -
#pragma mark SQL-aware utility methods

/**
 * Removes comments within the current string, trimming "#", "--[/s]", and "⁄* *⁄" style strings.
 */
- (void) deleteComments
{
	NSUInteger currentStringIndex, commentEndIndex, quotedStringEndIndex;
	unichar currentCharacter;
	NSUInteger stringLength = [string length];

	// Walk along the string, processing characters.
	for (currentStringIndex = 0; currentStringIndex < stringLength; currentStringIndex++) {
		currentCharacter = CFStringGetCharacterAtIndex((CFStringRef)string ,currentStringIndex);
		switch (currentCharacter) {

			// When quote characters are encountered walk to the end of the quoted string.
			case '\'':
			case '"':
			case '`':
				quotedStringEndIndex = [self endIndexOfStringQuotedByCharacter:currentCharacter startingAtIndex:currentStringIndex+1];
				if (quotedStringEndIndex == NSNotFound) {
					return;
				}
				currentStringIndex = quotedStringEndIndex;
				break;

			// For comments starting "--[\s]", ensure the start syntax is valid before proceeding.
			case '-':
				if (stringLength < currentStringIndex + 2) break;
				if (CFStringGetCharacterAtIndex((CFStringRef)string, currentStringIndex+1) != '-') break;
				if (![[NSCharacterSet whitespaceCharacterSet] characterIsMember:CFStringGetCharacterAtIndex((CFStringRef)string, currentStringIndex+2)]) break;
				commentEndIndex = [self endIndexOfCommentOfType:SPDoubleDashComment startingAtIndex:currentStringIndex];

				// Remove the comment
				[self deleteCharactersInRange:NSMakeRange(currentStringIndex, commentEndIndex - currentStringIndex + 1)];
				stringLength -= commentEndIndex - currentStringIndex + 1;
				currentStringIndex--;
				break;

			case '#':
				commentEndIndex = [self endIndexOfCommentOfType:SPHashComment startingAtIndex:currentStringIndex];

				// Remove the comment
				[self deleteCharactersInRange:NSMakeRange(currentStringIndex, commentEndIndex - currentStringIndex + 1)];
				stringLength -= commentEndIndex - currentStringIndex + 1;
				currentStringIndex--;
				break;

			// For comments starting "/*", ensure the start syntax is valid before proceeding.
			case '/':
				if (stringLength < currentStringIndex + 1) break;
				if (CFStringGetCharacterAtIndex((CFStringRef)string, currentStringIndex+1) != '*') break;
				commentEndIndex = [self endIndexOfCommentOfType:SPCStyleComment startingAtIndex:currentStringIndex];

				// Remove the comment
				[self deleteCharactersInRange:NSMakeRange(currentStringIndex, commentEndIndex - currentStringIndex + 1)];
				stringLength -= commentEndIndex - currentStringIndex + 1;
				currentStringIndex--;
				break;
		}
	}
}

/**
 * Removes quotes surrounding the string if present, and un-escapes internal occurrences of the quote character before returning.
 */
- (NSString *) unquotedString
{
	NSMutableString *returnString;
	NSUInteger stringEndIndex;
	unichar quoteCharacter;

	if (![string length]) return nil;

	// If the first character is not a quote character, return the entire string.
	quoteCharacter = CFStringGetCharacterAtIndex((CFStringRef)string, 0);
	if (quoteCharacter != '`' && quoteCharacter != '"' && quoteCharacter != '\'') {
		return [NSString stringWithString:string];
	}

	// Get the end of the string
	stringEndIndex = [self endIndexOfStringQuotedByCharacter:quoteCharacter startingAtIndex:1];
	if (stringEndIndex == NSNotFound) {
		return [NSString stringWithString:string];
	}

	// Trim the string appropriately
	returnString = [NSMutableString stringWithString:[string substringWithRange:NSMakeRange(1, stringEndIndex-1)]];

	// Remove escaped characters and escaped strings as appropriate
	if (quoteCharacter == '`' || quoteCharacter == '"' || quoteCharacter == '\'') {
		[returnString replaceOccurrencesOfString:[NSString stringWithFormat:@"%C%C", quoteCharacter, quoteCharacter] withString:[NSString stringWithFormat:@"%C", quoteCharacter] options:0 range:NSMakeRange(0, [returnString length])];
	}
	if (quoteCharacter == '"') {
		[returnString replaceOccurrencesOfString:@"\\\"" withString:@"\"" options:0 range:NSMakeRange(0, [returnString length])];
		[returnString replaceOccurrencesOfString:@"\\\\" withString:@"\\" options:0 range:NSMakeRange(0, [returnString length])];
	} else	if (quoteCharacter == '\'') {
		[returnString replaceOccurrencesOfString:@"\\'" withString:@"'" options:0 range:NSMakeRange(0, [returnString length])];
		[returnString replaceOccurrencesOfString:@"\\\\" withString:@"\\" options:0 range:NSMakeRange(0, [returnString length])];
	}

	return returnString;
}

/**
 * Normalise a string, readying it for queries - trims whitespace from both
 * ends, and ensures line endings which aren't in quotes are LF.
 */
+ (NSString *) normaliseQueryForExecution:(NSString *)queryString
{
	NSUInteger stringLength = [queryString length];
	NSCharacterSet *trimCharset = [NSCharacterSet whitespaceAndNewlineCharacterSet];

	// Check the ends of the string for whitespace, to determine if it needs removing
	NSUInteger whitespaceCharsAtStart = 0;
	NSUInteger whitespaceCharsAtEnd = 0;
	while (whitespaceCharsAtStart < stringLength && [trimCharset characterIsMember:CFStringGetCharacterAtIndex((CFStringRef)queryString, whitespaceCharsAtStart)])
		whitespaceCharsAtStart++;
	while (whitespaceCharsAtEnd < stringLength && [trimCharset characterIsMember:CFStringGetCharacterAtIndex((CFStringRef)queryString, stringLength - whitespaceCharsAtEnd - 1)])
		whitespaceCharsAtEnd++;

	// Trim if necessary
	if (whitespaceCharsAtStart || whitespaceCharsAtEnd) {
		stringLength -= whitespaceCharsAtStart + whitespaceCharsAtEnd;
		queryString = [queryString substringWithRange:NSMakeRange(whitespaceCharsAtStart, stringLength)];
	}

	// Check for carriage returns in the string
	NSMutableArray *carriageReturnPositions = [NSMutableArray array];
	NSUInteger currentStringIndex, innerStringIndex, i, quotedStringLength;
	unichar currentCharacter, innerCharacter;
	BOOL characterIsEscaped;
	for (currentStringIndex = 0; currentStringIndex < stringLength; currentStringIndex++) {
		currentCharacter = CFStringGetCharacterAtIndex((CFStringRef)queryString, currentStringIndex);
		switch (currentCharacter) {

			// When quote characters are encountered walk to the end of the quoted string.
			case '\'':
			case '"':
			case '`':
				for (innerStringIndex = currentStringIndex+1; innerStringIndex < stringLength; innerStringIndex++) {
					innerCharacter = CFStringGetCharacterAtIndex((CFStringRef)queryString, innerStringIndex);

					// If the string end is a backtick and one has been encountered, treat it as end of string
					if (innerCharacter == '`' && currentCharacter == '`') {

						// ...as long as the next character isn't also a backtick, in which case it's being quoted.  Skip both.
						if ((innerStringIndex + 1) < stringLength && CFStringGetCharacterAtIndex((CFStringRef)queryString, innerStringIndex+1) == '`') {
							innerStringIndex++;
							continue;
						}

						currentStringIndex = innerStringIndex;
						break;

					// Otherwise, prepare to treat the string as ended when meeting the correct boundary character....
					} else if (innerCharacter == currentCharacter) {

						// ...but only if the string end isn't escaped with an *odd* number of escaping characters...
						characterIsEscaped = NO;
						i = 1;
						quotedStringLength = innerStringIndex - 1;
						while ((quotedStringLength - i) > 0 && CFStringGetCharacterAtIndex((CFStringRef)queryString, innerStringIndex - i) == '\\') {
							characterIsEscaped = !characterIsEscaped;
							i++;
						}

						// If an even number have been found, it may be the end of the string - as long as the subsequent character
						// isn't also the same character, in which case it's another form of escaping.
						if (!characterIsEscaped) {
							if ((innerStringIndex + 1) < stringLength && CFStringGetCharacterAtIndex((CFStringRef)queryString, innerStringIndex+1) == currentCharacter) {
								innerStringIndex++;
								continue;
							}

							// Really is the end of the string.
							currentStringIndex = innerStringIndex;
							break;
						}
					}
				}

				// The quoted string has been left open - end processing.
				currentStringIndex = innerStringIndex;
				break;

			case '\r':
				[carriageReturnPositions addObject:[NSNumber numberWithUnsignedInteger:currentStringIndex]];
				break;
		}
	}

	// If any CRs were found, iterate over them backwards, converting to LFs by replacing or subtracting as appropriate
	NSUInteger carriageReturnCount = [carriageReturnPositions count];
	if (carriageReturnCount) {
		NSMutableString *normalisedString = [NSMutableString stringWithString:queryString];
		BOOL isCRLF;
		NSUInteger CRLocation;
		while ( carriageReturnCount-- ) {
			CRLocation = [[carriageReturnPositions objectAtIndex:carriageReturnCount] unsignedIntegerValue];

			// Check whether it's a CRLF or just a CR
			isCRLF = NO;
			if ([normalisedString length] > CRLocation + 1 && CFStringGetCharacterAtIndex((CFStringRef)normalisedString, CRLocation + 1) == '\n') isCRLF = YES;

			// Normalise the line endings
			if (isCRLF) {
				[normalisedString deleteCharactersInRange:NSMakeRange(CRLocation, 1)];
			} else {
				[normalisedString replaceCharactersInRange:NSMakeRange(CRLocation, 1) withString:@"\n"];
			}
		}
		queryString = normalisedString;
	}

	return queryString;
}

#pragma mark -
#pragma mark Trimming or retrieving strings from the front of the string

/**
 * Removes characters from the string up to the first occurrence of the supplied character.
 */
- (BOOL) trimToCharacter:(unichar)character inclusively:(BOOL)inclusive
{
	return [self trimToCharacter:character inclusively:inclusive ignoringQuotedStrings:YES];
}

/**
 * As trimToCharacter: ..., but allows control over whether characters within quoted
 * strings are ignored.
 */
- (BOOL) trimToCharacter:(unichar)character inclusively:(BOOL)inclusive ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	NSUInteger stringIndex = -1;

	// Get the first occurrence of the specified character, returning NO if not found
	do {
		stringIndex = [self firstOccurrenceOfCharacter:character afterIndex:stringIndex ignoringQuotedStrings:ignoreQuotedStrings];
	} while (lastMatchIsDelimiter && stringIndex != NSNotFound);
	if (stringIndex == NSNotFound) return NO;

	// If it has been found, trim the string appropriately and return YES
	[self deleteCharactersInRange:NSMakeRange(0, stringIndex + (inclusive?1:-delimiterLengthMinusOne))];
	return YES;
}

/**
 * Returns an NSString containing characters from the string up to the first occurrence of the supplied character.
 */
- (NSString *) stringToCharacter:(unichar)character inclusively:(BOOL)inclusive
{
	return [self stringToCharacter:character inclusively:inclusive ignoringQuotedStrings:YES];
}

/**
 * As stringToCharacter: ..., but allows control over whether characters within quoted strings
 * are ignored.
 */
- (NSString *) stringToCharacter:(unichar)character inclusively:(BOOL)inclusive ignoringQuotedStrings:(BOOL)ignoreQuotedStrings {
	NSUInteger stringIndex = -1;
	NSUInteger returnFromPosition;

	// Get the first occurrence of the specified character, returning nil if not found
	do {
		returnFromPosition = stringIndex + 1;
		stringIndex = [self firstOccurrenceOfCharacter:character afterIndex:stringIndex ignoringQuotedStrings:ignoreQuotedStrings];
	} while (lastMatchIsDelimiter && stringIndex != NSNotFound);
	if (stringIndex == NSNotFound) return nil;

	// If it has been found, return the appropriate string range
	return [string substringWithRange:NSMakeRange(returnFromPosition, stringIndex + (inclusive?1:-delimiterLengthMinusOne) - returnFromPosition)];
}

/**
 * Returns an NSString containing characters from the string up to the first occurrence of the supplied
 * character, also removing them from the string.
 */
- (NSString *) trimAndReturnStringToCharacter:(unichar)character trimmingInclusively:(BOOL)inclusiveTrim returningInclusively:(BOOL)inclusiveReturn
{
	return [self trimAndReturnStringToCharacter:character trimmingInclusively:inclusiveTrim returningInclusively:inclusiveReturn ignoringQuotedStrings:YES];
}

/**
 * As trimAndReturnStringToCharacter: ..., but allows control over whether characters within quoted
 * strings are ignored.
 */
- (NSString *) trimAndReturnStringToCharacter:(unichar)character trimmingInclusively:(BOOL)inclusiveTrim returningInclusively:(BOOL)inclusiveReturn ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	NSUInteger returnFromPosition;
	NSUInteger stringIndex = 0;
	NSString *resultString;

	if (character != parsedToChar) {
		parsedToChar = character;
		parsedToPosition = -1;
	}

	// Get the first occurrence of the specified character, returning nil if it could not be found
	do {
		returnFromPosition = stringIndex;
		stringIndex = [self firstOccurrenceOfCharacter:character afterIndex:parsedToPosition ignoringQuotedStrings:ignoreQuotedStrings];
	} while (lastMatchIsDelimiter && stringIndex != NSNotFound);
	if (stringIndex == NSNotFound) return nil;

	// Select the appropriate string range, truncate the current string, and return the selected string
	resultString = [NSString stringWithString:[string substringWithRange:NSMakeRange(returnFromPosition, stringIndex + (inclusiveReturn?1:-delimiterLengthMinusOne) - returnFromPosition)]];
	[self deleteCharactersInRange:NSMakeRange(0, stringIndex + (inclusiveTrim?1:-delimiterLengthMinusOne))];
	return resultString;
}

#pragma mark -
#pragma mark Trimming or retrieving strings from one specified character to another

/**
 * Returns characters from the string up to and from the first occurrence of the supplied opening character
 * to the appropriate occurrence of the supplied closing character. "inclusively" controls whether the supplied
 * characters should also be returned.
 */
- (NSString *) stringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter inclusively:(BOOL)inclusive
{
	return [self stringFromCharacter:fromCharacter toCharacter:toCharacter inclusively:inclusive skippingBrackets:NO ignoringQuotedStrings:YES];
}

/**
 * As stringFromCharacter: toCharacter: ..., but allows control over whether to skip
 * over bracket-enclosed characters, as in subqueries, enums, definitions or groups
 */
- (NSString *) stringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter inclusively:(BOOL)inclusive skippingBrackets:(BOOL)skipBrackets
{
	return [self stringFromCharacter:fromCharacter toCharacter:toCharacter inclusively:inclusive skippingBrackets:skipBrackets ignoringQuotedStrings:YES];
}

/**
 * As stringFromCharacter: toCharacter: ..., but allows control over whether characters within quoted
 * strings are ignored.
 */
- (NSString *) stringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter inclusively:(BOOL)inclusive ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	return [self stringFromCharacter:fromCharacter toCharacter:toCharacter inclusively:inclusive skippingBrackets:NO ignoringQuotedStrings:ignoreQuotedStrings];
}

/**
 * As stringFromCharacter: toCharacter: ..., but allows control over both bracketing and quoting.
 */
- (NSString *) stringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter inclusively:(BOOL)inclusive skippingBrackets:(BOOL)skipBrackets ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	NSUInteger toCharacterIndex, fromCharacterIndex = -1;

	// Look for the first occurrence of the from: character
	do {
		fromCharacterIndex = [self firstOccurrenceOfCharacter:fromCharacter afterIndex:fromCharacterIndex skippingBrackets:skipBrackets ignoringQuotedStrings:ignoreQuotedStrings];
	} while (lastMatchIsDelimiter && fromCharacterIndex != NSNotFound);
	if (fromCharacterIndex == NSNotFound) return nil;

	// Look for the first/balancing occurrence of the to: character
	toCharacterIndex = fromCharacterIndex;
	do {
		toCharacterIndex = [self firstOccurrenceOfCharacter:toCharacter afterIndex:toCharacterIndex skippingBrackets:skipBrackets ignoringQuotedStrings:ignoreQuotedStrings];
	} while (lastMatchIsDelimiter && toCharacterIndex != NSNotFound);
	if (toCharacterIndex == NSNotFound) return nil;

	// Return the correct part of the string.
	return [string substringWithRange:NSMakeRange(fromCharacterIndex + (inclusive?0:1), toCharacterIndex + (inclusive?1:-1) - fromCharacterIndex)];
}

/**
 * As stringFromCharacter: toCharacter: ..., but also trims the string up to the "to" character and
 * up to or including the "from" character, depending on whether "trimmingInclusively" is set.
 */
- (NSString *) trimAndReturnStringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter trimmingInclusively:(BOOL)inclusiveTrim returningInclusively:(BOOL)inclusiveReturn
{
	return [self trimAndReturnStringFromCharacter:fromCharacter toCharacter:toCharacter trimmingInclusively:inclusiveTrim returningInclusively:inclusiveReturn skippingBrackets:NO ignoringQuotedStrings:YES];
}

/**
 * As trimAndReturnStringFromCharacter: toCharacter: ..., but allows control over whether to
 * skip over bracket-enclosed characters, as in subqueries, enums, definitions or groups.
 */
- (NSString *) trimAndReturnStringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter trimmingInclusively:(BOOL)inclusiveTrim returningInclusively:(BOOL)inclusiveReturn skippingBrackets:(BOOL)skipBrackets
{
	return [self trimAndReturnStringFromCharacter:fromCharacter toCharacter:toCharacter trimmingInclusively:inclusiveTrim returningInclusively:inclusiveReturn skippingBrackets:skipBrackets ignoringQuotedStrings:YES];
}

/**
 * As trimAndReturnStringFromCharacter: toCharacter: ..., but allows control over whether characters
 * within quoted strings are ignored.
 */
- (NSString *) trimAndReturnStringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter trimmingInclusively:(BOOL)inclusiveTrim returningInclusively:(BOOL)inclusiveReturn ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	return [self trimAndReturnStringFromCharacter:fromCharacter toCharacter:toCharacter trimmingInclusively:inclusiveTrim returningInclusively:inclusiveReturn skippingBrackets:NO ignoringQuotedStrings:ignoreQuotedStrings];
}

/**
 * As trimAndReturnStringFromCharacter: toCharacter: ..., but allows control over both bracketing
 * and quoting.
 */
- (NSString *) trimAndReturnStringFromCharacter:(unichar)fromCharacter toCharacter:(unichar)toCharacter trimmingInclusively:(BOOL)inclusiveTrim returningInclusively:(BOOL)inclusiveReturn skippingBrackets:(BOOL)skipBrackets ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	NSUInteger fromCharacterIndex = -1, toCharacterIndex;
	NSString *resultString;

	// Look for the first occurrence of the from: character
	do {
		fromCharacterIndex = [self firstOccurrenceOfCharacter:fromCharacter afterIndex:fromCharacterIndex skippingBrackets:skipBrackets ignoringQuotedStrings:ignoreQuotedStrings];
	} while (lastMatchIsDelimiter && fromCharacterIndex != NSNotFound);
	if (fromCharacterIndex == NSNotFound) return nil;

	// Look for the first/balancing occurrence of the to: character
	toCharacterIndex = fromCharacterIndex;
	do {
		toCharacterIndex = [self firstOccurrenceOfCharacter:toCharacter afterIndex:toCharacterIndex skippingBrackets:skipBrackets ignoringQuotedStrings:ignoreQuotedStrings];
	} while (lastMatchIsDelimiter && toCharacterIndex != NSNotFound);
	if (toCharacterIndex == NSNotFound) return nil;

	// Select the correct part of the string, truncate the current string, and return the selected string.
	resultString = [string substringWithRange:NSMakeRange(fromCharacterIndex + (inclusiveReturn?0:1), toCharacterIndex + (inclusiveReturn?1:-1) - fromCharacterIndex)];
	[self deleteCharactersInRange:NSMakeRange(fromCharacterIndex + (inclusiveTrim?0:1), toCharacterIndex + (inclusiveTrim?1:-1) - fromCharacterIndex)];
	return resultString;
}

#pragma mark -
#pragma mark Splitting strings

/**
 * Split a string on the boundaries formed by the supplied character, returning an array of strings.
 */
- (NSArray *) splitStringByCharacter:(unichar)character
{
	return [self splitStringByCharacter:character skippingBrackets:NO ignoringQuotedStrings:YES];
}

/**
 * As splitStringByCharacter: ..., but allows control over whether to skip over bracket-enclosed
 * characters, as in subqueries, enums, definitions or groups.
 */
- (NSArray *) splitStringByCharacter:(unichar)character skippingBrackets:(BOOL)skipBrackets
{
	return [self splitStringByCharacter:character skippingBrackets:skipBrackets ignoringQuotedStrings:YES];
}

/**
 * As splitStringByCharacter:, but allows control over whether characters
 * within quoted strings are ignored.
 */
- (NSArray *) splitStringByCharacter:(unichar)character ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	return [self splitStringByCharacter:character skippingBrackets:NO ignoringQuotedStrings:ignoreQuotedStrings];
}

/**
 * As splitStringByCharacter: ..., but allows control over both bracketing and quoting.
 */
- (NSArray *) splitStringByCharacter:(unichar)character skippingBrackets:(BOOL)skipBrackets ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	NSMutableArray *resultsArray = [NSMutableArray array];
	NSInteger stringIndex = -1;
	NSUInteger nextIndex = 0;
	NSInteger queryLength;

	IMP firstOccOfChar = [self methodForSelector:@selector(firstOccurrenceOfCharacter:afterIndex:skippingBrackets:ignoringQuotedStrings:)];
	IMP subString = [string methodForSelector:@selector(substringWithRange:)];

	// Walk through the string finding the character to split by, and add all strings to the array.
	while (1) {
		nextIndex = (NSUInteger)(*firstOccOfChar)(self, @selector(firstOccurrenceOfCharacter:afterIndex:skippingBrackets:ignoringQuotedStrings:), character, stringIndex, skipBrackets, ignoreQuotedStrings);
		while (lastMatchIsDelimiter && nextIndex != NSNotFound) {
			stringIndex = nextIndex;
			nextIndex = (NSUInteger)(*firstOccOfChar)(self, @selector(firstOccurrenceOfCharacter:afterIndex:skippingBrackets:ignoringQuotedStrings:), character, stringIndex, skipBrackets, ignoreQuotedStrings);
		}
		if (nextIndex == NSNotFound)
			break;

		// Add queries to the result array if they have a length
		stringIndex++;
		queryLength = nextIndex - stringIndex - delimiterLengthMinusOne;
		if (queryLength > 0)
			CFArrayAppendValue((CFMutableArrayRef)resultsArray, (NSString *)(*subString)(string, @selector(substringWithRange:), NSMakeRange(stringIndex, queryLength)));

		stringIndex = nextIndex;
	}

	// Add the end of the string after the previously matched character where appropriate.
	if ((NSUInteger)(stringIndex + 1) < [string length]) {
		NSString *finalQuery = [[string substringFromIndex:stringIndex + 1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
		if (supportDelimiters && [finalQuery isMatchedByRegex:@"(?i)^\\s*delimiter\\s+\\S+"])
			finalQuery = nil;
		if ([finalQuery length])
			[resultsArray addObject:finalQuery];
	}

	return resultsArray;
}

/**
 * As splitStringByCharacter:, but returning only the ranges of queries, stored as NSValues.
 */
- (NSArray *) splitStringIntoRangesByCharacter:(unichar)character
{
	NSMutableArray *resultsArray = [NSMutableArray array];
	NSInteger stringIndex = -1;
	NSUInteger nextIndex = 0;
	NSInteger queryLength;

	IMP firstOccOfChar = [self methodForSelector:@selector(firstOccurrenceOfCharacter:afterIndex:skippingBrackets:ignoringQuotedStrings:)];

	// Walk through the string finding the character to split by, and add all ranges to the array.
	while (1) {
		nextIndex = (NSUInteger)(*firstOccOfChar)(self, @selector(firstOccurrenceOfCharacter:afterIndex:skippingBrackets:ignoringQuotedStrings:), character, stringIndex, NO, YES);
		while (lastMatchIsDelimiter && nextIndex != NSNotFound) {
			stringIndex = nextIndex;
			nextIndex = (NSUInteger)(*firstOccOfChar)(self, @selector(firstOccurrenceOfCharacter:afterIndex:skippingBrackets:ignoringQuotedStrings:), character, stringIndex, NO, YES);
		}
		if (nextIndex == NSNotFound)
			break;

		// Add ranges to the result array if they have a length
		stringIndex++;
		queryLength = nextIndex - stringIndex - delimiterLengthMinusOne;
		if (queryLength > 0)
			CFArrayAppendValue((CFMutableArrayRef)resultsArray, [NSValue valueWithRange:NSMakeRange(stringIndex, queryLength)]);

		stringIndex = nextIndex;
	}

	// Add the end of the string after the previously matched character where appropriate.
	stringIndex++;
	if ((NSUInteger)stringIndex < [string length]) {
		NSString *finalQuery = [[string substringFromIndex:stringIndex] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
		if (supportDelimiters && [finalQuery isMatchedByRegex:@"(?i)^\\s*delimiter\\s+\\S+"])
			finalQuery = nil;
		if ([finalQuery length])
			[resultsArray addObject:[NSValue valueWithRange:NSMakeRange(stringIndex, [string length] - stringIndex)]];
	}

	return resultsArray;
}

#pragma mark -
#pragma mark SQL-aware character lookups (mostly for internal use)

/**
 * A shortcut method for looking up the first occurrence of a character in
 * the string.  Brackets aren't processed, quoted strings are processed according
 * to the supplied argument, and comments are processed according to the setting on
 * the object.
 */
- (NSUInteger) firstOccurrenceOfCharacter:(unichar)character ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	return [self firstOccurrenceOfCharacter:character afterIndex:-1 skippingBrackets:NO ignoringQuotedStrings:ignoreQuotedStrings];
}

/**
 * A shortcut method for looking up the first occurrence of a character in
 * the string after a specified start index.  Brackets aren't processed, quoted
 * strings are processed according to the supplied argument, and comments are
 * processed according to the setting on the object.
 */
- (NSUInteger) firstOccurrenceOfCharacter:(unichar)character afterIndex:(NSInteger)startIndex ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	return [self firstOccurrenceOfCharacter:character afterIndex:startIndex skippingBrackets:NO ignoringQuotedStrings:ignoreQuotedStrings];
}

/**
 * Look for the first occurrence of a character, in SQL-aware form - with support
 * for skipping bracketed or quoted ranges.
 * Comments are also skipped depending on the setting for this object.
 * Mostly intended for internal use, but available externally.
 */
- (NSUInteger) firstOccurrenceOfCharacter:(unichar)character afterIndex:(NSInteger)startIndex skippingBrackets:(BOOL)skipBrackets ignoringQuotedStrings:(BOOL)ignoreQuotedStrings
{
	NSUInteger currentStringIndex, quotedStringEndIndex;
	unichar currentCharacter;
	NSUInteger stringLength = [string length];
	NSInteger bracketingLevel = 0;
	lastMatchIsDelimiter = NO;

	// Cache frequently used selectors, avoiding dynamic binding overhead
	IMP charAtIndex = [self methodForSelector:@selector(_charAtIndex:)];
	SEL charAtIndexSEL = @selector(_charAtIndex:);
	IMP endIndex = [self methodForSelector:@selector(endIndexOfStringQuotedByCharacter:startingAtIndex:)];
	IMP substringWithRange = [self methodForSelector:@selector(substringWithRange:)];

	// Sanity check inputs
	if (startIndex < -1) startIndex = -1;

	// Walk along the string, processing characters
	for (currentStringIndex = startIndex + 1; currentStringIndex < stringLength; currentStringIndex++) {
		currentCharacter = (unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex);

		// Check for the ending character, and if it has been found and quoting/brackets is valid, return.
		// If delimiter support is active and a delimiter is set, check for the delimiter
		if (supportDelimiters && delimiter) {
			if (currentStringIndex >= delimiterLengthMinusOne && [delimiter isEqualToString:(NSString *)(*substringWithRange)(self, @selector(substringWithRange:), NSMakeRange(currentStringIndex - delimiterLengthMinusOne, delimiterLengthMinusOne + 1))]) {
				if (!skipBrackets || bracketingLevel <= 0) {
					parsedToPosition = currentStringIndex;
					return currentStringIndex;
				}
			}
		} else if (currentCharacter == character) {
			if (!skipBrackets || bracketingLevel <= 0) {
				parsedToPosition = currentStringIndex;
				return currentStringIndex;
			}
		}

		// Process strings and comments as appropriate
		switch (currentCharacter) {

			// When quote characters are encountered and strings are not being ignored, walk to the end of the quoted string.
			case '\'':
			case '"':
			case '`':
				if (!ignoreQuotedStrings) break;
				quotedStringEndIndex = (NSUInteger)(*endIndex)(self, @selector(endIndexOfStringQuotedByCharacter:startingAtIndex:), currentCharacter, currentStringIndex+1);
				if (quotedStringEndIndex == NSNotFound) {
					parsedToPosition = stringLength - 1;
					return NSNotFound;
				}
				currentStringIndex = quotedStringEndIndex;
				break;

			// For opening brackets increment the bracket count
			case '(':
				bracketingLevel++;
				break;

			// For closing brackets decrement the bracket count
			case ')':
				bracketingLevel--;

			// For comments starting "--[\s]", ensure the start syntax is valid before proceeding.
			case '-':
				if (ignoreCommentStrings) break;
				if (stringLength < currentStringIndex + 2) break;
				if ((unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+1) != '-') break;
				if (![[NSCharacterSet whitespaceCharacterSet] characterIsMember:(unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+2)]) break;
				currentStringIndex = [self endIndexOfCommentOfType:SPDoubleDashComment startingAtIndex:currentStringIndex];
				break;

			case '#':
				if (ignoreCommentStrings) break;
				currentStringIndex = [self endIndexOfCommentOfType:SPHashComment startingAtIndex:currentStringIndex];
				break;

			// For comments starting "/*", ensure the start syntax is valid before proceeding.
			case '/':
				if (ignoreCommentStrings) break;
				if (stringLength < currentStringIndex + 1) break;
				if ((unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+1) != '*') break;
				currentStringIndex = [self endIndexOfCommentOfType:SPCStyleComment startingAtIndex:currentStringIndex];
				break;

			// Capture whether carriage returns are encountered
			case '\r':
				if (!containsCRs) containsCRs = YES;
				break;

			// Check for delimiter strings, by first checking letter-by-letter to "deli" for speed (as there's no default
			// commands which start with it), and then switching to regex for simplicty.
			case 'd':
			case 'D':

				// Only proceed if delimiter support is enabled and the remaining string is long enough,
				// and that the "d" is the start of a word
				if (supportDelimiters && stringLength >= currentStringIndex + 11
					&& (currentStringIndex == 0
						|| [[NSCharacterSet whitespaceAndNewlineCharacterSet] characterIsMember:(unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex-1)]))
				{
					switch((unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+1)) {
						case 'e':
						case 'E':
						switch((unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+2)) {
							case 'l':
							case 'L':
							switch((unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+3)) {
								case 'i':
								case 'I':
									if([self isMatchedByRegex:@"^(delimiter[ \\t]+(\\S+))(?=\\s|\\Z)"
													  options:RKLCaseless
													  inRange:NSMakeRange(currentStringIndex, stringLength - currentStringIndex)
														error:nil])
									{

										// Delimiter command found.  Extract the delimiter string itself
										NSArray *delimiterCommandParts = [[self arrayOfCaptureComponentsMatchedByRegex:@"(?i)^(delimiter[ \\t]+(\\S+))(?=\\s|\\Z)"
																			range:NSMakeRange(currentStringIndex, stringLength - currentStringIndex)] objectAtIndex:0];
										if (delimiter) [delimiter release];
										delimiter = [[NSString alloc] initWithString:[delimiterCommandParts objectAtIndex:2]];
										delimiterLengthMinusOne = [delimiter length] - 1;
										parsedToPosition = currentStringIndex + [(NSString*)[delimiterCommandParts objectAtIndex:1] length];

										// Drop back to standard non-delimiter mode if the delimiter has ended
										if ([delimiter isEqualToString:[NSString stringWithFormat:@"%C", character]]) {
											if (delimiter) [delimiter release];
											delimiter = nil;
											delimiterLengthMinusOne = 0;
										}

										// With the internal state updated, return the match, clearly marked as a delimiter
										lastMatchIsDelimiter = YES;
										return parsedToPosition;
									}
								default: break;
							}
							default: break;
						}
					default: break;
				}
			}
		}
	}

	// If no matches have been made in this string, return NSNotFound.
	parsedToPosition = stringLength - 1;
	return NSNotFound;
}

/**
 * Walk along the string and locate the end of a quoted string, taking
 * into account the various forms of SQL escaping.
 * A method intended for use by the functions above.
 */
- (NSUInteger) endIndexOfStringQuotedByCharacter:(unichar)quoteCharacter startingAtIndex:(NSInteger)startIndex
{
	NSInteger currentStringIndex, stringLength;
	NSUInteger i, quotedStringLength;
	BOOL characterIsEscaped;
	unichar currentCharacter;

	// Cache the charAtIndex selector, avoiding dynamic binding overhead
	IMP charAtIndex = [self methodForSelector:@selector(_charAtIndex:)];
	SEL charAtIndexSEL = @selector(_charAtIndex:);

	stringLength = [string length];

	// Walk the string looking for the string end
	for ( currentStringIndex = startIndex; currentStringIndex < stringLength; currentStringIndex++) {
		currentCharacter = (unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex);

		// If the string end is a backtick and one has been encountered, treat it as end of string
		if (quoteCharacter == '`' && currentCharacter == '`') {

			// ...as long as the next character isn't also a backtick, in which case it's being quoted.  Skip both.
			if ((currentStringIndex + 1) < stringLength && (unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+1) == '`') {
				currentStringIndex++;
				continue;
			}

			return currentStringIndex;

		// Otherwise, prepare to treat the string as ended when meeting the correct boundary character....
		} else if (currentCharacter == quoteCharacter) {

			// ...but only if the string end isn't escaped with an *odd* number of escaping characters...
			characterIsEscaped = NO;
			i = 1;
			quotedStringLength = currentStringIndex - 1;
			while ((quotedStringLength - i) > 0 && (unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex - i) == '\\') {
				characterIsEscaped = !characterIsEscaped;
				i++;
			}

			// If an even number have been found, it may be the end of the string - as long as the subsequent character
			// isn't also the same character, in which case it's another form of escaping.
			if (!characterIsEscaped) {
				if ((currentStringIndex + 1) < stringLength && (unichar)(long)(*charAtIndex)(self, charAtIndexSEL, currentStringIndex+1) == quoteCharacter) {
					currentStringIndex++;
					continue;
				}

				// Really is the end of the string.
				return currentStringIndex;
			}
		}
	}

	return NSNotFound;
}

/**
 * A method intended for use by the functions above.
 */
- (NSUInteger) endIndexOfCommentOfType:(SPCommentType)commentType startingAtIndex:(NSInteger)anIndex
{
	NSInteger stringLength = [string length];
	unichar currentCharacter;

	// Cache the charAtIndex selector, avoiding dynamic binding overhead
	IMP charAtIndex = [self methodForSelector:@selector(_charAtIndex:)];
	SEL charAtIndexSEL = @selector(_charAtIndex:);

	switch (commentType) {

		// For comments of type "--[\s]", start the comment processing two characters in to match the start syntax,
		// then flow into the Hash comment handling (looking for first newline).
		case SPDoubleDashComment:
			anIndex = anIndex+2;

		// For comments starting "--[\s]" and "#", continue until the first newline.
		case SPHashComment:
			anIndex++;
			for ( ; anIndex < stringLength; anIndex++ ) {
				currentCharacter = (unichar)(long)(*charAtIndex)(self, charAtIndexSEL, anIndex);
				if (currentCharacter == '\r') containsCRs = YES;
				if (currentCharacter == '\r' || currentCharacter == '\n') {
					return anIndex-1;
				}
			}
			break;

		// For comments starting "/*", start the comment processing one character in to match the start syntax, then
		// continue until the first matching "*/".
		case SPCStyleComment:
			anIndex = anIndex+2;
			for ( ; anIndex < stringLength; anIndex++ ) {
				if ((unichar)(long)(*charAtIndex)(self, charAtIndexSEL, anIndex) == '*') {
					if ((stringLength > anIndex + 1) && (unichar)(long)(*charAtIndex)(self, charAtIndexSEL, anIndex+1) == '/') {
						return (anIndex+1);
					}
				}
			}
	}

	// If no match has been found, the comment must continue until the very end of the string.
	return (stringLength-1);
}

#pragma mark -
#pragma mark Required and primitive methods to allow subclassing the class cluster

- (id) init {

	if ((self = [super init])) {
		string = [[NSMutableString string] retain];
	}
	[self initSQLExtensions];
	return self;
}
- (id) initWithBytes:(const void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding {
	if ((self = [super init])) {
		string = [[NSMutableString alloc] initWithBytes:bytes length:length encoding:encoding];
	}
	[self initSQLExtensions];
	return self;
}
- (id) initWithBytesNoCopy:(void *)bytes length:(NSUInteger)length encoding:(NSStringEncoding)encoding freeWhenDone:(BOOL)flag {
	if ((self = [super init])) {
		string = [[NSMutableString alloc] initWithBytesNoCopy:bytes length:length encoding:encoding freeWhenDone:flag];
	}
	[self initSQLExtensions];
	return self;
}
- (id) initWithCapacity:(NSUInteger)capacity {
	if ((self = [super init])) {
		string = [[NSMutableString stringWithCapacity:capacity] retain];
	}
	[self initSQLExtensions];
	return self;
}
- (id) initWithCharactersNoCopy:(unichar *)characters length:(NSUInteger)length freeWhenDone:(BOOL)flag {
	if ((self = [super init])) {
		string = [[NSMutableString alloc] initWithCharactersNoCopy:characters length:length freeWhenDone:flag];
	}
	[self initSQLExtensions];
	return self;
}
- (id) initWithContentsOfFile:(id)path {
	return [self initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
}
- (id) initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)encoding error:(NSError **)error {
	if ((self = [super init])) {
		string = [[NSMutableString alloc] initWithContentsOfFile:path encoding:encoding error:error];
	}
	[self initSQLExtensions];
	return self;
}
- (id) initWithCString:(const char *)nullTerminatedCString encoding:(NSStringEncoding)encoding {
	if ((self = [super init])) {
		string = [[NSMutableString alloc] initWithCString:nullTerminatedCString encoding:encoding];
	}
	[self initSQLExtensions];
	return self;
}
- (id) initWithFormat:(NSString *)format, ... {
	va_list argList;
	va_start(argList, format);
	id str = [self initWithFormat:format arguments:argList];
	va_end(argList);
	[self initSQLExtensions];
	return str;
}
- (id) initWithFormat:(NSString *)format arguments:(va_list)argList {
	if ((self = [super init])) {
		string = [[NSMutableString alloc] initWithFormat:format arguments:argList];
	}
	[self initSQLExtensions];
	return self;
}
- (void) initSQLExtensions {
	parsedToChar = '\0';
	parsedToPosition = -1;
	charCacheEnd = -1;
	ignoreCommentStrings = NO;
	supportDelimiters = NO;
	delimiter = nil;
	delimiterLengthMinusOne = 0;
	lastMatchIsDelimiter = NO;
	containsCRs = NO;
}
- (NSUInteger) length {
	return [string length];
}
- (unichar) characterAtIndex:(NSUInteger)anIndex {
	return CFStringGetCharacterAtIndex((CFStringRef)string, anIndex);
}
- (id) description {
	return [string description];
}
- (NSUInteger) replaceOccurrencesOfString:(NSString *)target withString:(NSString *)replacement options:(NSUInteger)options range:(NSRange)searchRange {
	return [string replaceOccurrencesOfString:target withString:replacement options:options range:searchRange];
	[self _clearCharCache];
}
- (void) setString:(NSString *)aString {
	[string setString:aString];
	if (delimiter) [delimiter release], delimiter = nil;
	delimiterLengthMinusOne = 0;
	lastMatchIsDelimiter = NO;
	[self _clearCharCache];
}
- (void) replaceCharactersInRange:(NSRange)range withString:(NSString *)aString {
	[string replaceCharactersInRange:range withString:aString];
	[self _clearCharCache];
}
- (void) deleteCharactersInRange:(NSRange)aRange {
	[super deleteCharactersInRange:aRange];
	[self _clearCharCache];
}
- (void) insertString:(NSString *)aString atIndex:(NSUInteger)anIndex {
	[super insertString:aString atIndex:anIndex];
	[self _clearCharCache];
}
- (void) dealloc {
	[string release];
	if (delimiter) [delimiter release];
	if (charCacheEnd != -1) free(stringCharCache);
	[super dealloc];
}

@end

#pragma mark -

@implementation SPSQLParser (PrivateAPI)

/**
 * Provide a method to retrieve a character from the local cache.
 * Does no bounds checking on the underlying string, and so is kept
 * separate from characterAtIndex:.
 */
- (unichar) _charAtIndex:(NSInteger)anIndex
{

	// If the current cache doesn't include the current character, update it.
	if (anIndex > charCacheEnd || anIndex < charCacheStart) {
		if (charCacheEnd > -1) {
			free(stringCharCache);
		}
		NSUInteger remainingStringLength = [string length] - anIndex;
		NSUInteger newcachelength = (CHARACTER_CACHE_LENGTH < remainingStringLength)?CHARACTER_CACHE_LENGTH:remainingStringLength;
		stringCharCache = (unichar *)calloc(newcachelength, sizeof(unichar));
		CFStringGetCharacters((CFStringRef)string, CFRangeMake(anIndex, newcachelength), stringCharCache);
		charCacheEnd = anIndex + newcachelength - 1;
		charCacheStart = anIndex;
	}
	return stringCharCache[anIndex - charCacheStart];
}

/**
 * Provide a method to clear the cache, which should be used whenever
 * the underlying string is updated.
 */
- (void) _clearCharCache
{
	if (charCacheEnd > -1) {
		free(stringCharCache);
	}
	charCacheEnd = -1;
	charCacheStart = 0;
	parsedToChar = '\0';
	parsedToPosition = -1;
}

@end


text:
=====================
CodeCoverageExtension
=====================

The Code Coverage extension allows you to collect local and/or remote code
coverage.

Use this extension to find dead code in your application, or unused/obsolete
contexts or step definitions.

Installation
============
This extension requires:

* Behat 2.4+
* Mink 1.4+

Through Composer
----------------
1. Set dependencies in your **composer.json**:

.. code-block:: js

    {
        "require": {
            ...
            "vipsoft/code-coverage-extension": "*"
        }
    }

2. Install/update your vendors:

.. code-block:: bash

    $ curl http://getcomposer.org/installer | php
    $ php composer.phar install

Through PHAR
------------
Download the .phar archive:

* `code_coverage_extension.phar <http://behat.org/downloads/code_coverage_extension.phar>`_

Configuration
=============
Activate extension in your **behat.yml** and define your routes for remote code coverage collection (relative to Mink's base URL):

.. code-block:: yaml

    # behat.yml
    default:
      # ...
      extensions:
        VIPSoft\CodeCoverageExtension\Extension:
          auth:       ~
          create:
            method:   POST
            path:     /
          read:
            method:   GET
            path:     /
          delete:
            method:   DELETE
            path:     /
          drivers:
            - remote
            - local
          filter:     ~
          report:
            format:   html
            options:
              target: /tmp/report

Settings
--------
If HTTP Authentication is required, use:

.. code-block:: yaml

    # behat.yml
    default:
      # ...
      extensions:
        VIPSoft\CodeCoverageExtension\Extension:
          auth:
            user:     your_user
            password: your_password
          ...

There are two code coverage driver services.  The "local" driver will
collect code coverage from the PHP instance running Behat.  The "remote"
driver will collect code coverage for the Symfony 2 application under test
on a remote web server.

The report "directory" determines where the extension will write the code
coverage report.

Other choices for report "format" include "clover", "crap4j", "php", "text",
and "xml".  The "options" vary and correspond to the __construct() and process()
arguments of the underlying PHP_CodeCoverage report class.

The default "filter" includes everything / excludes nothing.  Using a
PHPUnit configuration as an example:

.. code-block:: xml

    <filter>
        <whitelist addUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">src</directory>
            <exclude>
                <directory>src/*/*/Tests</directory>
            </exclude>
        </whitelist>
    </filter>

would be configured in YAML as:

.. code-block:: yaml

    filter:
        whitelist:
          addUncoveredFilesFromWhitelist: true
          include:
            directories:
              'src':
                suffix: .php
          exclude:
            directories:
              'src/*/*/Tests': ~

Limitations
-----------
Multiple web servers (e.g., clusters or distributed testing environments) are not
currently supported because the Code Coverage Bundle uses a SQLite database.

Source
======
`Github <https://github.com/vipsoft/code-coverage-extension>`_

Copyright
=========
Copyright (c) 2013 Anthon Pang.  See **LICENSE** for details.

Contributors
============
* Anthon Pang `(robocoder) <http://github.com/robocoder>`_
* `Others <https://github.com/vipsoft/code-coverage-extension/graphs/contributors>`_


text:
;(function() {
    var Keyboard = {};
    if (typeof define === "function" && define.amd) {
        define('GKeyboard', ['require', 'jquery'], function(require) {
            factory(require('jquery'));
            return Keyboard;
        });
    } else if (typeof module === "object" && typeof module.exports === "object") {
        factory(require('jquery'));
        module.exports = Keyboard;
    } else {
        factory(window.jQuery);
    }

    function factory($, G) {
        var keyboardList = [];
        Keyboard = function(el, opt) {
            opt = opt ? opt : {};
            this.el = el;
            this.config = $.extend({}, {
                numbers: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
                random: false,
                titleDisplay: 'none',
                btnClose: '关闭',
                btnBack: '后退',
                output: function(num) {
                    console.log(num);
                    return false;
                },
                back: function() {
                    console.log('back');
                    return false;
                },
                onClose: function() {
                    return false;
                },
                onOpen: function() {
                    return false;
                }
            }, opt);
            $(el).addClass('g-keyboard-outer');
            this.init(el, this.config);
            keyboardList.push(this);
            return this;
        };
        Keyboard.prototype = {
            _event: function() {
                var self = this;
                $(self.el).on('click', '.g-keyboard-num', function() {
                    var num = $(this).attr('data-num');
                    if (num) {
                        self.config.output(num);
                    } else if ($(this).hasClass('g-keyboard-back')) {
                        self.config.back();
                    } else if ($(this).hasClass('g-keyboard-close')) {
                        self.close();
                    }
                    return false;
                });
                $(window).on('resize', function(){
                    self.rePos();
                });
            },
            init: function() {
                var resultStr = '';
                resultStr += '
';
                resultStr += '
';
                resultStr += '
';
                resultStr += this.config.title;
                resultStr += '
';
                resultStr += '
';
                resultStr += this._renderKeyboard();
                resultStr += '
';
                resultStr += '
';
                resultStr += '
';
                $(this.el).html(resultStr);
                this._event();
            },
            _renderKeyboard: function() {
                var numbers = [];
                if (this.config.random) {
                    numbers = this.reSort(this.config.numbers);
                } else {
                    numbers = this.config.numbers;
                }
                var numbersStr = '';
                for (var i = 0; i < numbers.length; i++) {
                    if (i < numbers.length - 1) {
                        numbersStr += '' + numbers[i] + '';
                    } else {
                        numbersStr += '' + numbers[i] + '';
                    }
                }
                numbersStr += '' + this.config.btnClose + '';
                numbersStr += '' + this.config.btnBack + '';
                numbersStr += '';
                return numbersStr;
            },
            reSort: function(arr){
                var randomSort = function(a, b) {
                    return Math.random() > 0.79 ? -1 : 1;
                }
                var finalArr = arr.sort(randomSort);
                return finalArr;
            },
            rePos: function(){
                var keyboardHeight = $(this.el).find('.g-keyboard').outerHeight();
                $(this.el).css('paddingBottom',keyboardHeight+'px');
            },
            open: function() {
                $(this.el).show();
                this.rePos();
                this.config.onOpen();
            },
            close: function() {
                $(this.el).hide();
                $(this.el).css('paddingBottom','0');
                this.config.onClose();
            }
        }
        window.GKeyboard = Keyboard;
    };
})();


text:
"""
Actual simualtion happens here. It uses data from conf.py for simualation parameters.
"""
# Copyright (c) 2014, Pavlo Bazilinskyy <pavlo.bazilinskyy@gmail.com>
# Department of Computer Science, National University of Ireland, Maynooth
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
__author__ = "Pavlo Bazilinskyy"
__copyright__ = "Copyright 2008, National University of Ireland, Maynooth"
__credits__ = "Ronan Reilly"
__version__ = "1.0"
__maintainer__ = "Pavlo Bazilinskyy"
__email__ = "pavlo.bazilinskyy@gmail.com"
__status__ = "Production"

import conf
import model
import random
from UniData import UniData
import random
import copy
from math import ceil

# Populate list of student in current intake
# Load data from Excel and csv files
intake = {} 		# Summer intake
intakeAutumn = {} 	# Autumn intake
modules = {}		# All modules, sorted by ID
courses = []		# List of all courses

# Record initial state, with no changes
initial_intake = {} 		# Summer intake
initial_intakeAutumn = {} 	# Autumn intake
initial_modules = {}		# All modules, sorted by ID
initial_courses = []		# List of all courses

# Record statistics of students passing/failing based on their school leaving certificates
lcPassed = {}
lcFailed = {}
# Also record passed/failed ratios for individual faculties
# ARTS,CELT.STUD. AND PHILOSOPHY
lcPassedArts = {}
lcFailedArts = {}
# SOCIAL SCIENCES
lcPassedSocial = {}
lcFailedSocial = {}
# SCIENCE AND ENGINEERING
lcPassedScience = {}
lcFailedScience = {}

# Algorithm by Pavlo Bazilinskyy
def simulate():
	# Reset data
	intake = copy.deepcopy(initial_intake)
	intakeAutumn = copy.deepcopy(initial_intakeAutumn)
	modules = copy.deepcopy(initial_modules)
	courses = copy.deepcopy(initial_courses)
	lcPassed.clear()
	lcFailed.clear()
	lcPassedArts.clear()
	lcFailedArts.clear()
	lcPassedSocial.clear()
	lcFailedSocial.clear()
	lcPassedScience.clear()
	lcFailedScience.clear()

	# Variables for calculating
	studentsPassed = 0
	studentsFailed = 0
	studentsDidNotComplete = 0
	studentsExcempt = 0
	studentsAbsent = 0
	studentsSatisfactory = 0
	studentsPassedByCompensation = 0
	studentsPassedByTransferCredits = 0
	studentsPassedByAutoRepeats = 0
	totalAverageMark = 0.0

	# For calculation of the average leaving certificate
	averageLeavingCert = 0.0

	# Sanity check for a number of failed students
	tempFailedCounter = 0
	for student in intake.keys(): # Iterate through all students
		for moduleEnr in intake[student].moduleEnrollments:
			if (intake[student].moduleEnrollments[moduleEnr].status == "PASS BY COMPENSATION" or
			intake[student].moduleEnrollments[moduleEnr].status == "FAIL" or
			intake[student].moduleEnrollments[moduleEnr].status == "ABSENT" or
			intake[student].moduleEnrollments[moduleEnr].status == "DID NOT COMPLETE"):

				tempFailedCounter += 1
				break
	if conf.DETAILED_DEBUG:
		print "SUMMER INTAKE: ", len(intake)
		print "FAILED before adjustments: ", tempFailedCounter

	for student in intake.keys(): # Iterate through all students

		# Define variables to calculate results in modules
		passedModules = 0
		failedModules = 0
		failedModulesList = []
		absentModules = 0
		passByCompensationModules = 0
		excemptionModules = 0
		satisfactoryModules = 0
		didNotCompleteModules = 0

		## Now loop through modules of the student
		for moduleEnr in intake[student].moduleEnrollments:
			moduleEnr = intake[student].moduleEnrollments[moduleEnr]

			## Intelligent agent behaviour
			# Add marks based on the leaving school certificate mark, based on probability of exhibiting intellgent behaviour INTELLENT_AGENT_CHANGE
			if (conf.INTELLIGENT_AGENTS and random.random() <= conf.INTELLENT_AGENT_CHANCE and
				intake[student].leavingCertificate >= conf.INTELLENT_AGENT_LC_THRESHOLD and not
				moduleEnr.marksReceived == 0):

				grade = moduleEnr.marksReceived
				#print "grade: ", grade, " plus: ", float(conf.INTELLENT_AGENT_COEF) / 1000 * intake[student].leavingCertificate
				grade += float(conf.INTELLENT_AGENT_COEF) / 1000 * intake[student].leavingCertificate
				moduleEnr.marksReceived = grade
				if moduleEnr.marksReceived > 100:
					moduleEnr.marksReceived = 100

				# Calcualate total average grade
				tempAverageGrade = 0.0
				for tempModuleEnr in intake[student].moduleEnrollments:
					tempAverageGrade += moduleEnr.marksReceived
				tempAverageGrade /= len(intake[student].moduleEnrollments)

				# # Check if it makes a failed module passed
				# if (moduleEnr.status == "FAIL" and moduleEnr.marksReceived >= conf.PASSING_THRESHOLD):
				# 	moduleEnr.status = "PASS"
				# # Check if it makes a failed module passed by compensation
				# elif (moduleEnr.status == "FAIL" and
				# 	moduleEnr.marksReceived >= conf.COMPENSATION_LEVEL and
				# 	tempAverageGrade >= conf.COMPENSATION_THREASHOLD and
				# 	conf.PASS_BY_COMPENSATION == True):

				# 	moduleEnr.status = "PASS BY COMPENSATION"
				# # Check if it makes a passed by compensation module passed
				# elif moduleEnr.status == "PASS BY COMPENSATION" and moduleEnr.marksReceived >= conf.PASSING_THRESHOLD:
				# 	moduleEnr.status = "PASS"
				# # Check if a student was absent on the exam
				if ((moduleEnr.status == "ABSENT" or moduleEnr.status == "DID NOT COMPLETE") and conf.INTELLENT_AGENT_ABSENT_MODULE):

					# If average grade > conf.INTELLENT_AGENT_ABSENT_MODULE_THRESHOLD, there is "conf.INTELLENT_AGENT_CHANGE / 2" chance the student passed this module with a grade equal to his average grade
					if tempAverageGrade >= conf.INTELLENT_AGENT_ABSENT_MODULE_THRESHOLD and random.random() <= conf.INTELLENT_AGENT_CHANCE / 2:
						moduleEnr.status = "PASS"
						moduleEnr.marksReceived = int(tempAverageGrade)

			## Normalise some values of received marks as they seem to be wrong in Excel sheets
			# Check if it is actually a pass based on received marks
			if conf.NORMALISE_VALUES:
				if moduleEnr.status == "PASS BY COMPENSATION":
					if (moduleEnr.marksReceived < conf.COMPENSATION_LEVEL):
						moduleEnr.marksReceived = conf.PASSING_THRESHOLD - 1
				elif moduleEnr.status == "PASS":
					if (moduleEnr.marksReceived < conf.PASSING_THRESHOLD):
						moduleEnr.marksReceived = conf.PASSING_THRESHOLD
				elif moduleEnr.status == "FAIL":
					if (moduleEnr.marksReceived == 0):
						moduleEnr.marksReceived = int(conf.PASSING_THRESHOLD / 2) # Many rows have mark == 0 in the table
					elif (moduleEnr.marksReceived > conf.PASSING_THRESHOLD):
						moduleEnr.marksReceived = conf.PASSING_THRESHOLD - 1
				# elif moduleEnr.status == "DID NOT COMPLETE": # Artificially, bring the average grade up
				# 	if (moduleEnr.marksReceived < conf.COMPENSATION_LEVEL):
				# 		moduleEnr.marksReceived = conf.PASSING_THRESHOLD - 1

		# Calculate average grade
		averageGrade = 0.0
		for moduleEnr in intake[student].moduleEnrollments:
			# Average grade calculation
			averageGrade += intake[student].moduleEnrollments[moduleEnr].marksReceived
		averageGrade /= len(intake[student].moduleEnrollments)
		totalAverageMark += averageGrade # Calculating average grade among all students

		# Calculating average leaving certificate
		averageLeavingCert += intake[student].leavingCertificate

		if conf.DETAILED_DEBUG:
			print "\nStudent ID: ", intake[student].studentID, " Average grade: ", averageGrade

		##### MAIN ALGORITHM Iterate through all modeules that were taken by the student
		for moduleEnr in intake[student].moduleEnrollments:
			moduleEnr = intake[student].moduleEnrollments[moduleEnr]

			if conf.DETAILED_DEBUG:
				print "MODULE ID: ", moduleEnr.module.moduleID, " MARK: ", moduleEnr.marksReceived, " STATUS: ", moduleEnr.status, " CREDIT: ", moduleEnr.module.moduleCredit

			## Adjust what was assigned to modules, based on the configuration
			if moduleEnr.status == "PASS BY COMPENSATION":
				if (averageGrade < conf.COMPENSATION_THREASHOLD or
				moduleEnr.marksReceived < conf.COMPENSATION_LEVEL or
				conf.PASS_BY_COMPENSATION == False):
				# Could be two possibilities
					if moduleEnr.marksReceived < conf.PASSING_THRESHOLD: # Check if received grade is less than passing threshold
						moduleEnr.status = "FAIL"
					else:
						moduleEnr.status = "PASS"

			elif moduleEnr.status == "PASS":
				if (moduleEnr.marksReceived >= conf.COMPENSATION_LEVEL and
				averageGrade >= conf.COMPENSATION_THREASHOLD and
				moduleEnr.marksReceived < conf.PASSING_THRESHOLD and
				conf.PASS_BY_COMPENSATION == True):
					moduleEnr.status = "PASS BY COMPENSATION"

				elif moduleEnr.marksReceived < conf.PASSING_THRESHOLD: # Check if received grade is less than passing threshold
					moduleEnr.status = "FAIL"

			elif moduleEnr.status == "FAIL":
				if (moduleEnr.marksReceived >= conf.COMPENSATION_LEVEL and
				averageGrade >= conf.COMPENSATION_THREASHOLD and
				moduleEnr.marksReceived < conf.PASSING_THRESHOLD and
				conf.PASS_BY_COMPENSATION == True):
					moduleEnr.status = "PASS BY COMPENSATION"

				elif moduleEnr.marksReceived < conf.PASSING_THRESHOLD: # Check if received grade is less than passing threshold
					moduleEnr.status = "FAIL"

			#First check if pass by compesation still holds
			if (moduleEnr.status == "PASS BY COMPENSATION"):
				passByCompensationModules += 1
			elif (moduleEnr.status == "PASS"):
				passedModules += 1
			elif (moduleEnr.status == "FAIL"):
				failedModules += 1
				failedModulesList.append(moduleEnr)
			elif (moduleEnr.status == "ABSENT"):
				absentModules += 1
				failedModules += 1
				failedModulesList.append(moduleEnr)
			elif (moduleEnr.status == "DID NOT COMPLETE"): # Treat it as a fail
				didNotCompleteModules += 1
				failedModules += 1
				failedModulesList.append(moduleEnr)
			elif (moduleEnr.status == "EXEMPTION"): # Treat it as a fail
				passedModules += 1
			elif (moduleEnr.status == "SATISFACTORY"):
				#satisfactoryModules += 1
				passedModules += 1

		# Record if the student was absent / did not complete a module etc.
		if absentModules > 0:
			studentsAbsent += 1
		if didNotCompleteModules > 0:
			studentsDidNotComplete += 1

		# Found failed modules, and autumn repeats are possible
		if (failedModules > 0 and conf.AUTUMN_REPEATS == True and conf.TRANSFER_OF_CREDITS == False
			and conf.PASS_BY_COMPENSATION == False):
			# Check if a student failed fewer or equal number of modules that can be repeated in autumn
			failedCredits = 0
			for fMod in failedModulesList:
				try:
					failedCredits += int(fMod.module.moduleCredit)
				except:
					failedCredits += 5 # Give 5 credits by default, if information is missing

			if conf.DETAILED_DEBUG:
				print "AUTUMN failedModulesList: ", len(failedModulesList), " failed credits: ", failedCredits
			# Check if the student does not have too many failed credits
			if failedCredits <= conf.AUTUMN_REPEATS_LIMIT:
				# Find this student in autumn intake
				if (intake[student].studentID in intakeAutumn.keys()):
					for moduleEnr in intake[student].moduleEnrollments:
						moduleEnr = intake[student].moduleEnrollments[moduleEnr]
						# Iterate through failed modules
						if (moduleEnr.module.moduleID in intakeAutumn[intake[student].studentID].moduleEnrollments.keys()):
							# Check new status of the module after it was retaken
							modEnrAutumn = intakeAutumn[intake[student].studentID].moduleEnrollments[moduleEnr.module.moduleID]
							if (modEnrAutumn.status == "PASS"):
								failedModules -= 1

							# elif (intakeAutumn[intake[student].studentID].moduleEnrollments[moduleEnr.module.moduleID] == "FAIL"):
							# 	failedModules += 1
							# 	failedModulesList.append(moduleEnr)
							# elif (intakeAutumn[intake[student].studentID].moduleEnrollments[moduleEnr.module.moduleID] == "ABSENT"):
							# 	absentModules += 1
							elif (modEnrAutumn.status == "PASS BY COMPENSATION"):
									# Check if pass by compensation holds, if not mark this module as failed
									if (averageGrade >= conf.COMPENSATION_THREASHOLD and modEnrAutumn.marksReceived >= conf.COMPENSATION_LEVEL):
										failedModules -= 1
							elif (modEnrAutumn.status == "DID NOT COMPLETE"):
								didNotCompleteModules += 1
								failedModules -= 1
							elif (modEnrAutumn.status == "EXEMPTION"):
								excemptionModules += 1
								failedModules -= 1
							# Treat Satisfactory as Passed
							elif (modEnrAutumn.status == "SATISFACTORY"):
								#satisfactoryModules += 1
								failedModules -= 1

							if conf.DETAILED_DEBUG:
								print "AUTUMN MODULE ID: ", modEnrAutumn.module.moduleID, " MARK: ", modEnrAutumn.marksReceived, " STATUS: ", modEnrAutumn.status, " CREDIT: ", modEnrAutumn.module.moduleCredit

					# Check if students managed to pass all modules by auto repeats
					if (failedModules == 0):
						if conf.DETAILED_DEBUG:
							print "1 passed with autumn repeats"
						studentsPassedByAutoRepeats += 1
						studentsPassed += 1
						intake[student].resultFromSimluation = True
						addLcPassed(intake[student])
						continue

			# Student did not pass failed modules
			if conf.DETAILED_DEBUG:
				print "2 failed modules: ", failedModules
				for fMod in failedModulesList:
					print fMod.status, " ", fMod.module.moduleID
			studentsFailed += 1
			intake[student].resultFromSimluation = False
			addLcFailed(intake[student])
			continue

		# Pass by compensation modules found, but it was used for more than two modules
		if (passByCompensationModules > 2 and conf.PASS_BY_COMPENSATION == True):
			studentsFailed += 1
			intake[student].resultFromSimluation = False
			addLcFailed(intake[student])
			continue
		# Found failed modules, transer of credits is allowed
		elif (failedModules > 0 and conf.TRANSFER_OF_CREDITS == True and conf.AUTUMN_REPEATS == False and conf.PASS_BY_COMPENSATION == False):
			# Calculate how many modules were failed and compare that number
			# to the number of modules that can be transfered to the next year
			if (failedModules > conf.TRANSFER_OF_CREDITS_MODULES):
				if conf.DETAILED_DEBUG:
					print "7 transfer of credits, failed modules: ", failedModules
					for fMod in failedModulesList:
						print fMod.status, " ", fMod.module.moduleID
				studentsFailed += 1
				intake[student].resultFromSimluation = False
				addLcFailed(intake[student])
				continue
			else:
				if conf.DETAILED_DEBUG:
					print "8 passed with transfer of credits."
				studentsPassedByTransferCredits += 1
				studentsPassed += 1
				intake[student].resultFromSimluation = True
				addLcPassed(intake[student])
				continue
		# Student can pass by compensation
		elif (passByCompensationModules <= 2 and passByCompensationModules > 0 and conf.PASS_BY_COMPENSATION == True):
			# for moduleEnr in intake[student].moduleEnrollments:
			# 	if (intake[student].moduleEnrollments[moduleEnr].status == "PASS BY COMPENSATION"):
			# 		print intake[student].moduleEnrollments[moduleEnr].marksReceived
			if conf.DETAILED_DEBUG:
				print "10 passed by compensation. Modules passed by compensation: ", passByCompensationModules
			studentsPassedByCompensation += 1
			studentsPassed += 1
			intake[student].resultFromSimluation = True
			addLcPassed(intake[student])
			continue

		# Student has absent modules, and auto repeats, transfer of credits and pass by compensation are disabled
		elif (absentModules > 0):
			if conf.DETAILED_DEBUG:
				print "6 absent: ", absentModules
			studentsFailed += 1
			intake[student].resultFromSimluation = False
			addLcFailed(intake[student])
			continue
		# Student did not complete modules
		elif (didNotCompleteModules > conf.DID_NOT_COMPLETE_MODULES and didNotCompleteModules > 0):
			if conf.DETAILED_DEBUG:
				print "9 did not complete: ", didNotCompleteModules
			studentsFailed += 1
			intake[student].resultFromSimluation = False
			addLcFailed(intake[student])
			continue
				# Students still has failed modules -> fail
		elif (failedModules > 0):
			if conf.DETAILED_DEBUG:
				print "11 failed: ", failedModules
				for fMod in failedModulesList:
					print fMod.status, " ", fMod.module.moduleID
			studentsFailed += 1
			intake[student].resultFromSimluation = False
			addLcFailed(intake[student])
			continue

		# Everything is fine and this student can go to the next year
		studentsPassed += 1
		intake[student].resultFromSimluation = True
		addLcPassed(intake[student])
		if conf.DETAILED_DEBUG:
				print "12 passed"

	totalAverageMark /= len(intake) # Calculate average grade
	averageLeavingCert /= len(intake) # Calcualte average leaving certificate

	if conf.DEBUG:
		print "Simulation finished."

		print 'Results:'
		print 'Students passed: ', str(studentsPassed)
		print 'Students failed: ', str(studentsFailed)
		print 'Students passed by compensation: ', str(studentsPassedByCompensation)
		print 'Students passed by transfer of credits: ', str(studentsPassedByTransferCredits)
		print 'Students passed by auto repeats: ', str(studentsPassedByAutoRepeats)
		print 'Average grade: ', str(totalAverageMark)
		print 'Average leaving certificate: ', str(averageLeavingCert)

	update = {}
	update["studentsPassedValue"] = str(studentsPassed)
	update["studentsFailedValue"] = str(studentsFailed)
	update["studentsAbsentValue"] = str(studentsAbsent)
	update["studentsDidNotCompleteValue"] = str(studentsDidNotComplete)
	update["studentsExcemptValue"] = str(studentsExcempt)
	update["studentsSatisfactoryValue"] = str(studentsSatisfactory)
	update["studentsPassedByCompensationValue"] = str(studentsPassedByCompensation)
	update["studentsPassedByTransferOfCreditsValue"] = str(studentsPassedByTransferCredits)
	update["studentsPassedByAutoRepeatsValue"] = str(studentsPassedByAutoRepeats)
	update["averageGradeValue"] = str(totalAverageMark)
	update["averageLeavingCertificateValue"] = str(averageLeavingCert)

	# update["modulesPassedValue"] = str(passedModules)
	# update["modulesFailedValue"] = str(failedModulesd)
	# update["modulesPassedByCompensationValue"] = str(modulesPass)
	# update["modulesAbsentValue"] = str(studentsPassed)
	# update["modulesPassedByAutoRepeatsValue"] = str(studentsPassed)

	if conf.DEBUG:
		print update

	return update

# Record in the dictionary of numbers of students who failed sorted by leaving certificate points
def addLcFailed(student):
	try:
		lcFailed[roundup(student.leavingCertificate)] += 1
	except KeyError, e:
		lcFailed[roundup(student.leavingCertificate)] = 1

		# Also add to the list of the faculty
	if (student.faculty == "ARTS,CELT.STUD. AND PHILOSOPHY"):
		try:
			lcFailedArts[roundup(student.leavingCertificate)] += 1
		except KeyError, e:
			lcFailedArts[roundup(student.leavingCertificate)] = 1
	if (student.faculty == "SOCIAL SCIENCES"):
		try:
			lcFailedSocial[roundup(student.leavingCertificate)] += 1
		except KeyError, e:
			lcFailedSocial[roundup(student.leavingCertificate)] = 1
	if (student.faculty == "SCIENCE AND ENGINEERING"):
		try:
			lcFailedScience[roundup(student.leavingCertificate)] += 1
		except KeyError, e:
			lcFailedScience[roundup(student.leavingCertificate)] = 1

# Record in the dictionary of numbers of students who passed sorted by leaving certificate points
def addLcPassed(student):
	try:
		lcPassed[roundup(student.leavingCertificate)] += 1
	except KeyError, e:
		lcPassed[roundup(student.leavingCertificate)] = 1

	# Also add to the list of the faculty
	if (student.faculty == "ARTS,CELT.STUD. AND PHILOSOPHY"):
		try:
			lcPassedArts[roundup(student.leavingCertificate)] += 1
		except KeyError, e:
			lcPassedArts[roundup(student.leavingCertificate)] = 1
	if (student.faculty == "SOCIAL SCIENCES"):
		try:
			lcPassedSocial[roundup(student.leavingCertificate)] += 1
		except KeyError, e:
			lcPassedSocial[roundup(student.leavingCertificate)] = 1
	if (student.faculty == "SCIENCE AND ENGINEERING"):
		try:
			lcPassedScience[roundup(student.leavingCertificate)] += 1
		except KeyError, e:
			lcPassedScience[roundup(student.leavingCertificate)] = 1

# Round integer, used for smoothing graphs
def roundup(x):
	return int(ceil(x / float(conf.GRAPH_ROUND)) * conf.GRAPH_ROUND)

# Algorithm by Ronan Reilly and Pavlo Bazilinskyy
def simulate_old(compensationLevel, compensationThreashold, autoRepeats, transferOfCredits):
	#createIntake()
	semester = 1

	# Assume a four year course with two semesters per year
	while (semester <= 8):

		for student in intake:
			# intake
			if (semester == 1):
				course = random.choice(courses)
				course.addStudent(intake[student])
				modules = course.getModules()

				for module in modules:
					if (intake[student].canTake(module) and module.getSemesterGiven() == intake[student].getSemester()):
						module.addStudent(intake[student])

			# progress
			modulesTaken = intake[student].moduleEnrollments
			for module in modulesTaken:
				result = modulesTaken[module].marksReceived
				if (result >= 40):
					intake[student].points += modulesTaken[module].module.getModuleCredit()
					intake[student].marks += result * modulesTaken[module].module.getModuleCredit() / course.getCourseCredit()
				intake[student].semester += 1
		semester += 1

	if conf.DEBUG:
		print "Simulation finished."

	return "SIMULATION FINISHED."


text:
FROM node:6.7-slim

MAINTAINER Vladimir Posvistelik <v.posvistelik@gmail.com>

ARG APT_PROXY
RUN if [ "$APT_PROXY" ]; then echo "Acquire::http { Proxy \"$APT_PROXY\"; };" > /etc/apt/apt.conf.d/01proxy; fi

# install gosu:
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates wget \
    && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/1.9/gosu-$(dpkg --print-architecture)" \
    && wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/1.9/gosu-$(dpkg --print-architecture).asc" \
    && export GNUPGHOME="$(mktemp -d)" \
    && gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 \
    && gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu \
    && rm -r "$GNUPGHOME" /usr/local/bin/gosu.asc \
    && chmod +x /usr/local/bin/gosu \
    && gosu nobody true \
    && apt-get remove -y ca-certificates wget \
    && apt-get clean -y \
    && apt-get autoremove -y \
    && rm -rf /var/lib/apt/lists/*

# change entrypoint to use gosu-based script:
ADD run-with-user.sh /usr/local/bin/run-with-user.sh
RUN chmod +x /usr/local/bin/run-with-user.sh

ENTRYPOINT ["/usr/local/bin/run-with-user.sh"]

WORKDIR /app


text:
echo "killing all node processes in containers belonging to pod: $1"
kubectl exec $1 ./kill_containers.sh


text:
"""Config flow for Plaato."""
from pyplaato.plaato import PlaatoDeviceType
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.components import cloud, webhook
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_SCAN_INTERVAL, CONF_TOKEN, CONF_WEBHOOK_ID
from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv

from .const import (
    CONF_CLOUDHOOK,
    CONF_DEVICE_NAME,
    CONF_DEVICE_TYPE,
    CONF_USE_WEBHOOK,
    DEFAULT_SCAN_INTERVAL,
    DOCS_URL,
    DOMAIN,
    PLACEHOLDER_DEVICE_NAME,
    PLACEHOLDER_DEVICE_TYPE,
    PLACEHOLDER_DOCS_URL,
    PLACEHOLDER_WEBHOOK_URL,
)

class PlaatoConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
    """Handles a Plaato config flow."""

    VERSION = 1

    def __init__(self):
        """Initialize."""
        self._init_info = {}

    async def async_step_user(self, user_input=None):
        """Handle user step."""

        if user_input is not None:
            self._init_info[CONF_DEVICE_TYPE] = PlaatoDeviceType(
                user_input[CONF_DEVICE_TYPE]
            )
            self._init_info[CONF_DEVICE_NAME] = user_input[CONF_DEVICE_NAME]

            return await self.async_step_api_method()

        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema(
                {
                    vol.Required(
                        CONF_DEVICE_NAME,
                        default=self._init_info.get(CONF_DEVICE_NAME, None),
                    ): str,
                    vol.Required(
                        CONF_DEVICE_TYPE,
                        default=self._init_info.get(CONF_DEVICE_TYPE, None),
                    ): vol.In(list(PlaatoDeviceType)),
                }
            ),
        )

    async def async_step_api_method(self, user_input=None):
        """Handle device type step."""

        device_type = self._init_info[CONF_DEVICE_TYPE]

        if user_input is not None:
            token = user_input.get(CONF_TOKEN, None)
            use_webhook = user_input.get(CONF_USE_WEBHOOK, False)

            if not token and not use_webhook:
                errors = {"base": PlaatoConfigFlow._get_error(device_type)}
                return await self._show_api_method_form(device_type, errors)

            self._init_info[CONF_USE_WEBHOOK] = use_webhook
            self._init_info[CONF_TOKEN] = token
            return await self.async_step_webhook()

        return await self._show_api_method_form(device_type)

    async def async_step_webhook(self, user_input=None):
        """Validate config step."""

        use_webhook = self._init_info[CONF_USE_WEBHOOK]

        if use_webhook and user_input is None:
            try:
                webhook_id, webhook_url, cloudhook = await self._get_webhook_id()
            except cloud.CloudNotConnected:
                return self.async_abort(reason="cloud_not_connected")
            self._init_info[CONF_WEBHOOK_ID] = webhook_id
            self._init_info[CONF_CLOUDHOOK] = cloudhook

            return self.async_show_form(
                step_id="webhook",
                description_placeholders={
                    PLACEHOLDER_WEBHOOK_URL: webhook_url,
                    PLACEHOLDER_DOCS_URL: DOCS_URL,
                },
            )

        return await self._async_create_entry()

    async def _async_create_entry(self):
        """Create the entry step."""

        webhook_id = self._init_info.get(CONF_WEBHOOK_ID, None)
        auth_token = self._init_info[CONF_TOKEN]
        device_name = self._init_info[CONF_DEVICE_NAME]
        device_type = self._init_info[CONF_DEVICE_TYPE]

        unique_id = auth_token if auth_token else webhook_id

        await self.async_set_unique_id(unique_id)
        self._abort_if_unique_id_configured()

        return self.async_create_entry(
            title=device_type.name,
            data=self._init_info,
            description_placeholders={
                PLACEHOLDER_DEVICE_TYPE: device_type.name,
                PLACEHOLDER_DEVICE_NAME: device_name,
            },
        )

    async def _show_api_method_form(
        self, device_type: PlaatoDeviceType, errors: dict = None
    ):
        data_schema = vol.Schema({vol.Optional(CONF_TOKEN, default=""): str})

        if device_type == PlaatoDeviceType.Airlock:
            data_schema = data_schema.extend(
                {vol.Optional(CONF_USE_WEBHOOK, default=False): bool}
            )

        return self.async_show_form(
            step_id="api_method",
            data_schema=data_schema,
            errors=errors,
            description_placeholders={PLACEHOLDER_DEVICE_TYPE: device_type.name},
        )

    async def _get_webhook_id(self):
        """Generate webhook ID."""
        webhook_id = webhook.async_generate_id()
        if cloud.async_active_subscription(self.hass):
            webhook_url = await cloud.async_create_cloudhook(self.hass, webhook_id)
            cloudhook = True
        else:
            webhook_url = webhook.async_generate_url(self.hass, webhook_id)
            cloudhook = False

        return webhook_id, webhook_url, cloudhook

    @staticmethod
    def _get_error(device_type: PlaatoDeviceType):
        if device_type == PlaatoDeviceType.Airlock:
            return "no_api_method"
        return "no_auth_token"

    @staticmethod
    @callback
    def async_get_options_flow(config_entry):
        """Get the options flow for this handler."""
        return PlaatoOptionsFlowHandler(config_entry)

class PlaatoOptionsFlowHandler(config_entries.OptionsFlow):
    """Handle Plaato options."""

    def __init__(self, config_entry: ConfigEntry) -> None:
        """Initialize domain options flow."""
        super().__init__()

        self._config_entry = config_entry

    async def async_step_init(self, user_input=None):
        """Manage the options."""
        use_webhook = self._config_entry.data.get(CONF_USE_WEBHOOK, False)
        if use_webhook:
            return await self.async_step_webhook()

        return await self.async_step_user()

    async def async_step_user(self, user_input=None):
        """Manage the options."""
        if user_input is not None:
            return self.async_create_entry(title="", data=user_input)

        return self.async_show_form(
            step_id="user",
            data_schema=vol.Schema(
                {
                    vol.Optional(
                        CONF_SCAN_INTERVAL,
                        default=self._config_entry.options.get(
                            CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
                        ),
                    ): cv.positive_int
                }
            ),
        )

    async def async_step_webhook(self, user_input=None):
        """Manage the options for webhook device."""
        if user_input is not None:
            return self.async_create_entry(title="", data=user_input)

        webhook_id = self._config_entry.data.get(CONF_WEBHOOK_ID, None)
        webhook_url = (
            ""
            if webhook_id is None
            else webhook.async_generate_url(self.hass, webhook_id)
        )

        return self.async_show_form(
            step_id="webhook",
            description_placeholders={PLACEHOLDER_WEBHOOK_URL: webhook_url},
        )


text:
<!DOCTYPE html>

    <meta charset="UTF-8" />
    <meta name="robots" content="index, follow, all" />
    <title>Thelia\Core\Event\Module\ModuleDeleteEvent | Thelia 2 API</title>

            <link rel="stylesheet" type="text/css" href="../../../../css/bootstrap.min.css">
        <link rel="stylesheet" type="text/css" href="../../../../css/bootstrap-theme.min.css">
        <link rel="stylesheet" type="text/css" href="../../../../css/sami.css">

        <meta name="MobileOptimized" content="width">
        <meta name="HandheldFriendly" content="true">
        <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">

                <form id="search-form" action="../../../../search.html" method="GET">

            <input name="search"
                   class="typeahead form-control"
                   type="search"
                   placeholder="Search">
        </form>

                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-elements">
                    Toggle navigation

                </button>
                Thelia 2 API

Classes

Namespaces

Interfaces

Traits

Index

Search

class

Thelia

Core

Event

Module

ModuleDeleteEvent

ModuleDeleteEvent

    class
    ModuleDeleteEvent        extends ModuleEvent

Class ModuleDeleteEvent

Methods

                    __set($name, $value)

No description

from
    ActionEvent

                    __get($name)

No description

from
    ActionEvent

                    bindForm(
    Form $form)

No description

from
    ActionEvent

                    setChapo(
    mixed $chapo)

No description

from
    ModuleEvent

    mixed

                    getChapo()

No description

from
    ModuleEvent

                    setDescription(
    mixed $description)

No description

from
    ModuleEvent

    mixed

                    getDescription()

No description

from
    ModuleEvent

                    setId(
    mixed $id)

No description

from
    ModuleEvent

    mixed

                    getId()

No description

from
    ModuleEvent

                    setLocale(
    mixed $locale)

No description

from
    ModuleEvent

    mixed

                    getLocale()

No description

from
    ModuleEvent

                    setPostscriptum(
    mixed $postscriptum)

No description

from
    ModuleEvent

    mixed

                    getPostscriptum()

No description

from
    ModuleEvent

                    setTitle(
    mixed $title)

No description

from
    ModuleEvent

    mixed

                    getTitle()

No description

from
    ModuleEvent

                    __construct($module_id)

No description

    $this

                    setModule(
    Module $module)

No description

from
    ModuleEvent

    Module

                    getModule()

No description

from
    ModuleEvent

                    hasModule()

No description

from
    ModuleEvent

                    setModuleId(
    int $module_id)

No description

    int

                    getModuleId()

No description

                    getDeleteData()

No description

                    setDeleteData($delete_data)

No description

Details

in
    ActionEvent at line 30

    __set($name, $value)

Parameters

                $name

                $value

in
    ActionEvent at line 35

    __get($name)

Parameters

                $name

in
    ActionEvent at line 44

    bindForm(
    Form $form)

Parameters

    Form
                $form

in
    ModuleEvent at line 40

    setChapo(
    mixed $chapo)

Parameters

    mixed
                $chapo

in
    ModuleEvent at line 48

    mixed
    getChapo()

Return Value

    mixed

in
    ModuleEvent at line 56

    setDescription(
    mixed $description)

Parameters

    mixed
                $description

in
    ModuleEvent at line 64

    mixed
    getDescription()

Return Value

    mixed

in
    ModuleEvent at line 72

    setId(
    mixed $id)

Parameters

    mixed
                $id

in
    ModuleEvent at line 80

    mixed
    getId()

Return Value

    mixed

in
    ModuleEvent at line 88

    setLocale(
    mixed $locale)

Parameters

    mixed
                $locale

in
    ModuleEvent at line 96

    mixed
    getLocale()

Return Value

    mixed

in
    ModuleEvent at line 104

    setPostscriptum(
    mixed $postscriptum)

Parameters

    mixed
                $postscriptum

in
    ModuleEvent at line 112

    mixed
    getPostscriptum()

Return Value

    mixed

in
    ModuleEvent at line 120

    setTitle(
    mixed $title)

Parameters

    mixed
                $title

in
    ModuleEvent at line 128

    mixed
    getTitle()

Return Value

    mixed

at line 28

    __construct($module_id)

Parameters

                $module_id

in
    ModuleEvent at line 143

    $this
    setModule(
    Module $module)

Parameters

    Module
                $module

Return Value

    $this

in
    ModuleEvent at line 153

    Module
    getModule()

Return Value

    Module

in
    ModuleEvent at line 158

    hasModule()

at line 36

    setModuleId(
    int $module_id)

Parameters

    int
                $module_id

at line 44

    int
    getModuleId()

Return Value

    int

at line 49

    getDeleteData()

at line 54

    setDeleteData($delete_data)

Parameters

                $delete_data

        Generated by Sami, the API Documentation Generator.