From 2fd64db6f5ec813954e49a8c4a5949dc6c878a84 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Fri, 3 Feb 2023 10:29:12 +0000 Subject: [PATCH 01/16] Init --- .../src/message/types.ts | 27 +++- .../external-import/DataCentreImporter.tsx | 131 ++++++++++++++++++ .../src/external-import/ExternalImport.tsx | 4 + truthsayer/src/lib/global.tsx | 17 +-- 4 files changed, 162 insertions(+), 17 deletions(-) create mode 100644 truthsayer/src/external-import/DataCentreImporter.tsx diff --git a/truthsayer-archaeologist-communication/src/message/types.ts b/truthsayer-archaeologist-communication/src/message/types.ts index afa029ba..c8700175 100644 --- a/truthsayer-archaeologist-communication/src/message/types.ts +++ b/truthsayer-archaeologist-communication/src/message/types.ts @@ -14,16 +14,37 @@ import type { StorageApiMsgReturnValue, } from 'smuggler-api' import { VersionStruct } from '../Version' +import { log, errorise } from 'armoury' + +export type StorageType = + | 'datacenter' /** Stores user data in @file storage_api_datacenter.ts */ + | 'browser_ext' /** Stores user data in @file storage_api_browser_ext.ts */ export type AppSettings = { - storageType: - | 'datacenter' /** Stores user data in @file storage_api_datacenter.ts */ - | 'browser_ext' /** Stores user data in @file storage_api_browser_ext.ts */ + storageType: StorageType } + export function defaultSettings(): AppSettings { return { storageType: 'datacenter' } } +export async function getAppSettings(): Promise { + try { + const response = await FromTruthsayer.sendMessage({ + type: 'GET_APP_SETTINGS_REQUEST', + }) + return response.settings + } catch (err) { + const defaults = defaultSettings() + log.warning( + `Failed to get user's app settings,` + + ` falling back to ${JSON.stringify(defaults)}; ` + + `error - ${errorise(err).message}` + ) + return defaults + } +} + export namespace FromTruthsayer { export type GetArchaeologistStateRequest = { type: 'GET_ARCHAEOLOGIST_STATE_REQUEST' diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx new file mode 100644 index 00000000..0af76166 --- /dev/null +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -0,0 +1,131 @@ +import React from 'react' +import styled from '@emotion/styled' +import { useAsyncEffect } from 'use-async-effect' + +import { MzdGlobalContext } from '../lib/global' + +import { log, genOriginId } from 'armoury' +import { Spinner } from 'elementary' +import * as truthsayer_archaeologist_communication from 'truthsayer-archaeologist-communication' +import BrowserLogo from '../apps-list/img/GoogleChromeLogo.svg' +import { makeDatacenterStorageApi, StorageApi, Nid } from 'smuggler-api' + +export { BrowserLogo } + +const Box = styled.div`` +const Title = styled.div` + margin-bottom: 10px; +` +const Message = styled.div`` + +export function NotImplementedMessage() { + return ( + Import of local data to Mazed backend is not implemented + ) +} + +async function downloadUserDataFromMazedBackend( + localStorageApi: StorageApi, + datacenterStorageApi: StorageApi +): Promise { + const oldToNewNids: Map = new Map() + const iter = datacenterStorageApi.node.iterate() + while (true) { + const node = await iter.next() + if (node == null) { + break + } + const url = node.extattrs?.web?.url ?? node.extattrs?.web_quote?.url + const origin = url != null ? genOriginId(url) : undefined + const r = await localStorageApi.node.create({ + text: node.text, + index_text: node.index_text, + extattrs: node.extattrs, + ntype: node.ntype, + origin: origin ? { ...origin } : undefined, + created_at: node.created_at.toDate(), + }) + oldToNewNids.set(node.nid, r.nid) + log.debug('Saved node', node.nid, r.nid) + } + for (const oldNid of oldToNewNids.keys()) { + const edges = await datacenterStorageApi.edge.get({ nid: oldNid }) + for (const oldEdge of edges.from_edges.concat(edges.to_edges)) { + const fromNid = oldToNewNids.get(oldEdge.from_nid) + const toNid = oldToNewNids.get(oldEdge.to_nid) + log.debug('Saved edge', fromNid, toNid) + if (fromNid && toNid) { + await localStorageApi.edge.create({ from: fromNid, to: toNid }) + } + } + } +} + +const ControlBox = styled.div`` +const BoxButtons = styled.div`` +const Button = styled.button` + background-color: #ffffff; + border-style: solid; + border-width: 0; + border-radius: 32px; + + vertical-align: middle; + &:hover { + background-color: #d0d1d2; + } +` + +type LoadingState = { type: 'standby' } | { type: 'loading'; progress: string } + +export function DownloadUserDataFromMazedBackendControl() { + const [loadingState, setLoadingState] = React.useState({ + type: 'standby', + }) + const ctx = React.useContext(MzdGlobalContext) + const sync = React.useCallback(() => { + const datacenterStorageApi = makeDatacenterStorageApi() + downloadUserDataFromMazedBackend(ctx.storage, datacenterStorageApi) + }, [ctx.storage]) + return ( + + + Download fragments stored in Mazed backend + + + + + + ) +} + +export function DataCentreImporter({ className }: { className?: string }) { + const [storageType, setStorageType] = React.useState< + 'loading' | truthsayer_archaeologist_communication.StorageType + >('loading') + useAsyncEffect(async () => { + const settings = + await truthsayer_archaeologist_communication.getAppSettings() + setStorageType(settings.storageType) + }) + let element + switch (storageType) { + case 'loading': + element = + break + case 'browser_ext': + element = + break + case 'datacenter': + element = + break + } + return {element} +} diff --git a/truthsayer/src/external-import/ExternalImport.tsx b/truthsayer/src/external-import/ExternalImport.tsx index 29359c21..a90c77eb 100644 --- a/truthsayer/src/external-import/ExternalImport.tsx +++ b/truthsayer/src/external-import/ExternalImport.tsx @@ -14,6 +14,7 @@ import { BrowserHistoryImporter, BrowserLogo as BrowserHistoryImporterLogo, } from './BrowserHistoryImporter' +import { DataCentreImporter } from './DataCentreImporter' const Box = styled.div` padding: 18px; @@ -65,6 +66,9 @@ export function ExternalImport({ + + + ) diff --git a/truthsayer/src/lib/global.tsx b/truthsayer/src/lib/global.tsx index 52ea251e..5fa08265 100644 --- a/truthsayer/src/lib/global.tsx +++ b/truthsayer/src/lib/global.tsx @@ -22,9 +22,8 @@ import { NotificationToast } from './Toaster' import { errorise, log, productanalytics } from 'armoury' import { useAsyncEffect } from 'use-async-effect' import { - defaultSettings, FromTruthsayer, - ToTruthsayer, + getAppSettings, } from 'truthsayer-archaeologist-communication' import type { AppSettings } from 'truthsayer-archaeologist-communication' import { Loader } from './loader' @@ -106,18 +105,8 @@ export function MzdGlobal(props: React.PropsWithChildren) { const [storage, setStorage] = React.useState(null) useAsyncEffect(async () => { - const response = await FromTruthsayer.sendMessage({ - type: 'GET_APP_SETTINGS_REQUEST', - }).catch((reason): ToTruthsayer.GetAppSettingsResponse => { - const defaults = defaultSettings() - log.warning( - `Failed to get user's app settings,` + - ` falling back to ${JSON.stringify(defaults)}; ` + - `error - ${errorise(reason).message}` - ) - return { type: 'GET_APP_SETTINGS_RESPONSE', settings: defaults } - }) - setStorage(makeStorageApi(response.settings)) + const settings = await getAppSettings() + setStorage(makeStorageApi(settings)) }, []) const [state] = React.useState>({ From 06a1a184f84f89928cc2942a41d4a16a5b1546ac Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sat, 4 Feb 2023 10:18:46 +0000 Subject: [PATCH 02/16] Debugging code' --- smuggler-api/src/storage_api_msg_proxy.ts | 1 + .../external-import/DataCentreImporter.tsx | 20 +++++++++++++++---- .../src/external-import/ExternalImport.tsx | 3 ++- truthsayer/src/lib/global.tsx | 2 ++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/smuggler-api/src/storage_api_msg_proxy.ts b/smuggler-api/src/storage_api_msg_proxy.ts index 568e3dc3..a3879c83 100644 --- a/smuggler-api/src/storage_api_msg_proxy.ts +++ b/smuggler-api/src/storage_api_msg_proxy.ts @@ -200,6 +200,7 @@ export function makeMsgProxyStorageApi(forward: ForwardToRealImpl): StorageApi { create: async (args: NodeCreateArgs) => { const apiName = 'node.create' const resp = await forward({ apiName, args }) + console.log('Resp', resp) if (apiName !== resp.apiName) throw mismatchError(apiName, resp.apiName) const ret: NewNodeResponse = resp.ret return ret diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index 0af76166..0a4c1785 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -29,7 +29,9 @@ async function downloadUserDataFromMazedBackend( datacenterStorageApi: StorageApi ): Promise { const oldToNewNids: Map = new Map() + log.debug('Creating an iterator...') const iter = datacenterStorageApi.node.iterate() + log.debug('Done, iterator crated', iter) while (true) { const node = await iter.next() if (node == null) { @@ -37,6 +39,8 @@ async function downloadUserDataFromMazedBackend( } const url = node.extattrs?.web?.url ?? node.extattrs?.web_quote?.url const origin = url != null ? genOriginId(url) : undefined + log.debug('Got node', node, url) + log.debug('Saving node to local storage...') const r = await localStorageApi.node.create({ text: node.text, index_text: node.index_text, @@ -45,6 +49,7 @@ async function downloadUserDataFromMazedBackend( origin: origin ? { ...origin } : undefined, created_at: node.created_at.toDate(), }) + log.debug('Node is saved', r.nid) oldToNewNids.set(node.nid, r.nid) log.debug('Saved node', node.nid, r.nid) } @@ -83,14 +88,15 @@ export function DownloadUserDataFromMazedBackendControl() { }) const ctx = React.useContext(MzdGlobalContext) const sync = React.useCallback(() => { + log.debug('Creating datacenter storage interface...') const datacenterStorageApi = makeDatacenterStorageApi() + log.debug('Done datacenter storage:', datacenterStorageApi) + log.debug('Starting the process...') downloadUserDataFromMazedBackend(ctx.storage, datacenterStorageApi) }, [ctx.storage]) return ( - - Download fragments stored in Mazed backend - + Download fragments stored in Mazed backend diff --git a/truthsayer/src/external-import/ExternalImport.tsx b/truthsayer/src/external-import/ExternalImport.tsx index a90c77eb..515f1125 100644 --- a/truthsayer/src/external-import/ExternalImport.tsx +++ b/truthsayer/src/external-import/ExternalImport.tsx @@ -68,7 +68,8 @@ export function ExternalImport({ - + + ) diff --git a/truthsayer/src/lib/global.tsx b/truthsayer/src/lib/global.tsx index 5fa08265..4b5455f7 100644 --- a/truthsayer/src/lib/global.tsx +++ b/truthsayer/src/lib/global.tsx @@ -40,10 +40,12 @@ function makeStorageApi(appSettings: AppSettings): StorageApi { const forwardToArchaeologist: ForwardToRealImpl = async ( payload: StorageApiMsgPayload ): Promise => { + log.debug('Sending message to Archaeologist', payload) const response = await FromTruthsayer.sendMessage({ type: 'MSG_PROXY_STORAGE_ACCESS_REQUEST', payload, }) + log.debug('Got response from Archaeologist', response) return response.value } return makeMsgProxyStorageApi(forwardToArchaeologist) From 29def9dd04dc787ac289e6f1c61d93b6e8266ab9 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 07:59:17 +0000 Subject: [PATCH 03/16] Log --- truthsayer/src/external-import/DataCentreImporter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index 0a4c1785..f35236a7 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -40,7 +40,7 @@ async function downloadUserDataFromMazedBackend( const url = node.extattrs?.web?.url ?? node.extattrs?.web_quote?.url const origin = url != null ? genOriginId(url) : undefined log.debug('Got node', node, url) - log.debug('Saving node to local storage...') + log.debug('Saving node to local storage...', node.created_at.toDate()) const r = await localStorageApi.node.create({ text: node.text, index_text: node.index_text, From 6e9e187eeab4582b46485ec10b6cac0a8fb86a2a Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 08:11:33 +0000 Subject: [PATCH 04/16] Use plain unixtime for NodeCreateArgs --- archaeologist/src/storage_api_browser_ext.ts | 5 +-- armoury/src/time.ts | 20 ++++++------ smuggler-api/src/api_datacenter.ts | 2 +- smuggler-api/src/api_node_even_listener.ts | 32 -------------------- smuggler-api/src/storage_api.ts | 4 +-- smuggler-api/src/types.ts | 6 ++-- 6 files changed, 18 insertions(+), 51 deletions(-) delete mode 100644 smuggler-api/src/api_node_even_listener.ts diff --git a/archaeologist/src/storage_api_browser_ext.ts b/archaeologist/src/storage_api_browser_ext.ts index fb8e8b24..6a5f84cb 100644 --- a/archaeologist/src/storage_api_browser_ext.ts +++ b/archaeologist/src/storage_api_browser_ext.ts @@ -415,10 +415,7 @@ async function createNode( ): Promise { const from_nid: Nid[] = args.from_nid ?? [] const to_nid: Nid[] = args.to_nid ?? [] - - const createdAt: number = - args.created_at != null ? unixtime.from(args.created_at) : unixtime.now() - + const createdAt = args.created_at ?? unixtime.now() const node: TNodeJson = { nid: generateNid(), ntype: args.ntype ?? NodeType.Text, diff --git a/armoury/src/time.ts b/armoury/src/time.ts index c89cd0d4..b1aacfa5 100644 --- a/armoury/src/time.ts +++ b/armoury/src/time.ts @@ -1,15 +1,17 @@ -export const unixtime = { - now: (): number => { +export namespace unixtime { + export type Type = number + + export function now(): Type { return Math.floor(new Date().getTime() / 1000) - }, - nowMs: (): number => { + } + export function nowMs(): Type { return Math.floor(new Date().getTime()) - }, - from: (date: Date): number => { + } + export function from(date: Date): Type { return Math.floor(date.getTime()) - }, - toDate: (unixtime: number): Date => { + } + export function toDate(unixtime: Type): Date { return new Date(unixtime) - }, + } } export const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)) diff --git a/smuggler-api/src/api_datacenter.ts b/smuggler-api/src/api_datacenter.ts index 5cf14657..4c5c6af3 100644 --- a/smuggler-api/src/api_datacenter.ts +++ b/smuggler-api/src/api_datacenter.ts @@ -99,7 +99,7 @@ async function createNode( } const headers: Record = { 'Content-type': MimeType.JSON } if (created_at != null) { - headers['X-Created-At'] = created_at.toUTCString() + headers['X-Created-At'] = new Date(created_at).toUTCString() } const resp = await fetch(makeUrl('node/new', query), { method: 'POST', diff --git a/smuggler-api/src/api_node_even_listener.ts b/smuggler-api/src/api_node_even_listener.ts deleted file mode 100644 index a4edbde3..00000000 --- a/smuggler-api/src/api_node_even_listener.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { Nid } from './types' -import type { - NodeEventListener, - NodeEventPatch, - NodeEventType, -} from './storage_api' - -export namespace NodeEvent { - const _listeners: NodeEventListener[] = [] - - export function addListener(listener: NodeEventListener): void { - _listeners.push(listener) - } - export function removeListener(listener: NodeEventListener): void { - const index = _listeners.findIndex((l) => l === listener) - if (index < 0) { - throw new Error( - 'Attempt to remove non existin node even listener from storage API' - ) - } - _listeners.splice(index, 1) - } - export const registerEvent: NodeEventListener = async ( - type: NodeEventType, - nid: Nid, - patch: NodeEventPatch - ) => { - for (const listener of _listeners) { - listener(type, nid, patch) - } - } -} diff --git a/smuggler-api/src/storage_api.ts b/smuggler-api/src/storage_api.ts index 2035e55c..2a49da15 100644 --- a/smuggler-api/src/storage_api.ts +++ b/smuggler-api/src/storage_api.ts @@ -1,4 +1,4 @@ -import { MimeType } from 'armoury' +import { MimeType, unixtime } from 'armoury' import type { Optional } from 'armoury' import { INodeIterator } from './node_slice_iterator' import { @@ -43,7 +43,7 @@ export type NodeCreateArgs = { ntype?: NodeType origin?: OriginId created_via?: NodeCreatedVia - created_at?: Date + created_at?: unixtime.Type } export type NodeBatchRequestBody = { diff --git a/smuggler-api/src/types.ts b/smuggler-api/src/types.ts index 981d2881..ec9c31a1 100644 --- a/smuggler-api/src/types.ts +++ b/smuggler-api/src/types.ts @@ -1,4 +1,4 @@ -import { MimeType } from 'armoury' +import { MimeType, unixtime } from 'armoury' import moment from 'moment' export type SlateText = object[] @@ -133,8 +133,8 @@ export type TNodeJson = { text: NodeTextData extattrs?: NodeExtattrs index_text?: NodeIndexText - created_at: number - updated_at: number + created_at: unixtime.Type + updated_at: unixtime.Type meta?: NodeMeta crypto?: TNodeCrypto } From b82b4bd3fe341bd003e24a048783ac15eb21a861 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 08:16:52 +0000 Subject: [PATCH 05/16] Fix --- archaeologist/src/background.ts | 2 +- archaeologist/src/background/savePage.ts | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/archaeologist/src/background.ts b/archaeologist/src/background.ts index e7e7b664..906ee433 100644 --- a/archaeologist/src/background.ts +++ b/archaeologist/src/background.ts @@ -786,7 +786,7 @@ async function uploadSingleHistoryItem( createdVia, content, undefined, - item.lastVisitTime ? new Date(item.lastVisitTime) : undefined + item.lastVisitTime ) } diff --git a/archaeologist/src/background/savePage.ts b/archaeologist/src/background/savePage.ts index a648d260..6f25e543 100644 --- a/archaeologist/src/background/savePage.ts +++ b/archaeologist/src/background/savePage.ts @@ -2,7 +2,14 @@ import { DisappearingToastProps } from '../content/toaster/Toaster' import { WebPageContent } from '../content/extractor/webPageContent' import { extractSearchEngineQuery } from '../content/extractor/url/searchEngineQuery' -import { log, isAbortError, MimeType, errorise, genOriginId } from 'armoury' +import { + log, + isAbortError, + MimeType, + errorise, + genOriginId, + unixtime, +} from 'armoury' import { Nid, NodeCreatedVia, @@ -119,7 +126,7 @@ export async function saveWebPage( createdVia: NodeCreatedVia, content?: WebPageContent, tabId?: number, - visitedAt?: Date + visitedAt?: unixtime.Type ): Promise<{ node?: TNode; unmemorable: boolean }> { const searchEngineQuery = extractSearchEngineQuery(url) if (searchEngineQuery != null) { From 689610eb3f89f4bb74745d0994c3031e086ea25d Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 08:42:51 +0000 Subject: [PATCH 06/16] Fix warning --- smuggler-api/src/storage_api_msg_proxy.ts | 1 - .../external-import/DataCentreImporter.tsx | 49 +++++++------------ .../src/external-import/ExternalImport.tsx | 4 +- 3 files changed, 19 insertions(+), 35 deletions(-) diff --git a/smuggler-api/src/storage_api_msg_proxy.ts b/smuggler-api/src/storage_api_msg_proxy.ts index a3879c83..568e3dc3 100644 --- a/smuggler-api/src/storage_api_msg_proxy.ts +++ b/smuggler-api/src/storage_api_msg_proxy.ts @@ -200,7 +200,6 @@ export function makeMsgProxyStorageApi(forward: ForwardToRealImpl): StorageApi { create: async (args: NodeCreateArgs) => { const apiName = 'node.create' const resp = await forward({ apiName, args }) - console.log('Resp', resp) if (apiName !== resp.apiName) throw mismatchError(apiName, resp.apiName) const ret: NewNodeResponse = resp.ret return ret diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index f35236a7..3f8180ac 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -2,26 +2,22 @@ import React from 'react' import styled from '@emotion/styled' import { useAsyncEffect } from 'use-async-effect' -import { MzdGlobalContext } from '../lib/global' - -import { log, genOriginId } from 'armoury' -import { Spinner } from 'elementary' import * as truthsayer_archaeologist_communication from 'truthsayer-archaeologist-communication' -import BrowserLogo from '../apps-list/img/GoogleChromeLogo.svg' +import { Spinner } from 'elementary' +import { genOriginId } from 'armoury' import { makeDatacenterStorageApi, StorageApi, Nid } from 'smuggler-api' -export { BrowserLogo } +import { getLogoImage } from '../util/env' +import { MzdGlobalContext } from '../lib/global' + +export { getLogoImage } const Box = styled.div`` const Title = styled.div` margin-bottom: 10px; ` -const Message = styled.div`` - export function NotImplementedMessage() { - return ( - Import of local data to Mazed backend is not implemented - ) + return
} async function downloadUserDataFromMazedBackend( @@ -29,9 +25,8 @@ async function downloadUserDataFromMazedBackend( datacenterStorageApi: StorageApi ): Promise { const oldToNewNids: Map = new Map() - log.debug('Creating an iterator...') const iter = datacenterStorageApi.node.iterate() - log.debug('Done, iterator crated', iter) + // Clone all nodes, saving mapping between { old-nid → new-nid } while (true) { const node = await iter.next() if (node == null) { @@ -39,26 +34,22 @@ async function downloadUserDataFromMazedBackend( } const url = node.extattrs?.web?.url ?? node.extattrs?.web_quote?.url const origin = url != null ? genOriginId(url) : undefined - log.debug('Got node', node, url) - log.debug('Saving node to local storage...', node.created_at.toDate()) const r = await localStorageApi.node.create({ text: node.text, index_text: node.index_text, extattrs: node.extattrs, ntype: node.ntype, origin: origin ? { ...origin } : undefined, - created_at: node.created_at.toDate(), + created_at: node.created_at.unix(), }) - log.debug('Node is saved', r.nid) oldToNewNids.set(node.nid, r.nid) - log.debug('Saved node', node.nid, r.nid) } + // Clone all edges for (const oldNid of oldToNewNids.keys()) { const edges = await datacenterStorageApi.edge.get({ nid: oldNid }) for (const oldEdge of edges.from_edges.concat(edges.to_edges)) { const fromNid = oldToNewNids.get(oldEdge.from_nid) const toNid = oldToNewNids.get(oldEdge.to_nid) - log.debug('Saved edge', fromNid, toNid) if (fromNid && toNid) { await localStorageApi.edge.create({ from: fromNid, to: toNid }) } @@ -80,7 +71,7 @@ const Button = styled.button` } ` -type LoadingState = { type: 'standby' } | { type: 'loading'; progress: string } +type LoadingState = { type: 'standby' } | { type: 'loading' } export function DownloadUserDataFromMazedBackendControl() { const [loadingState, setLoadingState] = React.useState({ @@ -88,23 +79,17 @@ export function DownloadUserDataFromMazedBackendControl() { }) const ctx = React.useContext(MzdGlobalContext) const sync = React.useCallback(() => { - log.debug('Creating datacenter storage interface...') + setLoadingState({ type: 'loading' }) const datacenterStorageApi = makeDatacenterStorageApi() - log.debug('Done datacenter storage:', datacenterStorageApi) - log.debug('Starting the process...') - downloadUserDataFromMazedBackend(ctx.storage, datacenterStorageApi) + downloadUserDataFromMazedBackend(ctx.storage, datacenterStorageApi).then( + () => setLoadingState({ type: 'loading' }) + ) }, [ctx.storage]) return ( - Download fragments stored in Mazed backend + Download fragments from Mazed backend - From c56c9e3e0aa2f7b37decee203147c8bfa3370714 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 09:16:37 +0000 Subject: [PATCH 09/16] Add not implemented message --- truthsayer/src/external-import/DataCentreImporter.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index 3ba2eadc..06e2a772 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -4,7 +4,7 @@ import { useAsyncEffect } from 'use-async-effect' import * as truthsayer_archaeologist_communication from 'truthsayer-archaeologist-communication' import { Spinner } from 'elementary' -import { genOriginId, log } from 'armoury' +import { genOriginId } from 'armoury' import { makeDatacenterStorageApi, StorageApi, Nid } from 'smuggler-api' import { getLogoImage } from '../util/env' @@ -17,7 +17,7 @@ const Title = styled.div` margin-bottom: 10px; ` export function NotImplementedMessage() { - return
+ return Please enable local mode in Settings } async function downloadUserDataFromMazedBackend( From de22de773bf08a1532da943eb899f167d1ee32d9 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 09:18:27 +0000 Subject: [PATCH 10/16] FIx not implemetned message --- truthsayer/src/external-import/DataCentreImporter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index 06e2a772..c9d4855a 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -17,7 +17,7 @@ const Title = styled.div` margin-bottom: 10px; ` export function NotImplementedMessage() { - return Please enable local mode in Settings + return To store data locally please enable local mode in Settings } async function downloadUserDataFromMazedBackend( From 97db5c4ab6153c3ce64c2a5b8344de6af2a61de4 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 09:20:39 +0000 Subject: [PATCH 11/16] Remove logs --- logs | 747 ----------------------------------------------------------- 1 file changed, 747 deletions(-) delete mode 100644 logs diff --git a/logs b/logs deleted file mode 100644 index d695a992..00000000 --- a/logs +++ /dev/null @@ -1,747 +0,0 @@ -thqu16swt6ioyuprrmy6gq3gw9ohzn93q35wznugs68tq gu7zfp83wzg6hkc6wwb3q7rct6qjuy44wo5ditpem3sk1 -o9c5jeyipyogxkypqm5m54bp5698shenm6apwd9iicxue uekupexwdmxqwubnmm46maszzosx1k8rumh197a4kgqr6 -zwo5xt7omb4oa6y3j9cgx6dmrhbj5ozfq1pnnf93d9f3g 3pwircmx9y1wrme9czxakohx8n318oi1r8mgac5dknrbw -mea6yf4qdrjdy54ah9uyjinbftxdc1tzbw4iqcezmjt6k 7ht3itzs4x6ht6west7se6x6o7dj8a4ppzn48mr856ysq -uywyssdkmtxw3pti5nce7pa5c13njzfnzu8bc9hn7giwo 8tsqxuhyu4eqhyfoihn84c7j7nc7wg71zhb6wa8fqg3eq -6dpo49ro8sh5mnke3nd8w3ic639ip9ha379n6db8tp6pn gm3pdfc5t6n9jp4i1itbh99mcwiwr17mztykq6349h7hk -gj14jzxh1r5bq3wx8e5y1zhc4nad644ac1iyffsyrww91 p8fdzrnb3qkx8qm51tt8rnw7aahbmdjazchadk6g4hksq -rhzpgdmx5pfwqdwftphjkhcckwz9acq5mqxws7arsz594 35f11o6exp7foakq1tthmoq3cmcffrbxwktiwhoci9cdg -m7utkbizmmwgrasygbo7x3wpw6frgbemm6dbpqxgyxbm6 ymraq9a14niqw7pcxyzj79tyqocuomer8wompn44g6ffk -kd16e3p8mpu1upk96fbf1ggf11ti8js5tjut6bhg73ues tnbm95r5wazg5fo8biwzopemh6umwcbdcepd81q35ofhs -mrki3df3ou7x357g7bqptb3ma6uyjqgw7iinuad5xzedw tqooxpp6ogswzj16w1kub5oayd7j6934shsf7uw415jmh -br48gb9xyece7ah8rhp3qwqi3ctzdxu7qw3wp1d5ec6sh p8c3qq9nuxrdwn1b9swp1sco6txko56pficrsycorp9eh -ow8nradhiaeuh3eez97qfwq1n6daaeiy3ntggud7y5och yc1rpig3r9q5iemogwzf9gtde9hpy9cf1uwtkff3mmgha -wb6znpfn66xoy5ki5nbemz5yi5d7m78r3jgafyr11odmn fnpuz8m8x1857ugooy5mgmw8kqod1ey6mznk63gwh9nje -skz4wfchnnyis8j7yazz943qhb4jqc6e8nf8cxebq333q nu6xdps4dtpu8r6txm4osijtzfxa8obsbsqsh8tppr9po -te3xm7jzq71sxj7c1ir8m64of8y9snyih7toh5xz1ouuw mfp5foih8q5no93nruf9n6b1ro635wwwxsswzty4mcyxk -k4ugkaxsyg4ga84fy71hnoqq9usofodhit998priq1d4c 7xcjrpcxqajpqs8uadd55snetjkyq9hfn5cjshrpi85oa -9tys6zim5o6hzb7iu5dnr17jend87xb619juf4pjre46o zmi6fzpmpo5o6ohosuxop7as4ht9ru37m5uwcxh9bo4rk -mq489ztd78c6ucn5ek1giwgegwu69ed3ezxi4r4cut86a 96g3irhz3seyij7fmuycq7zq7huq466kmnws49hhfds1o -fc7t7abck39m4e818tyipehjq3s8hcmkfgjdkengdnyu6 kctqf1xn9eqkjk1jpjumdqotjfbuwmfkbpauosqtrxt8o -kdcbhk1zxp463jahcn1enuxggxjjtse8uacoru59zd38g b3e1wkceddkq8ickrr5i9j19tk5h3xqzhmnra5kbwko36 -euotxa9zszqepzccbfiiue59ztc3y5m1jfsma46e7jo4h sw1twcg5ijcn65oibjnh5pg9hs38xwnon76js8wqe8fuc -4woz6a3m5xf7u4fh65biptzoobhce4u4mwan6joyyd4ss tfjqydatdkc3t5jjups5yk695pp8g1j418ue75cbimed4 -w5yp1x8u33wb8tjetgx1nkcjbmq6etc1yr34apicjg8eg mejh1jry8tk3bu3dcyxmsqxgfa8rpxyb3eeeduof49mdy -dex41h173stek9gjd63okh595jygg6y5s88sdmgj1c55w ynf7hxxn68f7goppqiyidzqx7rn1mmfj7i6n4uk4zu6dr -ow355r545h9um1jn876d6g5fzt8mt1zcmjrgrk95k89mk bs777zcs5wom595ahtcugi7ip4om51bk93dxt6897h99g -1wnhnptu3joz16xjandq8wzch5sb987rjbdgp9nxzmct4 7j9byq9jw6uye3g5p17qkn3n334re7r4bpuo46hbi375y -7h4eoiha1g6nemqt66iyzd4phpmbb7oaa6phi65zknk1q xzdboe47df1yjkjeojjt6r1od6bo949mog98ttqtzh9xc -zpriincw3yogsdmw91iie19zxnjwbm9kc4mnep8tqfx8a k9ndyadjnmugkd9449g38cixrdza6kxykmw6eq4kuo8o4 -nmyakzcc3g6p9yj4gooy6i4m3u7jfg9stpz9muneqy1mr 41axzti45amfzppszqby5jtbj1774x7s41bg5oeejxepr -pibsh3hugiuu7149ietqfonhshya7jm58it888re8dcno 3r8g7aj5pe77c5htxks3rge79k8cuttfqfwxdqnutkt7h -7uwyiph3dso7fmfuuhk4gcswcybhrprincmgctxs3gdxy 8h3sqbtaokgwxtm4cp191aydrr6bt5urg96wcnfad57bc -m6gb1sxnet7smxe5zr5jg94h4jqqyqmfr1uudm3nuqx6y 7eqp9q61hyxo8dp59rekx6acp66gxoua5k49yi3f7m3wg -untqpp5wjujyx14erqjbxs1einrdgk6d8fbxrmzq76jhh xnpmnfa5h8a6k65adw1wwwf9rj8ammwjaf8gxxg9cu4th -mzxy3sahdy8badukqbxpzrgwhjox4ptqmza7qxka56q76 ycc53xdchpwkwyrefyi1fi15egpk3mwd4wbq3ag5tsizc -chjhw3qq6umyi81w85pjfpagno9haeqc4ftss6qrmwazh eyijfi5ngsrguosc67hpuofdoqwfsxm5y6hx7sdrmr7sn -ckm9pw6f6cfj6ewhznpsdswab1ka5r1yynzu8thr3fxik pade1n571x9ozjpmzmdkbftpxuzfpu4xptzabroe8na4y -86uwzfrkt9bw3gqakejr8sdsb9m7tikxw8zgo3uyj4gdn 737t91doz4y43ztipqx3n6hbdeh1te1uq9u9gmyxfzg7o -gbo3i5e6aayjcj5fych53twszaex65gg7w973wd311sow mj5qjdrifquu84nops837gahfscjywdzoz4z1txd3mnh6 -wifwx5xtznrhp761ijenq6jxepqndi6spty87g6tnbyq4 aheirnyikenccyf5fb48tscf61e73esfns6ts8obyszga -cjhb3xci1k3ex4zwbb6q58rxtsa6gsbh35zbn5as5oaxq czy9giqjdyet8hi8ww4tfkywsok4atq59a3dynbwrgm8k -5pjnx6k5nfzo4poiucqtuqs65id9rquwb8wnkwu16fd9e 7gheeic4qz44igh4xc31hfi8tggpg838kh7fim6mpr8gn -3gj47xt68aici9chxpozse7msmroao7tmh8dbax4kahno 6z3zy7qh6si6x39sauooi9ny6k7c81ry87fchzcye8k5k -wdg4njxbq6msi3ebefj3rbgunp3imo3gkrtprdx34scsw ohxcm9q4dij3gazc7kp8c5pnaw74jtzo6gscpiij74ayg -wimw9tizatq4myub4xje7ebhh1ck69iaxs6xfnkuwsb5e qjxdmfgzfh7jsa7bz8qnfci4h5u98cgnb5t84kdoo38k1 -kisndda56p8qpbu8er9nttwwf3atnr8oeupqh5ct6o65k re4saa16f4yjwe8qsh6afwugzak69bee4auz83hycrinn -6b1gxdiggui4rea4fhadzu6bywwti58y8d95w59h4yq4k onir1jcozmq1qx4m1h9j19hebhnu6ja794tmm9am8kh4g -f4w916k6dfgbmicumfpi8sujtt9iqb478wkjbk111krn6 g6jbfq87bo3owxtyxe33yyougq48ab9ipd8h5kmpwgdjw -p4sd9pm184ptir5e14q61ci7oo7fnqkid1xmcshpx5o4c 4izzufunhsh3rogg7uo1s4czee4einp41btj5jrk7r186 -7dfxrzf7mfw3fq1iydrx1ya7qa4jtms3udee1a7cn3fps kgu6p1kzctp4yqmht6rioz537qbtd4p4wuy61b4beuuaa -14dujgoww1gfuegiattny6ruta9czcaqx8mewbctrpwqr a1ipkbcsmkd445btfnsshbfnqypo9qy69pdfoyo4z1hxk -awborkhbjmby76n7oe84jbhfo1mde4nkc5s7h9jkhuxzg xzdg6wwmzayycxo4umkgdt3ikei3w4eyxxsta5ezq8e76 -j6jyci37ybemmjohsjbsgawe1gg7nwczm1n3qettoi6xo bkayow6q6tzmrsp86zd9j7rjq6u6i484tsg3o14pgz3hc -tw418hnxx3rj5bwhsj7bbpmu5hnzxjcaf53nuds8uw9fy ctitmn34cmijcisfe9b7fe5xmaqig5dnszzyf9ffsfybg -b4hdpzkhn5k6e5jyu1iohoqrct8wk6icuaej3jw1s9mre psiy31om4upfzjuofikcnxaxp9c4xxehr4pjpp9tzwgiw -p7ftx8h7u69raj73pih11h4gxwhe6zsya7c7qjuj3sqkr 571zhwee3m9oohr5ebkwrgfg6r4w85y53qrr8xysk1gbc -shks9imykpxuwcuxzbfpxojph8rcaywm9a5ef8hzy8kty u95aqf41waz9iqmh4hdbio5nrhz15w7gre6sh7ahwym3g -4y8qdzy7x6nm9fozqyihgh8o3kz9mtb73ehxzi7rjehmh seuqhyh5b8w3ziw15itgib9s1jtirit1up4etfuhm356r -w5qzbea9bq944d6831ry97cuiaayzgeygey63pm57d6fg uptq8aenw1he7s8q4u95pc8c3ony49uoogpcp9g6b38bk -uwoibbz6bw336wrp8a3da3ee3wdechkrxwt9dzenxwgcc c5x9ptawei9hntdmnquzdwp3ijzghfhn4i3ai7ut8r9m6 -3jog4igfydt3efq5w9nxm9i871rfocy4gzep5fpn4ad66 4wk4xynzihjk81kgu5kimooxexpiewzqoxu57t83ma5g4 -d53pqki9it6fzxopx7n9ybdw9aiucc17jzd1gb5ztm3z4 113ze8yeth61a9krnhx7knztsxio4t47zg7mynu7c3ubg -thox3fwdmi7cijkyzyxd4x7dp3i3cge9su83y5ix7ewr4 m7horhtku6yaswowxzg1px9zqqarmwup59nirt71ft35a -5cd75664mfrrukbypfckumzf6qr1tm1xecos6hafhhr6y xsxeyth1fso4gec1izxg1s6arry5tg7kjjnctdh61urjr -q3zwssewkq9gk7n198h475jbsi6k7zbu3b88k8f5ozwuc 3wzc9uwo3rd7bjw549d33a64df9bz386j8ybckj53ddky -myzjqg4h74maxguckp6mp6mq6154gipbnyba3oihz71bg 7aempekxzg58i3d6ugwezrjii76gfksfje4ufoeshmezk -3cpdf5c8w43yp7c7qwyy8c6pdedd1i3isyjqao4jsuz5k noinxomnjetu8mxmwnapodu6mqoj5hmtxkk93p9frgns4 -79xuuqdx61y1uewb9r75y6z89rqyd37x3hjhs353azxzh s5jd8qhtzrdw5u6kiq1byk8n9so68bkaxku3uxbxppfaw -15cwxx7na6xbs4yff4ixqj8bredtk3373yqh3etpesxxo jger6i3ufmrnk8tw65jeidbmak5bwaq9463ga45q8sjbk -ztwytebpx1cackcw66difhtws6bw639q9h1sj1hk4md8c y84tko8hs36q5tiwr89tidgqx5ibag7hj4cbhbwiareak -99ukxdgrp45y3q9ts3gngjswkbj6f5hajuuaknccqomtc hkinuc4bdggy4sqdeyzg3t4bt6znut48f5mq6qs68xdb6 -yjd8keiw5ti8d171ra7fnkr1deu3eeumyooecsd19coxw jdw8wc6g5wzffqntajxbna5kwdefm65pmrfxoxip1rkis -64e5u1grr3e6qzqruqsrn9c1br64p1xd4ruptda4a9spo k385pu493n96og5fjw9fqouz5q1yiafwmhor8eikcpd8a -wpi78k1gun9fw3byixixatzqgaji34sbb8u7cqbmdw3u6 76ay6j7ejymxt9quawca5up8udb97zceewzf4kfcrn11w -q87q5timgxgjkw4gzqz7ce57e85htb1iwr7xwmzk9a971 y1ramo3im4i8zwuiky9wfgx1pec3sjr6uaso819yx1xxe -fk94xicriy5d6xbuwm3aah1cmtz3ygt5qh8u89wp7oba4 5xwiyqe1oofz9jhnqwgseahkdwbmxkkt8mcmg5q91y71g -tpme1m1b89zbgf8ojmz4981ox3amkexorzfynwns9gqtg qmee5tcffctkbz9uc1hpwcutw3k6f3coam5n1d3sdgpbc -8p69yczow8xb7f9mzcyzz91ogi5rcterz371a13cn4q7w a6sjyp6ddhmotudom1sbptzs77kmzjgy947wd8ucfwfze -ys9eno74wqotn15w3fcttaus195gh1a9j5gdynafozuiy 88cchikxnjtaj37dswr18fbbr3mymyxa5pzq36j436xzh -9hq7o49afj7x1jzdru8qgpx4ucgu3ywppwo3ikzdrspew qqjrgwag3dc3fq5bhjgnuouusdt5m8oum3y7hxtemhxqq -xfdw1n4sdoeddtfdk197sst678sj6kw7d9iegk69tb4rs m88tx7pzedtjdnugbe39yfpi56dgmiz4pwwbp5ga5qpos -8syie4fxdozoz45ewammb3hhsgqx6rie3184ydph1mqy1 364mqcrsrsc3735naogoouzg1kdjzfacmuebxf5sk64jw -a5dper67fzkk3gh39wqwkndw3618tgt7jmj6a3ani6ei4 68xnpx3thsgo7kn91u5t4zkt36c89k7wrix1t9dwdzjzn -wtp3hko6mrxzcs7zyfqzgx5fq3byrw3tynpg5k5ezh5og junn6y6xjk4bo4ugehuuaq5rtqxnpiitj6nnxnxf1n7ja -dkoar4ornq7a3iob74azpjbbq37ufp5bs39nbuiijq354 dtdweyp5gqu93qii761ztn7383ytnaqtqanetwd75swik -susxho48suj8erg4dobx8am46a7xp58cnp41hiz18ztgh iksz4q3o35c9grmntodqq7pyay1y7uahmz8cco39u7g3n -m9quxcqx3rdu1f1wx3bamjuk4ebb58rnina9ejkz6w4wa jnrfdwcg9r54w3qtecsb3ujcwzbh8bdrs4pn6x9zypcgs -iyma67wowhwyhaxbqacrid3x3j3y3zgarfhfdwsd7gahy 5g7okwndnqzne3xigo1uxbbxh57pun899nr9jn4r39gxh -o14b1qto886q8p3ode7sa5n1mepj8efjb7ums9uzqcour hju997pwxpoozqapw4n7rduo6yo7gcriewbyeowmq3k9w -jn39ix3eidow8ri7krra9hizu4m91ia1jmkh1z9fugadq eydjtuic4ofxcacj9phyrg9fwyxnzkra4397tomk3xtdk -xfurd1xqbrkrzcjr8cwwmoadgdefm3ckcajbuzi7ptg1h i3euo5jwrcitxiwkc3o5soed5arrqqw83kwnesh6hmk7r -b4qpb9wef7icks6rwheo1cjqmg4adpazgmmep5of8atmh mkk7naw5tj6r74tjzkw6fc4u1ge5ru39ymdwarpfiwyt6 -8qxay3zm1r6uxwwa7yrp68p9x7ox61xk1ky4ea6jwarxg pffzcrg5o8bmbxmhonst8czchknbhjm88gg6k5ipt6b7e -tis1w339n17tuirehb7arjpgd5ozjg9g76g9ykz4t7hqo eikwd866gwuoyscqihjzb8ich4w491ki8y3aibzstu6iw -1gf188p4ckb9975bawoqh7w8c66jsosjys9hmuxznfioo fmsab4zghgj6xdgu3ngw65qhwn3a3sutfeaidr7y8niug -rgm6tgkc5wxbezgfsci8hmqjiazp1kq7wdmqnfthax18h ahdaruetbi7jij44gk9wxohjfcti1dw3kz3ojqw33zgry -my1gyz6xn61zgonm9dqa3d4wrjthkxywjoc9mpfeto61w 7wye7qj3i4whrw6nqwtrihk5scgfyqeu31eoty3dmf7js -6dnemb9whkfmm4xsgrc9sdpf9sdac9qjc9hqwzxwsrt6h pqnwsjmxykxnbzpm198s7dyo8e1kajr1knpeoiuxk8956 -sp5mq1o3pfwibjatogednn5nbdyrmaj553q14hg8a5a51 pzybap3pdtdxbsyfw5onjbxmqsawnwyy1osmowobhcrih -fakkchbajbpiis39oy7cwm3a4y7uc7ctgt6z8jktfwhps 347s1t5d41sqi9twb9nth8gdekem5y5wcgnbptm51i4h6 -cbzg1t4d884tjjrasy5s46gfr7odjuzf79iwqy4syfskc hxpngfyfumhbu7b8pihwi3z3y1tgsw8ign59sd1qbcrn6 -164d3p638cbwok75gx9fhpzs5znoo44c8wgxytpiu4ete 7zpfi1kkk365y6tft5ibztiqgh8icc6hwceutyu9c4r1h -sxpysehcqbhwahkw5b8sepwp31tt981jnnizz93kspock 6f54yw17gihww9oex9ab37aacdroojig4i7qw67zmpadw -zfn3uidadyrm1j1hy6atiyfsqd1hdbmoymjcu9t875akk 6ju5x19wzfnm4q3dpkqibm7wrmnxteje555iru71orekc -cusjyutkkpp7bh56ozxgyyuecr3nofe1jyqpbjufhg49c bqk4zwgjd9apys8f61y35acy73a9axy6r4cn57kfo14kk -8i6wu4uei415mk5dpbbb56ucfmkdcpzors9oh4rkgf4tr kdytr6zg9qx81p9u1g5tizd66apt99c7h1yd5ojpe4wx1 -3kk4skueo4nigrojry7sj4oeuinhwude75qouy7i93ozo 6d6tu6i3pnb4yksu56pyzyn8t8kifme1obdm599arh814 -i3hf7h9b54tror4f4dxfo5px9hyjruhck6zua768sea3w auqzwzj659r33k7dxaz3u4rbdsremr6on9qcn7d3xyp5o -ns165brfdm5nq5u9qa346e9s5h4yaw4hzs9in9dqyuma1 59ozcif59xhxmiw6a1351r9bygwgiodr3ntxsj1yxtoyk -nser99funqdpa9syuc6gykyhymjeig54tbfrsyu4yxyxq 9u71ebbpi4dbhgu7m1k6uwj3ray5keeuoe1mh51uf381q -ymhoo4n9am887usre4657o9te7wncee46zo4wt465b9nc hwbktrow7ifo6bdxraoamd6mhu1e1xo441gi8pck3r8aw -5znf4cz3uwtsi1ue97csptowkca4bs89rxoojm9scpeah 5fo3ocd88xrifqdt3qkqfhrhmyweyso7p8fqx817u38is -owb9qdz9d47khwix89fdrtwr65u6fn53t57nxrp8zm4ck 15qjazgbigyxuy597soih63kg88i6s9n3bc5fmozipnzg -ogjm5pfr9o38e3b93efagzzei3cx1p79w7aiqc48tuask ojkco49shqfimpb6niogndaakrpte9t9ddanrwfrcz95a -hw43s6m1xciizjq3a5o57iyx4owjxugonm635canoshw1 wm9rptfrdebu4bq356t7oqgkqzmati7weyroskhjmy6k6 -fijt9umjowj6pgizzcb98pz74pd6nmas93m7339jfo6cc mqae9q9gnjcg4z19jr6zeuyp1npu184zuf5df5qxkxj3r -h6h16ji374bu4g84h8srromq3h1pn3dw8gt7e1rs7mgiw bs9a661yhggxjcdrt44rbun4gixywymqx15kk7m6uemww -5mr964suore1nxb1j965psnz3kbit8komryt38exyhszw ew9gmd1bzfo771f8r89x66ifni7o1y3z4xpecsr5ceq16 -b4xfsdt986fu4hgzcug1ua3ozc6hx6johgdamfkk4cbxk m4qj1jk6sjsmn78h4ofm39bs699y1cwhd6a44ki9b8rir -6cjn9xcztfcm4gnbxmmqakm8r6on8gw9ots3w5a8cx8j4 nyfnkg9yj5s9sjzafq4sx6ix4hr4mq96hbcy6qumhk6en -3equzoj3xw8k9o7qm3kihojq1z8ztjqn7nfz16ojxy5fw djek8n33wwy9ddgky4ycqbd41mh185xhabxoi11own754 -qowyh3fn4pqix9p1bjkkoos6r1634amjtfkpc56rdmkmk rfqbkxko47d58ef345hoied53aq5ir4uii1t4zy3woqgg -rn3qfx9uykqsyf76hfi5z7c98qj6tdu6w85szd9mza3wo yf3iw44fwyxeq4qi3z7y5zsymn3jzwyrfpcjhueuzxun1 -okadtertt1s1emg7r7rp5h3ga8u5uuqui5bm7ouzbjtrr oumqafmduup7npco4jam8h1yfnkq86c8woherfat6j4og -67tke9nxgooug3wtoatxk49rrq9w91dq7rcdjqtq7utjg sr6ip8thqrzq7iexadtyfywbdbz53rhgdhtc1ctskpuba -mqja4bpqczh34kehonu7fjyikt9gprf6h1yzbhdb9byxs 8hsoefdyujns7bsepasmz58m6cg55gcfw67g8majk1kbk -yno35ikirpdeombn78u1auwkcsu6dejamkijoqxt7f7ws t9yak745egfi4bxuz4arxkjwj33o6rdgwtbx1m89e8xy6 -7fdysuru31wyqkkngq69kzta8rawkmwaocgcrcrju86ky x7uiqy4fy9pynf6xy979f8bsuka4rs3jo6cq9n67ebqa4 -yqr9p6nqnyk7pkfbfn1ittgcakb836gjjju8opdpiduw1 r4s55eqpce6sdzhkhi1dgmg6xwia5zkd8pfpz64xf4hxe -r3ebf1fcn6iouk5bazkrzkko1fxip6br9k9owzbrgfiey 3f6yp5w6idt4txzqcwz4gkuuxtnu3s7m64awofcz1gnqk -pzmo9uku7e175s5ozt9trdk1p5pc5b1rxjmd1cehp1e61 pxin9ggcq547uzdmwxj7ssn8jj9np74iw97cmobpyqj8o -x65xyorfgsbt5r9pahq68jcmb9speb9njg3jsxe5s36ch cbh6n7zxch5g66hr5tofmwc7gbw4asxtzpu471tqe9886 -imwparkexwmcohnc7bobm6it38eamcuq5mgetkr6w9suc 1qxa5xmx5caopytrjyqrf67mtfihmtcoi7ihi6xzio74n -eds53xwsbw6xr5on71os9t589zah93j1au8fp11qrcd1w emy5y7ck5owemuhpdrzidy1gyxba44w54xps8c9o9ptqw -7eiderafnpphi8se6r7wy8q95jakd74m78cihy6xmxt1o 99ac9nrq77f4k11tfusdqmhwozgxxumrkukqzh8hwwokc -xon7cw79by7pr9nkh6ho7ibcterkys3i8iq8j8ehsk3mg ju6hqxqkug5p7i96zsw5a5h98o6a3rjxqzjtppfhzt8in -miu6gdyry5aaz1aiwoxnsfrfajhcc69amxcp4m9yhzk3q co6czjnyr5t9ed9ika1gqri9h7563cfuobbzigkns99ys -fycpmkohh441md9a3ahurp5u4jrt783qsk9rpkyobkkts 8z5b5x65uiqzkwj7hjnq8zo5gp1xm99hg3a9ie69qwske -k59w4kqeifh3qpiskht6cejcc5pmktwe8nc1dc9cpt5qc mad76k3685wmmacwui94gnc5bxugcndo6guw7az7p86yq -ywe5xxxgents1ahn4ztf5sa1d47sqkwqjdwurokgkgeqe s3jtadg3upgpgxrp3cntd1jqk6u3s891y3ganoe7qyoy1 -8mukct3b58u5r649w3nstdh1bwn681uw5u91xxmzhjary nir4ssabnq8bap84338uy4hc98k1gcwqe457ifn74g9q6 -juc46ufnmzt3fp6h5akp9ko9iueiskgi7w9f5twbe94oy 4sanr9kj8xe9xtxwgxjxpyaobfk9nzy6rm6n7jcf6qich -rx4aryobeus3b6gt8yrokmi9t5qjgqkc9c3cwxozjr9rs 9oyhjere8rfu61x8qieje6th9zgpntbbubffknj835gao -htkq3e6pch5zpmqa56dog5n13xcisbdzeww8f6w73jbtw 938hbrozqgkpruj4xyzenckupm9bye4n1hqiu7y19ypqy -zjayw694jyes3696dhymfj513nnbcjrxzms89ib6ktme4 6n6apjjo1gz16mwc5u4jat7my1mmwkawwbpuh34nh8zrc -ndhenaqwrxhwqcpsm7xrzdfh1oq8jswdeksn9rwwq1wyh jtkymh5qwwogwo6z9u98egmqeui4cqzqjmpj78sm5w6x6 -i43ypgdwda154wtdbzm1wdmoty3nitffundga5djxrxu6 mfa4gqu5ufecypq7xddqe33wj37ym954gwg8sats9jszq -xnwtoa6xb61c1ztbhgxch1s5ba7seiono4mgnf6hqwomn xozdffcs639kipd3uhmudpfmf7iqgx851th14e6jdpnhg -sik41u8xodrksfge91m16e8xwgj41s34frr8zmr98basq 9m7kq17p3fdkdwbmym7ti8zitanpdwqh8ajyqakbyhcke -96x7jm45aw3se8h4fbyidck571qqqfkuqfomo8w73qz4e 46p838w441x4qcbe9ktpw7bg8pbtmhnubqcagmw8ya1ta -9iinr11gfzkx49ibdpeucs4uko7m96dej6g71rg8pbmx4 km797wmo9ezikok81dssx9j8prmse4zz4snwnd4ofocxr -sad3uaomjxmbx84i3w353tcec1dp4dkpwabaarchn3dee kkfbnzfmbg7s9izbdjtfxxwjb7zp6p9379xjs88bbo8xa -bc9q3ckm8hxbs1eyydq8iad3xqwta95xzntytu3hi1nwn ex4humz8si3d8r8s7xkbp1fbipm1yk3855m7meyh7o4g1 -bho5ghqswy6duwahpgj1g7oh6dboa43sug14f1agf3a9q qpwmsuepw8cocsephyzuswazsam6e877r5kzpmhu6zf1h -thfwar51pataeqqj7nf1bzt6eg9jxrzqfxme1a9phdejg 9zffrpefzwfbu7nkaqm3rxrzrq7jm1q6u6ytmw3yaegi4 -637ahr36iajcbqimznqc3zz3bjg6hqe887d9w68j81qa1 qxbhm3hknwos93fd46e8psjc31uu6kpgze6i6ts3ngfrr -caikdqbt5j77ioy379gmyxcgggri6ba3fpef9rds4dhng yc4i3x7ohcj1hps3dsmpkb7j3iwj1cn79nm7hscfi5o9c -5g1nigxssrkba6gz39zra9azk997q4cuming8x6qzr5pe 6h7aiuz9qyo7n5tk8zozbm8wk9skkea8ieysxhqf3rysk -1qk1d7p3s891jbi4sbfybsxbuk9pitgrrt5uhywzm41as omwdzauqo7148kdkefdhoo8wktnwgmth7ujcucynyuu3y -zpmfm99rtdnfh6ocmt16hzb68isy3f4arbpea375qfr5c j159zj3h1d85zucw7r7p4k59uyw3ws6j58dxmkwz7cesw -71xeo7ssz6mtb8ixcbykf8sx74zxki5gdcnzxhppyoigk 5bu34oitsqunqjd394fxbaxf8ek5qzc9xwm5hkopthdfh -hsiwse1ptqyjmf137r13pg676iuqzb49yac73s9jtqee6 8j3ehd4ee1jeupbgfzn4n785ik91asea76pe57uarpuhh -m35qcatuw5r6d3c5qwju81w1hewjydk33ei8wtr6ogtuh 37yuduf3mtf3b7b7f7z5ime4kyogorq4rqh6nbq156opy -q7dec6cygp43jaqqf1ru9f9eosem4bfdexpcfiokz478k m5itdt546bwradexqgww7pyscfsjfqiqn7h7uhz5ojdto -1dhdoci5ajsbhpbp5awaifej59x7bkqqmwejab8fzi9tq 61mfbjq3ueh31s6edot1zkr3kryeoq9odpqkmi9r1f43e -yoz5a73twddqq4rrcyzw54rr8gzjujt6dns8xgr9jp67y f59owpuo548gf11a4qi6edpgtjrfo1wn8dq7zoayn7knh -admsmkb9udb63637dstoyocibs5uq8j79e4hh71xhntk1 bkj4bi71hf38hh6mhefa7yakmbh8p1jsapo9cqwocdpnn -9dfdfumipkn844engk5zcbk6iizyxzpm9efx8ao73a8yk urnbs9e7dazn3myjfsnxt1d3hmfw7won5utyd55ao39sc -qc5szwwi48m73q3k4iuho1z85ztgiqazytg41bk174gw6 wrsassdcdg3sb387bpur949ef3cid6suewai4psqq1861 -ibwib8hhthj63zgocwzxqbxo7bbynro8qjgkdao5ck7a1 7yjkxa7rsrr1yt5q8iympjzrhr9agb7ao4goewf4kxka4 -o1m57ukh98y54xkq7enaiu55dqced3s8gczohzxor6mes x81z3ftu3rak3q8gaoepatpsfoewp4bt9hqyckmhg8ote -6aytpnong6gfsecwx9xomtmjp4fhjsk1qm9twq787tykw dg78fac98xr9m36us57hx9zi111fdu6inqfffkni8cm9n -74191pnnmfqnxiyjnawffkrcj4kt51zqkfkfwu18ytgc6 d1z4yxpe6asqi6ukbcfhptatm467fjupzqghbcx6ntws4 -6fea7zdumw8asfo5ksucar8xsfigkagi354g3owk68841 wjosm8481zxd1ddn7ozu8mbdjmggtsf583149e8npbxqo -a1i4dn4z5bymtkdbryrrt86d9qsmcubdyfj44s5ojz5eo baybot9c74kxwqf6o6wuchmep6x3z9oxqw3jn8tu7mkog -pz8kgobkqb8fqykmuktq9sty94owzsdkybr11tujr94ca e3x5tr5aqni1h1hczyzxqzwzezipox5gj54gsgiaro7b4 -x5t7u9q99opzxqktbq7kauojy1y8yebrr7y9drxwatdzh usifj3cunexb41x1kqjuafj9ycy7qn9gn4dn6rsf3gcgk -erb1jrrzmr67b36po5izz95aenkbhpph3o3pzz3qw4xqo 46he79utwtph4m99pq7orommg5mhwmoh6x8a8uqqa873n -wgjpef73r4boaa3ku9zo678ynte9m84oeendkpkmca1cy oexhsrh9s81q1fbj1j7zmnnoonh5iffzhimsscajmofws -4waz5iosi7enckc8axfcmeuk9hax8iczr15h37exzimpn 77y95qa3hwd1sgr9ysh6jtxwnqozjj4bg7ikpbrbfmjh6 -39uemm8k36ejma9jjteaa4tw8p1tyxxyo31xzesco6tbq sjb6bherkucwhgohykh8qwb41du6i5mokf14twqjzzj8w -uyzei4sy5za8qyoft5j6md4i5kfpgrj7kns8e6cmu1wsw xdg5setzh4u63gwzaj3xrrsqa1wikz4dgttqyaz4djybh -q48zsncfxrz3dgbnng6q9h3qg3tc56g6n6qs7eiuwa5kn 1pjwm3sxto1dookk9sk71ba1rw38wqwwfg8gztsmok9ty -mp8a5ccqouq3zq5xppctqqhf4w5gdq45btb1tubauf77k udbhsxux74h1wo9wkhib8ohicmwk1k843arcgceb16y9s -u9bqj1qkawdoyexgxzb79y8tgu3jie54i51whcez8ohdg cejuasdmbrw4nfy5kistyj3wk5eaeccr945dgoyw98d3q -hb7un6e1njmzn59qdpybndfq3mhutaqkftx48tcqb33f6 qtqtzak7kbchcs7owr91gnnbp16hw7rjj8sictwdnukxo -tcft7zdjyak5gngtpcez1q1o15um46qaesaxeuj5zzp4r okz3gr891camm4phqnxiwebje3rt3repjn8h5amjfqewg -rskbzp8qr5gh7nu89otj3mgozmessoh6sw37dfysq674r 7oiqankxnheza4gziidm668pyc88cacozmjwo8kufgqes -wj51ksocj6nb67nsg5cbt9bokatmz945n74d7yh9w51y6 6zrju6po5r3ty44yt9xi9b8j9k5np9ioazc8ir3i1g7zr -kxquw6e9tkefhch9n7e6wuedotcj1jkw17bib655fn3t4 58fprpfsk86nwbrmhdsngu9nbnn75fggp9kywp7hyo7r1 -6dzsznktnbgpk5ras3gkycpqd9dmbrry89euu4hes4oaw gjxqpm88n5t88pdzk49xkbuyhsp7w4ez6dhrtwwnrc6qw -awdm46ikn8s81g18z73byxt1f9fe3bo346x9hemezm5sq yo8ekmn19qke7ztbztu9o9inrfrxtc3q5kpc8z934ehdq -chmmjzqdqkq8mhhapb9bbgzsu7qkuzi9axd5yi4gepcmq y9k5j949kqhw6fwxnpmcjtg4brhmzi4ezw144arqdbgac -bzpiz3eodxuzdnq6x5itkufoa7qmazd5q8epxds74t974 mw6fkou6r1xshxuyz5wd3n9hrycf1e3696mz4aty885za -pyo3n5m19bumdpiexjdp67kk4yded8yhcs7pbe4ciy7u6 1cyqihizo89j9dccjipc94tdnceepp8xg7fcu4didnb5s -rmcrufe1syqawgyoignap153pub3xyx8sdp697eggg7zw zdu5i3awdgi9qau3azhwunigh8af8trhmx1zu3kyo44bn -8n6kcqj1rpm4xcam6k189su7zssodresdofsbzcefc4ra 9qpshnkxxb4ek1pus1gfqui1y65dfym34tzt6xb9k8co6 -bckxjcpeau7b556r6hz1pz7ido43ziwtknra6keqce38r 3ufqq9wctpei417m5r1o8f4qnnc4niejan6qbs71mwtsk -cgtxmj1w4zf731o1dcrrhcyhojkkdzu1awu7exwsroyp6 894rz5m4ewjatj7k8pt8gd7iocno4m9qnqkzgc6miky4g -9sbk34mmio9p6jtwzrox6c9qf9k3kxy7mqwhcr5k19zuy 9i4y919fkbqcjoqbuk3he9pb9aukee6dsm9gc944k4qjg -egkta6f7cbjjzssdgrjumwrwpfn97461mo7kxwecp4oc1 ahhecmchh6pphdq3bkj91nhn8t4trpupxz3j1af9d1nf6 -bjk7oix5itinw1u88ep7xug8ua8si1h71d5p6y4fefb5s ce73o5sop1nkm9tedzipgzumrzar3pwpcj95m3bnywirc -ya846su4jfuhgio51dym89fneq3yyd31xjfdy8pcfxx5s 8o4ppq57n3i4pnd7edw7crfgbjowoqsygdq9f5gf84hss -j5cudptpk683tbskrf57f19gdptz8a8s1bn149dz5xqhy z8iom7xecfqh9zkmbbkw7jb63t77et1htttwm1x8hnw9q -wmwh9qd8mhpuyuen7ypxfc7k5mrx4f4omzuc4zxpx9z4r ejycw7bag4tp93mby7g6zrr4fidjfa6xhqq7i1ee554x4 -ja57b5xxeorpx6bdq9hte7ddiws1dkx3dexipun88nxce wwmo9hdr46jcqbe4c5cxh9n6zr47x1ox13o8bynku6neq -nodntungw78je8eb6i5hgbdppuy115zjawhk1pbff49s4 16kgckt7sea99fekfwrpddh35sp594fboon64z9zb1j5a -93679yrmqbxg1ax1xxwppejd4f1ue5cj9xmbh788jsn8h tq9xgq3yqiuhexd3p1yxeytcbyzcoh1g19rf1bt7nukbh -xo8m3znrq87jbio6xqsmecx31r134axnb4ee6n68cw11e 6fpodg5wn5ekw79za7qjozxf8cj8i5xfedfijy6fhxsrk -asdu7uffugoickahofwq1zgp7p6agiog1ks6jcdyccc36 izqkhcep1mp3b8nzhr6cu81g31wg3u8w6px3t9hoia8p4 -e49ow3zapjea5adadpdz1c56ject4odtaou1c87gw7gjq qx1daf9aintbb5jpukz7gx7nfswuad5wwyk8jeyejfhe6 -dwzhgn67t4yj717hsjgricdnwt48qdwbpys6nbmm67kj6 p6cp77bdq8e5aa6rodu9kq9t567fh5rrkiqcs9gp1y4yq -qonqirgsuffzsdm65mmu9q8wx4detdczmz1bmm7mcf7zq aq7suzjdinj9h1udz3cw64r4eacriiazztwq7tbrxpqyc -puo7bpee5pk1usy4ucyh5okuagqj3eohep7mfpew7db3s ryaxd6cx7qd614cirxt7bgym4xem6iid8x3b3wnwp9dxw -rhrwntwodeztshqb7tjijpzecrxpm41wgjs8jzohpeyr1 dkfbupo3xoyaqqydqe3ozfjyc5fu7cau9w8ezy6ywfq84 -mcka1kfc38ru7bwkadjhoo3xcz3qh6xkaztbuqskpuhp1 cg4y1tu1roususdmjmtbisht1h38c6jnnx1ez4wjdiy1y -an7333x4eox7neo4ngppdnzc39pmirtqugi3diropq43a owf39tqq75zwabujetxs8t9rmja76ya8h178rik9iaar4 -3m881ah8anh4wtokc8emtncz81b4krdmnj74a6ci386rn 5htpz3wi1jgkqt88579u9eyc3rrqtme4b5oi8m8oewbze -6bgxn5gaafmwaxpgjpb3xj744mzazbbihc47pqdfbbmew jyqu46wbcjwtmdcijq466qeorx9z3j8b9rpgmrzt7ri7n -xf87i6x365pmmu68wptugromaaucs3q88qh6w3f677ncr dfqdun7yayuh1e37n3x76ihmzh8gj9gyhoaj3raizpj61 -7f6i3aqz7butr46mfr9e4oju95r8rdtffb31grcdi5uys iiuomc87ythqxritq993y5yzqnruoikst3bts57zxumwq -chw9577uminrubo9nwssyb99ae8aops6oda3dbx6sst8r kznkhipzugzqtpedijhj6zmn1onpiwe3xff5ncy5k8woh -a7o4sdw7xurno5huh3nh9boq7ka5shoz4tj7aqg5c8qyw 11a8c1kwfaa9asubymyu97abem8rf3x93g5txy9xkbt1y -e84yomew31d3nj44bd5tc1sh9kyqb7immjnps1s9u96dr y5qgmmxuy9m4h4tt4rwr6ittpu8t4eqet65rmaafbcih6 -ppizftnk4w1t9m75yan79o1kshprbbcdbux364wjwn8mh e6u7nx8gkbgfsq1hgt8c5zoc6rar58c6jh7d4174fx85q -3mmdksq6pn71u1wzsx56sfxmxasb4919sjepnfe51t9en 3187rmf6xtgnryir1k4kofbsdq8abk6rbtjyxzqgok3oc -b4k8qutygnewrcmrahqongac19a49smtxegfmjmh4hmpk juz56pyboitiyez83yr9fow6mbm17efggzgptzjxj8hrc -rhcn5rqadpue7g1rgp9338zdy6c1m3gijqm38wc8tk1qn piudjrzqcu7pd36c7p8t4p6j5ica7op8xeih5ggqdkpwe -ccd9tq3pcjf3p6r5aad5ubi1t87kzxcs3ncr4w6o3zrss 4f9eq6gdbwkwu5hb9nfggh78j4xbx5obdm33f1ithb9no -8ed8g7drahrofuf5kizu6bgmcps88d83bifqpe5xpd7ch hrkquqeoszzbjwcrkozig8sfxkkrx97ex3i1mjaucj91r -mdt64pnsc98h8ipo5rgzaiyahtq73terkic3cm7gzfrie g9qe63m6fe4e1b4pr7uiq1ycz915aj7gxox37d5w8r4tw -yri4akxkop1ta46xpjceyeszrk6r71k8r1gex7wxhzwc6 zb5tozmyguji8eqnyym6zug3fpn5nsi15f7q5j6k7p6ia -a1q9ec4ym9ywqhqbncx1s1cg9t63fgdz8m8eeurxop8m1 ddwa1cimo7tdiqdm11t1wtnhhwrmytk4jt8ddkuhxmuy1 -pg83gbqqd6ir9bdy4bnfztuw3j5awzccsgu6sp1rk71hr t6kpmhnn9bamk3sjwdbbkyhktsdy6j8ciz4z4gxyeb9tw -ewwt4m1ugoatgfikfryspp31dq8xeh7nxoiz19c88sw3y nwfjp4we1j3rmuh8ommz3ot5rduzxmwzqagqrzu6q5scg -jhhjcbaqbp8mfmzogty9qs9g4hapstbesbkj8smbk4pae 6ti1e4b1c5bpb3sidsykco61cikoanhrkrp9cq3ca6qmq -ertjypsar4nbg6nxhtq4xp7i5a9fey5geht3yymoxt5uc y8o84j5dargyrsxxnnnf7u5mwfojnipbn59ukd9ym81yo -impc8wfwxm6hcfb1186ecd9jo4r418nc6ko6sxwm7q5a6 zwt6esfgzieiuintg3tfjsnui7mn9o4ciyt5egdtb9n6e -c8urwsyxfcg4s91k5c3i9xww6t7odhqtb6fioekgohsra xrwz6q1m8fthss96o7cpnqiku3kg9rai8gwybhu3kgisk -z53bu15o5yxqd93h3waqc5tqf4j7ja54gf6xdd9d48ay4 a53b8nhho7tb16abhekzimx9eckzg9ygjwpqkw98twmsc -c991p8qp5z1k53imokauzj4b8iujz8wexbuagyxgzzu9c jauuqnbk163prpton94qy1ss6pzknphiboks4hzpu5wba -i8kiyiypwrom85irpi3bj45j8tudkr36yqcioot13c6jk c8bjz6jyt4xgerobntu933hx7fc44u1whqcxyfu59dk7c -hb9wpyy7fzsjdbwuuug5waihjmarj84uujocw3pmgn7uk bpd3kr77hxwjppyg87u833wkhpfs7qc5i918on5q43sar -wkafq3ox56oz1zhwbier3epk35atust7gcmdacnzntft6 8ijw6yzdayrug3eoft45s1cs3pwx5iq3qmibjd6q3zsnr -xicqgu9ej8eu85awhesqjbqk7jsm5xoh8j58z4ccscosg ccztqcpnfmqkt6rmwok4y7s4pmrtd4okoyuorcx8optx6 -a4rha7ubhun5nyazne17aazuemz888i91hsc8tae9me9c 1rk6k89m8qgoomm1yc58f3qhyyb3pu4yijpydtun8ikik -kg3ttgns3e8ysc7jfeoxcsmj7amprzdn5xdkhz7ui4cae i15ceg5armzy5m8dk6p59kwdae6yx133sct3rsyy733is -hyz4u4wchp531sasij4jtnpp4iyr3947rtxnckp6a66to dw5em43f3bu4hjtc66keucjuub15w9x4osmncaunfag11 -oko4dm8utj3mksezp7wzwmba3hws7akadheixdnz1d7r6 9e9je5tko1qhespaft3o4isaomrny3hiefe1g3zaaz8hr -jee3y81qforko8qwm3d85ii9g7154m6c39mfgg3cq5s54 iwnzjye94bkfgp8zd41o3jbkptju48w798ghu4f1ap5tg -a4f66t8hhsx67isf7aetcr5rkgj1mnfywhj1ie3843i9r h3n5jktndq7r7d6bzmgbz41pmjce1ye5fpiogjwp499h4 -g4479x573rzu78nmrt574kfrmhrrpq5uiow6z145nn94q 4c31kr36f61ox1ws7nsrktm7rnweoxi8kg4ped7fa9tjn -i4zuen7zj6u4pgzjrqdyo5r3gqgcpyx7mwcfdjqzabfw1 3nfu376b7app4dbau1g13ueyqzbjmnap6y64krrfgbxqq -kd7ysn174ogizgd4qpzf8sfh879c6aadnc16i9ijh13zk ugejo7pecsbw1pp3nk157mk6ypbamt4f1hrsjpziamm5e -rkoqjii9spugxes5tohw1gkdzkk3tke6isz3q4nbzugg1 k6i47krzff664mwenn8k7fxgqzqyghprqrg1bxtrh5b4r -dr118qquxtj7dy38fye4aag5xqo9n3etnjbs77xgfdrhy hfqijcqf95ybn8cci9ydhhq7ihyabdo5m47f8qm57ghcs -64kyawojbxiyynuqxe97w1x6ir1tsobdq585nnsuiuone pr9wkdpgc5qgztp69747hwdhxw95yjf6fdhcsqzouo6jy -sj6btcczij46ghgmhsj44pqkj6agaxufisrutk4s9jz5r zn3udjwywjzx3cjrgk88guh3nmknf5iq97n3n5qyyh11r -msbgwek456e5gsnb1cnx8ms4mtrurraxi1c6em17mtx5y efkmeewjmojxzm1uwgw5d7z85ucggegwzazzjfk84npuy -kti5bcux9ziesy3tq4yq6rxaxtb8t8idic8o6agjjrg4o b1a8sasahp15hs5qstkftw7dg38f9p549skon49mfz1d4 -snd7ob941e97wyotstkzhb7uhm4jorde6m9zpfaz8cf6o 1wk3h17cjha78dc95jttkn95d7ntm8ukba6ucegececca -yspxg4ysocsdew9e3trjsh1kcxyfkrp6iuz57gta4etxr kzxt3hrm9ffw465yt8ejdftbbiwhs6e75ox7k5ttipija -mgm5jtu88nryt4x7i146njit6e9s9yecym4zcu1upk544 3819t3fk4z8sobq6iesit49kzhjht3urxxnwftqjwgpne -ziandkz7sjcysnh8efu98i9hu4aqqp8a45ppkhs8oi7xo 1dw9zjd34ccdhpyzufiiu7ot3hdg83g5993s5w8cmbwmh -wcbn9g538jpzsge4u63xdat9nreujnhd3n7mknga7z99s gm6xihx1guq57riarkoyx11tkxxxw3a9ehy6r9g6wngby -93tu91mcn6harjtyc4868ntgw1hcrbmsmcfz8dt668pig x3srwgypxz3bgerzzrb7sf1gycz9nnec4jpbfd8eot7rs -ewkh17dtfgxa8gmf3x1sp4ntjrqu7819jzzgxh48akawy gtb7d19swqzmx99b6xmkrtcy1eiuoqcd79mny1zq6n3ac -dnrq8nusfm7tonwb1fhjt8ry936bfwed9hknbufix9eih xibrhw6ediw7rpgi5mzttcskt7z1skeny6bqus84y59as -8iw4ow6wiruw7sibns5wqi7zwm9zcirizkdrgkapnugj1 cnababuf17jze67xemk8j5sjoubrsjs4w4nd4egs3uoer -5rkbocnfsntbayeckpdr3nx6kdmdj55td3hwcxdzbhu4h 8xcn13zxsbnbjoqscapdfy6kqnt41mchrtnuq8scxj1ch -87qwhfmk7jgaupcunttm5cfjmr11bcr6z6afi3b6ukmcq 9n67pwyiqao91w8f7wtzngwwpucbzer7gbf5jijaqkmtr -imj4eqxg47iky13f91k4a4yyzqhuratq1hfptoqiys7g1 wpf3eeb9s9dq3hheew7d58zncqtpm59ixk41f1ax9e51y -pp99artcr1tp3hm74qzuik9jztzwozy4p53fipxktc9mk 6zecekisidugeagdj3kdmiw1whkkrgpyjkyib1aatj9ay -zx3xxbp9my9owmrugjc5zm8c45ffq8m74cx67tp9xdoq1 dz8gesotgbunp8nycn4faucsqkj6i4ettf5ngckh8bk4n -znt4hew1wprkk4morsm4u6uqhtckco8pycby65ti4rzpw gd76m8ght6do6p9rbdqcgah5a9rmhiyhadpxbfo8emdza -iok95nrnynatbamdh1f88aed3o6jrehrhngdf7e5xii76 9cxw9nxrfbp5jdgyg3x6fko4h8bk6bgaidagxw5hpa48a -yjsmuzi8ecu8edi7sct59odj9w5wnzxeo4iijyi9t45gy yuu918iycpem9ozd6fyx9mwrm5cbqa85yjpxrioni3ckh -nhifmemos37si8y34c4i7cotrryoue8aephkgq9kk7z1c ugexysey9xxdfwjgrhdphepg9gzye4oroj6kjprt17srg -f5973q1h7me5p55skihcmr9cj3og6r48yenp5kgbust6o upf1fxzhrd89ypaw8nwas8nu4umzqo9g8ke1hyetgoe4e -wcsc16umqm8r93o99a585kstt4q45a56q4haj7um66j4q 6hxg5to76x8wwno5taher3tuxz3nmy7t3i3176t9xqhky -u3bg15sw18urqtfwa74d3w44fgrio9pk6s5fnzosuy35q td4aftyrxkrqb443xi1qdbshof7ua7z4orsqwyyrme694 -dsy1yk8x5t5tnioderupi6tdr7txqgk79cwqhjpcdqodn 3nycsmyg94x8nwky99q9dfqmsmb6t8uioj7amc4ec6kk1 -djwn86j8a5cec95xx7s8jqnacc81c9uj57um3u3embz1q ku8epny469z6y1qsbb75zm1pooqsxeyqaydtydgibk9qh -p6cncqaezz6jsx9w3huuo8c5t91at6bdwi4nhunfk47bw fya9yr98dzscsg4jq3d7k7sn35994eohu1mhuwjmygyfg -xgqao7w3ztskihnhsnmzhpdxpfrsxxon4aa8dkowkqaay wafgqnbbtf7u5ot7x5gg1rofadbxcrgx4hy3r5bwofkpc -6pwx5yxktsutbxnshudemdckuuw4jji8gwyw4i5hd5agq p8pwbi1csmk111p1b8ubjd144zmzaa5koy7tcyrwntcry -d8q1fipyq8xoh37pon11b5dyix3kpuyr3bp55xi7eg63q gkn5phaej5zooqrc3i8aew5iuxop9pwb5y4s3wti4ngnr -nwhoncooqde9y9tsqb5rq47qzyo616c83hp4ztw1rqca6 8wstatdpjbkkp1dr9twqkgoa5iaqdo9amfhtp3jwts98k -z78eoo148npkr1gcehae8eduin61s531tkp9cjoxdfgig mxnw7oqa4mdi5jkgqtdsxyg9t1pam51t377egaojadez4 -w6se69a1tnn4br63zfcc3uhupjc3yy1h4mgg4sto1tuoh 9owb5whmm8frwst18ie754qgiof4ixbptanwxajnffhuy -fw7rnnef1jirkmgsfegys13pq75b7mkjgxbdg89pcb8nc s8nteyqc4hig5m3ixhihaijqgsx9embbb7oox9y86npdn -fb5nmjucztmcwsde7ffbbu3su9cq8m44bje7ubj3z8unw 1be6oc7e8dnoge8o9e75dihmz8tfr8fe1pbypcqsfgy91 -f78gjz1wyt4ywrogbimkqsads85z5jogpzss6z6tscmxw f33eboij58m8183hc5p7hb9pxybsee3rs5n6hmg6qdqky -ajhswgbxf7caf7zf4oxy8nhteo3urmaks3ac8fuz9dzgy j46wse6ano6gzr19efmu4mbe17mj187e6bwa51tyb4giy -pznsdyzizrkaf38on484f8xp9t3qrfpduw9u8f9adiykk dzx6oqijjzhsniqz4b6nzw9ypod9ftti7ayb3q64juz44 -uhteze3s3cizm5qakkqjmdftjpmzgsrmdrosnagyfh6er ig5xth71o8q6n1hy8thj95fqpyssagdktxmzam5m6zumk -dgh5ode7rpjpys83pyen3h71r31twdrtocy7cnreshjsc swzzm1dpqpwi84ddeh8j3yfhmqqumoyhj4xa9e8hfhbsq -855cz1iwkdfi7dzzpesmeourbdyeh6e4rkyrmw7hicqqe biapcerbt17hkht4y4b44yqj38qo7rbae763myb68f45r -ahz61znmgjr1sydhj8kybsirdj3cmb5yhjsjes73fdxq1 n6783uadw3y9irkn3mhrrdxetny39kn1i5coqjaneisqw -5uydq5hus7b8esjpi5aoyfgmzxhpafkp1nu55hr8ze6ow h3orfb6taeof5sftdkewmb7ti4tdk6yr9eehr9r4hmweo -rgpsh4dxc7smaoy55f7ozupm8rufau93hsxx5se648ysc 5e7jryfr87hi4hu9u75mh85qqe5ip6n5aa88duk6pg1dw -uq8u915iqut667kbjm8a7fcsm16awijj3x3cyemt1rjyy hesob9jey6mtzyhqiqbttueqtpzccrf766n55sa7agxia -ac8gems66z58ks8wq86c5tr6pfekb15dms8zka1khjer1 gpr1w4g5faa98py1ngf8h7ioc4e6z7tbtktxfynuntaj6 -fe1d5yo4bfbfsd16xhubfe6xpgkxbtnkuk86i3m8kc7sk qt14ds7sw6a8uaskgmrns6zo5wbdmrb39c7ogswx3u9cw -pefso39shkpuk4r5ue87tbm3mpsayz3r4ooo8jrr9sz4c ib639fyjegedo6ikxdkdwd8ky17mdrtiuqzpbxiw85nty -a9aumjraoogs1k4nex5uq4hju5dogny4jioyzpek1pz9q 9y49z6fnfmnuork7e136q9uz1mdfbty9uthjj3cu8kuwa -qqmycfxtgxiph7nokjfq3jrbzgb4z8dd159nsfdtrgz7n fqfc31ztfgezmez6ctb6ygspy4yu66ehok7sa7cyx7rf6 -j7rb3bouzafh7gpitfnfj7nbxd951bossm3d9i76ayw5g p7fnux63a1ppfo4m6yz7bhgcrmwrs8myigyi5u6mzr44k -38tenem16c5feyiu8woghest8f33hz6ayp8a4nte3hzco o4xh3tqkseeas6zsyq18xcs8rew1qj8creyp7njpef85w -jqsudy4gb9isxoq4hyi79f1dk4x91wrdih968e95an731 wsx6mbhyez8jjngrn4jgru5f9zmyrr1wiszku938hp8bs -dpi8mofbcknu93zwxfrkpdj75s7aogoqrs8k88j4i3ttr bm15bpgohm33g3w7atif5joxxwkthxet9h6r3owgsk8r4 -njmdt6tn8x3r8rjohthwea1dorwmzmrt3cjqcpmpdtrts 3kf5rkdm833ijjmkfc4c8i1zqwit53ytmu9ytwa7m3oxh -ee7erw6o1riswg5i4j5hp7c55zyj1sun97x9s8jacqb6n r3anxhh41u5qd8aposuuuwq3q3ddkigjh7r4xs4iw4p7k -drd6hndjdtwf9a4a8kstt7noof159gfcyqpctb7ftmscq fuop8mi6su4dtnf59dh4forifamzawduzto448unezuiw -a3m93sukdanmnkby3mhx36jr8btp7uwd3a35mt8rjszfe p4qsx8w5mgjsgx9ujpbgjwuag8sc1kj5mbzn6hmobfk6w -3ucxjbo3ibt1mibshmyaqkjpnkmufkwdhk993e1u87w6a qjopxbq5ucmbjs3exgd1ewsxt9z4ihizsijg848e8hzzk -5myrk3sbgdugs7jk5wetk3u1dzcwdswcidue8qe54znxw 5cwazswtpw33dj99q844wxojj98ts4qebnibhomjf1xfw -trar3s6i7y4h8h167h1usg8jew1dz8xat637yzfsnw6ro fnqq8k4smjnmmz5b3qyzjkytw9g9saoq33dq63u4uryay -gtjpu4fxu94ftyccz8ndr3dop47qoy3dmmw61xt9se9ww smup44rautacqo44hj7igtbahfs78soipg718jrq3wfg6 -xyt5r7xfjh1orxt79s6w7zpbqxp7gs15fmtdd79fad4ss ak4sdst1fiqbpabqkjwmxzdxsug7dncexutriqg774go1 -p4tw3bmamg1mtam9qowksa8coqx1tb66eqq5erbqg9bia rc13djzp3roiz59ofy73x8ememowoeqif5ht9nccjh63r -6krant5z5zqfwyogsurh1ey65hbc5aeixi7b468of8bgq anukcusm9pzwaj9smcxd9dqwzt5gktnkwyejzmmt73oms -bo8mhidyfu7ker44pf8xth81njumanko1iscqjmoqaw6e 4am6eqzsc139n1f4zzo88eg6xi1q5p5ngwnsij7ph9rn4 -jjpmoyuq318jemcsroosy5xodenxujth8xkz5ssxwr5uo r7ec5anu74739pb47mtj1g9rtxo76nh5n9u3psnpzm8nc -mzcss897hfg3itfh3nf1759npfiq7p535w5sdtk6bnrdn a7f314xje8phfertq8gya7gbbm4qacofrc974y7oa33qr -maud3kntk4py68u3imi46jcd5aipg16cngrqicdztmn3w 6nbdsq8gfsoj7bgr3n98er85dcwk67oq9bem4hfiy6eph -xwhttb4ejipk47hu7kbua1ibbeqrrazw8cuwbk5qugzek 7r3bh9rbdu1grfk3x9jdh5c4ip91ghfph3jgykci48au6 -mhwbwkqgs8e5864gqh5oo7ie81r6nbtfgbu6juat3jryn stj4aihxr874yqiggagcagpg48kg55fo6dd4sx4q8b5wk -heakhyfiynfcce5zy1qs4qtr8d4fassxbhu6jpajt18yc dfwe6urjk4sf8kjr73736gzp8dsnt7dk45kn9kow83hzh -dqm1ggood693e3yxd8mq5rmaws6fyea6ye7umjfjzpz71 qwpjsc3ur731331unbjnty1txuspurag1ubp5sakp7661 -jirwf5rcf88xy8m8qrry88g9gucrfhnmdaugm39ks8c4g kui18s4ibidak6ibkre7uta9n1143mehw3ydgcgs5j8ze -5eq4cu4y8o78ffyyunht3bo8gmr8r9ndbubbtgbm8iihn b5ocbeu9nf75zquj39gd4gikqsumcrsxqnhqg5kfbs3ic -3sthxj6fo9htrc8zw61n3b8ykk9qt7ni6iwofdwx7ck8n ru37tybszhxhesgjdw4ud69bk5ctxm91ksbp5p5rjgmwo -dabk1excw3jnb696mtpjrb5xutddtz3w1mc9rm6fxrqiy 6xbwrufhh9wd8thhts59px6guip5ibbt4tbgmqcd1g98s -j577n1kkxmzq5sndgtii4p7qitr5hi9g1bm1hfpp3qt51 c5oepakf18rimutq16qccwmqdb35yjpgc4ecmfz66z66r -r3rskayuqf4x5uo989hhnu6ujhys7mo95tccfbxbhqeir fdxsurtm93pcwxu7cu7asyhygde1iqsn11nzbo7re3hjh -bd6s79t169dptmpq5u57tmw6tynph3mtxf719xqk8b4r1 enosy5secnayuqcr5b1ywi81mgjp81oe9bsosgrrx9y6h -re7spr8yhzbg9io163qre5x7m7h7pdxxmnd5ap7ec8y1k kzr8h4ze38n3ty5fc7sky79tt7jqe1ek6dh88g8zfz71a -1e93y5ansro8wgjgobaroidhsi3w8y5gq49hrb5ziuhwg 1aiqp37msgkais576ryec9rq1hdxihew3mw7n7up3pi44 -65ssbqe4bjchmouzo1f3r78kcg9gdqp8gej4oua8ysg56 p49z7gpqeneqqkers8a67p5i6u3x389mgezaopywa1764 -yfy85a6pt8ig5hq1ssiuc1rr7wwn6x9nuo3rrfarptzyq pt1twioqmc3ac3rrw1nr8t8b3twpsxktgbf4qyah51y7g -coa1k8upyek3mnwo9iqkmo8xwsgs9r56af5zmpw9zsonr t6bwjgr3gdju51xk88cxe6w4ma6m5f93rf43naao1gcta -9tp783f73co77fkuqptbtign1pg8oxtnkcz9rhm1cxtsc azbnkqbi39s4db5d9b7hnp3nrokmpfgfqwskpfhinpnck -fri8m3hgd5kpcpjgz8jee4wmtaj86bmjk6auf34a3iq8y 8juhpwpo7px6a7nq4aypwphgf41meo8hd7mgokj4zsqtn -hyc64qejc75zrnxyepyb16573x3xo336quc83nezyr6y1 q97jb1mffyo8ei4ggpug9rtabzeofuxiqc7d6o85jy6uy -hnrnzqa5yznmjsfkctwyunukeagxp9omdtw1sa3e4gmwr 3m793d3ungko7s1561ihd76s1p6dndkundfmxu34dokky -miejeto7arc6754q7k9isq6r6p7w5kzxfss79864wbj8k fkayf8m196tf9pm9h5tx9imnw449hqj3g9h7oniq6yxon -dq7dwxcpo9f8it44qem4rkbrofxm9zgh6htthqn78rbx4 6dm9cr3tei11nd9csngcr3e9y4px5ea7qjbfsfzh8rjt4 -k993eo5snsh4ghecssauwby3d75fizp3hfye1b4z9zusa 67ccye7h4mqody948kdmefjtuc7rnpu9azxf4esjd7wdn -dnsfkdqk8ikjaahjsyiabsyzr7mhdq47xkkchqah6sqwa dbne5gs8nkg3k46sxbpu6j3x9e8e4s1o6e3f4ix73ya1g -hkgnxxggrcpxr6k784kmojyyzpc6ks5j84a5erpprhkk4 cucjai77ejq43gjim3qqw1qu8jipnjmf66cqoqsoqtb6w -gwt3q31ggwwb5w9hftg3zk4kqod59p11u8sbz9wzrt4wk ztx65ndyxzyc31x5cje3pcsqfb7qkkc3psmg8yh6b6jy4 -t6qca3b7zx4qexfs137zs8qmp3mfrhye5e4kj9cwpi7hq wmzboge9zweoter9tai6job6qc5rgx4poe6fwy87xcr66 -yup18dhcartgidtozt1qgeync8f9f95b58kjeryuicphg xz6x3kq6p5otygkk4q86aacrge1dgk3x6u3probo98ypn -qdm7osoj4ccxrqqea1kn5rdayi1h7qsf3sj6y5af1g7mo 1z4fyyga59td1xpshspki36j8hgm5zmkcoctgubijrt1y -68frgb3kba3zx1ra13t388dezfnmgknctfaffp8pi1k16 9kkgwpzhdouzws9mtdytma5cuqh9j958gka3ba63rujsc -5mota5ki579z3jnfwgrpnpfc1ppcm3f69qqbsdy9egki4 ig5txyc89ibrkfu47msegt7jrk197hmm1wm3twgyfye5w -tfzb535ms7d191x5x98h39y5eyoz3oqyn7nheu8r4zpyr nkwk9q5n9i1xed8phzzimexnpkubmg3rftxu1p9fkqwy4 -w5iy7aik19ccfiwc3hczjj48j1fmmoo5p4pdwujhoqr5g 87cpgtbj4hweattj6iftpykozut8ekrbk7w4mehnxmptq -3ycn7zmru6y37ewwdt54njc6guk9mii695g8ghhaczn9h h88hi7hs9aq4jwwyi5wg638mojsk7gratqtp94ghp7xz4 -a85kh13h1c9n9bgk8w8ra1w4dnkqg8hzrj8u39zaoqb5y xjargodkinqfirkogckaopr6fy98sfhtradur16f8jcdh -btam6q4atwhmrnt759rthau897h15f4jsnntu5m7ysb1k fzoz6ijrdd8b1d85oejnz8mtthygnng9148sagjkbkpeq -o7wiufp95fes3xor6h87k35kqheotmkd7xhs8z8hewjo6 tfnqij6b7d6hrumnqsr4jpr53tguce7m3h3fxx5gj3q6k -aj3n7umc3bwa7kmuf4z9rhk4htgqh8q1exuzjhgb7urj1 pp66sqnakwdpbwwn95zjhoqtgfrnn4cxxqg7ffes9ki1q -tydtk65c54u694qug69kqwmxdomz56naz899xjgnccozc jsy7mfusazy3jxggixspie99mjwckb6foth9w7b8oxk14 -3u3tbokm88qr81dcf7dhbn55zjwymsq3cs6b4ozffkbiw 8nc71y7mebgn4bgay7usdwchoxikbacb3eyw97uftq6yn -6hoyq4fgbk4hfg417imkuk4utmokmmd8f3a1tbn1n6fb1 bye39jp6ck87fzgzwwjo5x7tsh945u73rjy3droczwguq -9rnuajabmgryiiuiznisc7u7bmek4r71kwkmhijzkof7h af4qofhfnhfr7noa6sjxbmxzriihxwsgidnx3a61sq7ar -wxhjmt4sqjcyx1wo8yawco6k8h8nfngd58mgdrmdexunw t8wqiuwrnghbiju8tietzjpdcuin65y69694cjf5zn6cw -n7mjtsn7p5feyqfyxq9ap7y9ohtu4x8aujc41c7b414ae 317ncs18s7eu3wjx6maiza35p4o1tpizkx1q1annoeq8k -p3od5yfz1jt7m9sebazkdgmt6mrcxwh3afe5jxxqq94c1 7h8xi91mjtzutwm3teo5gu8oe6e1pfx3z98ohnqpbupqk -4mkcj99c68tdb6uyspj65fo39ufe1icnbrsfdqfr64z9s jbmwgnem43hj4cn8319o46zouawjoyys3tmi43yyapoie -fut55fi1zhj3fpubdawatbhg6awe5e53wzxdqg3f79ndg 6t4g4yupf6ai6tihcpnkf6y78asndihs8est3ixpqbnpg -d8zkmm4y41q1u1kkjbd1i83u1ps4pq5mjry74fxw9oa9r amba1nzaic38pe3feghik8x9siuhay5mawsh1kqtd6q4w -dq4ow6fon47zgud6tu5bmx8czfca7dwtsgoeu756gjkqe p1f45e558u3hxz11esrqg6copcy7icktzi56tdrjcdq6s -xwd1xut3kt78wg9dscciwhzmic9hpzbos1pc7sieitz46 8mb8kaz1hfux6xk4hup58oyrkirjq4kaapw6gyoqc6hd4 -or7pryxhs1p61td54r1jqrkpc6cjdbb9orjehuen6636e bawxkfsch5bp7mntp8xtpjqopcg41ns5afq6oba6j8ata -7oopr1iqkfek8iqak9igim9q6nti36a7d96trec9zt1ck kir5fuirdgzaxuumbozicidu8rzmrg5r8uozy5iui7yx6 -jpjj941ddorca1bqaezrf1d6pajm8ci1zt73shxkjexrr yyus5agu74yf6y9e7pz43xa9o347tuatx3qtahqucfkm1 -fo813pph1btrwk8y7qcbty3xd9gzgbafrw6me45gbu5fq uyh4fx7gcepe3fnuzf5u1515qtd3gipgbeh17dp16ge7g -yiormqmefgue7xp9hmowkkk1h9uqu69q7kidxhxj7mfrs pnyw68ytx19bibmocwzfqdh1u7ggg6apfr9d3dc1695d1 -t5xi1m6tcbpx3fkqze8rdwtzt6j893md43794d7ury7fc x3pxjdbbcptycfwa6fxhjkdsfsbwkxinkb6pb5yrs6nbg -8znc4thr4s9ytdqsgq54ku5p8o9rq9fwf1r9yk6ec6kw4 4gujxhu714ga4tn1e4d88x9yzw3wsu89yx847y5iyouae -x7ohik18fohei1bwg1z9s9etpstf5mgeix98aud9qxgko kkfeez6gfspg5x3i5gydceeao8hot1izm5n7c44prj3pc -3tszknigf43847ffc6iid73iujnsbr571x9rwim8rozxc s5687hy9y333sbyckiyxcec3ckpseqdzcndtnmoeusryk -qq8m8ssijrexh5wkc8gred6ft83ryrdgr98xg3pxmkn6n h6rainstbf34e8rnopw3xow8c9fi64ek4696motg1kkhe -dy3ej9k6fdowh6dyw9bfpuqracbg5mx3n3zqonq7o4rzc fnygdhndcz3fr6mn9ynmxm4pztoyf87mp4zwwacpsxezr -ochb83tx1rhjocf18pjmuo6873nhs4jta9dsr3d3es9qk c11ez1j88segdqxdefbtpp6c7e1ebcwnwsaxysf551ntn -9jycwfjgq15xn7z6pn1844kxccuenr3c8imexq7a7z5pq 5p6bx8ctafd7injpfh44r8xycaacaxf4e7dy7ptq36yyo -tt7t966h4r9uubyrftqbk5xxqptf3njwphxg9q63hwdkn t898bjxwrzosormragj9gtoanckpodqnpr7zrtkrfmn6q -riksqtgecnozagmq431x7o1noqzknohoox3ramoynfta1 5c64iecj6zxeepqx6bui9yurkrftb67e56cga79xoqxks -bs7xmrogx9cza1pgag16n3yfpd9juh7mr5ohhfk9mgfpg zrwxif3hwygsprytt9fggdykdmk6p5c8dw7z7r7z6bbmq -jiku479e318xq6r1qwyiqnzu7fgss3gqd78raais4b5wc q1wuxfhhtwgyetmww9wdiqzg58pawo5rxzspxp3fswzog -43sf39pirz76xsxcd7qr7t98fdine8ftayewin6dmfgte of6mebo9jwceo7nz6eoqj9dwot37igkbx4fhfp1sij5no -dy6ee56ehcgg4acw1rdxxqncmich7j8jo33tjk1q95p16 bo4ckro7owzqr4rhprsqx5dt9uuzrrnusmitdack6cnbc -w94mffctf93f4exobwynr96a3jwjuiz88f8a5rpyf6ba1 44iqxi5minzfch1511pcatxkhx4r9ikem6hbsuq4ar5ec -on5ndr4iiani6fm6bio1bap3qxzujsqtrudrixsowex6q x5sczukrd9iw6inj1ozqo1w43ac8o1dsk5de1n4s8amb1 -4cmxqiansje8wods4xuf5gimhzm3j3h5ib8okyq3cd3aq w66hjjppsjmiy647hopsemi6mwdau7ry1514yssj4kwas -c4norqn3qeustatesgif8uiro164wkjcpagxqn9p1bgk6 1prgbej78aiehimprnxje98xpzosyw975r4tmk91i6kqe -jhnoejtnuokhcwpo1m1i895hqf3gobhhak9rd6jfki3qe xpskf7kokccojum3ghcxus4u18pfez749cqygns3meh7c -yzeq4xk5jirmsjb546ry58yhqjb3us16max1myf915hca a8xoigzuhazfubkmfpyco4eqrfs4y1m3tswesgngjd1p4 -tca5ibapedgpif8rjr4wudicks9tbhf5k4rfxjx5gt8hg yqp8cqw9twmwdieeyft61qokwq1gzh5p461a15tatqu1h -7xd4nhgjzcskt4xmjzc7bn5h8hku5oej5i559jqnq4f6e 9f5jod9q54j5z93j8kooiage4saprxku6ehtprukjp6gn -h1u3mguwgmy9n4mqzikaa3g76tfysisk78iwepj7n93x6 51agoy7t6qi5xfnx8smnniuzs1ufjc9jioyxczxm154dk -jnq3chokyg3tdb6q5xjykd4n8pfj997z3gn3x39amheyw i9thi4yybw7zq5g7hczx8yfqp5bn3frefdhb3b6gneh8k -ha1cqbscrcooruau61pdjshbtspzxajhukpr6d5m41y4s wokcar4y59snaiinijtmn8zmd3wgugj3abu5jfhk87xdh -h3awd95bjzq63ibezuz3mpwb6mxh5yfm3qio5snxaxpxn 7t1zciktdu13febr3dg8nrxyd5ffo1qc1c56s94zw1bwo -b6g3e7wtyw3d9bdau65kekk7auojihgjpodwhm78tf1fe 1a34aeic878cexpc1dc1mzwg9brmtmjkonuyuein73b3n -xgj7ui8d5nfemgsttqatycxxx1z4nproi7m1b8tj5ddww 5jqkqydz3ihmep4drp3knbw9t73n7581371nojzdy3ywq -ted461xi3mxt6gs8zgx6ttik8tdpcg55r1cffpu9ytk7y dijccw6ffssumu73t9cbhs5e3yiwhfm6st1m7nwxtzb84 -m5s9s4es9igbmh7gwqsnfr6ytrxxdmrrqh6946i5tsi4w 8igijzwqtcux4yiqt6iad9ipm71ras6ur6hrzmseud3y6 -s779p4jjeek4euwezysasw6oxbnqomyixy4a39w56b4dn 59nhzfbcs88oft691kkn8ikgynkerxt7pepekoxr7skr6 -1ebgsk4ktr8kkr8rybhwtnqbj8a8p9bt9mfns4irmn1j4 gn6ffe74jzjmx5gcxaqfb67j8px1uhhoe8c5q8ygyufds -5gu1arrbjesi65444sitkgq5jg9wgk5wsr3aiz5ns8f8g kq1npqyiew4fumrrbuotr94c8zi4y57g4g3t5kerj8rmc -ydsycffj9u74n1hdahep41fkjee3damxn3uh5juz68831 aocd1mju4w7thqx7o1nqu1paf3pec37k4fnmz7aw7afrq -y1zrfhgzbwtkf9837cap86bdqpbr6zskakfwuhii6sq5o 7rp57bhgcp13wygxjxxnh7fui9o8r46cno4p9kecu9pd1 -icug9wtr5tubi41qc77spocw7mq45dxmbo8k8pkbafbs6 3mdcr9ueerkq7euhwg1e49o4t8o96ga7ypn1181caouca -ouwt4x8ientq9679wqpa5b4pq5gscjzfahr3fxk5f9a84 qf51bw8iy3occ4y1fwpgxmc7eghfrjwfjo1zjib5oob1k -exat6t3dahcs5jgjp8ypskic8iio6uji4qkb6qyarmgha hsbii8eiof53fu8bmwnfzcyyq5ewwnayoxngcbbw4p3xy -4hwmep7ukrh43sbse1pa4ejqjnjo565gjpwmp44skmf6h 6o4d6ppdmfwcgp5tbuk3nui6sa1im8pzxa9x1hs3bh9z6 -n8i5fq6hu3fkszhtep5g67j86c78f6ynr16wqjuxebtnw fn9hth9wu31uyiesf8qz7j71oezzqpca4axj51t4q71jh -zgbs9jhhbwbc9kp5escip4p11jn98uxrxx45d5tcfirs6 bfdm7dmzo9pkwb7j7e9wo73pj5ctmaxai7k6f5g6fjxsk -3ce1f9y1h4ticx419iipw4m91eqomh74emp54jrmih8mh rgjymnejmmfu3hjawwmgdkgxzbsb7zd7n8qno4hz53314 -4fmdfacxqg4ua5nkhsy4k38639mzqe8ar9top4p79eofr wh3dkjpgcnw9sgmw1zt6wzoy89muoack1rounsqxbzid4 -ew89amuzf5mead33kpgdr6ux7w63p31hatkg3o3tm7byw yu7b5fkzigcdzk9akrpgomo5s4xf3qctk3cjqipgyj3w1 -amitqkyne66abfk6w86mc95uozgt4jbabgcizygcjfijn c66cbxgpff3w3t5471nyq15h3hhhuhuoixjf8dwsng1gq -bbtdtwz74xu39hp97z7jxucano6ms6ne4q7kfbuxkfaa1 hu6kacc91zgztsh8c735nrmhnrur1spcrq3kzbowppmsh -dfhg9o144wnggfka7u6pijg4b6369u9ocnks9yn16hwhq 46eerayzo9fnr9q1fw86irfot8i43nnpsxzxr4tmuter1 -5ppgpet91qiqqrkpbh63r8iohbr3warto9moorhwcujuk asffmcditsacmqbeuhok3xqmjkn4ohu8bo59xfshun5rg -qz65d9ouqyj7hxodz85b5nsgx7jddi91t9dr4ypxue3nk gxfkajd4fkwzrc5nd9itwqcjc94zbepj51yc7shns9gyc -aqrqmfhr1omccb34zmnyxrzjk6pa7zsnzgozg55bsw14o 89fpjkytffowhz7hri1fweu31injfsrd8uwz5m7a8rkwo -qtfaa91wknirxejqh7s5ffsfrw9uzhsrysdodi753jbg6 r7c5z7w1g5mh75cbnqq3xazh3ksxuixemwo5n9skuw5ny -4uncpqdcw11tbzyr6szq8im1bpotd4ytip9gxwdbiab7s idospfmr5gkbnucf97z3u5gh57wc5ba5rq98rd9wt4rfn -to3wqasnh4wtdfb4uff7px9omggq4yea8bw38jpg1jz14 qekn4jm78yyqxbspngp673sbm91n9y341xntnahq9o7pe -btf5kjbf3de1s7mkag7d9w6upxuba5ofzgi3xnfxnbx1c 7qb65hic79d14nf4ojycgbf9f5s3wcssrih3cikyjdeir -zbj8bwdn7c1ad9nk8cn73m6trkowmay6ky3byumh1cydq fmma5zhi8dkeubn4tnxb9ega98a39pywdt1kweexqkdqa -i71ktxbupiyahp14kdwuut4my666gzpsi816gmp3teije hicz3ygwr7mi31mddq8hjehkg3mg8kknwzt5t76pusgr1 -mnha9kpw8bymufmhw4syewpswfzx97gz331rc5tx6fkp1 rdcx187ehjtdws7u5cge6jumxx7doqqqbrap9ptxyigeq -8ch7kzqsp99tn861h7xafbtafqzh53ykt8e5ob55ggofs d3h7fpz5ccpopbcxj6d9ewgou4nj9dhb6dk43xtt84c34 -6bmi15h4ipfur9fo8mjdfaqj314ftnpz4xhwupu1wpsik 4g7mu15goihmyxw946khqh6gp7dhcksuadrbqpsnogwng -9qcdosiw98dij3ojcyz3ym7fd353of7zd4nhoec6ccqxy uxj69491j8nutxttbpy1kdhe3wbu4o9un1fuzwrk5f3yh -j9fqbc648fnnaxi5s3w6qf86uxnik96pys3sjcqwhkqcg wk6t83xw1996uxwzbdh6pmp7hnaq343kspym51hrwcebo -zyyosyio51mhzbkhorhwrxnqgu7gs1cppi1y5beub6r91 5phkpdngmnffrmraq8637wrkme4oabik3wjpgyjsizobr -awufptc865mhxobbpxamz85sibc4fakacxp3cem4aiwrq feoomg516t834tqjxtj5ab78ak7h3kksescoieb6kwoia -nxrf6jzj4te4r9dndi38kyzakdddw4xtaakogkfo5sez4 zkr5adyp9y5qaxk6fmcd6jimuuwuupm6eew9wwy996atc -gb8y9kyku89ayopfjdaux8tx6jjsd8cgd6zg3xzp4ni74 m747hr4ru75jqkquatfy5xyc3w6pqfn9fyioshdmbpewh -6bdo5cxoxfk71mjqfhmqg754w79k1t8psnxmdjsdwybye aix1iwtu7nweidzied5wok1udoq51x91p6aieje3fz9oc -xujfgzjrpws7crw8shs4k9ioq8t53fdh9mn5fr73jowtn athpik4im6tsdbjt37s87gkeauyc7oj9rbroxbzyio6f4 -nco9am7qbszdi5unmnae8db8jostpzjwhoqeox7pu53xy dbx4xjny83zjnx8ziky9tmksguwydc6iw9o8sbc9fkxya -zwbttsrkfpu3bpabgb4s68yu15ztaddq1bi8jjrkaqh1e nux1hykubqy6q3isxc5iwgyohdpz4nyibk7gro6997z16 -ztmqrcwr8ptc3ufkerwy3drr4fowdyu7qsttcpi438zrh wgk11b3hhsgc6oripd7o615arrg1p9eba4mzj3opynzsk -u8mneujaqa548sqnssjqfx4ggqypbwf1938gh1tgmcn3e gjzp7o6ffpg1prskbst56my73iyfxu4x1ruor6pamh66n -jnzduetgb7zmpesu34ri339isup8wfudeazhbyr4943fo sjz8qtygiq9c9s7mmekmzie7gzuyaipinsb7kqe76s3qr -f19tacsndhu9icfbrxr1u6rnc7ct61q5f9e3kw9jg4jne pe38apz3946ag35u8uatcjpfq4e49bdd3oxyr1drigecn -rbzhm8cuohnrw5w4du654z5e3s43qth3zcbpumk3735ka drboiwfgbrp7ph3nwa3yewrd6988x16cw988wny76zjuh -sxp3wzkgyr3outa5gg4rbtn5k1kkrt57nes3cmextnzgg cyabwzz7966i38ujxy7z9rjc3csc9411i6xzje3bwt6m1 -bpi1nokjizgmy9no1pjxo39n1yfw6k1akewjjm6h7iern kgio71sf9xaqtns59gzwoxc5oi99j9n3tngg8q5zm3uor -ehp9k8td9anur58cg3ddg6ycibz77xuqmzabuz1115rgk pmfermazz1wpqf63hbtrbnycnwfiz398y3836tn3maid6 -qw5p1kjy1pxfnbfomxnm5ph4p56m3x3creaj1mkuedw6a cm4f4f6ergcwxp7xd7ogztk9qg3dk7dj1o5urngjtswsy -uwbzeg4748repxdqzretnmyjfyh61imrxm4h78km73afq 6gdkwjx3wy6acwhqrypbxp5nfzr93p7faeo1bibkgzi96 -xtkoe4fbfzqbt1thd8w4jw6cfxoibwmwczwg4fqducyfy edxgngk5uuazw1gqm5sn8o4h35y97s5ykxd7nk8rdo3xy -orxgoqxji9uyruj3b9p8h7mjjat47xdye3rutcsqhf43g b3wabseseg7r9zykgze1xitdy5er97tntaqj9tu16hz1h -gcbbqkkopjhsymx1tkouqybpsccfmxs81fka5zctomth6 6mm8b6z7n6cc8iou1y7czaqe65ikj8sjztbqkd1hxcfun -4n4j7as4yboahn3ffeb9eq4u5k3pgm1mp91fei9ph6zme to7tns5z7kaifhkibw3ahpg3xr8tcpz683xs438ypednc -odxr5bch67qgskusaujqusy3s3q5bxgh11haj5xpk4af6 yzmbkjhk7u3nfaw87mg14o74htfj937kyixotsyqf6i9o -jomx76dmg1gs41ggc74pweny46fcy4j95yfpqt4wjgs8y ewbwpqo63cji1i7fzzdij6rhxz5gp73ubp6nsu6zngrx6 -uxtptd8k856x1cncjmypfc8xqz97kn4xchyj7nf7x7x9c 3wea6dpccdej53irkmfmhu5onjjnczbt53iftsqdf3qxc -j4qb46rag7eks7rgq8ra9gb89zpis4iu5wdiz838txopg qhr8iip9jtgiugmsf7czq1hyee6tf4tg77pbpctre3c14 -g48prptie3zcy8quy1ayiyx4opsbnh6aqwu7kidw3cao1 fe8ecsdmtfzf5bsqws6m69d63gskjagxnweb6fd71agms -wkweedw8qo6a6tx99iei4i184kmi7ogytryc9wpwcthah 97zyyn5a36rice1dxzg3wd3j6f3c71ew3w4a99ewfnxqs -kkp9z1zq5ztpjph634756yt8b41496wxoqndydr49cago oxhfi5dggjbigj3reji9364mfdkj5jrnzrxnsgxgofajq -dan11muwr4gc3k1xn6n6g6j77nrjzbndbsgcc9kuctm9w ie3r91c85eyipnm4kg8n515of7u5d8kpqqxm9snoqtoxk -87hrwzhdx9egdwugrwo89oidwt5q9kpu3t6czes16yucq duhqcfe13wa7mmi6w39oqss31bjb56ixn6uhm9ted7mdq -f9ufzgttxykbw5makcyqg58i9w43jnukq687shu611wpc 9fn9z9wa1s74ro7yq4p63yoesjsghqqj8z6zzgtaqbmb1 -wjefg8ohhj93fx7b3fb8juiwic8y79t6cw338r5p7616o h1yy5hwo3o9895d96we9fnrgia18ewtzmua4g7qdjbyig -waq6cxoyo3e1bc5y7drnkhr9zxmm319mn77qbnn3s7tkh sp9uz36jszgd1q9r18id63mejh95k4cfahzdy4wcdfeig -bexxag8uwdik9czuk3td3ef9xq7t7qpg93zenduez59h6 h8t9txu8spfxgnr79gopyregcicn5mwzmintyyjyqwy8s -7thinw37yb4ptetfsbbgnupkbp769b6htzwt1d5eeq86a i4qyyxdjq7tapbzue6x3tq9nr9d73htup43wyj4nagf4g -b8phd7gdzr3ed39qhjkzuhpphp445irq54d39b4qfx994 woausg5qcrtttym7qwpbjxzyif7tspn147sht7ueit8sc -oxskwffh4xeeyykjq4168arjfgr98qxgtiyyp4nfujh4q 91ksqhc9j7kuyjhs97wohtkmogdg1pye8jm16oxrr3bz1 -3h4bwmunfahpd4f17j983fa8b5akwcmfjk9q6cyd87uth 3ppzccyy9tci5c7x3gctzrb4us7ckkxrxiniiw9aqgd4r -efa9dysd19t3i9tcg1xckbmaxkqqi7ugbpd8ihbedknrs t7emdfae4tm8q7hxiadk7b4khunes1f4topfpn5ouq1dk -nr5zndjjy6a55tao3886n7qn77ndbg8iirp53gzsr5qb1 7jximx1m89s558fmc4ib4ub8imqpmjss6dky6sqmbegac -7b9mgy8n33f7bfgqzfz5yeo876cmxuexgy93bm4sjpfs6 d9amfo1fc9imkr7b747jw91ayre3q86g11azcaq9hkqtc -3xenbw6ojfkrm7dct867fradkcxs3b6pmkfpwykj8xpxy 87q63oa6u4enkixiwy955pcyk7js5u3ur75964yjoxnyq -cxd1kexkafjuukhi9mirdui89z1re99e3at41tgzhsejr j8rdmwogchg5a7cptckspbo8g3qu84ynb4yoafudqork4 -iahd8xiiio48rrrkqxptyeujbztmykmnmq3saygiguum1 d38cu77y8bghwcej45tnkh861boabqo8fkizhs1ggatkg -x8pdxokn471p5c87seexxoddmu6dmphhz4up1id97n5ur o3erhkwz3paa47rp91z4fo9ozgcwtouz6pkszkw9pr7bn -1ydsptc8y6n1w41ezqfx8jurhxi6tz85tkjkb46tzf3tc ne7rtfdyisptaftmuu914xasw6mha8mzm5etiyczykun6 -z7znswji4tyg9ex5qrjtzsn3cxmznzyamg88dkb19mauo 4tyn7tregfby95j6k8dz5hfxf7ntkygofn9hesyzp8hds -jejifc7c44z6ukmofsg38p6ysef54bgw91fwigwfw37do bzsz1s9iwg3jrrbwtq1z6qnkata7ecuu8ng47ox9wbptw -gj1jqdhmn6bitiiua6xo8tc3gudexpcnmx38y7wi4rpea j3kgxrcfycghbw7tg1jnqt49kx43urucifwpatfaeuca1 -xx19ocsquh1dskc8gqxue4c6hqruxhpc3iuzwhp7w77ww 8ppnsgupz4scb7xoc1th1kacpn7rg6u5ubuo4e17qofae -f6kodjfsc48mwz59e4dcpkiodcn76foi89rc1pubfxy7w hrhts7c5mrsgon8tosei5edohmmk3eec9ks4694s1ijcg -7jf6u18uia54bjin5ag9p767oqc43sq6sborxxc46jurc fsg5ry9ji4zo5phrtfn35jbmeqpym95u4j1i3wp7d9jgg -fxt59jdpdqk5knro3xed1s8mgw81qzfhdew9jskpcacy6 pwafoz1awtdarmpo4hk67e9xm585k9pjcff67noe6dq86 -yami31j59x71tu96zw5we1fzg69zfmokp6qxf7weru16a pk38wjbjdxuunrzq473rfjooujx4nkjeqafnhg5a9rnuw -tqpwt7i4r56r97k64jzmzegmnqrf9a5engkhb8rk5tkye xegrjztmeipy9qad4t4wk5k7bhx7ajrtpc9pa85rnmg1q -3sx34zi1qw959e1kasbfizudh45oag8wzss61dfahnhaa e9shw9du3m5so5skbpsuur6ik4njzgsse1q5rqqdcb5xr -tjcan9tpe4m1pombtb48eeryf8n51sit3ococ35bexdkq sn17f3ix79ir6nxy9kmc4id9m7taosub5e1zseg3ps37r -1cuk9bmq9qprq4taz67z3wmc5n7fpg165oobfo75zz7kc dbf356si9m8oib37qr59ydzk1qnx17mu8cdkq6f5s99kk -7mbqamih7iyz3ah8di84bi5f6kgwehitmuayt55jk8e7n xst7rw83es1ofbkj33sqtsnquese949moptdu4snbaiyo -h54s6hazi4gqps5zbzswpgjabahcpirfmhsjhzwx5tqto fxsknrdetb4nu6cbyqn8xojebh33aofyd8hk7yq5uphp4 -4he18fb4pw5618ymb9usb48oj8kinaikmwwr63gkudae6 zoz3d9qhoqmygtwc3y1yp4uwgwze6583njz4dwbtsei7c -yq9w631buqfp36mioameqm3q8gnn4fupane3bg93kdu44 5tbhp3jbqqzcnduadb9kro75tpnwoy7ccafgzsm7cafah -gcwawc65pxc1nftniptd6gc8dyhjjf9h8szs8yzxjazwq fzif4zmengx6p79zxbfj8psgy45ypjr6n3ousdzdmz146 -fjbh11odsd5j1zsa9ifi8k75yj5rm3xyum7wfc15fxyi1 yki5c5rur6eqc5zm3cwwuqifq46rho5aj7p41i9irx4wg -yqsebwkj55usn7yso8euf3ai7q5ir6xhza5g8x9tia18n 3bcz8rg735aogi7qzz78wy76ab6eeog38bft8zbsza3xg -43qs1qry7uszqynoxysaz9zf5451kge89bzuo5my4tzie caqrr3ndfatm5fmtehubbqq5xuwnddtz9jzqbaa5kutmh -r53czmk3jpr4w5phc5jw9tq5t8aum7aahs4kpa6hczj6r 8dotewo9r77zmgdugs67zptoxyjbqd7wb8m3o8kkqeqrk -a73kh5o8636myzicq4ut6hzsurrn4h76ad3b1gh7e4q3y x7nbzkrq8web9qmqdk3orehmb4a38xn79oqzuteuqbay1 -piy4dx4rkxcoey535ruxifomogtn39fy9qq4tmg1fbskq nys7t5844ucufommo4nt44kqb6yugqkhyn5i3j3z6z6hk -p7yjcof8ygmbxx43hcpzezahwkgywtffxrdkknuk138q6 9knpgofdapjsfosbyxsbqduku311dnyp4ruba9pjgq1ng -6fegko5a4p46kpmfu6h1zoau5rysippsacsz4pzwxwnsc puai3ts8mun4a9ixow5tqk83om5brwry1pwy51wgs1yna -gqcedhmgyz3km6kizgdchz9zsz47kde5zr64q7tfieh31 suzqpupdsicjffgpoi6og5cmoowi8o49cd5b8qrffh1fk -zkykzezt33w8tnkhesikopormauahfb45xepywxssz31o jq1isgi9ed41cor3djsrcsqsd3fq9jdbqny8x6bs13cfh -huz3jkyqsi33kiowr567i8a65zt3nm7mok5z5k4ean6rr siubgzfbybd71zz5p4fe9jtf34k8u1jmfqa9msc7uxn7w -cn637pgzsy6nua48trzcgpzrzdfydoeadu1kawnkqkpjk wuxfaenuhxxab981eyuhctxdh4noxzoanqiw1fcwugpwn -tufa1mnik1hqbkwpzwmxapb8onu3iwh4idiia19tomx5h qen9ziesu9t7u8h5168hnuxmn1ctrgs3tgtzj95rw3wfy -wcwsufnomdpqxp4ko4xysaatr76p9th6sswkwj1wtkc66 jtwmgdmfjoo9gkz984ow95rhsfeo9p6hf7hmd8rxm5xw4 -tq6mntn9ppt9wzkxhpikngqtzzmajo7bkbr5nqmyb8roy 6qwk166457gzx4fdzqfxhhq71rhed5mb87e5mu3pzfdzg -o6ffjr8rpo9au3u39kcrecf8i38pbyfk1wj3j4fgdq1jo 8fdc3hozxabyjp4wpqjkonox3cqxppkzfq7q41c1inddn -s7i9ykyxkwcec5ua563gj74cwuncb6yeyi1srr4wxm85n 7f7gepzm7nbgg1xqjuytyxe3i17eywjc1ntiohka3mr8e -96srodhfb4pr8xrsy95r6nkttsx86yexrdkrsn3bc3snh spj6atz3qsc9wcydu4wk36mhh94yupreaueud4p5b4cbs -xzfd88jadd8kg1gytnr6h3rdshs7snqn8z4rr8cwm33xg f9yhhn9exi11i8q33fi7zkkx4zsuqjapakjd15c1m7fwy -gn8h45of61jhbnwm6t16gpnh6pf9cwswaym7pzd4gkdhe b1q5ztscoqtbjcni5wjraykj1g7py6g69w7gd7i6395i1 -tyf35ezwh3wfto9ik1f55bap87t1rmepmwrr91z9zd711 m3ie8dy5qmf3wnj7iamjbh5er17wbdp96b8g1r33wfzzn -cd978txcaz49gsyqiag6qusoywsxzzo44sje384qojsfr j6ooberxk1m3oywcsna8rm7zspwdqkaijc44k9p875itn -wq4nbsxopqiahynm115optisp74uh834k3a67rt3trwt6 gsd88ttqau6h37pdrw884h8tw1wab9mnobr6q5kbzf3rc -51ww6rwk769egr937ofa3w5pspyefsdr5zfsoxbz38xr6 faghg1jpxdhx4jy3kp4f3em4dwbpq6b59dixk15uuj5og -mwb9xe1ez4u4gdq1utce6u4z95esk9zj3rsy71qpdqr4q 5yiofekqf6rwu8kip6i6gme9yoirjnp59hp89etu7nk4r -syaeekkchzruupafcjd8h47ct1c54uoe8rxaw9ojy4xga t3tk8bb7nrui5ymsmb6hcg1h8x7qzdjrfn1oqu6hxmudk -5ngc3dkjtwuy3m4x6jjn54zy1dw4npcgwd9iih53fbbgg nfizh1n4jq4gk1tqdnnu39fseg1era5hw14qmae89tnjq -337xasxmuynstyq6js7rw7bi8n6k1du6rkxirtjd4iw1y 5dkn4tktthyoniqt7stonqmb1xeeynfnq48itdy77jofh -6x4rchnsomfgtbfs8aqs1wciw8hipxoq9pqo7iq5jqouo 85jginir73cgrbp7j8hkwfs8bmf3mx4oum6gip77py8ir -skra3cf1e1hnw4igiue3u9hptrx4ib6sdd6j58jzjows4 j7eybs3dnc53kihsmta7i4qx4cjoreko8qn3cuo8jnfzg -gxxo9rrf9ezpi799k94n8e97qwoyutx4k356tjpfod6ge r4tj3tukepcrojrqrbwpfq5rj617dby3iuowm6rz3kwx1 -mx4jgtx4nt5zzkpq57dc4kcz7iupqst9wzmbmpr7o83mn w1dbfemgm6sa14wz9563jop5bnayj9carakwgnqzqj4aa -tcjzu6863endbnexesfe51zfduxw694ajx1kmqjjo3i6y rfr56otq1cqhd76yype3eixm9ufbaahowyeq488bfj7ya -3y9xret8ms8ruqaw4o5pai37m6fowy17mhheiexuff65r hwau9kubz8kucqnj5tqkf8nbgaytrnn81zzbjs8g6r9ae -k6j553w1umd17z4x7xmsf59y3mhm3y5x7ypd3bsy3fc9h xsu43fkm88gp8dinz69fh498yjdqtme8ib1hm3jj9mkue -1zuouxa3je1mq3cza117ejb78qgaz5bp8k3t4t45chucg 1rp1d3c5fxojt38tk7kcgwjhe1fk7ut5rak6a449q717a -hgh1tuszb77hwh1i7iockjnr8qo6qdyxddy479yu4nmp1 rgz3e6zaadbq6gy4xy9h861koa5db76q9rx5ymx5ff4xs -w1ojpy9zkokcfbso5koyzj5qqwbhsk8biud85br81bxfn 1pt5dwtrb6gtpmb51d3uhb5fqph75g5ih77rzwq3otghs -fncp1ocfbqyogp1yfc939bha4e1gqa4pms6sfz8jkzhhy gamyio81uzqu3nuejg9s45ftc1qu1gg64wo7am9m84j7n -ibeo9zrhg1fnz8rabkrrtjyookawza4eb9e3b9xwiw4wr 79dk73ruiix8s5jct5thy51gu1dwa33pathmjfg7bpx5q -zmak3e65f45hpscjgus1ye7him5qubsucob49sxakxr3n zfo7goi4yqaxk83kwhw7pnco7j7bqh8xuhxz8cpt9sujw -ms4so51mx51mr667g4fmwh99is3y6szj96ptsi1rzpywc ch6doya833k7ijazhdue1tt5ei9uom4da8ze5x1rz6dhk -mt1ju3bdcroyk7owsk7nooitrdryem8se8c6ctyorgtyr j1c6855pt9anqishxbt48e917htoo3c71xdzy93o6uh9c -3ofcxwn5hzi451ar7tezc1o71rspn3hw9ytseofqkc8gc k6fna38aemymgukiajhgu6yq76rqhtrbnnhe86j6ggawo -ottcf7wwpuc3nsrbdpa987nsmznbjzdy1zs6f6m9iqnwa 56f4kznsti9y7nexf8de5kbeaa9not8funkgntmb79qe4 -ousod6waqo5cdicpmchmn5rxy9i6ehuis757ctr9dgo5n yqnj43iutejk1zxhf4ep8cutyp9ohapci1ht9d4u4h8ks -a4ynp9s7fmyap3q9j86yy1r7napskrpyeifsq4f397mwy nez4jfsy1dfhrukmh5mbtq3roset3e3obu39mymmwy73a -j5whb9hh6yqhg4ks6h4kzf6oo38arkyep5rwwa66q1cr4 ywqjt6dcsbecnau8zw53iq1hqd3q5ya3x863acjkj1wrr -rye5k46ngcsimpy91q46hboch3h6azwyxh476osrdtnpo 84w14n4ikuqcmomz15mwzpg5g4dhxpqkcg7cnpegkk3iq -utnr7k9pzn5wpf8kk3eurzwkqa33p3c98mdre5r8zmqqw e1kmorndkff98dc6xeg1wu3sbnk8h3o74qhuobfnxurqy -7i74dpt81ohktok7f4zbcrui3ha45n5qpjbupks9ku446 x383hbkot7pow7jjrwntgsfcu7dunaoarjxh19c8a9czn -iembcjyrnfi1nj9oqf1r3nkrht1ouuxsmiy67xxz57bqq 7obka5gtup5tmt34uiyw6s6ocq1ycn1sbhiqqnomcpius -3x4egmpkegzjd71mykdargt5jj6yfk9wd6wodpoo1kosr oghfqaqiyccspx31jjea8fwei9b9n9dxizmne413u4ins -3hufah4bqro74pknz8jrob3f47awxpr4hrygqr9c4juhk qikpxqd9rgjzrc57or3ynaimn3rayruxskkh6eq8spqza -1f5t3sppcku6jm3t6z4cheuuii9citptni85zfhb8mo4y w95y1hi7ke8kykm7kg7eybfmtcnm18tsc8urwnno5nqba -okjojg5x1q9yaq6fgd588x3sm5313wp7b9b38dzfuuf4h i14fchfykqttan1q48rt3skzoyzb48nzrahm1yjeqguuw -m1xqcugw1tscc69t9w4naujy15x5cx69auzmuswehykn1 bghxudf4fqhdojaqtyrp9xqztffy6zcz3u1eygnxoot6k -nx4w6jnoso6f5zfs549naq5rz41g7d6599rguhwuk4djg ixfnyaupqzxo4gkk3sg565p81uttrzwczkn49ubatujsn -9rzjoph48t9qfau18gfrubxez6mrdqrzyauzwzj4xw3bc fs1s9igychujtd7bz1bfspuzer8uq1s68unzcnr3wmwse -e9cqdrqdhgwzq654e9x1g5bngoedikqgqhtxhpeaqoy4s dmzdyj55z11au8tbqrfoqwzndaj14g69z7ocpb3x33xpy -qnm7ewsoeapdzqeh4wup1y1zcpth7pih9wss8kbgocgkw 8uxskcjtbgs7498qj1jkbx6xkfbb9cbc6usek5powbffs -sbct46mrt99d1694ibr9es6t7djaebewynzstitd9o68k mtcztnufcyi9kma5877wo5hbmoupqdpyktgzqutmdsmoc -3mbcxt7kobsb5axwbp6tnabxaas6bo4wapobhff7xix5e 59pssxzsexnzmp7hwjphjp5xsgmoybsa1uef9s44wyj54 -87u83kannc987idtcr44ndgbcx418ctt5jci7jhegt6eo btrnec3jfacx8q5jwdbcbdoo1fqnjh78js1fi871ed91e -rp4b4wxixfbdodxtf47snugjkb7utrtpy6iqcu9of4rfg ryqkege6kfh3a3tgz5zfzb6cda68qefb7hcdyw1qxotkg -wirdnhn71cnqonc9hbyd4saz1hhgtnsoii7kxto353xj4 qokx3re9omtzquna9sfax7ay4zotjro5zgz8ebof895or -j6q7yokpgnxphrcr7wts1yr1buee6coggfynzjw4djfhq atbofihrzibfz8febb5u5jq8g6w9mtnokcakg8h3dotwo -p9qj3idk647kwod1sezyfsrzgj48tkn9uwd3wus5dxc9y c61tdudx7jishyu47r1gszaje8cg4a8pc93ntfhtwry8c -zobmrdrmtncro6xsre8usapieutz54mu1gfbk8rswqg9e 97ohj3cxurmnn7e8csfq4n968qxhfssfp557qbbudsqbw -befiwg74tmt1q9thh7yp4kbmk1im8mue5qihp665zkyu4 brngxyj8mf86yzmwnr9yw5ie3m8syqkwc1z14tgxpmxxe -9ofzr9ch3n57m46datsyjcitcz8oxj7qciifr7daaeaah w77nw3j4chqbgaau8wiy7qexzdfi7ph1o8ztp9thierre -y53rej7ggnoou1fq3p98kayixbz1biax5kddu8d6pg6cq 56fwcywy1gs8q7tf5w94ggo9aiir65ng7f4wxuka431qr -zis4z7u8txttns6eep5oicn4qmcejej9f1faeqdp9q31o 6bc8tux36ohkjdukohixk6g8gjf8jaay98b7m3oa5j6sa -t3j8io6u49seg89jfi3mhiukiywzzkgdwg5hrfqtpb8yk f75a59gux9tbh16zkeq3pr6mwzdyng5b6p7bpm9a4gw4c -nff4niqfwmd5zm4ptox1by6i7o3cadh4dbqdr6jqqswfh 1nnkjhesn1bdsfocp9azti5soser8kz5dxqu183gnfuac -x8srjtnotga6gwbyg579arf8p176bmrrghdo8fopod1rn 1oqgs7zwzhrnufyonshukt839pg8bsso7kyqp3uon8wr4 -8z65pc8knjre79wo8g7ruuqxm7hawjgijtb3dqaat41eq w11tmugmoj6f7jtmr6g1ijfs6fidirecmxmqok5uczixc -8e611ifr6u9o3kmf84ineyk7a96ykte6fs7pgmnn958qw kq3o1dmjrcqjdjthwh85jj3j48dpxc6jee46w93y6cbae -w34sfue1xqbar6xwzox44woimk41z8hipnhc7yt6ppms6 peurckuiyzgtntwdq8rauibb9cnn8k4wnfa5obifffcwo -r1511wzjmjfz5bqyj97y8m98j1xbysp5puwqphubn66y6 fj43t4m5ofookf6fr5s7r76wbgns3ek88fnufqd7augy6 -uhradwx5pywzen5k5u985r54geh1rb31quadbnt9jz9t6 p979h1cfhanpxmwn3fn9msican5cigiy9do665qu8ajq1 -97i993ej9b4jywt9c1myf79da1f9ut5pwm6jfkch8ywgg 8hj9zcpox41dcympu4fnjb8fouacekto54i5f5bfecid4 -snmhsard8ozkzowx3pwegpyidn1sictfxgbhcdznuok41 pr9y7mi5yd5wx1h9ioqncga893pdebzwi5ueqm6nhs6dy -ytdiopeoeruidc9qmsuftum43ry1sro4gi57n11wtx6y1 xb3sus9xu31aizey4dc5h6ofifm348ugrowfm6mprx3tn -kupi6frf4ijreggqakw5huyj8ofg1adi35cg5ipmpajos xegznhex75xwkrxqknbijjhczommc3gsmeyzrfn75fxuo -gpcuu5cs4hhez6hi4jpgotscyeicqxcpegdx97oaxz1on apmdy36h8w3jf9jh3nkp3mr5s74beebdqzzh769oboi6n -5asftry1ur5tytnrgn19mdp7oqp84f6g3hweb5h4yqc86 816dmpanibyr84s8urumz1y7qo99qqs1ypqkfe6zhef8g -8izmr8xbiqs3ri7jmat5wo71hzxkfmxc47szgok54ksnr 8p1xod5zh5fidsxqmu6dtjcxsjow9k99bur8cgsqudeg6 -x3rm6y1wp3ibbqqza9eh1thyacz4nh8p3kdjumsgf4c7s miswnkmo55z6wn5doqck8hb651md51s4y5oehy6xxrm36 -5egpc9ohk1ts3r9w7epcc9jqd7femtprhtj87gfq1dsxe jo8j3utigpbtb3q5ze9ttek5nawu17azsa6awwmpef1zh -x317hk9faskr99snc9gun6gqnfbb7usrsftc7dj1nz71e 71zkykrffr95qkaxckdrgegqysnce9wjxxnkz84sertcn -bnkwnr7r17goioso8mmc3gkje6gxj3u5sbfs9yy1knfdw 6xjnaw3yqydb14zu458mkq979gpgh3eeep8mnsrr1nukr -pgw8wwbaauiarndrec11px613dpwct86mrc41w9prs6fk 1jd7ou6kskupg1sw96nmg91fefmkhhy3pyhyq18qf4en4 -5zhdrxr6ea1m3rzfys1qjhjiz4493d9npbnths5wbh79o warespajppk383cwrz6cccwxizzkcpkox7p8a5n7awzyo -q9urebax8oqr46huxxab474y7snhdcnduyh1xqc93zwhy stno6axi55zz6941do96rro9m8hnwf3yt1ongnpftrqiw -porauscegw93pect5374pe3kyey6om8jc4mijtrujsx8n swbbsbupegikrtgdmays5os3auso7pons6nprxknfssjn -rnff88st6nhxpsq1kqiqsy3wg5fh47ngjut5tnzpysxoy exrpjz7oub1bcdr7wmqtw773rynop6j4epk5wen59kfon -qou8sefsity7yhyw6xmb3ygspqg6fu74gsao4wcfan4fn do7oxtkjuteywth33c3simxdyk3hcwe6ktiw9q71fbcbr -j3c88ms3mgc35ou1pqhua6wi7f8jhbmftqus4zhzwgx74 9fewymx6cjej8tenhn7ozqwjk9mdbban344ys6umuroq6 -49555psf5qe59zix1jzp3nfew399fpbzenbf6f1hxkxqa uswazzhx4ymwpqysgjie1bapwpwenejeubtzstg8mg96w -8gi7nobxowspnuhkwx4xmr6ucccbfts9qc48wcpgtcixh x18oxjkacsatxbpghn8pq3kgcjyzexowase7dtndfc58g -hnbobd7ntrwxsa4ta7fs6347hexi4ki9hdehcf6ggb6so bhyz18iep3k6mfq45wzsq57rjzfqzzq1dotsf4r1kkaz1 -hyzh17p35ff47zaphmn4n8awq3tqxbgeu9sax4npsbkkc acd64wzxnozn6ypxpwnj5qspimsrj7nr7s1obd17mcbqa -uc6w6y8jmz1ubsambzg6rq5h5cgz4znw54iyz5gbyunug tws1camx7rop77y4m4p48zh97bqk73cfiioehg7tm4s1q -ris7j4gx4n8ea11tm3as4nn5nk1fwkbecrj41jppgp5gw ibiwe67kxbjcsf8mcr1n81meotyqjqih6bcu9xkgffgnq -5abpaawt3pktaqw39wcjgts1m1bsrizc9as41prqh4h5s y6f4y1qzh9ooduy17u3chdrq6odigbn8ihmfx7p9pj34q -pdcqotz1iin1kw91uaorycyz54t9dxws7udxmygb34gxe g9jhi3r8ef4o9rdcpockdbabfgrn4wbgqyma7hnkcpefw -dtmy9rctbeua7nsz9yo454mzq8eudspgf5txxq3p4sihk gfdw9e5axhcpjdn13y1np4yyaupq999myhfy5rhyknuzy -g6tw36758rx7w3ps6jjw7oerwwc9qxm8qq3nwzpx6w87h sds9mg3p3igupdph49jkiag3yt6q1mqmo9c51bqbpz5sq -mqppxyhfk86jiz816ndtts7gptqre7pznyzf1kxpn5c6o 88otr7kcehpw1g4rzoagwzhz368ike9epidk9yebesmkc -ocu36786z34czaxokaen9fi8shxoqddtujqn6tt4966xk 4imo6g1yd49pj13uacgrmqifz3wq1bfbrcfpeba69icwy -4dazro9q3nhmamecifwjmo4o9ocdsmkeajne8c1kis7fk skygid9zsyj6f49wy8pgepm3n5wmnh35pug9c118uyh1n -pcfyew64mt5ykjfo1mdgo9qgkd6oo6t8oubp9bwymo79w ka6giznyxoigmni1z8nibcsb1bp4p68tk9epw65m94ore -gjzqh13uc5798ozhrxdkknmkjd484bsihn8u7g54c7u94 ar3ej4zwob1dhnh9cfyns7t39xgyuk3jop8ninmrfykko -nmo7g7pfsfbb3jxjmknnok3fd9c8qde4pxfzfqeo3f1g1 5s3r3jdsbzigk8decsz3aftiznbjnreoi9d9e1mczfdth -dwx6f78kjkit5rnuo1ypwsh7zpx967oyojqha4ekc8ery 36aukmb1573zedt9oewuzyjrjfbinriqqer514tjw6urs -fuyxkrngz96najgtx3otn5z7z7fmya7rh9p6w7wajr9eq j6sbhnp748aebi4k1ifwxjqbiurwk7odeh3ethbgm8uwa -88i6gmwo7c5t53m85hojwng4mtaacutr6rccoaagw4dhh my4ii47ftutzuu3w68s5rf7sedpu46sqo1u393cxjcqe4 -r1akp4m5tno17gz3pjs8zthig9gd774p116mj4twb8xca t7fkqxw17ijoxr58qgzjunz9jfmzuj6m8d5jhr6uj36zc -saswgth1w6nnqfgenhckdsqrwpt9pc8qui6ru94mytik4 a5n8a1cwor6mtsg3nxfzhpi4m4xtjx49wrh6eskt1bs1g -d9k4ebywhgq397itsrx5b8emze7dfnay86uc34fc8wufw 8oib37nifq79q5iqhzpc4n3makwcu4dqaxq5tqb37okwc -stx7kgjimz4dftzqeuc7fy39yex9tipaxsp8djrnxc6pa mrrabsz89qa4nrtkjuspidexoyzyocjs5r95m7afpj4po -fbpuzatmh5yg95dwyherbfop4dwmbrpdrzqmgdsrcxcdr z81qbzyimh3q8kct8qoeds1pu4x5ryiakir6jytjomwjw -au44wwbxsy6wfufcwya1rwikfneat53ymboc6bsut8nb6 tcjec8bwq6eqhkw7ekzkz1n7ssz7yz1occyfemmbmsgae -umqradxpqtofjsu7ikbek97y6bc8ht3nr76xczdhr6wdc ppe3dxymay5ya9a1yh7fdf1b5um8fpfzqur3xfow1sigo -ouc6xyjwb89xfat6ctc7spr59bt1kxwfkppjpeb5pp46o sehdsirz16ouy9k9mqe9f7b5jcep51pfknjaayaotcfkq -udnbxdr9ejqru8rb44pku4k89bi7zxffw43qj3yzz3gny kx6srgz8uqkpzx353zi7xft1xsuuhku5n1nfnkm87i954 -yp1mmakfxb5ksasrkhqzzj8okgtcreu4sgjkqfqzc4g5h pbqz7xt5a81ee7bekrhri9yqcf3hq449g1igbx3k17bfn -kt8ke37dxs6xqibq69aq13jugrxr58k167une19um9dso tzbr14ufchpgqox7zwc431x38edg36rix6uzby33nizdy -wr89uezfcdzomiw71d1eibaus3b7gjubas3ims8y7bugk 79jg3gknnzty77c7bnceseoguaubn8xag9hxmxrp58fba -8c3dd8395eu3u6zimtk85tiq6ao3fqw5uf79gqa4py33a ch7w6p4nwmcicmfynz9rb7in7kxq13h3dsxeuj57654d4 -1paguy855jsr5j3rukcy3beaqupi5ewk84drhima7pkmy iga33o8axcfnttkhkc56qph1impw6uuyz7izeucqfn71o -ouf8qj99wwqjqezr8ayff4pz8xqaup1j3xcwpu9qu1pj4 m1rxhstjbjtfztr9xb7tbz1c6h15krtjyom1drnmdxasw -1ipi7i1shb53opx6m7n8g3c4pp6x9545copungenkyxnk cibqr7jtrz1jehuqu35gu749c6u8b5wyzbdg9p5q8u74g -rcm51s94amdi55thhqbiqwbwjkxd4wish9tc9tt9sxe8g xcyfgg41uhwmhb4brup71n8py13cwqsrszi9ug17787o4 -xohjh6e59imd1imikz5zfx3qbdeuetnwmsdiypi5f1cqa hhyxnkzz1kymaxgnoibwxuhshcrds5fpoboe69yzt8p1e -1ouz6gb3f9nzuicy7eezid31r6a6w788i7xa8w5rjth7o 944a6ti87gittqe513tmzhjpbbrijrtscdxcwkxs5adna -ybh6jnj4d8aqwxj87hnbrepda6uiwoaarj6ad48dssahe niwqxagmg39kcoh15kxcx79319u95op4x7mjzxj9934j6 -zdzedbpwoj874x3ijedurboo4rbjh9xkc1kqgbthwqf4e f5kjpjuzhs7tegxdi47zud6b319kakdo91no55icbajj1 -4n59ytt9jig63iaigsqykpe5i4xygsh688wnmzaxyxi7h y16bsnsqqg544a594ehppuc9678zyxg7oqyy9i771bce1 -ier89cqtpcgcrtnks4edh9cqfz78eupfro9d67t6aizbg xgj1z9c4ssekhwm9djni4yh9dn1fcr6m6hqenuzy6rd5k -zs6ux6iwxzsa36mwsnhrmsyjpyeaiupz63nn9xp41mm54 45zn4oyw6odhh5sc5deszck3ttg1sqxrfazb8yffnxryg -57ep3cqc4ex5ybzddinpciu3z1uu6uye44wwregfre9zy nx9y6trktu3ctt17h9dfttwysznhdetpahcuyj1f67h6a -59kru3ri99yuxu7dpy4r7i7fmnitznsi6sy18itxecf4o h1wu1qwdt1kju5kjdazru8wdhircs7iywncayrtunt13k -nga3nks6w1qgaswydnb4q9iecnttf3933auysts7u4d1o qar5pmcsxu81s3sdymmkxc4y1795eecg5zkcskuf7ow8w -qh1y7uugkkkyhu66ohq1rirujhb9gpuxn1i6j8d3nibta 7gcjw4pkmghm4pky76y7qw5r6fifhq7d95cga7oo7hbnh -n1o6d6ufktxq18ouhedg4k6fxchbm15qw49tx6iff93o4 cq9qggomxxhjooxzucc59b63n5j4i13aiphakoj1bkmj1 -hsco4pq9mnwhax4w59zpayxz83dtuys4x6tmyby9n4bnk encb3miyjs4jday9ww551t8o6rogwrn6s3148f5oenfkk -gf939qsjiei77cuyms5ohjqk5ydmtiqrt1r8fjke3hotr x8pi7su6djs4ategkmu6fu16qcqmrjomnxfuyjnoo1wpe -s93uikws7qc6kidgs46s1gnfkt3h943td3onr8sziqckh ffjdopdzd1kspdfygx76nugp1ubbe8r5c9f1ok8r5ucy6 -te3k86xmafnepifyybixuuq3pbae4gt3kr6razkc8uz4c dcwthrfawb8u4q4ptuidtxas7eow6oz7rpagyz1qrfgnr -75atfgdd13ia67yzdc7coiu17cji4zq5nn7kwd4hqpg7a nk57fyfdcoczjqzeep7o9z15rsidp3gcs4gghidsuhf66 -nyrqf8cxjh9fkfz6gr71bkdjxw176d43onzatgkb5ohdn tfpr3gikffqx4as6ohx1k9z5sjdet1m4tjxt7yha7qb8g -g79isuohb6xbnrsu6gis5nqg8pbj39hbpd9axzmairaq1 qib8kx4smwfhwyp56f5bfkmr8sgnj7x34rx3hz6pqyg4a -xq174tqr8k8pw4zd5i6rtfxxza7ttfa91mbat7ryac9tw x4cckbg9nbeinc3wsjcqe1hncjyzqhsk5o5efkzt6jpmg -xgzsu6fc3cka8isqibbttukk9kk6sxn53bxreswzwcjzk 1yzmeh4j5utqppz3yh1o6uqy6rn5an71bxk1wrfgdfasr -tmpyrerzqier8z45e3m34xgiobm6tezumqutzbsgds5ra jqk6pxek7sxgye4rcqutacfttbi6zskm8rubtwrt8khkk -zma3hxougek4n5inwywf4top8zpeogibtnpjxyscdbqg1 fdynbxochh1michj5xigrhzu3tn9ped7byn76g1haty16 -98bqr4o6dgnzsbejmjqxia97n3hyxcc9x5prro3inwu7g b36ejdu9tgg4j1i6qgsyrtb8yecc57jyq1tjuz5jz4dbh -eiw3qukwqtxpp13ktfmpddptbophhbn5htbh1bo4xijyq f8grzkzyde3bognyzgiwjjniwra5oco7gj83d1dj8upjc -eom77dbhinh918p9wp7on4jqrwaoh6q138fjqfmrws96w g5j57bg9ctzsw9kaqwmcwibadn718hfehy6kk97dci5cy -b7uy78n3csbghqpo3kyeitubofrqq44uqp8553zbapi64 m8io9ppnjf3ekisj5yt1bprf6bjiu7hkbugjimxwrk3i4 -c9y35aef9yhaxaimurbthphsyimokcm9qnw81bz649eaw gbnm8h7yhiwcfa3sbsw1yhofx3ed94q6xtitbwydgdqus -kqfphctmkuu5wxqds5tewe9pgmm5s446j4y7jhdq5thsn fac4h9c8ckumxs7mo7ptrjwdgmcfqrrk8zoh4rgramu7c -fpz3tkabkc9i1xeaam6wt3qjb9s1o5i4xzhnjng1pr7hq t57yec37wzg5rpmkeuweoqtr41zm6j5cpqu5noq4x5yur -wbne5c7uq7q8ktk4t38ddshpczp1s4oiizms56e5rpwie 5mo94jfnbew1orihgb7jkbc1m53pdij8xwozea1pry1ck -w81up9jemsu3ubmw1nkmiuryupe3ez4zr4s6414tb46yk xfhff4saccw5a8txnx46y3phe9fdhhob1oj7gj1g6butk -hn3nnj6okd4uyrfhsdz61qeiyp1men6m7enkcn3udnjuk ua5uhg6k4jup9j1b7593rcswekqsmy9dyz66q8gcqba1y -eo5cczxmgk1kxp13i9jia3oh8bpapgic59dqij6gskd7s zy35d4k8o4a4wjkjoe5h64t93xpurz8guchss3xcx6rin -e684qazbumwiunmb6yq3h75hzeetqqfj53bqyoc5nxmhc zmona7qdei3m65k5rnptrajacey9fgrcj5w3ibdhp5na1 -htjdz479kg8cgfno3z7xm4wujugoku9jf88m1qcaazmss bcz4eyr3mgpec3x8wegid9s78wfps95k5h9fu6igdde3g -cn59mc36w3mznftai4z8xutse9fi89kz7yugwx1tnc7je feoymdzm3mbutyf74umwxh98azyk1egus7peywkgbf374 -ttqjh71h1sma4o31zjri4pnnydrroyzi56uifhr8n5wtc 1a7gms4t6y7zcbra99hfg8d9ibjwwz9n3rj9ycymu665o -opoqtodoh7ud6sxgqd513q9d5xunk1cjbqjb4j5zqgoze y5fjyuq7akgmxn91se5hndmh1gp57g4xu5rrozbo58nqe -th1iqsfgdmhswx6hwirrrnx1w9jgojnxm43d8n17krnna dnn7qnpfpp8tnk5krodrhaq4x1aobxqguimgsbhcb5oa1 -nadpofg144dc6h9o1smhjnneahrp6ef11jiwksdpcj9my k755417f7wr5hdgyaksaxjqp1z7azfcyfy7wy8zgmi1kn -kgxi6cn694uty5haretze3czgonuru3o83hcpxxdf6ryy 3zwd8zyxi8hymyhrsrui859yqxjeakk4ucmj3bbrsokq4 -emfrpi69oaj34cwjgnx58zw7t3ubna797ozzzkhbe5dm1 cxnnqhohidxrtnqabwxfekh4bjt6kgyz18x98awfuwdus -yxgsucwamrkc1zrc3dkr6qojdm7yaase4ddrsigdafc7c ymbtgcmx57r9p6iu57368o974rpu414dtrk16acnq7nkw -ad8hy5w79785nqak8h5goep3cztd7g3r338uuwxgxdknr n9cpsm7krjeeua5d57icmknuaqh5nwwa7dg66o4oo5oye -a8mn5wrkkccmfzaxz5sj4kph6wyzfaarr3djwohgraqya pczafmqfrfkyi5nazoey8qcaj66ggw3bu74ob67ohb91c -h5z4ao1mu8mqpetf55m695rdtchzx16w14gudnwgfbugk cpm7f8xmccmcomxxwzx7sdnk98ebjmy5bgcak8b6drsih -uw6b4en37jzomkty7pbux3gnnx4hjagcor13r8ap4pghh r46h8m9s9nqadwhz3xh9mrr7wwc6i1pyrcefpkrjy5bwh -i7ecqrfk5btgqjsz6njyaufxymy5z6qh9xoacqp458o5o 8xjgrai3r3jmgfeqbhfh1gx6a8fdy9c9q6wkcc16m74qo -h3i5xdm8hb8cbqck89exui5gi63dzz59jsk8g861nigka dt86qk46uaurbknktfuh98ggjsg7wtz5agxzpzbd36d4a -muadfsq5hkcsr7fxomfj9839ma1zyicjtqym31hoonbd4 empepdj4sees9fkwzgkhtf81igw5foxz99zxtbnapr8sw -g8je5yiznjzc1pa5ghspe7d1sds6mdk1muzfu53f5pfzq ds9mopqxfmwrpr739hmpn6xeo93sc3mhxpz767izyah36 -9zjhmketeqmzjoa4sx74iy3xsy6msdtnt36mumwb48nyr e779iryhc9ikbdudi8x4ym3zt4kho3nr3efmewq1fz1qy -gid34sbbmg8z5dsebieiky9oqcn4i4y9fqexrsfdwgwu6 zix6ny6cqb7bkrznmixfqtc8ko1goq4zk7dd8o4wn7kck -85c7krqfh8yoa9b8atbjebmcg88aofgtyo697x65id41h cxgt59qxmr6oinsqsj153tueozqcnnnj8ymy9pfwjjb31 -ocj4tma5h3qhkhjwub8uk5sg7xwxihn7yriyzhwnwd65o 7c7okktckectzzyam9phhk54mhsq8w7u799dn67o4nw3a -eacdxfhuhe8xigodncd6hhsqa7fr6x4znkw5ppu87dax6 g65f5gan6cbroq7pwt78miupf8q4z6bg4mse8xsufj4oc -cntj3mnxtcadn7bfgy4a1nqguyg7pa3xkw8iw11yh8gqa 1hmd6dsd8ou5bu8q7hacz1ismdqem5e7tg3rrfmmxuzhs -7cjcdps6msbqbmoe688m8aa4sefg1ope55dmy9oz9khuc bnmfwkoftcoufb5znjzq5jm84eix7p9wmge589tj9sy8y -1t4pibfgo7qs6njh64mcaxs4ct1uj6m8dr1sbdeg464en s7cxzuzh9xf8dxpr1kbwfaf5zffu6gupxreqjpt9h98zy -zfsm9g1np1dhytroyf6asxep7nwy3bd5e61dweh91yccr pjk8xjo5hx9iin4gprm9a6mbhuzb6ho88bktbeqnj4wun -f1f7x8ahw4oh9gybnribtq3rif63d6e17sbtboemyisqq p7hugb85efzsqmsiionphpzsjc4wourm3dxqo7nf8fi3n -iedtu5yx8ef8deccwmjtmpjecffttr71iejdku9f86nmy 74g9wjkdqxd4548ostappfagupr13gpsxuzf5om5nizen -tc7imdnexhokp69t6htn5df35jy46ki9cgjhpriqfttsh wks7kegs8w95e6crb3zkxubajywa63616wc1ugje36zj4 -39erpprp6umj4kwgndeoumbq434wtgo83z8reopcubghe uzb5dap19fuok4e9ehezr68hhb1d9s6c9e55pun7uquig -pmuq6kimo5brd3simsq9iekis4dcram9kz1frrnuwh7ka upqpnbm9f3r7fodk6t1kczitkjrqyts1cymskafahqyqc -6d8z7n3inuw6ecjgofq86zbqd4n84ohnj7ap5paesbms4 8yotjx3z8fekmhi8yxyoa6pxy5wmw3jxz7qgokhjb4jps -fs8o9tgg5j36fk9xbnio5u39t5f4p3krmi1o9qzq6u5tk 4oh61io1pcjbafinkkxh5wr9s1y3uyzc81bisqo51qchn -w8s46ybq958hpro9fti51qkz3bkk4zyu7fiyqfk6dasnk c765rwu4id643ynmj3xrw7c7hhch3ahwxzxizarjezct4 -z7xr3poyicbfqzrrq3eira4ikkpw6zttori7azex1dyrr 5kd7dysowhqybcn5h6zpte8obd6r3ekef1arsxhwnxpkc -szezs7nq6y9mwbdhjwng9n7mey5zpb9fz9fb1ghmh6ymq x69tycpu6tmzoo6fqtgjynxbtehbp9cfjcm3kdgmikdpa -aqombxawkohciidpbjuigu97bt1zki5qo8c4geetqgdq6 qpezcxykzw36mfwc7jdatie9i97bxyfsirtm9mgcsfqrh -tc8xaqghs9ah1ko7pmo9p4ugsz97dgr99qerq3otr9cgy pnbso4kiu7xdjhue39iqgzajmaxj7my5qpn68nqb5q84r -rxrocrbprbyogcqfb98766ro751a7jmkecs18ceoxeda1 1g4gug69sadx48mq3jqhdy7rtuy5473qf7d7g3yz14nts -seqnwx9d6g85ea5c3eqioromrfkzeqk9ozhi95sktk1or 9czuhpznww7ceah3rwqq98p8wpdshmn7uqhoriu6pxmyc -gd7khwhjbq6zt47uab53ct17q6kcggnbjrotsq57q5kgg aoakoegc9xt58j538rskkfszkndmer7wtprmpi1q71adn -ezh19pj1aw1mg8h4grgybz7zgppbu5ncn1a1fdtiuowh6 itwpaoq7ii1msona6i5ph3qgo1pps6dn6jubdqz4ekh7w -sx16ykyaw13s5pdcjhkorfg44cz5ufy6h63owqcuusqmn stpdbe9djkuh66d7tj9nbwhhjoo7kxp1rtduqf4jrdupy -h4yjxspfom4r4znhm8w75jra9zxgzzu5dg17y1hxnfpw1 mp743tj6rnrz7rq6bbrnxc67qqyz3cwpjeym96x9pdsug -z5do79knf3bf1bjjt6rqpwe7ut3snyht867zg8we6csz4 wbnsj57k8pqp7jr8j67ihbgis3tji1zjwbjoyy67jzr64 -9nfycp69tjj6thu75aeyzen94i9568h9o7rr61mrn9bn1 ygn83otu1x1wb93fwzeyrf616uce9aa1hbkfeenoutpsr -7mzirjkgigpf1t8qwpes9psx6qb918ibdcagkj4fssmds zckcf9xen9hwg6c4n7yzq5uiuxwjyj554tywf1kowna9s -mcrt8sng1ixx1ggai8xogpiqt5hrq84g9f7ar8knd1zdk b335wq3ki9yi7sjax78fk1p1mde3ofbeyumitrpc6iq3s -mkgp7ngmxwseca16xhh4ns7d1q4uuwmxrupr18s53giag 4zajwei6oxd4wccfstas9dsnczhxgqrxhqt77fj8qx5sy -m9m4nkbmfzm3ruxxesx53dodsqq4hfgcfn1ge9hy4u6y1 z9gmf1t1jzkfyt8y6b89j6tu3f5jbr8c5fss177ma5y1q -af6z9eanknun7kk7zfiw51nop97mbm8wkbwx38f5yefs1 s6w94fugyp67gbue1qb1uft7o9hyu95hzxjnuym693tbs -rtis5fgra5urdfdij6bw7anwkrthg39tigk86cp9aa441 4x98ymwztnetrq94qeeyr5ozf1n511jt67awzdwt9h6tg -pqisrquop4cj7d8jttmq3n6kapa8zge954thbkf7iez9g 6ndnf4kohh8fneek5b51pcmj9sgifuwbh4pra18enoipc -tsdp351x6u3wqz3177f368gbkchhqutjo8cdf1abbq9gy biqmmkty3uwyywx3x8zuei597oxayi5wi88rb87yudg8h -fbdap4xshpjb7r35ar4s1muiejoknhs8hsw76oj615hsy 59fei6njmwyiein3oa563x5wh976ftw1wuonb5cyft3sg -u39hpi5we7mhescg4seym5mof6jmy4aozuamgo9xdw38y qak68jpb9d4ankzp6ymsnf6wipsdosfq9q6xmko6ihrco -dp8fgpfdbemghr6fo7r5ickgh54hhe7u3qhkp7tsx6fzy 4zrybd6gfam1n3u7k7q6bz3wi76ujt7ir3zqnk148c3xo -z6oeh3abznj3xboxok4nm9axbdo6atmtak4khy1gefyyk f7m4f61ym89fmp8j6ebwmqx9y9em6b4ida4pdzczhfspy -ck7oi9aza9gmkds933fbdn1rpmwe6dcen7hm8ixf7fz7o d3ibep9zc7zwy8jwju9cni5w7w7t5bfdfs8py5dzu99kg -kb5tz43q5bzk6q6gybj3pj4pyneg5hwm8krg7fo8qd1fc bdgzmnqfdppyghjakx4aqqpkizi8muasxj3561eqwd84g -ngpcibe6k61gs41cmmrdbajjj9fa8oiqgk3hc8xpfrntc e9x9bs79xf8xjaumqanonwwi8qnysbbh4ip1ouk4ksa3r -k7shbi45zt8w9qi69opjfhxuo5b18in1e4ygpbjhirmu4 mip9h38i3yrtdcrqp5hhycg7ywujz3uh755wgpqi5ctsw -z7g9ou9eaweo8kcqtgw3ekwhdob6wwpetn6j3npxw5tjn kpc65a7tquyki4b6j7eprdc7h3zs8aynfgozrungur9t4 -f67s7553ofiiozydoeukyp5ixe3f86dbeqe1ii5iiq3jn e94gzbu9z8md3eugwm9xji8qu7ojyis5onsefkb3kxa9g -swzdqsxcxphkk6rw366mk5kckt99hxd86euofmnezz8dq aepw39yzg6sh6e8jgq6z78rcbfpui53hpzck47f7qnhow -kkpaxew5k1e9qk8tckyfojgfsk8r4mxciiq9a9fdyi6t4 8oc69hsmc81jmgiwptfuf3mdipssm4paoxx8e7jyiwfcy -bx5cw3pmw7r155zpbk3gxjdgdk8es4zofy4w7pn5fy4go pqe1jy75ckxmodss7nxchwu7fujf46rtz7hq99z9dmqx1 -6erz98x3u5rbbt8cbjdshirsc51igyz1wqc8pn7ke9ic4 kxo6atxckeiimhjurrz33i1j8xz1n15yi4wctx6itp5pn -k8nn7hc7ki1o7mjwmadrihdydffnkm1x9eq15i6umrub1 zycrmkhewtz9hjc9mhyow6p89kqrmqxw56rjsxhfja6h4 -f9agitjk96ffebkpj1jg89s466eofgkok1mmts1mxkfz6 gafwdogwiwatakc1opo7cmhxf7bwathsmjqfo99kbngg6 -ycdnp3hn88bidyp13e3anq5njo17q7itfzc8g75yqbq7y 9tap54d85mbauetgp8ddppguhjfhcgar5cmnyget94du1 From f7de8ddaba86b695bc13a82b01a3e2e6d2e96676 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Sun, 5 Feb 2023 09:33:36 +0000 Subject: [PATCH 12/16] Fix linter issues --- truthsayer/src/external-import/DataCentreImporter.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index c9d4855a..fad8a369 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -17,7 +17,9 @@ const Title = styled.div` margin-bottom: 10px; ` export function NotImplementedMessage() { - return To store data locally please enable local mode in Settings + return ( + To store data locally please enable local mode in Settings + ) } async function downloadUserDataFromMazedBackend( From db8ad4aaeb7d90c8a6b2485610733eb43c762b92 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Tue, 7 Feb 2023 09:12:04 +0000 Subject: [PATCH 13/16] Init --- .../src/background/search/similarity.ts | 2 +- .../src/background/suggestAssociations.ts | 2 +- archaeologist/src/omnibox/omnibox.ts | 2 +- archaeologist/src/storage_api_browser_ext.ts | 54 +++++++++++++------ elementary/src/grid/SearchGrid.tsx | 5 +- smuggler-api/src/api_datacenter.ts | 2 +- smuggler-api/src/storage_api.ts | 2 +- smuggler-api/src/storage_api_msg_proxy.ts | 21 +++++--- t | 21 ++++++++ truthsayer/src/export/DownloadAsFile.tsx | 4 +- 10 files changed, 83 insertions(+), 32 deletions(-) create mode 100644 t diff --git a/archaeologist/src/background/search/similarity.ts b/archaeologist/src/background/search/similarity.ts index bfd42ec7..0183dbcf 100644 --- a/archaeologist/src/background/search/similarity.ts +++ b/archaeologist/src/background/search/similarity.ts @@ -179,7 +179,7 @@ export function addNode(node: TNode): void { } export async function register(storage: StorageApi) { - const iter = storage.node.iterate() + const iter = await storage.node.iterate() while (true) { const node = await iter.next() if (node) { diff --git a/archaeologist/src/background/suggestAssociations.ts b/archaeologist/src/background/suggestAssociations.ts index 8c9682ab..dfe39c68 100644 --- a/archaeologist/src/background/suggestAssociations.ts +++ b/archaeologist/src/background/suggestAssociations.ts @@ -7,7 +7,7 @@ export async function suggestAssociations( limit?: number ): Promise { const beagle = Beagle.fromString(phrase) - const iter = storage.node.iterate() + const iter = await storage.node.iterate() const suggested: TNode[] = [] limit = limit ?? 8 // FIXME(akindyakov): This is a dirty hack to limit time of search by limiting diff --git a/archaeologist/src/omnibox/omnibox.ts b/archaeologist/src/omnibox/omnibox.ts index 4226abb6..f87e9877 100644 --- a/archaeologist/src/omnibox/omnibox.ts +++ b/archaeologist/src/omnibox/omnibox.ts @@ -51,7 +51,7 @@ const lookUpAndSuggestFor = lodash.debounce( suggest: (suggestResults: browser.Omnibox.SuggestResult[]) => void ): Promise => { const beagle = Beagle.fromString(text) - const iter = storage.node.iterate() + const iter = await storage.node.iterate() const suggestions: browser.Omnibox.SuggestResult[] = [] for ( let node = await iter.next(); diff --git a/archaeologist/src/storage_api_browser_ext.ts b/archaeologist/src/storage_api_browser_ext.ts index b58d1566..a727444f 100644 --- a/archaeologist/src/storage_api_browser_ext.ts +++ b/archaeologist/src/storage_api_browser_ext.ts @@ -93,8 +93,23 @@ type GenericLav = { } } +/** + * Structure describes a node in minimalistic maner to build a full list of all + * nodes out of it. All node fields mentioned here are immutable throughout of + * a node life. + */ +type NodeTag = { + // A unique node identifier, there is no more than one item in the list with + // the same nid. + nid: Nid + + // The rest of the fields are added here for quick sorting purposes. + + // Node creation date, exact copy of the `created_at` fild of the `TNode`. + created_at: unixtime.Type +} type AllNidsYek = GenericYek<'all-nids', undefined> -type AllNidsLav = GenericLav<'all-nids', Nid[]> +type AllNidsLav = GenericLav<'all-nids', NodeTag[]> type NidToNodeYek = GenericYek<'nid->node', Nid> type NidToNodeLav = GenericLav< @@ -438,7 +453,12 @@ async function createNode( let records: YekLav[] = [ await store.prepareAppend( { yek: { kind: 'all-nids', key: undefined } }, - { lav: { kind: 'all-nids', value: [node.nid] } } + { + lav: { + kind: 'all-nids', + value: [{ nid: node.nid, created_at: node.created_at }], + }, + } ), { yek: { yek: { kind: 'nid->node', key: node.nid } }, @@ -714,27 +734,26 @@ async function bulkDeleteNodes( class Iterator implements INodeIterator { private store: YekLavStore - private nids: Promise + private nids: Nid[] private index: number - constructor(store: YekLavStore) { + constructor(store: YekLavStore, nids: Nid[]) { this.store = store this.index = 0 + this.nids = nids + } - const yek: AllNidsYek = { - yek: { kind: 'all-nids', key: undefined }, - } - this.nids = store - .get(yek) - .then((lav: AllNidsLav | undefined) => lav?.lav.value ?? []) + static async create(store: YekLavStore): Promise { + const nids = await getAllNids(store, {}) + return new Iterator(store, nids) } async next(): Promise { - const nids = await this.nids + const nids = this.nids if (this.index >= nids.length) { return null } - const nid: Nid = nids[nids.length - this.index - 1] + const nid: Nid = nids[0] const yek: NidToNodeYek = { yek: { kind: 'nid->node', key: nid } } const lav: NidToNodeLav | undefined = await this.store.get(yek) if (lav == null) { @@ -748,7 +767,7 @@ class Iterator implements INodeIterator { } abort(): void { this.index = 0 - this.nids = Promise.resolve([]) + this.nids = [] } } @@ -912,8 +931,11 @@ export async function getAllNids( if (lav == null) { return [] } - const value: Nid[] = lav.lav.value - return value.reverse() + const tags = lav?.lav.value ?? [] + // Sort tags by creation date, latest first + tags.sort((a, b) => b.created_at - a.created_at) + const nids = tags.map((t) => t.nid) + return nids } export function makeBrowserExtStorageApi( @@ -938,7 +960,7 @@ export function makeBrowserExtStorageApi( getAllNids: (args: NodeGetAllNidsArgs) => getAllNids(store, args), update: (args: NodeUpdateArgs) => updateNode(store, args), create: (args: NodeCreateArgs) => createNode(store, args, account), - iterate: () => new Iterator(store), + iterate: () => Iterator.create(store), delete: (args: NodeDeleteArgs) => deleteNode(store, args), bulkDelete: (args: NodeBulkDeleteArgs) => bulkDeleteNodes(store, args), batch: { diff --git a/elementary/src/grid/SearchGrid.tsx b/elementary/src/grid/SearchGrid.tsx index 1b08524a..7912aee2 100644 --- a/elementary/src/grid/SearchGrid.tsx +++ b/elementary/src/grid/SearchGrid.tsx @@ -1,6 +1,7 @@ /** @jsxImportSource @emotion/react */ import React, { useEffect, useRef, useState } from 'react' +import { useAsyncEffect } from 'use-async-effect' import styled from '@emotion/styled' @@ -73,9 +74,9 @@ export const SearchGrid = ({ iter: INodeIterator beagle: Beagle } | null>(null) - useEffect(() => { + useAsyncEffect(async () => { setUpSearch({ - iter: storage.node.iterate(), + iter: await storage.node.iterate(), beagle: Beagle.fromString(q || undefined), }) }, [q]) diff --git a/smuggler-api/src/api_datacenter.ts b/smuggler-api/src/api_datacenter.ts index 4c5c6af3..f1374c78 100644 --- a/smuggler-api/src/api_datacenter.ts +++ b/smuggler-api/src/api_datacenter.ts @@ -805,7 +805,7 @@ export function makeDatacenterStorageApi(): StorageApi { }, update: updateNode, create: createNode, - iterate: () => _getNodesSliceIter({}), + iterate: async () => _getNodesSliceIter({}), delete: deleteNode, bulkDelete: bulkDeleteNodes, batch: { diff --git a/smuggler-api/src/storage_api.ts b/smuggler-api/src/storage_api.ts index 2a49da15..854897b9 100644 --- a/smuggler-api/src/storage_api.ts +++ b/smuggler-api/src/storage_api.ts @@ -126,7 +126,7 @@ export type StorageApi = { args: NodeCreateArgs, signal?: AbortSignal ) => Promise - iterate: () => INodeIterator + iterate: () => Promise delete: (args: NodeDeleteArgs, signal?: AbortSignal) => Promise bulkDelete: ( args: NodeBulkDeleteArgs, diff --git a/smuggler-api/src/storage_api_msg_proxy.ts b/smuggler-api/src/storage_api_msg_proxy.ts index 568e3dc3..f5031d79 100644 --- a/smuggler-api/src/storage_api_msg_proxy.ts +++ b/smuggler-api/src/storage_api_msg_proxy.ts @@ -122,16 +122,23 @@ export type ForwardToRealImpl = ( ) => Promise class MsgProxyNodeIterator implements INodeIterator { - private nids: Promise + private nids: Nid[] private index: number private forward: ( payload: StorageApiMsgPayload ) => Promise - constructor(forward: ForwardToRealImpl) { + constructor(forward: ForwardToRealImpl, nids: Nid[]) { this.forward = forward + this.nids = nids + this.index = 0 + } + + static async create( + forward: ForwardToRealImpl + ): Promise { const apiName = 'node.getAllNids' - this.nids = this.forward({ apiName, args: {} }).then( + const nids = await forward({ apiName, args: {} }).then( (value: StorageApiMsgReturnValue) => { if (apiName !== value.apiName) { throw mismatchError(apiName, value.apiName) @@ -140,11 +147,11 @@ class MsgProxyNodeIterator implements INodeIterator { return ret } ) - this.index = 0 + return new MsgProxyNodeIterator(forward, nids) } async next(): Promise { - const nids = await this.nids + const nids = this.nids if (this.index >= nids.length) { return null } @@ -162,7 +169,7 @@ class MsgProxyNodeIterator implements INodeIterator { } abort(): void { this.index = 0 - this.nids = Promise.resolve([]) + this.nids = [] } } @@ -204,7 +211,7 @@ export function makeMsgProxyStorageApi(forward: ForwardToRealImpl): StorageApi { const ret: NewNodeResponse = resp.ret return ret }, - iterate: () => new MsgProxyNodeIterator(forward), + iterate: () => MsgProxyNodeIterator.create(forward), delete: async (args: NodeDeleteArgs) => { const apiName = 'node.delete' const resp = await forward({ apiName, args }) diff --git a/t b/t new file mode 100644 index 00000000..f60d2e5e --- /dev/null +++ b/t @@ -0,0 +1,21 @@ +ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/suggestAssociations.ts +16:28-32 +[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/suggestAssociations.ts(16,29) + TS2339: Property 'next' does not exist on type 'Promise'. + +ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/search/similarity.ts +./src/background/search/similarity.ts 184:28-32 +[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/search/similarity.ts(184,29) + TS2339: Property 'next' does not exist on type 'Promise'. + @ ./src/background.ts 16:0-61 185:32-60 367:44-72 717:8-27 + +ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts +./src/omnibox/omnibox.ts 57:28-32 +[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts(57,29) + TS2339: Property 'next' does not exist on type 'Promise'. + @ ./src/background.ts 10:0-45 714:8-24 + +ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts +./src/omnibox/omnibox.ts 59:24-28 +[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts(59,25) + diff --git a/truthsayer/src/export/DownloadAsFile.tsx b/truthsayer/src/export/DownloadAsFile.tsx index f014882f..b6f51b5a 100644 --- a/truthsayer/src/export/DownloadAsFile.tsx +++ b/truthsayer/src/export/DownloadAsFile.tsx @@ -46,7 +46,7 @@ export function DownloadAsFile({ className }: { className?: string }) { const [processingStatus, setProcessingStatus] = useState(false) const saveAsPlainText = useCallback(async () => { setProcessingStatus(true) - const iter = ctx.storage.node.iterate() + const iter = await ctx.storage.node.iterate() const chunks: string[] = [] while (true) { const node = await iter.next() @@ -105,7 +105,7 @@ export function DownloadAsFile({ className }: { className?: string }) { }, [ctx.account, ctx.storage.node]) const saveAsJson = useCallback(async () => { setProcessingStatus(true) - const iter = ctx.storage.node.iterate() + const iter = await ctx.storage.node.iterate() const chunks: Record = {} while (true) { const node = await iter.next() From 590a8a95199b15d7282cfcb2272818ed1d4a4cd0 Mon Sep 17 00:00:00 2001 From: akindyakov Date: Tue, 7 Feb 2023 09:24:16 +0000 Subject: [PATCH 14/16] Remove debug files --- t | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 t diff --git a/t b/t deleted file mode 100644 index f60d2e5e..00000000 --- a/t +++ /dev/null @@ -1,21 +0,0 @@ -ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/suggestAssociations.ts -16:28-32 -[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/suggestAssociations.ts(16,29) - TS2339: Property 'next' does not exist on type 'Promise'. - -ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/search/similarity.ts -./src/background/search/similarity.ts 184:28-32 -[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/background/search/similarity.ts(184,29) - TS2339: Property 'next' does not exist on type 'Promise'. - @ ./src/background.ts 16:0-61 185:32-60 367:44-72 717:8-27 - -ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts -./src/omnibox/omnibox.ts 57:28-32 -[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts(57,29) - TS2339: Property 'next' does not exist on type 'Promise'. - @ ./src/background.ts 10:0-45 714:8-24 - -ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts -./src/omnibox/omnibox.ts 59:24-28 -[tsl] ERROR in /Users/akindyakov/source/truthsayer/archaeologist/src/omnibox/omnibox.ts(59,25) - From a07cc53a4e9901de81333134f44fa9aa6b6a024e Mon Sep 17 00:00:00 2001 From: akindyakov Date: Wed, 8 Feb 2023 07:14:21 +0000 Subject: [PATCH 15/16] Merge PR #430 --- truthsayer/src/external-import/DataCentreImporter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index fad8a369..7713f51d 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -28,7 +28,7 @@ async function downloadUserDataFromMazedBackend( setLoadingState: (value: LoadingState) => void ): Promise { const oldToNewNids: Map = new Map() - const iter = datacenterStorageApi.node.iterate() + const iter = await datacenterStorageApi.node.iterate() let progressCounter = 0 // Clone all nodes, saving mapping between { old-nid → new-nid } while (true) { From 129837e8771c07d6d994049bbe092ab8e6c5b67a Mon Sep 17 00:00:00 2001 From: akindyakov Date: Wed, 8 Feb 2023 08:52:45 +0000 Subject: [PATCH 16/16] Change wording --- .../external-import/DataCentreImporter.tsx | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/truthsayer/src/external-import/DataCentreImporter.tsx b/truthsayer/src/external-import/DataCentreImporter.tsx index 7713f51d..f2f3ff2a 100644 --- a/truthsayer/src/external-import/DataCentreImporter.tsx +++ b/truthsayer/src/external-import/DataCentreImporter.tsx @@ -23,12 +23,16 @@ export function NotImplementedMessage() { } async function downloadUserDataFromMazedBackend( - localStorageApi: StorageApi, - datacenterStorageApi: StorageApi, + dstStorage: StorageApi, + srcStorage: StorageApi, setLoadingState: (value: LoadingState) => void ): Promise { const oldToNewNids: Map = new Map() - const iter = await datacenterStorageApi.node.iterate() + // Data centre implementation of iterator is buggy and sometimes returs same + // node twice, check for duplicates to prevent creating duplicates in local + // storage + const oldNids: Set = new Set() + const iter = await srcStorage.node.iterate() let progressCounter = 0 // Clone all nodes, saving mapping between { old-nid → new-nid } while (true) { @@ -40,9 +44,13 @@ async function downloadUserDataFromMazedBackend( type: 'loading', progress: `Downloading fragments (${++progressCounter})...`, }) + if (oldNids.has(node.nid)) { + continue + } + oldNids.add(node.nid) const url = node.extattrs?.web?.url ?? node.extattrs?.web_quote?.url const origin = url != null ? genOriginId(url) : undefined - const r = await localStorageApi.node.create({ + const r = await dstStorage.node.create({ text: node.text, index_text: node.index_text, extattrs: node.extattrs, @@ -55,7 +63,7 @@ async function downloadUserDataFromMazedBackend( // Clone all edges progressCounter = 0 for (const oldNid of oldToNewNids.keys()) { - const edges = await datacenterStorageApi.edge.get({ nid: oldNid }) + const edges = await srcStorage.edge.get({ nid: oldNid }) for (const oldEdge of edges.from_edges.concat(edges.to_edges)) { setLoadingState({ type: 'loading', @@ -64,7 +72,7 @@ async function downloadUserDataFromMazedBackend( const fromNid = oldToNewNids.get(oldEdge.from_nid) const toNid = oldToNewNids.get(oldEdge.to_nid) if (fromNid && toNid) { - await localStorageApi.edge.create({ from: fromNid, to: toNid }) + await dstStorage.edge.create({ from: fromNid, to: toNid }) } } } @@ -93,27 +101,27 @@ export function DownloadUserDataFromMazedBackendControl() { const [loadingState, setLoadingState] = React.useState({ type: 'standby', }) - const ctx = React.useContext(MzdGlobalContext) + const currentStorage = React.useContext(MzdGlobalContext).storage const sync = React.useCallback(() => { setLoadingState({ type: 'loading', progress: '...' }) - const datacenterStorageApi = makeDatacenterStorageApi() + const sourceStorage = makeDatacenterStorageApi() downloadUserDataFromMazedBackend( - ctx.storage, - datacenterStorageApi, + currentStorage, + sourceStorage, setLoadingState ) - }, [ctx.storage]) + }, [currentStorage]) let buttonText switch (loadingState.type) { case 'loading': buttonText = ( <> - Loading {loadingState.progress} + Downloading {loadingState.progress} ) break case 'standby': - buttonText = <>Start + buttonText = <>Download break case 'done': buttonText = <>Done 🏁 @@ -121,7 +129,9 @@ export function DownloadUserDataFromMazedBackendControl() { } return ( - Download fragments from Mazed backend + + Download fragments from <b>Mazed datacenter</b> to <b>local storage</b> +