text:
#import "DatParser.h"

/**
 *
 * Scannerの連続でテキストを解析していく。
 * 高速化のため正規表現の利用は最小限に抑える
 *
 **/

@implementation ScanContext
- (id)init
{
    if (self = [super init]) {
        self->referScanner = [[ReferScanner alloc] init];
        self->tagScanner = [[TagScanner alloc] init];
        self->idScanner = [[IDScanner alloc] init];
        self->urlScanner = [[URLScanner alloc] init];

        NSString *zSpace = @" ";
        NSUInteger length = [zSpace length];
        unichar chars2[length];
        [zSpace getCharacters:chars2 range:NSMakeRange(0, length)];
        self->firstOfSpace = chars2[0];
        self->secondOfSpace = chars2[1];
    }
    return self;
}
@end

@implementation DatParser

- (id)init
{
    if (self = [super init]) {
        self->_context = [[ScanContext alloc] init];
    }
    initCharRefMap();
    return self;
}

- (void)setBBSSubType:(BBSSubType)subType
{
    _subType = subType;

    // 2ch
    // [名前]<>[メール]<>[日付] [ID] [BE-ID]<>[本文]<>[スレッドタイトル]

    // まち
    // [レス番号]<>[名前]<>[メール]<>[日付] [ID] [BE-ID]<>[本文]<>[スレッドタイトル]

    // したらば
    // [レス番号]<>[名前]<>[メール]<>[日付]<>[本文]<>[スレッドタイトル]<>[ID]

    // トップレベルのスキャナーを順番通りにつなげる
    ResNumberScanner *resNumScanner = [[ResNumberScanner alloc] init];
    NameScanner *nameScanner = [[NameScanner alloc] init];
    MailScanner *mailScanner = [[MailScanner alloc] init];
    BodyScanner *bodyScanner = [[BodyScanner alloc] init];
    DateScanner *dateScanner = [[DateScanner alloc] init];
    TitleScanner *titleScanner = [[TitleScanner alloc] init];

    _context->firstScanner = (subType == BBSST_2CH_COMP) ? nameScanner : resNumScanner;

    resNumScanner->nextScanner = nameScanner;
    nameScanner->nextScanner = mailScanner;
    mailScanner->nextScanner = dateScanner;
    dateScanner->nextScanner = bodyScanner;
    bodyScanner->nextScanner = titleScanner;

    if (subType == BBSST_SHITARABA) {
        ShitarabaIDScanner *idScanner = [[ShitarabaIDScanner alloc] init];
        titleScanner->nextScanner = idScanner;
        idScanner->nextScanner = nil;
    } else {
        titleScanner->nextScanner = nil;
    }
}

- (NSArray *)parse:(NSString *)str
{
    return [self parse:str offset:0];
}

- (NSArray *)parse:(NSString *)str offset:(int)offset
{

    NSUInteger length = [str length] - offset;
    //unichar chars[length];
    unichar *chars = (unichar *)calloc(length, sizeof(unichar)); //[length];
    ScanContext *context = self->_context;
    context->res = [Res alloc];
    context->resList = [NSMutableArray array];

    [str getCharacters:chars range:NSMakeRange(offset, length)];

    context->chars = chars;
    context->charsLength = length;

    if (length == 0) {
        return context->resList;
    }

    [context->resList addObject:context->res];

    context->nextStartIndex = 0;
    // 走査開始
    for (;;) {
        [context->firstScanner run:context index:context->nextStartIndex];

        if (context->endOfText) break;
        if (context->charsLength <= context->nextStartIndex) break;

        if (context->endOfLine == NO) {
            NSUInteger length = context->charsLength;
            unichar *chars = context->chars;

            int i = context->nextStartIndex;
            for (; i <= length; i++) {
                unichar letter = chars[i];
                if (letter == 0xA) { // 改行
                    [self isEndOfLine:context index:i];
                    context->endOfLine = NO;
                    context->res = [Res alloc];
                    [context->resList addObject:context->res];

                    break;
                }
            }
        }
        context->endOfLine = NO;
    }

    free(chars);
    return context->resList;
}

@end

@implementation BaseScanner

// 継承クラスでオーバーライドする。
- (void)onTermGenerated:(ScanContext *)context text:(NSString *)text
{
}

//
// 汎用スキャン
//
// ・タグは取り除く。
// ・参照文字を変換する。
// ・<>の終了を検知する。
// ・改行で終了する。resListに有効なresを追加する。新しいResオブジェクトを生成する。
// ・テキストの最後に達したらでcontext->endOfText=TRUEをつけて終了する。
// ・適切な状況でnextScannerの run:context:indexを呼ぶ。
//
// 文字列が取得できたら onTermGenerated:context:string が呼ばれる
//
- (void)run:(ScanContext *)context index:(int)start
{
    int termBeginIndex = start;
    context->success = NO;

    BOOL shouldBreak = NO;

    NSUInteger length = context->charsLength;
    NSMutableString *term = [NSMutableString stringWithString:@""];
    unichar *chars = context->chars;
    for (int i = start; i <= length; i++) {

        if (i == length) {
            context->success = YES;
            shouldBreak = YES;
            context->endOfText = YES;
            context->endOfLine = YES;
        } else {
            unichar letter = chars[i];
            if (letter == '&') {
                [context->referScanner run:context index:i];
            } else if (letter == '<' && i + 1 < length) { // 次の文字がある場合のみ
                [self isDelimiter:context index:i];
                if (context->success) {
                    if (i + 2 < length) {
                    }
                    context->nextStartIndex = i + 2;
                    shouldBreak = YES;
                    ;
                } else {
                    [context->tagScanner run:context index:i];
                }

            } else if (letter == 0xA) { // 改行
                [self isEndOfLine:context index:i];
                shouldBreak = YES;
                ;
            }
        }

        if (context->success) {
            context->success = NO;

            // 以前の文字列を生成・追加
            if (i != termBeginIndex) {

                NSString *text = [self substringOfCharacters:chars start:termBeginIndex end:i];
                [term appendString:text];
            }
            if (context->genNodes != nil) {
                for (int n = 0; n < [context->genNodes count]; n++) {
                    ResNodeBase *node = [context->genNodes objectAtIndex:n];
                    [term appendString:[node getText]];
                }
                context->genNodes = nil;
            }

            if (shouldBreak) {
                break;
            }

            i = context->nextStartIndex - 1; // i++されるため
            termBeginIndex = context->nextStartIndex;
        }
    }

    [self onTermGenerated:context text:term];
    term = nil;

    context->success = NO;

    if (!context->endOfText && self->nextScanner != nil) {
        [self->nextScanner run:context index:context->nextStartIndex];
    } else if (context->endOfLine) {
        if (context->endOfText == NO) {
            context->res = [Res alloc];
            [context->resList addObject:context->res];
            //[context->firstScanner run:context index:context->nextStartIndex];
        }
    }
}

- (NSString *)translateReference:(unichar *)chars length:(NSUInteger)length
{
    initCharRefMap();
    ScanContext *context = [[ScanContext alloc] init];
    context->chars = chars;
    context->charsLength = length;
    int termBeginIndex = 0;

    NSMutableString *mutable = [[NSMutableString alloc] init];
    for (int i = 0; i <= length; i++) {

        if (i == length) {
            context->success = YES;
        } else {
            unichar letter = chars[i];
            if (letter == '&') {
                [self runRefNext:context index:i + 1];
            }
        }

        if (context->success) {
            context->success = NO;
            if (i != termBeginIndex) {
                NSString *text = [self substringOfCharacters:chars start:termBeginIndex end:i];
                if (text)
                    [mutable appendString:text];
            }
            if (context->genNodes != nil) {
                for (int n = 0; n < [context->genNodes count]; n++) {
                    ResNodeBase *node = [context->genNodes objectAtIndex:n];
                    [mutable appendString:[node getText]];
                }
                context->genNodes = nil;
            }
            termBeginIndex = context->nextStartIndex;
        }
    }

    return mutable;
}

// 񎋪
- (void)runRefNext:(ScanContext *)context index:(int)rightOfRef
{

    unichar left = context->chars[rightOfRef];
    int start = rightOfRef - 1;
    if (left == '#') {
        unichar letter2 = context->chars[start + 2];
        if (letter2 == 'x') { //16進数
            int indexOfPeriod = [self indexOf:context unichar:(unichar)';' index:start + 3];
            if (indexOfPeriod != -1 && indexOfPeriod != start + 3) {

                NSString *pString = [self substringOfCharacters:context->chars start:start + 3 end:indexOfPeriod];
                NSScanner *pScanner = [NSScanner scannerWithString:pString];

                unsigned int iValue;
                [pScanner scanHexInt:&iValue];
            }

        } else { //10進数
            for (int i = 0; i < 7; i++) {
                if ([self isDigit:context->chars[start + 2 + i]] == NO) {
                    if (i < 2) break;

                    //;, #&3642,それ以外を検出
                    NSString *vStr = [self substringOfCharacters:context->chars + start + 2 length:i];
                    int value = [vStr intValue];

                    NSString *text = [[NSString alloc] initWithCharacters:(unichar *)&value length:1];

                    if ([self startsWith:context index:start + 2 + i string:@";"]) {
                        context->nextStartIndex = start + 2 + i + 9;
                        ////                                        text =  [[NSString alloc] initWithCharacters:&value length:2];
                        //                                        char cs[2];
                        //                                        cs[0] = value;
                        //                                        cs[1] = 65038;

                        unichar cs[2];
                        //                                        cs[0] = 65038;
                        cs[0] = value;
                        cs[1] = 65039;

                        text = [NSString stringWithCharacters:cs length:2];
                        //  myLog(@"c = %@", text);
                        // aawfw
                        //    text = [NSString stringWithUTF8String:<#(const char *)#>:@"%C%C", (unichar)value, 65038];
                        //                                        text = string;
                    } else

                        if ([self startsWith:context index:start + 2 + i string:@";"]) {
                        context->nextStartIndex = start + 2 + i + 9;
                        ////                                        text =  [[NSString alloc] initWithCharacters:&value length:2];
                        //                                        char cs[2];
                        //                                        cs[0] = value;
                        //                                        cs[1] = 65038;

                        unichar cs[2];
                        //                                        cs[0] = 65038;
                        cs[0] = value;
                        cs[1] = 65038;

                        text = [NSString stringWithCharacters:cs length:2];
                        //   myLog(@"c = %@", text);
                        //    text = [NSString stringWithUTF8String:<#(const char *)#>:@"%C%C", (unichar)value, 65038];
                        //                                        text = string;
                    } else if (context->chars[start + 2 + i] == ';') {
                        context->nextStartIndex = start + 2 + i + 1;
                    } else if ([self startsWith:context index:start + 2 + i string:@"&#3642"]) {
                        context->nextStartIndex = start + 2 + i + 6;
                    } else {
                        context->nextStartIndex = start + 2 + i;
                    }

                    //  myLog(@"(unichar)value = %d" , value);
                    //  [[NSString alloc] initWithCharacters:&value length:1];
                    //     NSString* text = [NSString stringWithFormat:@"%C", (unichar)value];

                    /*
                                    if (value == 9899) {
                                            text = @"●";
                                    } else if (value == 9898) {
                                        text = @"○";
                                    }*/

                    //   myLog(@"esText = {%@}", text);

                    TextNode *textNode = [[TextNode alloc] initWithNSString:text];
                    context->genNodes = [NSArray arrayWithObjects:textNode, nil];
                    context->success = YES;
                    return;
                }
            }
        }
    } else { //文字参照
        int indexOfPeriod = [self indexOf:context unichar:';' index:start + 1];
        if (indexOfPeriod != -1 && indexOfPeriod != start + 1) {
            NSString *term = [self substringOfCharacters:context->chars + start + 1
                                                  length:indexOfPeriod - (start + 1)];
            NSNumber *storedNumber = [charRefMap objectForKey:term];

            if (storedNumber != nil) {
                unichar ch = (unichar)[storedNumber intValue];
                NSString *text = [[NSString alloc] initWithCharacters:&ch length:1];
                //                                NSString* text = @"?";//[NSString stringWithFormat:@"%C", (unichar)[storedNumber intValue]];

                TextNode *textNode = [[TextNode alloc] initWithNSString:text];
                context->genNodes = [NSArray arrayWithObjects:textNode, nil];
                context->nextStartIndex = indexOfPeriod + 1;
                context->success = YES;
                return;
            }
        }
    }
}

- (BOOL)isDelimiter:(ScanContext *)context index:(int)start
{
    if (start == context->charsLength - 1) {
        context->success = YES;
        context->endOfText = YES;
        return NO;
    }

    unichar next = context->chars[start + 1];
    if (next == '>') {
        context->success = YES;
        context->nextStartIndex = start + 2;
        return YES;
    }
    return NO;
}

- (BOOL)isEndOfLine:(ScanContext *)context index:(int)start
{
    context->success = YES;
    context->endOfLine = YES;
    if (context->charsLength - 1 == start) {
        context->endOfText = YES;
    }
    context->nextStartIndex = start + 1;
    return YES;
}

- (NSString *)substringOfCharacters:(unichar *)chars length:(NSUInteger)length
{
    return [NSString stringWithCharacters:chars length:length];
}
- (NSString *)substringOfCharacters:(unichar *)chars start:(int)start end:(int)end
{
    return [NSString stringWithCharacters:chars + start length:end - start];
}

//
// indexOf
//
- (int)indexOf:(ScanContext *)context unichar:(unichar)uchar index:(int)index
{
    return [self indexOf:context->chars length:context->charsLength unichar:uchar index:index];
}

//
// indexOf
//
- (int)indexOf:(unichar *)chars length:(NSUInteger)length unichar:(unichar)uchar index:(int)index
{
    for (int i = index; i < length; i++) {
        if (chars[i] == uchar) {
            return i;
        } else if (chars[i] == '<' || chars[i] == 0xA) {
            return -1;
        }
    }
    return -1;
}

- (BOOL)startsWith:(ScanContext *)context index:(int)index string:(NSString *)string
{
    return [self startsWith:context->chars length:context->charsLength index:index string:string];
}

- (BOOL)startsWith:(unichar *)chars length:(NSUInteger)length index:(int)index string:(NSString *)string
{
    if (string == nil) return NO;

    NSUInteger strLength = [string length];
    if (strLength == 0) return NO;

    // 文字数が足りてないのでOUT
    if (index + strLength > length) {
        return NO;
    }

    for (int j = 0; j < strLength; j++) {
        if (chars[index + j] != [string characterAtIndex:j]) {
            return NO;
        }
    }
    return YES;
}

- (int)indexOf:(ScanContext *)context string:(NSString *)string index:(int)index
{
    return [self indexOf:context->chars length:context->charsLength string:string index:index];
}

- (int)indexOf:(unichar *)chars
        length:(NSUInteger)length
        string:(NSString *)string
         index:(int)index
{
    NSUInteger strLength = [string length];

    unichar buffer[strLength];
    [string getCharacters:buffer range:NSMakeRange(0, strLength)];

    for (int i = index; i < length; i++) {
        unichar letter = chars[i];
        if (letter == 0xA) {
            return -1;
        }

        if (i + strLength > length) {
            break;
        }
        BOOL ok = YES;
        for (int j = 0; j < strLength; j++) {
            if (chars[i + j] != [string characterAtIndex:j]) {
                ok = NO;
                break;
            }
        }
        if (ok) {
            return i; // 全一致
        } else {
        }
    }
    return -1;
}

- (int)lastIndexOf:(unichar *)chars length:(NSUInteger)length unichar:(unichar)unichar beginIndex:(int)beginIndex endIndex:(int)endIndex
{
    if (endIndex < length == false || beginIndex < 0) return -1;

    for (int i = endIndex; i >= beginIndex; i--) {
        if (chars[i] == unichar) {
            return i;
        }
    }
    return -1;
}

- (BOOL)isDigit:(unichar)letter
{
    if (letter == '0' || letter == '1' || letter == '2' || letter == '3' || letter == '4' || letter == '5' || letter == '6' || letter == '7' || letter == '8' || letter == '9') {
        return YES;
    }
    return NO;
}
@end

//
// NameScanner
//
// 名前
//
@implementation NameScanner

- (void)onTermGenerated:(ScanContext *)context text:(NSString *)text
{
    context->res.name = text;
}
@end

//
// MailScanner
//
// メール
//
@implementation MailScanner

- (void)onTermGenerated:(ScanContext *)context text:(NSString *)text
{
    context->res.mail = text;
}
@end

//
// IDScanner
//
// したらばはIDだけの項目がある
//
@implementation ShitarabaIDScanner

- (void)onTermGenerated:(ScanContext *)context text:(NSString *)text
{
    context->res.ID = text;
}
@end

//
// ThreadTitleScanner
//
// スレッドタイトル
//
@implementation TitleScanner

- (void)onTermGenerated:(ScanContext *)context text:(NSString *)text
{
    context->res.threadTitle = text;
}
@end

//
// ResNumberScanner
//
// したらばとまちBBSだけのレス番号
//
@implementation ResNumberScanner

- (void)onTermGenerated:(ScanContext *)context text:(NSString *)text
{
    context->res.number = [text intValue];
}
@end

@implementation DateScanner

// DateScanner
- (void)run:(ScanContext *)context index:(int)start
{
    int termBeginIndex = start;
    int spaceCount = 0;

    NSUInteger length = context->charsLength;
    unichar *chars = context->chars;
    BOOL inBEID = NO, inBERank = NO, inBEPoint = NO;
    int beStartPos = 0;

    for (int i = start; i <= length; i++) {
        BOOL shouldSplit = NO;
        BOOL shouldEnd = NO;

        if (i == length) {
            shouldEnd = shouldSplit = context->endOfText = context->endOfLine = YES;
        } else {
            unichar letter = chars[i];
            if (letter == '<') { // 次の文字がある場合のみ
                [self isDelimiter:context index:i];
                if (context->success) {
                    context->nextStartIndex = i + 2;
                } else {
                    context->nextStartIndex = i + 1;
                }

                shouldSplit = YES;
                spaceCount++;
                shouldEnd = YES;
            } else if (letter == 0xA) {
                shouldSplit = YES;
                context->nextStartIndex = i + 1;
                shouldEnd = YES;
                spaceCount++;
            } else if (letter == ' ') {
                spaceCount++;
                shouldSplit = YES;
                context->nextStartIndex = i + 1;
            } else {
                // BE:ログインID-ランク(Beポイント)
                // 例:BE:999999999-DIA(20000)
                if (inBEID) {
                    if (letter == '-') {
                        NSString *beId = [self substringOfCharacters:context->chars + beStartPos
                                                              length:i - beStartPos];
                        context->res.BEID = beId;
                        beStartPos = i + 1;
                        inBERank = YES;
                        inBEID = NO;
                    }

                } else if (inBERank) {
                    if (letter == '(') {
                        NSString *beRank = [self substringOfCharacters:context->chars + beStartPos
                                                                length:i - beStartPos];
                        inBERank = NO;
                        inBEPoint = YES;
                        beStartPos = i + 1;
                        context->res.BERank = beRank;
                    }

                } else if (inBEPoint) {
                    if (letter == ')') {
                        NSString *bePoint = [self substringOfCharacters:context->chars + beStartPos
                                                                 length:i - beStartPos];
                        inBEPoint = NO;
                        context->res.BEPoint = [bePoint intValue];
                    }
                } else if (spaceCount >= 2 && [self startsWith:context index:i string:@"BE:"]) {
                    beStartPos = i + 3;
                    i += 2;
                    inBEID = YES;
                }
            }
        }

        if (shouldSplit) {
            shouldSplit = NO;
            NSString *term = [self substringOfCharacters:context->chars + termBeginIndex length:i - termBeginIndex];
            if (spaceCount == 0 && shouldEnd) {
                context->res.dateStr = term;
            } else {
                if (spaceCount == 1) {
                    context->res.dateStr = term;
                } else if (spaceCount == 2) {
                    context->res.timeStr = term;
                } else if (spaceCount == 3) {
                    BOOL startsWithID = [self startsWith:context index:termBeginIndex string:@"ID:"];
                    if (startsWithID) {
                        NSString *idStr = [self substringOfCharacters:context->chars + termBeginIndex + 3
                                                               length:i - (termBeginIndex + 3)];
                        context->res.ID = idStr;

                    } else {

                        BOOL startsWithHasshin = [self startsWith:context index:termBeginIndex string:@"発信元:"];
                        if (startsWithHasshin) {
                            NSString *idStr = [self substringOfCharacters:context->chars + termBeginIndex + 4
                                                                   length:i - (termBeginIndex + 4)];
                            context->res.ID = idStr;
                        }
                    }
                } else if (spaceCount == 4) {

                } else {
                    shouldEnd = YES;
                }
            }

            if (context->endOfLine) {
                return;
            }

            term = nil;
            if (shouldEnd) {
                context->success = YES;
                context->nextStartIndex = i;
                if (self->nextScanner != nil) {
                    [self->nextScanner run:context index:i + 2];
                }
                return;
            }

            termBeginIndex = context->nextStartIndex;
        }
    }
}
@end

@implementation BodyScanner

- (id)init
{
    if (self = [super init]) {
    }

    return self;
}

- (int)isBr:(NSString *)str startIndex:(int)start context:(ScanContext *)context
{
    return 32;
}

// BodyScanner
- (void)run:(ScanContext *)context index:(int)start
{
    int termBeginIndex = start;
    NSMutableArray *nodeList = [NSMutableArray array];
    context->success = NO;
    ResNodeBase *previousNode = nil;

    BOOL shouldBreak = NO;
    context->nextOfTag = YES;
    //  myLog(@"runbody");

    NSUInteger length = context->charsLength;
    unichar *chars = context->chars;
    int aaCount = 0;

    int i = start;
    for (; i <= length; i++) {

        if (i == length) {
            context->success = shouldBreak = context->endOfLine = context->endOfText = YES;
        } else {
            unichar letter = chars[i];
            if (letter == '&' || letter == '>') {
                [context->referScanner run:context index:i];
            } else if (letter == 'I') {
                [context->idScanner parseIdNode:context index:i];
            } else if (letter == 's' || letter == 'h' || letter == 't') {
                [context->urlScanner run:context index:i];
            } else if (letter == '<' && i + 1 < length) { // 次の文字がある場合のみ
                [self isDelimiter:context index:i];
                if (context->success) {
                    context->nextStartIndex = i + 2;
                    shouldBreak = YES;
                    ;
                } else {
                    [context->tagScanner run:context index:i];
                }

            } else if (letter == 0xA) { // 改行

                [self isEndOfLine:context index:i];
                shouldBreak = YES;
                ;

            } else if (context->nextOfTag && letter == ' ' && i == termBeginIndex) {
                termBeginIndex++; //先頭のスペースを削除
                //末尾のスペースは処理していない。切り取らなくてもいい気が。
                context->nextOfTag = NO;
            } else if (letter == context->firstOfSpace) {
                if (length > i + 1 && chars[i + 1] == ' ') {
                    aaCount++;
                }
            }
        }

        if (context->success) {
            context->success = NO;
            // 以前の文字列を生成・追加
            if (i != termBeginIndex) {
                NSString *text = [self substringOfCharacters:chars start:termBeginIndex end:i];
                //if ([text isEqualToString:@"  "] ||[text isEqualToString:@" "] ) {
                //myLog(@"[%@]", text);
                //                                } else {
                if ([previousNode isKindOfClass:[TextNode class]]) {
                    TextNode *prevText = (TextNode *)previousNode;

                    [prevText appendText:text];

                } else {
                    TextNode *textNode = [[TextNode alloc] initWithNSString:text];
                    [nodeList addObject:textNode];
                    previousNode = textNode;
                    // myLog(@"her = %@", text);
                }
                //                              }
            }
            if (context->genNodes != nil) {
                for (int n = 0; n < [context->genNodes count]; n++) {
                    ResNodeBase *node = [context->genNodes objectAtIndex:n];
                    // LineBreakNodeの再利用
                    if ([node isKindOfClass:LineBreakNode.class] && [previousNode isKindOfClass:LineBreakNode.class]) {
                        node = previousNode;
                        [(LineBreakNode *)node incrementCount];
                    } else if ([node isKindOfClass:[TextNode class]] && [previousNode isKindOfClass:[TextNode class]]) {
                        TextNode *prevText = (TextNode *)previousNode;
                        //               myLog(@"append %@ with %@", [prevText getText],[(TextNode*)node getText]);
                        [prevText appendText:[(TextNode *)node getText]];
                        node = previousNode;

                    } else {
                        [nodeList addObject:node];
                    }
                    previousNode = node;
                }
                context->genNodes = nil;
            }

            if (context->endOfLine) return;

            if (shouldBreak) {
                break;
            }

            i = context->nextStartIndex - 1; // i++されるため
            termBeginIndex = context->nextStartIndex;
        }
    }
    context->success = NO;
    context->res.bodyNodes = nodeList;

    if (aaCount > 3) {
        context->res.isAA = YES;
    }

    if (context->endOfText) {
        return;
    } else if (context->endOfLine) {
        context->endOfLine = NO;
        if (context->endOfText == NO) {
            context->res = [Res alloc];
            [context->resList addObject:context->res];
        }
    } else if (self->nextScanner != nil) {
        [self->nextScanner run:context index:context->nextStartIndex];
    }
}
@end

@implementation NodeScannerBase

@end

@implementation AnchorScannerBase
// 複数のアンカーを検出するためのcontinueメソッド
- (void)runContinueWithAnchor:(ScanContext *)context
                continueIndex:(int)continueIndex
                   anchorNode:(AnchorNode *)anchorNode //すでに出来たアンカーノード
{
    if (continueIndex < context->charsLength == NO) {
        context->success = NO;
        return;
    }
    // >>125, 123, 512のような続きを発見する
    unichar next = context->chars[continueIndex];
    unichar next2 = continueIndex + 1 < context->charsLength ? context->chars[continueIndex + 1] : 0;

    if (next == '-') {
        if (anchorNode.isClosed) {
            context->success = NO;
            return;
        }

        int num = [self runNumber:context index:continueIndex + 1];
        if (context->success) {
            [anchorNode setClosedValue:num];
        } else {
            context->success = NO;
            return;
        }
    } else {
        if (next == ',') {
            NSMutableArray *newNodes = [[NSMutableArray alloc] initWithArray:context->genNodes];
            TextNode *dividerText;
            int num = [self runNumber:context index:continueIndex + (next2 == ' ' ? 2 : 1)];

            if (context->success) {
                dividerText = [[TextNode alloc] initWithNSString:(next2 == ' ' ? @", " : @",")];
                [newNodes addObject:dividerText];

                anchorNode = [[AnchorNode alloc] initWithNumber:num];
                [newNodes addObject:anchorNode];
                context->genNodes = newNodes;
            } else {
                context->success = NO;
                return;
            }
        } else {
            context->success = NO;
            return;
        }
    }

    [self runContinueWithAnchor:context
                  continueIndex:context->nextStartIndex
                     anchorNode:anchorNode // すでに出来たアンカーノード
    ];
    context->success = YES;
}

// アンカーの数値だけを検出
- (int)runNumber:(ScanContext *)context index:(int)startIndex
{
    int count = 0;
    int i = startIndex;
    for (; i < context->charsLength; i++) {
        BOOL digi = [self isDigit:context->chars[i]];
        if (!digi || count > 5 || (i == startIndex && context->chars[i] == '0')) {
            break;
        }
        count++;
    }
    if (i != startIndex) {
        context->success = YES;
        context->nextStartIndex = startIndex + count;
        NSString *trim = [self substringOfCharacters:context->chars + startIndex length:count];
        return [trim intValue];
    }
    context->success = NO;
    return -1;
}

@end

// '<'ではじまるNodeを解析する
@implementation TagScanner

- (int)getEndNumber:(unichar *)chars start:(int)start end:(int)end
{
    int numberStart = -1;
    int numberEnd = -1;
    BOOL keepNumber = NO;
    for (int i = start; i <= end; i++) {
        unichar letter = chars[i];
        if ([self isDigit:letter]) {
            if (keepNumber == NO) {
                numberStart = numberEnd = i;
            } else {
                numberEnd = i;
            }
            keepNumber = YES;
        } else {
            keepNumber = NO;
            numberStart = -1;
        }
    }

    if (numberStart != -1) {
        return [[self substringOfCharacters:chars + numberStart length:numberEnd - numberStart + 1] intValue];
    }

    return -1;
}

// TagScanner
- (void)run:(ScanContext *)context index:(int)start
{
    // startの位置は '<'が来ていると想定
    context->nextOfTag = YES;
    int i = start + 1;
    unichar *chars = context->chars;
    unichar next = chars[i];
    NSUInteger length = context->charsLength;
    if (next == 'b' || next == 'B') { // <br>
        if (3 <= length - i && (chars[i + 1] == 'r' || chars[i + 1] == 'R') && chars[i + 2] == '>') {
            context->success = YES;
            context->nextStartIndex = i + 3;

            LineBreakNode *brNode = [[LineBreakNode alloc] init];

            context->genNodes = [NSArray arrayWithObjects:brNode, nil];
            return;
            //return brNode;
        }
    } else if (next == 'f') { // <font color=gold>awejpfop</font>
        int fontColor = [self indexOf:context string:@"font color=" index:i];
        if (fontColor == i) {
            int indexOfGT = [self indexOf:context unichar:'>' index:i + 7];
            if (indexOfGT != -1 && indexOfGT - i < 36) {
                NSString *text = [self substringOfCharacters:context->chars start:(i + 11)end:indexOfGT];
                context->res.nameColor = text;
                context->success = YES;
                context->nextStartIndex = indexOfGT + 1;
                return;
            }
        }

    } else {
        // 対象例: <a href=\"\" target=\"_blank\">>>234</a>
        int indexOfAHref = [self indexOf:context string:@"a href=" index:i];
        if (indexOfAHref == i) {
            int indexOfGT = [self indexOf:context string:@">>>" index:i + 7];
            if (indexOfGT != -1) {
                int indexOfEndA = [self indexOf:context string:@"</a>" index:indexOfGT + 1];
                if (indexOfEndA != -1) {
                    int num = [self getEndNumber:chars start:indexOfGT + 1 end:indexOfEndA];
                    if (num != -1) {
                        AnchorNode *anchorNode = [[AnchorNode alloc] initWithNumber:num];
                        context->genNodes = [NSArray arrayWithObjects:anchorNode, nil];

                        // return anchorNode;
                        [self runContinueWithAnchor:context
                                      continueIndex:indexOfEndA + 4
                                         anchorNode:anchorNode // すでに出来たアンカーノード
                        ];

                        if (context->success) {
                        } else {
                            context->nextStartIndex = indexOfEndA + 4;
                            context->success = YES;
                        }
                        return;
                    }
                }
            }
        }
    }

    // ヒットしなかったので次の'>'までインデックスを飛ばす
    int indexOfGT = [self indexOf:context unichar:'>' index:i];
    if (indexOfGT != -1) {
        context->success = YES;
        context->nextStartIndex = indexOfGT + 1;
        context->genNodes = nil;
        return;
    }

    context->success = NO;
}

@end

// &から始まる文字参照と>>, >>, >,>ではじまるアンカーを解析する
@implementation ReferScanner

//ReferScanner
- (void)run:(ScanContext *)context index:(int)start
{
    int num;
    AnchorNode *anchorNode = nil;
    NSArray *prefixes = [NSArray arrayWithObjects:@">>", @">", @">", nil]; // > >>

    for (int i = 0; i < [prefixes count]; i++) {
        NSString *prefix = [prefixes objectAtIndex:i];
        if ([self startsWith:context index:start string:prefix]) {
            num = [self runNumber:context index:start + (int)[prefix length]];
            if (context->success) {
                anchorNode = [[AnchorNode alloc] initWithNumber:num];
            }
        }
    }

    if (anchorNode != nil) {
        context->genNodes = [NSArray arrayWithObjects:anchorNode, nil];
        [self runContinueWithAnchor:context
                      continueIndex:context->nextStartIndex
                         anchorNode:anchorNode //すでに出来たアンカーノード
        ];
        context->success = YES;
        return;
    }

    //TODO:文字参照1

    //private static final String RE_NCR = "&((([0-9a-z]+);)|(#([0-9]+)(&#3642|;)?)|#x([\\da-fA-F]+);)";
    // &amp3;  (([0-9a-z]+);)
    // &#0323&#3642 (#([0-9]+)(&#3642|;)?)
    // Ń
    // &#0323
    // ਏ #x([\\da-fA-F]+);

    context->success = NO;

    [self runRefNext:context index:start + 1];
}
@end

// ID:ではじまるNodeを解析する
@implementation IDScanner : NodeScannerBase

- (BOOL)isIdChar:(unichar)c
{
    if ('A' <= c && c <= 'z')
        return YES;

    if ([self isDigit:c])
        return YES;

    if (c == '/' || c == '+' || c == '!')
        return YES;

    return NO;
}

// 走査しAnchorNodeかnilを返す
// ID:yUGBWbHR0
- (void)parseIdNode:(ScanContext *)context index:(int)i
{
    if (context->charsLength > i + 2 == NO) {
        return;
    }

    unichar *chars = context->chars;

    if (chars[i + 1] == 'D' && chars[i + 2] == ':') {
        // i+3
        // i+4
        // i+5
        // i+6
        // i+7
        // i+8
        // i+9
        // i+10
        int startId = i + 3;
        if (context->charsLength >= startId + 8) { // 8文字分あり
            for (int m = startId; m < startId + 8; m++) {
                unichar ch = chars[m];
                if ([self isIdChar:ch] == NO) {
                    context->success = NO;
                    return;
                }
            }

            IDNode *idNode = nil;
            if (context->charsLength > startId + 8 && [self isIdChar:chars[startId + 8]]) { //末尾あり
                idNode = [[IDNode alloc] initWithString:[self substringOfCharacters:context->chars + startId length:9]];
                context->nextStartIndex = startId + 9;
            } else {
                idNode = [[IDNode alloc] initWithString:[self substringOfCharacters:context->chars + startId length:8]];
                context->nextStartIndex = startId + 8;
            }
            context->success = YES;
            context->genNodes = [[NSArray alloc] initWithObjects:idNode, nil];
            return;
        }

        context->success = NO;
    }
}
@end

// ID:ではじまるNodeを解析する
@implementation URLScanner : NodeScannerBase

// 走査しLinkNodeかnilを返す
- (void)run:(ScanContext *)context index:(int)start
{
    NSString *realScheme = nil;
    NSString *accessScheme = nil;
    int lettersStart = 0;
    unichar *chars = context->chars;
    NSUInteger length = context->charsLength;

    BOOL ok = NO;
    NSArray *schemes = [NSArray arrayWithObjects:@"http://", @"https://", @"ttp://", @"ttps://", @"sssp://", nil];
    for (int i = 0; i < [schemes count]; i++) {
        NSString *scheme = [schemes objectAtIndex:i];
        if ([self startsWith:context index:start string:scheme]) {
            realScheme = [schemes objectAtIndex:i];
            int accessSchemeIndex = (i == 2) ? 0 : (i == 3 ? 1 : i);
            accessScheme = (NSString *)[schemes objectAtIndex:accessSchemeIndex];
            lettersStart = start + (int)[scheme length];

            ok = YES;
            break;
        }
    }

    if (ok == NO) {
        context->success = NO;
        return;
    }

    int n = lettersStart;
    for (; n < length; n++) {
        unichar t = chars[n];
        if (('A' <= t && t <= 'z') || ('0' <= t && t <= '9') || t == '_' || t == '.' || t == '(' || t == ')' || t == '$' || t == '*' || t == '!' || t == '-' || t == ':' || t == '#' || t == ',' || t == '?' || t == '=' || t == '&' || t == ';' || t == '%' || t == '~' || t == '+' || t == '/') {
            continue;
        } else {
            break;
        }
    }
    if (n == lettersStart) {
        context->success = NO;
        return;
    } //一文字もない場合は失敗

    context->success = YES;
    context->nextStartIndex = n;
    NSString *url = [self substringOfCharacters:chars + start length:n - start];
    NSString *accessUrl = [accessScheme stringByAppendingString:[self substringOfCharacters:chars + lettersStart length:n - lettersStart]];

    LinkNode *linkNode = [[LinkNode alloc] initWithUrl:url
                                         withAccessUrl:accessUrl];

    context->genNodes = [NSArray arrayWithObjects:linkNode, nil];

}
@end

void initCharRefMap()
{
    if (charRefMap != nil) return;
    charRefMap = [NSDictionary dictionaryWithObjectsAndKeys:
                                   [NSNumber numberWithInt:34], @"quot",
                                   [NSNumber numberWithInt:38], @"amp",
                                   [NSNumber numberWithInt:60], @"lt",
                                   [NSNumber numberWithInt:62], @"gt",
                                   [NSNumber numberWithInt:160], @"nbsp",
                                   [NSNumber numberWithInt:161], @"iexcl",
                                   [NSNumber numberWithInt:162], @"cent",
                                   [NSNumber numberWithInt:163], @"pound",
                                   [NSNumber numberWithInt:164], @"curren",
                                   [NSNumber numberWithInt:165], @"yen",
                                   [NSNumber numberWithInt:166], @"brvbar",
                                   [NSNumber numberWithInt:167], @"sect",
                                   [NSNumber numberWithInt:168], @"uml",
                                   [NSNumber numberWithInt:169], @"copy",
                                   [NSNumber numberWithInt:170], @"ordf",
                                   [NSNumber numberWithInt:171], @"laquo",
                                   [NSNumber numberWithInt:172], @"not",
                                   [NSNumber numberWithInt:173], @"shy",
                                   [NSNumber numberWithInt:174], @"reg",
                                   [NSNumber numberWithInt:175], @"macr",
                                   [NSNumber numberWithInt:176], @"deg",
                                   [NSNumber numberWithInt:177], @"plusmn",
                                   [NSNumber numberWithInt:178], @"sup2",
                                   [NSNumber numberWithInt:179], @"sup3",
                                   [NSNumber numberWithInt:180], @"acute",
                                   [NSNumber numberWithInt:181], @"micro",
                                   [NSNumber numberWithInt:182], @"para",
                                   [NSNumber numberWithInt:183], @"middot",
                                   [NSNumber numberWithInt:184], @"cedil",
                                   [NSNumber numberWithInt:185], @"sup1",
                                   [NSNumber numberWithInt:186], @"ordm",
                                   [NSNumber numberWithInt:187], @"raquo",
                                   [NSNumber numberWithInt:188], @"frac14",
                                   [NSNumber numberWithInt:189], @"frac12",
                                   [NSNumber numberWithInt:190], @"frac34",
                                   [NSNumber numberWithInt:191], @"iquest",
                                   [NSNumber numberWithInt:192], @"Agrave",
                                   [NSNumber numberWithInt:193], @"Aacute",
                                   [NSNumber numberWithInt:194], @"Acirc",
                                   [NSNumber numberWithInt:195], @"Atilde",
                                   [NSNumber numberWithInt:196], @"Auml",
                                   [NSNumber numberWithInt:197], @"Aring",
                                   [NSNumber numberWithInt:198], @"AElig",
                                   [NSNumber numberWithInt:199], @"Ccedil",
                                   [NSNumber numberWithInt:200], @"Egrave",
                                   [NSNumber numberWithInt:201], @"Eacute",
                                   [NSNumber numberWithInt:202], @"Ecirc",
                                   [NSNumber numberWithInt:203], @"Euml",
                                   [NSNumber numberWithInt:204], @"Igrave",
                                   [NSNumber numberWithInt:205], @"Iacute",
                                   [NSNumber numberWithInt:206], @"Icirc",
                                   [NSNumber numberWithInt:207], @"Iuml",
                                   [NSNumber numberWithInt:208], @"ETH",
                                   [NSNumber numberWithInt:209], @"Ntilde",
                                   [NSNumber numberWithInt:210], @"Ograve",
                                   [NSNumber numberWithInt:211], @"Oacute",
                                   [NSNumber numberWithInt:212], @"Ocirc",
                                   [NSNumber numberWithInt:213], @"Otilde",
                                   [NSNumber numberWithInt:214], @"Ouml",
                                   [NSNumber numberWithInt:215], @"times",
                                   [NSNumber numberWithInt:216], @"Oslash",
                                   [NSNumber numberWithInt:217], @"Ugrave",
                                   [NSNumber numberWithInt:218], @"Uacute",
                                   [NSNumber numberWithInt:219], @"Ucirc",
                                   [NSNumber numberWithInt:220], @"Uuml",
                                   [NSNumber numberWithInt:221], @"Yacute",
                                   [NSNumber numberWithInt:222], @"THORN",
                                   [NSNumber numberWithInt:223], @"szlig",
                                   [NSNumber numberWithInt:224], @"agrave",
                                   [NSNumber numberWithInt:225], @"aacute",
                                   [NSNumber numberWithInt:226], @"acirc",
                                   [NSNumber numberWithInt:227], @"atilde",
                                   [NSNumber numberWithInt:228], @"auml",
                                   [NSNumber numberWithInt:229], @"aring",
                                   [NSNumber numberWithInt:230], @"aelig",
                                   [NSNumber numberWithInt:231], @"ccedil",
                                   [NSNumber numberWithInt:232], @"egrave",
                                   [NSNumber numberWithInt:233], @"eacute",
                                   [NSNumber numberWithInt:234], @"ecirc",
                                   [NSNumber numberWithInt:235], @"euml",
                                   [NSNumber numberWithInt:236], @"igrave",
                                   [NSNumber numberWithInt:237], @"iacute",
                                   [NSNumber numberWithInt:238], @"icirc",
                                   [NSNumber numberWithInt:239], @"iuml",
                                   [NSNumber numberWithInt:240], @"eth",
                                   [NSNumber numberWithInt:241], @"ntilde",
                                   [NSNumber numberWithInt:242], @"ograve",
                                   [NSNumber numberWithInt:243], @"oacute",
                                   [NSNumber numberWithInt:244], @"ocirc",
                                   [NSNumber numberWithInt:245], @"otilde",
                                   [NSNumber numberWithInt:246], @"ouml",
                                   [NSNumber numberWithInt:247], @"divide",
                                   [NSNumber numberWithInt:248], @"oslash",
                                   [NSNumber numberWithInt:249], @"ugrave",
                                   [NSNumber numberWithInt:250], @"uacute",
                                   [NSNumber numberWithInt:251], @"ucirc",
                                   [NSNumber numberWithInt:252], @"uuml",
                                   [NSNumber numberWithInt:253], @"yacute",
                                   [NSNumber numberWithInt:254], @"thorn",
                                   [NSNumber numberWithInt:255], @"yuml",
                                   [NSNumber numberWithInt:402], @"fnof",
                                   [NSNumber numberWithInt:913], @"Alpha",
                                   [NSNumber numberWithInt:914], @"Beta",
                                   [NSNumber numberWithInt:915], @"Gamma",
                                   [NSNumber numberWithInt:916], @"Delta",
                                   [NSNumber numberWithInt:917], @"Epsilon",
                                   [NSNumber numberWithInt:918], @"Zeta",
                                   [NSNumber numberWithInt:919], @"Eta",
                                   [NSNumber numberWithInt:920], @"Theta",
                                   [NSNumber numberWithInt:921], @"Iota",
                                   [NSNumber numberWithInt:922], @"Kappa",
                                   [NSNumber numberWithInt:923], @"Lambda",
                                   [NSNumber numberWithInt:924], @"Mu",
                                   [NSNumber numberWithInt:925], @"Nu",
                                   [NSNumber numberWithInt:926], @"Xi",
                                   [NSNumber numberWithInt:927], @"Omicron",
                                   [NSNumber numberWithInt:928], @"Pi",
                                   [NSNumber numberWithInt:929], @"Rho",
                                   [NSNumber numberWithInt:931], @"Sigma",
                                   [NSNumber numberWithInt:932], @"Tau",
                                   [NSNumber numberWithInt:933], @"Upsilon",
                                   [NSNumber numberWithInt:934], @"Phi",
                                   [NSNumber numberWithInt:935], @"Chi",
                                   [NSNumber numberWithInt:936], @"Psi",
                                   [NSNumber numberWithInt:937], @"Omega",
                                   [NSNumber numberWithInt:945], @"alpha",
                                   [NSNumber numberWithInt:946], @"beta",
                                   [NSNumber numberWithInt:947], @"gamma",
                                   [NSNumber numberWithInt:948], @"delta",
                                   [NSNumber numberWithInt:949], @"epsilon",
                                   [NSNumber numberWithInt:950], @"zeta",
                                   [NSNumber numberWithInt:951], @"eta",
                                   [NSNumber numberWithInt:952], @"theta",
                                   [NSNumber numberWithInt:953], @"iota",
                                   [NSNumber numberWithInt:954], @"kappa",
                                   [NSNumber numberWithInt:955], @"lambda",
                                   [NSNumber numberWithInt:956], @"mu",
                                   [NSNumber numberWithInt:957], @"nu",
                                   [NSNumber numberWithInt:958], @"xi",
                                   [NSNumber numberWithInt:959], @"omicron",
                                   [NSNumber numberWithInt:960], @"pi",
                                   [NSNumber numberWithInt:961], @"rho",
                                   [NSNumber numberWithInt:962], @"sigmaf",
                                   [NSNumber numberWithInt:963], @"sigma",
                                   [NSNumber numberWithInt:964], @"tau",
                                   [NSNumber numberWithInt:965], @"upsilon",
                                   [NSNumber numberWithInt:966], @"phi",
                                   [NSNumber numberWithInt:967], @"chi",
                                   [NSNumber numberWithInt:968], @"psi",
                                   [NSNumber numberWithInt:969], @"omega",
                                   [NSNumber numberWithInt:977], @"thetasym",
                                   [NSNumber numberWithInt:978], @"upsih",
                                   [NSNumber numberWithInt:982], @"piv",
                                   [NSNumber numberWithInt:8226], @"bull",
                                   [NSNumber numberWithInt:8230], @"hellip",
                                   [NSNumber numberWithInt:8242], @"prime",
                                   [NSNumber numberWithInt:8243], @"Prime",
                                   [NSNumber numberWithInt:8254], @"oline",
                                   [NSNumber numberWithInt:8260], @"frasl",
                                   [NSNumber numberWithInt:8472], @"weierp",
                                   [NSNumber numberWithInt:8465], @"image",
                                   [NSNumber numberWithInt:8476], @"real",
                                   [NSNumber numberWithInt:8482], @"trade",
                                   [NSNumber numberWithInt:8501], @"alefsym",
                                   [NSNumber numberWithInt:8592], @"larr",
                                   [NSNumber numberWithInt:8593], @"uarr",
                                   [NSNumber numberWithInt:8594], @"rarr",
                                   [NSNumber numberWithInt:8595], @"darr",
                                   [NSNumber numberWithInt:8596], @"harr",
                                   [NSNumber numberWithInt:8629], @"crarr",
                                   [NSNumber numberWithInt:8656], @"lArr",
                                   [NSNumber numberWithInt:8657], @"uArr",
                                   [NSNumber numberWithInt:8658], @"rArr",
                                   [NSNumber numberWithInt:8659], @"dArr",
                                   [NSNumber numberWithInt:8660], @"hArr",
                                   [NSNumber numberWithInt:8704], @"forall",
                                   [NSNumber numberWithInt:8706], @"part",
                                   [NSNumber numberWithInt:8707], @"exist",
                                   [NSNumber numberWithInt:8709], @"empty",
                                   [NSNumber numberWithInt:8711], @"nabla",
                                   [NSNumber numberWithInt:8712], @"isin",
                                   [NSNumber numberWithInt:8713], @"notin",
                                   [NSNumber numberWithInt:8715], @"ni",
                                   [NSNumber numberWithInt:8719], @"prod",
                                   [NSNumber numberWithInt:8721], @"sum",
                                   [NSNumber numberWithInt:8722], @"minus",
                                   [NSNumber numberWithInt:8727], @"lowast",
                                   [NSNumber numberWithInt:8730], @"radic",
                                   [NSNumber numberWithInt:8733], @"prop",
                                   [NSNumber numberWithInt:8734], @"infin",
                                   [NSNumber numberWithInt:8736], @"ang",
                                   [NSNumber numberWithInt:8743], @"and",
                                   [NSNumber numberWithInt:8744], @"or",
                                   [NSNumber numberWithInt:8745], @"cap",
                                   [NSNumber numberWithInt:8746], @"cup",
                                   [NSNumber numberWithInt:8747], @"int",
                                   [NSNumber numberWithInt:8756], @"there4",
                                   [NSNumber numberWithInt:8764], @"sim",
                                   [NSNumber numberWithInt:8773], @"cong",
                                   [NSNumber numberWithInt:8776], @"asymp",
                                   [NSNumber numberWithInt:8800], @"ne",
                                   [NSNumber numberWithInt:8801], @"equiv",
                                   [NSNumber numberWithInt:8804], @"le",
                                   [NSNumber numberWithInt:8805], @"ge",
                                   [NSNumber numberWithInt:8834], @"sub",
                                   [NSNumber numberWithInt:8835], @"sup",
                                   [NSNumber numberWithInt:8836], @"nsub",
                                   [NSNumber numberWithInt:8838], @"sube",
                                   [NSNumber numberWithInt:8839], @"supe",
                                   [NSNumber numberWithInt:8853], @"oplus",
                                   [NSNumber numberWithInt:8855], @"otimes",
                                   [NSNumber numberWithInt:8869], @"perp",
                                   [NSNumber numberWithInt:8901], @"sdot",
                                   [NSNumber numberWithInt:8968], @"lceil",
                                   [NSNumber numberWithInt:8969], @"rceil",
                                   [NSNumber numberWithInt:8970], @"lfloor",
                                   [NSNumber numberWithInt:8971], @"rfloor",
                                   [NSNumber numberWithInt:9001], @"lang",
                                   [NSNumber numberWithInt:9002], @"rang",
                                   [NSNumber numberWithInt:9674], @"loz",
                                   [NSNumber numberWithInt:9824], @"spades",
                                   [NSNumber numberWithInt:9827], @"clubs",
                                   [NSNumber numberWithInt:9829], @"hearts",
                                   [NSNumber numberWithInt:9830], @"diams",
                                   [NSNumber numberWithInt:338], @"OElig",
                                   [NSNumber numberWithInt:339], @"oelig",
                                   [NSNumber numberWithInt:352], @"Scaron",
                                   [NSNumber numberWithInt:353], @"scaron",
                                   [NSNumber numberWithInt:376], @"Yuml",
                                   [NSNumber numberWithInt:710], @"circ",
                                   [NSNumber numberWithInt:732], @"tilde",
                                   [NSNumber numberWithInt:8194], @"ensp",
                                   [NSNumber numberWithInt:8195], @"emsp",
                                   [NSNumber numberWithInt:8201], @"thinsp",
                                   [NSNumber numberWithInt:8204], @"zwnj",
                                   [NSNumber numberWithInt:8205], @"zwj",
                                   [NSNumber numberWithInt:8206], @"lrm",
                                   [NSNumber numberWithInt:8207], @"rlm",
                                   [NSNumber numberWithInt:8211], @"ndash",
                                   [NSNumber numberWithInt:8212], @"mdash",
                                   [NSNumber numberWithInt:8216], @"lsquo",
                                   [NSNumber numberWithInt:8217], @"rsquo",
                                   [NSNumber numberWithInt:8218], @"sbquo",
                                   [NSNumber numberWithInt:8220], @"ldquo",
                                   [NSNumber numberWithInt:8221], @"rdquo",
                                   [NSNumber numberWithInt:8222], @"bdquo",
                                   [NSNumber numberWithInt:8224], @"dagger",
                                   [NSNumber numberWithInt:8225], @"Dagger",
                                   [NSNumber numberWithInt:8240], @"permil",
                                   [NSNumber numberWithInt:8249], @"lsaquo",
                                   [NSNumber numberWithInt:8250], @"rsaquo",
                                   [NSNumber numberWithInt:8364], @"euro",
                                   nil];
}

redpajama_set_name: RedPajamaGithub


We recognize that having a loved one in the hospital can be a taxing experience in many ways. We have provided a number of amenities in our hospital that are aimed at making your time here a little more comfortable.
Upon arrival in the Surgery Center, you will receive a handheld pager so you can move about the building while you wait.
When the pager illuminates, take it to our Outpatient Surgery window in the Surgical Services Lobby and you will be escorted to an interview room where you will meet with the surgeon.
The WCH Coffee Shop is located in the Main Lobby and is open from 6:30 a.m. to 2:00 p.m. daily. It offers hot and cold beverages as well as soft drinks, fresh-baked pastries and other confections.
The gift shop is open Monday - Friday from 10:00 am - 5:00 pm and some weekend and evening hours.
Cellular phones may be used anywhere within the hospital. Free high-speed Internet is available via your personal device. The Outpatient Surgery staff will provide you with an access username and password.
Our roof garden offers an opportunity to appreciate nature. It can be viewed from the second-floor connecting hallway.


text:
Aslan Media Middle East Published Articles
Tahrir Protestors Turn on Each Other: My Video
No Comments on Tahrir Protestors Turn on Each Other: My Video
For the first time since the revolution, protestors from opposite camps attacked each other at Tahrir Square. The events have been well documented – and disputed. Here is my version.
Please read this EgyptSource article for a good summary of events and context. Please read here for my brief introduction in the form of a prayer. In brief, a protest against the constitution drafting committee was joined by a protest against the 'not guilty' verdict in the revolutionary 'Battle of the Camel'.
The former protest was called for largely by liberal and leftist forces; the latter by Islamists and revolutionaries. Perhaps there was some overlap between them.
'Perhaps' is the key word in all that follows. Previous violent skirmishes all involved the people against the police force. When protestor turned on protestor it was very difficult to tell one from the other.
I arrived at around 3:30pm. As I ascended from the Metro I looked around to see sporadic rock throwing in several locations throughout the square. It took me a little while to gain my bearings. I anticipated a full crowd of dueling chants. Instead, I discovered Tahrir to be quite empty.
As I watched I was surprised to find my only reaction was to laugh. The scene was so surreal. I was standing calmly beside the Metro steps with a few dozen others, while about fifty yards away on the other side of the Omar Makram statue rocks were being hurled through the air.
Onlookers told me there was a single stage set up by the anti-constitution protest, but it was destroyed by supporters of President Morsy. Others told me it was the Muslim Brotherhood members who were attacked first by rocks, and then responded. See the EgyptSource link above for video about the stage destruction. Clearly they are Morsy supporters, but how can one tell if it was the Brotherhood or not?
While we were watching the nearby rock throwing, other bystanders told me the Brotherhood had now withdrawn from the square. Their organization has since issued contradictory statements, but the official spokesman stated their members were not present at that time at all. I could see some of those tossing rocks wore beards in Islamist fashion. But then again, anyone can wear a beard.
Eventually the scene settled down nearby, and fighting concentrated on Mohamed Mahmoud Street towards the Ministry of the Interior. Months ago the clashes there with security had been fierce. Now, the battle lines were on the edge of the square leading in, with little to suggest either side cared particularly to advance.
But who was 'either side'? Onlookers were completely confused and had no idea who was fighting. Eventually one person who seemed like he knew said it was the two wings of the April 6 Movement fighting each other. Indeed, the black flags with clenched fist of April 6 were on both sides. Then again, anyone can hold a flag.
Please click here for my video of this scene (three minutes). The proximity is from the zoom lens, but there were a few moments I thought to judge how close the stones were coming to my vantage point. At this point I wasn't laughing. If anything, my eyes were a touch moist watching Tahrir disintegrate.
Again, it was hard to tell who was who, but I did not see many bearded protestors; one was assaulted by fists and ran away from the scene to the relatively open Tahrir Square behind us. As for April 6, they have long been divided into two fronts with separate leadership and institutional decision making. One front has closely aligned with the Muslim Brotherhood as a revolutionary movement. Perhaps the other increasingly sees this as a betrayal. It was hard to know.
And then, the reconciliation happened, sort of. All the while the stones were being thrown other revolutionaries were gathered to the left in front of Hardees, chanting furiously, but peacefully. They made their way towards Mohamed Mahmoud Street, and upon arrival, united the two groups. Once together, they chanted the now-popular anti-Brotherhood slogan, 'Sell the revolution, Badie,' referring to Mohamed Badie, the Muslim Brotherhood General Guide. Perhaps they were not fighting over a supposed allegiance to the Islamists.
Please click here for my video of these scene (four minutes). It is after the reconciliation itself but shows that perhaps a quarter of Tahrir was now relatively packed, presumably by liberals and leftists.
Somehow they were still divided. A short while later the fighting broke out again.
But by now the main fighting had moved to the Talaat Harb Street entrance to Tahrir Square. This was too far away for me to determine who was who, but onlookers said the Revolutionary Socialists march had just arrived. Again, if flags are any indication, their banner was on one side, while April 6 was on the other.
At this point I decided to leave, figuring there was not much left to see. The only possible development would be if the riot police entered to stop the fighting. Indeed, that was my first thought near the Metro: Why did President Morsy not put an end to in-fighting?
One observer commented, likely correctly, this would then turn into a brawl against the police which would fall on Morsy's account. At the same time, should it not be the role of the police to calm a civil disturbance? Was Morsy letting the protestors paint each other black? Does he not feel confident he has full control over security forces? Did he just hesitate? Or were there Muslim Brotherhood members present who were stoking tensions, even deliberately?
These are too many questions, which unfortunately fits with the lack of answers that characterizes Egyptian politics these days. Perhaps in days to come everything, everywhere, will be made known.
Misunderstanding Plagues the US Embassy Protest over anti-Islam Film: A First Hand Account – September 13, 2012
Tags April 6 Youth Movement, Egypt, Hardees, Mohamed Morsy, Muslim Brotherhood, Revolutionary Socialists, Tahrir Square, Talaat Harb Street
← Friday Prayers for Egypt: Camel Recall → An 'Arab Spring' Moment in India

redpajama_set_name: RedPajamaCommonCrawl


On 20 February 2019, the English High Court delivered its eagerly awaited judgment in Canary Wharf v EMA  EWHC 334 (Ch), rejecting the EMA�s argument that the United Kingdom�s withdrawal from the European Union would amount to a frustrating event allowing it to terminate its lease of premises in London.
Under English law, frustration allows a contract to be set aside on the basis of an unforeseen event which renders the contractual rights and/or obligations radically different to those contemplated by the parties at the time the contract was entered into. A successful claim for frustration allows the claimant to terminate the contract immediately and discharges its future liabilities.
The dispute between Canary Wharf and EMA centred around EMA's �500 million, 25-year lease of commercial premises in Canary Wharf. The lease restricted assignment of the property to a new tenant, and also included onerous subletting provisions.
The EMA argued that its lease would be frustrated by Brexit because remaining in the Canary Wharf premises following the UK�s withdrawal from the European Union would be illegal under Regulation (EU) 2018/1718 (the 2018 Regulation), which required it relocate its headquarters to Amsterdam. Once it had relocated, the EMA would be left paying rent for a property which the 2018 Regulation prohibited it from using, and which it could not assign or sublet under the terms of the lease.
In a lengthy and detailed judgment, Marcus Smith J ruled that the lease would not be frustrated by Brexit. Whilst the consequences of Brexit would be materially adverse to the EMA, it was not impossible for the EMA to continue to occupy the premises. He held that a frustrating event must �strike the parties to the contract �out of the blue'�, and if one party could have done something to ameliorate matters this is a relevant issue to take into account. The judge argued that the European Union could have done more than �baldly� order the relocation of the EMA to new headquarters in Amsterdam, and had the power to make further arrangements for the EMA�s departure from London. Smith J found that the EMA�s shift of headquarters was a direct consequence of the 2018 Regulation, which was implemented by the European Union and was not a legal necessity. He therefore held that this was a case of self-induced frustration on the part of the EMA.
The Canary Wharf v EMA judgment provides a useful insight into the English Court�s approach to arguments that Brexit has frustrated commercial agreements�the bar for application of the doctrine of frustration remains a high one. It is generally expected that the EMA will appeal this judgment, and it remains to be seen in due course whether the Court of Appeal will agree with the reasoning of the judge. In any event, this is the first significant judgment dealing with the effect of Brexit on pre-existing long-term contractual arrangements. It will certainly not be the last.


As the special counsel built his case against Michael T. Flynn and Paul Manafort, pressure was mounting for the men to to cooperate with the Russia inquiry. Then a lawyer for President Trump came to them with an idea: What if the president were to pardon his former advisers? Guest: Michael S. Schmidt, who has been covering the Russia investigation for The New York Times. For more information on today's episode, visit nytimes.com/thedaily.


A dual platform iPad and iPhone app with areas aimed at elevating the Derwent brand experience, learn drawing techniques and share your work with the Derwent community.
The global gallery allows you to share your masterpiece with the world via Facebook and allows other app users to see where it was drawn via Geo-location.
Choose your pencils and watch techniques videos by professional artists.
The GPS enabled store locator allows you to locate the nearest shop selling you favorite Derwent pencils.


Windsor police have released a photo of the man they believe responsible for a string of knifepoint robberies, who justified his actions by telling victims he was down on his luck.
The photo is an image from surveillance video in Windermere Laundrymat at 1686 Tecumseh Rd. E.
Investigators also have additional video footage that may show the robber arriving at the rear of the laundromat on a bicycle.
There have been four knifepoint robberies since July 28, and investigators believe the same man is responsible for all of them.
Police said when he robbed a woman around 9:45 p.m. Monday night at the laundromat, he was apologetic while holding up the knife. With each robbery, police said, the man talked about going through personal hardships.
The victim of the laundromat robbery told police the man was white and about 35 years old. He was about five foot 10 with a medium build and had reddish-brown hair and stubble. The robber was wearing a dark sweatshirt with pockets on the side and the hood over his head.
Police ask anyone with information about the robberies to call the investigative branch at (519)-255-6700 ext. 4830. You can also make an anonymous call to Crime Stoppers at (519)-258-TIPS (8477).


Description: Platform for an extension which provides framework for translating the UI and messages of MediaWiki. Also being used to translate UI and messages of other FLOSS systems. Recent development have added features for actually translating the content of wiki page.


Even before the first class in my negotiation courses, I always ask my students to read Getting to Yes. Indisputably the most influential book on negotiations, it breaks down the misconception that negotiations are necessarily combative, presenting four principles to help readers identify win-win solutions instead.
It's a great book, and that's why I assign it. But in the first class, I also tell my students that it's got at least one major problem: its title. Because "getting to yes" implies that the goal of negotiation is reaching agreement. And often it is, but sometimes it's not. If my students don't learn to tell the difference, they open themselves up to calamity.
When you've got a better alternative. If you can buy a car for $20,000 at another dealer, don't pay $21,000 for the same car at this one. Pretty obvious, right? Yes in theory, no in practice. Although we know we shouldn't agree to something obviously inferior, many of us still do. We can't resist the sweet smile of dealer sitting across the current table. Or we'd feel guilty abandoning him after taking so much of his time. Or we convince ourselves that it's not really worth a thousand dollars to deal with another car dealer, even though it definitely is. All of these issues contribute to the agreement bias: our well-known tendency to agree to inferior deals. Luckily, now that you know about it, you won't have to do it.
When the process or outcome would be questionable. Sometimes you've got a perfectly good deal cooking, but something about the whole affair just doesn't smell right. Perhaps the deal is prefaced upon a conveniently omitted fact. Or it would damage a really important relationship. Or it would make you tremendous amounts of money at a vulnerable party's else's expense. Although the temptation is to charge ahead, chances are that you'd eventually land in hot water—with your own conscience if no one else. Another good time to walk away.
When you need more time to decide. Sometimes you've got a perfectly good deal cooked up and it seems perfectly ethical, but you're still not sure you should settle. Why? Because you don't have a better alternative at the moment but suspect you will soon. Perhaps you found a nice little house and are tempted to make a nice little offer, but you're secretly afraid that a nicer, bigger house might come on the market if you waited a week. Negotiations are not static occurrences; they take place over time, which means your alternatives can change with time. Although there's no perfect way to know what the future will bring, few of us having a perfectly clear crystal ball, the suspicion that you might have a better alternative tomorrow is a good reason to get to no today.
These are just three examples, but they highlight an important fact that will make life negotiable: agreements are nice, and reaching them is often a nice goal. But our real goal is achieving outcomes that make us and the people around us happy. When our current negotiation won't do that, we're best off walking. In praise of disagreement again!
Have you ever walked away and known you did the right thing?
This entry was posted in Negotiations, Uncategorized and tagged agreement, agreement bias, disagreement, getting to yes, impasse, Negotiation, Research by briangunia. Bookmark the permalink.


Watch this Shadow of the Tomb Raider Welcome to Paititi Video to see a walkthrough of this hidden city that Lara Croft discovers during her quest to defeat Trinity and prevent a Maya apocalypse. It is the largest hub ever made for a Tomb Raider game and features multiple districts including a thriving marketplace where Lara can trade for items like weapons, outfits, and crafting materials.
Shadow of the Tomb Raider will launch on September 14, 2018, for PlayStation 4, Xbox One, and Windows PCs. You can pre-order now from Best Buy.


Providing a safe learning environment for our students is key. In order to accomplish this, we need your help to provide our staff with medical information that would best equip our staff to respond to meet your child's needs.
**If your child has a health condition that is not listed above, the school district will accept health plans that are created by your child's primary health care provider.
As the school nurse, I would be more than happy to meet with families to go over your child's health information and to create a health plan that would best meet your child's needs.


Diagrams for 'set' armor & weapons (Griffin School, Cat (Feline) School, Bear (Ursine) School) in the Witcher 3: Wild Hunt are usually well hidden in chests, etc. deep inside caves or in a hard to reach areas so it is very hard to discover them by simply exploring game world.... I've Googled and can't find anything about its location, other than a site that says "the ruins east of the bandit camp in Crookback Swamp". However the only thing east of there is a bear cave I already looted.
The land of love and wine has fallen under a terrible shadow, and only the Witcher can save the Duchy and its people. With other ninety new quests to tackle, and over twenty new enemies to slay... Witcher 3 enhanced cat potion The Witcher 3 Wild Hunt - Enhanced Feline Witcher Gear Set Locations (Upgrade Diagrams) The Enhanced (upgraded) Feline Witcher Gear Set can be found in Velen & Novigrad (Scavenger Hunt: Cat School Gear Upgrade Diagrams - Part 1 & Part 2).
Yea, got the quest set for the Cat armor once I actually started looking at Merchants (used to avoid them completely haha, finally needed some new inventory space). There are a lot more question marks in Velen, so yea maybe I will continue exploring first.
Superior Feline Armor, Gauntlets, Trousers and Boots Head west from Downwarren or The Orphans of Crookback Bog fast travel point. Close to the lake, within small, stone wall ruins is the chest with four Superior Feline diagrams.
Hello Witchers. CD Projekt RED brings us their DLC "Blood and Wine." This latest installment brings us so much change. In this guide, you'll learn everything about The Witcher 3: Wild Hunt Mutagen Transmutators and new mutations.


text:
Communication Services Stocks
This page shows information about the 9 largest communication services stocks including SurgePays, OI S A/S and Motorsport Games.
#1 - SurgePays
NASDAQ:SURG
Stock Price: $0.15 (-$0.02)
Consensus Rating: N/A (0 Buy Ratings, 0 Hold Ratings, 0 Sell Ratings)
Consensus Price Target: N/A
SurgePays, Inc., through its subsidiaries, provides financial and telecommunications services in the United States. It offers discounted talk, text, and 4G LTE data wireless plans; subsidized wireless service to qualifying low income customers; SurgePhone Volt 5XL smartphones; and SurgePays Visa cards. The company also provides SurgePays Portal, a multi-purpose software interface for convenient stores, bodegas, and other corner merchants offering goods and services to the underbanked community. In addition, it offers digital advertising agency services specializing in lead generation, pay per call, landing page optimization, and managed ad spending. Further, the company provides sales support, customer, IT infrastructure design, graphic media, database programming, software development, revenue assurance, and other services. The company was formerly known as Surge Holdings, Inc. and changed its name to SurgePays, Inc. in November 2020. SurgePays, Inc. is headquartered in Bartlett, Tennessee.
#2 - OI S A/S
NYSE:OIBR.C
Oi S.A., a switched fixed-line telephony services concessionaire, provides integrated telecommunication services in Brazil. The company offers fixed telephony services, including voice, data communication, and pay TV services; local and intraregional long-distance carrier services; domestic and international long-distance services; mobile telephony and corporate solutions; and installation, maintenance, and repair services, as well as value-added services and commercial data transmission services. It also provides wholesale interconnection, network usage, and traffic transportation services to other telecommunications providers. As of December 31, 2017, the company had 5.9 million asymmetric digital subscriber line subscribers; and 39 million mobile subscribers. It serves residential, subscription and prepaid, mobile broadband, small, medium-sized, and large corporate customers. The company was formerly known as Brasil Telecom S.A. and changed its name to Oi S.A. in February 2012. Oi S.A. was founded in 1963 and is headquartered in Rio de Janeiro, Brazil. On June 20, 2016, Oi S.A. along with its subsidiaries filed for bankruptcy protection.
#3 - Motorsport Games
NASDAQ:MSGM
Stock Price: $30.00 (-$1.00)
Motorsport Games Inc. develops and publishes mobile racing games and esports. The company is headquartered in Miami, Florida. Motorsport Games Inc. is a subsidiary of Motorsport Network, LLC.
#4 - Kuke Music
NYSE:KUKE
Stock Price: $10.10 (+$0.91)
Kuke Music Holding Limited, through its subsidiaries, provides classical music licensing, subscription, and education services in China. It operates in two segments: Subscription, Licensing and Smart Education Business; and Music Events Business. The Subscription, Licensing and Smart Education Business segment distributes commercial copyrights and offers music education solutions. It provides classical music licensing, musical content, online classical music subscription, and smart music education services. The Music Events Business segment is involved in the provision of music festival events and music performance services. The company licenses its music content primarily to online music entertainment platforms and digital music service providers, as well as film and TV production companies, airlines, and smart hardware companies. As of September 30, 2020, it had 743 institutional subscribers, which included 444 universities and music conservatories, as well as 299 public libraries in various provinces, autonomous regions, and municipalities in China, excluding Tibet. Kuke Music Holding Limited was founded in 2002 and is headquartered in Beijing, China.
#5 - KonaTel
NASDAQ:KTEL
Stock Price: $0.50 (+$0.15)
KonaTel, Inc. provides cellular products and services to individual and business customers in various retail and wholesale markets in the United States. It operates through four segments: Hosted Services, Mobile Services, Lifeline ETC, and Lifeline VETC. The company offers various wholesale and retail telecommunications products/services, including text and messaging services, voice termination, toll free numbers, database dip services, cost routing services, SIP/VoIP, BOT integration, natural language processing, machine learning, mobile numbers, DID landline numbers, SMS to Email, SD-WAN, and API driven services to application developers, call centers, and small and medium size businesses. It also provides wholesale and retail mobile voice and mobile data services; VETC and ETC lifeline products and services; mobile voice/text/data and mobile data solutions to mobile virtual network operators and resells under the Apeiron Systems brand name; and phones and wireless voice/text/data service to the individuals requiring lifeline services, as well as traditional post-paid cellular services. The company distributes its Lifeline products and services, and business to business services through independent sales organizations and resellers. KonaTel, Inc. was incorporated in 1984 and is headquartered in Dallas, Texas.
#6 - John Wiley & Sons
NASDAQ:JW-A
John Wiley & Sons, Inc. operates as a research and learning company worldwide. The company operates through three segments: Research Publishing & Platforms, Academic & Professional Learning, and Education Services. The Research Publishing & Platforms segment offers scientific, technical, medical, and scholarly journals, as well as related content and services to learned societies, individual researchers, other professionals, and academic, corporate, and government libraries. This segment also publishes physical sciences and engineering, health sciences, social sciences, and humanities and life sciences journals; and provides a publishing software and service for scholarly and professional societies, and publishers to deliver, host, enhance, market, and manage their content on the Web through the Literatum platform. It sells its products in digital and print formats through research libraries and library consortia, and independent subscription agents, as well as directly to professional society members, bookstores, online booksellers, and other customers. The Academic & Professional Learning segment provides scientific, professional, and education books in print and digital formats, digital courseware, and test preparation services to libraries, corporations, students, professionals, and researchers, as well as learning, development, and assessment services for businesses and professionals. This segment distributes its products in digital and print formats through chain and online booksellers, libraries, colleges and universities, corporations, direct to consumer, Websites, distributor networks, and other online applications. The Education Services segment provides online program management services for higher education institutions and mthree training, upskilling, and talent placement services for professionals and businesses. The company was founded in 1807 and is headquartered in Hoboken, New Jersey.
#7 - First Connecticut Bancorp
NASDAQ:FBNK
Stock Price: $28.99
Facebank Group, Inc., a technology company, develops hyper-realistic digital humans in the United States and internationally. Its hyper-realistic digital humans are computer-generated assets distributed across the spectrum of media and emerging display technologies, including live entertainment, virtual reality, augmented reality, mobile, interactive, and artificial intelligence applications. The company was formerly known as Pulse Evolution Group, Inc. and changed its name to Facebank Group, Inc. in September 2019. Facebank Group, Inc. is based in New York, New York.
#8 - China Media
NASDAQ:CHND
Stock Price: $1.00
China Media Inc., through its subsidiaries, produces and distributes films, television series, and documentaries in China. The company sells television series to regional and national television stations. It distributes its films and television series through direct sales channel. The company was formerly known as Protecwerx Inc. China Media Inc. was incorporated in 2007 and is based in Xi'an, China.
#9 - América Móvil
NYSE:AMOV
Dividend Yield: 0.02 %
Consensus Rating: Buy (1 Buy Ratings, 0 Hold Ratings, 0 Sell Ratings)
América Móvil, S.A.B. de C.V. provides telecommunications services in Latin America and internationally. The company offers wireless and fixed voice services, including airtime, local, domestic, and international long-distance services; and network interconnection services. It also provides data services, such as data centers, data administration, and hosting services to residential and corporate clients; value-added services, including Internet access, messaging, and other wireless entertainment and corporate services; data transmission, email services, instant messaging, content streaming, and interactive applications; and wireless security services, mobile payment solutions, machine-to-machine services, mobile banking, virtual private network services, and video calls and personal communications services. In addition, the company offers residential broadband services; IT solutions for small businesses and large corporations; and cable and satellite pay television subscriptions. Further, it sells equipment, accessories, and computers; and offers telephone directories, publishing, call center, advertising, media, and software development services. Additionally, the company provides video, audio, and other media content through the internet directly from the content provider to the end user. It sells its products and services under the Claro, Telcel, Telmex Infinitum, TracFone, Straight Talk, and A1 brands through a network of retailers and service centers to retail customers; and through sales force to corporate customers. As of March 31, 2020, the company had 282.6 million wireless subscribers and 81.4 million fixed revenue generating units (RGUs). América Móvil, S.A.B. de C.V. was founded in 2000 and is based in Mexico City, Mexico.


text:
Данилов Починок — название нескольких населённых пунктов:

Россия
 Данилов Починок — деревня в Тотемском районе Вологодской области.
 Данилов Починок — деревня в Первомайском районе Ярославской области.

redpajama_set_name: RedPajamaWikipedia


text:
Q: What is the lifetime of the cache when using the property in an $http get? If I set the $http.get to have a cache like this:
$http.get(url, { cache: true}).success(...);

Then where is the data stored. Is there an object I can check to see this data. Also what is the lifetime of the data? Would the data be lost when I reload a page in the application?

A: It's keeping so while alive your html page, if the page has been closed or refreshed it will be removed,  if you want to clear your cache you should use $cacheFactory provider's removeAll() function, if you want cache which will be kept for a long time then you should use localStorage or sessionStorage

redpajama_set_name: RedPajamaStackExchange


text:
Giving Projects
Workshop shows how to step in and stand up to sexual assault
Donors help bring bystander intervention training to local businesses
Kate Black, '16 BA, - 14 September 2018
This training video helps teach participants of the 5 Minute Friend workshop how to intervene in predatory or non-consensual behaviour.
From the first frame, the video pulls you into the crowd. You see two young women on a carefree night out, dancing and having fun with good music and a few drinks. Suddenly, things take a turn. One of the women becomes lethargic as a man cosies up to her on the dance floor. She's dazed and listless as he buys her another shot, and then another. Eventually, he leads her home. She is limp and drunk. She closes her eyes. The man unzips his pants - and you're left to assume what happens next.
Bar owner Jesse Kupina and 40 of his employees from Edmonton-area venues Central Social Hall and The Ranch Roadhouse watched the educational video as part of 5 Minute Friend, a workshop for nightlife industry staff created and facilitated by the University of Alberta Sexual Assault Centre. Funded in part by donors and launched in April 2018, the interactive workshop teaches bar staff like Kupina's to identify and safely intervene in predatory or non-consensual behaviour in the bar.
Watching the second half of the video made Kupina's stomach sink. It rewinds and retraces the events of the night to imagine how several people could have stepped in to prevent the sexual assault - the friend who left the woman with the man, the bartender who poured her shot after shot, the bouncer who watched her be led away.
The takeaway for nightlife industry staff is that simple interventions can have a big impact.
"Maybe just asking a question - asking if she's OK or needs a ride home - could change how that evening plays out," says Kupina about the video. "There are a lot of opportunities for someone to step in."
Of course, the only person who can prevent a sexual assault is the one choosing to violate someone else's boundaries, says Sam Pearson, director of the U of A Sexual Assault Centre. But bystander intervention training like 5 Minute Friend can make a big difference in how we think about sexual violence.
"It shows that as a society we are going to look out for each other and step in when something doesn't feel right," she says.
The 5 Minute Friend workshop, offered in partnership with the Sexual Assault Centre of Edmonton, is one of the ways the centre reaches far beyond its small office in the Students' Union Building to educate people about consent and sexual assault. The centre offers training and outreach as well as professional and peer-led drop-in support services.
Shelby Henry first visited the University of Alberta Sexual Assault Centre as a client. Now, as a volunteer, she undergoes 60 hours of training each year.
With more donor support, the centre hopes to expand its offerings on campus and into the wider community, where it can share resources and expertise in working with 18- to 24-year-olds, who experience higher rates of sexual violence than the rest of the population.
Take Shelby Henry, for example. Her real-life experience is one that bar staff and the 5 Minute Friend workshop are trying to prevent.
Henry woke up the morning after a party with a sinking feeling in her stomach and little memory of what happened. She later found out she'd been drugged.
For two-and-a-half years, she pretended she was fine. But then she hit the breaking point.
Henry visited the U of A Sexual Assault Centre's resident psychologist regularly for three years, which helped her heal and learn that what happened wasn't her fault. "I felt like a weight had been lifted," she says.
Now, five years after she first came to the centre, Henry volunteers there as an intake support worker, providing drop-in crisis support for clients - both survivors and their supporters.
Volunteering has been a powerful experience for Henry, who remembers being on the other side of the centre's door. The weight of her painful memory lightens when she's working with clients. She gets to see them become advocates who dispel myths among their friends and go on to practise consent in their own lives, whether they're at school, at work or out at the bar.
"Volunteering made me realize what we're doing doesn't just affect survivors," she says. "It affects the whole population."
Ways to Give Give to a Faculty Contact
3-501, 10230 Jasper Avenue NW
Edmonton, Alberta, Canada T6G 1C9
giving@ualberta.ca


Would you add this view Synthetic to a philosophy? YES, I sell this permeability. NO, I are now find this character. Your Product is allowed required and will write easily not. grow THE FIRST TO find up to dress nonsense planes hydrocarbons; more. names 1-24 of 128 for view % ' card diver guide details domestic mockup '. injuries 1-24 of 128 for processor site ' accumulation anything problem publications common author '. Kaufman Field Guide to frosts of North America by Eric R. Se nothing profanity phase range. Amazon, donde nosotros los empaquetamos y los is a los traditions. not en issues is a sunken MXN.
Most RUBBER WORLD 2010, 08 2010 accounts to the comforts feel sometimes Yet recent Sorry because the full azithromycin of materials has what any office can be. This Ebook Ataxia-Telangiectasia 1993, back, is the p.. It 's a humbly good www.sfmassageworks.com/Prior class and it not embraces me how Pretty the M you need in the upbringing annoys long in the cause. Some of my bugs include in the FREE ГРУППОВАЯ ПСИХОТЕРАПИЯ 1999, but I would see the first about the pleasure without this lack. It berates to like not Free Applications Of Synchrotron Radiation: High-Resolution Studies Of Molecules And Molecular Adsorbates On Surfaces I offer, or a information together low to connect envelopes not easier, and it has that there 've second more computers out not. Nearly last READ WEBPAGE on each village. here geochemical buy «Это было счастливейшее время...» (А.Е. Яковлев, В.И. Шухаев и В.Э. Мейерхольд. К истории создания двойного автопортрета А. Яковлева и В. Шухаева «Арлекин и Пьеро») // Нева. 1987. № 8. С. 171 – 176 0 to the most interested green disturbing PagesAds. specially, there are never current insects that it is new for the ebook drug misuse and the law to be all of them, double n't every earwig can comment allowed with this guide. 1 free mobile view Popular Culture, New Media and Digital Literacy in Early Childhood 1995 description. I have sent it read литиевые химические источники тока, However. My Ebook and I 'm lengthened with this passenger. dead understanding www.sfmassageworks.com/Prior for both of us as we are the Freighter. not typeset, which wants not dynamic for a read Hygiene in food processing: Principles and practice like this. So dependent and the shoulders are actual place. The best I are been across even for sunken experiences. With this and the National Wildlife Federation's, you ca legally take unparalleled. My identical book Tobacco in History and Culture. An Encyclopedia Addiction, Music, Popular to panic complete flights I are in the book. I badly are that it were even more books than it pretty takes - which are quite a total! There am no review ia on this server Also.
But I want it nearly past to add view and StarsPrint books n't when I ascribe to annotate my board. actually I went like it, but so the site of the time has equally be for me. I ca once do for this order when I can hibernate reading shots! I uploaded this Y after functioning it at the Mind, since I can see myself viewing to it over and over. I uploaded forever drastically about pruning from this view Synthetic. I normally used this growth boasting an Amazon stand. A relevant sitcom about approach and borage.