text:
NSString * const MSPCallIncomingNotification = @"com.peter.MSPCallIncomingNotification";
NSString * const MSPCallAnswerNotification = @"com.peter.MSPCallAnswerNotification";
NSString * const MSPCallhangupNotification = @"com.peter.MSPCallhangupNotification";

NSString * const MSPPjsuaQueueName = @"com.peter.MSPPjsuaQueueName";

@interface MSPMyPjsuaManager () {
    pj_pool_t *appPool;
    pj_pool_t *tmpPool;
}

@property (assign, nonatomic, readwrite) MSPMyPjsuaManagerStatus status;
@property (strong, nonatomic) MSPPjsuaSipAccount *currentSipAccount;
@property (strong, nonatomic, readwrite) MSPPjsuaCall *currentCall;

@property (strong, nonatomic) NSMutableDictionary *calls;
@property (strong, nonatomic) dispatch_queue_t pjsuaQueue;

@end

@implementation MSPMyPjsuaManager

+ (instancetype)sharedManager {
    static id instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[self alloc] init];
    });

    return instance;
}

- (instancetype)init {
    self = [super init];

    if (self) {
        self.status = MSPMyPjsuaManagerStatusNone;
        self.calls = [[NSMutableDictionary alloc] init];

        //Create queue for pjsua to run.
        //self.pjsuaQueue = dispatch_queue_create([MSPPjsuaQueueName UTF8String], NULL);
    }

    return self;
}

- (void)dealloc {
    [self releasePjsua];
}

- (void)releasePjsua {
    pjsua_call_hangup_all();
    if (appPool) {
        pj_pool_release(appPool);
        appPool = nil;
    }
    if (tmpPool) {
        pj_pool_release(tmpPool);
        tmpPool = nil;
    }
    pjsua_destroy();

    self.status = MSPMyPjsuaManagerStatusNone;
    self.currentSipAccount = nil;
    [self.calls removeAllObjects];
}

#pragma mark - Easy connect APIs

- (void)loginWithConfig:(MSPPjsuaConfig *)pjsuaConfig accountConfig:(MSPPjsuaSipAccount *)accountConfig {
    if ((self.status & MSPMyPjsuaManagerStatusInitedPjsua) ||
        (self.status & MSPMyPjsuaManagerStatusStartedPjsua)) {
        //If pjsua has been init or running, release it and create new one;
        [self releasePjsua];
    }

    MSPMyPjsuaManagerResult result = MSPMyPjsuaManagerResultSuccess;

    result = [self initPjsua:pjsuaConfig];
    if (result != MSPMyPjsuaManagerResultSuccess) {
        return;
    }

    result = [self initPjsuaTransport:pjsuaConfig];
    if (result != MSPMyPjsuaManagerResultSuccess) {
        return;
    }

    result = [self startPjsua];
    if (result != MSPMyPjsuaManagerResultSuccess) {
        return;
    }

    result = [self registerSipServer:accountConfig];
}

- (void)logout {
    [self releasePjsua];
}

#pragma mark - PJSUA Process Method

- (MSPMyPjsuaManagerResult)initPjsua:(MSPPjsuaConfig *)pjsuaConfig {
    if ((self.status & MSPMyPjsuaManagerStatusInitedPjsua) ||
        (self.status & MSPMyPjsuaManagerStatusStartedPjsua)) {
        NSLog(@"\n\nPjsua is inited or running!!\n\n");
        return MSPMyPjsuaManagerResultSuccess;
    }

    pj_status_t status;

    //Create pjsua.
    status = pjsua_create();
    if (status != PJ_SUCCESS) {
        NSLog(@"\n\nStatus ID : %d - Error in pjsua_create()\n\n", status);
        [self releasePjsua];
        return MSPMyPjsuaManagerResultCreatePjsuaError;
    }

    //Create pool for application.
//    appPool = pjsua_pool_create("pjsua-app", 1000, 1000);
//    tmpPool = pjsua_pool_create("pjsua-tmp", 1000, 1000);

    //Set up configs.
    pjsua_config cfg;
    pjsua_logging_config log_cfg;

    //Set to default.
    pjsua_config_default(&cfg);

    //Init pjsua callbacks.
    cfg.cb.on_call_state                    = &on_call_state;
    cfg.cb.on_incoming_call                 = &on_incoming_call;

    cfg.cb.on_call_media_state              = &on_call_media_state;
//    cfg.cb.on_call_sdp_created              = &on_call_sdp_created;
//    cfg.cb.on_call_tsx_state                = &on_call_tsx_state;
//
//    cfg.cb.on_stream_created                = &on_stream_created;
//    cfg.cb.on_stream_destroyed              = &on_stream_destroyed;
//
//    cfg.cb.on_dtmf_digit                    = &on_dtmf_digit;
//
//    cfg.cb.on_call_transfer_request         = &on_call_transfer_request;
//    cfg.cb.on_call_transfer_request2        = &on_call_transfer_request2;
//    cfg.cb.on_call_transfer_status          = &on_call_transfer_status;
//
//    cfg.cb.on_call_replace_request          = &on_call_replace_request;
//    cfg.cb.on_call_replace_request2         = &on_call_replace_request2;
//    cfg.cb.on_call_replaced                 = &on_call_replaced;
//
//    cfg.cb.on_call_rx_offer                 = &on_call_rx_offer;
//
//    cfg.cb.on_reg_started                   = &on_reg_started;
//    cfg.cb.on_reg_state                     = &on_reg_state;
//    cfg.cb.on_reg_state2                    = &on_reg_state2;
//
//    cfg.cb.on_incoming_subscribe            = &on_incoming_subscribe;
//    cfg.cb.on_srv_subscribe_state           = &on_srv_subscribe_state;
//
//    cfg.cb.on_buddy_state                   = &on_buddy_state;
//    cfg.cb.on_buddy_evsub_state             = &on_buddy_evsub_state;
//
//    cfg.cb.on_pager                         = &on_pager;
//    cfg.cb.on_pager2                        = &on_pager2;
//    cfg.cb.on_pager_status                  = &on_pager_status;
//    cfg.cb.on_pager_status2                 = &on_pager_status2;
//
//    cfg.cb.on_typing                        = &on_typing;
//    cfg.cb.on_typing2                       = &on_typing2;
//
//    cfg.cb.on_nat_detect                    = &on_nat_detect;
//
//    cfg.cb.on_call_redirected               = &on_call_redirected;
//
//    cfg.cb.on_mwi_state                     = &on_mwi_state;
//    cfg.cb.on_mwi_info                      = &on_mwi_info;
//
//    cfg.cb.on_transport_state               = &on_transport_state;
//    cfg.cb.on_call_media_transport_state    = &on_call_media_transport_state;
//    cfg.cb.on_ice_transport_error           = &on_ice_transport_error;
//    cfg.cb.on_snd_dev_operation             = &on_snd_dev_operation;
//
//    cfg.cb.on_call_media_event              = &on_call_media_event;
//    cfg.cb.on_create_media_transport        = &on_create_media_transport;
//    cfg.cb.on_acc_find_for_incoming         = &on_acc_find_for_incoming;

    //Set logging config to default.
    pjsua_logging_config_default(&log_cfg);
    log_cfg.console_level = [pjsuaConfig.consoleLevel unsignedIntValue];
    log_cfg.msg_logging = false;

    //Init pjsua
    status = pjsua_init(&cfg, &log_cfg, NULL);
    if (status != PJ_SUCCESS) {
        NSLog(@"\n\nStatus ID : %d - Error in pjsua_init()\n\n", status);
        [self releasePjsua];
        return MSPMyPjsuaManagerResultInitPjsuaError;
    }

    self.status |= MSPMyPjsuaManagerStatusInitedPjsua;
    return MSPMyPjsuaManagerResultSuccess;
}

- (MSPMyPjsuaManagerResult)initPjsuaTransport:(MSPPjsuaConfig *)pjsuaConfig {
    if (!(self.status & MSPMyPjsuaManagerStatusInitedPjsua)) {
        NSLog(@"\n\nError! pjsua not init, please init pjsua before init pjsua transport.\n\n");
        return MSPMyPjsuaManagerResultPjsuaNotInitedError;
    }

    if (self.status & MSPMyPjsuaManagerStatusStartedPjsua) {
        NSLog(@"\n\nPjsua is running!!\n\n");
        return MSPMyPjsuaManagerResultSuccess;
    }

    pj_status_t status;
    pjsua_transport_id transport_id = TRANSPORTID_NONE;

    //Init transport config structure
    pjsua_transport_config cfg;
    pjsua_transport_config_default(&cfg);
    cfg.port = [pjsuaConfig.transportProxy unsignedIntValue];

    pjsip_transport_type_e transportType;
    if (pjsuaConfig.transportype == MSPTransportTypeUDP) {
        transportType = PJSIP_TRANSPORT_UDP;
    }
    else if (pjsuaConfig.transportype == MSPTransportTypeTCP) {
        transportType = PJSIP_TRANSPORT_TCP;
    }

    //Add transport.
    status = pjsua_transport_create(transportType, &cfg, &transport_id);
    if (status != PJ_SUCCESS) {
        NSLog(@"\n\nStatus ID : %d - Error in pjsua_transport_create(%d)\n\n", status, transportType);
        [self releasePjsua];
        if (pjsuaConfig.transportype == MSPTransportTypeUDP) {
            return MSPMyPjsuaManagerResultCreateTransportUDPError;
        }
        else if (pjsuaConfig.transportype == MSPTransportTypeTCP) {
            return MSPMyPjsuaManagerResultCreateTransportTCPError;
        }
        else {
            return MSPMyPjsuaManagerResultCreateTransportError;
        }
    }

    if (transport_id == TRANSPORTID_NONE) {
        NSLog(@"\n\nStatus ID : %d - Error no transport is configured\n\n", TRANSPORTID_NONE);
        [self releasePjsua];
        return MSPMyPjsuaManagerResultCreateTransportError;
    }

    self.status |= MSPMyPjsuaManagerStatusInitedTransport;
    return MSPMyPjsuaManagerResultSuccess;
}

- (MSPMyPjsuaManagerResult)startPjsua {
    if (!(self.status & MSPMyPjsuaManagerStatusInitedPjsua) ||
        !(self.status & MSPMyPjsuaManagerStatusInitedTransport)) {
        NSLog(@"\n\nError! pjsua not init or transport not init, please init them before start pjsua.\n\n");
        return MSPMyPjsuaManagerResultPjsuaNotInitedError;
    }

    if (self.status & MSPMyPjsuaManagerStatusStartedPjsua) {
        NSLog(@"\n\nPjsua is running!!\n\n");
        return MSPMyPjsuaManagerResultSuccess;
    }

    pj_status_t status;

    //Initialization is done, now start pjsua
    status = pjsua_start();
    if (status != PJ_SUCCESS) {
        NSLog(@"\n\nStatus ID : %d - Error in pjsua_start()\n\n", status);
        [self releasePjsua];
        return MSPMyPjsuaManagerResultStartPjsuaError;
    }

    self.status |= MSPMyPjsuaManagerStatusStartedPjsua;
    return MSPMyPjsuaManagerResultSuccess;
}

- (MSPMyPjsuaManagerResult)registerSipServer:(MSPPjsuaSipAccount *)sipAccount {
    if (!(self.status & MSPMyPjsuaManagerStatusStartedPjsua)) {
        NSLog(@"\n\nError! pjsua not init, transport not init or not start, please init them before register sip server.\n\n");
        return MSPMyPjsuaManagerResultPjsuaNotInitedError;
    }

    if (self.currentSipAccount) {
        pjsua_acc_del([self.currentSipAccount.accountId intValue]);
        self.currentSipAccount = nil;
        self.status &= ~MSPMyPjsuaManagerStatusRegisterredSipServer;
    }

    pj_status_t status;
    pjsua_acc_config cfg;
    pjsua_acc_id pjsuaAccountId;

    pjsua_acc_config_default(&cfg);
    cfg.id = pj_str((char *)[[NSString stringWithFormat:@"sip:%@@%@", sipAccount.userName, sipAccount.domain] UTF8String]);
    cfg.reg_uri = pj_str((char *)[[NSString stringWithFormat:@"sip:%@", sipAccount.domain] UTF8String]);
    cfg.cred_count = 1;
    cfg.cred_info[0].realm = pj_str((char *)[sipAccount.realm UTF8String]);
    cfg.cred_info[0].scheme = pj_str((char *)[sipAccount.scheme UTF8String]);
    cfg.cred_info[0].username = pj_str((char *)[sipAccount.userName UTF8String]);
    cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
    cfg.cred_info[0].data = pj_str((char *)[sipAccount.password UTF8String]);

//    NSLog(@"\n\n----------------- cred_info -----------------");
//    NSLog(@"id : %s", cfg.id.ptr);
//    NSLog(@"reg_uri : %s", cfg.reg_uri.ptr);
//    NSLog(@"cred_count : %d", cfg.cred_count);
//    NSLog(@"cred_info[0].realm : %s", cfg.cred_info[0].realm.ptr);
//    NSLog(@"cred_info[0].scheme : %s", cfg.cred_info[0].scheme.ptr);
//    NSLog(@"cred_info[0].username : %s", cfg.cred_info[0].username.ptr);
//    NSLog(@"cred_info[0].data_type : %d", cfg.cred_info[0].data_type);
//    NSLog(@"cred_info[0].data : %s", cfg.cred_info[0].data.ptr);
//    NSLog(@"----------------- cred_info end -----------------\n\n");

    status = pjsua_acc_add(&cfg, PJ_TRUE, &pjsuaAccountId);
    if (status != PJ_SUCCESS) {
        NSLog(@"\n\nStatus ID : %d - Error in pjsua_start()\n\n", status);
        self.currentSipAccount = nil;
        return MSPMyPjsuaManagerResultRegisterSipServerError;
    }

    //Connect success, clear password and add into manager.
    sipAccount.password = @"";
    sipAccount.accountId = @(pjsuaAccountId);
    self.currentSipAccount = sipAccount;

    self.status |= MSPMyPjsuaManagerStatusRegisterredSipServer;
    return MSPMyPjsuaManagerResultSuccess;
}

- (MSPMyPjsuaManagerResult)makeCall:(MSPPjsuaCall *)call {
    if (!(self.status & MSPMyPjsuaManagerStatusStartedPjsua)) {
        NSLog(@"\n\nError! pjsua not init, transport not init or not start, please init them before register sip server.\n\n");
        return MSPMyPjsuaManagerResultPjsuaNotInitedError;
    }

    if (!(self.status & MSPMyPjsuaManagerStatusRegisterredSipServer)) {
        NSLog(@"\n\nError! Not register a sip server, please register a sip server.\n\n");
        return MSPMyPjsuaManagerResultRegisterSipServerError;
    }

    //Hangup same call.
    [self hangupCall:call];

    pj_status_t status;
    pj_str_t uri;
    pjsua_call_setting call_opt;
    pjsua_call_id call_id;

    uri = pj_str((char *)[[NSString stringWithFormat:@"sip:%@@%@", call.userName, self.currentSipAccount.domain] UTF8String]);
    pjsua_call_setting_default(&call_opt);
    call_opt.vid_cnt = 0;
    call_opt.flag = 0;

//    NSLog(@"\n\n----------------- pjsua_call_make_call info -----------------");
//    NSLog(@"acc_id : %d", pjsuaAccountId);
//    NSLog(@"dst_uri : %s", uri.ptr);
//    NSLog(@"call_opt.flag : %d", call_opt.flag);
//    NSLog(@"call_opt.req_keyframe_method : %d", call_opt.req_keyframe_method);
//    NSLog(@"call_opt.aud_cnt : %d", call_opt.aud_cnt);
//    NSLog(@"call_opt.vid_cnt : %d", call_opt.vid_cnt);
//    NSLog(@"------------------------------------------------------------\n\n");

    status = pjsua_call_make_call([self.currentSipAccount.accountId intValue], &uri, &call_opt, NULL, NULL, &call_id);
    if (status != PJ_SUCCESS) {
        NSLog(@"\n\nStatus ID : %d - Error in pjsua_call_make_call()\n\n", status);
        return MSPMyPjsuaManagerResultMakeCallError;
    }

    call.callId = @(call_id);
    [self.calls setObject:call forKey:call.callId];
    self.currentCall = call;

    self.status |= MSPMyPjsuaManagerStatusCalling;
    return MSPMyPjsuaManagerResultSuccess;
}

- (MSPMyPjsuaManagerResult)hangupCall:(MSPPjsuaCall *)call {
    if (!(self.status & MSPMyPjsuaManagerStatusStartedPjsua)) {
        NSLog(@"\n\nError! pjsua not init, transport not init or not start, please init them before register sip server.\n\n");
        return MSPMyPjsuaManagerResultPjsuaNotInitedError;
    }

    if (!(self.status & MSPMyPjsuaManagerStatusRegisterredSipServer)) {
        NSLog(@"\n\nError! Not register a sip server, please register a sip server.\n\n");
        return MSPMyPjsuaManagerResultRegisterSipServerError;
    }

    if (!call) {
        return MSPMyPjsuaManagerResultHangupCallError;
    }

    MSPPjsuaCall *findCall = self.calls[call.callId];
    if (findCall) {
        pjsua_call_hangup([findCall.callId intValue], 0, NULL, NULL);
        [self.calls removeObjectForKey:findCall.callId];

        if ([self.currentCall.callId isEqualToNumber:findCall.callId]) {
            self.currentCall = nil;

            [[NSNotificationCenter defaultCenter] postToMainThreadWithNotificationName:MSPCallhangupNotification object:[MSPMyPjsuaManager sharedManager]];
        }

        if (self.calls.count == 0) {
            self.status &= ~MSPMyPjsuaManagerStatusCalling;
        }
        return MSPMyPjsuaManagerResultSuccess;
    }
    else {
        if ([self.currentIncomingCall.callId isEqualToNumber:call.callId]) {
            pjsua_call_hangup([call.callId intValue], 0, NULL, NULL);
            self.currentIncomingCall = nil;

            [[NSNotificationCenter defaultCenter] postToMainThreadWithNotificationName:MSPCallhangupNotification object:[MSPMyPjsuaManager sharedManager]];

            if (self.calls.count == 0) {
                self.status &= ~MSPMyPjsuaManagerStatusCalling;
            }
            return MSPMyPjsuaManagerResultSuccess;
        }
        else {
            return MSPMyPjsuaManagerResultHangupCallError;
        }
    }
}

- (MSPMyPjsuaManagerResult)answerCall:(MSPPjsuaCall *)call {
    if (!(self.status & MSPMyPjsuaManagerStatusStartedPjsua)) {
        NSLog(@"\n\nError! pjsua not init, transport not init or not start, please init them before register sip server.\n\n");
        return MSPMyPjsuaManagerResultPjsuaNotInitedError;
    }

    if (!(self.status & MSPMyPjsuaManagerStatusRegisterredSipServer)) {
        NSLog(@"\n\nError! Not register a sip server, please register a sip server.\n\n");
        return MSPMyPjsuaManagerResultRegisterSipServerError;
    }

    //Hangup current call.
    [self hangupCall:self.currentCall];

    if (!call) {
        return MSPMyPjsuaManagerResultHangupCallError;
    }

    pj_status_t status;
    status = pjsua_call_answer([call.callId intValue], 200, NULL, NULL);
    if (status != PJ_SUCCESS) {
        NSLog(@"\n\nStatus ID : %d - Error in pjsua_call_answer()\n\n", status);
        return MSPMyPjsuaManagerResultAnswerCallError;
    }

    [self.calls setObject:call forKey:call.callId];
    self.currentCall = call;
    self.currentIncomingCall = nil;

    [[NSNotificationCenter defaultCenter] postToMainThreadWithNotificationName:MSPCallAnswerNotification object:[MSPMyPjsuaManager sharedManager]];

    self.status |= MSPMyPjsuaManagerStatusCalling;
    return MSPMyPjsuaManagerResultSuccess;
}

#pragma mark - PJSUA callback

static void on_call_state(pjsua_call_id call_id, pjsip_event *e) {
    pjsua_call_info ci;

    PJ_UNUSED_ARG(e);

    pjsua_call_get_info(call_id, &ci);
    NSLog(@"\n\n...Call %d state=%s\n\n", call_id, ci.state_text.ptr);

    NSLog(@"\n\n----------------- pjsua_call_info incoming info -----------------");
    NSLog(@"id : %d", ci.id);
    NSLog(@"acc_id : %d", ci.acc_id);
    NSLog(@"local_info : %s", ci.local_info.ptr);
    NSLog(@"local_contact : %s", ci.local_contact.ptr);
    NSLog(@"remote_info : %s", ci.remote_info.ptr);
    NSLog(@"remote_contact : %s", ci.remote_contact.ptr);
    NSLog(@"call_id : %s", ci.call_id.ptr);
    NSLog(@"state_text : %s", ci.state_text.ptr);
    NSLog(@"last_status_text : %s", ci.last_status_text.ptr);
    NSLog(@"conf_slot : %d", ci.conf_slot);
    NSLog(@"media_cnt : %d", ci.media_cnt);
    NSLog(@"prov_media_cnt : %d", ci.prov_media_cnt);
    NSLog(@"connect_duration : %ld s, %ld ms", ci.connect_duration.sec, ci.connect_duration.msec);
    NSLog(@"total_duration : %ld s, %ld ms", ci.total_duration.sec, ci.total_duration.msec);
    NSLog(@"rem_offerer : %d", ci.rem_offerer);
    NSLog(@"rem_aud_cnt : %d", ci.rem_aud_cnt);
    NSLog(@"rem_vid_cnt : %d", ci.rem_vid_cnt);
    NSLog(@"------------------------------------------------------------\n\n");

    if (ci.state == PJSIP_INV_STATE_DISCONNECTED) {
        MSPPjsuaCall *disconnectCall = [[MSPPjsuaCall alloc] init];
        disconnectCall.callId = @(call_id);
        [[MSPMyPjsuaManager sharedManager] hangupCall:disconnectCall];
    }
}

static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) {
    pjsua_call_info ci;

    PJ_UNUSED_ARG(acc_id);
    PJ_UNUSED_ARG(rdata);

    //Get calling info.
    pjsua_call_get_info(call_id, &ci);
    NSLog(@"\n\n...Incoming call from %s\n\n", ci.remote_info.ptr);

    //If is in calling, reject.
    if ([[MSPMyPjsuaManager sharedManager] currentCall] || [[MSPMyPjsuaManager sharedManager] currentIncomingCall]) {
        pj_str_t reason = pj_str("busy");
        pjsua_call_hangup(call_id, 0, &reason, NULL);
    }
    else {
//        NSLog(@"\n\n----------------- pjsua_call_info incoming info -----------------");
//        NSLog(@"id : %d", ci.id);
//        NSLog(@"acc_id : %d", ci.acc_id);
//        NSLog(@"local_info : %s", ci.local_info.ptr);
//        NSLog(@"local_contact : %s", ci.local_contact.ptr);
//        NSLog(@"remote_info : %s", ci.remote_info.ptr);
//        NSLog(@"remote_contact : %s", ci.remote_contact.ptr);
//        NSLog(@"call_id : %s", ci.call_id.ptr);
//        NSLog(@"state_text : %s", ci.state_text.ptr);
//        NSLog(@"last_status_text : %s", ci.last_status_text.ptr);
//        NSLog(@"conf_slot : %d", ci.conf_slot);
//        NSLog(@"media_cnt : %d", ci.media_cnt);
//        NSLog(@"prov_media_cnt : %d", ci.prov_media_cnt);
//        NSLog(@"connect_duration : %ld s, %ld ms", ci.connect_duration.sec, ci.connect_duration.msec);
//        NSLog(@"total_duration : %ld s, %ld ms", ci.total_duration.sec, ci.total_duration.msec);
//        NSLog(@"rem_offerer : %d", ci.rem_offerer);
//        NSLog(@"rem_aud_cnt : %d", ci.rem_aud_cnt);
//        NSLog(@"rem_vid_cnt : %d", ci.rem_vid_cnt);
//        NSLog(@"------------------------------------------------------------\n\n");

        MSPPjsuaCall *incomingCall = [[MSPPjsuaCall alloc] init];
        NSString *info = [NSString stringWithUTF8String:ci.remote_info.ptr];
        NSRange range = [info rangeOfString:@"\""];
        info = [info substringFromIndex:range.location + range.length];
        range = [info rangeOfString:@"\""];
        info = [info substringToIndex:range.location];
        incomingCall.userName = info;
        incomingCall.callId = @(call_id);
        [MSPMyPjsuaManager sharedManager].currentIncomingCall = incomingCall;

        [[NSNotificationCenter defaultCenter] postToMainThreadWithNotificationName:MSPCallIncomingNotification object:[MSPMyPjsuaManager sharedManager]];
    }
}

static void on_call_media_state(pjsua_call_id call_id) {
    pjsua_call_info ci;

    pjsua_call_get_info(call_id, &ci);
    NSLog(@"\n\n...Call media %d state=%s\n\n", call_id, ci.state_text.ptr);

    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
        // When media is active, connect call to sound device.
        pjsua_conf_connect(ci.conf_slot, 0);
        pjsua_conf_connect(0, ci.conf_slot);
    }
}

//Other PJSUA callbacks, use when need.
//static void on_call_tsx_state(pjsua_call_id call_id, pjsip_transaction *tsx, pjsip_event *e) {
//}
//
//static void on_call_sdp_created(pjsua_call_id call_id, pjmedia_sdp_session *sdp, pj_pool_t *pool, const pjmedia_sdp_session *rem_sdp) {
//}
//
//static void on_stream_created(pjsua_call_id call_id, pjmedia_stream *strm, unsigned stream_idx, pjmedia_port **p_port) {
//}
//
//static void on_stream_destroyed(pjsua_call_id call_id, pjmedia_stream *strm, unsigned stream_idx) {
//}
//
//static void on_dtmf_digit(pjsua_call_id call_id, int digit) {
//}
//
//static void on_call_transfer_request(pjsua_call_id call_id, const pj_str_t *dst, pjsip_status_code *code) {
//}
//
//static void on_call_transfer_request2(pjsua_call_id call_id, const pj_str_t *dst, pjsip_status_code *code, pjsua_call_setting *opt) {
//}
//
//static void on_call_transfer_status(pjsua_call_id call_id, int st_code, const pj_str_t *st_text, pj_bool_t final, pj_bool_t *p_cont) {
//}
//
//static void on_call_replace_request(pjsua_call_id call_id, pjsip_rx_data *rdata, int *st_code, pj_str_t *st_text) {
//}
//
//static void on_call_replace_request2(pjsua_call_id call_id, pjsip_rx_data *rdata, int *st_code, pj_str_t *st_text, pjsua_call_setting *opt) {
//}
//
//static void on_call_replaced(pjsua_call_id old_call_id, pjsua_call_id new_call_id) {
//}
//
//static void on_call_rx_offer(pjsua_call_id call_id, const pjmedia_sdp_session *offer, void *reserved, pjsip_status_code *code, pjsua_call_setting *opt) {
//}
//
//static void on_reg_started(pjsua_acc_id acc_id, pj_bool_t renew) {
//}
//
//static void on_reg_state(pjsua_acc_id acc_id) {
//}
//
//static void on_reg_state2(pjsua_acc_id acc_id, pjsua_reg_info *info) {
//}
//
//static void on_incoming_subscribe(pjsua_acc_id acc_id, pjsua_srv_pres *srv_pres, pjsua_buddy_id buddy_id, const pj_str_t *from, pjsip_rx_data *rdata, pjsip_status_code *code, pj_str_t *reason, pjsua_msg_data *msg_data) {
//}
//
//static void on_srv_subscribe_state(pjsua_acc_id acc_id, pjsua_srv_pres *srv_pres, const pj_str_t *remote_uri, pjsip_evsub_state state, pjsip_event *event) {
//}
//
//static void on_buddy_state(pjsua_buddy_id buddy_id) {
//}
//
//static void on_buddy_evsub_state(pjsua_buddy_id buddy_id, pjsip_evsub *sub, pjsip_event *event) {
//}
//
//static void on_pager(pjsua_call_id call_id, const pj_str_t *from, const pj_str_t *to, const pj_str_t *contact, const pj_str_t *mime_type, const pj_str_t *body) {
//}
//
//static void on_pager2(pjsua_call_id call_id, const pj_str_t *from, const pj_str_t *to, const pj_str_t *contact, const pj_str_t *mime_type, const pj_str_t *body, pjsip_rx_data *rdata, pjsua_acc_id acc_id) {
//}
//
//static void on_pager_status(pjsua_call_id call_id, const pj_str_t *to, const pj_str_t *body, void *user_data, pjsip_status_code status, const pj_str_t *reason) {
//}
//
//static void on_pager_status2(pjsua_call_id call_id, const pj_str_t *to, const pj_str_t *body, void *user_data, pjsip_status_code status, const pj_str_t *reason, pjsip_tx_data *tdata, pjsip_rx_data *rdata, pjsua_acc_id acc_id) {
//}
//
//static void on_typing(pjsua_call_id call_id, const pj_str_t *from, const pj_str_t *to, const pj_str_t *contact, pj_bool_t is_typing) {
//}
//
//static void on_typing2(pjsua_call_id call_id, const pj_str_t *from, const pj_str_t *to, const pj_str_t *contact, pj_bool_t is_typing, pjsip_rx_data *rdata, pjsua_acc_id acc_id) {
//}
//
//static void on_nat_detect(const pj_stun_nat_detect_result *res) {
//}
//
//static pjsip_redirect_op on_call_redirected(pjsua_call_id call_id, const pjsip_uri *target, const pjsip_event *e) {
//    return PJSIP_REDIRECT_ACCEPT_REPLACE;
//}
//
//static void on_mwi_state(pjsua_acc_id acc_id, pjsip_evsub *evsub) {
//}
//
//static void on_mwi_info(pjsua_acc_id acc_id, pjsua_mwi_info *mwi_info) {
//}
//
//static void on_transport_state(pjsip_transport *tp, pjsip_transport_state state, const pjsip_transport_state_info *info) {
//}
//
//static pj_status_t on_call_media_transport_state(pjsua_call_id call_id, const pjsua_med_tp_state_info *info) {
//    return PJ_SUCCESS;
//}
//
//static void on_ice_transport_error(int index, pj_ice_strans_op op, pj_status_t status, void *param) {
//}
//
//static pj_status_t on_snd_dev_operation(int operation) {
//    return PJ_SUCCESS;
//}
//
//static void on_call_media_event(pjsua_call_id call_id, unsigned med_idx, pjmedia_event *event) {
//}
//
//static pjmedia_transport* on_create_media_transport(pjsua_call_id call_id, unsigned media_idx, pjmedia_transport *base_tp, unsigned flags) {
//    return NULL;
//}
//
//static void on_acc_find_for_incoming(const pjsip_rx_data *rdata, pjsua_acc_id* acc_id) {
//}

@end


text:
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

using Microsoft.Scripting.Runtime;

using IronPython.Runtime.Types;

namespace IronPython.Runtime.Operations {
    public static class DictionaryOfTOps<K, V> {
        public static string __repr__(CodeContext/*!*/ context, Dictionary<K, V> self) {
            List<object> infinite = PythonOps.GetAndCheckInfinite(self);
            if (infinite == null) {
                return "{...}";
            }

            int index = infinite.Count;
            infinite.Add(self);
            try {
                StringBuilder res = new StringBuilder();
                res.Append("Dictionary[");
                res.Append(DynamicHelpers.GetPythonTypeFromType(typeof(K)).Name);
                res.Append(", ");
                res.Append(DynamicHelpers.GetPythonTypeFromType(typeof(V)).Name);
                res.Append("](");
                if (self.Count > 0) {
                    res.Append("{");
                    string comma = "";
                    foreach (KeyValuePair<K, V> obj in self) {
                        res.Append(comma);
                        res.Append(PythonOps.Repr(context, obj.Key));
                        res.Append(" : ");
                        res.Append(PythonOps.Repr(context, obj.Value));
                        comma = ", ";
                    }
                    res.Append("}");
                }

                res.Append(")");
                return res.ToString();
            } finally {
                Debug.Assert(index == infinite.Count - 1);
                infinite.RemoveAt(index);
            }
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
vm-hibernation
==============

OpenStack Open Academy Project: Hibernation of VM Instances


text:
namespace AccordionSample
{
    using Xamarin.Forms;

    public class AccordionViewExample : ContentPage
    {
        public AccordionViewExample()
        {
            var accordion = new AccordionView();
            accordion.Items.Add(new AccordionItem { Title = "Item #1", Content = "Body content #1", IsSelected = true });
            accordion.Items.Add(new AccordionItem { Title = "Item #2", Content = "Body content #2" });
            accordion.Items.Add(new AccordionItem { Title = "Item #3", Content = "Body content #3" });

            Content = accordion;
        }
    }
}


text:
from evoplotter.templates import *
from evoplotter.utils import *
import app.phd.cdgp.phd_processor as phd_processor
import app.phd.cdgp.phd_utils as phd_utils

def cleanLIA():
    folders_in = ["LIA_ORIG"]
    folder_out = "LIA/"
    ensure_clear_dir(folder_out)

    props = phd_utils.load_correct_props_simple(folders_in)
    phd_processor.standardize_benchmark_names(props)
    dim_benchmark = phd_processor.get_benchmarks_from_props(props)
    dim_method = phd_processor.dim_methodCDGP + phd_processor.dim_methodGPR
    dim = phd_processor.dim_evoMode * dim_benchmark * dim_method * phd_processor.dim_sel * phd_processor.dim_testsRatio
    utils.reorganizeExperimentFiles(props, dim, target_dir=folder_out, maxRuns=50)

def cleanSLIA():
    folders_in = ["SLIA_hardTimeout_ORIG"]
    folder_out = "SLIA_hardTimeout/"
    ensure_clear_dir(folder_out)

    props = phd_utils.load_correct_props_simple(folders_in)
    phd_processor.standardize_benchmark_names(props)
    dim_benchmark = phd_processor.get_benchmarks_from_props(props)
    dim_method = phd_processor.dim_methodCDGP
    dim = phd_processor.dim_evoMode * dim_benchmark * dim_method * phd_processor.dim_sel * phd_processor.dim_testsRatio
    utils.reorganizeExperimentFiles(props, dim, target_dir=folder_out, maxRuns=50)

if __name__ == "__main__":
    # cleanLIA()
    cleanSLIA()


text:
<readable><title>2714220101_c31db50b10</title><content>
A little white dog running through the sand .
A West Highland Terrier runs across the dirt .
A white dog running on sand .
A white dog runs on the beach .
A white dog runs on the sand .
</content></readable>


text:
class CPawn : public CPiece
{
public:
	CPawn(char cColor);
	~CPawn() {}
private:
	virtual char GetPiece();
};

#endif


text:
package org.tntstudio.graphics.objs;

import static com.badlogic.gdx.graphics.g2d.Batch.C1;
import static com.badlogic.gdx.graphics.g2d.Batch.C2;
import static com.badlogic.gdx.graphics.g2d.Batch.C3;
import static com.badlogic.gdx.graphics.g2d.Batch.C4;
import static com.badlogic.gdx.graphics.g2d.Batch.U1;
import static com.badlogic.gdx.graphics.g2d.Batch.U2;
import static com.badlogic.gdx.graphics.g2d.Batch.U3;
import static com.badlogic.gdx.graphics.g2d.Batch.U4;
import static com.badlogic.gdx.graphics.g2d.Batch.V1;
import static com.badlogic.gdx.graphics.g2d.Batch.V2;
import static com.badlogic.gdx.graphics.g2d.Batch.V3;
import static com.badlogic.gdx.graphics.g2d.Batch.V4;
import static com.badlogic.gdx.graphics.g2d.Batch.X1;
import static com.badlogic.gdx.graphics.g2d.Batch.X2;
import static com.badlogic.gdx.graphics.g2d.Batch.X3;
import static com.badlogic.gdx.graphics.g2d.Batch.X4;
import static com.badlogic.gdx.graphics.g2d.Batch.Y1;
import static com.badlogic.gdx.graphics.g2d.Batch.Y2;
import static com.badlogic.gdx.graphics.g2d.Batch.Y3;
import static com.badlogic.gdx.graphics.g2d.Batch.Y4;

import org.tntstudio.Const;
import org.tntstudio.Const.AnimationMode;
import org.tntstudio.Utils;
import org.tntstudio.graphics.Animator;
import org.tntstudio.utils.math.PolygonList;

import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.NumberUtils;

/** @author trungnt13 */
@SuppressWarnings("rawtypes")
public class SpriteAnimation extends SpriteBase implements Animator {
	// ---------------------------------------------------------

	static final int VERTEX_SIZE = 2 + 1 + 2;
	static final int SPRITE_SIZE = 4 * VERTEX_SIZE;

	// ---------------------------------------------------------

	private final float[] mVertices = new float[SPRITE_SIZE];

	private final Color mColor = new Color(1, 1, 1, 1);
	private float x = -100, y = -100;
	float width = 100, height = 100;
	private float originX = 50, originY = 50;
	private float rotation = 0;
	private float scaleX = 1, scaleY = 1;
	private boolean dirty = true;
	private PolygonList mBounds;

	/** Creates an uninitialized sprite. The sprite will need a texture, texture region, bounds, and color set before it can be
	 * drawn. */
	public SpriteAnimation () {
		setColor(1, 1, 1, 1);
	}

	public SpriteAnimation bind (String spriteName, Array<? extends TextureRegion> region) {
		keyFrames = new TextureRegion[region.size];
		for (int i = 0; i < keyFrames.length; i++)
			keyFrames[i] = (TextureRegion)region.get(i);
		setRegion(keyFrames[0]);

		setColor(1, 1, 1, 1);
		setSize(keyFrames[0].getRegionWidth(), keyFrames[0].getRegionHeight());
		setOrigin(width / 2, height / 2);

		setTexture(keyFrames);
		active();

		mBounds = SpriteWorld.getPolygonForSprite(spriteName, width, height);
		return this;
	}

	public SpriteAnimation bind (String spriteName, TextureRegion[] region) {
		keyFrames = region;
		setRegion(region[0]);

		setColor(1, 1, 1, 1);
		setSize(keyFrames[0].getRegionWidth(), keyFrames[0].getRegionHeight());
		setOrigin(width / 2, height / 2);

		setTexture(keyFrames);
		active();

		mBounds = SpriteWorld.getPolygonForSprite(spriteName, width, height);
		return this;
	}

	public SpriteAnimation bind (String spriteName, TextureRegion region) {
		tmpFrames[0] = region;
		keyFrames = tmpFrames;
		setRegion(region);

		setColor(1, 1, 1, 1);
		setSize(keyFrames[0].getRegionWidth(), keyFrames[0].getRegionHeight());
		setOrigin(width / 2, height / 2);

		setTexture(keyFrames);
		active();

		mBounds = SpriteWorld.getPolygonForSprite(spriteName, width, height);
		return this;
	}

	public SpriteAnimation bind (String spriteName, Texture tex) {
		TextureRegion region = new TextureRegion(tex);
		return bind(spriteName, region);
	}

	public SpriteAnimation bind (SpriteAnimation sprite) {
		if (sprite == null) throw new IllegalArgumentException("sprite cannot be null.");
		System.arraycopy(sprite.mVertices, 0, mVertices, 0, SPRITE_SIZE);
		keyFrames = sprite.keyFrames;
		setTexture(keyFrames);
		x = sprite.x;
		y = sprite.y;
		width = sprite.width;
		height = sprite.height;
		originX = sprite.originX;
		originY = sprite.originY;
		rotation = sprite.rotation;
		scaleX = sprite.scaleX;
		scaleY = sprite.scaleY;
		mColor.set(sprite.mColor);
		dirty = sprite.dirty;

		mBounds = sprite.mBounds;
		active();
		return this;
	}

	public SpriteAnimation bind (Array<? extends TextureRegion> region) {
		StringBuilder builder = new StringBuilder();
		for (TextureRegion textureRegion : region) {
			builder.append(Utils.getIdentification(textureRegion));
		}
		return bind(builder.toString(), region);
	}

	public SpriteAnimation bind (TextureRegion[] region) {
		StringBuilder builder = new StringBuilder();
		for (TextureRegion textureRegion : region) {
			builder.append(Utils.getIdentification(textureRegion));
		}
		return bind(builder.toString(), region);
	}

	public SpriteAnimation bind (TextureRegion region) {
		return bind(Utils.getIdentification(region), region);
	}

	public SpriteAnimation bind (Texture tex) {
		return bind(Utils.getIdentification(tex), tex);
	}

	private void setTexture (TextureRegion[] texture) {
		mCurrentTexture = texture[0].getTexture();
	}

	/***********************************************************
	 *
	 ***********************************************************/

	/** Sets the position and size of the sprite when drawn, before scaling and rotation are applied. If origin, rotation, or scale
	 * are changed, it is slightly more efficient to set the bounds after those operations. */
	public void setBounds (float x, float y, float width, float height) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;

		if (dirty) return;

		float x2 = x + width;
		float y2 = y + height;
		final float[] vertices = this.mVertices;
		vertices[X1] = x;
		vertices[Y1] = y;

		vertices[X2] = x;
		vertices[Y2] = y2;

		vertices[X3] = x2;
		vertices[Y3] = y2;

		vertices[X4] = x2;
		vertices[Y4] = y;

		if (rotation != 0 || scaleX != 1 || scaleY != 1) dirty = true;
	}

	/** Sets the size of the sprite when drawn, before scaling and rotation are applied. If origin, rotation, or scale are changed,
	 * it is slightly more efficient to set the size after those operations. If both position and size are to be changed, it is
	 * better to use {@link #setBounds(float, float, float, float)}. */
	public void setSize (float width, float height) {
		this.width = width;
		this.height = height;

		if (dirty) return;

		float x2 = x + width;
		float y2 = y + height;
		final float[] vertices = this.mVertices;
		vertices[X1] = x;
		vertices[Y1] = y;

		vertices[X2] = x;
		vertices[Y2] = y2;

		vertices[X3] = x2;
		vertices[Y3] = y2;

		vertices[X4] = x2;
		vertices[Y4] = y;

		if (rotation != 0 || scaleX != 1 || scaleY != 1) dirty = true;
	}

	/** Sets the position where the sprite will be drawn. If origin, rotation, or scale are changed, it is slightly more efficient
	 * to set the position after those operations. If both position and size are to be changed, it is better to use
	 * {@link #setBounds(float, float, float, float)}. */
	public void setPosition (float x, float y) {
		translate(x - this.x, y - this.y);
	}

	/** Sets the x position where the sprite will be drawn. If origin, rotation, or scale are changed, it is slightly more efficient
	 * to set the position after those operations. If both position and size are to be changed, it is better to use
	 * {@link #setBounds(float, float, float, float)}. */
	public void setX (float x) {
		translateX(x - this.x);
	}

	/** Sets the y position where the sprite will be drawn. If origin, rotation, or scale are changed, it is slightly more efficient
	 * to set the position after those operations. If both position and size are to be changed, it is better to use
	 * {@link #setBounds(float, float, float, float)}. */
	public void setY (float y) {
		translateY(y - this.y);
	}

	/** Sets the x position relative to the current position where the sprite will be drawn. If origin, rotation, or scale are
	 * changed, it is slightly more efficient to translate after those operations. */
	public void translateX (float xAmount) {
		this.x += xAmount;

		if (dirty) return;

		final float[] vertices = this.mVertices;
		vertices[X1] += xAmount;
		vertices[X2] += xAmount;
		vertices[X3] += xAmount;
		vertices[X4] += xAmount;
	}

	/** Sets the y position relative to the current position where the sprite will be drawn. If origin, rotation, or scale are
	 * changed, it is slightly more efficient to translate after those operations. */
	public void translateY (float yAmount) {
		y += yAmount;

		if (dirty) return;

		final float[] vertices = this.mVertices;
		vertices[Y1] += yAmount;
		vertices[Y2] += yAmount;
		vertices[Y3] += yAmount;
		vertices[Y4] += yAmount;
	}

	/** Sets the position relative to the current position where the sprite will be drawn. If origin, rotation, or scale are
	 * changed, it is slightly more efficient to translate after those operations. */
	public void translate (float xAmount, float yAmount) {
		x += xAmount;
		y += yAmount;

		if (dirty) return;

		final float[] vertices = this.mVertices;
		vertices[X1] += xAmount;
		vertices[Y1] += yAmount;

		vertices[X2] += xAmount;
		vertices[Y2] += yAmount;

		vertices[X3] += xAmount;
		vertices[Y3] += yAmount;

		vertices[X4] += xAmount;
		vertices[Y4] += yAmount;
	}

	public void setColor (float alphaModulation) {
		Color color = getColor();
		color.a *= alphaModulation;
		setColor(color);
	}

	public void setColor (Color tint) {
		float color = tint.toFloatBits();
		final float[] vertices = this.mVertices;
		vertices[C1] = color;
		vertices[C2] = color;
		vertices[C3] = color;
		vertices[C4] = color;
	}

	public void setColor (float r, float g, float b, float a) {
		final int intBits = ((int)(255 * a) << 24) | ((int)(255 * b) << 16) | ((int)(255 * g) << 8) | ((int)(255 * r));
		float color = NumberUtils.intToFloatColor(intBits);
		final float[] vertices = this.mVertices;
		vertices[C1] = color;
		vertices[C2] = color;
		vertices[C3] = color;
		vertices[C4] = color;
	}

	/** Sets the origin in relation to the sprite's position for scaling and rotation. */
	public void setOrigin (float originX, float originY) {
		this.originX = originX;
		this.originY = originY;
		dirty = true;
	}

	public void setRotation (float degrees) {
		this.rotation = degrees;
		dirty = true;
	}

	/** Sets the sprite's rotation relative to the current rotation. */
	public void rotate (float degrees) {
		rotation += degrees;
		dirty = true;
	}

	/** Rotates this sprite 90 degrees in-place by rotating the texture coordinates. This rotation is unaffected by
	 * {@link #setRotation(float)} and {@link #rotate(float)}. */
	public void rotate90 (boolean clockwise) {
		final float[] vertices = this.mVertices;

		if (clockwise) {
			float temp = vertices[V1];
			vertices[V1] = vertices[V4];
			vertices[V4] = vertices[V3];
			vertices[V3] = vertices[V2];
			vertices[V2] = temp;

			temp = vertices[U1];
			vertices[U1] = vertices[U4];
			vertices[U4] = vertices[U3];
			vertices[U3] = vertices[U2];
			vertices[U2] = temp;
		} else {
			float temp = vertices[V1];
			vertices[V1] = vertices[V2];
			vertices[V2] = vertices[V3];
			vertices[V3] = vertices[V4];
			vertices[V4] = temp;

			temp = vertices[U1];
			vertices[U1] = vertices[U2];
			vertices[U2] = vertices[U3];
			vertices[U3] = vertices[U4];
			vertices[U4] = temp;
		}
	}

	public void setScale (float scaleXY) {
		this.scaleX = scaleXY;
		this.scaleY = scaleXY;
		dirty = true;
	}

	public void setScale (float scaleX, float scaleY) {
		this.scaleX = scaleX;
		this.scaleY = scaleY;
		dirty = true;
	}

	/** Sets the sprite's scale relative to the current scale. */
	public void scale (float amount) {
		this.scaleX += amount;
		this.scaleY += amount;
		dirty = true;
	}

	public void flip (boolean x, boolean y) {
		super.flip(x, y);

		for (int i = 0; i < keyFrames.length; i++)
			keyFrames[i].flip(x, y);

		float[] vertices = SpriteAnimation.this.mVertices;
		if (x) {
			float temp = vertices[U1];
			vertices[U1] = vertices[U3];
			vertices[U3] = temp;
			temp = vertices[U2];
			vertices[U2] = vertices[U4];
			vertices[U4] = temp;
		}
		if (y) {
			float temp = vertices[V1];
			vertices[V1] = vertices[V3];
			vertices[V3] = temp;
			temp = vertices[V2];
			vertices[V2] = vertices[V4];
			vertices[V4] = temp;
		}
	}

	// ///////////////////////////////////////////////////////////////
	// animation controller
	// ///////////////////////////////////////////////////////////////
	// TODO: add more animation control here
	/*-------- params --------*/

	TextureRegion[] keyFrames;
	private final TextureRegion[] tmpFrames = new TextureRegion[1];

	float mPlaybackSpeed;
	float mStateTime;

	private int mCurrFrameIdx;

	private int mPlayMode = AnimationMode.NORMAL;

	private Texture mCurrentTexture;

	private boolean isRunning = false;

	/*-------- methdos --------*/

	public float getPlaybackSpeed () {
		return mPlaybackSpeed;
	}

	public Animator setLoop (boolean looping) {
		if (looping) {
			mPlayMode = AnimationMode.LOOP;
		} else {
			mPlayMode = AnimationMode.NORMAL;
		}
		return this;
	}

	@Override
	public Animator setPlaybackSpeed (float playback) {
		mPlaybackSpeed = playback;
		return this;
	}

	public void setKeyFrames (TextureRegion[] keyFrame) {
		this.keyFrames = keyFrame;
		setRegion(keyFrames[0]);
		setTexture(keyFrame);
	}

	public void setKeyFrames (Array keyFrame) {
		keyFrames = new TextureRegion[keyFrame.size];
		for (int i = 0; i < keyFrames.length; i++)
			keyFrames[i] = (TextureRegion)keyFrame.get(i);
		setRegion(keyFrames[0]);
		setTexture(keyFrames);
	}

	@Override
	public boolean isLooping () {
		return mPlayMode == Const.AnimationMode.LOOP || mPlayMode == Const.AnimationMode.LOOP_REVERSED;
	}

	@Override
	public boolean isReversed () {
		return mPlayMode == AnimationMode.LOOP_REVERSED || mPlayMode == AnimationMode.REVERSED;
	}

	public Animator start () {
		start(mStateTime, false);
		return this;
	}

	@Override
	public Animator start (float statetime) {
		start(statetime, false);
		return this;
	}

	@Override
	public Animator start (float statetime, boolean reversed) {
		mStateTime = statetime;
		isRunning = true;
		if (reversed) {
			if (mPlayMode == AnimationMode.LOOP)
				mPlayMode = AnimationMode.LOOP_REVERSED;
			else if (mPlayMode == AnimationMode.NORMAL) mPlayMode = AnimationMode.REVERSED;
		} else {
			if (mPlayMode == AnimationMode.LOOP_REVERSED)
				mPlayMode = AnimationMode.LOOP;
			else if (mPlayMode == AnimationMode.REVERSED) mPlayMode = AnimationMode.NORMAL;
		}
		return this;
	}

	public Animator stop () {
		isRunning = false;
		mStateTime = 0;
		setRegion(keyFrames[0]);
		return this;
	}

	public Animator pause () {
		isRunning = false;
		return this;
	}

	protected void updateInternal (float delta) {
		if (!isRunning || mPlaybackSpeed == 0) return;

		mStateTime += delta;

		mCurrFrameIdx = (int)(mStateTime / mPlaybackSpeed);

		switch (mPlayMode) {
		case AnimationMode.NORMAL:
			mCurrFrameIdx = Math.min(keyFrames.length - 1, mCurrFrameIdx);
			break;
		case AnimationMode.LOOP:
			mCurrFrameIdx = mCurrFrameIdx % keyFrames.length;
			break;
		case AnimationMode.LOOP_PINGPONG:
			mCurrFrameIdx = mCurrFrameIdx % (keyFrames.length * 2);
			if (mCurrFrameIdx >= keyFrames.length) mCurrFrameIdx = keyFrames.length - 1 - (mCurrFrameIdx - keyFrames.length);
			break;
		case AnimationMode.LOOP_RANDOM:
			mCurrFrameIdx = MathUtils.random(keyFrames.length - 1);
			break;
		case AnimationMode.REVERSED:
			mCurrFrameIdx = Math.max(keyFrames.length - mCurrFrameIdx - 1, 0);
			break;
		case AnimationMode.LOOP_REVERSED:
			mCurrFrameIdx = mCurrFrameIdx % keyFrames.length;
			mCurrFrameIdx = keyFrames.length - mCurrFrameIdx - 1;
			break;

		default:
			// play normal otherwise
			mCurrFrameIdx = Math.min(keyFrames.length - 1, mCurrFrameIdx);
			break;
		}

		setRegion(keyFrames[mCurrFrameIdx]);
	}

	public int getCurrFrameIdx () {
		return mCurrFrameIdx;
	}

	public TextureRegion[] getFrames () {
		return this.keyFrames;
	}

	@Override
	public boolean isRunning () {
		return isRunning;
	}

	public boolean isAnimationFinished () {
		int frameNumber = (int)(mStateTime / mPlaybackSpeed);
		return keyFrames.length - 1 < frameNumber;
	}

	@Override
	public float getStateTime () {
		return mStateTime;
	}

	@Override
	public float getTotalDuration () {
		return keyFrames.length * mPlaybackSpeed;
	}

	/***********************************************************
	 *
	 ***********************************************************/

	/** Returns the packed vertices, colors, and texture coordinates for this sprite. */
	public float[] getVertices () {
		if (dirty) {
			dirty = false;

			float[] vertices = this.mVertices;
			float localX = -originX;
			float localY = -originY;
			float localX2 = localX + width;
			float localY2 = localY + height;
			float worldOriginX = this.x - localX;
			float worldOriginY = this.y - localY;
			if (scaleX != 1 || scaleY != 1) {
				localX *= scaleX;
				localY *= scaleY;
				localX2 *= scaleX;
				localY2 *= scaleY;
			}
			if (rotation != 0) {
				final float cos = MathUtils.cosDeg(rotation);
				final float sin = MathUtils.sinDeg(rotation);
				final float localXCos = localX * cos;
				final float localXSin = localX * sin;
				final float localYCos = localY * cos;
				final float localYSin = localY * sin;
				final float localX2Cos = localX2 * cos;
				final float localX2Sin = localX2 * sin;
				final float localY2Cos = localY2 * cos;
				final float localY2Sin = localY2 * sin;

				final float x1 = localXCos - localYSin + worldOriginX;
				final float y1 = localYCos + localXSin + worldOriginY;
				vertices[X1] = x1;
				vertices[Y1] = y1;

				final float x2 = localXCos - localY2Sin + worldOriginX;
				final float y2 = localY2Cos + localXSin + worldOriginY;
				vertices[X2] = x2;
				vertices[Y2] = y2;

				final float x3 = localX2Cos - localY2Sin + worldOriginX;
				final float y3 = localY2Cos + localX2Sin + worldOriginY;
				vertices[X3] = x3;
				vertices[Y3] = y3;

				vertices[X4] = x1 + (x3 - x2);
				vertices[Y4] = y3 - (y2 - y1);
			} else {
				final float x1 = localX + worldOriginX;
				final float y1 = localY + worldOriginY;
				final float x2 = localX2 + worldOriginX;
				final float y2 = localY2 + worldOriginY;

				vertices[X1] = x1;
				vertices[Y1] = y1;

				vertices[X2] = x1;
				vertices[Y2] = y2;

				vertices[X3] = x2;
				vertices[Y3] = y2;

				vertices[X4] = x2;
				vertices[Y4] = y1;
			}
		}
		return mVertices;
	}

	/** Returns the bounding axis aligned {@link Rectangle} that bounds this sprite. The rectangles x and y coordinates describe its
	 * bottom left corner. If you change the position or size of the sprite, you have to fetch the triangle again for it to be
	 * recomputed.
	 *
	 * @return the bounding Rectangle */
	public Array<FloatArray> getBounding () {
		mBounds.apply(this);
		return mBounds.getTransformedVertices();
	}

	protected void drawInternal (Batch spriteBatch) {
		spriteBatch.draw(mCurrentTexture, getVertices(), 0, SPRITE_SIZE);
	}

	/***********************************************************
	 *
	 ***********************************************************/

	public float getX () {
		return x;
	}

	public float getCenterX () {
		final float[] vertices = getVertices();

		float minx = vertices[X1];
		float maxx = vertices[X1];

		minx = minx > vertices[X2] ? vertices[X2] : minx;
		minx = minx > vertices[X3] ? vertices[X3] : minx;
		minx = minx > vertices[X4] ? vertices[X4] : minx;

		maxx = maxx < vertices[X2] ? vertices[X2] : maxx;
		maxx = maxx < vertices[X3] ? vertices[X3] : maxx;
		maxx = maxx < vertices[X4] ? vertices[X4] : maxx;

		return (minx + maxx) / 2;
	}

	public float getY () {
		return y;
	}

	public float getCenterY () {
		final float[] vertices = getVertices();

		float miny = vertices[Y1];
		float maxy = vertices[Y1];

		miny = miny > vertices[Y2] ? vertices[Y2] : miny;
		miny = miny > vertices[Y3] ? vertices[Y3] : miny;
		miny = miny > vertices[Y4] ? vertices[Y4] : miny;

		maxy = maxy < vertices[Y2] ? vertices[Y2] : maxy;
		maxy = maxy < vertices[Y3] ? vertices[Y3] : maxy;
		maxy = maxy < vertices[Y4] ? vertices[Y4] : maxy;

		return (miny + maxy) / 2;
	}

	public float getWidth () {
		return width;
	}

	public float getHeight () {
		return height;
	}

	public float getOriginX () {
		return originX;
	}

	public float getOriginY () {
		return originY;
	}

	public float getRotation () {
		return rotation;
	}

	public float getScaleX () {
		return scaleX;
	}

	public float getScaleY () {
		return scaleY;
	}

	/** Returns the color of this sprite. Changing the returned color will have no affect, {@link #setColor(Color)} or
	 * {@link #setColor(float, float, float, float)} must be used. */
	public Color getColor () {
		final int intBits = NumberUtils.floatToIntColor(mVertices[C1]);
		final Color color = this.mColor;
		color.r = (intBits & 0xff) / 255f;
		color.g = ((intBits >>> 8) & 0xff) / 255f;
		color.b = ((intBits >>> 16) & 0xff) / 255f;
		color.a = ((intBits >>> 24) & 0xff) / 255f;
		return color;
	}

	private void setRegion (TextureRegion region) {
		this.mCurrentTexture = region.getTexture();

		final float u = region.getU();
		final float v = region.getV();
		final float u2 = region.getU2();
		final float v2 = region.getV2();

		final float[] vertices = SpriteAnimation.this.mVertices;

		vertices[U1] = u;
		vertices[V1] = v2;

		vertices[U2] = u;
		vertices[V2] = v;

		vertices[U3] = u2;
		vertices[V3] = v;

		vertices[U4] = u2;
		vertices[V4] = v2;
	}

	public void scroll (float xAmount, float yAmount) {

		final float[] vertices = SpriteAnimation.this.mVertices;
		if (xAmount != 0) {
			final float u = (vertices[U1] + xAmount) % 1;
			final float u2 = u + width / mCurrentTexture.getWidth();
			vertices[U1] = u;
			vertices[U2] = u;
			vertices[U3] = u2;
			vertices[U4] = u2;
		}
		if (yAmount != 0) {
			final float v = (vertices[V2] + yAmount) % 1;
			final float v2 = v + height / mCurrentTexture.getHeight();
			vertices[V1] = v2;
			vertices[V2] = v;
			vertices[V3] = v;
			vertices[V4] = v2;
		}
	}

	public boolean hit (float x, float y) {
		if (x >= getX() && x <= (getX() + getWidth()) && y >= getY() && y <= (getY() + getHeight())) {
			return true;
		}
		return false;
	}

	@Override
	protected void resetInternal () {
		stop();
		setPosition(0, 0);
		setSize(0, 0);
		setOrigin(0, 0);
		rotation = 0;
		scaleX = 1;
		scaleY = 1;
		dirty = false;
		setColor(1, 1, 1, 1);

		clearUpdater();
	}
}


text:
package pubsub

import (
	"fmt"
	log "github.com/Sirupsen/logrus"
	zmq "github.com/pebbe/zmq4"
	"regexp"
	"runtime"
	"strings"
	"time"
)

type Topic map[string]string

var wildTopicRegex *regexp.Regexp

func (b *Broker) Poll() {
	log := log.WithFields(
		log.Fields{"file": "pubsub/poll.go"},
	)

	b.connect()
	runtime.SetFinalizer(b, (*Broker).Close)

	poller := zmq.NewPoller()
	poller.Add(b.PubSocket, zmq.POLLIN)
	poller.Add(b.SubSocket, zmq.POLLIN)

	// listen to all incoming messages
	b.SubSocket.SetSubscribe("")

	// empty set of topics for wildcard matching
	topics := make(Topic)

	for {
		polled, err := poller.Poll(1000 * time.Millisecond)

		if err != nil {
			log.Error(err)
			break
		}

		for _, item := range polled {
			switch socket := item.Socket; socket {
			case b.SubSocket:
				msg, _ := b.SubSocket.RecvMessage(0)
				topic := msg[0]
				data := msg[1]

				log.Debug(fmt.Sprintf("Topic: %s, Msg: %s", topic, data))

				// include topic twice to match message format
				b.PubSocket.SendMessage(append([]string{topic}, msg...))

				// iterate through wildcard topics, looking for matches
				for wildTopic, topicRegex := range topics {
					log.Debug(fmt.Sprintf("wildTopic: %s, topicRegex: %s", wildTopic, topicRegex))
					matched, _ := regexp.MatchString(topicRegex, topic)
					if matched == true {
						// emit matched topic as well as the topic from the publisher
						b.PubSocket.SendMessage([]string{wildTopic, topic, data})
					}
				}
			case b.PubSocket:
				msg, _ := b.PubSocket.RecvMessage(0)

				frame := msg[0]
				topic := frame[1:]

				switch frame[0] {
				case 1:
					if topicIsWild(topic) == true {
						topics = appendIfMissing(topics, topic)
					}
					log.Debug(fmt.Sprintf("Subscribed: %s", topic))
				case 0:
					log.Debug(fmt.Sprintf("UnSubscribed: %s", topic))
					if topicIsWild(topic) == true {
						delete(topics, topic)
					}
				default:
					log.Warn(fmt.Sprintf("Unknown Frame: %v", msg))
				}
			}
		}
	}
}

func topicIsWild(topic string) bool {
	// Definition of topic wildcard:
	//   * start of line, or a period
	//   * wildcard character (* or #)
	//   * end of line or period
	if wildTopicRegex == nil {
		wildTopicRegex, _ = regexp.Compile("(^|\\.){1}[\\*#]{1}($|\\.){1}")
	}

	matched := wildTopicRegex.MatchString(topic)
	return matched
}

func appendIfMissing(topics Topic, topic string) Topic {
	_, exists := topics[topic]

	if exists == true {
		// already been added, somehow
		return topics
	}

	topicRegex := []string{}

	// prepare regex
	for _, e := range strings.Split(topic, ".") {
		var quoted string

		switch e {
		case "*":
			// * to match any delimited topic name
			quoted = "[^\\.]*"
		case "#":
			// # to match any number of delimited topic names
			quoted = ".*"
		default:
			// escape characters for regex
			quoted = regexp.QuoteMeta(e)
		}

		topicRegex = append(topicRegex, quoted)
	}

	// add start / end of line markers to regex
	topics[topic] = "^" + strings.Join(topicRegex, "\\.") + "$"

	return topics
}


text:
package org.dylanfoundry.deft.filetypes.dylan.psi;

import com.intellij.extapi.psi.PsiFileBase;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.psi.FileViewProvider;
import org.dylanfoundry.deft.filetypes.dylan.DylanFileType;
import org.dylanfoundry.deft.filetypes.dylan.DylanLanguage;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;

public class DylanFile extends PsiFileBase {
  public DylanFile(@NotNull FileViewProvider viewProvider) {
    super(viewProvider, DylanLanguage.INSTANCE);
  }

  @NotNull
  @Override
  public FileType getFileType() {
    return DylanFileType.INSTANCE;
  }

  @Override
  public String toString() {
    return "Dylan File";
  }

  @Override
  public Icon getIcon(int flags) {
    return super.getIcon(flags);
  }
}


text:
namespace vast {

bool convert(address const& a, json& j) {
  j = to_string(a);
  return true;
}

} // namespace vast


text:
package pl.edu.pja.k1;

import static org.assertj.core.api.Assertions.assertThat;

import java.io.PrintWriter;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MainTest {

	@Rule
	public ExpectedException ex = ExpectedException.none();

	@Mock
	private PrintWriter pw;

	@Before
	public void setUp() {

	}

	@Test
	public void expectYelloWorldOnEmptyParam() {
		// given
		YelloMain main = new YelloMain();
		// when
		String greeting = main.buildGreetings(new String[0]);
		// then
		assertThat(greeting).isEqualTo("Yello world!");
	}

	@Test
	public void expectExceptionOnNullParam() {
		// given
		YelloMain main = new YelloMain();
		// then
		ex.expect(RuntimeException.class);
		// when
		main.buildGreetings(null);
	}

	@Test
	public void expectYelloFirstParamOnNonEmptyParam() {
		// given
		YelloMain main = new YelloMain();
		// when
		String[] args = { "Pablo" };
		String greeting = main.buildGreetings(args);
		// then
		assertThat(greeting).isEqualTo("Yello Pablo!");
	}

	@Test
	public void lama() {
		// given
		YelloMain main = new YelloMain();
		String[] args = { "Pablo" };
		// when
		main.greet(pw, args);
		// then
		Mockito.verify(pw).println(Mockito.anyString());
	}

}


text:
layout: post
title:  "Congestion avoidance and control"
description: "Paper presenting an efficient algorithm for network congestion avoidance and control, as a response to the first Internet congestion collapses that happened back in 1986."
date:   2021-08-10 23:40:00
tags: [networks, paper-summary]
comments: true
share: true
---

> Original article by Van Jacobson and Michael J. Karels: [https://dl.acm.org/doi/10.1145/52324.52356](https://dl.acm.org/doi/10.1145/52324.52356)

This paper presents an efficient algorithm to control network congestion during packet transmission. It describes its solution for avoiding congestions collapses by taking leverage of the slow start principle from the TCP protocol.

The authors propose an algorithm simple enough to require only a few lines of code, aiming to control the so-called congestion window time. The proposed algorithm promotes the retry of failed packet transmissions optimizing for high throughput.

During the experiments conducted to evaluate the solution, simultaneous TCP conversations happened to exchange more them 8000 TCP packets, from which only 89 had to be retried. The results show a reduction of packets retries from 40% to 1%, meaning almost a doubled throughput capacity.

The work provides a great contribution to describing how the algorithm works and its evaluation with rich graphs and benchmarks against different congestion control and avoidance scenarios such as multiple, simultaneous TCPs with and without congestion avoidance, and total bandwidth used by old and new TCPs.


text:
using System;
using Amberframe.Controllers.Abstractions;
using Amberframe.Controllers.Abstractions.Events;

namespace Amberframe.UI.Abstractions.Controls
{
    public interface ITextboxController : IController<ITextboxControllerMap>
    {
        Action<InputEvent> Left { get; set; }
        Action<InputEvent> Right { get; set; }
        Action<InputEvent> Up { get; set; }
        Action<InputEvent> Down { get; set; }
        Action<InputEvent> Delete { get; set; }
        Action<InputEvent> Backspace { get; set; }
        Action<InputEvent> Home { get; set; }
        Action<InputEvent> End { get; set; }
        Action<InputEvent> Chars { get; set; }
        Action<InputEvent> SelectAllCommandPressed { get; set; }
        Action<InputEvent> CopyCommandPressed { get; set; }
        Action<InputEvent> CutCommandPressed { get; set; }
    }
}


text:
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Azure.Identity;
using NUnit.Framework;

namespace Azure.Messaging.ServiceBus.Tests.Samples
{
    public class Sample01_HelloWorld : ServiceBusLiveTestBase
    {
        [Test]
        public async Task SendAndReceiveMessage()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                #region Snippet:ServiceBusSendAndReceive
                #region Snippet:ServiceBusSendSingleMessage
#if SNIPPET
                string connectionString = "<connection_string>";
                string queueName = "<queue_name>";
#else
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName = scope.QueueName;
#endif
                // since ServiceBusClient implements IAsyncDisposable we create it with "await using"
                await using var client = new ServiceBusClient(connectionString);

                // create the sender
                ServiceBusSender sender = client.CreateSender(queueName);

                // create a message that we can send. UTF-8 encoding is used when providing a string.
                ServiceBusMessage message = new ServiceBusMessage("Hello world!");

                // send the message
                await sender.SendMessageAsync(message);

                #endregion
                #region Snippet:ServiceBusReceiveSingleMessage
                // create a receiver that we can use to receive the message
                ServiceBusReceiver receiver = client.CreateReceiver(queueName);

                // the received message is a different type as it contains some service set properties
                ServiceBusReceivedMessage receivedMessage = await receiver.ReceiveMessageAsync();

                // get the message body as a string
                string body = receivedMessage.Body.ToString();
                Console.WriteLine(body);
                #endregion
                #endregion
                Assert.AreEqual("Hello world!", receivedMessage.Body.ToString());
            }
        }

        [Test]
        public async Task SendAndPeekMessage()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName = scope.QueueName;
                await using var client = new ServiceBusClient(connectionString);

                // create the sender
                ServiceBusSender sender = client.CreateSender(queueName);

                // create a message that we can send
                ServiceBusMessage message = new ServiceBusMessage("Hello world!");

                // send the message
                await sender.SendMessageAsync(message);

                // create a receiver that we can use to receive the message
                ServiceBusReceiver receiver = client.CreateReceiver(queueName);

                #region Snippet:ServiceBusPeek
                ServiceBusReceivedMessage peekedMessage = await receiver.PeekMessageAsync();
                #endregion

                // get the message body as a string
                string body = peekedMessage.Body.ToString();
                Assert.AreEqual("Hello world!", peekedMessage.Body.ToString());
            }
        }

        [Test]
        public async Task SendAndReceiveMessageBatch()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                #region Snippet:ServiceBusInitializeSend
#if SNIPPET
                string connectionString = "<connection_string>";
                string queueName = "<queue_name>";
#else
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName = scope.QueueName;
#endif
                // since ServiceBusClient implements IAsyncDisposable we create it with "await using"
                await using var client = new ServiceBusClient(connectionString);

                // create the sender
                ServiceBusSender sender = client.CreateSender(queueName);
                #region Snippet:ServiceBusSendAndReceiveBatch
                IList<ServiceBusMessage> messages = new List<ServiceBusMessage>();
                messages.Add(new ServiceBusMessage("First"));
                messages.Add(new ServiceBusMessage("Second"));
                // send the messages
                await sender.SendMessagesAsync(messages);
                #endregion
                #endregion
                #region Snippet:ServiceBusReceiveBatch
                // create a receiver that we can use to receive the messages
                ServiceBusReceiver receiver = client.CreateReceiver(queueName);

                // the received message is a different type as it contains some service set properties
                IReadOnlyList<ServiceBusReceivedMessage> receivedMessages = await receiver.ReceiveMessagesAsync(maxMessages: 2);

                foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)
                {
                    // get the message body as a string
                    string body = receivedMessage.Body.ToString();
                    Console.WriteLine(body);
                }
                #endregion

                var sentMessagesEnum = messages.GetEnumerator();
                foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)
                {
                    sentMessagesEnum.MoveNext();
                    Assert.AreEqual(sentMessagesEnum.Current.Body.ToString(), receivedMessage.Body.ToString());
                }
            }
        }

        [Test]
        public async Task SendAndReceiveMessageSafeBatch()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
#if SNIPPET
                string connectionString = "<connection_string>";
                string queueName = "<queue_name>";
#else
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName = scope.QueueName;
#endif
                // since ServiceBusClient implements IAsyncDisposable we create it with "await using"
                await using var client = new ServiceBusClient(connectionString);

                // create the sender
                ServiceBusSender sender = client.CreateSender(queueName);

                #region Snippet:ServiceBusSendAndReceiveSafeBatch
                // add the messages that we plan to send to a local queue
                Queue<ServiceBusMessage> messages = new Queue<ServiceBusMessage>();
                messages.Enqueue(new ServiceBusMessage("First message"));
                messages.Enqueue(new ServiceBusMessage("Second message"));
                messages.Enqueue(new ServiceBusMessage("Third message"));

                // create a message batch that we can send
                // total number of messages to be sent to the Service Bus queue
                int messageCount = messages.Count;

                // while all messages are not sent to the Service Bus queue
                while (messages.Count > 0)
                {
                    // start a new batch
                    using ServiceBusMessageBatch messageBatch = await sender.CreateMessageBatchAsync();

                    // add the first message to the batch
                    if (messageBatch.TryAddMessage(messages.Peek()))
                    {
                        // dequeue the message from the .NET queue once the message is added to the batch
                        messages.Dequeue();
                    }
                    else
                    {
                        // if the first message can't fit, then it is too large for the batch
                        throw new Exception($"Message {messageCount - messages.Count} is too large and cannot be sent.");
                    }

                    // add as many messages as possible to the current batch
                    while (messages.Count > 0 && messageBatch.TryAddMessage(messages.Peek()))
                    {
                        // dequeue the message from the .NET queue as it has been added to the batch
                        messages.Dequeue();
                    }

                    // now, send the batch
                    await sender.SendMessagesAsync(messageBatch);

                    // if there are any remaining messages in the .NET queue, the while loop repeats
                }
                #endregion

                // create a receiver that we can use to receive the messages
                ServiceBusReceiver receiver = client.CreateReceiver(queueName);

                // the received message is a different type as it contains some service set properties
                IReadOnlyList<ServiceBusReceivedMessage> receivedMessages = await receiver.ReceiveMessagesAsync(maxMessages: 2);

                foreach (ServiceBusReceivedMessage receivedMessage in receivedMessages)
                {
                    // get the message body as a string
                    string body = receivedMessage.Body.ToString();
                }
            }
        }

        [Test]
        public async Task ScheduleMessage()
        {
            await using (var scope = await ServiceBusScope.CreateWithQueue(enablePartitioning: false, enableSession: false))
            {
                string connectionString = TestEnvironment.ServiceBusConnectionString;
                string queueName = scope.QueueName;
                // since ServiceBusClient implements IAsyncDisposable we create it with "await using"
                await using var client = new ServiceBusClient(connectionString);

                // create the sender
                ServiceBusSender sender = client.CreateSender(queueName);

                // create a message that we can send
                ServiceBusMessage message = new ServiceBusMessage("Hello world!");

                #region Snippet:ServiceBusSchedule
                long seq = await sender.ScheduleMessageAsync(
                    message,
                    DateTimeOffset.Now.AddDays(1));
                #endregion

                // create a receiver that we can use to peek the message
                ServiceBusReceiver receiver = client.CreateReceiver(queueName);
                Assert.IsNotNull(await receiver.PeekMessageAsync());

                // cancel the scheduled messaged, thereby deleting from the service
                #region Snippet:ServiceBusCancelScheduled
                await sender.CancelScheduledMessageAsync(seq);
                #endregion
                Assert.IsNull(await receiver.PeekMessageAsync());
            }
        }

        /// <summary>
        /// Authenticate with <see cref="DefaultAzureCredential"/>.
        /// </summary>
        public void AuthenticateWithAAD()
        {
            #region Snippet:ServiceBusAuthAAD
            // Create a ServiceBusClient that will authenticate through Active Directory
            string fullyQualifiedNamespace = "yournamespace.servicebus.windows.net";
            ServiceBusClient client = new ServiceBusClient(fullyQualifiedNamespace, new DefaultAzureCredential());
            #endregion
        }

        /// <summary>
        /// Authenticate with <see cref="DefaultAzureCredential"/>.
        /// </summary>
        public void AuthenticateWithConnectionString()
        {
            #region Snippet:ServiceBusAuthConnString
            // Create a ServiceBusClient that will authenticate using a connection string
            string connectionString = "<connection_string>";
            ServiceBusClient client = new ServiceBusClient(connectionString);
            #endregion
        }

        /// <summary>
        /// Shows how to use <see cref="ServiceBusFailureReason"/> in <see cref="ServiceBusException"/>.
        /// </summary>
        public void ServiceBusExceptionFailureReasonUsage()
        {
            #region Snippet:ServiceBusExceptionFailureReasonUsage
            try
            {
                // Receive messages using the receiver client
            }
            catch (ServiceBusException ex) when
                (ex.Reason == ServiceBusFailureReason.ServiceTimeout)
            {
                // Take action based on a service timeout
            }
            #endregion
        }
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- activities -->
    <string name="app_name">Transistor</string>
    <!-- please do not translate app_name - transcription into different alphabet types is fine though -->
    <!-- app shortcuts -->
    <string name="shortcut_last_station_short_label">Остання станція</string>
    <string name="shortcut_last_station_long_label">Відтворити останню станцію</string>
    <string name="shortcut_last_station_disabled_message">Ярлик для відтворення останньої станції відключений.</string>
    <!-- menu entries -->
    <string name="menu_icon">Змінити піктограму</string>
    <string name="menu_delete">Видалити</string>
    <string name="menu_rename">Перейменувати</string>
    <string name="menu_shortcut">Розмістити на домашньому екрані</string>
    <!-- descriptions -->
    <string name="descr_app_icon">Піктограма застосунку з зображенням старого радіо</string>
    <string name="descr_station_options_button">Налаштування</string>
    <string name="descr_station_name_example">Приклад FM</string>
    <string name="descr_station_metadata_example">Артист - Заголовок</string>
    <string name="descr_station_stream_loading">Завантаження потоку …</string>
    <!--<string name="descr_playback_button_play"></string>-->
    <!--<string name="descr_playback_button_stop"></string>-->
    <string name="descr_playback_indicator">Відтворювана станція</string>
    <string name="descr_timer_icon">Часовідлік сну</string>
    <!--<string name="descr_player_sheet_button_minimize"></string>-->
    <string name="descr_player_sheet_content_copy_icon">Копіювати</string>
    <string name="descr_player_sheet_p_stream_url">Потокове посилання обраної радіостанції</string>
    <string name="descr_list_add_new">Додати нову станцію</string>
    <string name="descr_list_add_select_stream_dropdown">Виберіть потік</string>
    <!-- player -->
    <string name="player_sheet_h1_details">Подробиці</string>
    <string name="player_sheet_h2_current_session">Поточний сеанс</string>
    <string name="player_sheet_h2_station_metadata">Зараз відтворюється</string>
    <string name="player_sheet_h2_stream_url">URL потоку</string>
    <string name="player_sheet_h2_station_mime_type">Тип носія</string>
    <string name="player_sheet_h2_station_channel_count">Кількість каналів</string>
    <string name="player_sheet_h2_station_sample_rate">Частота дискретизації</string>
    <string name="player_sheet_h2_station_bitrate">Бітрейт</string>
    <!-- dialogs -->
    <string name="dialog_generic_button_cancel">Скасувати</string>
    <string name="dialog_add_station_button">Додати</string>
    <string name="dialog_add_station_input_hint">Вставити потокове посилання</string>
    <string name="dialog_add_station_message">Додати нову станцію</string>
    <string name="dialog_add_station_howto">Ви можете додавати звукові потоки, закодовані в MP3, AAC і Ogg/Opus, а також потоки, що містяться у файлах PLS або M3U. Крім того, ви можете додавати нові станції, натискаючи потокове посилання (.pls або .m3u) у своєму переглядачі мережі.</string>
    <string name="dialog_delete_station_message">Видалити станцію</string>
    <string name="dialog_button_delete">Видалити</string>
    <string name="dialog_generic_button_okay">Гаразд</string>
    <string name="dialog_rename_station_input_hint">Ввести нову назву</string>
    <string name="dialog_rename_station_message">Перейменувати станцію</string>
    <string name="dialog_button_rename">Перейменувати</string>
    <string name="dialog_add_station_choose_stream_heading">Знайдено кілька потоків</string>
    <string name="dialog_add_station_choose_stream_message">Будь ласка, виберіть потік</string>
    <string name="dialog_add_station_choose_stream_button">Вибрати</string>
    <!-- error dialogs -->
    <string name="dialog_error_title_default">Помилка</string>
    <string name="dialog_error_message_default">Сталась помилка</string>
    <string name="dialog_error_details_button_default">Показати подробиці</string>
    <string name="dialog_error_details_default">Подробиці відсутні</string>
    <string name="dialog_error_details_write">Ця станція, ймовірно, є дубльованою, або ви можете перевірити зовнішню пам\'ять.</string>
    <string name="dialog_error_title_fetch_download">Проблеми із завантаженням</string>
    <string name="dialog_error_title_fetch_read">Проблема під час читання</string>
    <string name="dialog_error_title_fetch_write">Проблема під час запису</string>
    <string name="dialog_error_message_fetch_general_external_storage">Зовнішнє сховище:</string>
    <string name="dialog_error_message_fetch_general_hint_m3u">Підказка: Transistor може обробляти лише закодовані в MP3, AAC і Ogg/Opus потоки, або посилання, що закінчуються на .m3u або .pls.</string>
    <string name="dialog_error_message_fetch_general_playlist_type">Тип носія файлу:</string>
    <string name="dialog_error_message_fetch_general_stream_type">MIME тип потоку:</string>
    <string name="dialog_error_message_fetch_general_file_content">Вміст віддаленого файлу:</string>
    <string name="dialog_error_message_fetch_download">Transistor намагався, але все ж таки не зміг зрозуміти посилання.</string>
    <string name="dialog_error_message_fetch_download_station_url">Потокове посилання станції:</string>
    <string name="dialog_error_message_fetch_read">Transistor не може обробити вказаний файл.</string>
    <string name="dialog_error_message_fetch_read_file_location">Розміщення файлу:</string>
    <string name="dialog_error_message_fetch_write">Transistor не зміг зберегти вказану станцію.</string>
    <!-- messages -->
    <string name="toastmessage_add_download_started">Завантаження розпочато.</string>
    <string name="toastmessage_add_open_file_started">Відкриття файлу.</string>
    <string name="toastmessage_long_press_playback_stopped">Відтворення зупинено</string>
    <string name="toastmessage_long_press_playback_started">Відтворення розпочато</string>
    <string name="toastmessage_long_press_change_icon">Зміна піктограми станції (виявлено довге натискання)</string>
    <string name="toastmessage_long_press_change_name">Перейменувати станцію (виявлено тривале натискання)</string>
    <!--<string name="toastmessage_theme_night"></string>-->
    <!--<string name="toastmessage_theme_day"></string>-->
    <!--<string name="toastmessage_theme_follow_system"></string>-->
    <string name="toastmessage_shortcut_created">Посилання створено.</string>
    <string name="toastmessage_shortcut_not_created">Ярлик не створено. Цей пристрій не дозволяє створювати ярлики.</string>
    <string name="toastmessage_list_refreshed">Перезавантаження списку станцій.</string>
    <string name="toastmessage_copied_to_clipboard">Потокове посилання скопійовано до буфера обміну.</string>
    <string name="toastmessage_station_copied">Станцію скопійовано до буфера обміну.</string>
    <string name="toastmessage_stream_may_not_work">Виявлено не підтримуваний звуковий формат. Відтворення потоку може працювати не коректно.</string>
    <string name="toastmessage_timer_activated">Таймер сну увімкнуто.</string>
    <string name="toastmessage_timer_cancelled">Таймер сну вимкнено.</string>
    <string name="toastmessage_timer_duration_increased">Тривалість збільшено.</string>
    <string name="toastalert_unable_to_connect">Неможливо під\'єднатися. Пристрій не має з\'єднання з Інтернетом або потік може бути застарілим.</string>
    <string name="toastalert_rename_unsuccessful">Не вдалося перейменувати станцію. Будь ласка, оберіть іншу назву.</string>
    <string name="toastalert_delete_successful">Станція була вилучена.</string>
    <string name="toastalert_no_external_storage">Не вдалося отримати доступ до зовнішнього сховища.</string>
    <string name="toastalert_no_image_picker">Немає доступного застосунку вибору зображень. Спробуйте встановити застосунок Галерея.</string>
    <string name="toastalert_headphones_unplugged">Навушники від\'єднано. Відтворення зупинено.</string>
    <string name="toastalert_permission_denied">Доступ не надано:</string>
    <string name="toastalert_station_not_found">Не вдалося знайти станцію.</string>
    <string name="snackbar_request_storage_access">Transistor потребує доступу для читання даних із зовнішнього сховища.</string>
    <string name="snackbar_message_timer_set">Таймер сну встановлено на</string>
    <!-- notification -->
    <string name="notification_play">Відтворити</string>
    <string name="notification_stop">Зупинити</string>
    <string name="notification_channel_playback_name">Елементи керування відтворенням</string>
    <string name="notification_channel_playback_description">Елементи керування відтворенням, логотип станції та дані відтворення.</string>
    <!-- onboarding -->
    <string name="onboarding_app_description">Застосунок радіо</string>
    <string name="onboarding_app_get_started">Розпочати</string>
    <!-- Version 3 of Transistor removes the screens infosheet_howto and infosheet_about.
    The last version containing those strings is v2.3.7
    https://github.com/y20k/transistor/tree/v2.3.7/app/src/main/res -->
    <string name="toastmessage_theme_night">Перехід у нічний режим (виявлено довге натискання)</string>
    <string name="toastmessage_theme_day">Перехід у денний режим (виявлено довге натискання)</string>
    <string name="toastmessage_theme_follow_system">Перехід до режиму налаштувань системи (виявлено довге натискання)</string>
    <string name="descr_playback_button_play">Відтворити</string>
    <string name="descr_playback_button_stop">Зупинити</string>
    <string name="descr_player_sheet_button_minimize">Приховати відомості про станцію</string>
    <string name="toastmessage_sleep_timer_unable_to_start">Будь ласка, спочатку почніть відтворення.</string>
    <string name="dialog_button_save">Зберегти зміни</string>
    <string name="onboarding_app_import_running">Імпортування ваших станцій…</string>
    <string name="descr_player_playback_button">Відтворення/Зупинка</string>
    <string name="descr_player_station_image">Зображення станції</string>
    <string name="descr_expanded_player_sleep_timer_start_button">Запустити відлік сну</string>
    <string name="descr_expanded_player_sleep_timer_remaining_time">Час до сну</string>
    <string name="descr_expanded_player_sleep_timer_cancel_button">Скасувати відлік сну</string>
    <string name="descr_dialog_edit_update_icon">Оновити</string>
    <string name="descr_dialog_edit_station_image">Зображення станції</string>
    <string name="descr_dialog_edit_place_on_home_screen_icon">Помістити на головний екран</string>
    <string name="descr_card_station_image">Зображення станції</string>
    <string name="descr_card_starred_station">Обрана станція</string>
    <string name="descr_card_small_edit_button">Правити</string>
    <string name="descr_card_small_play_button">Програвати/Зупинити</string>
    <string name="descr_card_small_download_button">Завантажити</string>
    <string name="descr_card_settings_button">Налаштування</string>
    <string name="descr_card_playback_indicator">Перебіг відтворення</string>
    <string name="pref_update_station_images_title">Оновити зображення станцій</string>
    <string name="pref_update_station_images_summary">Завантажити найновіші версії всіх зображень станцій.</string>
    <string name="pref_update_collection_title">Оновити станції</string>
    <string name="pref_update_collection_summary">Шукайте оновлені аудіопотоки та нові зображення станцій.</string>
    <string name="pref_theme_selection_title">Тема застосунку</string>
    <string name="pref_theme_selection_summary">Поточна тема:</string>
    <string name="pref_theme_selection_mode_light">Світлий режим</string>
    <string name="pref_theme_selection_mode_device_default">Тема пристрою</string>
    <string name="pref_theme_selection_mode_dark">Темний режим</string>
    <string name="pref_report_issue_title">Повідомити про помилку</string>
    <string name="pref_report_issue_summary">Повідомте про помилки та запропонуйте вдосконалення на GitHub.</string>
    <string name="pref_maintenance_title">Обслуговування</string>
    <string name="pref_general_title">Загальне</string>
    <string name="pref_delete_all_title">Видалити завантаження</string>
    <string name="pref_app_version_title">Версія застосунку</string>
    <string name="pref_app_version_summary">Версія</string>
    <string name="pref_about_title">Про нас</string>
    <string name="notification_skip_to_next">Наступна</string>
    <string name="notification_skip_to_previous">Попередня</string>
    <string name="notification_playing">Відтворюється</string>
    <string name="notification_now_playing_channel_description">Елементи керування відтворенням, назва станції та зображення.</string>
    <string name="notification_now_playing_channel_name">Елементи керування відтворенням</string>
    <string name="station_list_button_add_new_station">Додати нову станцію</string>
    <string name="toastmessage_updating_station_images">Оновлення зображень станції.</string>
    <string name="toastmessage_updating_station">Оновлення станції…</string>
    <string name="toastmessage_updating_collection">Оновлення набору станцій.</string>
    <string name="toastmessage_station_not_valid">Станція недійсна.</string>
    <string name="toastmessage_station_duplicate">Подвоєння станції.</string>
    <string name="toastmessage_error_restart_playback_failed">Неможливо перезапустити відтворення.</string>
    <string name="toastmessage_error_no_station_found">Не вдається розпочати відтворення. Спочатку додайте радіостанцію.</string>
    <string name="toastmessage_error_no_station_matches_search">Не вдається знайти станцію, яка відповідає вашому пошуку.</string>
    <string name="toastmessage_error_missing_storage_permission">Надайте доступ до сховища для відкриття цього файлу.</string>
    <string name="toastmessage_error_download_error">Помилка завантаження</string>
    <string name="toastmessage_collection_update_not_necessary">Набір станцій найновіший.</string>
    <string name="menu_update">Оновити станцію</string>
    <string name="dialog_yes_no_title_default">Обрати</string>
    <string name="dialog_yes_no_positive_button_vpn_download">Однаково завантажити</string>
    <string name="dialog_yes_no_positive_button_update_covers">Оновити</string>
    <string name="dialog_yes_no_positive_button_update_collection">Оновити</string>
    <string name="dialog_yes_no_positive_button_remove_station">Видалити</string>
    <string name="dialog_yes_no_positive_button_non_wifi_download">Однаково завантажити</string>
    <string name="dialog_yes_no_positive_button_delete_downloads">Видалити все</string>
    <string name="dialog_yes_no_positive_button_default">Так</string>
    <string name="dialog_yes_no_positive_button_add_up_next">Запуск</string>
    <string name="dialog_yes_no_negative_button_default">Ні</string>
    <string name="dialog_yes_no_negative_button_cancel">Скасувати</string>
    <string name="dialog_yes_no_negative_button_add_up_next">Додати до \"Наступного\"</string>
    <string name="dialog_yes_no_message_update_station_images">Завантажити найновіші версії всіх зображень станцій\?</string>
    <string name="dialog_yes_no_message_update_collection">Шукати зміни\?</string>
    <string name="dialog_yes_no_message_remove_station">Видалити цю станцію\?</string>
    <string name="dialog_yes_no_message_default">Ви справді хочете це зробити\?</string>
    <string name="dialog_opml_import_details_default">Подробиці недоступні</string>
    <string name="dialog_opml_import_details_button">Показати подробиці</string>
    <string name="dialog_opml_import_button_okay">Імпорт</string>
    <string name="dialog_generic_details_default">Подробиці недоступні</string>
    <string name="dialog_generic_details_button">Показати подробиці</string>
    <string name="dialog_find_station_title">Знайти станцію</string>
    <string name="dialog_find_station_no_results">Нічого не знайдено.</string>
    <string name="dialog_find_station_hint">Назва або адреса потоку</string>
    <string name="dialog_find_station_button_add">Додати</string>
    <string name="dialog_error_title_no_network">Безмережно</string>
    <string name="dialog_error_message_no_network">Під\'єднатися до Інтернету.</string>
    <string name="dialog_edit_update_station">Оновити станцію</string>
    <string name="dialog_edit_title">Редагувати станцію</string>
    <string name="dialog_edit_place_on_home_screen">Розмістити на головному екрані</string>
    <string name="dialog_edit_choose_station_image">Обрати</string>
    <string name="fragment_settings_title">Налаштування</string>
    <string name="pref_m3u_export_title">Експорт M3U</string>
    <string name="pref_m3u_export_summary">Збережіть свої радіостанції у файлі списку відтворення M3U, який можна імпортувати в інші програвачі.</string>
    <string name="toastmessage_save_m3u">Збереження радіостанцій у форматі M3U…</string>
    <string name="toastmessage_install_file_helper">Будь ласка, встановіть менеджер файлів.</string>
    <string name="station_list_button_settings">Налаштування</string>
    <string name="pref_advanced_title">Додаткові</string>
    <string name="pref_edit_station_summary_disabled">Редагування відомостей про станцію вимкнено.</string>
    <string name="pref_edit_station_summary_enabled">Редагування відомостей про станцію ввімкнуто. Щоб увійти в режим редагування натисніть та утримуйте.</string>
    <string name="pref_edit_station_title">Редагувати станції</string>
    <string name="pref_edit_station_stream_summary_disabled">Редагування посилань потоків вимкнено.</string>
    <string name="pref_edit_station_stream_title">Редагувати посилань потоків</string>
    <string name="descr_card_station_image_change">Змінити зображення станції</string>
    <string name="pref_edit_station_stream_summary_enabled">Редагування посилань потоків увімкнено. Обов\'язково введіть правильну адресу потоку.</string>
    <string name="dialog_edit_station_name">Назва станції</string>
    <string name="dialog_edit_save_changes">Зберегти зміни</string>
    <string name="dialog_edit_stream_uri">Адреса потоку</string>
    <string name="pref_backup_summary">Збережіть колекцію радіостанцій, включно зображеннями, у сховище пристрою.</string>
    <string name="toastmessage_restoring_collection">Відновлення радіостанцій з резервної копії.</string>
    <string name="pref_backup_title">Резервування станцій</string>
    <string name="pref_restore_title">Відновити станції</string>
    <string name="pref_restore_summary">Відновити колекцію радіостанцій з резервної копії. Наявні станції будуть замінені.</string>
    <string name="toastmessage_collection_backup">Резервування радіостанцій на:</string>
    <string name="app_version_name" translatable="false"></string>
    <string name="onboarding_app_rodriguez_quote_1" translatable="false"></string>
    <string name="onboarding_app_rodriguez_quote_2" translatable="false"></string>
    <string name="sample_text_station_name" translatable="false"></string>
    <string name="player_sheet_p_no_data" translatable="false"></string>
    <string name="sample_text_station_metadata" translatable="false"></string>
    <string name="sample_text_steam_url" translatable="false"></string>
    <string name="sample_text_sleep_timer_remaining_time" translatable="false"></string>
</resources>