@animo-id/pex
Version:
A Typescript implementation of the v1 and v2 DIF Presentation Exchange specification
109 lines • 15.3 kB
JavaScript
import { JSONPath as jp } from '@astronautlabs/jsonpath';
import { Optionality } from '@sphereon/pex-models';
import { Status } from '../../ConstraintUtils';
import { AbstractEvaluationHandler } from './abstractEvaluationHandler';
export class SubjectIsHolderEvaluationHandler extends AbstractEvaluationHandler {
fieldIdzInputDescriptorsSameSubjectRequired;
fieldIdzInputDescriptorsSameSubjectPreferred;
fieldIds;
isHolder;
credentialsSubjectsByPath;
credentialsByPath;
messages;
constructor(client) {
super(client);
this.fieldIdzInputDescriptorsSameSubjectRequired = new Map();
this.fieldIdzInputDescriptorsSameSubjectPreferred = new Map();
this.isHolder = [];
this.fieldIds = [];
this.credentialsSubjectsByPath = new Map();
this.credentialsByPath = new Map();
this.messages = new Map();
this.messages.set(Status.INFO, 'The field ids requiring the subject to be the holder');
this.messages.set(Status.WARN, 'The field ids preferring the subject to be the holder');
this.messages.set(Status.ERROR, 'The field id missing');
}
getName() {
return 'IsHolderEvaluation';
}
handle(pd, wrappedVcs) {
this.findIsHolderFieldIdsToInputDescriptorsSets(pd);
this.findAllCredentialSubjects(wrappedVcs);
this.confirmAllFieldSetHasSameSubject(this.fieldIdzInputDescriptorsSameSubjectRequired, Status.INFO, Optionality.Required);
this.confirmAllFieldSetHasSameSubject(this.fieldIdzInputDescriptorsSameSubjectPreferred, Status.WARN, Optionality.Preferred);
this.updatePresentationSubmission(pd);
}
/**
* We have input descriptor to field ids mapping. This function gets a (reverse) map from field id to input descriptor
*/
findIsHolderFieldIdsToInputDescriptorsSets(pd) {
this.fieldIds.push(...jp.nodes(pd, '$..fields[*].id'));
this.isHolder.push(...jp.nodes(pd, '$..is_holder[*]'));
const fields = this.fieldIds?.map((n) => n.value);
const error = [];
error.push(...this.evaluateFields(this.fieldIdzInputDescriptorsSameSubjectPreferred, this.isHolder, fields, Optionality.Preferred));
error.push(...this.evaluateFields(this.fieldIdzInputDescriptorsSameSubjectRequired, this.isHolder, fields, Optionality.Required));
error.forEach((q) => this.getResults().push(this.createResult(q[1], q[0], ['', {}], Status.ERROR, undefined)));
}
evaluateFields(fieldsMapping, isHolder, fields, directive) {
const error = [];
isHolder
.filter((d) => d.value.directive === directive)
.filter((e) => e.value.field_id.every((id) => fields.includes(id)))
.forEach((p) => fieldsMapping.set(jp.stringify(p.path.slice(0, 3)), p.value.field_id));
isHolder
.filter((d) => d.value.directive === directive)
.filter((e) => !e.value.field_id.every((id) => fields.includes(id)))
.forEach((p) => error.push([jp.stringify(p.path.slice(0, 3)), p.value.field_id]));
return error;
}
findAllCredentialSubjects(wrappedVcs) {
//TODO handle nested path
const credentialSubjects = jp.nodes(wrappedVcs.map((wvc) => wvc.credential), '$..credentialSubject');
for (let idx = 0; idx < credentialSubjects.length; idx++) {
const cs = credentialSubjects[idx];
const path = jp.stringify(cs.path.slice(0, 2));
this.credentialsSubjectsByPath.set(path, cs.value);
this.credentialsByPath.set(path, wrappedVcs[idx]);
}
}
confirmAllFieldSetHasSameSubject(fieldIdsInputDescriptorsGroups, status, directive) {
const subjectsMatchingFields = Array.from(fieldIdsInputDescriptorsGroups).flatMap((k) => Array.from(this.credentialsSubjectsByPath).filter((a) => k[1].find((c) => Object.keys(a[1]).includes(c))));
const credentialPathsToInputDescriptors = this.mapCredentialPathsToInputDescriptors(directive);
const fields = Array.from(subjectsMatchingFields).flatMap((s) => Object.keys(s[1]).filter((w) => w !== 'id'));
const allFieldsMatched = Array.from(fieldIdsInputDescriptorsGroups.values()).flatMap((v) => v.every((e) => fields.includes(e)))[0];
subjectsMatchingFields.forEach((subject) => {
const inDescPath = credentialPathsToInputDescriptors.get(subject[0]);
if (allFieldsMatched && subject[1].id && this.client.dids.includes(subject[1].id)) {
this.getResults().push(this.createResult(Object.keys(subject[1]).filter((k) => k !== 'id'), inDescPath, subject, status, this.credentialsByPath.get(subject[0])));
}
else {
this.getResults().push(this.createResult(Object.keys(subject[1]).filter((k) => k !== 'id'), inDescPath, subject, Status.ERROR, this.credentialsByPath.get(subject[0])));
}
});
}
mapCredentialPathsToInputDescriptors(directive) {
const credentialsToInputDescriptors = new Map();
this.fieldIds?.forEach((id) => {
const inDescPath = jp.stringify(id.path.slice(0, 3));
this.credentialsSubjectsByPath.forEach((cs, credentialPath) => {
const hs = this.isHolder.find((e) => jp.stringify(e.path.slice(0, 3)) === inDescPath);
if (Object.keys(cs).includes(id.value) && hs?.value.directive === directive) {
credentialsToInputDescriptors.set(credentialPath, inDescPath);
}
});
});
return credentialsToInputDescriptors;
}
createResult(fieldIdSet, inputDescriptorPath, credentialSub, myStatus, wvc, message) {
return {
input_descriptor_path: inputDescriptorPath,
verifiable_credential_path: credentialSub[0],
evaluator: this.getName(),
status: myStatus,
payload: { fieldIdSet, credentialSubject: credentialSub[1], ...(wvc ? { format: wvc.format } : {}) },
message: message ?? this.messages.get(myStatus),
};
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3ViamVjdElzSG9sZGVyRXZhbHVhdGlvbkhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWIvZXZhbHVhdGlvbi9oYW5kbGVycy9zdWJqZWN0SXNIb2xkZXJFdmFsdWF0aW9uSGFuZGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxJQUFJLEVBQUUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pELE9BQU8sRUFBaUIsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFHbEUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBTS9DLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRXhFLE1BQU0sT0FBTyxnQ0FBaUMsU0FBUSx5QkFBeUI7SUFDNUQsMkNBQTJDLENBQXdCO0lBQ25FLDRDQUE0QyxDQUF3QjtJQUNwRSxRQUFRLENBQTZDO0lBQ3JELFFBQVEsQ0FBb0Q7SUFFckUseUJBQXlCLENBQWtDO0lBQzNELGlCQUFpQixDQUEyQztJQUU1RCxRQUFRLENBQXNCO0lBRXRDLFlBQVksTUFBd0I7UUFDbEMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRWQsSUFBSSxDQUFDLDJDQUEyQyxHQUFHLElBQUksR0FBRyxFQUFvQixDQUFDO1FBQy9FLElBQUksQ0FBQyw0Q0FBNEMsR0FBRyxJQUFJLEdBQUcsRUFBb0IsQ0FBQztRQUNoRixJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMseUJBQXlCLEdBQUcsSUFBSSxHQUFHLEVBQThCLENBQUM7UUFDdkUsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksR0FBRyxFQUF1QyxDQUFDO1FBRXhFLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7UUFDMUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxzREFBc0QsQ0FBQyxDQUFDO1FBQ3ZGLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsdURBQXVELENBQUMsQ0FBQztRQUN4RixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLHNCQUFzQixDQUFDLENBQUM7SUFDMUQsQ0FBQztJQUVNLE9BQU87UUFDWixPQUFPLG9CQUFvQixDQUFDO0lBQzlCLENBQUM7SUFFTSxNQUFNLENBQUMsRUFBbUMsRUFBRSxVQUF5QztRQUMxRixJQUFJLENBQUMsMENBQTBDLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEQsSUFBSSxDQUFDLHlCQUF5QixDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQzNDLElBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxJQUFJLENBQUMsMkNBQTJDLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDM0gsSUFBSSxDQUFDLGdDQUFnQyxDQUFDLElBQUksQ0FBQyw0Q0FBNEMsRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM3SCxJQUFJLENBQUMsNEJBQTRCLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVEOztPQUVHO0lBQ0ssMENBQTBDLENBQUMsRUFBbUM7UUFDcEYsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFDdkQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7UUFDdkQsTUFBTSxNQUFNLEdBQWEsSUFBSSxDQUFDLFFBQVEsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQWEsQ0FBQztRQUN4RSxNQUFNLEtBQUssR0FBeUIsRUFBRSxDQUFDO1FBRXZDLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyw0Q0FBNEMsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztRQUNwSSxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsMkNBQTJDLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFFbEksS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDakgsQ0FBQztJQUVPLGNBQWMsQ0FDcEIsYUFBb0MsRUFDcEMsUUFBMkQsRUFDM0QsTUFBZ0IsRUFDaEIsU0FBc0I7UUFFdEIsTUFBTSxLQUFLLEdBQXlCLEVBQUUsQ0FBQztRQUN2QyxRQUFRO2FBQ0wsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUM7YUFDOUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNsRSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFFekYsUUFBUTthQUNMLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxTQUFTLEtBQUssU0FBUyxDQUFDO2FBQzlDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQzthQUNuRSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BGLE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVPLHlCQUF5QixDQUFDLFVBQXlDO1FBQ3pFLHlCQUF5QjtRQUN6QixNQUFNLGtCQUFrQixHQUEyRCxFQUFFLENBQUMsS0FBSyxDQUN6RixVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQ3ZDLHNCQUFzQixDQUN2QixDQUFDO1FBQ0YsS0FBSyxJQUFJLEdBQUcsR0FBRyxDQUFDLEVBQUUsR0FBRyxHQUFHLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDO1lBQ3pELE1BQU0sRUFBRSxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ25DLE1BQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDL0MsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25ELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3BELENBQUM7SUFDSCxDQUFDO0lBRU8sZ0NBQWdDLENBQUMsOEJBQXFELEVBQUUsTUFBYyxFQUFFLFNBQXNCO1FBQ3BJLE1BQU0sc0JBQXNCLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQ3RGLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQzFHLENBQUM7UUFFRixNQUFNLGlDQUFpQyxHQUFHLElBQUksQ0FBQyxvQ0FBb0MsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUUvRixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUM7UUFFOUcsTUFBTSxnQkFBZ0IsR0FBWSxLQUFLLENBQUMsSUFBSSxDQUFDLDhCQUE4QixDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUU1SSxzQkFBc0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUN6QyxNQUFNLFVBQVUsR0FBVyxpQ0FBaUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFXLENBQUM7WUFDdkYsSUFBSSxnQkFBZ0IsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDbEYsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FDcEIsSUFBSSxDQUFDLFlBQVksQ0FDZixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUNqRCxVQUFVLEVBQ1YsT0FBTyxFQUNQLE1BQU0sRUFDTixJQUFJLENBQUMsaUJBQWlCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUN2QyxDQUNGLENBQUM7WUFDSixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLElBQUksQ0FDcEIsSUFBSSxDQUFDLFlBQVksQ0FDZixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxFQUNqRCxVQUFVLEVBQ1YsT0FBTyxFQUNQLE1BQU0sQ0FBQyxLQUFLLEVBQ1osSUFBSSxDQUFDLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDdkMsQ0FDRixDQUFDO1lBQ0osQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLG9DQUFvQyxDQUFDLFNBQXNCO1FBQ2pFLE1BQU0sNkJBQTZCLEdBQXdCLElBQUksR0FBRyxFQUFrQixDQUFDO1FBQ3JGLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUMsRUFBNEMsRUFBRSxFQUFFO1lBQ3RFLE1BQU0sVUFBVSxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDckQsSUFBSSxDQUFDLHlCQUF5QixDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQXNCLEVBQUUsY0FBc0IsRUFBRSxFQUFFO2dCQUN4RixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxVQUFVLENBQUMsQ0FBQztnQkFDdEYsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLEtBQUssQ0FBQyxTQUFTLEtBQUssU0FBUyxFQUFFLENBQUM7b0JBQzVFLDZCQUE2QixDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ2hFLENBQUM7WUFDSCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTyw2QkFBNkIsQ0FBQztJQUN2QyxDQUFDO0lBRU8sWUFBWSxDQUNsQixVQUFvQixFQUNwQixtQkFBMkIsRUFDM0IsYUFBMkMsRUFDM0MsUUFBZ0IsRUFDaEIsR0FBaUMsRUFDakMsT0FBZ0I7UUFFaEIsT0FBTztZQUNMLHFCQUFxQixFQUFFLG1CQUFtQjtZQUMxQywwQkFBMEIsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDO1lBQzVDLFNBQVMsRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ3pCLE1BQU0sRUFBRSxRQUFRO1lBQ2hCLE9BQU8sRUFBRSxFQUFFLFVBQVUsRUFBRSxpQkFBaUIsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtZQUNwRyxPQUFPLEVBQUUsT0FBTyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQztTQUNoRCxDQUFDO0lBQ0osQ0FBQztDQUNGIn0=