@gorgo/medusa-payment-robokassa
Version:
Robokassa payment provider for Medusa
337 lines • 32.1 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const utils_1 = require("@medusajs/framework/utils");
const types_1 = require("../types");
const axios_1 = __importDefault(require("axios"));
const fast_xml_parser_1 = require("fast-xml-parser");
const utils_2 = require("../utils");
const crypto_1 = require("crypto");
const telemetry_1 = require("@gorgo/telemetry");
class RobokassaBase extends utils_1.AbstractPaymentProvider {
static validateOptions(options) {
RobokassaBase.telemetry_.track("plugin.started");
if (!(0, utils_1.isDefined)(options.merchantLogin)) {
throw new Error("Required option `merchantLogin` is missing in Robokassa provider");
}
if (!(0, utils_1.isDefined)(options.password1)) {
throw new Error("Required option `password1` is missing in Robokassa provider");
}
if (!(0, utils_1.isDefined)(options.password2)) {
throw new Error("Required option `password2` is missing in Robokassa provider");
}
if (!(0, utils_1.isDefined)(options.hashAlgorithm) || !types_1.HashAlgorithms.includes(options.hashAlgorithm)) {
throw new Error("Required option `hashAlgorithm` is missing in Robokassa provider");
}
if (options.useReceipt == true) {
if (!(0, utils_1.isDefined)(options.taxation)) {
throw new Error("Required option `taxation` is missing in Robokassa provider");
}
else if (!types_1.taxations.includes(options.taxation)) {
throw new Error(`Invalid option \`taxation\` provided in Robokassa provider. Valid values are: ${types_1.taxations.join(", ")}`);
}
if (!(0, utils_1.isDefined)(options.taxItemDefault)) {
throw new Error("Required option `taxItemDefault` is missing in Robokassa provider");
}
else if (!types_1.taxes.includes(options.taxItemDefault)) {
throw new Error(`Invalid option \`taxItemDefault\` provided in Robokassa provider. Valid values are: ${types_1.taxes.join(", ")}`);
}
if (!(0, utils_1.isDefined)(options.taxShippingDefault)) {
throw new Error("Required option `taxShippingDefault` is missing in Robokassa provider");
}
else if (!types_1.taxes.includes(options.taxShippingDefault)) {
throw new Error(`Invalid option \`taxShippingDefault\` provided in Robokassa provider. Valid values are: ${types_1.taxes.join(", ")}`);
}
}
}
constructor(container, options) {
super(container, options);
this.baseUrl_ = "https://auth.robokassa.ru";
this.paymentUrl_ = `${this.baseUrl_}/Merchant/Index.aspx`;
this.getPaymentUrl_ = `${this.baseUrl_}/Merchant/WebService/Service.asmx/OpStateExt`;
this.capturePaymentUrl_ = `${this.baseUrl_}/Merchant/Payment/Confirm`;
this.options_ = options;
this.logger_ = container.logger;
}
createSignature(signatureParams) {
const concatenatedParams = signatureParams.filter(v => v).join(":");
const res = (0, crypto_1.createHash)(this.options_.hashAlgorithm).update(concatenatedParams).digest('hex');
return res;
}
normalizePaymentParameters(extra) {
const res = {};
if (extra?.data?.SuccessUrl2)
res.SuccessUrl2 = extra?.data?.SuccessUrl2;
if (extra?.data?.SuccessUrl2Method)
res.SuccessUrl2Method = extra?.data?.SuccessUrl2Method;
if (extra?.data?.FailUrl2)
res.FailUrl2 = extra?.data?.FailUrl2;
if (extra?.data?.FailUrl2Method)
res.FailUrl2Method = extra?.data?.FailUrl2Method;
if (extra?.data?.EMail)
res.EMail = extra?.data?.EMail;
if (extra?.data?.Culture)
res.Culture = extra?.data?.Culture;
const isTest = extra?.data?.isTest ??
(this.options_.isTest ? "1" : undefined);
if (isTest !== undefined)
res.isTest = isTest;
const stepByStep = extra?.data?.StepByStep ??
(this.options_.capture === false ? "true" : undefined);
if (stepByStep !== undefined)
res.StepByStep = stepByStep;
return res;
}
/**
* Initiate a new payment.
*/
async initiatePayment(input) {
this.logger_.debug(`RobokassaBase.initiatePayment input:\n${JSON.stringify(input, null, 2)}`);
const { amount, context = {} } = input;
const outSum = Number(amount).toFixed(2);
// TODO: can we avoide generating invoice id?
const invoiceId = (0, utils_2.stringToNumberHash)(context.idempotency_key).toString();
const sessionId = input.data?.session_id;
const cart = input.data?.cart;
const additionalParameters = this.normalizePaymentParameters(input);
let receipt = {};
if (this.options_.useReceipt && cart) {
receipt = (0, utils_2.generateReceipt)(this.options_.taxation, this.options_.taxItemDefault, this.options_.taxShippingDefault, input.data?.cart);
}
const receiptJson = JSON.stringify(receipt);
const receiptEncoded = encodeURIComponent(receiptJson);
const raw = [
this.options_.merchantLogin,
outSum,
invoiceId,
...(this.options_.useReceipt ? [receiptJson] : []),
...(additionalParameters.StepByStep ? [additionalParameters.StepByStep] : []),
additionalParameters.SuccessUrl2,
additionalParameters.SuccessUrl2Method,
additionalParameters.FailUrl2,
additionalParameters.FailUrl2Method,
this.options_.isTest ? this.options_.testPassword1 : this.options_.password1,
`Shp_SessionID=${sessionId}`
];
const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm);
const payment = {
MerchantLogin: this.options_.merchantLogin,
OutSum: outSum,
...(this.options_.useReceipt ? { Receipt: receiptEncoded } : {}),
InvoiceID: invoiceId,
SignatureValue: signature,
Shp_SessionID: sessionId,
...additionalParameters
};
const params = new URLSearchParams(payment).toString();
const paymentUrl = `${this.paymentUrl_}?${params}`;
const output = {
id: invoiceId,
data: {
paymentUrl: paymentUrl,
...payment
}
};
this.logger_.debug("RobokassaBase.initiatePayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
/**
* Capture an existing payment.
*/
async capturePayment(input) {
this.logger_.debug(`RobokassaBase.capturePayment input:\n${JSON.stringify(input, null, 2)}`);
const invoiceId = input.data?.InvoiceID;
const outSum = input.data?.OutSum;
const raw = [
this.options_.merchantLogin,
outSum,
invoiceId,
this.options_.isTest ? this.options_.testPassword1 : this.options_.password1
];
const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm);
const capturePayment = {
MerchantLogin: this.options_.merchantLogin,
InvoiceID: invoiceId,
SignatureValue: signature,
OutSum: outSum
};
const params = new URLSearchParams(capturePayment).toString();
const capturePaymentUrl = `${this.capturePaymentUrl_}?${params}`;
try {
const response = await axios_1.default.post(capturePaymentUrl);
const output = { data: response.data };
this.logger_.debug("RobokassaBase.capturePayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
catch (e) {
throw this.buildError("An error occurred in capturePayment", e);
}
}
/**
* Authorize a payment by retrieving its status.
*/
async authorizePayment(input) {
this.logger_.debug(`RobokassaBase.authorizePayment input:\n${JSON.stringify(input, null, 2)}`);
const output = await this.getPaymentStatus(input);
this.logger_.debug("RobokassaBase.authorizePayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
/**
* Delete a payment.
* Payment delete is not supported by Robokassa.
*/
async deletePayment(input) {
this.logger_.debug(`RobokassaBase.deletePayment input:\n${JSON.stringify(input, null, 2)}`);
const output = input;
this.logger_.debug("RobokassaBase.deletePayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
/**
* Update a payment.
* Payment update is not supported by Robokassa.
*/
async updatePayment(input) {
this.logger_.debug(`RobokassaBase.updatePayment input:\n${JSON.stringify(input, null, 2)}`);
const output = input;
this.logger_.debug("RobokassaBase.updatePayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
/**
* Refund a payment.
* Payment refund is not supported by Robokassa.
*/
async refundPayment(input) {
this.logger_.debug(`RobokassaBase.refundPayment input:\n${JSON.stringify(input, null, 2)}`);
const output = input;
this.logger_.debug("RobokassaBase.refundPayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
/**
* Cancel an existing payment.
*/
async cancelPayment(input) {
this.logger_.debug(`RobokassaBase.cancelPayment input:\n${JSON.stringify(input, null, 2)}`);
const output = input;
this.logger_.debug("RobokassaBase.cancelPayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
/**
* Retrieve a payment.
*/
async retrievePayment(input) {
this.logger_.debug(`RobokassaBase.retrievePayment input:\n${JSON.stringify(input, null, 2)}`);
const invoiceId = input.data?.InvoiceID;
const raw = [
this.options_.merchantLogin,
invoiceId,
this.options_.isTest ? this.options_.testPassword2 : this.options_.password2
];
const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm);
const params = new URLSearchParams({
MerchantLogin: this.options_.merchantLogin,
InvoiceID: invoiceId,
Signature: signature,
}).toString();
const url = `${this.getPaymentUrl_}?${params}`;
try {
const { data: xml } = await axios_1.default.post(url);
const parser = new fast_xml_parser_1.XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "@_",
});
const parsed = parser.parse(xml);
const response = parsed['OperationStateResponse'];
const output = {
data: {
...input.data,
response: response
}
};
this.logger_.debug("RobokassaBase.retrievePayment output:\n" + JSON.stringify(output, null, 2));
return output;
}
catch (e) {
throw this.buildError("An error occurred in retrievePayment", e);
}
}
/**
* Retrieve payment status and map it to Medusa status.
*/
async getPaymentStatus(input) {
this.logger_.debug(`RobokassaBase.getPaymentStatus input:\n${JSON.stringify(input, null, 2)}`);
try {
const response = (await this.retrievePayment(input)).data?.response;
if (!response || !response.Result || !response.State) {
throw new Error("Invalid response structure from Robokassa");
}
const result = response.Result;
const state = response.State;
const resultCode = parseInt(result.Code, 10);
const resultDescription = result.Description;
if (resultCode !== 0) {
throw new Error(`Robokassa error ${resultCode}: ${resultDescription}`);
}
const paymentState = parseInt(state.Code, 10);
const map = {
10: utils_1.PaymentSessionStatus.CANCELED,
60: utils_1.PaymentSessionStatus.CANCELED,
20: utils_1.PaymentSessionStatus.AUTHORIZED,
5: utils_1.PaymentSessionStatus.PENDING,
50: utils_1.PaymentSessionStatus.PENDING,
3: utils_1.PaymentSessionStatus.PENDING,
80: utils_1.PaymentSessionStatus.REQUIRES_MORE,
100: utils_1.PaymentSessionStatus.CAPTURED,
};
const status = map[paymentState] ?? utils_1.PaymentSessionStatus.ERROR;
const output = { status, data: { ...input.data, response } };
this.logger_.debug("RobokassaBase.getPaymentStatus output:\n" + JSON.stringify(output, null, 2));
return output;
}
catch (e) {
throw this.buildError("An error occurred in getPaymentStatus", e);
}
}
async getWebhookActionAndData(payload) {
this.logger_.debug(`RobokassaBase.getWebhookActionAndData payload:\n${JSON.stringify(payload, null, 2)}`);
const data = payload.data;
const isValid = await this.isWebhookEventValid(data);
if (!isValid)
return {
action: utils_1.PaymentActions.NOT_SUPPORTED
};
const sessionId = data.Shp_SessionID;
const outSum = Number(data.OutSum);
const result = {
action: utils_1.PaymentActions.SUCCESSFUL,
data: { session_id: sessionId, amount: outSum }
};
this.logger_.debug("RobokassaBase.getWebhookActionAndData result:\n" + JSON.stringify(result, null, 2));
return result;
}
async isWebhookEventValid(data) {
const incomingSignature = data.SignatureValue;
const raw = [
data.OutSum,
data.InvId,
this.options_.password2,
`Shp_SessionID=${data.Shp_SessionID}`
];
const signature = (0, utils_2.createSignature)(raw, this.options_.hashAlgorithm);
return signature === incomingSignature;
}
/**
* Helper to build errors with additional context.
*/
buildError(message, error) {
if (axios_1.default.isAxiosError(error)) {
return new Error(`${message}: ${error.response?.status} ${error.response?.data?.code} - ${error.response?.data?.description}`.trim());
}
return new Error(`${message}: ${error.message}`.trim());
}
}
RobokassaBase.identifier = "robokassa";
RobokassaBase.telemetry_ = (0, telemetry_1.createTelemetryClient)({ packageDir: __dirname });
exports.default = RobokassaBase;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9ib2thc3NhLWJhc2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvcHJvdmlkZXJzL3BheW1lbnQtcm9ib2thc3NhL2NvcmUvcm9ib2thc3NhLWJhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSxxREFLa0M7QUFhbEMsb0NBUWlCO0FBQ2pCLGtEQUF5QztBQUN6QyxxREFBMkM7QUFDM0Msb0NBSWlCO0FBQ2pCLG1DQUFtQztBQUNuQyxnREFBd0Q7QUFFeEQsTUFBZSxhQUFjLFNBQVEsK0JBQXlDO0lBVzVFLE1BQU0sQ0FBQyxlQUFlLENBQUMsT0FBeUI7UUFDOUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTtRQUVoRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDO1lBQ3RDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0VBQWtFLENBQUMsQ0FBQTtRQUNyRixDQUFDO1FBQ0QsSUFBSSxDQUFDLElBQUEsaUJBQVMsRUFBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQztZQUNsQyxNQUFNLElBQUksS0FBSyxDQUFDLDhEQUE4RCxDQUFDLENBQUE7UUFDakYsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFBLGlCQUFTLEVBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyw4REFBOEQsQ0FBQyxDQUFBO1FBQ2pGLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLHNCQUFjLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxhQUFnRCxDQUFDLEVBQUUsQ0FBQztZQUM1SCxNQUFNLElBQUksS0FBSyxDQUFDLGtFQUFrRSxDQUFDLENBQUE7UUFDckYsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLFVBQVUsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMvQixJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUNqQyxNQUFNLElBQUksS0FBSyxDQUFDLDZEQUE2RCxDQUFDLENBQUE7WUFDaEYsQ0FBQztpQkFBTSxJQUFJLENBQUMsaUJBQVMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7Z0JBQ2pELE1BQU0sSUFBSSxLQUFLLENBQUMsaUZBQWlGLGlCQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUMxSCxDQUFDO1lBQ0QsSUFBSSxDQUFDLElBQUEsaUJBQVMsRUFBQyxPQUFPLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztnQkFDdkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxtRUFBbUUsQ0FBQyxDQUFBO1lBQ3RGLENBQUM7aUJBQU0sSUFBSSxDQUFDLGFBQUssQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLENBQUM7Z0JBQ25ELE1BQU0sSUFBSSxLQUFLLENBQUMsdUZBQXVGLGFBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQzVILENBQUM7WUFDRCxJQUFJLENBQUMsSUFBQSxpQkFBUyxFQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7Z0JBQzNDLE1BQU0sSUFBSSxLQUFLLENBQUMsdUVBQXVFLENBQUMsQ0FBQTtZQUMxRixDQUFDO2lCQUFNLElBQUksQ0FBQyxhQUFLLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZELE1BQU0sSUFBSSxLQUFLLENBQUMsMkZBQTJGLGFBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBQ2hJLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELFlBQVksU0FBNkIsRUFBRSxPQUF5QjtRQUNsRSxLQUFLLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFBO1FBeENqQixhQUFRLEdBQUcsMkJBQTJCLENBQUE7UUFDdEMsZ0JBQVcsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLHNCQUFzQixDQUFBO1FBQ3BELG1CQUFjLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSw4Q0FBOEMsQ0FBQTtRQUMvRSx1QkFBa0IsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLDJCQUEyQixDQUFBO1FBc0N4RSxJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQTtRQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUE7SUFDakMsQ0FBQztJQUVTLGVBQWUsQ0FDdkIsZUFBeUI7UUFFekIsTUFBTSxrQkFBa0IsR0FBRyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFBO1FBQ25FLE1BQU0sR0FBRyxHQUFHLElBQUEsbUJBQVUsRUFBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtRQUU1RixPQUFPLEdBQUcsQ0FBQTtJQUNaLENBQUM7SUFFTywwQkFBMEIsQ0FDaEMsS0FBNEI7UUFFNUIsTUFBTSxHQUFHLEdBQUcsRUFBc0IsQ0FBQTtRQUVsQyxJQUFJLEtBQUssRUFBRSxJQUFJLEVBQUUsV0FBVztZQUMxQixHQUFHLENBQUMsV0FBVyxHQUFHLEtBQUssRUFBRSxJQUFJLEVBQUUsV0FBcUMsQ0FBQTtRQUV0RSxJQUFJLEtBQUssRUFBRSxJQUFJLEVBQUUsaUJBQWlCO1lBQ2hDLEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLEVBQUUsSUFBSSxFQUFFLGlCQUFpRCxDQUFBO1FBRXhGLElBQUksS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRO1lBQ3ZCLEdBQUcsQ0FBQyxRQUFRLEdBQUcsS0FBSyxFQUFFLElBQUksRUFBRSxRQUErQixDQUFBO1FBRTdELElBQUksS0FBSyxFQUFFLElBQUksRUFBRSxjQUFjO1lBQzdCLEdBQUcsQ0FBQyxjQUFjLEdBQUcsS0FBSyxFQUFFLElBQUksRUFBRSxjQUEyQyxDQUFBO1FBRS9FLElBQUksS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLO1lBQ3BCLEdBQUcsQ0FBQyxLQUFLLEdBQUcsS0FBSyxFQUFFLElBQUksRUFBRSxLQUF5QixDQUFBO1FBRXBELElBQUksS0FBSyxFQUFFLElBQUksRUFBRSxPQUFPO1lBQ3RCLEdBQUcsQ0FBQyxPQUFPLEdBQUcsS0FBSyxFQUFFLElBQUksRUFBRSxPQUE2QixDQUFBO1FBRTFELE1BQU0sTUFBTSxHQUNWLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBMkI7WUFDeEMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUMxQyxJQUFJLE1BQU0sS0FBSyxTQUFTO1lBQUUsR0FBRyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUE7UUFFN0MsTUFBTSxVQUFVLEdBQ2QsS0FBSyxFQUFFLElBQUksRUFBRSxVQUFtQztZQUNoRCxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUN4RCxJQUFJLFVBQVUsS0FBSyxTQUFTO1lBQUUsR0FBRyxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUE7UUFFekQsT0FBTyxHQUFHLENBQUE7SUFDWixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsZUFBZSxDQUFDLEtBQTJCO1FBQy9DLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUNoQix5Q0FBeUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQzFFLENBQUE7UUFFRCxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sR0FBRyxFQUFFLEVBQUUsR0FBRyxLQUFLLENBQUE7UUFFdEMsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUN4Qyw2Q0FBNkM7UUFDN0MsTUFBTSxTQUFTLEdBQUcsSUFBQSwwQkFBa0IsRUFBQyxPQUFPLENBQUMsZUFBeUIsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFBO1FBQ2xGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsVUFBb0IsQ0FBQTtRQUNsRCxNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQTJCLENBQUE7UUFFcEQsTUFBTSxvQkFBb0IsR0FBRyxJQUFJLENBQUMsMEJBQTBCLENBQUMsS0FBSyxDQUFDLENBQUE7UUFFbkUsSUFBSSxPQUFPLEdBQUcsRUFBYSxDQUFBO1FBQzNCLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLElBQUksSUFBSSxFQUFFLENBQUM7WUFDckMsT0FBTyxHQUFHLElBQUEsdUJBQWUsRUFDdkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFTLEVBQ3ZCLElBQUksQ0FBQyxRQUFRLENBQUMsY0FBZSxFQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLGtCQUFtQixFQUNqQyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQTJCLENBQ3hDLENBQUE7UUFDSCxDQUFDO1FBRUQsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUMzQyxNQUFNLGNBQWMsR0FBRyxrQkFBa0IsQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUV0RCxNQUFNLEdBQUcsR0FBRztZQUNWLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYTtZQUMzQixNQUFNO1lBQ04sU0FBUztZQUNULEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ2xELEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUM3RSxvQkFBb0IsQ0FBQyxXQUFXO1lBQ2hDLG9CQUFvQixDQUFDLGlCQUFpQjtZQUN0QyxvQkFBb0IsQ0FBQyxRQUFRO1lBQzdCLG9CQUFvQixDQUFDLGNBQWM7WUFDbkMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVM7WUFDNUUsaUJBQWlCLFNBQVMsRUFBRTtTQUM3QixDQUFBO1FBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBQSx1QkFBZSxFQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBRW5FLE1BQU0sT0FBTyxHQUFZO1lBQ3ZCLGFBQWEsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWE7WUFDMUMsTUFBTSxFQUFFLE1BQU07WUFDZCxHQUFHLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDaEUsU0FBUyxFQUFFLFNBQVM7WUFDcEIsY0FBYyxFQUFFLFNBQVM7WUFDekIsYUFBYSxFQUFFLFNBQVM7WUFDeEIsR0FBRyxvQkFBb0I7U0FDeEIsQ0FBQTtRQUVELE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxDQUFDLE9BQTRDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtRQUMzRixNQUFNLFVBQVUsR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLElBQUksTUFBTSxFQUFFLENBQUE7UUFFbEQsTUFBTSxNQUFNLEdBQUc7WUFDYixFQUFFLEVBQUUsU0FBUztZQUNiLElBQUksRUFBRTtnQkFDSixVQUFVLEVBQUUsVUFBVTtnQkFDdEIsR0FBRyxPQUFPO2FBQ1g7U0FDRixDQUFBO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMseUNBQXlDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDL0YsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsY0FBYyxDQUFDLEtBQTBCO1FBQzdDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLHdDQUF3QyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBRTVGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsU0FBbUIsQ0FBQTtRQUNqRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxFQUFFLE1BQWdCLENBQUE7UUFFM0MsTUFBTSxHQUFHLEdBQUc7WUFDVixJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWE7WUFDM0IsTUFBTTtZQUNOLFNBQVM7WUFDVCxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUztTQUM3RSxDQUFBO1FBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBQSx1QkFBZSxFQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFBO1FBRW5FLE1BQU0sY0FBYyxHQUFxQjtZQUN2QyxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhO1lBQzFDLFNBQVMsRUFBRSxTQUFTO1lBQ3BCLGNBQWMsRUFBRSxTQUFTO1lBQ3pCLE1BQU0sRUFBRSxNQUFNO1NBQ2YsQ0FBQTtRQUNELE1BQU0sTUFBTSxHQUFHLElBQUksZUFBZSxDQUFDLGNBQW1ELENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtRQUNsRyxNQUFNLGlCQUFpQixHQUFHLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixJQUFJLE1BQU0sRUFBRSxDQUFBO1FBRWhFLElBQUksQ0FBQztZQUNILE1BQU0sUUFBUSxHQUFHLE1BQU0sZUFBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO1lBRXBELE1BQU0sTUFBTSxHQUFHLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxJQUEwQyxFQUFFLENBQUE7WUFDNUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0NBQXdDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDOUYsT0FBTyxNQUFNLENBQUE7UUFDZixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxxQ0FBcUMsRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNqRSxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUFDLEtBQTRCO1FBQ2pELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLDBDQUEwQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBRTlGLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ2pELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLDBDQUEwQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ2hHLE9BQU8sTUFBTSxDQUFBO0lBQ2YsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBeUI7UUFDM0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUNBQXVDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFM0YsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFBO1FBQ3BCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLHVDQUF1QyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzdGLE9BQU8sTUFBTSxDQUFBO0lBQ2YsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBeUI7UUFDM0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUNBQXVDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFM0YsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFBO1FBQ3BCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLHVDQUF1QyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzdGLE9BQU8sTUFBTSxDQUFBO0lBQ2YsQ0FBQztJQUVEOzs7T0FHRztJQUNILEtBQUssQ0FBQyxhQUFhLENBQUMsS0FBeUI7UUFDM0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUNBQXVDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUE7UUFFM0YsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFBO1FBQ3BCLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLHVDQUF1QyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzdGLE9BQU8sTUFBTSxDQUFBO0lBQ2YsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGFBQWEsQ0FBQyxLQUF5QjtRQUMzQyxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyx1Q0FBdUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUUzRixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUE7UUFDcEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsdUNBQXVDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDN0YsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0lBRUQ7O09BRUc7SUFDSCxLQUFLLENBQUMsZUFBZSxDQUFDLEtBQTJCO1FBQy9DLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLHlDQUF5QyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBRTdGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLEVBQUUsU0FBbUIsQ0FBQTtRQUNqRCxNQUFNLEdBQUcsR0FBRztZQUNWLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYTtZQUMzQixTQUFTO1lBQ1QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVM7U0FDN0UsQ0FBQTtRQUNELE1BQU0sU0FBUyxHQUFHLElBQUEsdUJBQWUsRUFBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUVuRSxNQUFNLE1BQU0sR0FBRyxJQUFJLGVBQWUsQ0FBQztZQUNqQyxhQUFhLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhO1lBQzFDLFNBQVMsRUFBRSxTQUFTO1lBQ3BCLFNBQVMsRUFBRSxTQUFTO1NBQ3JCLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtRQUViLE1BQU0sR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLGNBQWMsSUFBSSxNQUFNLEVBQUUsQ0FBQTtRQUU5QyxJQUFJLENBQUM7WUFDSCxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLE1BQU0sZUFBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUMzQyxNQUFNLE1BQU0sR0FBRyxJQUFJLDJCQUFTLENBQUM7Z0JBQzNCLGdCQUFnQixFQUFFLEtBQUs7Z0JBQ3ZCLG1CQUFtQixFQUFFLElBQUk7YUFDMUIsQ0FBQyxDQUFBO1lBRUYsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUNoQyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsQ0FBQTtZQUVqRCxNQUFNLE1BQU0sR0FBRztnQkFDYixJQUFJLEVBQUU7b0JBQ0osR0FBRyxLQUFLLENBQUMsSUFBSTtvQkFDYixRQUFRLEVBQUUsUUFBUTtpQkFDbkI7YUFDRixDQUFBO1lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMseUNBQXlDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDL0YsT0FBTyxNQUFNLENBQUE7UUFDZixDQUFDO1FBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztZQUNYLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxzQ0FBc0MsRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNsRSxDQUFDO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0gsS0FBSyxDQUFDLGdCQUFnQixDQUNwQixLQUE0QjtRQUU1QixJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FDaEIsMENBQTBDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUMzRSxDQUFBO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsUUFBc0YsQ0FBQTtZQUNqSixJQUFJLENBQUMsUUFBUSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDckQsTUFBTSxJQUFJLEtBQUssQ0FBQywyQ0FBMkMsQ0FBQyxDQUFBO1lBQzlELENBQUM7WUFFRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsTUFBK0MsQ0FBQTtZQUN2RSxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsS0FBeUIsQ0FBQTtZQUVoRCxNQUFNLFVBQVUsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQTtZQUM1QyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUE7WUFDNUMsSUFBSSxVQUFVLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQ3JCLE1BQU0sSUFBSSxLQUFLLENBQUMsbUJBQW1CLFVBQVUsS0FBSyxpQkFBaUIsRUFBRSxDQUFDLENBQUE7WUFDeEUsQ0FBQztZQUNELE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFBO1lBRTdDLE1BQU0sR0FBRyxHQUF5QztnQkFDaEQsRUFBRSxFQUFFLDRCQUFvQixDQUFDLFFBQVE7Z0JBQ2pDLEVBQUUsRUFBRSw0QkFBb0IsQ0FBQyxRQUFRO2dCQUNqQyxFQUFFLEVBQUUsNEJBQW9CLENBQUMsVUFBVTtnQkFDbkMsQ0FBQyxFQUFFLDRCQUFvQixDQUFDLE9BQU87Z0JBQy9CLEVBQUUsRUFBRSw0QkFBb0IsQ0FBQyxPQUFPO2dCQUNoQyxDQUFDLEVBQUUsNEJBQW9CLENBQUMsT0FBTztnQkFDL0IsRUFBRSxFQUFFLDRCQUFvQixDQUFDLGFBQWE7Z0JBQ3RDLEdBQUcsRUFBRSw0QkFBb0IsQ0FBQyxRQUFRO2FBQ25DLENBQUE7WUFDRCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLElBQUksNEJBQW9CLENBQUMsS0FBSyxDQUFBO1lBRTlELE1BQU0sTUFBTSxHQUFHLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFBO1lBQzVELElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLDBDQUEwQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ2hHLE9BQU8sTUFBTSxDQUFBO1FBQ2YsQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksQ0FBQyxVQUFVLENBQUMsdUNBQXVDLEVBQUUsQ0FBQyxDQUFDLENBQUE7UUFDbkUsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsdUJBQXVCLENBQUMsT0FBMEM7UUFDdEUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQ2hCLG1EQUFtRCxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FDdEYsQ0FBQTtRQUVELE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxJQUFpQyxDQUFBO1FBQ3RELE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ3BELElBQUksQ0FBQyxPQUFPO1lBQ1YsT0FBTztnQkFDTCxNQUFNLEVBQUUsc0JBQWMsQ0FBQyxhQUFhO2FBQ3JDLENBQUE7UUFFSCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFBO1FBQ3BDLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7UUFFbEMsTUFBTSxNQUFNLEdBQUc7WUFDYixNQUFNLEVBQUUsc0JBQWMsQ0FBQyxVQUFVO1lBQ2pDLElBQUksRUFBRSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRTtTQUNoRCxDQUFBO1FBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsaURBQWlELEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDdkcsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0lBRVMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLElBQW9CO1FBQ3RELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQTtRQUM3QyxNQUFNLEdBQUcsR0FBRztZQUNWLElBQUksQ0FBQyxNQUFNO1lBQ1gsSUFBSSxDQUFDLEtBQUs7WUFDVixJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVM7WUFDdkIsaUJBQWlCLElBQUksQ0FBQyxhQUFhLEVBQUU7U0FDdEMsQ0FBQTtRQUNELE1BQU0sU0FBUyxHQUFHLElBQUEsdUJBQWUsRUFBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUVuRSxPQUFPLFNBQVMsS0FBSyxpQkFBaUIsQ0FBQTtJQUN4QyxDQUFDO0lBRUQ7O09BRUc7SUFDTyxVQUFVLENBQUMsT0FBZSxFQUFFLEtBQXlCO1FBQzdELElBQUksZUFBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQzlCLE9BQU8sSUFBSSxLQUFLLENBQ2QsR0FBRyxPQUFPLEtBQUssS0FBSyxDQUFDLFFBQVEsRUFBRSxNQUFNLElBQUksS0FBSyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsSUFBSSxNQUFNLEtBQUssQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxDQUFDLElBQUksRUFBRSxDQUNwSCxDQUFBO1FBQ0gsQ0FBQztRQUNELE9BQU8sSUFBSSxLQUFLLENBQ2QsR0FBRyxPQUFPLEtBQUssS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLElBQUksRUFBRSxDQUN0QyxDQUFBO0lBQ0gsQ0FBQzs7QUE5WU0sd0JBQVUsR0FBRyxXQUFXLEFBQWQsQ0FBYztBQUNoQix3QkFBVSxHQUFHLElBQUEsaUNBQXFCLEVBQUMsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLENBQUMsQUFBbkQsQ0FBbUQ7QUFnWjlFLGtCQUFlLGFBQWEsQ0FBQSJ9