From 7cea24556cc2fea84871b33c0ea0d32a7910e79f Mon Sep 17 00:00:00 2001 From: rahulramesha Date: Fri, 4 Oct 2024 15:23:36 +0530 Subject: [PATCH 01/24] fix layout switching when filter is not yet completely fetched --- .../roots/archived-issue-layout-root.tsx | 13 ++++++++++++- .../issue-layouts/roots/cycle-layout-root.tsx | 13 +++++++++++-- .../roots/draft-issue-layout-root.tsx | 13 +++++++++++-- .../issue-layouts/roots/module-layout-root.tsx | 14 ++++++++++++-- .../issue-layouts/roots/project-layout-root.tsx | 13 +++++++++++-- .../roots/project-view-layout-root.tsx | 5 +++-- web/core/store/issue/archived/filter.store.ts | 1 + web/core/store/issue/cycle/filter.store.ts | 1 + web/core/store/issue/draft/filter.store.ts | 1 + web/core/store/issue/module/filter.store.ts | 1 + web/core/store/issue/project-views/filter.store.ts | 14 +++++++++++--- web/core/store/issue/project/filter.store.ts | 1 + 12 files changed, 76 insertions(+), 14 deletions(-) diff --git a/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx b/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx index 322c0005460..641a82be4fc 100644 --- a/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx +++ b/web/core/components/issues/issue-layouts/roots/archived-issue-layout-root.tsx @@ -4,6 +4,7 @@ import { useParams } from "next/navigation"; import useSWR from "swr"; // mobx store // components +import { LogoSpinner } from "@/components/common"; import { ArchivedIssueListLayout, ArchivedIssueAppliedFiltersRoot, IssuePeekOverview } from "@/components/issues"; import { EIssuesStoreType } from "@/constants/issue"; // ui @@ -16,7 +17,7 @@ export const ArchivedIssueLayoutRoot: React.FC = observer(() => { // hooks const { issuesFilter } = useIssues(EIssuesStoreType.ARCHIVED); - useSWR( + const { isLoading } = useSWR( workspaceSlug && projectId ? `ARCHIVED_ISSUES_${workspaceSlug.toString()}_${projectId.toString()}` : null, async () => { if (workspaceSlug && projectId) { @@ -26,7 +27,17 @@ export const ArchivedIssueLayoutRoot: React.FC = observer(() => { { revalidateIfStale: false, revalidateOnFocus: false } ); + const issueFilters = issuesFilter?.getIssueFilters(projectId?.toString()); + if (!workspaceSlug || !projectId) return <>; + + if (isLoading && !issueFilters) + return ( +
+ +
+ ); + return ( diff --git a/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx b/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx index 4da446aab88..1b69156ba11 100644 --- a/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx +++ b/web/core/components/issues/issue-layouts/roots/cycle-layout-root.tsx @@ -5,6 +5,7 @@ import { useParams } from "next/navigation"; import useSWR from "swr"; // hooks // components +import { LogoSpinner } from "@/components/common"; import { TransferIssues, TransferIssuesModal } from "@/components/cycles"; import { CycleAppliedFiltersRoot, @@ -50,7 +51,7 @@ export const CycleLayoutRoot: React.FC = observer(() => { // state const [transferIssuesModal, setTransferIssuesModal] = useState(false); - useSWR( + const { isLoading } = useSWR( workspaceSlug && projectId && cycleId ? `CYCLE_ISSUES_${workspaceSlug.toString()}_${projectId.toString()}_${cycleId.toString()}` : null, @@ -62,7 +63,8 @@ export const CycleLayoutRoot: React.FC = observer(() => { { revalidateIfStale: false, revalidateOnFocus: false } ); - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout; + const issueFilters = issuesFilter?.getIssueFilters(cycleId?.toString()); + const activeLayout = issueFilters?.displayFilters?.layout; const cycleDetails = cycleId ? getCycleById(cycleId.toString()) : undefined; const cycleStatus = cycleDetails?.status?.toLocaleLowerCase() ?? "draft"; @@ -75,6 +77,13 @@ export const CycleLayoutRoot: React.FC = observer(() => { if (!workspaceSlug || !projectId || !cycleId) return <>; + if (isLoading && !issueFilters) + return ( +
+ +
+ ); + return ( setTransferIssuesModal(false)} isOpen={transferIssuesModal} /> diff --git a/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx b/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx index a4b78be80d1..c13ff104e16 100644 --- a/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx +++ b/web/core/components/issues/issue-layouts/roots/draft-issue-layout-root.tsx @@ -2,6 +2,7 @@ import React from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import useSWR from "swr"; +import { LogoSpinner } from "@/components/common"; import { IssuePeekOverview } from "@/components/issues/peek-overview"; import { EIssueLayoutTypes, EIssuesStoreType } from "@/constants/issue"; // hooks @@ -30,7 +31,7 @@ export const DraftIssueLayoutRoot: React.FC = observer(() => { // hooks const { issuesFilter } = useIssues(EIssuesStoreType.DRAFT); - useSWR( + const { isLoading } = useSWR( workspaceSlug && projectId ? `DRAFT_ISSUES_${workspaceSlug.toString()}_${projectId.toString()}` : null, async () => { if (workspaceSlug && projectId) { @@ -40,10 +41,18 @@ export const DraftIssueLayoutRoot: React.FC = observer(() => { { revalidateIfStale: false, revalidateOnFocus: false } ); - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout || undefined; + const issueFilters = issuesFilter?.getIssueFilters(projectId?.toString()); + const activeLayout = issueFilters?.displayFilters?.layout || undefined; if (!workspaceSlug || !projectId) return <>; + if (isLoading && !issueFilters) + return ( +
+ +
+ ); + return (
diff --git a/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx b/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx index 70d7dce43ff..b4eb7c464cd 100644 --- a/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx +++ b/web/core/components/issues/issue-layouts/roots/module-layout-root.tsx @@ -5,6 +5,7 @@ import useSWR from "swr"; // mobx store // components import { Row, ERowVariant } from "@plane/ui"; +import { LogoSpinner } from "@/components/common"; import { IssuePeekOverview, ModuleAppliedFiltersRoot, @@ -43,7 +44,7 @@ export const ModuleLayoutRoot: React.FC = observer(() => { // hooks const { issuesFilter } = useIssues(EIssuesStoreType.MODULE); - useSWR( + const { isLoading } = useSWR( workspaceSlug && projectId && moduleId ? `MODULE_ISSUES_${workspaceSlug.toString()}_${projectId.toString()}_${moduleId.toString()}` : null, @@ -55,9 +56,18 @@ export const ModuleLayoutRoot: React.FC = observer(() => { { revalidateIfStale: false, revalidateOnFocus: false } ); + const issueFilters = issuesFilter?.getIssueFilters(moduleId?.toString()); + if (!workspaceSlug || !projectId || !moduleId) return <>; - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout || undefined; + if (isLoading && !issueFilters) + return ( +
+ +
+ ); + + const activeLayout = issueFilters?.displayFilters?.layout || undefined; return ( diff --git a/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx b/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx index 24009ff8d7d..853f13dd4f2 100644 --- a/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx +++ b/web/core/components/issues/issue-layouts/roots/project-layout-root.tsx @@ -6,6 +6,7 @@ import { useParams } from "next/navigation"; import useSWR from "swr"; // components import { Spinner } from "@plane/ui"; +import { LogoSpinner } from "@/components/common"; import { ListLayout, CalendarLayout, @@ -44,7 +45,7 @@ export const ProjectLayoutRoot: FC = observer(() => { // hooks const { issues, issuesFilter } = useIssues(EIssuesStoreType.PROJECT); - useSWR( + const { isLoading } = useSWR( workspaceSlug && projectId ? `PROJECT_ISSUES_${workspaceSlug}_${projectId}` : null, async () => { if (workspaceSlug && projectId) { @@ -54,10 +55,18 @@ export const ProjectLayoutRoot: FC = observer(() => { { revalidateIfStale: false, revalidateOnFocus: false } ); - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout; + const issueFilters = issuesFilter?.getIssueFilters(projectId?.toString()); + const activeLayout = issueFilters?.displayFilters?.layout; if (!workspaceSlug || !projectId) return <>; + if (isLoading && !issueFilters) + return ( +
+ +
+ ); + return (
diff --git a/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx b/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx index d04089a7e1a..8c84417578d 100644 --- a/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx +++ b/web/core/components/issues/issue-layouts/roots/project-view-layout-root.tsx @@ -53,11 +53,12 @@ export const ProjectViewLayoutRoot: React.FC = observer(() => { { revalidateIfStale: false, revalidateOnFocus: false } ); - const activeLayout = issuesFilter?.issueFilters?.displayFilters?.layout; + const issueFilters = issuesFilter?.getIssueFilters(viewId?.toString()); + const activeLayout = issueFilters?.displayFilters?.layout; if (!workspaceSlug || !projectId || !viewId) return <>; - if (isLoading) { + if (isLoading && !issueFilters) { return (
diff --git a/web/core/store/issue/archived/filter.store.ts b/web/core/store/issue/archived/filter.store.ts index 31f5f4496af..ad673c8cf41 100644 --- a/web/core/store/issue/archived/filter.store.ts +++ b/web/core/store/issue/archived/filter.store.ts @@ -33,6 +33,7 @@ export interface IArchivedIssuesFilter extends IBaseIssueFilterStore { groupId: string | undefined, subGroupId: string | undefined ) => Partial>; + getIssueFilters(projectId: string): IIssueFilters | undefined; // action fetchFilters: (workspaceSlug: string, projectId: string) => Promise; updateFilters: ( diff --git a/web/core/store/issue/cycle/filter.store.ts b/web/core/store/issue/cycle/filter.store.ts index 3565a05c062..5e62061f055 100644 --- a/web/core/store/issue/cycle/filter.store.ts +++ b/web/core/store/issue/cycle/filter.store.ts @@ -31,6 +31,7 @@ export interface ICycleIssuesFilter extends IBaseIssueFilterStore { groupId: string | undefined, subGroupId: string | undefined ) => Partial>; + getIssueFilters(cycleId: string): IIssueFilters | undefined; // action fetchFilters: (workspaceSlug: string, projectId: string, cycleId: string) => Promise; updateFilters: ( diff --git a/web/core/store/issue/draft/filter.store.ts b/web/core/store/issue/draft/filter.store.ts index 0c657543838..bbada1199bf 100644 --- a/web/core/store/issue/draft/filter.store.ts +++ b/web/core/store/issue/draft/filter.store.ts @@ -33,6 +33,7 @@ export interface IDraftIssuesFilter extends IBaseIssueFilterStore { groupId: string | undefined, subGroupId: string | undefined ) => Partial>; + getIssueFilters(projectId: string): IIssueFilters | undefined; // action fetchFilters: (workspaceSlug: string, projectId: string) => Promise; updateFilters: ( diff --git a/web/core/store/issue/module/filter.store.ts b/web/core/store/issue/module/filter.store.ts index 1830619cd9f..9c22963b91e 100644 --- a/web/core/store/issue/module/filter.store.ts +++ b/web/core/store/issue/module/filter.store.ts @@ -31,6 +31,7 @@ export interface IModuleIssuesFilter extends IBaseIssueFilterStore { groupId: string | undefined, subGroupId: string | undefined ) => Partial>; + getIssueFilters(moduleId: string): IIssueFilters | undefined; // action fetchFilters: (workspaceSlug: string, projectId: string, moduleId: string) => Promise; updateFilters: ( diff --git a/web/core/store/issue/project-views/filter.store.ts b/web/core/store/issue/project-views/filter.store.ts index 4261b1bece2..b49633c367c 100644 --- a/web/core/store/issue/project-views/filter.store.ts +++ b/web/core/store/issue/project-views/filter.store.ts @@ -31,6 +31,7 @@ export interface IProjectViewIssuesFilter extends IBaseIssueFilterStore { groupId: string | undefined, subGroupId: string | undefined ) => Partial>; + getIssueFilters(viewId: string): IIssueFilters | undefined; // action fetchFilters: (workspaceSlug: string, projectId: string, viewId: string) => Promise; updateFilters: ( @@ -264,9 +265,16 @@ export class ProjectViewIssuesFilter extends IssueFilterHelperStore implements I const currentUserId = this.rootIssueStore.currentUserId; if (currentUserId) - this.handleIssuesLocalFilters.set(EIssuesStoreType.PROJECT_VIEW, type, workspaceSlug, viewId, currentUserId, { - kanban_filters: _filters.kanbanFilters, - }); + this.handleIssuesLocalFilters.set( + EIssuesStoreType.PROJECT_VIEW, + type, + workspaceSlug, + viewId, + currentUserId, + { + kanban_filters: _filters.kanbanFilters, + } + ); runInAction(() => { Object.keys(updatedKanbanFilters).forEach((_key) => { diff --git a/web/core/store/issue/project/filter.store.ts b/web/core/store/issue/project/filter.store.ts index 54b109d12af..069f2ed8932 100644 --- a/web/core/store/issue/project/filter.store.ts +++ b/web/core/store/issue/project/filter.store.ts @@ -31,6 +31,7 @@ export interface IProjectIssuesFilter extends IBaseIssueFilterStore { groupId: string | undefined, subGroupId: string | undefined ) => Partial>; + getIssueFilters(projectId: string): IIssueFilters | undefined; // action fetchFilters: (workspaceSlug: string, projectId: string) => Promise; updateFilters: ( From 0ca5509cc413119f4a2e15ef4edbb00e9664eb96 Mon Sep 17 00:00:00 2001 From: rahulramesha Date: Fri, 4 Oct 2024 15:30:22 +0530 Subject: [PATCH 02/24] add layout in issue filter params --- packages/types/src/view-props.d.ts | 3 ++- web/core/store/issue/helpers/issue-filter-helper.store.ts | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/types/src/view-props.d.ts b/packages/types/src/view-props.d.ts index 59d5ffded52..c8375ba2551 100644 --- a/packages/types/src/view-props.d.ts +++ b/packages/types/src/view-props.d.ts @@ -77,7 +77,8 @@ export type TIssueParams = | "show_empty_groups" | "cursor" | "per_page" - | "issue_type"; + | "issue_type" + | "layout"; export type TCalendarLayouts = "month" | "week"; diff --git a/web/core/store/issue/helpers/issue-filter-helper.store.ts b/web/core/store/issue/helpers/issue-filter-helper.store.ts index 5d4b638a539..338b6a4ac85 100644 --- a/web/core/store/issue/helpers/issue-filter-helper.store.ts +++ b/web/core/store/issue/helpers/issue-filter-helper.store.ts @@ -13,7 +13,7 @@ import { TStaticViewTypes, } from "@plane/types"; // constants -import { EIssueFilterType, EIssuesStoreType } from "@/constants/issue"; +import { EIssueFilterType, EIssueLayoutTypes, EIssuesStoreType } from "@/constants/issue"; // helpers import { getComputedDisplayFilters, getComputedDisplayProperties } from "@/helpers/issue.helper"; // lib @@ -114,6 +114,8 @@ export class IssueFilterHelperStore implements IIssueFilterHelperStore { : nonEmptyArrayValue; }); + if (displayFilters?.layout) issueFiltersParams.layout = displayFilters?.layout; + return issueFiltersParams; }; From 84956cdb49d8bb33d32d26059a37f932d5924c53 Mon Sep 17 00:00:00 2001 From: Satish Gandham Date: Fri, 4 Oct 2024 16:07:31 +0530 Subject: [PATCH 03/24] Handle cases when DB intilization failed --- web/core/local-db/storage.sqlite.ts | 8 ++++---- web/core/local-db/utils/load-issues.ts | 10 +++++----- web/core/local-db/utils/query-executor.ts | 4 +--- web/core/local-db/utils/query.utils.ts | 18 +++++++++++++++--- web/core/local-db/utils/utils.ts | 2 +- web/next.config.js | 2 -- 6 files changed, 26 insertions(+), 18 deletions(-) diff --git a/web/core/local-db/storage.sqlite.ts b/web/core/local-db/storage.sqlite.ts index 099063aca11..e8735e87ff4 100644 --- a/web/core/local-db/storage.sqlite.ts +++ b/web/core/local-db/storage.sqlite.ts @@ -148,7 +148,7 @@ export class Storage { }; syncWorkspace = async () => { - if (document.hidden || !rootStore.user.localDBEnabled) return; // return if the window gets hidden + if (document.hidden || !rootStore.user.localDBEnabled || !this.db) return; // return if the window gets hidden await Sentry.startSpan({ name: "LOAD_WS", attributes: { slug: this.workspaceSlug } }, async () => { await loadWorkSpaceData(this.workspaceSlug); }); @@ -173,7 +173,7 @@ export class Storage { }; syncIssues = async (projectId: string) => { - if (document.hidden || !rootStore.user.localDBEnabled) return false; // return if the window gets hidden + if (document.hidden || !rootStore.user.localDBEnabled || !this.db) return false; // return if the window gets hidden try { const sync = Sentry.startSpan({ name: `SYNC_ISSUES` }, () => this._syncIssues(projectId)); @@ -191,7 +191,7 @@ export class Storage { log("### Sync started"); let status = this.getStatus(projectId); if (status === "loading" || status === "syncing") { - logInfo(`Project ${projectId} is already loading or syncing`); + log(`Project ${projectId} is already loading or syncing`); return; } const syncPromise = this.getSync(projectId); @@ -290,7 +290,7 @@ export class Storage { !rootStore.user.localDBEnabled ) { if (rootStore.user.localDBEnabled) { - logInfo(`Project ${projectId} is loading, falling back to server`); + log(`Project ${projectId} is loading, falling back to server`); } const issueService = new IssueService(); return await issueService.getIssuesFromServer(workspaceSlug, projectId, queries); diff --git a/web/core/local-db/utils/load-issues.ts b/web/core/local-db/utils/load-issues.ts index 1524edea7d3..1487cece71f 100644 --- a/web/core/local-db/utils/load-issues.ts +++ b/web/core/local-db/utils/load-issues.ts @@ -8,7 +8,7 @@ import { issueSchema } from "./schemas"; export const PROJECT_OFFLINE_STATUS: Record = {}; export const addIssue = async (issue: any) => { - if (document.hidden || !rootStore.user.localDBEnabled) return; + if (document.hidden || !rootStore.user.localDBEnabled || !persistence.db) return; persistence.db.exec("BEGIN TRANSACTION;"); stageIssueInserts(issue); @@ -16,7 +16,7 @@ export const addIssue = async (issue: any) => { }; export const addIssuesBulk = async (issues: any, batchSize = 100) => { - if (!rootStore.user.localDBEnabled) return; + if (!rootStore.user.localDBEnabled || !persistence.db) return; for (let i = 0; i < issues.length; i += batchSize) { const batch = issues.slice(i, i + batchSize); @@ -32,7 +32,7 @@ export const addIssuesBulk = async (issues: any, batchSize = 100) => { } }; export const deleteIssueFromLocal = async (issue_id: any) => { - if (!rootStore.user.localDBEnabled) return; + if (!rootStore.user.localDBEnabled || !persistence.db) return; const deleteQuery = `delete from issues where id='${issue_id}'`; const deleteMetaQuery = `delete from issue_meta where issue_id='${issue_id}'`; @@ -44,7 +44,7 @@ export const deleteIssueFromLocal = async (issue_id: any) => { }; // @todo: Update deletes the issue description from local. Implement a separate update. export const updateIssue = async (issue: TIssue & { is_local_update: number }) => { - if (document.hidden || !rootStore.user.localDBEnabled) return; + if (document.hidden || !rootStore.user.localDBEnabled || !persistence.db) return; const issue_id = issue.id; // delete the issue and its meta data @@ -53,7 +53,7 @@ export const updateIssue = async (issue: TIssue & { is_local_update: number }) = }; export const syncDeletesToLocal = async (workspaceId: string, projectId: string, queries: any) => { - if (!rootStore.user.localDBEnabled) return; + if (!rootStore.user.localDBEnabled || !persistence.db) return; const issueService = new IssueService(); const response = await issueService.getDeletedIssues(workspaceId, projectId, queries); diff --git a/web/core/local-db/utils/query-executor.ts b/web/core/local-db/utils/query-executor.ts index 9002d5a7bfc..357fbbbc401 100644 --- a/web/core/local-db/utils/query-executor.ts +++ b/web/core/local-db/utils/query-executor.ts @@ -1,9 +1,7 @@ -// import { SQL } from "./sqlite"; - import { persistence } from "../storage.sqlite"; export const runQuery = async (sql: string) => { - const data = await persistence.db.exec({ + const data = await persistence.db?.exec({ sql, rowMode: "object", returnValue: "resultRows", diff --git a/web/core/local-db/utils/query.utils.ts b/web/core/local-db/utils/query.utils.ts index fbc42fec991..520338e6af6 100644 --- a/web/core/local-db/utils/query.utils.ts +++ b/web/core/local-db/utils/query.utils.ts @@ -4,8 +4,20 @@ import { issueSchema } from "./schemas"; import { wrapDateTime } from "./utils"; export const translateQueryParams = (queries: any) => { - const { group_by, sub_group_by, labels, assignees, state, cycle, module, priority, type, issue_type, ...otherProps } = - queries; + const { + group_by, + layout, + sub_group_by, + labels, + assignees, + state, + cycle, + module, + priority, + type, + issue_type, + ...otherProps + } = queries; const order_by = queries.order_by; if (state) otherProps.state_id = state; @@ -33,7 +45,7 @@ export const translateQueryParams = (queries: any) => { } // Fix invalid orderby when switching from spreadsheet layout - if ((group_by || sub_group_by) && Object.keys(SPECIAL_ORDER_BY).includes(order_by)) { + if (layout === "spreadsheet" && Object.keys(SPECIAL_ORDER_BY).includes(order_by)) { otherProps.order_by = "sort_order"; } // For each property value, replace None with empty string diff --git a/web/core/local-db/utils/utils.ts b/web/core/local-db/utils/utils.ts index 39c49d745cc..cbe373fb2ef 100644 --- a/web/core/local-db/utils/utils.ts +++ b/web/core/local-db/utils/utils.ts @@ -15,7 +15,7 @@ export const logError = (e: any) => { e = parseSQLite3Error(e); } Sentry.captureException(e); - console.log(e); + console.error(e); }; export const logInfo = console.info; diff --git a/web/next.config.js b/web/next.config.js index 1d191da3d84..fba54a17dae 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -20,8 +20,6 @@ const nextConfig = { key: "Referrer-Policy", value: "origin-when-cross-origin", }, - { key: "Cross-Origin-Opener-Policy", value: "same-origin" }, - { key: "Cross-Origin-Embedder-Policy", value: "credentialless" }, ], }, ]; From aeca6f771bbe330ba8744be2c07b45f6154c0c44 Mon Sep 17 00:00:00 2001 From: gurusainath Date: Fri, 4 Oct 2024 16:30:06 +0530 Subject: [PATCH 04/24] chore: permission layer and updated issues v1 query from workspace to project level --- apiserver/plane/app/urls/issue.py | 2 +- apiserver/plane/app/views/issue/base.py | 33 ++++++++++++++---------- web/core/services/issue/issue.service.ts | 9 +------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/apiserver/plane/app/urls/issue.py b/apiserver/plane/app/urls/issue.py index 910eb91078c..564725e8391 100644 --- a/apiserver/plane/app/urls/issue.py +++ b/apiserver/plane/app/urls/issue.py @@ -42,7 +42,7 @@ ), # updated v2 paginated issues path( - "workspaces//v2/issues/", + "workspaces//projects//v2/issues/", IssuePaginatedViewSet.as_view({"get": "list"}), name="project-issues-paginated", ), diff --git a/apiserver/plane/app/views/issue/base.py b/apiserver/plane/app/views/issue/base.py index 8adc5a84200..eca14018fff 100644 --- a/apiserver/plane/app/views/issue/base.py +++ b/apiserver/plane/app/views/issue/base.py @@ -741,17 +741,12 @@ def get(self, request, slug, project_id): class IssuePaginatedViewSet(BaseViewSet): def get_queryset(self): workspace_slug = self.kwargs.get("slug") - - # getting the project_id from the request params - project_id = self.request.GET.get("project_id", None) + project_id = self.kwargs.get("project_id") issue_queryset = Issue.issue_objects.filter( - workspace__slug=workspace_slug + workspace__slug=workspace_slug, project_id=project_id ) - if project_id: - issue_queryset = issue_queryset.filter(project_id=project_id) - return ( issue_queryset.select_related( "workspace", "project", "state", "parent" @@ -793,8 +788,8 @@ def process_paginated_result(self, fields, results, timezone): return paginated_data - def list(self, request, slug): - project_id = self.request.GET.get("project_id", None) + @allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST]) + def list(self, request, slug, project_id): cursor = request.GET.get("cursor", None) is_description_required = request.GET.get("description", False) updated_at = request.GET.get("updated_at__gt", None) @@ -833,14 +828,26 @@ def list(self, request, slug): required_fields.append("description_html") # querying issues - base_queryset = Issue.issue_objects.filter(workspace__slug=slug) - - if project_id: - base_queryset = base_queryset.filter(project_id=project_id) + base_queryset = Issue.issue_objects.filter( + workspace__slug=slug, project_id=project_id + ) base_queryset = base_queryset.order_by("updated_at") queryset = self.get_queryset().order_by("updated_at") + # validation for guest user + project = Project.objects.get(pk=project_id, workspace__slug=slug) + project_member = ProjectMember.objects.filter( + workspace__slug=slug, + project_id=project_id, + member=request.user, + role=5, + is_active=True, + ) + if project_member.exists() and not project.guest_view_all_features: + base_queryset = base_queryset.filter(created_by=request.user) + queryset = queryset.filter(created_by=request.user) + # filtering issues by greater then updated_at given by the user if updated_at: base_queryset = base_queryset.filter(updated_at__gt=updated_at) diff --git a/web/core/services/issue/issue.service.ts b/web/core/services/issue/issue.service.ts index 107ad9923ba..76394a4d1f7 100644 --- a/web/core/services/issue/issue.service.ts +++ b/web/core/services/issue/issue.service.ts @@ -55,14 +55,7 @@ export class IssueService extends APIService { queries?: any, config = {} ): Promise { - queries.project_id = projectId; - return this.get( - `/api/workspaces/${workspaceSlug}/v2/issues/`, - { - params: queries, - }, - config - ) + return this.get(`/api/workspaces/${workspaceSlug}/projects/${projectId}/v2/issues/`, { params: queries }, config) .then((response) => response?.data) .catch((error) => { throw error?.response?.data; From 28acf5d743babd28d8f074183814caa9cc17a12c Mon Sep 17 00:00:00 2001 From: Satish Gandham Date: Thu, 17 Oct 2024 18:28:44 +0530 Subject: [PATCH 05/24] - Switch to using wa-sqlite instead of sqlite-wasm --- web/core/local-db/storage.sqlite.ts | 62 +- web/core/local-db/utils/query-executor.ts | 2 +- web/core/local-db/worker/db.ts | 77 + .../worker/wa-sqlite/src/FacadeVFS.js | 508 +++++++ .../worker/wa-sqlite/src/OPFSCoopSyncVFS.js | 592 ++++++++ web/core/local-db/worker/wa-sqlite/src/VFS.js | 222 +++ .../worker/wa-sqlite/src/sqlite-api.js | 899 +++++++++++ .../worker/wa-sqlite/src/sqlite-constants.js | 275 ++++ .../worker/wa-sqlite/src/types/globals.d.ts | 60 + .../worker/wa-sqlite/src/types/index.d.ts | 1317 +++++++++++++++++ web/package.json | 6 +- yarn.lock | 10 +- 12 files changed, 3971 insertions(+), 59 deletions(-) create mode 100644 web/core/local-db/worker/db.ts create mode 100644 web/core/local-db/worker/wa-sqlite/src/FacadeVFS.js create mode 100644 web/core/local-db/worker/wa-sqlite/src/OPFSCoopSyncVFS.js create mode 100644 web/core/local-db/worker/wa-sqlite/src/VFS.js create mode 100644 web/core/local-db/worker/wa-sqlite/src/sqlite-api.js create mode 100644 web/core/local-db/worker/wa-sqlite/src/sqlite-constants.js create mode 100644 web/core/local-db/worker/wa-sqlite/src/types/globals.d.ts create mode 100644 web/core/local-db/worker/wa-sqlite/src/types/index.d.ts diff --git a/web/core/local-db/storage.sqlite.ts b/web/core/local-db/storage.sqlite.ts index 099063aca11..faefce40b87 100644 --- a/web/core/local-db/storage.sqlite.ts +++ b/web/core/local-db/storage.sqlite.ts @@ -1,4 +1,5 @@ import * as Sentry from "@sentry/nextjs"; +import * as Comlink from "comlink"; import set from "lodash/set"; // plane import { EIssueGroupBYServerToProperty } from "@plane/constants"; @@ -17,10 +18,7 @@ import { issueFilterCountQueryConstructor, issueFilterQueryConstructor } from ". import { runQuery } from "./utils/query-executor"; import { createTables } from "./utils/tables"; import { getGroupedIssueResults, getSubGroupedIssueResults, log, logError, logInfo } from "./utils/utils"; - -declare module "@sqlite.org/sqlite-wasm" { - export function sqlite3Worker1Promiser(...args: any): any; -} +import { DBClass } from "./worker/db"; const DB_VERSION = 1; const PAGE_SIZE = 1000; @@ -93,57 +91,21 @@ export class Storage { logInfo("Loading and initializing SQLite3 module..."); + const MyWorker = Comlink.wrap(new Worker(new URL("./worker/db.ts", import.meta.url))); this.workspaceSlug = workspaceSlug; this.dbName = workspaceSlug; - const { sqlite3Worker1Promiser } = await import("@sqlite.org/sqlite-wasm"); - - try { - const promiser: any = await new Promise((resolve) => { - const _promiser = sqlite3Worker1Promiser({ - onready: () => resolve(_promiser), - }); - }); - - const configResponse = await promiser("config-get", {}); - log("Running SQLite3 version", configResponse.result.version.libVersion); - - const openResponse = await promiser("open", { - filename: `file:${this.dbName}.sqlite3?vfs=opfs`, - }); - const { dbId } = openResponse; - this.db = { - dbId, - exec: async (val: any) => { - if (typeof val === "string") { - val = { sql: val }; - } - return promiser("exec", { dbId, ...val }); - }, - }; - - // dump DB of db version is matching - const dbVersion = await this.getOption("DB_VERSION"); - if (dbVersion !== "" && parseInt(dbVersion) !== DB_VERSION) { - await this.clearStorage(); - this.reset(); - await this._initialize(workspaceSlug); - return false; - } + const instance = await new MyWorker(); + await instance.init(workspaceSlug); - log( - "OPFS is available, created persisted database at", - openResponse.result.filename.replace(/^file:(.*?)\?vfs=opfs$/, "$1") - ); - this.status = "ready"; - // Your SQLite code here. - await createTables(); + this.db = { + exec: instance.exec, + }; - await this.setOption("DB_VERSION", DB_VERSION.toString()); - } catch (err) { - logError(err); - throw err; - } + this.status = "ready"; + // Your SQLite code here. + await createTables(); + await this.setOption("DB_VERSION", DB_VERSION.toString()); return true; }; diff --git a/web/core/local-db/utils/query-executor.ts b/web/core/local-db/utils/query-executor.ts index 9002d5a7bfc..65b7210a86a 100644 --- a/web/core/local-db/utils/query-executor.ts +++ b/web/core/local-db/utils/query-executor.ts @@ -9,5 +9,5 @@ export const runQuery = async (sql: string) => { returnValue: "resultRows", }); - return data.result.resultRows; + return data; }; diff --git a/web/core/local-db/worker/db.ts b/web/core/local-db/worker/db.ts new file mode 100644 index 00000000000..4afda1af4ff --- /dev/null +++ b/web/core/local-db/worker/db.ts @@ -0,0 +1,77 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import * as Comlink from "comlink"; +import SQLiteESMFactory from "./wa-sqlite/dist/wa-sqlite.mjs"; +import { OPFSCoopSyncVFS as MyVFS } from "./wa-sqlite/src/OPFSCoopSyncVFS"; +import * as SQLite from "./wa-sqlite/src/sqlite-api"; + +type TQueryProps = { + sql: string; + rowMode: string; + returnValue: string; + bind: any[]; +}; +const mergeToObject = (columns: string[], row: any[]) => { + const obj: any = {}; + columns.forEach((column, index) => { + obj[column] = row[index]; + }); + return obj; +}; +export class DBClass { + instance: any = {}; + sqlite3: any; + async init(dbName: string) { + const m = await SQLiteESMFactory(); + this.sqlite3 = SQLite.Factory(m); + const vfs = await MyVFS.create("hello", m); + this.sqlite3.vfs_register(vfs, true); + const db = await this.sqlite3.open_v2(`${dbName}.sqlite3`); + this.instance.db = db; + this.instance.exec = async (sql: string) => { + const rows: any[] = []; + try { + await this.sqlite3.exec(db, sql, (row: any[], columns: string[]) => { + rows.push(mergeToObject(columns, row)); + }); + } catch (e) { + console.log(e); + throw e; + } + return rows; + }; + return true; + } + + runQuery(sql: string) { + return this.instance.exec(sql); + } + + async exec(props: string | TQueryProps) { + let sql: string, bind: any[]; + if (typeof props === "string") { + sql = props; + } else { + ({ sql, bind } = props); + if (bind) { + for await (const stmt of this.sqlite3.statements(this.instance.db, sql)) { + bind.forEach((b, i) => { + this.sqlite3.bind(stmt, i + 1, b); + }); + + const rows = []; + + do { + const columns = await this.sqlite3.column_names(stmt); + const row = await this.sqlite3.row(stmt); + // debugger; + rows.push(mergeToObject(columns, row)); + } while ((await this.sqlite3.step(stmt)) === SQLite.SQLITE_ROW); + + return rows; + } + } + } + return this.instance.exec(sql); + } +} +Comlink.expose(DBClass); diff --git a/web/core/local-db/worker/wa-sqlite/src/FacadeVFS.js b/web/core/local-db/worker/wa-sqlite/src/FacadeVFS.js new file mode 100644 index 00000000000..c975fdc913c --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/FacadeVFS.js @@ -0,0 +1,508 @@ +// Copyright 2024 Roy T. Hashimoto. All Rights Reserved. +import * as VFS from './VFS.js'; + +const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor; + +// Convenience base class for a JavaScript VFS. +// The raw xOpen, xRead, etc. function signatures receive only C primitives +// which aren't easy to work with. This class provides corresponding calls +// like jOpen, jRead, etc., which receive JavaScript-friendlier arguments +// such as string, Uint8Array, and DataView. +export class FacadeVFS extends VFS.Base { + /** + * @param {string} name + * @param {object} module + */ + constructor(name, module) { + super(name, module); + } + + /** + * Override to indicate which methods are asynchronous. + * @param {string} methodName + * @returns {boolean} + */ + hasAsyncMethod(methodName) { + // The input argument is a string like "xOpen", so convert to "jOpen". + // Then check if the method exists and is async. + const jMethodName = `j${methodName.slice(1)}`; + return this[jMethodName] instanceof AsyncFunction; + } + + /** + * Return the filename for a file id for use by mixins. + * @param {number} pFile + * @returns {string} + */ + getFilename(pFile) { + throw new Error('unimplemented'); + } + + /** + * @param {string?} filename + * @param {number} pFile + * @param {number} flags + * @param {DataView} pOutFlags + * @returns {number|Promise} + */ + jOpen(filename, pFile, flags, pOutFlags) { + return VFS.SQLITE_CANTOPEN; + } + + /** + * @param {string} filename + * @param {number} syncDir + * @returns {number|Promise} + */ + jDelete(filename, syncDir) { + return VFS.SQLITE_OK; + } + + /** + * @param {string} filename + * @param {number} flags + * @param {DataView} pResOut + * @returns {number|Promise} + */ + jAccess(filename, flags, pResOut) { + return VFS.SQLITE_OK; + } + + /** + * @param {string} filename + * @param {Uint8Array} zOut + * @returns {number|Promise} + */ + jFullPathname(filename, zOut) { + // Copy the filename to the output buffer. + const { read, written } = new TextEncoder().encodeInto(filename, zOut); + if (read < filename.length) return VFS.SQLITE_IOERR; + if (written >= zOut.length) return VFS.SQLITE_IOERR; + zOut[written] = 0; + return VFS.SQLITE_OK; + } + + /** + * @param {Uint8Array} zBuf + * @returns {number|Promise} + */ + jGetLastError(zBuf) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + jClose(pFile) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {Uint8Array} pData + * @param {number} iOffset + * @returns {number|Promise} + */ + jRead(pFile, pData, iOffset) { + pData.fill(0); + return VFS.SQLITE_IOERR_SHORT_READ; + } + + /** + * @param {number} pFile + * @param {Uint8Array} pData + * @param {number} iOffset + * @returns {number|Promise} + */ + jWrite(pFile, pData, iOffset) { + return VFS.SQLITE_IOERR_WRITE; + } + + /** + * @param {number} pFile + * @param {number} size + * @returns {number|Promise} + */ + jTruncate(pFile, size) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} flags + * @returns {number|Promise} + */ + jSync(pFile, flags) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {DataView} pSize + * @returns {number|Promise} + */ + jFileSize(pFile, pSize) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} lockType + * @returns {number|Promise} + */ + jLock(pFile, lockType) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} lockType + * @returns {number|Promise} + */ + jUnlock(pFile, lockType) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {DataView} pResOut + * @returns {number|Promise} + */ + jCheckReservedLock(pFile, pResOut) { + pResOut.setInt32(0, 0, true); + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} op + * @param {DataView} pArg + * @returns {number|Promise} + */ + jFileControl(pFile, op, pArg) { + return VFS.SQLITE_NOTFOUND; + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + jSectorSize(pFile) { + return super.xSectorSize(pFile); + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + jDeviceCharacteristics(pFile) { + return 0; + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} pFile + * @param {number} flags + * @param {number} pOutFlags + * @returns {number|Promise} + */ + xOpen(pVfs, zName, pFile, flags, pOutFlags) { + const filename = this.#decodeFilename(zName, flags); + const pOutFlagsView = this.#makeTypedDataView('Int32', pOutFlags); + this['log']?.('jOpen', filename, pFile, '0x' + flags.toString(16)); + return this.jOpen(filename, pFile, flags, pOutFlagsView); + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} syncDir + * @returns {number|Promise} + */ + xDelete(pVfs, zName, syncDir) { + const filename = this._module.UTF8ToString(zName); + this['log']?.('jDelete', filename, syncDir); + return this.jDelete(filename, syncDir); + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} flags + * @param {number} pResOut + * @returns {number|Promise} + */ + xAccess(pVfs, zName, flags, pResOut) { + const filename = this._module.UTF8ToString(zName); + const pResOutView = this.#makeTypedDataView('Int32', pResOut); + this['log']?.('jAccess', filename, flags); + return this.jAccess(filename, flags, pResOutView); + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} nOut + * @param {number} zOut + * @returns {number|Promise} + */ + xFullPathname(pVfs, zName, nOut, zOut) { + const filename = this._module.UTF8ToString(zName); + const zOutArray = this._module.HEAPU8.subarray(zOut, zOut + nOut); + this['log']?.('jFullPathname', filename, nOut); + return this.jFullPathname(filename, zOutArray); + } + + /** + * @param {number} pVfs + * @param {number} nBuf + * @param {number} zBuf + * @returns {number|Promise} + */ + xGetLastError(pVfs, nBuf, zBuf) { + const zBufArray = this._module.HEAPU8.subarray(zBuf, zBuf + nBuf); + this['log']?.('jGetLastError', nBuf); + return this.jGetLastError(zBufArray); + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + xClose(pFile) { + this['log']?.('jClose', pFile); + return this.jClose(pFile); + } + + /** + * @param {number} pFile + * @param {number} pData + * @param {number} iAmt + * @param {number} iOffsetLo + * @param {number} iOffsetHi + * @returns {number|Promise} + */ + xRead(pFile, pData, iAmt, iOffsetLo, iOffsetHi) { + const pDataArray = this.#makeDataArray(pData, iAmt); + const iOffset = delegalize(iOffsetLo, iOffsetHi); + this['log']?.('jRead', pFile, iAmt, iOffset); + return this.jRead(pFile, pDataArray, iOffset); + } + + /** + * @param {number} pFile + * @param {number} pData + * @param {number} iAmt + * @param {number} iOffsetLo + * @param {number} iOffsetHi + * @returns {number|Promise} + */ + xWrite(pFile, pData, iAmt, iOffsetLo, iOffsetHi) { + const pDataArray = this.#makeDataArray(pData, iAmt); + const iOffset = delegalize(iOffsetLo, iOffsetHi); + this['log']?.('jWrite', pFile, pDataArray, iOffset); + return this.jWrite(pFile, pDataArray, iOffset); + } + + /** + * @param {number} pFile + * @param {number} sizeLo + * @param {number} sizeHi + * @returns {number|Promise} + */ + xTruncate(pFile, sizeLo, sizeHi) { + const size = delegalize(sizeLo, sizeHi); + this['log']?.('jTruncate', pFile, size); + return this.jTruncate(pFile, size); + } + + /** + * @param {number} pFile + * @param {number} flags + * @returns {number|Promise} + */ + xSync(pFile, flags) { + this['log']?.('jSync', pFile, flags); + return this.jSync(pFile, flags); + } + + /** + * + * @param {number} pFile + * @param {number} pSize + * @returns {number|Promise} + */ + xFileSize(pFile, pSize) { + const pSizeView = this.#makeTypedDataView('BigInt64', pSize); + this['log']?.('jFileSize', pFile); + return this.jFileSize(pFile, pSizeView); + } + + /** + * @param {number} pFile + * @param {number} lockType + * @returns {number|Promise} + */ + xLock(pFile, lockType) { + this['log']?.('jLock', pFile, lockType); + return this.jLock(pFile, lockType); + } + + /** + * @param {number} pFile + * @param {number} lockType + * @returns {number|Promise} + */ + xUnlock(pFile, lockType) { + this['log']?.('jUnlock', pFile, lockType); + return this.jUnlock(pFile, lockType); + } + + /** + * @param {number} pFile + * @param {number} pResOut + * @returns {number|Promise} + */ + xCheckReservedLock(pFile, pResOut) { + const pResOutView = this.#makeTypedDataView('Int32', pResOut); + this['log']?.('jCheckReservedLock', pFile); + return this.jCheckReservedLock(pFile, pResOutView); + } + + /** + * @param {number} pFile + * @param {number} op + * @param {number} pArg + * @returns {number|Promise} + */ + xFileControl(pFile, op, pArg) { + const pArgView = new DataView( + this._module.HEAPU8.buffer, + this._module.HEAPU8.byteOffset + pArg); + this['log']?.('jFileControl', pFile, op, pArgView); + return this.jFileControl(pFile, op, pArgView); + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + xSectorSize(pFile) { + this['log']?.('jSectorSize', pFile); + return this.jSectorSize(pFile); + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + xDeviceCharacteristics(pFile) { + this['log']?.('jDeviceCharacteristics', pFile); + return this.jDeviceCharacteristics(pFile); + } + + /** + * Wrapped DataView for pointer arguments. + * Pointers to a single value are passed using DataView. A Proxy + * wrapper prevents use of incorrect type or endianness. + * @param {'Int32'|'BigInt64'} type + * @param {number} byteOffset + * @returns {DataView} + */ + #makeTypedDataView(type, byteOffset) { + const byteLength = type === 'Int32' ? 4 : 8; + const getter = `get${type}`; + const setter = `set${type}`; + const makeDataView = () => new DataView( + this._module.HEAPU8.buffer, + this._module.HEAPU8.byteOffset + byteOffset, + byteLength); + let dataView = makeDataView(); + return new Proxy(dataView, { + get(_, prop) { + if (dataView.buffer.byteLength === 0) { + // WebAssembly memory resize detached the buffer. + dataView = makeDataView(); + } + if (prop === getter) { + return function(byteOffset, littleEndian) { + if (!littleEndian) throw new Error('must be little endian'); + return dataView[prop](byteOffset, littleEndian); + } + } + if (prop === setter) { + return function(byteOffset, value, littleEndian) { + if (!littleEndian) throw new Error('must be little endian'); + return dataView[prop](byteOffset, value, littleEndian); + } + } + if (typeof prop === 'string' && (prop.match(/^(get)|(set)/))) { + throw new Error('invalid type'); + } + const result = dataView[prop]; + return typeof result === 'function' ? result.bind(dataView) : result; + } + }); + } + + /** + * @param {number} byteOffset + * @param {number} byteLength + */ + #makeDataArray(byteOffset, byteLength) { + let target = this._module.HEAPU8.subarray(byteOffset, byteOffset + byteLength); + return new Proxy(target, { + get: (_, prop, receiver) => { + if (target.buffer.byteLength === 0) { + // WebAssembly memory resize detached the buffer. + target = this._module.HEAPU8.subarray(byteOffset, byteOffset + byteLength); + } + const result = target[prop]; + return typeof result === 'function' ? result.bind(target) : result; + } + }); + } + + #decodeFilename(zName, flags) { + if (flags & VFS.SQLITE_OPEN_URI) { + // The first null-terminated string is the URI path. Subsequent + // strings are query parameter keys and values. + // https://www.sqlite.org/c3ref/open.html#urifilenamesinsqlite3open + let pName = zName; + let state = 1; + const charCodes = []; + while (state) { + const charCode = this._module.HEAPU8[pName++]; + if (charCode) { + charCodes.push(charCode); + } else { + if (!this._module.HEAPU8[pName]) state = null; + switch (state) { + case 1: // path + charCodes.push('?'.charCodeAt(0)); + state = 2; + break; + case 2: // key + charCodes.push('='.charCodeAt(0)); + state = 3; + break; + case 3: // value + charCodes.push('&'.charCodeAt(0)); + state = 2; + break; + } + } + } + return new TextDecoder().decode(new Uint8Array(charCodes)); + } + return zName ? this._module.UTF8ToString(zName) : null; + } +} + +// Emscripten "legalizes" 64-bit integer arguments by passing them as +// two 32-bit signed integers. +function delegalize(lo32, hi32) { + return (hi32 * 0x100000000) + lo32 + (lo32 < 0 ? 2**32 : 0); +} diff --git a/web/core/local-db/worker/wa-sqlite/src/OPFSCoopSyncVFS.js b/web/core/local-db/worker/wa-sqlite/src/OPFSCoopSyncVFS.js new file mode 100644 index 00000000000..2757ca9db9d --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/OPFSCoopSyncVFS.js @@ -0,0 +1,592 @@ +// Copyright 2024 Roy T. Hashimoto. All Rights Reserved. +import { FacadeVFS } from "./FacadeVFS.js"; +import * as VFS from "./VFS.js"; + +const DEFAULT_TEMPORARY_FILES = 10; +const LOCK_NOTIFY_INTERVAL = 1000; + +const DB_RELATED_FILE_SUFFIXES = ["", "-journal", "-wal"]; + +const finalizationRegistry = new FinalizationRegistry((releaser) => releaser()); + +class File { + /** @type {string} */ path; + /** @type {number} */ flags; + /** @type {FileSystemSyncAccessHandle} */ accessHandle; + + /** @type {PersistentFile?} */ persistentFile; + + constructor(path, flags) { + this.path = path; + this.flags = flags; + } +} + +class PersistentFile { + /** @type {FileSystemFileHandle} */ fileHandle; + /** @type {FileSystemSyncAccessHandle} */ accessHandle = null; + + // The following properties are for main database files. + + /** @type {boolean} */ isLockBusy = false; + /** @type {boolean} */ isFileLocked = false; + /** @type {boolean} */ isRequestInProgress = false; + /** @type {function} */ handleLockReleaser = null; + + /** @type {BroadcastChannel} */ handleRequestChannel; + /** @type {boolean} */ isHandleRequested = false; + + constructor(fileHandle) { + this.fileHandle = fileHandle; + } +} + +export class OPFSCoopSyncVFS extends FacadeVFS { + /** @type {Map} */ mapIdToFile = new Map(); + + lastError = null; + log = null; //function(...args) { console.log(`[${contextName}]`, ...args) }; + + /** @type {Map} */ persistentFiles = new Map(); + /** @type {Map} */ boundAccessHandles = new Map(); + /** @type {Set} */ unboundAccessHandles = new Set(); + /** @type {Set} */ accessiblePaths = new Set(); + releaser = null; + + static async create(name, module) { + const vfs = new OPFSCoopSyncVFS(name, module); + await Promise.all([vfs.isReady(), vfs.#initialize(DEFAULT_TEMPORARY_FILES)]); + return vfs; + } + + constructor(name, module) { + super(name, module); + } + + async #initialize(nTemporaryFiles) { + // Delete temporary directories no longer in use. + const root = await navigator.storage.getDirectory(); + // @ts-ignore + for await (const entry of root.values()) { + if (entry.kind === "directory" && entry.name.startsWith(".ahp-")) { + // A lock with the same name as the directory protects it from + // being deleted. + await navigator.locks.request(entry.name, { ifAvailable: true }, async (lock) => { + if (lock) { + this.log?.(`Deleting temporary directory ${entry.name}`); + await root.removeEntry(entry.name, { recursive: true }); + } else { + this.log?.(`Temporary directory ${entry.name} is in use`); + } + }); + } + } + + // Create our temporary directory. + const tmpDirName = `.ahp-${Math.random().toString(36).slice(2)}`; + this.releaser = await new Promise((resolve) => { + navigator.locks.request(tmpDirName, () => { + return new Promise((release) => { + resolve(release); + }); + }); + }); + finalizationRegistry.register(this, this.releaser); + const tmpDir = await root.getDirectoryHandle(tmpDirName, { create: true }); + + // Populate temporary directory. + for (let i = 0; i < nTemporaryFiles; i++) { + const tmpFile = await tmpDir.getFileHandle(`${i}.tmp`, { create: true }); + const tmpAccessHandle = await tmpFile.createSyncAccessHandle(); + this.unboundAccessHandles.add(tmpAccessHandle); + } + } + + /** + * @param {string?} zName + * @param {number} fileId + * @param {number} flags + * @param {DataView} pOutFlags + * @returns {number} + */ + jOpen(zName, fileId, flags, pOutFlags) { + try { + const url = new URL(zName || Math.random().toString(36).slice(2), "file://"); + const path = url.pathname; + + if (flags & VFS.SQLITE_OPEN_MAIN_DB) { + const persistentFile = this.persistentFiles.get(path); + if (persistentFile?.isRequestInProgress) { + // Should not reach here unless SQLite itself retries an open. + // Otherwise, asynchronous operations started on a previous + // open try should have completed. + return VFS.SQLITE_BUSY; + } else if (!persistentFile) { + // This is the usual starting point for opening a database. + // Register a Promise that resolves when the database and related + // files are ready to be used. + this.log?.(`creating persistent file for ${path}`); + const create = !!(flags & VFS.SQLITE_OPEN_CREATE); + this._module.retryOps.push( + (async () => { + try { + // Get the path directory handle. + let dirHandle = await navigator.storage.getDirectory(); + const directories = path.split("/").filter((d) => d); + const filename = directories.pop(); + for (const directory of directories) { + dirHandle = await dirHandle.getDirectoryHandle(directory, { create }); + } + + // Get file handles for the database and related files, + // and create persistent file instances. + for (const suffix of DB_RELATED_FILE_SUFFIXES) { + const fileHandle = await dirHandle.getFileHandle(filename + suffix, { create }); + await this.#createPersistentFile(fileHandle); + } + + // Get access handles for the files. + const file = new File(path, flags); + file.persistentFile = this.persistentFiles.get(path); + await this.#requestAccessHandle(file); + } catch (e) { + // Use an invalid persistent file to signal this error + // for the retried open. + const persistentFile = new PersistentFile(null); + this.persistentFiles.set(path, persistentFile); + console.error(e); + } + })() + ); + return VFS.SQLITE_BUSY; + } else if (!persistentFile.fileHandle) { + // The asynchronous open operation failed. + this.persistentFiles.delete(path); + return VFS.SQLITE_CANTOPEN; + } else if (!persistentFile.accessHandle) { + // This branch is reached if the database was previously opened + // and closed. + this._module.retryOps.push( + (async () => { + const file = new File(path, flags); + file.persistentFile = this.persistentFiles.get(path); + await this.#requestAccessHandle(file); + })() + ); + return VFS.SQLITE_BUSY; + } + } + + if (!this.accessiblePaths.has(path) && !(flags & VFS.SQLITE_OPEN_CREATE)) { + throw new Error(`File ${path} not found`); + } + + const file = new File(path, flags); + this.mapIdToFile.set(fileId, file); + + if (this.persistentFiles.has(path)) { + file.persistentFile = this.persistentFiles.get(path); + } else if (this.boundAccessHandles.has(path)) { + // This temporary file was previously created and closed. Reopen + // the same access handle. + file.accessHandle = this.boundAccessHandles.get(path); + } else if (this.unboundAccessHandles.size) { + // Associate an unbound access handle to this file. + file.accessHandle = this.unboundAccessHandles.values().next().value; + file.accessHandle.truncate(0); + this.unboundAccessHandles.delete(file.accessHandle); + this.boundAccessHandles.set(path, file.accessHandle); + } + this.accessiblePaths.add(path); + + pOutFlags.setInt32(0, flags, true); + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_CANTOPEN; + } + } + + /** + * @param {string} zName + * @param {number} syncDir + * @returns {number} + */ + jDelete(zName, syncDir) { + try { + const url = new URL(zName, "file://"); + const path = url.pathname; + if (this.persistentFiles.has(path)) { + const persistentFile = this.persistentFiles.get(path); + persistentFile.accessHandle.truncate(0); + } else { + this.boundAccessHandles.get(path)?.truncate(0); + } + this.accessiblePaths.delete(path); + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_DELETE; + } + } + + /** + * @param {string} zName + * @param {number} flags + * @param {DataView} pResOut + * @returns {number} + */ + jAccess(zName, flags, pResOut) { + try { + const url = new URL(zName, "file://"); + const path = url.pathname; + pResOut.setInt32(0, this.accessiblePaths.has(path) ? 1 : 0, true); + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_ACCESS; + } + } + + /** + * @param {number} fileId + * @returns {number} + */ + jClose(fileId) { + try { + const file = this.mapIdToFile.get(fileId); + this.mapIdToFile.delete(fileId); + + if (file?.flags & VFS.SQLITE_OPEN_MAIN_DB) { + if (file.persistentFile?.handleLockReleaser) { + this.#releaseAccessHandle(file); + } + } else if (file?.flags & VFS.SQLITE_OPEN_DELETEONCLOSE) { + file.accessHandle.truncate(0); + this.accessiblePaths.delete(file.path); + if (!this.persistentFiles.has(file.path)) { + this.boundAccessHandles.delete(file.path); + this.unboundAccessHandles.add(file.accessHandle); + } + } + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_CLOSE; + } + } + + /** + * @param {number} fileId + * @param {Uint8Array} pData + * @param {number} iOffset + * @returns {number} + */ + jRead(fileId, pData, iOffset) { + try { + const file = this.mapIdToFile.get(fileId); + + // On Chrome (at least), passing pData to accessHandle.read() is + // an error because pData is a Proxy of a Uint8Array. Calling + // subarray() produces a real Uint8Array and that works. + const accessHandle = file.accessHandle || file.persistentFile.accessHandle; + const bytesRead = accessHandle.read(pData.subarray(), { at: iOffset }); + + // Opening a database file performs one read without a xLock call. + if (file.flags & VFS.SQLITE_OPEN_MAIN_DB && !file.persistentFile.isFileLocked) { + this.#releaseAccessHandle(file); + } + + if (bytesRead < pData.byteLength) { + pData.fill(0, bytesRead); + return VFS.SQLITE_IOERR_SHORT_READ; + } + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_READ; + } + } + + /** + * @param {number} fileId + * @param {Uint8Array} pData + * @param {number} iOffset + * @returns {number} + */ + jWrite(fileId, pData, iOffset) { + try { + const file = this.mapIdToFile.get(fileId); + + // On Chrome (at least), passing pData to accessHandle.write() is + // an error because pData is a Proxy of a Uint8Array. Calling + // subarray() produces a real Uint8Array and that works. + const accessHandle = file.accessHandle || file.persistentFile.accessHandle; + const nBytes = accessHandle.write(pData.subarray(), { at: iOffset }); + if (nBytes !== pData.byteLength) throw new Error("short write"); + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_WRITE; + } + } + + /** + * @param {number} fileId + * @param {number} iSize + * @returns {number} + */ + jTruncate(fileId, iSize) { + try { + const file = this.mapIdToFile.get(fileId); + const accessHandle = file.accessHandle || file.persistentFile.accessHandle; + accessHandle.truncate(iSize); + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_TRUNCATE; + } + } + + /** + * @param {number} fileId + * @param {number} flags + * @returns {number} + */ + jSync(fileId, flags) { + try { + const file = this.mapIdToFile.get(fileId); + const accessHandle = file.accessHandle || file.persistentFile.accessHandle; + accessHandle.flush(); + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_FSYNC; + } + } + + /** + * @param {number} fileId + * @param {DataView} pSize64 + * @returns {number} + */ + jFileSize(fileId, pSize64) { + try { + const file = this.mapIdToFile.get(fileId); + const accessHandle = file.accessHandle || file.persistentFile.accessHandle; + const size = accessHandle.getSize(); + pSize64.setBigInt64(0, BigInt(size), true); + return VFS.SQLITE_OK; + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR_FSTAT; + } + } + + /** + * @param {number} fileId + * @param {number} lockType + * @returns {number} + */ + jLock(fileId, lockType) { + const file = this.mapIdToFile.get(fileId); + if (file.persistentFile.isRequestInProgress) { + file.persistentFile.isLockBusy = true; + return VFS.SQLITE_BUSY; + } + + file.persistentFile.isFileLocked = true; + if (!file.persistentFile.handleLockReleaser) { + // Start listening for notifications from other connections. + // This is before we actually get access handles, but waiting to + // listen until then allows a race condition where notifications + // are missed. + file.persistentFile.handleRequestChannel.onmessage = () => { + this.log?.(`received notification for ${file.path}`); + if (file.persistentFile.isFileLocked) { + // We're still using the access handle, so mark it to be + // released when we're done. + file.persistentFile.isHandleRequested = true; + } else { + // Release the access handles immediately. + this.#releaseAccessHandle(file); + } + file.persistentFile.handleRequestChannel.onmessage = null; + }; + + this.#requestAccessHandle(file); + this.log?.("returning SQLITE_BUSY"); + file.persistentFile.isLockBusy = true; + return VFS.SQLITE_BUSY; + } + file.persistentFile.isLockBusy = false; + return VFS.SQLITE_OK; + } + + /** + * @param {number} fileId + * @param {number} lockType + * @returns {number} + */ + jUnlock(fileId, lockType) { + const file = this.mapIdToFile.get(fileId); + if (lockType === VFS.SQLITE_LOCK_NONE) { + // Don't change any state if this unlock is because xLock returned + // SQLITE_BUSY. + if (!file.persistentFile.isLockBusy) { + if (file.persistentFile.isHandleRequested) { + // Another connection wants the access handle. + this.#releaseAccessHandle(file); + this.isHandleRequested = false; + } + file.persistentFile.isFileLocked = false; + } + } + return VFS.SQLITE_OK; + } + + /** + * @param {number} fileId + * @param {number} op + * @param {DataView} pArg + * @returns {number|Promise} + */ + jFileControl(fileId, op, pArg) { + try { + const file = this.mapIdToFile.get(fileId); + switch (op) { + case VFS.SQLITE_FCNTL_PRAGMA: + const key = extractString(pArg, 4); + const value = extractString(pArg, 8); + this.log?.("xFileControl", file.path, "PRAGMA", key, value); + switch (key.toLowerCase()) { + case "journal_mode": + if (value && !["off", "memory", "delete", "wal"].includes(value.toLowerCase())) { + throw new Error('journal_mode must be "off", "memory", "delete", or "wal"'); + } + break; + } + break; + } + } catch (e) { + this.lastError = e; + return VFS.SQLITE_IOERR; + } + return VFS.SQLITE_NOTFOUND; + } + + /** + * @param {Uint8Array} zBuf + * @returns + */ + jGetLastError(zBuf) { + if (this.lastError) { + console.error(this.lastError); + const outputArray = zBuf.subarray(0, zBuf.byteLength - 1); + const { written } = new TextEncoder().encodeInto(this.lastError.message, outputArray); + zBuf[written] = 0; + } + return VFS.SQLITE_OK; + } + + /** + * @param {FileSystemFileHandle} fileHandle + * @returns {Promise} + */ + async #createPersistentFile(fileHandle) { + const persistentFile = new PersistentFile(fileHandle); + const root = await navigator.storage.getDirectory(); + const relativePath = await root.resolve(fileHandle); + const path = `/${relativePath.join("/")}`; + persistentFile.handleRequestChannel = new BroadcastChannel(`ahp:${path}`); + this.persistentFiles.set(path, persistentFile); + + const f = await fileHandle.getFile(); + if (f.size) { + this.accessiblePaths.add(path); + } + return persistentFile; + } + + /** + * @param {File} file + */ + #requestAccessHandle(file) { + console.assert(!file.persistentFile.handleLockReleaser); + if (!file.persistentFile.isRequestInProgress) { + file.persistentFile.isRequestInProgress = true; + this._module.retryOps.push( + (async () => { + // Acquire the Web Lock. + file.persistentFile.handleLockReleaser = await this.#acquireLock(file.persistentFile); + + // Get access handles for the database and releated files in parallel. + this.log?.(`creating access handles for ${file.path}`); + await Promise.all( + DB_RELATED_FILE_SUFFIXES.map(async (suffix) => { + const persistentFile = this.persistentFiles.get(file.path + suffix); + if (persistentFile) { + persistentFile.accessHandle = await persistentFile.fileHandle.createSyncAccessHandle(); + } + }) + ); + file.persistentFile.isRequestInProgress = false; + })() + ); + return this._module.retryOps.at(-1); + } + return Promise.resolve(); + } + + /** + * @param {File} file + */ + async #releaseAccessHandle(file) { + DB_RELATED_FILE_SUFFIXES.forEach(async (suffix) => { + const persistentFile = this.persistentFiles.get(file.path + suffix); + if (persistentFile) { + persistentFile.accessHandle?.close(); + persistentFile.accessHandle = null; + } + }); + this.log?.(`access handles closed for ${file.path}`); + + file.persistentFile.handleLockReleaser?.(); + file.persistentFile.handleLockReleaser = null; + this.log?.(`lock released for ${file.path}`); + } + + /** + * @param {PersistentFile} persistentFile + * @returns {Promise} lock releaser + */ + #acquireLock(persistentFile) { + return new Promise((resolve) => { + // Tell other connections we want the access handle. + const lockName = persistentFile.handleRequestChannel.name; + const notify = () => { + this.log?.(`notifying for ${lockName}`); + persistentFile.handleRequestChannel.postMessage(null); + }; + const notifyId = setInterval(notify, LOCK_NOTIFY_INTERVAL); + setTimeout(notify); + + this.log?.(`lock requested: ${lockName}`); + navigator.locks.request(lockName, (lock) => { + // We have the lock. Stop asking other connections for it. + this.log?.(`lock acquired: ${lockName}`, lock); + clearInterval(notifyId); + return new Promise(resolve); + }); + }); + } +} + +function extractString(dataView, offset) { + const p = dataView.getUint32(offset, true); + if (p) { + const chars = new Uint8Array(dataView.buffer, p); + return new TextDecoder().decode(chars.subarray(0, chars.indexOf(0))); + } + return null; +} diff --git a/web/core/local-db/worker/wa-sqlite/src/VFS.js b/web/core/local-db/worker/wa-sqlite/src/VFS.js new file mode 100644 index 00000000000..12966b9cfbe --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/VFS.js @@ -0,0 +1,222 @@ +// Copyright 2024 Roy T. Hashimoto. All Rights Reserved. +import * as VFS from './sqlite-constants.js'; +export * from './sqlite-constants.js'; + +const DEFAULT_SECTOR_SIZE = 512; + +// Base class for a VFS. +export class Base { + name; + mxPathname = 64; + _module; + + /** + * @param {string} name + * @param {object} module + */ + constructor(name, module) { + this.name = name; + this._module = module; + } + + /** + * @returns {void|Promise} + */ + close() { + } + + /** + * @returns {boolean|Promise} + */ + isReady() { + return true; + } + + /** + * Overload in subclasses to indicate which methods are asynchronous. + * @param {string} methodName + * @returns {boolean} + */ + hasAsyncMethod(methodName) { + return false; + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} pFile + * @param {number} flags + * @param {number} pOutFlags + * @returns {number|Promise} + */ + xOpen(pVfs, zName, pFile, flags, pOutFlags) { + return VFS.SQLITE_CANTOPEN; + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} syncDir + * @returns {number|Promise} + */ + xDelete(pVfs, zName, syncDir) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} flags + * @param {number} pResOut + * @returns {number|Promise} + */ + xAccess(pVfs, zName, flags, pResOut) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pVfs + * @param {number} zName + * @param {number} nOut + * @param {number} zOut + * @returns {number|Promise} + */ + xFullPathname(pVfs, zName, nOut, zOut) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pVfs + * @param {number} nBuf + * @param {number} zBuf + * @returns {number|Promise} + */ + xGetLastError(pVfs, nBuf, zBuf) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + xClose(pFile) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} pData + * @param {number} iAmt + * @param {number} iOffsetLo + * @param {number} iOffsetHi + * @returns {number|Promise} + */ + xRead(pFile, pData, iAmt, iOffsetLo, iOffsetHi) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} pData + * @param {number} iAmt + * @param {number} iOffsetLo + * @param {number} iOffsetHi + * @returns {number|Promise} + */ + xWrite(pFile, pData, iAmt, iOffsetLo, iOffsetHi) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} sizeLo + * @param {number} sizeHi + * @returns {number|Promise} + */ + xTruncate(pFile, sizeLo, sizeHi) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} flags + * @returns {number|Promise} + */ + xSync(pFile, flags) { + return VFS.SQLITE_OK; + } + + /** + * + * @param {number} pFile + * @param {number} pSize + * @returns {number|Promise} + */ + xFileSize(pFile, pSize) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} lockType + * @returns {number|Promise} + */ + xLock(pFile, lockType) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} lockType + * @returns {number|Promise} + */ + xUnlock(pFile, lockType) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} pResOut + * @returns {number|Promise} + */ + xCheckReservedLock(pFile, pResOut) { + return VFS.SQLITE_OK; + } + + /** + * @param {number} pFile + * @param {number} op + * @param {number} pArg + * @returns {number|Promise} + */ + xFileControl(pFile, op, pArg) { + return VFS.SQLITE_NOTFOUND; + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + xSectorSize(pFile) { + return DEFAULT_SECTOR_SIZE; + } + + /** + * @param {number} pFile + * @returns {number|Promise} + */ + xDeviceCharacteristics(pFile) { + return 0; + } +} + +export const FILE_TYPE_MASK = [ + VFS.SQLITE_OPEN_MAIN_DB, + VFS.SQLITE_OPEN_MAIN_JOURNAL, + VFS.SQLITE_OPEN_TEMP_DB, + VFS.SQLITE_OPEN_TEMP_JOURNAL, + VFS.SQLITE_OPEN_TRANSIENT_DB, + VFS.SQLITE_OPEN_SUBJOURNAL, + VFS.SQLITE_OPEN_SUPER_JOURNAL, + VFS.SQLITE_OPEN_WAL +].reduce((mask, element) => mask | element); \ No newline at end of file diff --git a/web/core/local-db/worker/wa-sqlite/src/sqlite-api.js b/web/core/local-db/worker/wa-sqlite/src/sqlite-api.js new file mode 100644 index 00000000000..500980b4ecd --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/sqlite-api.js @@ -0,0 +1,899 @@ +// Copyright 2021 Roy T. Hashimoto. All Rights Reserved. + +import * as SQLite from "./sqlite-constants.js"; +export * from "./sqlite-constants.js"; + +const MAX_INT64 = 0x7fffffffffffffffn; +const MIN_INT64 = -0x8000000000000000n; + +const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor; + +export class SQLiteError extends Error { + constructor(message, code) { + super(message); + this.code = code; + } +} + +const async = true; + +/** + * Builds a Javascript API from the Emscripten module. This API is still + * low-level and closely corresponds to the C API exported by the module, + * but differs in some specifics like throwing exceptions on errors. + * @param {*} Module SQLite Emscripten module + * @returns {SQLiteAPI} + */ +export function Factory(Module) { + /** @type {SQLiteAPI} */ const sqlite3 = {}; + + Module.retryOps = []; + const sqliteFreeAddress = Module._getSqliteFree(); + + // Allocate some space for 32-bit returned values. + const tmp = Module._malloc(8); + const tmpPtr = [tmp, tmp + 4]; + + // Convert a JS string to a C string. sqlite3_malloc is used to allocate + // memory (use sqlite3_free to deallocate). + function createUTF8(s) { + if (typeof s !== "string") return 0; + const utf8 = new TextEncoder().encode(s); + const zts = Module._sqlite3_malloc(utf8.byteLength + 1); + Module.HEAPU8.set(utf8, zts); + Module.HEAPU8[zts + utf8.byteLength] = 0; + return zts; + } + + /** + * Concatenate 32-bit numbers into a 64-bit (signed) BigInt. + * @param {number} lo32 + * @param {number} hi32 + * @returns {bigint} + */ + function cvt32x2ToBigInt(lo32, hi32) { + return (BigInt(hi32) << 32n) | (BigInt(lo32) & 0xffffffffn); + } + + /** + * Concatenate 32-bit numbers and return as number or BigInt, depending + * on the value. + * @param {number} lo32 + * @param {number} hi32 + * @returns {number|bigint} + */ + const cvt32x2AsSafe = (function () { + const hiMax = BigInt(Number.MAX_SAFE_INTEGER) >> 32n; + const hiMin = BigInt(Number.MIN_SAFE_INTEGER) >> 32n; + + return function (lo32, hi32) { + if (hi32 > hiMax || hi32 < hiMin) { + // Can't be expressed as a Number so use BigInt. + return cvt32x2ToBigInt(lo32, hi32); + } else { + // Combine the upper and lower 32-bit numbers. The complication is + // that lo32 is a signed integer which makes manipulating its bits + // a little tricky - the sign bit gets handled separately. + return hi32 * 0x100000000 + (lo32 & 0x7fffffff) - (lo32 & 0x80000000); + } + }; + })(); + + const databases = new Set(); + function verifyDatabase(db) { + if (!databases.has(db)) { + throw new SQLiteError("not a database", SQLite.SQLITE_MISUSE); + } + } + + const mapStmtToDB = new Map(); + function verifyStatement(stmt) { + if (!mapStmtToDB.has(stmt)) { + throw new SQLiteError("not a statement", SQLite.SQLITE_MISUSE); + } + } + + sqlite3.bind_collection = function (stmt, bindings) { + verifyStatement(stmt); + const isArray = Array.isArray(bindings); + const nBindings = sqlite3.bind_parameter_count(stmt); + for (let i = 1; i <= nBindings; ++i) { + const key = isArray ? i - 1 : sqlite3.bind_parameter_name(stmt, i); + const value = bindings[key]; + if (value !== undefined) { + sqlite3.bind(stmt, i, value); + } + } + return SQLite.SQLITE_OK; + }; + + sqlite3.bind = function (stmt, i, value) { + verifyStatement(stmt); + switch (typeof value) { + case "number": + if (value === (value | 0)) { + return sqlite3.bind_int(stmt, i, value); + } else { + return sqlite3.bind_double(stmt, i, value); + } + case "string": + return sqlite3.bind_text(stmt, i, value); + default: + if (value instanceof Uint8Array || Array.isArray(value)) { + return sqlite3.bind_blob(stmt, i, value); + } else if (value === null) { + return sqlite3.bind_null(stmt, i); + } else if (typeof value === "bigint") { + return sqlite3.bind_int64(stmt, i, value); + } else if (value === undefined) { + // Existing binding (or NULL) will be used. + return SQLite.SQLITE_NOTICE; + } else { + console.warn("unknown binding converted to null", value); + return sqlite3.bind_null(stmt, i); + } + } + }; + + sqlite3.bind_blob = (function () { + const fname = "sqlite3_bind_blob"; + const f = Module.cwrap(fname, ...decl("nnnnn:n")); + return function (stmt, i, value) { + verifyStatement(stmt); + // @ts-ignore + const byteLength = value.byteLength ?? value.length; + const ptr = Module._sqlite3_malloc(byteLength); + Module.HEAPU8.subarray(ptr).set(value); + const result = f(stmt, i, ptr, byteLength, sqliteFreeAddress); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.bind_parameter_count = (function () { + const fname = "sqlite3_bind_parameter_count"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (stmt) { + verifyStatement(stmt); + const result = f(stmt); + return result; + }; + })(); + + sqlite3.bind_double = (function () { + const fname = "sqlite3_bind_double"; + const f = Module.cwrap(fname, ...decl("nnn:n")); + return function (stmt, i, value) { + verifyStatement(stmt); + const result = f(stmt, i, value); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.bind_int = (function () { + const fname = "sqlite3_bind_int"; + const f = Module.cwrap(fname, ...decl("nnn:n")); + return function (stmt, i, value) { + verifyStatement(stmt); + if (value > 0x7fffffff || value < -0x80000000) return SQLite.SQLITE_RANGE; + + const result = f(stmt, i, value); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.bind_int64 = (function () { + const fname = "sqlite3_bind_int64"; + const f = Module.cwrap(fname, ...decl("nnnn:n")); + return function (stmt, i, value) { + verifyStatement(stmt); + if (value > MAX_INT64 || value < MIN_INT64) return SQLite.SQLITE_RANGE; + + const lo32 = value & 0xffffffffn; + const hi32 = value >> 32n; + const result = f(stmt, i, Number(lo32), Number(hi32)); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.bind_null = (function () { + const fname = "sqlite3_bind_null"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (stmt, i) { + verifyStatement(stmt); + const result = f(stmt, i); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.bind_parameter_name = (function () { + const fname = "sqlite3_bind_parameter_name"; + const f = Module.cwrap(fname, ...decl("n:s")); + return function (stmt, i) { + verifyStatement(stmt); + const result = f(stmt, i); + return result; + }; + })(); + + sqlite3.bind_text = (function () { + const fname = "sqlite3_bind_text"; + const f = Module.cwrap(fname, ...decl("nnnnn:n")); + return function (stmt, i, value) { + verifyStatement(stmt); + const ptr = createUTF8(value); + const result = f(stmt, i, ptr, -1, sqliteFreeAddress); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.changes = (function () { + const fname = "sqlite3_changes"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (db) { + verifyDatabase(db); + const result = f(db); + return result; + }; + })(); + + sqlite3.clear_bindings = (function () { + const fname = "sqlite3_clear_bindings"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (stmt) { + verifyStatement(stmt); + const result = f(stmt); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.close = (function () { + const fname = "sqlite3_close"; + const f = Module.cwrap(fname, ...decl("n:n"), { async }); + return async function (db) { + verifyDatabase(db); + const result = await f(db); + databases.delete(db); + return check(fname, result, db); + }; + })(); + + sqlite3.column = function (stmt, iCol) { + verifyStatement(stmt); + const type = sqlite3.column_type(stmt, iCol); + switch (type) { + case SQLite.SQLITE_BLOB: + return sqlite3.column_blob(stmt, iCol); + case SQLite.SQLITE_FLOAT: + return sqlite3.column_double(stmt, iCol); + case SQLite.SQLITE_INTEGER: + const lo32 = sqlite3.column_int(stmt, iCol); + const hi32 = Module.getTempRet0(); + return cvt32x2AsSafe(lo32, hi32); + case SQLite.SQLITE_NULL: + return null; + case SQLite.SQLITE_TEXT: + return sqlite3.column_text(stmt, iCol); + default: + throw new SQLiteError("unknown type", type); + } + }; + + sqlite3.column_blob = (function () { + const fname = "sqlite3_column_blob"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (stmt, iCol) { + verifyStatement(stmt); + const nBytes = sqlite3.column_bytes(stmt, iCol); + const address = f(stmt, iCol); + const result = Module.HEAPU8.subarray(address, address + nBytes); + return result; + }; + })(); + + sqlite3.column_bytes = (function () { + const fname = "sqlite3_column_bytes"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (stmt, iCol) { + verifyStatement(stmt); + const result = f(stmt, iCol); + return result; + }; + })(); + + sqlite3.column_count = (function () { + const fname = "sqlite3_column_count"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (stmt) { + verifyStatement(stmt); + const result = f(stmt); + return result; + }; + })(); + + sqlite3.column_double = (function () { + const fname = "sqlite3_column_double"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (stmt, iCol) { + verifyStatement(stmt); + const result = f(stmt, iCol); + return result; + }; + })(); + + sqlite3.column_int = (function () { + // Retrieve int64 but use only the lower 32 bits. The upper 32-bits are + // accessible with Module.getTempRet0(). + const fname = "sqlite3_column_int64"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (stmt, iCol) { + verifyStatement(stmt); + const result = f(stmt, iCol); + return result; + }; + })(); + + sqlite3.column_int64 = (function () { + const fname = "sqlite3_column_int64"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (stmt, iCol) { + verifyStatement(stmt); + const lo32 = f(stmt, iCol); + const hi32 = Module.getTempRet0(); + const result = cvt32x2ToBigInt(lo32, hi32); + return result; + }; + })(); + + sqlite3.column_name = (function () { + const fname = "sqlite3_column_name"; + const f = Module.cwrap(fname, ...decl("nn:s")); + return function (stmt, iCol) { + verifyStatement(stmt); + const result = f(stmt, iCol); + return result; + }; + })(); + + sqlite3.column_names = function (stmt) { + const columns = []; + const nColumns = sqlite3.column_count(stmt); + for (let i = 0; i < nColumns; ++i) { + columns.push(sqlite3.column_name(stmt, i)); + } + return columns; + }; + + sqlite3.column_text = (function () { + const fname = "sqlite3_column_text"; + const f = Module.cwrap(fname, ...decl("nn:s")); + return function (stmt, iCol) { + verifyStatement(stmt); + const result = f(stmt, iCol); + return result; + }; + })(); + + sqlite3.column_type = (function () { + const fname = "sqlite3_column_type"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (stmt, iCol) { + verifyStatement(stmt); + const result = f(stmt, iCol); + return result; + }; + })(); + + sqlite3.create_function = function (db, zFunctionName, nArg, eTextRep, pApp, xFunc, xStep, xFinal) { + verifyDatabase(db); + + // Convert SQLite callback arguments to JavaScript-friendly arguments. + function adapt(f) { + return f instanceof AsyncFunction + ? async (ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n)) + : (ctx, n, values) => f(ctx, Module.HEAP32.subarray(values / 4, values / 4 + n)); + } + + const result = Module.create_function( + db, + zFunctionName, + nArg, + eTextRep, + pApp, + xFunc && adapt(xFunc), + xStep && adapt(xStep), + xFinal + ); + return check("sqlite3_create_function", result, db); + }; + + sqlite3.data_count = (function () { + const fname = "sqlite3_data_count"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (stmt) { + verifyStatement(stmt); + const result = f(stmt); + return result; + }; + })(); + + sqlite3.exec = async function (db, sql, callback) { + for await (const stmt of sqlite3.statements(db, sql)) { + let columns; + while ((await sqlite3.step(stmt)) === SQLite.SQLITE_ROW) { + if (callback) { + columns = columns ?? sqlite3.column_names(stmt); + const row = sqlite3.row(stmt); + await callback(row, columns); + } + } + } + return SQLite.SQLITE_OK; + }; + + sqlite3.finalize = (function () { + const fname = "sqlite3_finalize"; + const f = Module.cwrap(fname, ...decl("n:n"), { async }); + return async function (stmt) { + const result = await f(stmt); + mapStmtToDB.delete(stmt); + + // Don't throw on error here. Typically the error has already been + // thrown and finalize() is part of the cleanup. + return result; + }; + })(); + + sqlite3.get_autocommit = (function () { + const fname = "sqlite3_get_autocommit"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (db) { + const result = f(db); + return result; + }; + })(); + + sqlite3.libversion = (function () { + const fname = "sqlite3_libversion"; + const f = Module.cwrap(fname, ...decl(":s")); + return function () { + const result = f(); + return result; + }; + })(); + + sqlite3.libversion_number = (function () { + const fname = "sqlite3_libversion_number"; + const f = Module.cwrap(fname, ...decl(":n")); + return function () { + const result = f(); + return result; + }; + })(); + + sqlite3.limit = (function () { + const fname = "sqlite3_limit"; + const f = Module.cwrap(fname, ...decl("nnn:n")); + return function (db, id, newVal) { + const result = f(db, id, newVal); + return result; + }; + })(); + + sqlite3.open_v2 = (function () { + const fname = "sqlite3_open_v2"; + const f = Module.cwrap(fname, ...decl("snnn:n"), { async }); + return async function (zFilename, flags, zVfs) { + flags = flags || SQLite.SQLITE_OPEN_CREATE | SQLite.SQLITE_OPEN_READWRITE; + zVfs = createUTF8(zVfs); + try { + // Allow retry operations. + const rc = await retry(() => f(zFilename, tmpPtr[0], flags, zVfs)); + + const db = Module.getValue(tmpPtr[0], "*"); + databases.add(db); + + Module.ccall("RegisterExtensionFunctions", "void", ["number"], [db]); + check(fname, rc); + return db; + } finally { + Module._sqlite3_free(zVfs); + } + }; + })(); + + sqlite3.progress_handler = function (db, nProgressOps, handler, userData) { + verifyDatabase(db); + Module.progress_handler(db, nProgressOps, handler, userData); + }; + + sqlite3.reset = (function () { + const fname = "sqlite3_reset"; + const f = Module.cwrap(fname, ...decl("n:n"), { async }); + return async function (stmt) { + verifyStatement(stmt); + const result = await f(stmt); + return check(fname, result, mapStmtToDB.get(stmt)); + }; + })(); + + sqlite3.result = function (context, value) { + switch (typeof value) { + case "number": + if (value === (value | 0)) { + sqlite3.result_int(context, value); + } else { + sqlite3.result_double(context, value); + } + break; + case "string": + sqlite3.result_text(context, value); + break; + default: + if (value instanceof Uint8Array || Array.isArray(value)) { + sqlite3.result_blob(context, value); + } else if (value === null) { + sqlite3.result_null(context); + } else if (typeof value === "bigint") { + return sqlite3.result_int64(context, value); + } else { + console.warn("unknown result converted to null", value); + sqlite3.result_null(context); + } + break; + } + }; + + sqlite3.result_blob = (function () { + const fname = "sqlite3_result_blob"; + const f = Module.cwrap(fname, ...decl("nnnn:n")); + return function (context, value) { + // @ts-ignore + const byteLength = value.byteLength ?? value.length; + const ptr = Module._sqlite3_malloc(byteLength); + Module.HEAPU8.subarray(ptr).set(value); + f(context, ptr, byteLength, sqliteFreeAddress); // void return + }; + })(); + + sqlite3.result_double = (function () { + const fname = "sqlite3_result_double"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (context, value) { + f(context, value); // void return + }; + })(); + + sqlite3.result_int = (function () { + const fname = "sqlite3_result_int"; + const f = Module.cwrap(fname, ...decl("nn:n")); + return function (context, value) { + f(context, value); // void return + }; + })(); + + sqlite3.result_int64 = (function () { + const fname = "sqlite3_result_int64"; + const f = Module.cwrap(fname, ...decl("nnn:n")); + return function (context, value) { + if (value > MAX_INT64 || value < MIN_INT64) return SQLite.SQLITE_RANGE; + + const lo32 = value & 0xffffffffn; + const hi32 = value >> 32n; + f(context, Number(lo32), Number(hi32)); // void return + }; + })(); + + sqlite3.result_null = (function () { + const fname = "sqlite3_result_null"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (context) { + f(context); // void return + }; + })(); + + sqlite3.result_text = (function () { + const fname = "sqlite3_result_text"; + const f = Module.cwrap(fname, ...decl("nnnn:n")); + return function (context, value) { + const ptr = createUTF8(value); + f(context, ptr, -1, sqliteFreeAddress); // void return + }; + })(); + + sqlite3.row = function (stmt) { + const row = []; + const nColumns = sqlite3.data_count(stmt); + for (let i = 0; i < nColumns; ++i) { + const value = sqlite3.column(stmt, i); + + // Copy blob if aliasing volatile WebAssembly memory. This avoids an + // unnecessary copy if users monkey patch column_blob to copy. + // @ts-ignore + row.push(value?.buffer === Module.HEAPU8.buffer ? value.slice() : value); + } + return row; + }; + + sqlite3.set_authorizer = function (db, xAuth, pApp) { + verifyDatabase(db); + + // Convert SQLite callback arguments to JavaScript-friendly arguments. + function cvtArgs(_, iAction, p3, p4, p5, p6) { + return [ + _, + iAction, + Module.UTF8ToString(p3), + Module.UTF8ToString(p4), + Module.UTF8ToString(p5), + Module.UTF8ToString(p6), + ]; + } + function adapt(f) { + return f instanceof AsyncFunction + ? async (_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)) + : (_, iAction, p3, p4, p5, p6) => f(...cvtArgs(_, iAction, p3, p4, p5, p6)); + } + + const result = Module.set_authorizer(db, adapt(xAuth), pApp); + return check("sqlite3_set_authorizer", result, db); + }; + + sqlite3.sql = (function () { + const fname = "sqlite3_sql"; + const f = Module.cwrap(fname, ...decl("n:s")); + return function (stmt) { + verifyStatement(stmt); + const result = f(stmt); + return result; + }; + })(); + + sqlite3.statements = function (db, sql, options = {}) { + const prepare = Module.cwrap( + "sqlite3_prepare_v3", + "number", + ["number", "number", "number", "number", "number", "number"], + { async: true } + ); + + return (async function* () { + const onFinally = []; + try { + // Encode SQL string to UTF-8. + const utf8 = new TextEncoder().encode(sql); + + // Copy encoded string to WebAssembly memory. The SQLite docs say + // zero-termination is a minor optimization so add room for that. + // Also add space for the statement handle and SQL tail pointer. + const allocSize = utf8.byteLength - (utf8.byteLength % 4) + 12; + const pzHead = Module._sqlite3_malloc(allocSize); + const pzEnd = pzHead + utf8.byteLength + 1; + onFinally.push(() => Module._sqlite3_free(pzHead)); + Module.HEAPU8.set(utf8, pzHead); + Module.HEAPU8[pzEnd - 1] = 0; + + // Use extra space for the statement handle and SQL tail pointer. + const pStmt = pzHead + allocSize - 8; + const pzTail = pzHead + allocSize - 4; + + // Ensure that statement handles are not leaked. + let stmt; + function maybeFinalize() { + if (stmt && !options.unscoped) { + sqlite3.finalize(stmt); + } + stmt = 0; + } + onFinally.push(maybeFinalize); + + // Loop over statements. + Module.setValue(pzTail, pzHead, "*"); + do { + // Reclaim resources for the previous iteration. + maybeFinalize(); + + // Call sqlite3_prepare_v3() for the next statement. + // Allow retry operations. + const zTail = Module.getValue(pzTail, "*"); + const rc = await retry(() => { + return prepare(db, zTail, pzEnd - pzTail, options.flags || 0, pStmt, pzTail); + }); + + if (rc !== SQLite.SQLITE_OK) { + check("sqlite3_prepare_v3", rc, db); + } + + stmt = Module.getValue(pStmt, "*"); + if (stmt) { + mapStmtToDB.set(stmt, db); + yield stmt; + } + } while (stmt); + } finally { + while (onFinally.length) { + onFinally.pop()(); + } + } + })(); + }; + + sqlite3.step = (function () { + const fname = "sqlite3_step"; + const f = Module.cwrap(fname, ...decl("n:n"), { async }); + return async function (stmt) { + verifyStatement(stmt); + + // Allow retry operations. + const rc = await retry(() => f(stmt)); + + return check(fname, rc, mapStmtToDB.get(stmt), [SQLite.SQLITE_ROW, SQLite.SQLITE_DONE]); + }; + })(); + + sqlite3.update_hook = function (db, xUpdateHook) { + verifyDatabase(db); + + // Convert SQLite callback arguments to JavaScript-friendly arguments. + function cvtArgs(iUpdateType, dbName, tblName, lo32, hi32) { + return [iUpdateType, Module.UTF8ToString(dbName), Module.UTF8ToString(tblName), cvt32x2ToBigInt(lo32, hi32)]; + } + function adapt(f) { + return f instanceof AsyncFunction + ? async (iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)) + : (iUpdateType, dbName, tblName, lo32, hi32) => f(...cvtArgs(iUpdateType, dbName, tblName, lo32, hi32)); + } + + Module.update_hook(db, adapt(xUpdateHook)); + }; + + sqlite3.value = function (pValue) { + const type = sqlite3.value_type(pValue); + switch (type) { + case SQLite.SQLITE_BLOB: + return sqlite3.value_blob(pValue); + case SQLite.SQLITE_FLOAT: + return sqlite3.value_double(pValue); + case SQLite.SQLITE_INTEGER: + const lo32 = sqlite3.value_int(pValue); + const hi32 = Module.getTempRet0(); + return cvt32x2AsSafe(lo32, hi32); + case SQLite.SQLITE_NULL: + return null; + case SQLite.SQLITE_TEXT: + return sqlite3.value_text(pValue); + default: + throw new SQLiteError("unknown type", type); + } + }; + + sqlite3.value_blob = (function () { + const fname = "sqlite3_value_blob"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (pValue) { + const nBytes = sqlite3.value_bytes(pValue); + const address = f(pValue); + const result = Module.HEAPU8.subarray(address, address + nBytes); + return result; + }; + })(); + + sqlite3.value_bytes = (function () { + const fname = "sqlite3_value_bytes"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (pValue) { + const result = f(pValue); + return result; + }; + })(); + + sqlite3.value_double = (function () { + const fname = "sqlite3_value_double"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (pValue) { + const result = f(pValue); + return result; + }; + })(); + + sqlite3.value_int = (function () { + const fname = "sqlite3_value_int64"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (pValue) { + const result = f(pValue); + return result; + }; + })(); + + sqlite3.value_int64 = (function () { + const fname = "sqlite3_value_int64"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (pValue) { + const lo32 = f(pValue); + const hi32 = Module.getTempRet0(); + const result = cvt32x2ToBigInt(lo32, hi32); + return result; + }; + })(); + + sqlite3.value_text = (function () { + const fname = "sqlite3_value_text"; + const f = Module.cwrap(fname, ...decl("n:s")); + return function (pValue) { + const result = f(pValue); + return result; + }; + })(); + + sqlite3.value_type = (function () { + const fname = "sqlite3_value_type"; + const f = Module.cwrap(fname, ...decl("n:n")); + return function (pValue) { + const result = f(pValue); + return result; + }; + })(); + + sqlite3.vfs_register = function (vfs, makeDefault) { + const result = Module.vfs_register(vfs, makeDefault); + return check("sqlite3_vfs_register", result); + }; + + function check(fname, result, db = null, allowed = [SQLite.SQLITE_OK]) { + if (allowed.includes(result)) return result; + const message = db ? Module.ccall("sqlite3_errmsg", "string", ["number"], [db]) : fname; + throw new SQLiteError(message, result); + } + + // This function is used to automatically retry failed calls that + // have pending retry operations that should allow the retry to + // succeed. + async function retry(f) { + let rc; + do { + // Wait for all pending retry operations to complete. This is + // normally empty on the first loop iteration. + if (Module.retryOps.length) { + await Promise.all(Module.retryOps); + Module.retryOps = []; + } + + rc = await f(); + + // Retry on failure with new pending retry operations. + } while (rc && Module.retryOps.length); + return rc; + } + + return sqlite3; +} + +// Helper function to use a more compact signature specification. +function decl(s) { + const result = []; + const m = s.match(/([ns@]*):([nsv@])/); + switch (m[2]) { + case "n": + result.push("number"); + break; + case "s": + result.push("string"); + break; + case "v": + result.push(null); + break; + } + + const args = []; + for (let c of m[1]) { + switch (c) { + case "n": + args.push("number"); + break; + case "s": + args.push("string"); + break; + } + } + result.push(args); + return result; +} diff --git a/web/core/local-db/worker/wa-sqlite/src/sqlite-constants.js b/web/core/local-db/worker/wa-sqlite/src/sqlite-constants.js new file mode 100644 index 00000000000..3878b169631 --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/sqlite-constants.js @@ -0,0 +1,275 @@ +// Primary result codes. +// https://www.sqlite.org/rescode.html +export const SQLITE_OK = 0; +export const SQLITE_ERROR = 1; +export const SQLITE_INTERNAL = 2; +export const SQLITE_PERM = 3; +export const SQLITE_ABORT = 4; +export const SQLITE_BUSY = 5; +export const SQLITE_LOCKED = 6; +export const SQLITE_NOMEM = 7; +export const SQLITE_READONLY = 8; +export const SQLITE_INTERRUPT = 9; +export const SQLITE_IOERR = 10; +export const SQLITE_CORRUPT = 11; +export const SQLITE_NOTFOUND = 12; +export const SQLITE_FULL = 13; +export const SQLITE_CANTOPEN = 14; +export const SQLITE_PROTOCOL = 15; +export const SQLITE_EMPTY = 16; +export const SQLITE_SCHEMA = 17; +export const SQLITE_TOOBIG = 18; +export const SQLITE_CONSTRAINT = 19; +export const SQLITE_MISMATCH = 20; +export const SQLITE_MISUSE = 21; +export const SQLITE_NOLFS = 22; +export const SQLITE_AUTH = 23; +export const SQLITE_FORMAT = 24; +export const SQLITE_RANGE = 25; +export const SQLITE_NOTADB = 26; +export const SQLITE_NOTICE = 27; +export const SQLITE_WARNING = 28; +export const SQLITE_ROW = 100; +export const SQLITE_DONE = 101; + +// Extended error codes. +export const SQLITE_IOERR_ACCESS = 3338; +export const SQLITE_IOERR_CHECKRESERVEDLOCK = 3594; +export const SQLITE_IOERR_CLOSE = 4106; +export const SQLITE_IOERR_DATA = 8202; +export const SQLITE_IOERR_DELETE = 2570; +export const SQLITE_IOERR_DELETE_NOENT = 5898; +export const SQLITE_IOERR_DIR_FSYNC = 1290; +export const SQLITE_IOERR_FSTAT = 1802; +export const SQLITE_IOERR_FSYNC = 1034; +export const SQLITE_IOERR_GETTEMPPATH = 6410; +export const SQLITE_IOERR_LOCK = 3850; +export const SQLITE_IOERR_NOMEM = 3082; +export const SQLITE_IOERR_READ = 266; +export const SQLITE_IOERR_RDLOCK = 2314; +export const SQLITE_IOERR_SEEK = 5642; +export const SQLITE_IOERR_SHORT_READ = 522; +export const SQLITE_IOERR_TRUNCATE = 1546; +export const SQLITE_IOERR_UNLOCK = 2058; +export const SQLITE_IOERR_VNODE = 6922; +export const SQLITE_IOERR_WRITE = 778; +export const SQLITE_IOERR_BEGIN_ATOMIC = 7434; +export const SQLITE_IOERR_COMMIT_ATOMIC = 7690; +export const SQLITE_IOERR_ROLLBACK_ATOMIC = 7946; + +// Other extended result codes. +export const SQLITE_CONSTRAINT_CHECK = 275; +export const SQLITE_CONSTRAINT_COMMITHOOK = 531; +export const SQLITE_CONSTRAINT_FOREIGNKEY = 787; +export const SQLITE_CONSTRAINT_FUNCTION = 1043; +export const SQLITE_CONSTRAINT_NOTNULL = 1299; +export const SQLITE_CONSTRAINT_PINNED = 2835; +export const SQLITE_CONSTRAINT_PRIMARYKEY = 1555; +export const SQLITE_CONSTRAINT_ROWID = 2579; +export const SQLITE_CONSTRAINT_TRIGGER = 1811; +export const SQLITE_CONSTRAINT_UNIQUE = 2067; +export const SQLITE_CONSTRAINT_VTAB = 2323; + +// Open flags. +// https://www.sqlite.org/c3ref/c_open_autoproxy.html +export const SQLITE_OPEN_READONLY = 0x00000001; +export const SQLITE_OPEN_READWRITE = 0x00000002; +export const SQLITE_OPEN_CREATE = 0x00000004; +export const SQLITE_OPEN_DELETEONCLOSE = 0x00000008; +export const SQLITE_OPEN_EXCLUSIVE = 0x00000010; +export const SQLITE_OPEN_AUTOPROXY = 0x00000020; +export const SQLITE_OPEN_URI = 0x00000040; +export const SQLITE_OPEN_MEMORY = 0x00000080; +export const SQLITE_OPEN_MAIN_DB = 0x00000100; +export const SQLITE_OPEN_TEMP_DB = 0x00000200; +export const SQLITE_OPEN_TRANSIENT_DB = 0x00000400; +export const SQLITE_OPEN_MAIN_JOURNAL = 0x00000800; +export const SQLITE_OPEN_TEMP_JOURNAL = 0x00001000; +export const SQLITE_OPEN_SUBJOURNAL = 0x00002000; +export const SQLITE_OPEN_SUPER_JOURNAL = 0x00004000; +export const SQLITE_OPEN_NOMUTEX = 0x00008000; +export const SQLITE_OPEN_FULLMUTEX = 0x00010000; +export const SQLITE_OPEN_SHAREDCACHE = 0x00020000; +export const SQLITE_OPEN_PRIVATECACHE = 0x00040000; +export const SQLITE_OPEN_WAL = 0x00080000; +export const SQLITE_OPEN_NOFOLLOW = 0x01000000; + +// Locking levels. +// https://www.sqlite.org/c3ref/c_lock_exclusive.html +export const SQLITE_LOCK_NONE = 0; +export const SQLITE_LOCK_SHARED = 1; +export const SQLITE_LOCK_RESERVED = 2; +export const SQLITE_LOCK_PENDING = 3; +export const SQLITE_LOCK_EXCLUSIVE = 4; + +// Device characteristics. +// https://www.sqlite.org/c3ref/c_iocap_atomic.html +export const SQLITE_IOCAP_ATOMIC = 0x00000001; +export const SQLITE_IOCAP_ATOMIC512 = 0x00000002; +export const SQLITE_IOCAP_ATOMIC1K = 0x00000004; +export const SQLITE_IOCAP_ATOMIC2K = 0x00000008; +export const SQLITE_IOCAP_ATOMIC4K = 0x00000010; +export const SQLITE_IOCAP_ATOMIC8K = 0x00000020; +export const SQLITE_IOCAP_ATOMIC16K = 0x00000040; +export const SQLITE_IOCAP_ATOMIC32K = 0x00000080; +export const SQLITE_IOCAP_ATOMIC64K = 0x00000100; +export const SQLITE_IOCAP_SAFE_APPEND = 0x00000200; +export const SQLITE_IOCAP_SEQUENTIAL = 0x00000400; +export const SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN = 0x00000800; +export const SQLITE_IOCAP_POWERSAFE_OVERWRITE = 0x00001000; +export const SQLITE_IOCAP_IMMUTABLE = 0x00002000; +export const SQLITE_IOCAP_BATCH_ATOMIC = 0x00004000; + +// xAccess flags. +// https://www.sqlite.org/c3ref/c_access_exists.html +export const SQLITE_ACCESS_EXISTS = 0; +export const SQLITE_ACCESS_READWRITE = 1; +export const SQLITE_ACCESS_READ = 2; + +// File control opcodes +// https://www.sqlite.org/c3ref/c_fcntl_begin_atomic_write.html#sqlitefcntlbeginatomicwrite +export const SQLITE_FCNTL_LOCKSTATE = 1; +export const SQLITE_FCNTL_GET_LOCKPROXYFILE = 2; +export const SQLITE_FCNTL_SET_LOCKPROXYFILE = 3; +export const SQLITE_FCNTL_LAST_ERRNO = 4; +export const SQLITE_FCNTL_SIZE_HINT = 5; +export const SQLITE_FCNTL_CHUNK_SIZE = 6; +export const SQLITE_FCNTL_FILE_POINTER = 7; +export const SQLITE_FCNTL_SYNC_OMITTED = 8; +export const SQLITE_FCNTL_WIN32_AV_RETRY = 9; +export const SQLITE_FCNTL_PERSIST_WAL = 10; +export const SQLITE_FCNTL_OVERWRITE = 11; +export const SQLITE_FCNTL_VFSNAME = 12; +export const SQLITE_FCNTL_POWERSAFE_OVERWRITE = 13; +export const SQLITE_FCNTL_PRAGMA = 14; +export const SQLITE_FCNTL_BUSYHANDLER = 15; +export const SQLITE_FCNTL_TEMPFILENAME = 16; +export const SQLITE_FCNTL_MMAP_SIZE = 18; +export const SQLITE_FCNTL_TRACE = 19; +export const SQLITE_FCNTL_HAS_MOVED = 20; +export const SQLITE_FCNTL_SYNC = 21; +export const SQLITE_FCNTL_COMMIT_PHASETWO = 22; +export const SQLITE_FCNTL_WIN32_SET_HANDLE = 23; +export const SQLITE_FCNTL_WAL_BLOCK = 24; +export const SQLITE_FCNTL_ZIPVFS = 25; +export const SQLITE_FCNTL_RBU = 26; +export const SQLITE_FCNTL_VFS_POINTER = 27; +export const SQLITE_FCNTL_JOURNAL_POINTER = 28; +export const SQLITE_FCNTL_WIN32_GET_HANDLE = 29; +export const SQLITE_FCNTL_PDB = 30; +export const SQLITE_FCNTL_BEGIN_ATOMIC_WRITE = 31; +export const SQLITE_FCNTL_COMMIT_ATOMIC_WRITE = 32; +export const SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE = 33; +export const SQLITE_FCNTL_LOCK_TIMEOUT = 34; +export const SQLITE_FCNTL_DATA_VERSION = 35; +export const SQLITE_FCNTL_SIZE_LIMIT = 36; +export const SQLITE_FCNTL_CKPT_DONE = 37; +export const SQLITE_FCNTL_RESERVE_BYTES = 38; +export const SQLITE_FCNTL_CKPT_START = 39; + +// Fundamental datatypes. +// https://www.sqlite.org/c3ref/c_blob.html +export const SQLITE_INTEGER = 1; +export const SQLITE_FLOAT = 2; +export const SQLITE_TEXT = 3; +export const SQLITE_BLOB = 4; +export const SQLITE_NULL = 5; + +// Special destructor behavior. +// https://www.sqlite.org/c3ref/c_static.html +export const SQLITE_STATIC = 0; +export const SQLITE_TRANSIENT = -1; + +// Text encodings. +// https://sqlite.org/c3ref/c_any.html +export const SQLITE_UTF8 = 1; /* IMP: R-37514-35566 */ +export const SQLITE_UTF16LE = 2; /* IMP: R-03371-37637 */ +export const SQLITE_UTF16BE = 3; /* IMP: R-51971-34154 */ +export const SQLITE_UTF16 = 4; /* Use native byte order */ + +// Module constraint ops. +export const SQLITE_INDEX_CONSTRAINT_EQ = 2; +export const SQLITE_INDEX_CONSTRAINT_GT = 4; +export const SQLITE_INDEX_CONSTRAINT_LE = 8; +export const SQLITE_INDEX_CONSTRAINT_LT = 16; +export const SQLITE_INDEX_CONSTRAINT_GE = 32; +export const SQLITE_INDEX_CONSTRAINT_MATCH = 64; +export const SQLITE_INDEX_CONSTRAINT_LIKE = 65; +export const SQLITE_INDEX_CONSTRAINT_GLOB = 66; +export const SQLITE_INDEX_CONSTRAINT_REGEXP = 67; +export const SQLITE_INDEX_CONSTRAINT_NE = 68; +export const SQLITE_INDEX_CONSTRAINT_ISNOT = 69; +export const SQLITE_INDEX_CONSTRAINT_ISNOTNULL = 70; +export const SQLITE_INDEX_CONSTRAINT_ISNULL = 71; +export const SQLITE_INDEX_CONSTRAINT_IS = 72; +export const SQLITE_INDEX_CONSTRAINT_FUNCTION = 150; +export const SQLITE_INDEX_SCAN_UNIQUE = 1; /* Scan visits at most = 1 row */ + +// Function flags +export const SQLITE_DETERMINISTIC = 0x000000800; +export const SQLITE_DIRECTONLY = 0x000080000; +export const SQLITE_SUBTYPE = 0x000100000; +export const SQLITE_INNOCUOUS = 0x000200000; + +// Sync flags +export const SQLITE_SYNC_NORMAL = 0x00002; +export const SQLITE_SYNC_FULL = 0x00003; +export const SQLITE_SYNC_DATAONLY = 0x00010; + +// Authorizer action codes +export const SQLITE_CREATE_INDEX = 1; +export const SQLITE_CREATE_TABLE = 2; +export const SQLITE_CREATE_TEMP_INDEX = 3; +export const SQLITE_CREATE_TEMP_TABLE = 4; +export const SQLITE_CREATE_TEMP_TRIGGER = 5; +export const SQLITE_CREATE_TEMP_VIEW = 6; +export const SQLITE_CREATE_TRIGGER = 7; +export const SQLITE_CREATE_VIEW = 8; +export const SQLITE_DELETE = 9; +export const SQLITE_DROP_INDEX = 10; +export const SQLITE_DROP_TABLE = 11; +export const SQLITE_DROP_TEMP_INDEX = 12; +export const SQLITE_DROP_TEMP_TABLE = 13; +export const SQLITE_DROP_TEMP_TRIGGER = 14; +export const SQLITE_DROP_TEMP_VIEW = 15; +export const SQLITE_DROP_TRIGGER = 16; +export const SQLITE_DROP_VIEW = 17; +export const SQLITE_INSERT = 18; +export const SQLITE_PRAGMA = 19; +export const SQLITE_READ = 20; +export const SQLITE_SELECT = 21; +export const SQLITE_TRANSACTION = 22; +export const SQLITE_UPDATE = 23; +export const SQLITE_ATTACH = 24; +export const SQLITE_DETACH = 25; +export const SQLITE_ALTER_TABLE = 26; +export const SQLITE_REINDEX = 27; +export const SQLITE_ANALYZE = 28; +export const SQLITE_CREATE_VTABLE = 29; +export const SQLITE_DROP_VTABLE = 30; +export const SQLITE_FUNCTION = 31; +export const SQLITE_SAVEPOINT = 32; +export const SQLITE_COPY = 0; +export const SQLITE_RECURSIVE = 33; + +// Authorizer return codes +export const SQLITE_DENY = 1; +export const SQLITE_IGNORE = 2; + +// Limit categories +export const SQLITE_LIMIT_LENGTH = 0; +export const SQLITE_LIMIT_SQL_LENGTH = 1; +export const SQLITE_LIMIT_COLUMN = 2; +export const SQLITE_LIMIT_EXPR_DEPTH = 3; +export const SQLITE_LIMIT_COMPOUND_SELECT = 4; +export const SQLITE_LIMIT_VDBE_OP = 5; +export const SQLITE_LIMIT_FUNCTION_ARG = 6; +export const SQLITE_LIMIT_ATTACHED = 7; +export const SQLITE_LIMIT_LIKE_PATTERN_LENGTH = 8; +export const SQLITE_LIMIT_VARIABLE_NUMBER = 9; +export const SQLITE_LIMIT_TRIGGER_DEPTH = 10; +export const SQLITE_LIMIT_WORKER_THREADS = 11; + +export const SQLITE_PREPARE_PERSISTENT = 0x01; +export const SQLITE_PREPARE_NORMALIZED = 0x02; +export const SQLITE_PREPARE_NO_VTAB = 0x04; \ No newline at end of file diff --git a/web/core/local-db/worker/wa-sqlite/src/types/globals.d.ts b/web/core/local-db/worker/wa-sqlite/src/types/globals.d.ts new file mode 100644 index 00000000000..7c4507cec10 --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/types/globals.d.ts @@ -0,0 +1,60 @@ +declare namespace Asyncify { + function handleAsync(f: () => Promise); +} + +declare function UTF8ToString(ptr: number): string; +declare function lengthBytesUTF8(s: string): number; +declare function stringToUTF8(s: string, p: number, n: number); +declare function ccall(name: string, returns: string, args: Array, options?: object): any; +declare function getValue(ptr: number, type: string): number; +declare function setValue(ptr: number, value: number, type: string): number; +declare function mergeInto(library: object, methods: object): void; + +declare var HEAPU8: Uint8Array; +declare var HEAPU32: Uint32Array; +declare var LibraryManager; +declare var Module; +declare var _vfsAccess; +declare var _vfsCheckReservedLock; +declare var _vfsClose; +declare var _vfsDelete; +declare var _vfsDeviceCharacteristics; +declare var _vfsFileControl; +declare var _vfsFileSize; +declare var _vfsLock; +declare var _vfsOpen; +declare var _vfsRead; +declare var _vfsSectorSize; +declare var _vfsSync; +declare var _vfsTruncate; +declare var _vfsUnlock; +declare var _vfsWrite; + +declare var _jsFunc; +declare var _jsStep; +declare var _jsFinal; + +declare var _modStruct; +declare var _modCreate; +declare var _modConnect; +declare var _modBestIndex; +declare var _modDisconnect; +declare var _modDestroy; +declare var _modOpen; +declare var _modClose; +declare var _modFilter; +declare var _modNext; +declare var _modEof; +declare var _modColumn; +declare var _modRowid; +declare var _modUpdate; +declare var _modBegin; +declare var _modSync; +declare var _modCommit; +declare var _modRollback; +declare var _modFindFunction; +declare var _modRename; + +declare var _jsAuth; + +declare var _jsProgress; \ No newline at end of file diff --git a/web/core/local-db/worker/wa-sqlite/src/types/index.d.ts b/web/core/local-db/worker/wa-sqlite/src/types/index.d.ts new file mode 100644 index 00000000000..4056786243d --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/types/index.d.ts @@ -0,0 +1,1317 @@ +/** + * This is a WebAssembly build of SQLite with experimental support for + * writing SQLite virtual file systems and modules (for virtual tables) + * in Javascript. Also see the + * [GitHub repository](https://github.com/rhashimoto/wa-sqlite) and the + * [online demo](https://rhashimoto.github.io/wa-sqlite/demo/). + * @module + */ + +/** + * Javascript types that SQLite can use + * + * C integer and floating-point types both map to/from Javascript `number`. + * Blob data can be provided to SQLite as `Uint8Array` or `number[]` (with + * each element converted to a byte); SQLite always returns blob data as + * `Uint8Array` + */ +type SQLiteCompatibleType = number|string|Uint8Array|Array|bigint|null; + +/** + * SQLite Virtual File System object + * + * Objects with this interface can be passed to {@link SQLiteAPI.vfs_register} + * to define a new filesystem. + * + * There are examples of a synchronous + * [MemoryVFS.js](https://github.com/rhashimoto/wa-sqlite/blob/master/src/examples/MemoryVFS.js), + * and asynchronous + * [MemoryAsyncVFS.js](https://github.com/rhashimoto/wa-sqlite/blob/master/src/examples/MemoryAsyncVFS.js) + * and + * [IndexedDbVFS.js](https://github.com/rhashimoto/wa-sqlite/blob/master/src/examples/IndexedDbVFS.js). + * + * @see https://sqlite.org/vfs.html + * @see https://sqlite.org/c3ref/io_methods.html + */ +declare interface SQLiteVFS { + /** Maximum length of a file path in UTF-8 bytes (default 64) */ + mxPathName?: number; + + close(): void|Promise; + isReady(): boolean|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xClose(fileId: number): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xRead( + fileId: number, + pData: number, + iAmt: number, + iOffsetLo: number, + iOffsetHi: number + ): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xWrite( + fileId: number, + pData: number, + iAmt: number, + iOffsetLo: number, + iOffsetHi: number + ): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xTruncate(fileId: number, iSizeLo: number, iSizeHi): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xSync(fileId: number, flags: number): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xFileSize( + fileId: number, + pSize64: number + ): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xLock(fileId: number, flags: number): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xUnlock(fileId: number, flags: number): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xCheckReservedLock( + fileId: number, + pResOut: number + ): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xFileControl( + fileId: number, + flags: number, + pOut: number + ): number|Promise; + + /** @see https://sqlite.org/c3ref/io_methods.html */ + xDeviceCharacteristics(fileId: number): number|Promise; + + /** @see https://sqlite.org/c3ref/vfs.html */ + xOpen( + pVfs: number, + zName: number, + pFile: number, + flags: number, + pOutFlags: number + ): number|Promise; + + /** @see https://sqlite.org/c3ref/vfs.html */ + xDelete(pVfs: number, zName: number, syncDir: number): number|Promise; + + /** @see https://sqlite.org/c3ref/vfs.html */ + xAccess( + pVfs: number, + zName: number, + flags: number, + pResOut: number + ): number|Promise; +} + +/** + * Options object argument for {@link SQLiteAPI.statements} + */ +declare interface SQLitePrepareOptions { + /** + * Statement handles prepared and yielded by {@link SQLiteAPI.statements} + * are normally valid only within the scope of an iteration. + * Set `unscoped` to `true` to give iterated statements an arbitrary + * lifetime. + */ + unscoped?: boolean; + + /** + * SQLITE_PREPARE_* flags + * @see https://www.sqlite.org/c3ref/c_prepare_normalize.html#sqlitepreparepersistent + */ + flags?: number; +} + +/** + * Javascript wrappers for the SQLite C API (plus a few convenience functions) + * + * Function signatures have been slightly modified to be more + * Javascript-friendly. For the C functions that return an error code, + * the corresponding Javascript wrapper will throw an exception with a + * `code` property on an error. + * + * Note that a few functions return a Promise in order to accomodate + * either a synchronous or asynchronous SQLite build, generally those + * involved with opening/closing a database or executing a statement. + * + * To create an instance of the API, follow these steps: + * + * ```javascript + * // Import an ES6 module factory function from one of the + * // package builds, either 'wa-sqlite.mjs' (synchronous) or + * // 'wa-sqlite-async.mjs' (asynchronous). You should only + * // use the asynchronous build if you plan to use an + * // asynchronous VFS or module. + * import SQLiteESMFactory from 'wa-sqlite/dist/wa-sqlite.mjs'; + * + * // Import the Javascript API wrappers. + * import * as SQLite from 'wa-sqlite'; + * + * // Use an async function to simplify Promise handling. + * (async function() { + * // Invoke the ES6 module factory to create the SQLite + * // Emscripten module. This will fetch and compile the + * // .wasm file. + * const module = await SQLiteESMFactory(); + * + * // Use the module to build the API instance. + * const sqlite3 = SQLite.Factory(module); + * + * // Use the API to open and access a database. + * const db = await sqlite3.open_v2('myDB'); + * ... + * })(); + * ``` + * + * @see https://sqlite.org/c3ref/funclist.html + */ +declare interface SQLiteAPI { + /** + * Bind a collection of values to a statement + * + * This convenience function binds values from either an array or object + * to a prepared statement with placeholder parameters. + * + * Array example using numbered parameters (numbering is implicit in + * this example): + * ``` + * const sql = 'INSERT INTO tbl VALUES (?, ?, ?)'; + * for await (const stmt of sqlite3.statements(db, sql) { + * sqlite3.bind_collection(stmt, [42, 'hello', null]); + * ... + * } + * ``` + * + * Object example using named parameters (':', '@', or '$' prefixes + * are allowed): + * ``` + * const sql = 'INSERT INTO tbl VALUES (?, ?, ?)'; + * for await (const stmt of sqlite3.statements(db, sql) { + * sqlite3.bind_collection(stmt, { + * '@foo': 42, + * '@bar': 'hello', + * '@baz': null, + * }); + * ... + * } + * ``` + * + * Note that SQLite bindings are indexed beginning with 1, but when + * binding values from an array `a` the values begin with `a[0]`. + * @param stmt prepared statement pointer + * @param bindings + * @returns `SQLITE_OK` (throws exception on error) + */ + bind_collection( + stmt: number, + bindings: {[index: string]: SQLiteCompatibleType|null}|Array + ): number; + + /** + * Bind value to prepared statement + * + * This convenience function calls the appropriate `bind_*` function + * based on the type of `value`. Note that binding indices begin with 1. + * @param stmt prepared statement pointer + * @param i binding index + * @param value + * @returns `SQLITE_OK` (throws exception on error) + */ + bind(stmt: number, i: number, value: SQLiteCompatibleType|null): number; + + /** + * Bind blob to prepared statement parameter + * + * Note that binding indices begin with 1. + * @see https://www.sqlite.org/c3ref/bind_blob.html + * @param stmt prepared statement pointer + * @param i binding index + * @param value + * @returns `SQLITE_OK` (throws exception on error) + */ + bind_blob(stmt: number, i: number, value: Uint8Array|Array): number; + + /** + * Bind number to prepared statement parameter + * + * Note that binding indices begin with 1. + * @see https://www.sqlite.org/c3ref/bind_blob.html + * @param stmt prepared statement pointer + * @param i binding index + * @param value + * @returns `SQLITE_OK` (throws exception on error) + */ + bind_double(stmt: number, i: number, value: number): number; + + /** + * Bind number to prepared statement parameter + * + * Note that binding indices begin with 1. + * @see https://www.sqlite.org/c3ref/bind_blob.html + * @param stmt prepared statement pointer + * @param i binding index + * @param value + * @returns `SQLITE_OK` (throws exception on error) + */ + bind_int(stmt: number, i: number, value: number): number; + + /** + * Bind number to prepared statement parameter + * + * Note that binding indices begin with 1. + * @see https://www.sqlite.org/c3ref/bind_blob.html + * @param stmt prepared statement pointer + * @param i binding index + * @param value + * @returns `SQLITE_OK` (throws exception on error) + */ + bind_int64(stmt: number, i: number, value: bigint): number; + + /** + * Bind null to prepared statement + * + * Note that binding indices begin with 1. + * @see https://www.sqlite.org/c3ref/bind_blob.html + * @param stmt prepared statement pointer + * @param i binding index + * @returns `SQLITE_OK` (throws exception on error) + */ + bind_null(stmt: number, i: number): number; + + /** + * Get number of bound parameters + * @see https://www.sqlite.org/c3ref/bind_parameter_count.html + * @param stmt prepared statement pointer + * @returns number of statement binding locations + */ + bind_parameter_count(stmt: number): number; + + /** + * Get name of bound parameter + * + * Note that binding indices begin with 1. + * @see https://www.sqlite.org/c3ref/bind_parameter_name.html + * @param stmt prepared statement pointer + * @param i binding index + * @returns binding name + */ + bind_parameter_name(stmt: number, i: number): string; + + /** + * Bind string to prepared statement + * + * Note that binding indices begin with 1. + * @see https://www.sqlite.org/c3ref/bind_blob.html + * @param stmt prepared statement pointer + * @param i binding index + * @param value + * @returns `SQLITE_OK` (throws exception on error) + */ + bind_text(stmt: number, i: number, value: string): number; + + /** + * Get count of rows modified by last insert/update + * @see https://www.sqlite.org/c3ref/changes.html + * @param db database pointer + * @returns number of rows modified + */ + changes(db): number; + + /** + * Reset all bindings on a prepared statement. + * @see https://www.sqlite.org/c3ref/clear_bindings.html + * @param stmt prepared statement pointer + * @returns `SQLITE_OK` (throws exception on error) + */ + clear_bindings(stmt: number): number; + + /** + * Close database connection + * @see https://www.sqlite.org/c3ref/close.html + * @param db database pointer + * @returns `SQLITE_OK` (throws exception on error) + */ + close(db): Promise; + + /** + * Call the appropriate `column_*` function based on the column type + * + * The type is determined by calling {@link column_type}, which may + * not match the type declared in `CREATE TABLE`. Note that if the column + * value is a blob then as with `column_blob` the result may be invalid + * after the next SQLite call; copy if it needs to be retained. + * + * Integer values are returned as Number if within the min/max safe + * integer bounds, otherwise they are returned as BigInt. + * @param stmt prepared statement pointer + * @param i column index + * @returns column value + */ + column(stmt: number, i: number): SQLiteCompatibleType; + + /** + * Extract a column value from a row after a prepared statment {@link step} + * + * The contents of the returned buffer may be invalid after the + * next SQLite call. Make a copy of the data (e.g. with `.slice()`) + * if longer retention is required. + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns column value + */ + column_blob(stmt: number, i: number): Uint8Array; + + /** + * Get storage size for column text or blob + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns number of bytes in column text or blob + */ + column_bytes(stmt: number, i: number): number; + + /** + * Get number of columns for a prepared statement + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @returns number of columns + */ + column_count(stmt: number): number; + + /** + * Extract a column value from a row after a prepared statment {@link step} + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns column value + */ + column_double(stmt: number, i: number): number; + + /** + * Extract a column value from a row after a prepared statment {@link step} + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns column value + */ + column_int(stmt: number, i: number): number; + + /** + * Extract a column value from a row after a prepared statment {@link step} + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns column value + */ + column_int64(stmt: number, i: number): bigint; + + /** + * Get a column name for a prepared statement + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns column name + */ + column_name(stmt: number, i: number): string; + + /** + * Get names for all columns of a prepared statement + * + * This is a convenience function that calls {@link column_count} and + * {@link column_name}. + * @param stmt + * @returns array of column names + */ + column_names(stmt: number): Array; + + /** + * Extract a column value from a row after a prepared statment {@link step} + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns column value + */ + column_text(stmt: number, i: number): string; + + /** + * Get column type for a prepared statement + * + * Note that this type may not match the type declared in `CREATE TABLE`. + * @see https://www.sqlite.org/c3ref/column_blob.html + * @param stmt prepared statement pointer + * @param i column index + * @returns enumeration value for type + */ + column_type(stmt: number, i: number): number; + + /** + * Create or redefine SQL functions + * + * The application data passed is ignored. Use closures instead. + * + * If any callback function returns a Promise, that function must + * be declared `async`, i.e. it must allow use of `await`. + * @see https://sqlite.org/c3ref/create_function.html + * @param db database pointer + * @param zFunctionName + * @param nArg number of function arguments + * @param eTextRep text encoding (and other flags) + * @param pApp application data (ignored) + * @param xFunc + * @param xStep + * @param xFinal + * @returns `SQLITE_OK` (throws exception on error) + */ + create_function( + db: number, + zFunctionName: string, + nArg: number, + eTextRep: number, + pApp: number, + xFunc?: (context: number, values: Uint32Array) => void|Promise, + xStep?: (context: number, values: Uint32Array) => void|Promise, + xFinal?: (context: number) => void|Promise): number; + + /** + * Get number of columns in current row of a prepared statement + * @see https://www.sqlite.org/c3ref/data_count.html + * @param stmt prepared statement pointer + * @returns number of columns + */ + data_count(stmt: number): number; + + /** + * One-step query execution interface + * + * The implementation of this function uses {@link row}, which makes a + * copy of blobs and returns BigInt for integers outside the safe integer + * bounds for Number. + * @see https://www.sqlite.org/c3ref/exec.html + * @param db database pointer + * @param zSQL queries + * @param callback called for each output row + * @returns Promise resolving to `SQLITE_OK` (rejects on error) + */ + exec( + db: number, + zSQL: string, + callback?: (row: Array, columns: string[]) => void + ): Promise; + + /** + * Destroy a prepared statement object compiled by {@link statements} + * with the `unscoped` option set to `true` + * + * This function does *not* throw on error. + * @see https://www.sqlite.org/c3ref/finalize.html + * @param stmt prepared statement pointer + * @returns Promise resolving to `SQLITE_OK` or error status + */ + finalize(stmt: number): Promise; + + /** + * Test for autocommit mode + * @see https://sqlite.org/c3ref/get_autocommit.html + * @param db database pointer + * @returns Non-zero if autocommit mode is on, zero otherwise + */ + get_autocommit(db: number): number; + + /** + * Get SQLite library version + * @see https://www.sqlite.org/c3ref/libversion.html + * @returns version string, e.g. '3.35.5' + */ + libversion(): string; + + /** + * Get SQLite library version + * @see https://www.sqlite.org/c3ref/libversion.html + * @returns version number, e.g. 3035005 + */ + libversion_number(): number + + /** + * Set a usage limit on a connection. + * @see https://www.sqlite.org/c3ref/limit.html + * @param db database pointer + * @param id limit category + * @param newVal + * @returns previous setting + */ + limit( + db: number, + id: number, + newVal: number): number; + + /** + * Opening a new database connection. + * + * Note that this function differs from the C API in that it + * returns the Promise-wrapped database pointer (instead of a + * result code). + * @see https://sqlite.org/c3ref/open.html + * @param zFilename + * @param iFlags `SQLite.SQLITE_OPEN_CREATE | SQLite.SQLITE_OPEN_READWRITE` (0x6) if omitted + * @param zVfs VFS name + * @returns Promise-wrapped database pointer. + */ + open_v2( + zFilename: string, + iFlags?: number, + zVfs?: string + ): Promise; + + /** + * Specify callback to be invoked between long-running queries + * + * The application data passed is ignored. Use closures instead. + * + * If any callback function returns a Promise, that function must + * be declared `async`, i.e. it must allow use of `await`. + * @param db database pointer + * @param nProgressOps target number of database operations between handler invocations + * @param handler + * @param userData + */ + progress_handler(db: number, nProgressOps: number, handler: (userData: any) => number|Promise, userData); + + /** + * Reset a prepared statement object + * @see https://www.sqlite.org/c3ref/reset.html + * @param stmt prepared statement pointer + * @returns Promise-wrapped `SQLITE_OK` (rejects on error) + */ + reset(stmt: number): Promise; + + /** + * Convenience function to call `result_*` based of the type of `value` + * @param context context pointer + * @param value + */ + result(context: number, value: (SQLiteCompatibleType|number[])|null): void; + + /** + * Set the result of a function or vtable column + * @see https://sqlite.org/c3ref/result_blob.html + * @param context context pointer + * @param value + */ + result_blob(context: number, value: Uint8Array|number[]): void; + + /** + * Set the result of a function or vtable column + * @see https://sqlite.org/c3ref/result_blob.html + * @param context context pointer + * @param value + */ + result_double(context: number, value: number): void; + + /** + * Set the result of a function or vtable column + * @see https://sqlite.org/c3ref/result_blob.html + * @param context context pointer + * @param value + */ + result_int(context: number, value: number): void; + + /** + * Set the result of a function or vtable column + * @see https://sqlite.org/c3ref/result_blob.html + * @param context context pointer + * @param value + */ + result_int64(context: number, value: bigint): void; + + /** + * Set the result of a function or vtable column + * @see https://sqlite.org/c3ref/result_blob.html + * @param context context pointer + */ + result_null(context: number): void; + + /** + * Set the result of a function or vtable column + * @see https://sqlite.org/c3ref/result_blob.html + * @param context context pointer + * @param value + */ + result_text(context: number, value: string): void; + + /** + * Get all column data for a row from a prepared statement step + * + * This convenience function will return a copy of any blob, unlike + * {@link column_blob} which returns a value referencing volatile WASM + * memory with short validity. Like {@link column}, it will return a + * BigInt for integers outside the safe integer bounds for Number. + * @param stmt prepared statement pointer + * @returns row data + */ + row(stmt: number): Array; + + /** + * Register a callback function that is invoked to authorize certain SQL statement actions. + * @see https://www.sqlite.org/c3ref/set_authorizer.html + * @param db database pointer + * @param authFunction + * @param userData + */ + set_authorizer( + db: number, + authFunction: (userData: any, iActionCode: number, param3: string|null, param4: string|null, param5: string|null, param6: string|null) => number|Promise, + userData: any): number; + + /** + * Get statement SQL + * @see https://www.sqlite.org/c3ref/expanded_sql.html + * @param stmt prepared statement pointer + * @returns SQL + */ + sql(stmt: number): string; + + /** + * SQL statement iterator + * + * This function manages statement compilation by creating an async + * iterator that yields a prepared statement handle on each iteration. + * It is typically used with a `for await` loop (in an async function), + * like this: + * ```javascript + * // Compile one statement on each iteration of this loop. + * for await (const stmt of sqlite3.statements(db, sql)) { + * // Bind parameters here if using SQLite placeholders. + * + * // Execute the statement with this loop. + * while (await sqlite3.step(stmt) === SQLite.SQLITE_ROW) { + * // Collect row data here. + * } + * + * // Change bindings, reset, and execute again if desired. + * } + * ``` + * + * By default, the lifetime of a yielded prepared statement is managed + * automatically by the iterator, ending at the end of each iteration. + * {@link finalize} should *not* be called on a statement provided by + * the iterator unless the `unscoped` option is set to `true` (that + * option is provided for applications that wish to manage statement + * lifetimes manually). + * + * If using the iterator manually, i.e. by calling its `next` + * method, be sure to call the `return` method if iteration + * is abandoned before completion (`for await` and other implicit + * traversals provided by Javascript do this automatically) + * to ensure that all allocated resources are released. + * @see https://www.sqlite.org/c3ref/prepare.html + * @param db database pointer + * @param sql + * @param options + */ + statements(db: number, sql: string, options?: SQLitePrepareOptions): AsyncIterable; + + /** + * Evaluate an SQL statement + * @see https://www.sqlite.org/c3ref/step.html + * @param stmt prepared statement pointer + * @returns Promise resolving to `SQLITE_ROW` or `SQLITE_DONE` + * (rejects on error) + */ + step(stmt: number): Promise; + + /** + * Register an update hook + * + * The callback is invoked whenever a row is updated, inserted, or deleted + * in a rowid table on this connection. + * @see https://www.sqlite.org/c3ref/update_hook.html + * + * updateType is one of: + * - SQLITE_DELETE: 9 + * - SQLITE_INSERT: 18 + * - SQLITE_UPDATE: 23 + * @see https://www.sqlite.org/c3ref/c_alter_table.html + * + * @param db database pointer + * @param callback + */ + update_hook( + db: number, + callback: (updateType: number, dbName: string|null, tblName: string|null, rowid: bigint) => void): void; + + /** + * Extract a value from `sqlite3_value` + * + * This is a convenience function that calls the appropriate `value_*` + * function based on its type. Note that if the value is a blob then as + * with `value_blob` the result may be invalid after the next SQLite call. + * + * Integer values are returned as Number if within the min/max safe + * integer bounds, otherwise they are returned as BigInt. + * @param pValue `sqlite3_value` pointer + * @returns value + */ + value(pValue: number): SQLiteCompatibleType; + + /** + * Extract a value from `sqlite3_value` + * + * The contents of the returned buffer may be invalid after the + * next SQLite call. Make a copy of the data (e.g. with `.slice()`) + * if longer retention is required. + * @see https://sqlite.org/c3ref/value_blob.html + * @param pValue `sqlite3_value` pointer + * @returns value + */ + value_blob(pValue: number): Uint8Array; + + /** + * Get blob or text size for value + * @see https://sqlite.org/c3ref/value_blob.html + * @param pValue `sqlite3_value` pointer + * @returns size + */ + value_bytes(pValue: number): number; + + /** + * Extract a value from `sqlite3_value` + * @see https://sqlite.org/c3ref/value_blob.html + * @param pValue `sqlite3_value` pointer + * @returns value + */ + value_double(pValue: number): number; + + /** + * Extract a value from `sqlite3_value` + * @see https://sqlite.org/c3ref/value_blob.html + * @param pValue `sqlite3_value` pointer + * @returns value + */ + value_int(pValue: number): number; + + /** + * Extract a value from `sqlite3_value` + * @see https://sqlite.org/c3ref/value_blob.html + * @param pValue `sqlite3_value` pointer + * @returns value + */ + value_int64(pValue: number): bigint; + + /** + * Extract a value from `sqlite3_value` + * @see https://sqlite.org/c3ref/value_blob.html + * @param pValue `sqlite3_value` pointer + * @returns value + */ + value_text(pValue: number): string; + + /** + * Get type of `sqlite3_value` + * @see https://sqlite.org/c3ref/value_blob.html + * @param pValue `sqlite3_value` pointer + * @returns enumeration value for type + */ + value_type(pValue: number): number; + + /** + * Register a new Virtual File System. + * + * @see https://www.sqlite.org/c3ref/vfs_find.html + * @param vfs VFS object + * @param makeDefault + * @returns `SQLITE_OK` (throws exception on error) + */ + vfs_register(vfs: SQLiteVFS, makeDefault?: boolean): number; +} + +/** @ignore */ +declare module 'wa-sqlite/src/sqlite-constants.js' { + export const SQLITE_OK: 0; + export const SQLITE_ERROR: 1; + export const SQLITE_INTERNAL: 2; + export const SQLITE_PERM: 3; + export const SQLITE_ABORT: 4; + export const SQLITE_BUSY: 5; + export const SQLITE_LOCKED: 6; + export const SQLITE_NOMEM: 7; + export const SQLITE_READONLY: 8; + export const SQLITE_INTERRUPT: 9; + export const SQLITE_IOERR: 10; + export const SQLITE_CORRUPT: 11; + export const SQLITE_NOTFOUND: 12; + export const SQLITE_FULL: 13; + export const SQLITE_CANTOPEN: 14; + export const SQLITE_PROTOCOL: 15; + export const SQLITE_EMPTY: 16; + export const SQLITE_SCHEMA: 17; + export const SQLITE_TOOBIG: 18; + export const SQLITE_CONSTRAINT: 19; + export const SQLITE_MISMATCH: 20; + export const SQLITE_MISUSE: 21; + export const SQLITE_NOLFS: 22; + export const SQLITE_AUTH: 23; + export const SQLITE_FORMAT: 24; + export const SQLITE_RANGE: 25; + export const SQLITE_NOTADB: 26; + export const SQLITE_NOTICE: 27; + export const SQLITE_WARNING: 28; + export const SQLITE_ROW: 100; + export const SQLITE_DONE: 101; + export const SQLITE_IOERR_ACCESS: 3338; + export const SQLITE_IOERR_CHECKRESERVEDLOCK: 3594; + export const SQLITE_IOERR_CLOSE: 4106; + export const SQLITE_IOERR_DATA: 8202; + export const SQLITE_IOERR_DELETE: 2570; + export const SQLITE_IOERR_DELETE_NOENT: 5898; + export const SQLITE_IOERR_DIR_FSYNC: 1290; + export const SQLITE_IOERR_FSTAT: 1802; + export const SQLITE_IOERR_FSYNC: 1034; + export const SQLITE_IOERR_GETTEMPPATH: 6410; + export const SQLITE_IOERR_LOCK: 3850; + export const SQLITE_IOERR_NOMEM: 3082; + export const SQLITE_IOERR_READ: 266; + export const SQLITE_IOERR_RDLOCK: 2314; + export const SQLITE_IOERR_SEEK: 5642; + export const SQLITE_IOERR_SHORT_READ: 522; + export const SQLITE_IOERR_TRUNCATE: 1546; + export const SQLITE_IOERR_UNLOCK: 2058; + export const SQLITE_IOERR_VNODE: 6922; + export const SQLITE_IOERR_WRITE: 778; + export const SQLITE_IOERR_BEGIN_ATOMIC: 7434; + export const SQLITE_IOERR_COMMIT_ATOMIC: 7690; + export const SQLITE_IOERR_ROLLBACK_ATOMIC: 7946; + export const SQLITE_CONSTRAINT_CHECK: 275; + export const SQLITE_CONSTRAINT_COMMITHOOK: 531; + export const SQLITE_CONSTRAINT_FOREIGNKEY: 787; + export const SQLITE_CONSTRAINT_FUNCTION: 1043; + export const SQLITE_CONSTRAINT_NOTNULL: 1299; + export const SQLITE_CONSTRAINT_PINNED: 2835; + export const SQLITE_CONSTRAINT_PRIMARYKEY: 1555; + export const SQLITE_CONSTRAINT_ROWID: 2579; + export const SQLITE_CONSTRAINT_TRIGGER: 1811; + export const SQLITE_CONSTRAINT_UNIQUE: 2067; + export const SQLITE_CONSTRAINT_VTAB: 2323; + export const SQLITE_OPEN_READONLY: 1; + export const SQLITE_OPEN_READWRITE: 2; + export const SQLITE_OPEN_CREATE: 4; + export const SQLITE_OPEN_DELETEONCLOSE: 8; + export const SQLITE_OPEN_EXCLUSIVE: 16; + export const SQLITE_OPEN_AUTOPROXY: 32; + export const SQLITE_OPEN_URI: 64; + export const SQLITE_OPEN_MEMORY: 128; + export const SQLITE_OPEN_MAIN_DB: 256; + export const SQLITE_OPEN_TEMP_DB: 512; + export const SQLITE_OPEN_TRANSIENT_DB: 1024; + export const SQLITE_OPEN_MAIN_JOURNAL: 2048; + export const SQLITE_OPEN_TEMP_JOURNAL: 4096; + export const SQLITE_OPEN_SUBJOURNAL: 8192; + export const SQLITE_OPEN_SUPER_JOURNAL: 16384; + export const SQLITE_OPEN_NOMUTEX: 32768; + export const SQLITE_OPEN_FULLMUTEX: 65536; + export const SQLITE_OPEN_SHAREDCACHE: 131072; + export const SQLITE_OPEN_PRIVATECACHE: 262144; + export const SQLITE_OPEN_WAL: 524288; + export const SQLITE_OPEN_NOFOLLOW: 16777216; + export const SQLITE_LOCK_NONE: 0; + export const SQLITE_LOCK_SHARED: 1; + export const SQLITE_LOCK_RESERVED: 2; + export const SQLITE_LOCK_PENDING: 3; + export const SQLITE_LOCK_EXCLUSIVE: 4; + export const SQLITE_IOCAP_ATOMIC: 1; + export const SQLITE_IOCAP_ATOMIC512: 2; + export const SQLITE_IOCAP_ATOMIC1K: 4; + export const SQLITE_IOCAP_ATOMIC2K: 8; + export const SQLITE_IOCAP_ATOMIC4K: 16; + export const SQLITE_IOCAP_ATOMIC8K: 32; + export const SQLITE_IOCAP_ATOMIC16K: 64; + export const SQLITE_IOCAP_ATOMIC32K: 128; + export const SQLITE_IOCAP_ATOMIC64K: 256; + export const SQLITE_IOCAP_SAFE_APPEND: 512; + export const SQLITE_IOCAP_SEQUENTIAL: 1024; + export const SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN: 2048; + export const SQLITE_IOCAP_POWERSAFE_OVERWRITE: 4096; + export const SQLITE_IOCAP_IMMUTABLE: 8192; + export const SQLITE_IOCAP_BATCH_ATOMIC: 16384; + export const SQLITE_ACCESS_EXISTS: 0; + export const SQLITE_ACCESS_READWRITE: 1; + export const SQLITE_ACCESS_READ: 2; + export const SQLITE_FCNTL_LOCKSTATE: 1; + export const SQLITE_FCNTL_GET_LOCKPROXYFILE: 2; + export const SQLITE_FCNTL_SET_LOCKPROXYFILE: 3; + export const SQLITE_FCNTL_LAST_ERRNO: 4; + export const SQLITE_FCNTL_SIZE_HINT: 5; + export const SQLITE_FCNTL_CHUNK_SIZE: 6; + export const SQLITE_FCNTL_FILE_POINTER: 7; + export const SQLITE_FCNTL_SYNC_OMITTED: 8; + export const SQLITE_FCNTL_WIN32_AV_RETRY: 9; + export const SQLITE_FCNTL_PERSIST_WAL: 10; + export const SQLITE_FCNTL_OVERWRITE: 11; + export const SQLITE_FCNTL_VFSNAME: 12; + export const SQLITE_FCNTL_POWERSAFE_OVERWRITE: 13; + export const SQLITE_FCNTL_PRAGMA: 14; + export const SQLITE_FCNTL_BUSYHANDLER: 15; + export const SQLITE_FCNTL_TEMPFILENAME: 16; + export const SQLITE_FCNTL_MMAP_SIZE: 18; + export const SQLITE_FCNTL_TRACE: 19; + export const SQLITE_FCNTL_HAS_MOVED: 20; + export const SQLITE_FCNTL_SYNC: 21; + export const SQLITE_FCNTL_COMMIT_PHASETWO: 22; + export const SQLITE_FCNTL_WIN32_SET_HANDLE: 23; + export const SQLITE_FCNTL_WAL_BLOCK: 24; + export const SQLITE_FCNTL_ZIPVFS: 25; + export const SQLITE_FCNTL_RBU: 26; + export const SQLITE_FCNTL_VFS_POINTER: 27; + export const SQLITE_FCNTL_JOURNAL_POINTER: 28; + export const SQLITE_FCNTL_WIN32_GET_HANDLE: 29; + export const SQLITE_FCNTL_PDB: 30; + export const SQLITE_FCNTL_BEGIN_ATOMIC_WRITE: 31; + export const SQLITE_FCNTL_COMMIT_ATOMIC_WRITE: 32; + export const SQLITE_FCNTL_ROLLBACK_ATOMIC_WRITE: 33; + export const SQLITE_FCNTL_LOCK_TIMEOUT: 34; + export const SQLITE_FCNTL_DATA_VERSION: 35; + export const SQLITE_FCNTL_SIZE_LIMIT: 36; + export const SQLITE_FCNTL_CKPT_DONE: 37; + export const SQLITE_FCNTL_RESERVE_BYTES: 38; + export const SQLITE_FCNTL_CKPT_START: 39; + export const SQLITE_INTEGER: 1; + export const SQLITE_FLOAT: 2; + export const SQLITE_TEXT: 3; + export const SQLITE_BLOB: 4; + export const SQLITE_NULL: 5; + export const SQLITE_STATIC: 0; + export const SQLITE_TRANSIENT: -1; + export const SQLITE_UTF8: 1; + export const SQLITE_UTF16LE: 2; + export const SQLITE_UTF16BE: 3; + export const SQLITE_UTF16: 4; + export const SQLITE_INDEX_CONSTRAINT_EQ: 2; + export const SQLITE_INDEX_CONSTRAINT_GT: 4; + export const SQLITE_INDEX_CONSTRAINT_LE: 8; + export const SQLITE_INDEX_CONSTRAINT_LT: 16; + export const SQLITE_INDEX_CONSTRAINT_GE: 32; + export const SQLITE_INDEX_CONSTRAINT_MATCH: 64; + export const SQLITE_INDEX_CONSTRAINT_LIKE: 65; + export const SQLITE_INDEX_CONSTRAINT_GLOB: 66; + export const SQLITE_INDEX_CONSTRAINT_REGEXP: 67; + export const SQLITE_INDEX_CONSTRAINT_NE: 68; + export const SQLITE_INDEX_CONSTRAINT_ISNOT: 69; + export const SQLITE_INDEX_CONSTRAINT_ISNOTNULL: 70; + export const SQLITE_INDEX_CONSTRAINT_ISNULL: 71; + export const SQLITE_INDEX_CONSTRAINT_IS: 72; + export const SQLITE_INDEX_CONSTRAINT_FUNCTION: 150; + export const SQLITE_INDEX_SCAN_UNIQUE: 1; + export const SQLITE_DETERMINISTIC: 0x000000800; + export const SQLITE_DIRECTONLY: 0x000080000; + export const SQLITE_SUBTYPE: 0x000100000; + export const SQLITE_INNOCUOUS: 0x000200000; + export const SQLITE_SYNC_NORMAL: 0x00002; + export const SQLITE_SYNC_FULL: 0x00003; + export const SQLITE_SYNC_DATAONLY: 0x00010; + export const SQLITE_CREATE_INDEX: 1; + export const SQLITE_CREATE_TABLE: 2; + export const SQLITE_CREATE_TEMP_INDEX: 3; + export const SQLITE_CREATE_TEMP_TABLE: 4; + export const SQLITE_CREATE_TEMP_TRIGGER: 5; + export const SQLITE_CREATE_TEMP_VIEW: 6; + export const SQLITE_CREATE_TRIGGER: 7; + export const SQLITE_CREATE_VIEW: 8; + export const SQLITE_DELETE: 9; + export const SQLITE_DROP_INDEX: 10; + export const SQLITE_DROP_TABLE: 11; + export const SQLITE_DROP_TEMP_INDEX: 12; + export const SQLITE_DROP_TEMP_TABLE: 13; + export const SQLITE_DROP_TEMP_TRIGGER: 14; + export const SQLITE_DROP_TEMP_VIEW: 15; + export const SQLITE_DROP_TRIGGER: 16; + export const SQLITE_DROP_VIEW: 17; + export const SQLITE_INSERT: 18; + export const SQLITE_PRAGMA: 19; + export const SQLITE_READ: 20; + export const SQLITE_SELECT: 21; + export const SQLITE_TRANSACTION: 22; + export const SQLITE_UPDATE: 23; + export const SQLITE_ATTACH: 24; + export const SQLITE_DETACH: 25; + export const SQLITE_ALTER_TABLE: 26; + export const SQLITE_REINDEX: 27; + export const SQLITE_ANALYZE: 28; + export const SQLITE_CREATE_VTABLE: 29; + export const SQLITE_DROP_VTABLE: 30; + export const SQLITE_FUNCTION: 31; + export const SQLITE_SAVEPOINT: 32; + export const SQLITE_COPY: 0; + export const SQLITE_RECURSIVE: 33; + export const SQLITE_DENY: 1; + export const SQLITE_IGNORE: 2; + export const SQLITE_LIMIT_LENGTH: 0; + export const SQLITE_LIMIT_SQL_LENGTH: 1; + export const SQLITE_LIMIT_COLUMN: 2; + export const SQLITE_LIMIT_EXPR_DEPTH: 3; + export const SQLITE_LIMIT_COMPOUND_SELECT: 4; + export const SQLITE_LIMIT_VDBE_OP: 5; + export const SQLITE_LIMIT_FUNCTION_ARG: 6; + export const SQLITE_LIMIT_ATTACHED: 7; + export const SQLITE_LIMIT_LIKE_PATTERN_LENGTH: 8; + export const SQLITE_LIMIT_VARIABLE_NUMBER: 9; + export const SQLITE_LIMIT_TRIGGER_DEPTH: 10; + export const SQLITE_LIMIT_WORKER_THREADS: 11; + export const SQLITE_PREPARE_PERSISTENT: 0x01; + export const SQLITE_PREPARE_NORMALIZED: 0x02; + export const SQLITE_PREPARE_NO_VTAB: 0x04; +} + +declare module 'wa-sqlite' { + export * from 'wa-sqlite/src/sqlite-constants.js'; + + /** + * @ignore + * Builds a Javascript API from the Emscripten module. This API is still + * low-level and closely corresponds to the C API exported by the module, + * but differs in some specifics like throwing exceptions on errors. + * @param {*} Module SQLite module + * @returns {SQLiteAPI} + */ + export function Factory(Module: any): SQLiteAPI; + + export class SQLiteError extends Error { + constructor(message: any, code: any); + code: any; + } +} + +/** @ignore */ +declare module 'wa-sqlite/dist/wa-sqlite.mjs' { + function ModuleFactory(config?: object): Promise; + export = ModuleFactory; +} + +/** @ignore */ +declare module 'wa-sqlite/dist/wa-sqlite-async.mjs' { + function ModuleFactory(config?: object): Promise; + export = ModuleFactory; +} + +/** @ignore */ +declare module 'wa-sqlite/src/VFS.js' { + export * from 'wa-sqlite/src/sqlite-constants.js'; + + export class Base { + mxPathName: number; + /** + * @param {number} fileId + * @returns {number|Promise} + */ + xClose(fileId: number): number; + /** + * @param {number} fileId + * @param {Uint8Array} pData + * @param {number} iOffset + * @returns {number} + */ + xRead(fileId: number, pData: { + size: number; + value: Uint8Array; + }, iOffset: number): number; + /** + * @param {number} fileId + * @param {Uint8Array} pData + * @param {number} iOffset + * @returns {number} + */ + xWrite(fileId: number, pData: { + size: number; + value: Uint8Array; + }, iOffset: number): number; + /** + * @param {number} fileId + * @param {number} iSize + * @returns {number} + */ + xTruncate(fileId: number, iSize: number): number; + /** + * @param {number} fileId + * @param {*} flags + * @returns {number} + */ + xSync(fileId: number, flags: any): number; + /** + * @param {number} fileId + * @param {DataView} pSize64 + * @returns {number|Promise} + */ + xFileSize(fileId: number, pSize64: DataView): number; + /** + * @param {number} fileId + * @param {number} flags + * @returns {number} + */ + xLock(fileId: number, flags: number): number; + /** + * @param {number} fileId + * @param {number} flags + * @returns {number} + */ + xUnlock(fileId: number, flags: number): number; + /** + * @param {number} fileId + * @param {DataView} pResOut + * @returns {number} + */ + xCheckReservedLock(fileId: number, pResOut: DataView): number; + /** + * @param {number} fileId + * @param {number} flags + * @param {DataView} pArg + * @returns {number} + */ + xFileControl(fileId: number, flags: number, pArg: DataView): number; + /** + * @param {number} fileId + * @returns {number} + */ + xSectorSize(fileId: number): number; + /** + * @param {number} fileId + * @returns {number} + */ + xDeviceCharacteristics(fileId: number): number; + /** + * @param {string?} name + * @param {number} fileId + * @param {number} flags + * @param {DataView} pOutFlags + * @returns {number} + */ + xOpen(name: string | null, fileId: number, flags: number, pOutFlags: DataView): number; + /** + * + * @param {string} name + * @param {number} syncDir + * @returns {number} + */ + xDelete(name: string, syncDir: number): number; + /** + * @param {string} name + * @param {number} flags + * @param {DataView} pResOut + * @returns {number} + */ + xAccess(name: string, flags: number, pResOut: DataView): number; + /** + * Handle asynchronous operation. This implementation will be overriden on + * registration by an Asyncify build. + * @param {function(): Promise} f + * @returns {number} + */ + handleAsync(f: () => Promise): number; + } +} + +/** @ignore */ +declare module 'wa-sqlite/src/examples/IndexedDbVFS.js' { + import * as VFS from "wa-sqlite/src/VFS.js"; + export class IndexedDbVFS extends VFS.Base { + /** + * @param {string} idbName Name of IndexedDB database. + */ + constructor(idbName?: string); + name: string; + mapIdToFile: Map; + cacheSize: number; + db: any; + close(): Promise; + /** + * Delete a file from IndexedDB. + * @param {string} name + */ + deleteFile(name: string): Promise; + /** + * Forcibly clear an orphaned file lock. + * @param {string} name + */ + forceClearLock(name: string): Promise; + _getStore(mode?: string): any; + /** + * Returns the key for file metadata. + * @param {string} name + * @returns + */ + _metaKey(name: string): string; + /** + * Returns the key for file block data. + * @param {string} name + * @param {number} index + * @returns + */ + _blockKey(name: string, index: number): string; + _getBlock(store: any, file: any, index: any): Promise; + _putBlock(store: any, file: any, index: any, blockData: any): void; + _purgeCache(store: any, file: any, size?: number): void; + _flushCache(store: any, file: any): Promise; + _sync(file: any): Promise; + /** + * Helper function that deletes all keys greater or equal to `key` + * provided they start with `prefix`. + * @param {string} key + * @param {string} [prefix] + * @returns + */ + _delete(key: string, prefix?: string): Promise; + } +} + +/** @ignore */ +declare module 'wa-sqlite/src/examples/MemoryVFS.js' { + import * as VFS from "wa-sqlite/src/VFS.js"; + /** @ignore */ + export class MemoryVFS extends VFS.Base { + name: string; + mapNameToFile: Map; + mapIdToFile: Map; + } +} + +/** @ignore */ +declare module 'wa-sqlite/src/examples/MemoryAsyncVFS.js' { + import { MemoryVFS } from "wa-sqlite/src/examples/MemoryVFS.js"; + export class MemoryAsyncVFS extends MemoryVFS { + } +} + +/** @ignore */ +declare module 'wa-sqlite/src/examples/tag.js' { + /** + * @ignore + * Template tag builder. This function creates a tag with an API and + * database from the same module, then the tag can be used like this: + * ``` + * const sql = tag(sqlite3, db); + * const results = await sql` + * SELECT 1 + 1; + * SELECT 6 * 7; + * `; + * ``` + * The returned Promise value contains an array of results for each + * SQL statement that produces output. Each result is an object with + * properties `columns` (array of names) and `rows` (array of array + * of values). + * @param {SQLiteAPI} sqlite3 + * @param {number} db + * @returns {function(TemplateStringsArray, ...any): Promise} + */ + export function tag(sqlite3: any, db: number): (arg0: TemplateStringsArray, ...args: any[]) => Promise; +} diff --git a/web/package.json b/web/package.json index 517eba12044..e1ef0a21c3c 100644 --- a/web/package.json +++ b/web/package.json @@ -34,10 +34,10 @@ "@popperjs/core": "^2.11.8", "@react-pdf/renderer": "^3.4.5", "@sentry/nextjs": "^8.32.0", - "@sqlite.org/sqlite-wasm": "^3.46.0-build2", "axios": "^1.7.4", "clsx": "^2.0.0", "cmdk": "^1.0.0", + "comlink": "^4.4.1", "date-fns": "^2.30.0", "dotenv": "^16.0.3", "isomorphic-dompurify": "^2.12.0", @@ -59,6 +59,7 @@ "react-markdown": "^8.0.7", "react-pdf-html": "^2.1.2", "react-popper": "^2.3.0", + "recharts": "^2.12.7", "sharp": "^0.32.1", "smooth-scroll-into-view-if-needed": "^2.0.2", "swr": "^2.1.3", @@ -66,8 +67,7 @@ "use-debounce": "^9.0.4", "use-font-face-observer": "^1.2.2", "uuid": "^9.0.0", - "zxcvbn": "^4.4.2", - "recharts": "^2.12.7" + "zxcvbn": "^4.4.2" }, "devDependencies": { "@plane/eslint-config": "*", diff --git a/yarn.lock b/yarn.lock index 99246b4d462..04579f3c477 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2935,11 +2935,6 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz#719df7fb41766bc143369eaa0dd56d8dc87c9958" integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg== -"@sqlite.org/sqlite-wasm@^3.46.0-build2": - version "3.46.0-build2" - resolved "https://registry.yarnpkg.com/@sqlite.org/sqlite-wasm/-/sqlite-wasm-3.46.0-build2.tgz#f84c3014f3fed6db08fc585d67e386d39e3956bf" - integrity sha512-10s/u/Main1RGO+jjzK+mgC/zh1ls1CEnq3Dujr03TwvzLg+j4FAohOmlYkQj8KQOj1vGR9cuB9F8tVBTwVGVA== - "@storybook/addon-actions@8.3.5": version "8.3.5" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-8.3.5.tgz#03fdb891114439ed47cb7df6ef21826530449db7" @@ -5481,6 +5476,11 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +comlink@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/comlink/-/comlink-4.4.1.tgz#e568b8e86410b809e8600eb2cf40c189371ef981" + integrity sha512-+1dlx0aY5Jo1vHy/tSsIGpSkN4tS9rZSW8FIhG0JH/crs9wwweswIo/POr451r7bZww3hFbPAKnTpimzL/mm4Q== + comma-separated-tokens@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz#4e89c9458acb61bc8fef19f4529973b2392839ee" From 116b508816c4ec9f303a366d24b8529a71380a71 Mon Sep 17 00:00:00 2001 From: Satish Gandham Date: Thu, 17 Oct 2024 19:55:29 +0530 Subject: [PATCH 06/24] Code cleanup and fix indexes --- web/core/local-db/storage.sqlite.ts | 6 +++--- web/core/local-db/utils/indexes.ts | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/web/core/local-db/storage.sqlite.ts b/web/core/local-db/storage.sqlite.ts index 989bdea6c7a..5dbe521c12d 100644 --- a/web/core/local-db/storage.sqlite.ts +++ b/web/core/local-db/storage.sqlite.ts @@ -18,10 +18,9 @@ import { issueFilterCountQueryConstructor, issueFilterQueryConstructor } from ". import { runQuery } from "./utils/query-executor"; import { createTables } from "./utils/tables"; import { getGroupedIssueResults, getSubGroupedIssueResults, log, logError, logInfo } from "./utils/utils"; -import { DBClass } from "./worker/db"; const DB_VERSION = 1; -const PAGE_SIZE = 1000; +const PAGE_SIZE = 500; const BATCH_SIZE = 200; type TProjectStatus = { @@ -91,6 +90,8 @@ export class Storage { logInfo("Loading and initializing SQLite3 module..."); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { DBClass } = await import("./worker/db"); const MyWorker = Comlink.wrap(new Worker(new URL("./worker/db.ts", import.meta.url))); this.workspaceSlug = workspaceSlug; this.dbName = workspaceSlug; @@ -309,7 +310,6 @@ export class Storage { Parsing: parsingEnd - parsingStart, Grouping: groupingEnd - grouping, }; - log(issueResults); if ((window as any).DEBUG) { console.table(times); } diff --git a/web/core/local-db/utils/indexes.ts b/web/core/local-db/utils/indexes.ts index 214bacb44f5..1561f319309 100644 --- a/web/core/local-db/utils/indexes.ts +++ b/web/core/local-db/utils/indexes.ts @@ -34,10 +34,8 @@ export const createWorkSpaceIndexes = async () => { const promises: Promise[] = []; // Labels promises.push(persistence.db.exec({ sql: `CREATE INDEX labels_name_idx ON labels (id,name,project_id)` })); - // Modules promises.push(persistence.db.exec({ sql: `CREATE INDEX modules_name_idx ON modules (id,name,project_id)` })); - // States promises.push(persistence.db.exec({ sql: `CREATE INDEX states_name_idx ON states (id,name,project_id)` })); // Cycles @@ -49,7 +47,7 @@ export const createWorkSpaceIndexes = async () => { // Estimate Points @todo promises.push(persistence.db.exec({ sql: `CREATE INDEX estimate_points_name_idx ON estimate_points (id,value)` })); // Options - promises.push(persistence.db.exec({ sql: `CREATE INDEX options_name_idx ON options (name)` })); + promises.push(persistence.db.exec({ sql: `CREATE INDEX options_key_idx ON options (key)` })); await Promise.all(promises); }; From d821786028664e7d8b128d3d950f3cab85bb2094 Mon Sep 17 00:00:00 2001 From: Satish Gandham Date: Thu, 17 Oct 2024 20:27:51 +0530 Subject: [PATCH 07/24] Add missing files --- web/core/local-db/worker/db.ts | 2 +- .../worker/wa-sqlite/src/wa-sqlite.mjs | 16 ++++++++++++++++ .../worker/wa-sqlite/src/wa-sqlite.wasm | Bin 0 -> 594230 bytes 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 web/core/local-db/worker/wa-sqlite/src/wa-sqlite.mjs create mode 100755 web/core/local-db/worker/wa-sqlite/src/wa-sqlite.wasm diff --git a/web/core/local-db/worker/db.ts b/web/core/local-db/worker/db.ts index 4afda1af4ff..77c10f6d05c 100644 --- a/web/core/local-db/worker/db.ts +++ b/web/core/local-db/worker/db.ts @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import * as Comlink from "comlink"; -import SQLiteESMFactory from "./wa-sqlite/dist/wa-sqlite.mjs"; import { OPFSCoopSyncVFS as MyVFS } from "./wa-sqlite/src/OPFSCoopSyncVFS"; import * as SQLite from "./wa-sqlite/src/sqlite-api"; +import SQLiteESMFactory from "./wa-sqlite/src/wa-sqlite.mjs"; type TQueryProps = { sql: string; diff --git a/web/core/local-db/worker/wa-sqlite/src/wa-sqlite.mjs b/web/core/local-db/worker/wa-sqlite/src/wa-sqlite.mjs new file mode 100644 index 00000000000..7ba5e77d463 --- /dev/null +++ b/web/core/local-db/worker/wa-sqlite/src/wa-sqlite.mjs @@ -0,0 +1,16 @@ + +var Module = (() => { + var _scriptName = import.meta.url; + + return ( +function(moduleArg = {}) { + var moduleRtn; + +var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];var wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);function findWasmBinary(){if(Module["locateFile"]){var f="wa-sqlite.wasm";if(!isDataURI(f)){return locateFile(f)}return f}return new URL("wa-sqlite.wasm",import.meta.url).href}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["pa"];updateMemoryViews();wasmTable=wasmExports["hf"];addOnInit(wasmExports["qa"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var tempDouble;var tempI64;function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};function getValue(ptr,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":return HEAP8[ptr];case"i8":return HEAP8[ptr];case"i16":return HEAP16[ptr>>1];case"i32":return HEAP32[ptr>>2];case"i64":abort("to do getValue(i64) use WASM_BIGINT");case"float":return HEAPF32[ptr>>2];case"double":return HEAPF64[ptr>>3];case"*":return HEAPU32[ptr>>2];default:abort(`invalid type for getValue: ${type}`)}}var noExitRuntime=Module["noExitRuntime"]||true;function setValue(ptr,value,type="i8"){if(type.endsWith("*"))type="*";switch(type){case"i1":HEAP8[ptr]=value;break;case"i8":HEAP8[ptr]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":abort("to do setValue(i64) use WASM_BIGINT");case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;case"*":HEAPU32[ptr>>2]=value;break;default:abort(`invalid type for setValue: ${type}`)}}var stackRestore=val=>__emscripten_stack_restore(val);var stackSave=()=>_emscripten_stack_get_current();var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var ___assert_fail=(condition,filename,line,func)=>{abort(`Assertion failed: ${UTF8ToString(condition)}, at: `+[filename?UTF8ToString(filename):"unknown filename",line,func?UTF8ToString(func):"unknown function"])};var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:(...paths)=>PATH.normalize(paths.join("/")),join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else abort("initRandomDevice")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:(...args)=>{var resolvedPath="",resolvedAbsolute=false;for(var i=args.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?args[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else{}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size);return address};var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+length{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url).then(arrayBuffer=>{onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},err=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={r:0,"r+":2,w:512|64|1,"w+":512|64|2,a:1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class{constructor(errno){this.name="ErrnoError";this.errno=errno}},genericErrors:{},filesystems:null,syncFSRequests:0,FSStream:class{constructor(){this.shared={}}get object(){return this.node}set object(val){this.node=val}get isRead(){return(this.flags&2097155)!==1}get isWrite(){return(this.flags&2097155)!==0}get isAppend(){return this.flags&1024}get flags(){return this.shared.flags}set flags(val){this.shared.flags=val}get position(){return this.shared.position}set position(val){this.shared.position=val}},FSNode:class{constructor(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev;this.readMode=292|73;this.writeMode=146}get read(){return(this.mode&this.readMode)===this.readMode}set read(val){val?this.mode|=this.readMode:this.mode&=~this.readMode}get write(){return(this.mode&this.writeMode)===this.writeMode}set write(val){val?this.mode|=this.writeMode:this.mode&=~this.writeMode}get isFolder(){return FS.isDir(this.mode)}get isDevice(){return FS.isChrdev(this.mode)}},lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},dupStream(origStream,fd=-1){var stream=FS.createStream(origStream,fd);stream.stream_ops?.dup?.(stream);return stream},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push(...m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type,opts,mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;iFS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(input,output,error){if(input){FS.createDevice("/dev","stdin",input)}else{FS.symlink("/dev/tty","/dev/stdin")}if(output){FS.createDevice("/dev","stdout",null,output)}else{FS.symlink("/dev/tty","/dev/stdout")}if(error){FS.createDevice("/dev","stderr",null,error)}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack=""});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={MEMFS}},init(input,output,error){FS.initialized=true;input??=Module["stdin"];output??=Module["stdout"];error??=Module["stderr"];FS.createStandardStreams(input,output,error)},quit(){FS.initialized=false;for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]}setDataGetter(getter){this.getter=getter}cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true}get length(){if(!this.lengthKnown){this.cacheLength()}return this._length}get chunkSize(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=(...args)=>{FS.forceLoadFile(node);return fn(...args)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAP32[buf+12>>2]=stat.uid;HEAP32[buf+16>>2]=stat.gid;HEAP32[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAPU32[buf+48>>2]=atime%1e3*1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=mtime%1e3*1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=ctime%1e3*1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream},varargs:undefined,getStr(ptr){var ret=UTF8ToString(ptr);return ret}};function ___syscall_chmod(path,mode){try{path=SYSCALLS.getStr(path);FS.chmod(path,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_faccessat(dirfd,path,amode,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(amode&~7){return-28}var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchmod(fd,mode){try{FS.fchmod(fd,mode);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fchown32(fd,owner,group){try{FS.fchown(fd,owner,group);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function syscallGetVarargI(){var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret}var syscallGetVarargP=syscallGetVarargI;function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=syscallGetVarargI();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.dupStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=syscallGetVarargI();stream.flags|=arg;return 0}case 12:{var arg=syscallGetVarargP();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;function ___syscall_ftruncate64(fd,length_low,length_high){var length=convertI32PairToI53Checked(length_low,length_high);try{if(isNaN(length))return 61;FS.ftruncate(fd,length);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd)+1;if(sizeHEAPU32[ptr>>2]+HEAP32[ptr+4>>2]*4294967296;function ___syscall_utimensat(dirfd,path,times,flags){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path,true);var now=Date.now(),atime,mtime;if(!times){atime=now;mtime=now}else{var seconds=readI53FromI64(times);var nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){atime=now}else if(nanoseconds==1073741822){atime=-1}else{atime=seconds*1e3+nanoseconds/(1e3*1e3)}times+=16;seconds=readI53FromI64(times);nanoseconds=HEAP32[times+8>>2];if(nanoseconds==1073741823){mtime=now}else if(nanoseconds==1073741822){mtime=-1}else{mtime=seconds*1e3+nanoseconds/(1e3*1e3)}}if(mtime!=-1||atime!=-1){FS.utime(path,atime,mtime)}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __abort_js=()=>{abort("")};var __emscripten_runtime_keepalive_clear=()=>{noExitRuntime=false;runtimeKeepaliveCounter=0};var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var MONTH_DAYS_LEAP_CUMULATIVE=[0,31,60,91,121,152,182,213,244,274,305,335];var MONTH_DAYS_REGULAR_CUMULATIVE=[0,31,59,90,120,151,181,212,243,273,304,334];var ydayFromDate=date=>{var leap=isLeapYear(date.getFullYear());var monthDaysCumulative=leap?MONTH_DAYS_LEAP_CUMULATIVE:MONTH_DAYS_REGULAR_CUMULATIVE;var yday=monthDaysCumulative[date.getMonth()]+date.getDate()-1;return yday};function __localtime_js(time_low,time_high,tmPtr){var time=convertI32PairToI53Checked(time_low,time_high);var date=new Date(time*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var yday=ydayFromDate(date)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst}function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var timers={};var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;var maybeExit=()=>{if(!keepRuntimeAlive()){try{_exit(EXITSTATUS)}catch(e){handleException(e)}}};var callUserCallback=func=>{if(ABORT){return}try{func();maybeExit()}catch(e){handleException(e)}};var _emscripten_get_now;_emscripten_get_now=()=>performance.now();var __setitimer_js=(which,timeout_ms)=>{if(timers[which]){clearTimeout(timers[which].id);delete timers[which]}if(!timeout_ms)return 0;var id=setTimeout(()=>{delete timers[which];callUserCallback(()=>__emscripten_timeout(which,_emscripten_get_now()))},timeout_ms);timers[which]={id,timeout_ms};return 0};var __tzset_js=(timezone,daylight,std_name,dst_name)=>{var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);var winterOffset=winter.getTimezoneOffset();var summerOffset=summer.getTimezoneOffset();var stdTimezoneOffset=Math.max(winterOffset,summerOffset);HEAPU32[timezone>>2]=stdTimezoneOffset*60;HEAP32[daylight>>2]=Number(winterOffset!=summerOffset);var extractZone=timezoneOffset=>{var sign=timezoneOffset>=0?"-":"+";var absOffset=Math.abs(timezoneOffset);var hours=String(Math.floor(absOffset/60)).padStart(2,"0");var minutes=String(absOffset%60).padStart(2,"0");return`UTC${sign}${hours}${minutes}`};var winterName=extractZone(winterOffset);var summerName=extractZone(summerOffset);if(summerOffsetDate.now();var getHeapMax=()=>2147483648;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignMemory(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={USER:"web_user",LOGNAME:"web_user",PATH:"/",PWD:"/",HOME:"/home/web_user",LANG:lang,_:getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;return 0};function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf]=type;HEAP16[pbuf+2>>1]=flags;tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_sync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);if(stream.stream_ops?.fsync){return stream.stream_ops.fsync(stream)}return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var adapters_support=function(){const handleAsync=typeof Asyncify==="object"?Asyncify.handleAsync.bind(Asyncify):null;Module["handleAsync"]=handleAsync;const targets=new Map;Module["setCallback"]=(key,target)=>targets.set(key,target);Module["getCallback"]=key=>targets.get(key);Module["deleteCallback"]=key=>targets.delete(key);adapters_support=function(isAsync,key,...args){const receiver=targets.get(key);let methodName=null;const f=typeof receiver==="function"?receiver:receiver[methodName=UTF8ToString(args.shift())];if(isAsync){if(handleAsync){return handleAsync(()=>f.apply(receiver,args))}throw new Error("Synchronous WebAssembly cannot call async function")}const result=f.apply(receiver,args);if(typeof result?.then=="function"){console.error("unexpected Promise",f);throw new Error(`${methodName} unexpectedly returned a Promise`)}return result}};function _ipp(...args){return adapters_support(false,...args)}function _ipp_async(...args){return adapters_support(true,...args)}function _ippipppp(...args){return adapters_support(false,...args)}function _ippipppp_async(...args){return adapters_support(true,...args)}function _ippp(...args){return adapters_support(false,...args)}function _ippp_async(...args){return adapters_support(true,...args)}function _ipppi(...args){return adapters_support(false,...args)}function _ipppi_async(...args){return adapters_support(true,...args)}function _ipppiii(...args){return adapters_support(false,...args)}function _ipppiii_async(...args){return adapters_support(true,...args)}function _ipppiiip(...args){return adapters_support(false,...args)}function _ipppiiip_async(...args){return adapters_support(true,...args)}function _ipppip(...args){return adapters_support(false,...args)}function _ipppip_async(...args){return adapters_support(true,...args)}function _ipppj(...args){return adapters_support(false,...args)}function _ipppj_async(...args){return adapters_support(true,...args)}function _ipppp(...args){return adapters_support(false,...args)}function _ipppp_async(...args){return adapters_support(true,...args)}function _ippppi(...args){return adapters_support(false,...args)}function _ippppi_async(...args){return adapters_support(true,...args)}function _ippppij(...args){return adapters_support(false,...args)}function _ippppij_async(...args){return adapters_support(true,...args)}function _ippppip(...args){return adapters_support(false,...args)}function _ippppip_async(...args){return adapters_support(true,...args)}function _ipppppip(...args){return adapters_support(false,...args)}function _ipppppip_async(...args){return adapters_support(true,...args)}function _vppippii(...args){return adapters_support(false,...args)}function _vppippii_async(...args){return adapters_support(true,...args)}function _vppp(...args){return adapters_support(false,...args)}function _vppp_async(...args){return adapters_support(true,...args)}function _vpppip(...args){return adapters_support(false,...args)}function _vpppip_async(...args){return adapters_support(true,...args)}var uleb128Encode=(n,target)=>{if(n<128){target.push(n)}else{target.push(n%128|128,n>>7)}};var sigToWasmTypes=sig=>{var typeNames={i:"i32",j:"i64",f:"f32",d:"f64",e:"externref",p:"i32"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i{var sigRet=sig.slice(0,1);var sigParam=sig.slice(1);var typeCodes={i:127,p:127,j:126,f:125,d:124,e:111};target.push(96);uleb128Encode(sigParam.length,target);for(var i=0;i{if(typeof WebAssembly.Function=="function"){return new WebAssembly.Function(sigToWasmTypes(sig),func)}var typeSectionBody=[1];generateFuncType(sig,typeSectionBody);var bytes=[0,97,115,109,1,0,0,0,1];uleb128Encode(typeSectionBody.length,bytes);bytes.push(...typeSectionBody);bytes.push(2,7,1,1,101,1,102,0,0,7,5,1,1,102,0,0);var module=new WebAssembly.Module(new Uint8Array(bytes));var instance=new WebAssembly.Instance(module,{e:{f:func}});var wrappedFunc=instance.exports["f"];return wrappedFunc};var wasmTable;var getWasmTableEntry=funcPtr=>wasmTable.get(funcPtr);var updateTableMap=(offset,count)=>{if(functionsInTableMap){for(var i=offset;i{if(!functionsInTableMap){functionsInTableMap=new WeakMap;updateTableMap(0,wasmTable.length)}return functionsInTableMap.get(func)||0};var freeTableIndexes=[];var getEmptyTableSlot=()=>{if(freeTableIndexes.length){return freeTableIndexes.pop()}try{wasmTable.grow(1)}catch(err){if(!(err instanceof RangeError)){throw err}throw"Unable to grow wasm table. Set ALLOW_TABLE_GROWTH."}return wasmTable.length-1};var setWasmTableEntry=(idx,func)=>wasmTable.set(idx,func);var addFunction=(func,sig)=>{var rtn=getFunctionAddress(func);if(rtn){return rtn}var ret=getEmptyTableSlot();try{setWasmTableEntry(ret,func)}catch(err){if(!(err instanceof TypeError)){throw err}var wrapped=convertJsFunctionToWasm(func,sig);setWasmTableEntry(ret,wrapped)}functionsInTableMap.set(func,ret);return ret};var getCFunc=ident=>{var func=Module["_"+ident];return func};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var stackAlloc=sz=>__emscripten_stack_alloc(sz);var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={string:str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},array:arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return(...args)=>ccall(ident,returnType,argTypes,args,opts)};var getTempRet0=val=>__emscripten_tempret_get();var stringToUTF16=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var AsciiToString=ptr=>{var str="";while(1){var ch=HEAPU8[ptr++];if(!ch)return str;str+=String.fromCharCode(ch)}};var UTF16Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf-16le"):undefined;var UTF16ToString=(ptr,maxBytesToRead)=>{var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str};var UTF32ToString=(ptr,maxBytesToRead)=>{var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str};function intArrayToString(array){var ret=[];for(var i=0;i255){chr&=255}ret.push(String.fromCharCode(chr))}return ret.join("")}FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();adapters_support();var wasmImports={a:___assert_fail,aa:___syscall_chmod,da:___syscall_faccessat,ba:___syscall_fchmod,$:___syscall_fchown32,b:___syscall_fcntl64,_:___syscall_fstat64,y:___syscall_ftruncate64,U:___syscall_getcwd,Y:___syscall_lstat64,R:___syscall_mkdirat,W:___syscall_newfstatat,P:___syscall_openat,N:___syscall_readlinkat,M:___syscall_rmdir,Z:___syscall_stat64,K:___syscall_unlinkat,J:___syscall_utimensat,F:__abort_js,E:__emscripten_runtime_keepalive_clear,w:__localtime_js,u:__mmap_js,v:__munmap_js,G:__setitimer_js,Q:__tzset_js,n:_emscripten_date_now,g:_emscripten_get_now,H:_emscripten_resize_heap,S:_environ_get,T:_environ_sizes_get,o:_fd_close,I:_fd_fdstat_get,O:_fd_read,x:_fd_seek,V:_fd_sync,L:_fd_write,na:_ipp,r:_ipp_async,ka:_ippipppp,oa:_ippipppp_async,j:_ippp,k:_ippp_async,c:_ipppi,d:_ipppi_async,ga:_ipppiii,ha:_ipppiii_async,ia:_ipppiiip,ja:_ipppiiip_async,h:_ipppip,i:_ipppip_async,z:_ipppj,A:_ipppj_async,e:_ipppp,f:_ipppp_async,ea:_ippppi,fa:_ippppi_async,B:_ippppij,C:_ippppij_async,p:_ippppip,q:_ippppip_async,la:_ipppppip,ma:_ipppppip_async,D:_proc_exit,s:_vppippii,t:_vppippii_async,l:_vppp,m:_vppp_async,X:_vpppip,ca:_vpppip_async};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["qa"])();var _sqlite3_status64=Module["_sqlite3_status64"]=(a0,a1,a2,a3)=>(_sqlite3_status64=Module["_sqlite3_status64"]=wasmExports["ra"])(a0,a1,a2,a3);var _sqlite3_status=Module["_sqlite3_status"]=(a0,a1,a2,a3)=>(_sqlite3_status=Module["_sqlite3_status"]=wasmExports["sa"])(a0,a1,a2,a3);var _sqlite3_db_status=Module["_sqlite3_db_status"]=(a0,a1,a2,a3,a4)=>(_sqlite3_db_status=Module["_sqlite3_db_status"]=wasmExports["ta"])(a0,a1,a2,a3,a4);var _sqlite3_msize=Module["_sqlite3_msize"]=a0=>(_sqlite3_msize=Module["_sqlite3_msize"]=wasmExports["ua"])(a0);var _sqlite3_vfs_find=Module["_sqlite3_vfs_find"]=a0=>(_sqlite3_vfs_find=Module["_sqlite3_vfs_find"]=wasmExports["va"])(a0);var _sqlite3_vfs_register=Module["_sqlite3_vfs_register"]=(a0,a1)=>(_sqlite3_vfs_register=Module["_sqlite3_vfs_register"]=wasmExports["wa"])(a0,a1);var _sqlite3_vfs_unregister=Module["_sqlite3_vfs_unregister"]=a0=>(_sqlite3_vfs_unregister=Module["_sqlite3_vfs_unregister"]=wasmExports["xa"])(a0);var _sqlite3_release_memory=Module["_sqlite3_release_memory"]=a0=>(_sqlite3_release_memory=Module["_sqlite3_release_memory"]=wasmExports["ya"])(a0);var _sqlite3_soft_heap_limit64=Module["_sqlite3_soft_heap_limit64"]=(a0,a1)=>(_sqlite3_soft_heap_limit64=Module["_sqlite3_soft_heap_limit64"]=wasmExports["za"])(a0,a1);var _sqlite3_memory_used=Module["_sqlite3_memory_used"]=()=>(_sqlite3_memory_used=Module["_sqlite3_memory_used"]=wasmExports["Aa"])();var _sqlite3_hard_heap_limit64=Module["_sqlite3_hard_heap_limit64"]=(a0,a1)=>(_sqlite3_hard_heap_limit64=Module["_sqlite3_hard_heap_limit64"]=wasmExports["Ba"])(a0,a1);var _sqlite3_memory_highwater=Module["_sqlite3_memory_highwater"]=a0=>(_sqlite3_memory_highwater=Module["_sqlite3_memory_highwater"]=wasmExports["Ca"])(a0);var _sqlite3_malloc=Module["_sqlite3_malloc"]=a0=>(_sqlite3_malloc=Module["_sqlite3_malloc"]=wasmExports["Da"])(a0);var _sqlite3_malloc64=Module["_sqlite3_malloc64"]=(a0,a1)=>(_sqlite3_malloc64=Module["_sqlite3_malloc64"]=wasmExports["Ea"])(a0,a1);var _sqlite3_free=Module["_sqlite3_free"]=a0=>(_sqlite3_free=Module["_sqlite3_free"]=wasmExports["Fa"])(a0);var _sqlite3_realloc=Module["_sqlite3_realloc"]=(a0,a1)=>(_sqlite3_realloc=Module["_sqlite3_realloc"]=wasmExports["Ga"])(a0,a1);var _sqlite3_realloc64=Module["_sqlite3_realloc64"]=(a0,a1,a2)=>(_sqlite3_realloc64=Module["_sqlite3_realloc64"]=wasmExports["Ha"])(a0,a1,a2);var _sqlite3_str_vappendf=Module["_sqlite3_str_vappendf"]=(a0,a1,a2)=>(_sqlite3_str_vappendf=Module["_sqlite3_str_vappendf"]=wasmExports["Ia"])(a0,a1,a2);var _sqlite3_str_append=Module["_sqlite3_str_append"]=(a0,a1,a2)=>(_sqlite3_str_append=Module["_sqlite3_str_append"]=wasmExports["Ja"])(a0,a1,a2);var _sqlite3_str_appendchar=Module["_sqlite3_str_appendchar"]=(a0,a1,a2)=>(_sqlite3_str_appendchar=Module["_sqlite3_str_appendchar"]=wasmExports["Ka"])(a0,a1,a2);var _sqlite3_str_appendall=Module["_sqlite3_str_appendall"]=(a0,a1)=>(_sqlite3_str_appendall=Module["_sqlite3_str_appendall"]=wasmExports["La"])(a0,a1);var _sqlite3_str_appendf=Module["_sqlite3_str_appendf"]=(a0,a1,a2)=>(_sqlite3_str_appendf=Module["_sqlite3_str_appendf"]=wasmExports["Ma"])(a0,a1,a2);var _sqlite3_str_finish=Module["_sqlite3_str_finish"]=a0=>(_sqlite3_str_finish=Module["_sqlite3_str_finish"]=wasmExports["Na"])(a0);var _sqlite3_str_errcode=Module["_sqlite3_str_errcode"]=a0=>(_sqlite3_str_errcode=Module["_sqlite3_str_errcode"]=wasmExports["Oa"])(a0);var _sqlite3_str_length=Module["_sqlite3_str_length"]=a0=>(_sqlite3_str_length=Module["_sqlite3_str_length"]=wasmExports["Pa"])(a0);var _sqlite3_str_value=Module["_sqlite3_str_value"]=a0=>(_sqlite3_str_value=Module["_sqlite3_str_value"]=wasmExports["Qa"])(a0);var _sqlite3_str_reset=Module["_sqlite3_str_reset"]=a0=>(_sqlite3_str_reset=Module["_sqlite3_str_reset"]=wasmExports["Ra"])(a0);var _sqlite3_str_new=Module["_sqlite3_str_new"]=a0=>(_sqlite3_str_new=Module["_sqlite3_str_new"]=wasmExports["Sa"])(a0);var _sqlite3_vmprintf=Module["_sqlite3_vmprintf"]=(a0,a1)=>(_sqlite3_vmprintf=Module["_sqlite3_vmprintf"]=wasmExports["Ta"])(a0,a1);var _sqlite3_mprintf=Module["_sqlite3_mprintf"]=(a0,a1)=>(_sqlite3_mprintf=Module["_sqlite3_mprintf"]=wasmExports["Ua"])(a0,a1);var _sqlite3_vsnprintf=Module["_sqlite3_vsnprintf"]=(a0,a1,a2,a3)=>(_sqlite3_vsnprintf=Module["_sqlite3_vsnprintf"]=wasmExports["Va"])(a0,a1,a2,a3);var _sqlite3_snprintf=Module["_sqlite3_snprintf"]=(a0,a1,a2,a3)=>(_sqlite3_snprintf=Module["_sqlite3_snprintf"]=wasmExports["Wa"])(a0,a1,a2,a3);var _sqlite3_log=Module["_sqlite3_log"]=(a0,a1,a2)=>(_sqlite3_log=Module["_sqlite3_log"]=wasmExports["Xa"])(a0,a1,a2);var _sqlite3_randomness=Module["_sqlite3_randomness"]=(a0,a1)=>(_sqlite3_randomness=Module["_sqlite3_randomness"]=wasmExports["Ya"])(a0,a1);var _sqlite3_stricmp=Module["_sqlite3_stricmp"]=(a0,a1)=>(_sqlite3_stricmp=Module["_sqlite3_stricmp"]=wasmExports["Za"])(a0,a1);var _sqlite3_strnicmp=Module["_sqlite3_strnicmp"]=(a0,a1,a2)=>(_sqlite3_strnicmp=Module["_sqlite3_strnicmp"]=wasmExports["_a"])(a0,a1,a2);var _sqlite3_os_init=Module["_sqlite3_os_init"]=()=>(_sqlite3_os_init=Module["_sqlite3_os_init"]=wasmExports["$a"])();var _sqlite3_os_end=Module["_sqlite3_os_end"]=()=>(_sqlite3_os_end=Module["_sqlite3_os_end"]=wasmExports["ab"])();var _sqlite3_serialize=Module["_sqlite3_serialize"]=(a0,a1,a2,a3)=>(_sqlite3_serialize=Module["_sqlite3_serialize"]=wasmExports["bb"])(a0,a1,a2,a3);var _sqlite3_prepare_v2=Module["_sqlite3_prepare_v2"]=(a0,a1,a2,a3,a4)=>(_sqlite3_prepare_v2=Module["_sqlite3_prepare_v2"]=wasmExports["cb"])(a0,a1,a2,a3,a4);var _sqlite3_step=Module["_sqlite3_step"]=a0=>(_sqlite3_step=Module["_sqlite3_step"]=wasmExports["db"])(a0);var _sqlite3_column_int64=Module["_sqlite3_column_int64"]=(a0,a1)=>(_sqlite3_column_int64=Module["_sqlite3_column_int64"]=wasmExports["eb"])(a0,a1);var _sqlite3_reset=Module["_sqlite3_reset"]=a0=>(_sqlite3_reset=Module["_sqlite3_reset"]=wasmExports["fb"])(a0);var _sqlite3_exec=Module["_sqlite3_exec"]=(a0,a1,a2,a3,a4)=>(_sqlite3_exec=Module["_sqlite3_exec"]=wasmExports["gb"])(a0,a1,a2,a3,a4);var _sqlite3_column_int=Module["_sqlite3_column_int"]=(a0,a1)=>(_sqlite3_column_int=Module["_sqlite3_column_int"]=wasmExports["hb"])(a0,a1);var _sqlite3_finalize=Module["_sqlite3_finalize"]=a0=>(_sqlite3_finalize=Module["_sqlite3_finalize"]=wasmExports["ib"])(a0);var _sqlite3_deserialize=Module["_sqlite3_deserialize"]=(a0,a1,a2,a3,a4,a5,a6,a7)=>(_sqlite3_deserialize=Module["_sqlite3_deserialize"]=wasmExports["jb"])(a0,a1,a2,a3,a4,a5,a6,a7);var _sqlite3_database_file_object=Module["_sqlite3_database_file_object"]=a0=>(_sqlite3_database_file_object=Module["_sqlite3_database_file_object"]=wasmExports["kb"])(a0);var _sqlite3_backup_init=Module["_sqlite3_backup_init"]=(a0,a1,a2,a3)=>(_sqlite3_backup_init=Module["_sqlite3_backup_init"]=wasmExports["lb"])(a0,a1,a2,a3);var _sqlite3_backup_step=Module["_sqlite3_backup_step"]=(a0,a1)=>(_sqlite3_backup_step=Module["_sqlite3_backup_step"]=wasmExports["mb"])(a0,a1);var _sqlite3_backup_finish=Module["_sqlite3_backup_finish"]=a0=>(_sqlite3_backup_finish=Module["_sqlite3_backup_finish"]=wasmExports["nb"])(a0);var _sqlite3_backup_remaining=Module["_sqlite3_backup_remaining"]=a0=>(_sqlite3_backup_remaining=Module["_sqlite3_backup_remaining"]=wasmExports["ob"])(a0);var _sqlite3_backup_pagecount=Module["_sqlite3_backup_pagecount"]=a0=>(_sqlite3_backup_pagecount=Module["_sqlite3_backup_pagecount"]=wasmExports["pb"])(a0);var _sqlite3_clear_bindings=Module["_sqlite3_clear_bindings"]=a0=>(_sqlite3_clear_bindings=Module["_sqlite3_clear_bindings"]=wasmExports["qb"])(a0);var _sqlite3_value_blob=Module["_sqlite3_value_blob"]=a0=>(_sqlite3_value_blob=Module["_sqlite3_value_blob"]=wasmExports["rb"])(a0);var _sqlite3_value_text=Module["_sqlite3_value_text"]=a0=>(_sqlite3_value_text=Module["_sqlite3_value_text"]=wasmExports["sb"])(a0);var _sqlite3_value_bytes=Module["_sqlite3_value_bytes"]=a0=>(_sqlite3_value_bytes=Module["_sqlite3_value_bytes"]=wasmExports["tb"])(a0);var _sqlite3_value_bytes16=Module["_sqlite3_value_bytes16"]=a0=>(_sqlite3_value_bytes16=Module["_sqlite3_value_bytes16"]=wasmExports["ub"])(a0);var _sqlite3_value_double=Module["_sqlite3_value_double"]=a0=>(_sqlite3_value_double=Module["_sqlite3_value_double"]=wasmExports["vb"])(a0);var _sqlite3_value_int=Module["_sqlite3_value_int"]=a0=>(_sqlite3_value_int=Module["_sqlite3_value_int"]=wasmExports["wb"])(a0);var _sqlite3_value_int64=Module["_sqlite3_value_int64"]=a0=>(_sqlite3_value_int64=Module["_sqlite3_value_int64"]=wasmExports["xb"])(a0);var _sqlite3_value_subtype=Module["_sqlite3_value_subtype"]=a0=>(_sqlite3_value_subtype=Module["_sqlite3_value_subtype"]=wasmExports["yb"])(a0);var _sqlite3_value_pointer=Module["_sqlite3_value_pointer"]=(a0,a1)=>(_sqlite3_value_pointer=Module["_sqlite3_value_pointer"]=wasmExports["zb"])(a0,a1);var _sqlite3_value_text16=Module["_sqlite3_value_text16"]=a0=>(_sqlite3_value_text16=Module["_sqlite3_value_text16"]=wasmExports["Ab"])(a0);var _sqlite3_value_text16be=Module["_sqlite3_value_text16be"]=a0=>(_sqlite3_value_text16be=Module["_sqlite3_value_text16be"]=wasmExports["Bb"])(a0);var _sqlite3_value_text16le=Module["_sqlite3_value_text16le"]=a0=>(_sqlite3_value_text16le=Module["_sqlite3_value_text16le"]=wasmExports["Cb"])(a0);var _sqlite3_value_type=Module["_sqlite3_value_type"]=a0=>(_sqlite3_value_type=Module["_sqlite3_value_type"]=wasmExports["Db"])(a0);var _sqlite3_value_encoding=Module["_sqlite3_value_encoding"]=a0=>(_sqlite3_value_encoding=Module["_sqlite3_value_encoding"]=wasmExports["Eb"])(a0);var _sqlite3_value_nochange=Module["_sqlite3_value_nochange"]=a0=>(_sqlite3_value_nochange=Module["_sqlite3_value_nochange"]=wasmExports["Fb"])(a0);var _sqlite3_value_frombind=Module["_sqlite3_value_frombind"]=a0=>(_sqlite3_value_frombind=Module["_sqlite3_value_frombind"]=wasmExports["Gb"])(a0);var _sqlite3_value_dup=Module["_sqlite3_value_dup"]=a0=>(_sqlite3_value_dup=Module["_sqlite3_value_dup"]=wasmExports["Hb"])(a0);var _sqlite3_value_free=Module["_sqlite3_value_free"]=a0=>(_sqlite3_value_free=Module["_sqlite3_value_free"]=wasmExports["Ib"])(a0);var _sqlite3_result_blob=Module["_sqlite3_result_blob"]=(a0,a1,a2,a3)=>(_sqlite3_result_blob=Module["_sqlite3_result_blob"]=wasmExports["Jb"])(a0,a1,a2,a3);var _sqlite3_result_blob64=Module["_sqlite3_result_blob64"]=(a0,a1,a2,a3,a4)=>(_sqlite3_result_blob64=Module["_sqlite3_result_blob64"]=wasmExports["Kb"])(a0,a1,a2,a3,a4);var _sqlite3_result_double=Module["_sqlite3_result_double"]=(a0,a1)=>(_sqlite3_result_double=Module["_sqlite3_result_double"]=wasmExports["Lb"])(a0,a1);var _sqlite3_result_error=Module["_sqlite3_result_error"]=(a0,a1,a2)=>(_sqlite3_result_error=Module["_sqlite3_result_error"]=wasmExports["Mb"])(a0,a1,a2);var _sqlite3_result_error16=Module["_sqlite3_result_error16"]=(a0,a1,a2)=>(_sqlite3_result_error16=Module["_sqlite3_result_error16"]=wasmExports["Nb"])(a0,a1,a2);var _sqlite3_result_int=Module["_sqlite3_result_int"]=(a0,a1)=>(_sqlite3_result_int=Module["_sqlite3_result_int"]=wasmExports["Ob"])(a0,a1);var _sqlite3_result_int64=Module["_sqlite3_result_int64"]=(a0,a1,a2)=>(_sqlite3_result_int64=Module["_sqlite3_result_int64"]=wasmExports["Pb"])(a0,a1,a2);var _sqlite3_result_null=Module["_sqlite3_result_null"]=a0=>(_sqlite3_result_null=Module["_sqlite3_result_null"]=wasmExports["Qb"])(a0);var _sqlite3_result_pointer=Module["_sqlite3_result_pointer"]=(a0,a1,a2,a3)=>(_sqlite3_result_pointer=Module["_sqlite3_result_pointer"]=wasmExports["Rb"])(a0,a1,a2,a3);var _sqlite3_result_subtype=Module["_sqlite3_result_subtype"]=(a0,a1)=>(_sqlite3_result_subtype=Module["_sqlite3_result_subtype"]=wasmExports["Sb"])(a0,a1);var _sqlite3_result_text=Module["_sqlite3_result_text"]=(a0,a1,a2,a3)=>(_sqlite3_result_text=Module["_sqlite3_result_text"]=wasmExports["Tb"])(a0,a1,a2,a3);var _sqlite3_result_text64=Module["_sqlite3_result_text64"]=(a0,a1,a2,a3,a4,a5)=>(_sqlite3_result_text64=Module["_sqlite3_result_text64"]=wasmExports["Ub"])(a0,a1,a2,a3,a4,a5);var _sqlite3_result_text16=Module["_sqlite3_result_text16"]=(a0,a1,a2,a3)=>(_sqlite3_result_text16=Module["_sqlite3_result_text16"]=wasmExports["Vb"])(a0,a1,a2,a3);var _sqlite3_result_text16be=Module["_sqlite3_result_text16be"]=(a0,a1,a2,a3)=>(_sqlite3_result_text16be=Module["_sqlite3_result_text16be"]=wasmExports["Wb"])(a0,a1,a2,a3);var _sqlite3_result_text16le=Module["_sqlite3_result_text16le"]=(a0,a1,a2,a3)=>(_sqlite3_result_text16le=Module["_sqlite3_result_text16le"]=wasmExports["Xb"])(a0,a1,a2,a3);var _sqlite3_result_value=Module["_sqlite3_result_value"]=(a0,a1)=>(_sqlite3_result_value=Module["_sqlite3_result_value"]=wasmExports["Yb"])(a0,a1);var _sqlite3_result_error_toobig=Module["_sqlite3_result_error_toobig"]=a0=>(_sqlite3_result_error_toobig=Module["_sqlite3_result_error_toobig"]=wasmExports["Zb"])(a0);var _sqlite3_result_zeroblob=Module["_sqlite3_result_zeroblob"]=(a0,a1)=>(_sqlite3_result_zeroblob=Module["_sqlite3_result_zeroblob"]=wasmExports["_b"])(a0,a1);var _sqlite3_result_zeroblob64=Module["_sqlite3_result_zeroblob64"]=(a0,a1,a2)=>(_sqlite3_result_zeroblob64=Module["_sqlite3_result_zeroblob64"]=wasmExports["$b"])(a0,a1,a2);var _sqlite3_result_error_code=Module["_sqlite3_result_error_code"]=(a0,a1)=>(_sqlite3_result_error_code=Module["_sqlite3_result_error_code"]=wasmExports["ac"])(a0,a1);var _sqlite3_result_error_nomem=Module["_sqlite3_result_error_nomem"]=a0=>(_sqlite3_result_error_nomem=Module["_sqlite3_result_error_nomem"]=wasmExports["bc"])(a0);var _sqlite3_user_data=Module["_sqlite3_user_data"]=a0=>(_sqlite3_user_data=Module["_sqlite3_user_data"]=wasmExports["cc"])(a0);var _sqlite3_context_db_handle=Module["_sqlite3_context_db_handle"]=a0=>(_sqlite3_context_db_handle=Module["_sqlite3_context_db_handle"]=wasmExports["dc"])(a0);var _sqlite3_vtab_nochange=Module["_sqlite3_vtab_nochange"]=a0=>(_sqlite3_vtab_nochange=Module["_sqlite3_vtab_nochange"]=wasmExports["ec"])(a0);var _sqlite3_vtab_in_first=Module["_sqlite3_vtab_in_first"]=(a0,a1)=>(_sqlite3_vtab_in_first=Module["_sqlite3_vtab_in_first"]=wasmExports["fc"])(a0,a1);var _sqlite3_vtab_in_next=Module["_sqlite3_vtab_in_next"]=(a0,a1)=>(_sqlite3_vtab_in_next=Module["_sqlite3_vtab_in_next"]=wasmExports["gc"])(a0,a1);var _sqlite3_aggregate_context=Module["_sqlite3_aggregate_context"]=(a0,a1)=>(_sqlite3_aggregate_context=Module["_sqlite3_aggregate_context"]=wasmExports["hc"])(a0,a1);var _sqlite3_get_auxdata=Module["_sqlite3_get_auxdata"]=(a0,a1)=>(_sqlite3_get_auxdata=Module["_sqlite3_get_auxdata"]=wasmExports["ic"])(a0,a1);var _sqlite3_set_auxdata=Module["_sqlite3_set_auxdata"]=(a0,a1,a2,a3)=>(_sqlite3_set_auxdata=Module["_sqlite3_set_auxdata"]=wasmExports["jc"])(a0,a1,a2,a3);var _sqlite3_column_count=Module["_sqlite3_column_count"]=a0=>(_sqlite3_column_count=Module["_sqlite3_column_count"]=wasmExports["kc"])(a0);var _sqlite3_data_count=Module["_sqlite3_data_count"]=a0=>(_sqlite3_data_count=Module["_sqlite3_data_count"]=wasmExports["lc"])(a0);var _sqlite3_column_blob=Module["_sqlite3_column_blob"]=(a0,a1)=>(_sqlite3_column_blob=Module["_sqlite3_column_blob"]=wasmExports["mc"])(a0,a1);var _sqlite3_column_bytes=Module["_sqlite3_column_bytes"]=(a0,a1)=>(_sqlite3_column_bytes=Module["_sqlite3_column_bytes"]=wasmExports["nc"])(a0,a1);var _sqlite3_column_bytes16=Module["_sqlite3_column_bytes16"]=(a0,a1)=>(_sqlite3_column_bytes16=Module["_sqlite3_column_bytes16"]=wasmExports["oc"])(a0,a1);var _sqlite3_column_double=Module["_sqlite3_column_double"]=(a0,a1)=>(_sqlite3_column_double=Module["_sqlite3_column_double"]=wasmExports["pc"])(a0,a1);var _sqlite3_column_text=Module["_sqlite3_column_text"]=(a0,a1)=>(_sqlite3_column_text=Module["_sqlite3_column_text"]=wasmExports["qc"])(a0,a1);var _sqlite3_column_value=Module["_sqlite3_column_value"]=(a0,a1)=>(_sqlite3_column_value=Module["_sqlite3_column_value"]=wasmExports["rc"])(a0,a1);var _sqlite3_column_text16=Module["_sqlite3_column_text16"]=(a0,a1)=>(_sqlite3_column_text16=Module["_sqlite3_column_text16"]=wasmExports["sc"])(a0,a1);var _sqlite3_column_type=Module["_sqlite3_column_type"]=(a0,a1)=>(_sqlite3_column_type=Module["_sqlite3_column_type"]=wasmExports["tc"])(a0,a1);var _sqlite3_column_name=Module["_sqlite3_column_name"]=(a0,a1)=>(_sqlite3_column_name=Module["_sqlite3_column_name"]=wasmExports["uc"])(a0,a1);var _sqlite3_column_name16=Module["_sqlite3_column_name16"]=(a0,a1)=>(_sqlite3_column_name16=Module["_sqlite3_column_name16"]=wasmExports["vc"])(a0,a1);var _sqlite3_bind_blob=Module["_sqlite3_bind_blob"]=(a0,a1,a2,a3,a4)=>(_sqlite3_bind_blob=Module["_sqlite3_bind_blob"]=wasmExports["wc"])(a0,a1,a2,a3,a4);var _sqlite3_bind_blob64=Module["_sqlite3_bind_blob64"]=(a0,a1,a2,a3,a4,a5)=>(_sqlite3_bind_blob64=Module["_sqlite3_bind_blob64"]=wasmExports["xc"])(a0,a1,a2,a3,a4,a5);var _sqlite3_bind_double=Module["_sqlite3_bind_double"]=(a0,a1,a2)=>(_sqlite3_bind_double=Module["_sqlite3_bind_double"]=wasmExports["yc"])(a0,a1,a2);var _sqlite3_bind_int=Module["_sqlite3_bind_int"]=(a0,a1,a2)=>(_sqlite3_bind_int=Module["_sqlite3_bind_int"]=wasmExports["zc"])(a0,a1,a2);var _sqlite3_bind_int64=Module["_sqlite3_bind_int64"]=(a0,a1,a2,a3)=>(_sqlite3_bind_int64=Module["_sqlite3_bind_int64"]=wasmExports["Ac"])(a0,a1,a2,a3);var _sqlite3_bind_null=Module["_sqlite3_bind_null"]=(a0,a1)=>(_sqlite3_bind_null=Module["_sqlite3_bind_null"]=wasmExports["Bc"])(a0,a1);var _sqlite3_bind_pointer=Module["_sqlite3_bind_pointer"]=(a0,a1,a2,a3,a4)=>(_sqlite3_bind_pointer=Module["_sqlite3_bind_pointer"]=wasmExports["Cc"])(a0,a1,a2,a3,a4);var _sqlite3_bind_text=Module["_sqlite3_bind_text"]=(a0,a1,a2,a3,a4)=>(_sqlite3_bind_text=Module["_sqlite3_bind_text"]=wasmExports["Dc"])(a0,a1,a2,a3,a4);var _sqlite3_bind_text64=Module["_sqlite3_bind_text64"]=(a0,a1,a2,a3,a4,a5,a6)=>(_sqlite3_bind_text64=Module["_sqlite3_bind_text64"]=wasmExports["Ec"])(a0,a1,a2,a3,a4,a5,a6);var _sqlite3_bind_text16=Module["_sqlite3_bind_text16"]=(a0,a1,a2,a3,a4)=>(_sqlite3_bind_text16=Module["_sqlite3_bind_text16"]=wasmExports["Fc"])(a0,a1,a2,a3,a4);var _sqlite3_bind_value=Module["_sqlite3_bind_value"]=(a0,a1,a2)=>(_sqlite3_bind_value=Module["_sqlite3_bind_value"]=wasmExports["Gc"])(a0,a1,a2);var _sqlite3_bind_zeroblob=Module["_sqlite3_bind_zeroblob"]=(a0,a1,a2)=>(_sqlite3_bind_zeroblob=Module["_sqlite3_bind_zeroblob"]=wasmExports["Hc"])(a0,a1,a2);var _sqlite3_bind_zeroblob64=Module["_sqlite3_bind_zeroblob64"]=(a0,a1,a2,a3)=>(_sqlite3_bind_zeroblob64=Module["_sqlite3_bind_zeroblob64"]=wasmExports["Ic"])(a0,a1,a2,a3);var _sqlite3_bind_parameter_count=Module["_sqlite3_bind_parameter_count"]=a0=>(_sqlite3_bind_parameter_count=Module["_sqlite3_bind_parameter_count"]=wasmExports["Jc"])(a0);var _sqlite3_bind_parameter_name=Module["_sqlite3_bind_parameter_name"]=(a0,a1)=>(_sqlite3_bind_parameter_name=Module["_sqlite3_bind_parameter_name"]=wasmExports["Kc"])(a0,a1);var _sqlite3_bind_parameter_index=Module["_sqlite3_bind_parameter_index"]=(a0,a1)=>(_sqlite3_bind_parameter_index=Module["_sqlite3_bind_parameter_index"]=wasmExports["Lc"])(a0,a1);var _sqlite3_db_handle=Module["_sqlite3_db_handle"]=a0=>(_sqlite3_db_handle=Module["_sqlite3_db_handle"]=wasmExports["Mc"])(a0);var _sqlite3_stmt_readonly=Module["_sqlite3_stmt_readonly"]=a0=>(_sqlite3_stmt_readonly=Module["_sqlite3_stmt_readonly"]=wasmExports["Nc"])(a0);var _sqlite3_stmt_isexplain=Module["_sqlite3_stmt_isexplain"]=a0=>(_sqlite3_stmt_isexplain=Module["_sqlite3_stmt_isexplain"]=wasmExports["Oc"])(a0);var _sqlite3_stmt_explain=Module["_sqlite3_stmt_explain"]=(a0,a1)=>(_sqlite3_stmt_explain=Module["_sqlite3_stmt_explain"]=wasmExports["Pc"])(a0,a1);var _sqlite3_stmt_busy=Module["_sqlite3_stmt_busy"]=a0=>(_sqlite3_stmt_busy=Module["_sqlite3_stmt_busy"]=wasmExports["Qc"])(a0);var _sqlite3_next_stmt=Module["_sqlite3_next_stmt"]=(a0,a1)=>(_sqlite3_next_stmt=Module["_sqlite3_next_stmt"]=wasmExports["Rc"])(a0,a1);var _sqlite3_stmt_status=Module["_sqlite3_stmt_status"]=(a0,a1,a2)=>(_sqlite3_stmt_status=Module["_sqlite3_stmt_status"]=wasmExports["Sc"])(a0,a1,a2);var _sqlite3_sql=Module["_sqlite3_sql"]=a0=>(_sqlite3_sql=Module["_sqlite3_sql"]=wasmExports["Tc"])(a0);var _sqlite3_expanded_sql=Module["_sqlite3_expanded_sql"]=a0=>(_sqlite3_expanded_sql=Module["_sqlite3_expanded_sql"]=wasmExports["Uc"])(a0);var _sqlite3_value_numeric_type=Module["_sqlite3_value_numeric_type"]=a0=>(_sqlite3_value_numeric_type=Module["_sqlite3_value_numeric_type"]=wasmExports["Vc"])(a0);var _sqlite3_blob_open=Module["_sqlite3_blob_open"]=(a0,a1,a2,a3,a4,a5,a6,a7)=>(_sqlite3_blob_open=Module["_sqlite3_blob_open"]=wasmExports["Wc"])(a0,a1,a2,a3,a4,a5,a6,a7);var _sqlite3_blob_close=Module["_sqlite3_blob_close"]=a0=>(_sqlite3_blob_close=Module["_sqlite3_blob_close"]=wasmExports["Xc"])(a0);var _sqlite3_blob_read=Module["_sqlite3_blob_read"]=(a0,a1,a2,a3)=>(_sqlite3_blob_read=Module["_sqlite3_blob_read"]=wasmExports["Yc"])(a0,a1,a2,a3);var _sqlite3_blob_write=Module["_sqlite3_blob_write"]=(a0,a1,a2,a3)=>(_sqlite3_blob_write=Module["_sqlite3_blob_write"]=wasmExports["Zc"])(a0,a1,a2,a3);var _sqlite3_blob_bytes=Module["_sqlite3_blob_bytes"]=a0=>(_sqlite3_blob_bytes=Module["_sqlite3_blob_bytes"]=wasmExports["_c"])(a0);var _sqlite3_blob_reopen=Module["_sqlite3_blob_reopen"]=(a0,a1,a2)=>(_sqlite3_blob_reopen=Module["_sqlite3_blob_reopen"]=wasmExports["$c"])(a0,a1,a2);var _sqlite3_set_authorizer=Module["_sqlite3_set_authorizer"]=(a0,a1,a2)=>(_sqlite3_set_authorizer=Module["_sqlite3_set_authorizer"]=wasmExports["ad"])(a0,a1,a2);var _sqlite3_strglob=Module["_sqlite3_strglob"]=(a0,a1)=>(_sqlite3_strglob=Module["_sqlite3_strglob"]=wasmExports["bd"])(a0,a1);var _sqlite3_strlike=Module["_sqlite3_strlike"]=(a0,a1,a2)=>(_sqlite3_strlike=Module["_sqlite3_strlike"]=wasmExports["cd"])(a0,a1,a2);var _sqlite3_errmsg=Module["_sqlite3_errmsg"]=a0=>(_sqlite3_errmsg=Module["_sqlite3_errmsg"]=wasmExports["dd"])(a0);var _sqlite3_auto_extension=Module["_sqlite3_auto_extension"]=a0=>(_sqlite3_auto_extension=Module["_sqlite3_auto_extension"]=wasmExports["ed"])(a0);var _sqlite3_cancel_auto_extension=Module["_sqlite3_cancel_auto_extension"]=a0=>(_sqlite3_cancel_auto_extension=Module["_sqlite3_cancel_auto_extension"]=wasmExports["fd"])(a0);var _sqlite3_reset_auto_extension=Module["_sqlite3_reset_auto_extension"]=()=>(_sqlite3_reset_auto_extension=Module["_sqlite3_reset_auto_extension"]=wasmExports["gd"])();var _sqlite3_prepare=Module["_sqlite3_prepare"]=(a0,a1,a2,a3,a4)=>(_sqlite3_prepare=Module["_sqlite3_prepare"]=wasmExports["hd"])(a0,a1,a2,a3,a4);var _sqlite3_prepare_v3=Module["_sqlite3_prepare_v3"]=(a0,a1,a2,a3,a4,a5)=>(_sqlite3_prepare_v3=Module["_sqlite3_prepare_v3"]=wasmExports["id"])(a0,a1,a2,a3,a4,a5);var _sqlite3_prepare16=Module["_sqlite3_prepare16"]=(a0,a1,a2,a3,a4)=>(_sqlite3_prepare16=Module["_sqlite3_prepare16"]=wasmExports["jd"])(a0,a1,a2,a3,a4);var _sqlite3_prepare16_v2=Module["_sqlite3_prepare16_v2"]=(a0,a1,a2,a3,a4)=>(_sqlite3_prepare16_v2=Module["_sqlite3_prepare16_v2"]=wasmExports["kd"])(a0,a1,a2,a3,a4);var _sqlite3_prepare16_v3=Module["_sqlite3_prepare16_v3"]=(a0,a1,a2,a3,a4,a5)=>(_sqlite3_prepare16_v3=Module["_sqlite3_prepare16_v3"]=wasmExports["ld"])(a0,a1,a2,a3,a4,a5);var _sqlite3_get_table=Module["_sqlite3_get_table"]=(a0,a1,a2,a3,a4,a5)=>(_sqlite3_get_table=Module["_sqlite3_get_table"]=wasmExports["md"])(a0,a1,a2,a3,a4,a5);var _sqlite3_free_table=Module["_sqlite3_free_table"]=a0=>(_sqlite3_free_table=Module["_sqlite3_free_table"]=wasmExports["nd"])(a0);var _sqlite3_create_module=Module["_sqlite3_create_module"]=(a0,a1,a2,a3)=>(_sqlite3_create_module=Module["_sqlite3_create_module"]=wasmExports["od"])(a0,a1,a2,a3);var _sqlite3_create_module_v2=Module["_sqlite3_create_module_v2"]=(a0,a1,a2,a3,a4)=>(_sqlite3_create_module_v2=Module["_sqlite3_create_module_v2"]=wasmExports["pd"])(a0,a1,a2,a3,a4);var _sqlite3_drop_modules=Module["_sqlite3_drop_modules"]=(a0,a1)=>(_sqlite3_drop_modules=Module["_sqlite3_drop_modules"]=wasmExports["qd"])(a0,a1);var _sqlite3_declare_vtab=Module["_sqlite3_declare_vtab"]=(a0,a1)=>(_sqlite3_declare_vtab=Module["_sqlite3_declare_vtab"]=wasmExports["rd"])(a0,a1);var _sqlite3_vtab_on_conflict=Module["_sqlite3_vtab_on_conflict"]=a0=>(_sqlite3_vtab_on_conflict=Module["_sqlite3_vtab_on_conflict"]=wasmExports["sd"])(a0);var _sqlite3_vtab_config=Module["_sqlite3_vtab_config"]=(a0,a1,a2)=>(_sqlite3_vtab_config=Module["_sqlite3_vtab_config"]=wasmExports["td"])(a0,a1,a2);var _sqlite3_vtab_collation=Module["_sqlite3_vtab_collation"]=(a0,a1)=>(_sqlite3_vtab_collation=Module["_sqlite3_vtab_collation"]=wasmExports["ud"])(a0,a1);var _sqlite3_vtab_in=Module["_sqlite3_vtab_in"]=(a0,a1,a2)=>(_sqlite3_vtab_in=Module["_sqlite3_vtab_in"]=wasmExports["vd"])(a0,a1,a2);var _sqlite3_vtab_rhs_value=Module["_sqlite3_vtab_rhs_value"]=(a0,a1,a2)=>(_sqlite3_vtab_rhs_value=Module["_sqlite3_vtab_rhs_value"]=wasmExports["wd"])(a0,a1,a2);var _sqlite3_vtab_distinct=Module["_sqlite3_vtab_distinct"]=a0=>(_sqlite3_vtab_distinct=Module["_sqlite3_vtab_distinct"]=wasmExports["xd"])(a0);var _sqlite3_keyword_name=Module["_sqlite3_keyword_name"]=(a0,a1,a2)=>(_sqlite3_keyword_name=Module["_sqlite3_keyword_name"]=wasmExports["yd"])(a0,a1,a2);var _sqlite3_keyword_count=Module["_sqlite3_keyword_count"]=()=>(_sqlite3_keyword_count=Module["_sqlite3_keyword_count"]=wasmExports["zd"])();var _sqlite3_keyword_check=Module["_sqlite3_keyword_check"]=(a0,a1)=>(_sqlite3_keyword_check=Module["_sqlite3_keyword_check"]=wasmExports["Ad"])(a0,a1);var _sqlite3_complete=Module["_sqlite3_complete"]=a0=>(_sqlite3_complete=Module["_sqlite3_complete"]=wasmExports["Bd"])(a0);var _sqlite3_complete16=Module["_sqlite3_complete16"]=a0=>(_sqlite3_complete16=Module["_sqlite3_complete16"]=wasmExports["Cd"])(a0);var _sqlite3_libversion=Module["_sqlite3_libversion"]=()=>(_sqlite3_libversion=Module["_sqlite3_libversion"]=wasmExports["Dd"])();var _sqlite3_libversion_number=Module["_sqlite3_libversion_number"]=()=>(_sqlite3_libversion_number=Module["_sqlite3_libversion_number"]=wasmExports["Ed"])();var _sqlite3_threadsafe=Module["_sqlite3_threadsafe"]=()=>(_sqlite3_threadsafe=Module["_sqlite3_threadsafe"]=wasmExports["Fd"])();var _sqlite3_initialize=Module["_sqlite3_initialize"]=()=>(_sqlite3_initialize=Module["_sqlite3_initialize"]=wasmExports["Gd"])();var _sqlite3_shutdown=Module["_sqlite3_shutdown"]=()=>(_sqlite3_shutdown=Module["_sqlite3_shutdown"]=wasmExports["Hd"])();var _sqlite3_config=Module["_sqlite3_config"]=(a0,a1)=>(_sqlite3_config=Module["_sqlite3_config"]=wasmExports["Id"])(a0,a1);var _sqlite3_db_mutex=Module["_sqlite3_db_mutex"]=a0=>(_sqlite3_db_mutex=Module["_sqlite3_db_mutex"]=wasmExports["Jd"])(a0);var _sqlite3_db_release_memory=Module["_sqlite3_db_release_memory"]=a0=>(_sqlite3_db_release_memory=Module["_sqlite3_db_release_memory"]=wasmExports["Kd"])(a0);var _sqlite3_db_cacheflush=Module["_sqlite3_db_cacheflush"]=a0=>(_sqlite3_db_cacheflush=Module["_sqlite3_db_cacheflush"]=wasmExports["Ld"])(a0);var _sqlite3_db_config=Module["_sqlite3_db_config"]=(a0,a1,a2)=>(_sqlite3_db_config=Module["_sqlite3_db_config"]=wasmExports["Md"])(a0,a1,a2);var _sqlite3_last_insert_rowid=Module["_sqlite3_last_insert_rowid"]=a0=>(_sqlite3_last_insert_rowid=Module["_sqlite3_last_insert_rowid"]=wasmExports["Nd"])(a0);var _sqlite3_set_last_insert_rowid=Module["_sqlite3_set_last_insert_rowid"]=(a0,a1,a2)=>(_sqlite3_set_last_insert_rowid=Module["_sqlite3_set_last_insert_rowid"]=wasmExports["Od"])(a0,a1,a2);var _sqlite3_changes64=Module["_sqlite3_changes64"]=a0=>(_sqlite3_changes64=Module["_sqlite3_changes64"]=wasmExports["Pd"])(a0);var _sqlite3_changes=Module["_sqlite3_changes"]=a0=>(_sqlite3_changes=Module["_sqlite3_changes"]=wasmExports["Qd"])(a0);var _sqlite3_total_changes64=Module["_sqlite3_total_changes64"]=a0=>(_sqlite3_total_changes64=Module["_sqlite3_total_changes64"]=wasmExports["Rd"])(a0);var _sqlite3_total_changes=Module["_sqlite3_total_changes"]=a0=>(_sqlite3_total_changes=Module["_sqlite3_total_changes"]=wasmExports["Sd"])(a0);var _sqlite3_txn_state=Module["_sqlite3_txn_state"]=(a0,a1)=>(_sqlite3_txn_state=Module["_sqlite3_txn_state"]=wasmExports["Td"])(a0,a1);var _sqlite3_close=Module["_sqlite3_close"]=a0=>(_sqlite3_close=Module["_sqlite3_close"]=wasmExports["Ud"])(a0);var _sqlite3_close_v2=Module["_sqlite3_close_v2"]=a0=>(_sqlite3_close_v2=Module["_sqlite3_close_v2"]=wasmExports["Vd"])(a0);var _sqlite3_busy_handler=Module["_sqlite3_busy_handler"]=(a0,a1,a2)=>(_sqlite3_busy_handler=Module["_sqlite3_busy_handler"]=wasmExports["Wd"])(a0,a1,a2);var _sqlite3_progress_handler=Module["_sqlite3_progress_handler"]=(a0,a1,a2,a3)=>(_sqlite3_progress_handler=Module["_sqlite3_progress_handler"]=wasmExports["Xd"])(a0,a1,a2,a3);var _sqlite3_busy_timeout=Module["_sqlite3_busy_timeout"]=(a0,a1)=>(_sqlite3_busy_timeout=Module["_sqlite3_busy_timeout"]=wasmExports["Yd"])(a0,a1);var _sqlite3_interrupt=Module["_sqlite3_interrupt"]=a0=>(_sqlite3_interrupt=Module["_sqlite3_interrupt"]=wasmExports["Zd"])(a0);var _sqlite3_is_interrupted=Module["_sqlite3_is_interrupted"]=a0=>(_sqlite3_is_interrupted=Module["_sqlite3_is_interrupted"]=wasmExports["_d"])(a0);var _sqlite3_create_function=Module["_sqlite3_create_function"]=(a0,a1,a2,a3,a4,a5,a6,a7)=>(_sqlite3_create_function=Module["_sqlite3_create_function"]=wasmExports["$d"])(a0,a1,a2,a3,a4,a5,a6,a7);var _sqlite3_create_function_v2=Module["_sqlite3_create_function_v2"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8)=>(_sqlite3_create_function_v2=Module["_sqlite3_create_function_v2"]=wasmExports["ae"])(a0,a1,a2,a3,a4,a5,a6,a7,a8);var _sqlite3_create_window_function=Module["_sqlite3_create_window_function"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9)=>(_sqlite3_create_window_function=Module["_sqlite3_create_window_function"]=wasmExports["be"])(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9);var _sqlite3_create_function16=Module["_sqlite3_create_function16"]=(a0,a1,a2,a3,a4,a5,a6,a7)=>(_sqlite3_create_function16=Module["_sqlite3_create_function16"]=wasmExports["ce"])(a0,a1,a2,a3,a4,a5,a6,a7);var _sqlite3_overload_function=Module["_sqlite3_overload_function"]=(a0,a1,a2)=>(_sqlite3_overload_function=Module["_sqlite3_overload_function"]=wasmExports["de"])(a0,a1,a2);var _sqlite3_trace_v2=Module["_sqlite3_trace_v2"]=(a0,a1,a2,a3)=>(_sqlite3_trace_v2=Module["_sqlite3_trace_v2"]=wasmExports["ee"])(a0,a1,a2,a3);var _sqlite3_commit_hook=Module["_sqlite3_commit_hook"]=(a0,a1,a2)=>(_sqlite3_commit_hook=Module["_sqlite3_commit_hook"]=wasmExports["fe"])(a0,a1,a2);var _sqlite3_update_hook=Module["_sqlite3_update_hook"]=(a0,a1,a2)=>(_sqlite3_update_hook=Module["_sqlite3_update_hook"]=wasmExports["ge"])(a0,a1,a2);var _sqlite3_rollback_hook=Module["_sqlite3_rollback_hook"]=(a0,a1,a2)=>(_sqlite3_rollback_hook=Module["_sqlite3_rollback_hook"]=wasmExports["he"])(a0,a1,a2);var _sqlite3_autovacuum_pages=Module["_sqlite3_autovacuum_pages"]=(a0,a1,a2,a3)=>(_sqlite3_autovacuum_pages=Module["_sqlite3_autovacuum_pages"]=wasmExports["ie"])(a0,a1,a2,a3);var _sqlite3_wal_autocheckpoint=Module["_sqlite3_wal_autocheckpoint"]=(a0,a1)=>(_sqlite3_wal_autocheckpoint=Module["_sqlite3_wal_autocheckpoint"]=wasmExports["je"])(a0,a1);var _sqlite3_wal_hook=Module["_sqlite3_wal_hook"]=(a0,a1,a2)=>(_sqlite3_wal_hook=Module["_sqlite3_wal_hook"]=wasmExports["ke"])(a0,a1,a2);var _sqlite3_wal_checkpoint_v2=Module["_sqlite3_wal_checkpoint_v2"]=(a0,a1,a2,a3,a4)=>(_sqlite3_wal_checkpoint_v2=Module["_sqlite3_wal_checkpoint_v2"]=wasmExports["le"])(a0,a1,a2,a3,a4);var _sqlite3_wal_checkpoint=Module["_sqlite3_wal_checkpoint"]=(a0,a1)=>(_sqlite3_wal_checkpoint=Module["_sqlite3_wal_checkpoint"]=wasmExports["me"])(a0,a1);var _sqlite3_error_offset=Module["_sqlite3_error_offset"]=a0=>(_sqlite3_error_offset=Module["_sqlite3_error_offset"]=wasmExports["ne"])(a0);var _sqlite3_errmsg16=Module["_sqlite3_errmsg16"]=a0=>(_sqlite3_errmsg16=Module["_sqlite3_errmsg16"]=wasmExports["oe"])(a0);var _sqlite3_errcode=Module["_sqlite3_errcode"]=a0=>(_sqlite3_errcode=Module["_sqlite3_errcode"]=wasmExports["pe"])(a0);var _sqlite3_extended_errcode=Module["_sqlite3_extended_errcode"]=a0=>(_sqlite3_extended_errcode=Module["_sqlite3_extended_errcode"]=wasmExports["qe"])(a0);var _sqlite3_system_errno=Module["_sqlite3_system_errno"]=a0=>(_sqlite3_system_errno=Module["_sqlite3_system_errno"]=wasmExports["re"])(a0);var _sqlite3_errstr=Module["_sqlite3_errstr"]=a0=>(_sqlite3_errstr=Module["_sqlite3_errstr"]=wasmExports["se"])(a0);var _sqlite3_limit=Module["_sqlite3_limit"]=(a0,a1,a2)=>(_sqlite3_limit=Module["_sqlite3_limit"]=wasmExports["te"])(a0,a1,a2);var _sqlite3_open=Module["_sqlite3_open"]=(a0,a1)=>(_sqlite3_open=Module["_sqlite3_open"]=wasmExports["ue"])(a0,a1);var _sqlite3_open_v2=Module["_sqlite3_open_v2"]=(a0,a1,a2,a3)=>(_sqlite3_open_v2=Module["_sqlite3_open_v2"]=wasmExports["ve"])(a0,a1,a2,a3);var _sqlite3_open16=Module["_sqlite3_open16"]=(a0,a1)=>(_sqlite3_open16=Module["_sqlite3_open16"]=wasmExports["we"])(a0,a1);var _sqlite3_create_collation=Module["_sqlite3_create_collation"]=(a0,a1,a2,a3,a4)=>(_sqlite3_create_collation=Module["_sqlite3_create_collation"]=wasmExports["xe"])(a0,a1,a2,a3,a4);var _sqlite3_create_collation_v2=Module["_sqlite3_create_collation_v2"]=(a0,a1,a2,a3,a4,a5)=>(_sqlite3_create_collation_v2=Module["_sqlite3_create_collation_v2"]=wasmExports["ye"])(a0,a1,a2,a3,a4,a5);var _sqlite3_create_collation16=Module["_sqlite3_create_collation16"]=(a0,a1,a2,a3,a4)=>(_sqlite3_create_collation16=Module["_sqlite3_create_collation16"]=wasmExports["ze"])(a0,a1,a2,a3,a4);var _sqlite3_collation_needed=Module["_sqlite3_collation_needed"]=(a0,a1,a2)=>(_sqlite3_collation_needed=Module["_sqlite3_collation_needed"]=wasmExports["Ae"])(a0,a1,a2);var _sqlite3_collation_needed16=Module["_sqlite3_collation_needed16"]=(a0,a1,a2)=>(_sqlite3_collation_needed16=Module["_sqlite3_collation_needed16"]=wasmExports["Be"])(a0,a1,a2);var _sqlite3_get_clientdata=Module["_sqlite3_get_clientdata"]=(a0,a1)=>(_sqlite3_get_clientdata=Module["_sqlite3_get_clientdata"]=wasmExports["Ce"])(a0,a1);var _sqlite3_set_clientdata=Module["_sqlite3_set_clientdata"]=(a0,a1,a2,a3)=>(_sqlite3_set_clientdata=Module["_sqlite3_set_clientdata"]=wasmExports["De"])(a0,a1,a2,a3);var _sqlite3_get_autocommit=Module["_sqlite3_get_autocommit"]=a0=>(_sqlite3_get_autocommit=Module["_sqlite3_get_autocommit"]=wasmExports["Ee"])(a0);var _sqlite3_table_column_metadata=Module["_sqlite3_table_column_metadata"]=(a0,a1,a2,a3,a4,a5,a6,a7,a8)=>(_sqlite3_table_column_metadata=Module["_sqlite3_table_column_metadata"]=wasmExports["Fe"])(a0,a1,a2,a3,a4,a5,a6,a7,a8);var _sqlite3_sleep=Module["_sqlite3_sleep"]=a0=>(_sqlite3_sleep=Module["_sqlite3_sleep"]=wasmExports["Ge"])(a0);var _sqlite3_extended_result_codes=Module["_sqlite3_extended_result_codes"]=(a0,a1)=>(_sqlite3_extended_result_codes=Module["_sqlite3_extended_result_codes"]=wasmExports["He"])(a0,a1);var _sqlite3_file_control=Module["_sqlite3_file_control"]=(a0,a1,a2,a3)=>(_sqlite3_file_control=Module["_sqlite3_file_control"]=wasmExports["Ie"])(a0,a1,a2,a3);var _sqlite3_test_control=Module["_sqlite3_test_control"]=(a0,a1)=>(_sqlite3_test_control=Module["_sqlite3_test_control"]=wasmExports["Je"])(a0,a1);var _sqlite3_create_filename=Module["_sqlite3_create_filename"]=(a0,a1,a2,a3,a4)=>(_sqlite3_create_filename=Module["_sqlite3_create_filename"]=wasmExports["Ke"])(a0,a1,a2,a3,a4);var _sqlite3_free_filename=Module["_sqlite3_free_filename"]=a0=>(_sqlite3_free_filename=Module["_sqlite3_free_filename"]=wasmExports["Le"])(a0);var _sqlite3_uri_parameter=Module["_sqlite3_uri_parameter"]=(a0,a1)=>(_sqlite3_uri_parameter=Module["_sqlite3_uri_parameter"]=wasmExports["Me"])(a0,a1);var _sqlite3_uri_key=Module["_sqlite3_uri_key"]=(a0,a1)=>(_sqlite3_uri_key=Module["_sqlite3_uri_key"]=wasmExports["Ne"])(a0,a1);var _sqlite3_uri_boolean=Module["_sqlite3_uri_boolean"]=(a0,a1,a2)=>(_sqlite3_uri_boolean=Module["_sqlite3_uri_boolean"]=wasmExports["Oe"])(a0,a1,a2);var _sqlite3_uri_int64=Module["_sqlite3_uri_int64"]=(a0,a1,a2,a3)=>(_sqlite3_uri_int64=Module["_sqlite3_uri_int64"]=wasmExports["Pe"])(a0,a1,a2,a3);var _sqlite3_filename_database=Module["_sqlite3_filename_database"]=a0=>(_sqlite3_filename_database=Module["_sqlite3_filename_database"]=wasmExports["Qe"])(a0);var _sqlite3_filename_journal=Module["_sqlite3_filename_journal"]=a0=>(_sqlite3_filename_journal=Module["_sqlite3_filename_journal"]=wasmExports["Re"])(a0);var _sqlite3_filename_wal=Module["_sqlite3_filename_wal"]=a0=>(_sqlite3_filename_wal=Module["_sqlite3_filename_wal"]=wasmExports["Se"])(a0);var _sqlite3_db_name=Module["_sqlite3_db_name"]=(a0,a1)=>(_sqlite3_db_name=Module["_sqlite3_db_name"]=wasmExports["Te"])(a0,a1);var _sqlite3_db_filename=Module["_sqlite3_db_filename"]=(a0,a1)=>(_sqlite3_db_filename=Module["_sqlite3_db_filename"]=wasmExports["Ue"])(a0,a1);var _sqlite3_db_readonly=Module["_sqlite3_db_readonly"]=(a0,a1)=>(_sqlite3_db_readonly=Module["_sqlite3_db_readonly"]=wasmExports["Ve"])(a0,a1);var _sqlite3_compileoption_used=Module["_sqlite3_compileoption_used"]=a0=>(_sqlite3_compileoption_used=Module["_sqlite3_compileoption_used"]=wasmExports["We"])(a0);var _sqlite3_compileoption_get=Module["_sqlite3_compileoption_get"]=a0=>(_sqlite3_compileoption_get=Module["_sqlite3_compileoption_get"]=wasmExports["Xe"])(a0);var _sqlite3_sourceid=Module["_sqlite3_sourceid"]=()=>(_sqlite3_sourceid=Module["_sqlite3_sourceid"]=wasmExports["Ye"])();var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["Ze"])(a0);var _free=Module["_free"]=a0=>(_free=Module["_free"]=wasmExports["_e"])(a0);var _RegisterExtensionFunctions=Module["_RegisterExtensionFunctions"]=a0=>(_RegisterExtensionFunctions=Module["_RegisterExtensionFunctions"]=wasmExports["$e"])(a0);var _getSqliteFree=Module["_getSqliteFree"]=()=>(_getSqliteFree=Module["_getSqliteFree"]=wasmExports["af"])();var _main=Module["_main"]=(a0,a1)=>(_main=Module["_main"]=wasmExports["bf"])(a0,a1);var _libauthorizer_set_authorizer=Module["_libauthorizer_set_authorizer"]=(a0,a1,a2)=>(_libauthorizer_set_authorizer=Module["_libauthorizer_set_authorizer"]=wasmExports["cf"])(a0,a1,a2);var _libfunction_create_function=Module["_libfunction_create_function"]=(a0,a1,a2,a3,a4,a5,a6,a7)=>(_libfunction_create_function=Module["_libfunction_create_function"]=wasmExports["df"])(a0,a1,a2,a3,a4,a5,a6,a7);var _libhook_update_hook=Module["_libhook_update_hook"]=(a0,a1,a2)=>(_libhook_update_hook=Module["_libhook_update_hook"]=wasmExports["ef"])(a0,a1,a2);var _libprogress_progress_handler=Module["_libprogress_progress_handler"]=(a0,a1,a2,a3)=>(_libprogress_progress_handler=Module["_libprogress_progress_handler"]=wasmExports["ff"])(a0,a1,a2,a3);var _libvfs_vfs_register=Module["_libvfs_vfs_register"]=(a0,a1,a2,a3,a4,a5)=>(_libvfs_vfs_register=Module["_libvfs_vfs_register"]=wasmExports["gf"])(a0,a1,a2,a3,a4,a5);var _emscripten_builtin_memalign=(a0,a1)=>(_emscripten_builtin_memalign=wasmExports["jf"])(a0,a1);var __emscripten_timeout=(a0,a1)=>(__emscripten_timeout=wasmExports["kf"])(a0,a1);var __emscripten_tempret_get=()=>(__emscripten_tempret_get=wasmExports["lf"])();var __emscripten_stack_restore=a0=>(__emscripten_stack_restore=wasmExports["mf"])(a0);var __emscripten_stack_alloc=a0=>(__emscripten_stack_alloc=wasmExports["nf"])(a0);var _emscripten_stack_get_current=()=>(_emscripten_stack_get_current=wasmExports["of"])();var _sqlite3_version=Module["_sqlite3_version"]=5472;Module["getTempRet0"]=getTempRet0;Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["addFunction"]=addFunction;Module["setValue"]=setValue;Module["getValue"]=getValue;Module["UTF8ToString"]=UTF8ToString;Module["stringToUTF8"]=stringToUTF8;Module["lengthBytesUTF8"]=lengthBytesUTF8;Module["intArrayFromString"]=intArrayFromString;Module["intArrayToString"]=intArrayToString;Module["AsciiToString"]=AsciiToString;Module["UTF16ToString"]=UTF16ToString;Module["stringToUTF16"]=stringToUTF16;Module["UTF32ToString"]=UTF32ToString;Module["stringToUTF32"]=stringToUTF32;Module["writeArrayToMemory"]=writeArrayToMemory;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(){var entryFunction=_main;var argc=0;var argv=0;try{var ret=entryFunction(argc,argv);exitJS(ret,true);return ret}catch(e){return handleException(e)}}function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();if(shouldRunNow)callMain();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(()=>{setTimeout(()=>Module["setStatus"](""),1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;run();(function(){const AsyncFunction=Object.getPrototypeOf(async function(){}).constructor;let pAsyncFlags=0;Module["set_authorizer"]=function(db,xAuthorizer,pApp){if(pAsyncFlags){Module["deleteCallback"](pAsyncFlags);Module["_sqlite3_free"](pAsyncFlags);pAsyncFlags=0}pAsyncFlags=Module["_sqlite3_malloc"](4);setValue(pAsyncFlags,xAuthorizer instanceof AsyncFunction?1:0,"i32");const result=ccall("libauthorizer_set_authorizer","number",["number","number","number"],[db,xAuthorizer?1:0,pAsyncFlags]);if(!result&&xAuthorizer){Module["setCallback"](pAsyncFlags,(_,iAction,p3,p4,p5,p6)=>xAuthorizer(pApp,iAction,p3,p4,p5,p6))}return result}})();(function(){const AsyncFunction=Object.getPrototypeOf(async function(){}).constructor;const FUNC_METHODS=["xFunc","xStep","xFinal"];const mapFunctionNameToKey=new Map;Module["create_function"]=function(db,zFunctionName,nArg,eTextRep,pApp,xFunc,xStep,xFinal){const pAsyncFlags=Module["_sqlite3_malloc"](4);const target={xFunc,xStep,xFinal};setValue(pAsyncFlags,FUNC_METHODS.reduce((mask,method,i)=>{if(target[method]instanceof AsyncFunction){return mask|1<xUpdateHook(iUpdateType,dbName,tblName,lo32,hi32))}}})();(function(){const AsyncFunction=Object.getPrototypeOf(async function(){}).constructor;let pAsyncFlags=0;Module["progress_handler"]=function(db,nOps,xProgress,pApp){if(pAsyncFlags){Module["deleteCallback"](pAsyncFlags);Module["_sqlite3_free"](pAsyncFlags);pAsyncFlags=0}pAsyncFlags=Module["_sqlite3_malloc"](4);setValue(pAsyncFlags,xProgress instanceof AsyncFunction?1:0,"i32");ccall("libprogress_progress_handler","number",["number","number","number","number"],[db,nOps,xProgress?1:0,pAsyncFlags]);if(xProgress){Module["setCallback"](pAsyncFlags,_=>xProgress(pApp))}}})();(function(){const VFS_METHODS=["xOpen","xDelete","xAccess","xFullPathname","xRandomness","xSleep","xCurrentTime","xGetLastError","xCurrentTimeInt64","xClose","xRead","xWrite","xTruncate","xSync","xFileSize","xLock","xUnlock","xCheckReservedLock","xFileControl","xSectorSize","xDeviceCharacteristics","xShmMap","xShmLock","xShmBarrier","xShmUnmap"];const mapVFSNameToKey=new Map;Module["vfs_register"]=function(vfs,makeDefault){let methodMask=0;let asyncMask=0;VFS_METHODS.forEach((method,i)=>{if(vfs[method]){methodMask|=1<nEt#K$-s;w=xaZ6C&Zhm1Q4-b zOah`JPB^q;i%P2q3QpC1A#6Y1pP_-o zXPluXyK~ie4#Lzyw2kr6x2iBKe&g+DFuDe}wgGm4Pk;cA{!_VaD(9_H{cb-#pKF@4 znq1ogb<{Ggg{lGh>OjO$&(^1?M`sLLwfz|Z8i4likJm@z(YR~#JK1r76J3kn=h*LzmEUZ?Tb$?qbM5zeR`U5S;?7Af<#((7o(%VmN2jSz%VRBrB{nWT>`sr~E!k-Wh&mI>#{E6Z4oN*1x&xFI~aM%(K&kcv?g*Knh zRs8ARCwtA7kCQlQ!~oZ5^rE!ch<%(l_FmG6B8Kw_AG^fG&gCxID@qdIXe6x|{JLhl z=^BfpIP%WLagsD$l(ZKov3J~{y}04yDB+oJ_?%9nhqp`T{62ffZZUl{@@6}VsFm&Q zT$VH&u9@xAa8WysN20jha1GCM|1XbqNuv?9+AeM;F`Y$Ga}Ub)=q+(c=KUUfG^2&h zD2tka5$8#(;oQ~Ub`yLznhYcY`AHJ( z-`oG6T-02&=+P@c*?~z5Ov5ORMx#lCuI)Holw|FNEf0W=hARMLw6PGP(j0}7eH!fs zaDl|OcM%*E#kp%I`H}=`0`d~tP27?eW1_#kzz=AF1E|4ReA_jX#ay%;gxLc&i5qDO z8eOZIwwGzN;Byb2MeSyfu3WQ`!6>p3zPYUE!8IVX*^InzH{!xKV7R#524}wT1uR3$ zu9xk}V8FSmH9HPEw%UwLH;OEAT@cxH{A*?q9pJsOxk22HVh`$oJ9fptxuPAl7dA6^1-dvfX9K7qFub3@ zi{PE10Rp(m+Mul+Q_#n7rij(>Eiq)=*wfRVhpXv{0q3GiltewZgmR8?K`))OA(W&9 z5(CA-5E^boJd>#7v&R9lcQ7g(1hb0`V7meY(?9oU#Ve-MIdr{^#8<*79q4AS^=Zz&}hTqZZ8DI`y_^hkQa7rHvrQu zjuvFJ3cEFw-TpL^t|R6ikw(%K;XJ*y+GBj1=~5HpK$`?_HcX@W zFF=dT{nwd0eb8CdhY9)`BmCo|1(1?X&;>d?+_Yy4%?{hqn?av)0)Ietitz+lY5Iln zO6c1byy*U@xqxS|4;sx7AYx+!)P>GC=wJO`k}S~e+3UIcaJfp)6&*g>?O4~0qoBrf+_w%+tW!(L;>rWkbcXj;>#@**qf7-aax#?dx?(R+e>74ici^koL zI{rV$-Dgu@jl1hpzi!-Jm-;7+yU(Qlka73j$gdxF*Q9>KxI5Hu9Cz0?{ibpE>C_*} zx%Y>SyA%B3^x^#xL(}M#j&57aMyW1J>fo;`V%JHEs1~jg!_#5Cr-HExBYV_+#e!8GvPj& z`ppyWJ3YT;!hO5vpF81x-to_ya6jw#=TEqA_54W_?xvpKI^n+A^C#10iLZm?u$LYX~Mlf_J>ZmFZBFj6Yeta51(+KNc|BLZmU0X!o9#B zHQ{amdlT-xkw0d_eLVF~oNy=kCr!A|_xzJ5+~+{vgq!qFop2vZ{nIAgt>A9LeYWS1 zv-77U(%sYcr%k#KgS|<2bH|^~Q?NJbz60w`x+}pR zPhq`D_w9~2a$oQG6Q|sNwfu9Y-1$8}Gv(gY^P9N?4yW83!Qqs912~*=ze)V_ zr`(Mlf6|nD9XOnF=fQtd?oUmB%9ML8IGl1{?f4f=x!3gkX;bdi;Bd;l3J#oduS9&O z+_`YzlzRm@oO0*%{JJUk6>vD^UJeeY+{?h>lzS;0I3>y1IOV?F@te4x`$MPPCz}4S zDR*}64+qYcKVr(gB=<*7xwCSA)RenC^+!*+52XH>DffPOkWuIUNmFiT>YqI2cI5sk zQ*Kx0pE~8<(eY24at~zw*eUnd%pW)9{*w8pPq{y5{uzuV^Us=cf6V;IlzUIpk59XI zBg50~{>)EKyFX-pYT8}U@zc}p-prpc?S7Z}XHUD|X8y!!_nXW=XWHG9`I%{Vcjh-w zyI*I1%e4DI*FSgKUEcN2n|8m<{PU;XFEW49w7Wg=Tc_R6Gk@~5`&s5snRa(&{?uvr zmX?3PwEJo1Pn&k%&io6f-M2D-`n3CI=3g}J&W8`D-8V8{O}npWe%-XYG4oHDc3;c< zA=B=wnO{HczLNP3)9%Ze-#G2Ql=)55?hBbel)B(>+TD=(!>8TnGk?UiJFDT3r1!)h zHSIo^`J<=ZuGk+l?Jfg{)9$mGf6}yjbH_h<+FhUdr%b!+z~Qv}Oy-|9?XCfb-0Aq^ zrroE(;k5e{I0Q41e-_w?{K&NXWah_Da4*mN#0l>6=)n`*%fR6Y?j@O@KEdrm51!!u zn)+v-;QpNY6HmZu&Ya*r+VYzz*zsFVa6g0rPjH`t0Z(v$%>DCEa98G?AK{f%QF?iN z=zZNkbl=eaOmcqumh_G38`9UOuS?HMUz@%ry*0U|cX#im`1`%@^=|9k+WT(rquqOY zyIObp-*@lr{;qpl_cz^py1(uIp!@yq_qxx#y?aUg>+Y|*zv%wF`?Ky5Kkfdc`{VAN z-Iqi^>i)2MNB8dTy}eI$Z>7+8ySH?2?%vt^QSW!X*LQ!>yQBAp=oPK+bbs9Yb?;Zb zU-q8#tLWR^Z*_0#exv)%?(cg)jep+zS?{jiPkKM?-QN2_@9n*}^BSCr{7NBp8l!*w)7+ErRn?93)1(3u1nI3)Aytor9Vh- zPj61YmVP(ACA~HMM*5ZXd+Arxcc{bu^E^y}$&(*H>>i7$ySOh1r) zIekOt+VrgS%ydV(3nV?z{cHCx-9LB#)cs@k{_d^qH>Yn(A81?>|5y6z^i}CA({s~T zr01kBPhXb4G(9_gNqXjj9Se5#9_anG_m|$6x_|EdsrSd;Z+gG&{h@bX@BZGO^854q z@;~Ii&+pBDm;W~ZO@2>)cmC`ASNSjVU*tc}f0o~s|1|$e{^R`4{73l@^E>j}^B?5j z&%c-7mfxCxH@_vnIsZ=n?fhH$P5C$TZ{%OkZ_K}ze>MMd{-ykj`4{pV@;Bvg$j{4P zlfOEDU;f_wlKkTQJ^4lXMV)u&@9tdGc^AL$%>O69Fn>q>_WW)61^HX^x8%1b=jU(E zugEXYFY8>|d2iiiS=$McWn zSLGkgKazhq|4{zQ{M`H%`8oN^^B;9?P0sGUq<2>D%-)XPuKa=gulZl{&vpKs|0w%m zc1L!5_Ji!Lo$qD0X5Y$BHo=Vh*Q_jhkAKiTWK(v?x^%eZpIhV;}Z+FrU*zh%(S;iRLI zvC%*t3D7vJ;!sEkMb zA=S1cfGe)HQzZ4At#toOH_E6uLKnxb&m)>|1qf(w#NZssA^|;jO${y*DjC$T0<oW}$Y}O+OJ4Wu)juRS-kNb2_&enqhCuS*LTETdO}6G4;-N7*ppsQ!us2z>&(Y#MiN2?d+G75u-EB5SK`)*J`_ ztXow)Z;;S)0-0A8hYb=iA3rYI7jX)bC$2-Z%DDJZt4sp!kkR5vf&nUXlB8D<7j6ge z?Wgn+j8UHrqEUZP$7EO3-RYiplLPK^t9#nND|IzJRoj)BhZ z#bx}|lXJ3ssTF_*E>#m?@0?-R1CP>_M&jnIo~kv}jELx}+iG=nC>?PgK-*1kg@TM> z$1W+dBXh4aD=0nUE}rX8v=#gN^b2HFn8=FGDBS^30Xjyu3b%}Qf%qh<+FY;OG5l}4 zxbe}TB0fa=WY?}ATsN6V>%uv|=&W+~(G#X}OvYOdarWQsPne|T`0@qmyynD7)uOGY zI7WS&V_=mCR*BZR17pk=_XWp{&N8XWMa4(_K4r9j+@`lEFc3po1)~XMYiy-kJn&WP zaMMU089&%97OjkrLFfgjqt&${X%9@+8dRo>(}P&h&oK;M7Zq~57YHoA)=JZVw@PY0 z2$ia=p#1@aT~V5{1tx3}mDFQY?TWUl*HQJkb+$|Yn5d{6Cf=LP4?}S>t-d%NIBBk3 zNvoqNqT=j$AMTOyd0bR*gFdnF3i8i@CI z)8~85Cl2W@IvZ(?B(q%bu_1+$v6_zLsnY)|B7HW3NRNhsHHoIMcY?e?YW&Q=v`qVG z^@<1;*Co))9i~eLXXR!Dcd=<73aA>D(BC#Ns{{scbyPSWmQ2%^$ejs>Z@X}^Oz=x9 z!R~$x|A9_Ga!^t$Wo~I}*02JZZ1B*|4w8+zr$)5d7|r|)xM65*=NIiK$aI{_u5C^a z5)9Vsjvd_t_ zBI%h6CDd~2E`uTT^b$3^hJ!A4co>w*QT6jj<8EvW_W}g9b2jR)MwOborl&(cjhUx3 zT|~`!%DniaPd_Q(?5;{fwBjP^5G;Z8Actg@n?VJ%(=F_IbgJA>-EdXo)T({*&f+8L zSBQsc--pHs)^FBBbm$?Cgi!%MIN}<4SYj$c=#mjZGngTQdZ8=~Ze_uV$~x4C^hGEe z)!vtUFY~_Sj8&aV9mpB`Zoqu77>^Z7qo;_=gjGRGY0woAe6{&yq7k@5wfZpt+YvoY zq#DIt8kn~#@dJ<>eTFZ~{V#LhR8#%n%N~=U2RH0q;fCS;>vz9@eYme0*917OfdQi8 zKWJ6}7SE9bC~i}ct3r{hVBd5F>?jyR?-9PB)YVQI(pdM5G{vUAoK15e0lYXp&8#61 zRNU4{e;r31linr$h_)E~@+vXC4V9Ox$ED^Q;%?2dP4N|ZH#}bfM)2VqI={g9;*tmx z8?;C>L>)^8JXq=WsFITpc6(TZxK7b#QRrW-*8cG&(e{gRZ?;Mr=@qU^4y9q7sm%>B z(PrF9Up8jS`0!D9W!V zIM}Kn~L)U;D8UWKb%zolfmW}l%oBP2KfPufmXxE0+2=HkzYTo=K zY4+ua+v6hW12D7ANx%Wbu>I#~tI*vvD;m5}hLWc8wTumr5<)q|iK|h+1TK?B38Jw{ zt(sRaeH6;ju)nOraV^Z zB|0`&x+@}SftBtij+EfxT`((52d}F9U!ttrCGwR$|Q>RdQNC_9P5w=F`!Ux!Xro ztXf=Un|rZ~Jf0{bf#RbU9DQ^y;b|$v?8lX~O#K)mZI2}c_PC@EJh4+xrW|wA!*WSo zE}mb`SH-EJ{8FMgD#og)nkETy=tAp}m14YBe~qQ-B72KeC|<~eoM<v<^p}>=pt}E8>lcp~=4ipb!8{?pe zsZ;A-bb?VgJTg&tco;yYCjr^b>#)_(F_1QWwYx zLRn%nGm|W7zv^1u%4UkM-~hL!U7LnU`Mrta(c2gX|D9ej$j3y>&1AqK)x!^4cJdmY zs-?R?Td|`xXb{OD7mtmKm#sT{$9byfUvi9qY7|HB6VyHV2*mMC@O|-Ll;y`vyj=pX z{t0CXy<-ECLF42>v)WNeMWCNSUI8u4W*BPQP*7%GBSbhq?>5Rr=_1*%)q1Xe<2J~F zS96*4L;*(~N)sxD2&7g3LKlI4W-n zfL0Z4HN=Q2?X3)X>1i8z)L2h*HpWqvAH@Xhf|5RKro$GtV46Mld-d9g!wEzKN~6Nst=gLrX(&EKf)$={~19s{0>kjIyc3zlq$wgQa+LKx`va& z%Sv}Z)hT@G;Qu5hAefAAMis3pHze<%76AYy^J*S_dk|MwqZ*X?GKb}Mld9@JizgFk z1qDOR+d*QTI(;Q;UCe2NPglC4-&LdXQ#iSdECy0H2#gqMJF z+e_oQvRmB(r^4p+--n~;75=t8aMgio7y|21mhIx2*nHpW-@*;MKN{}K^{v+E{;E*E zzHh)kj$3V5WCOV!^pB9z81)tk0k|q92t~VGV8no|(^fIwZ`!Y? zXj1)~!m|K>QoTG1&^6JkJPVfqrAxV9db(WpcoaH#Ggi%5^oL(DQiW4XQ5n*BN@M#%S;@6IGZ}H7HzJ`JSY`L z3$gT8QauVHF~G{h8DDlA2Jx~Pp)5ww6AP@`0^eE>MZG=eS+S+x36+AA4KtVI>o5@j zA2j?vT;Mz5T|w7<$|muoFnn&54$$7xIx1R5Wme|JWpFa5aq&KSOAR;$b}9WcHu&w> zwCtqUvi5B*3_=cQIR+op1SjoOX?8VXhQNCGuF0>_9u5bAC44%^vH=Y@!GjM9S~B8{`;;;}GTR4S}eIh&jy8gU2WsUUVp zq^p)t5bj`%=@WuCEfE$$Rzitj*ai(L9MGZ(9>NByNDyrL1Hlk+8w`M~OZsMSzE)iy zPYoCp_3r+Uw#df8;AX_4mSuOjd4=SZHNjFhBO7EWs&i30O%pkIfMI1V6IZ0SmcLPj z^O)!BanDL8-@}oZ&uzZ#G11^C&OkW2w#v5PTQ_hF+tvgwPVxDe%g|y5(dfdOQ2s)F z1=X-br{aPGT%)?M9fAU!p;TmdDip~_6h$ydjOub=2Bp-%Pq!TJHRrmkx(QmvmS>5sjxhmhQ6#H`Ab$(~VB^ zfP-0!>9L^b9y5|u{91=jY!=}tOHkF3RWYvQgJ4}g@XD)NB_{VkweFT!Y$cA$I%&(T z74@wZ#%$@o%=Q@5BOaNOPRdmsQ+JI3waEq)uSNL;2wv++lX!Sm=1Bjd;w>aMpBLO# z!ha##Qnz-_8Jtcd;J&FtOoWk?og?rFn~KUzCCXI$;y9UUN81)^w%3;}1f}|5v=Lv0 zyEw;%%{yV#W$BZ?+@eU& zQ*eJ~^6+u4LqTa?A)uk42OxEb%Z|jeV*@mQrw)P0SCGu9UiPv`^Py`+Ah>0DRhmkY zzKT?5hfL)f4uHtzc@VcKxmd%g5&^~6lJt)?Co@ysfF1;JK*7kRH#kJqTg_8I=z`fG z-fJjyc&AO4N)`p8`M}_zS~atCmM-w9rs~{qstzDD!D~)MB6C-pCcpxT6|uwF#2x&? zhRZ;hNhuFj5r$I)m4^V);efe&p&XEKKVWU$1aP<-zOgxEF-jszo_B9Fvw|aTJB(9Y zk9H7-8EG>`@6FG~syUKkN%4(n;0khlE?rKY>dfPhCLX=!PjST+=ycU~)(xcT+gb8W zs$b~?VSiNk;-8UXf2rsj7xaA<_2bIi0VJV~0H60&x4C-xtG6GTLkP=Y>yV{=E?2r0 z3bmw?piV$v)&3qML#oYn>oiBi7_)J)y}v1 zE!AH>{JL+rnTmNx>Rij+^Wx`T%V~AN_UBf9=GvK$h8c)&y!o07?d+ttys>)cpt1V| zQ{!@oF>i(`9W)P&LB~q>Pqj=+3*CNGyhWo~QtkNOtSn;m^K`g7T_Rp8Kj7dU*Y=6NvQYRx-DEC-K=380lc$XoMR$ zm>Lx!sr+bEAD2nhJq^Y$&Ou`%Ckk+8OV{n;qQ0ZST{)!+BN&##9bHwQ#gG*DLQ|P< z%{|#|ioG1QV0M2NZNzehHXGE-)nIHWLgEC+pjDlz3!o!VGXESuG~ff7*vvBfgxqYF`$w-29soF^#Bu}xlHKkuyvw|NMMJ5P2}fY zr+ZLdBP-qwm60*dSp9Nw98y->(K~Xq^#nGitIG1&ek>l7brESTQpB7Ap3RWC;wU8$ z&`+2eMi+85zIyY0JR$W#Tg7k&ZnjbeG2!F4lW)rzrdX)D_tL0p70)&guO+XNCc&H^ zVi;HeN@ZMH>(SXi^LxWB&^hrtFwO^h{)~WHVy#@BLchg zfFjf|?_HQEW6kTSrFxXsv?d4VDrmNe%>oY^ilVTVX2=52v|^CX2d5sJQZQi<80YFY zKY`|OBgRBsI1r@_MUrmAlg44(;aNvA;;NfIt0DqU4iNb#O*xXrjy1n_uQ2!x%;G&d zK~a%w!_k9p*7#rQ)?La>n;cy0>!$iqb+ff;Z1yd5%|dCTm>%Wlofe`2w9O_NLZOii zPdH^mNern-pGpxT?((ev?@fI*`8`h70lDSTE2yQIKq@7uhA7ZB+$guy}Kc)pO}eAf=~Kt-+f=X)q@$ z^Q0tQ?}qckR14FH`=nuxt~%GIq3XMEUGW*Y)UDz|sBCTq0c9C&#moOTDxN$BpoSc^ zFa!K$B2F^zBj}g7cwwEv+x?oEDhk2@_WS_%$N|~^t(J?V_CYMn^V~%1q`L)>&y*^o zKv8@GLP&^*&AbFma$^M(5CE{!?KiAP4$B-1n{8BwECz!}7J~+-OfoGD0!n(>TOr?5h3H zXjf}Nf|zs_6c4(bl|e5y1*x!vU`|>BFlg!a$dAztJ*x*(xNT`ti>0|N$@?NU&EjJ% zut;)3m&~kDlT|?kp+oV%Lou_%>ZD}SoWm%jh^zZ{eR{j-aE%ikgm>^p#Daybh#W`< zN)zgAkk)vCvN|J6g~*nQi3d$BX+x7}7Dw*Qc9Og{ya2&7XQ_{Aql}^-P&6u^eHA?> zOpB}mAVo?R$t;%8X(DjM{!9itSeMxv(Vp&4*saf&>QJ3JY`t6sZ;+68o=mb!Z z*o#1`b%0=!jG^aFxv(tCUWupz;pNf@5;6N%hzbPsCb+f)Q>?I@TFC)!rDnq2N*aM1 z%iG5|>8@G19e(&x$qP#A{^`D~S_|5n-yLep8azv17E5YzS5j$b8ie(!6EH~@7<1u09q5i4(>Yxrt zYJ>ly@E4@xm`rU~%~J;pX9k4+1v-brl783YaISPC_;5EkGte|JqGzLqrme+Q%=)-; z(MtD3Y_DR@VR@ypASN0OjuKMuBPo|0>}-v=u0O9;3E1ahgOK`qTtj-ZNfd}KLZ}st z9(-<7$$&gav@(_?1@PL8_{boo7tt<-k~~W|x!YQ2Z?#>`?+Xdg)YSEw+$Jug@g!tc zJDd=yCe|*zp>fAdup5}TI|2m@)?J_T18W#8WlkP&5X+&>xzT6pUrUPHB8_;e6*QHr ze)TRMVI1%g7~_5riz*;;EordzIoTPSWX6#ZuPjM7>v(@zoFNCq7| zLE6nap(hxQ2o#e_GDrr<@9&EP<8$iM_JQ$^`V`T+KQgn3u3PEuj|NN~%d)1`AF#l- z_ySl(9OvF}tS-Mhs(x~1g!DukNDp0!KY@vsj(XEK=j_o}-JkZ-ZVBq9f(%#R8QmY=8!XAymSZ4I~Z7P;9G%dJO|RgnO>K z=teq#&7d??X$M!JMA_9y>7(?ajjQ^Cgrf4M_*aMV9mS(jbqzB?1QKObc8cpPBwj1W zLrla=4zrWlbe~5$g;D&~kF;p3E&l3CVv#`; zkpX@)PlIO}Gka-CMR6z$!x|yu6Lb?GK_K!8u+|5!QjHym3ivfgu6P@4Ev0l26mM4} z45m}8M{3*EIZ@eTW)PS)|aBq&=5u}c|eUWwW@8u$Ou7)UmESvz~I1~W>sX4$UW|&L>*CYa3bv4Boko}O4 zrU^f|gKkhd1#Vwigl!CvW0e?z&Jho6stO?Hij0lVF&Bg!ti%FS5|PZ>ft5QnM_NcM zHdp|fH?Xz>%>Xe_smHQ{%1p3S%V9Ze4uR$~e8(6**j{n^Mm)79UP+W`fpOd@$;3A_ zQ@u!jki!cycd}{$CF&m)AhTf$UeNA^c_bnqW(gk*!CX~#*4tEDN95?xIe8N)jwPHT zN#rl&n+4B8s{`QLSU1A#AN*m=*dhPs$8?Tamv%`cQY#EHneiRydsNgg1~BAQ-*E`q z1s+tG=U;n0A!vYflCcomqWb52cG*=|K{`^&5^iLlr4ocp3O+2jFx@gzeAw10T&R?h z$?9!-PEc~Qjt8vKwj~4TMqSh2ow`ON+@V=AxgQQtb7LQj9jTOm<17Ha9Rmuk056*E?gAcfWylS0$ z(ky+1TPB|Y6eFz>B*lxgNg7`=3Wdj>W>-3l~x&<9MoQKL>Kt4f>zD~RbviHL69qe3(sVC#bGD zdu|?5cKhT|w4w}<8Cm~P016PR26&#%)DA8mzFCE_s$^_?7(&q0MLOfMr^+Vp1T73l?pMI9nz7EzvrSYGkLoSZfTIT&&CEVXHoI`^Z{XImA(cs{W&?{HVv1S$$$&r@d zet!h+gzzBRC96}yzNW4e ziCQKt0b>gwNr4kA!)H#5a$ah{!hxGv#3JVaQ!Eg~!>WJ}C{H4mC()?3qZscLz?R&? zYPe7deU^mwacI$7jaqLJw@SsUp+PQ`Qs!3zM3b4RNro;Xci7d=l`zj9oZxKXVCO6l) zR!z0FYKms!gWVq?-@JcJgV@#V8WkLuLi2k_v3cYQ<49;*Aj2e$ExXPIHJmxH^~9W& zKxF@$<6az(n++>TBM{ud5{>G2;Sze|ul>zEOFBHLTwIr<6$~0gK=Y`1OO~w&9ycz> zAs`J`#=P$pbY#gLLT_6RXZSSl8B2`!EQ9#-9jL|fY$@DnG(&(v zt0LHf3k)Xs4+0bi&Y~2d4?1C>A>6Rt>L=$|lfU3#0sBKXv3o^Ri%P7STC52s$`3%y zaX^6%s0n5ydFBu>l@SK*?%FU?Iq}9CHflh7X1EL-wRQ+BZU#2boT-pwCLf0RWi_@h zUg>3+$TdGE`j-J*%{?V(P#46Il4;{^(FBqo5Ii81qJ+hshQum0h|X5Hl`ye}fa+1m zca!9kdaLl0(6wDA=XANEy4h_JUpA}D*$RYHaARW`9yX7aB(`}eEH4eQSSq-T%3#h{ zD`kd<@&j%nW>G-VL4##gym_#V0ppKdRgNe`DHX=tb)EM$5?H5S6%1Ck>**nFbh zfXMwd>;W^8Ledtppp=P!*X#A79>WStV>jf4(ZU3@U0QsIbwxcz8(bYnzGt3ef;8EP zDtK`NnibC6!0rn%y)I#Tt(aaQ`5b0-T*{Lk;RAV(V2v$Z z!EgnY6OW17M@UU1@=ALghM|iVE^5*UXiYg$Z_u?g%|EOnHmt7G-dpU=XY^JKEz({b z?5~(GvR37%(l}g#N}eCjDMN{Q?Fc-qpTG-F)gYh23(RL$I%X|!F_0#>WC$p=G$Da5 z?=P0-pjo_7q}N(O-kZI$Ui4`w&VPH zn-Udmj6~=-kCEC)icm&$sw@bpU9Getj#N@-7;HI{1Kh*0U)A~b#i;%nZ;lK zynFnm6vACPXpt}RaN z*K8Y-aAHPL$P`^#d`dz?u1#zGaATlAqj+gFn`y=Pt_-0s9xG{yI7Dy4M#M0&`Ui&S zH-1dCis_cdW1>;5ivt#oU(DDn+dPAMFazyEIF=MQYs(k7Toa=dF5Y8n?g((R>K>U{ zO&>+YQ(0F|J6T081_OTw4cV0Gia{*hj@)F_79S!D9F`8!8MzVE_@P?C=-G<)tojp| zmhT#F;%LHwZLu8~A;4CwNph86*ool{u`*XeZ1&)?WqWSLH1Z!bU9G5a=8kjXO<&r21|;t5vT+I zf^(Z#<(G7K$sPj0Gha%Hz;2<9?g$^&2rmw<7dk#HBtoU1toR5zE;r^fk5}jr;T5H;5xFe&=}J3R_cvw`7apw;n<_StNQB8J z@}M&QO*u9;2e*keoS_9Fwy;IwaaEdsLkbjG0D*wqDc;YzILnIRnz?e1vZx9c=y3`K zh3w^Z)Ekg&Ds#odB9xSn91|sBqZv6D zoDL1gtcp>=Sx!{aNN6=?6w{hJ++W5iHb$5$gZ~Rdh$--Y`x^!i*Ptx2y`Oa_)tBEN zRbOHHsg7!wHFSrx!AZ2zG|h1Jt_rU zn9VAO+yLDmH;$b*=SFH9`FRbKSQc8vu(Ne)=6DW&gB}iW*%LE?%bDT~QVgIH z_i;W-!|L1e2_yxl z8URATV8Y`w=F^K7Y@RD)H(|LHdhH8KXktv(&Jub^7E&Nshb4jzL4{=%vu)aq7E=b@ zM+YJgWMInztw}73Ysvkf65yDiHXc_#3~go_WL8laO31{MDMGVS>%o~K90xK*a)iaZ zd#O9@eYp%ZPwS??m9dz^$0GxSEas+0B5Os&xZDU}N@h2p0Ek&BgF+67wO4Do>tIp& z4cf$ZEYBVXR&2~|RACs#ut-qmz_$k!141^E&MI>87DjYvN;PeU5zPp3hRyFy^J)Pb zR~u-{!B~+!1;LW_O(jNzKm6@&{X%F^XelBgkUHd9nwW!-6JMm{siPV2RW> z6LBke%;8E8PvJY;q;hBXKs0s{LPhN*uwqyv)a=W@^<#<_7g@AATSy`@EQDSaKlJyc z@tD8G{ApbaSW!&-WlJIF_%d2>VYa^zryPO(P#HPBi_w~k#jtyDOJix41$IZBEMCJa zUbs_~53BF&yT)HXdq)y8c-R`=W4_`6}KYkb^59Y@*om`V1Z#+= zz{paHxuQ^;Y1dKzl!~-6oeeDi0kD0bG=)-+V1;Rz1ngLr5Vl&a#yD=0$My(F@(4&` z>yOLkrv4+u2w}(XK8mFt8S-n7oXfBE=5ldrY2GEkawjeKnU_S=oXtLRw0hO+qjDc{ z{6o}WP~{_*K}6sh<}qpx$FLZ+VQt#CNlJ^(1ts1C<_htu81-znV_ETGd_e6+<({0| z)C#edw!*or6EIdtV-44u|KM~XR3lM|<88YYSzmxmC|T90{*67>+8w+BDWx+k7C}56 zz!F!o&Y>E?$6;{6-PlP~pz+$RhV9AS%V;PQ(lm_-d+e?exg6%sZ3Yg#XaEJ_G=S7S z62>~rxq%pPzW@j5=8iZ+wQT9I-hLJ~lN)$_z?0Kj1FDmyg1A^;=3#q_@gbh7iE!XU z%EOyQx%eUO?fVe-9yafuIuokqMxOkgkq?3`K!1^qH`?X$nyG!6&5UbUWctH~cf&HK z39^I#Gg*lsLWR-lRNK$P!d|SFC3k4|AYpt96mGIDexaGNgpKlC%2Nu>pi^d>4A6(f zJwkSDu>4wl8^cJ1IMy+8J*+L0WN_T9&S9>ExIthDqQDtcWyNf$YFp&RYO@V+KHI%E zuGlc=D%3aB{Vb64YODLdgBW;q4l#y_q*8V*2+9yon3sd*At(kxbFI#GJ0EApjsaOg zQ4s_k3ox^-H!!bU5%{AOhpi!uvx7+Hp}-ay8+buZ@Jb&-PHN9Vi!)#|nB>@D=t}w& zTLaSTIRh5G;(68Ml`Hblg13B*{RAP&Y7Dt#1S8#NdO)Jc5}^NY^qr;9-_Ud(G7QvN zAj2x9K-Qv~#7?T-AO(oD&DiRp3d6Ch>d%E!Dy7i0kE6wd~j!Yn4$>BKLAyH4w)i&PZah_?$rzY0l)0%nc0_`T$U8gnP zXn7=$<$H!ni`cWWL_mzIe;JkTA(BALlrV^i@8!NqeuESHa2be<+brv1!sw4IXbv1h zxNGax;gS&BvQwO_7o}|CNY005z>yqo+@)2hP633e;yt8dF!Y4Py!tpAG?`GaysCv5 z2&<;nS<2{FI(#xXTp>tIGRod!)T(~WUP&z>X|lkR%>#h2Yp0^TRhD-X3}S>ad-C@8 z>&e*WA#AtP9kAv2UUYsNjmRwLVf`AbT}S=xkqvg#-yHQj^-S>?K4ynmoXB~vtO8lx zOg>G$t{!-8{T*oU33z*#7=bNUOL*n+R$B_o!>+<+aU@ZtUZ_EeEb3$4g<4IKD_3i1 zGS3nOuLzf;#2jIg(BPAgT`efKn3LV)ob{3HEy2U>YUzS}02`yYxG?4V@SU;SRLf7HjE0~%8FAz^(Jaa@g7@)fCy@=7kRc?+pF1r{(J~l71v9Mi8 z+d|hYE{Ju0BCvq5;o<@r=)AgvM4n=ssCxKmylIbV&u-~ATYki=b*d}lRX0olZibrY zswZx+l=Z3hvYEWP$r{Vxju7AGRc69qo?9=hm24Ex5(`<+WUGi?=zj@SSoNB-(u+oW zG}={?ohlJ5q$|Ck1t(m4OYy6a@4R|s^{83S!>JA0+oXcsR08=r$Z1_mK90qwG;#z= ztOwDe&5Uj8BRI@hEkdY^{|=D}unLPnark-`Ek)}9Xl z*~+ceg1$xCawJ#FZ{V&}Mp*LY(Fw!FizYCbhbOaxjzY~+ijbIGOVZdpbZLv5w$m!s zVtS$pEvBca)(*3#N$V=Lx3g^Y6*9BdVtCiVjleLXmG{8F8%F>HmX+C90TWhZpny&Q znBg0$8Q)r4c*gLM*{~`FRYNhd(_%16u<1!RvH_X@G1M%R`oIz-rsNHl1&K?!nvA3Z zbVe{-3bJ${zeZ^n>JzA1ozMWy>gK5WfRbtQHQ_3Ui+ZBbyzH%Y<=;sXDLZ4D%2FrPS6s(vExi+L@Ix<0Y6msP z5J@u0u_H^aZ06$GRe@}JP>e^LaGefJkAfwgEmti&W6&7J8sb zRpJv=n9!@0IRWqNQ>vTQ%y7l*CJWvl5`%?d@D{^h@sBVVNXM#m2uDW<@w?eETq2Yj zLvdDY`2D;1sqwoziqbIM%JKoN@A(UZo%3EgwiBO%b_c304Vzx??O1gKUX(5O!Wl=Ak0`&KMd^ipoo7XSktcF49 zEc6+%l0kE$zW6@xC1tsX0j!NR=pdw_XvA$ySt^f=!uld5HER`7h_6<$Oq+JTQCPd2B0!5p>-!=B_cP(BG&=wc5A5T*>+Fyba!~+FA zPAZsp$Z91N&X)u}wKlY9oq#jEbvub^R9+MDtxi}TjDBYtSj%F(8H3z5Za-MP*vE{( zij=8swMDn1MNpVP5Y}pxEZfkXx_`}|!R1%krXJQ3tY#3p$9Nej(FBW{CGCm5^l49^ z+*3MKNn2Ye4MMGW%@wGxBJ+xmJ@{v@JJ+^1MMU5X}}9B!I;qloHjnzJ+E3Xo)lj zscM5vjKzD!ae1JuoSJy1e!Y~&6PAOjW~trP3#td$Zo3$c#osXhnA84Zb*|l^w%@@v zJaPxay*ika1O-V=6)h`x#tlmMF%qAXTbcYGM0Zb+hfnl7Gy15JupGEQNMDW`yZ z89SL~TYC}6ARWuL=74=N%RFZ@1j8bdS-4C(7kwo`%#?T5?leV`>}RZ%c+ggLTV1VY zV3h;&Uh@su?el$6t^3u!_y@aNnlm=k3`j@ZRQqB#1_ii~N3#l$_vXoBarhgHbzx)* z@QYuSk-E?nAj4k>?3$Ev<{;8NS8sFnx{ z>0QJ&kcdpXm8J-h{5I5mUke^mT1O>#?O(a~+=GQuqgN3l4?2BcF2?qU$fir7h3I6> zh|<1@iGC)e)wFDFt676kyHG)9Ut!*i$1>>&nZ1aEX7MqRif3>^6#zBS>gy?_hL_ZH z&;X$oICGCR>8r=KmOLX#{M>zPJDlwzWGKzPwYQ)OopNamsNie1qJX!WC^;=tG^Zco zr@A__0a~XTpoMs$cqsVy;*zEF;*!vvSsEDvci0uvo{~#l34Pf z3!B}yP6x=L-a`YVC!!+ij0H|AdRkNanHn9_Pz>=8>e&Q!fW zpl+~-o&!Uo)Q$!4fL=gvoO*1JZSbNF+pM@xxm8+qsQID#99`4oiXyVbX|;pxEXqr7 zJ(d^1i;}o|dQ-;jZtFlhAQ09)#87)!KZ0lJO802<46BGqYrXg-w53iJ&y$a! zGqM8p#z{3Q1ct^ePbSy{Y^9bxEEzTs2S7F0MP)(AbDZ=k?|@#6ie}@=#nx3lkvo+ND?7QtE28NS_YS6tvbQ1BXo| zbs-$F?H{xS!0UzJcu!%OHSLxi@e>=9X@ZrQ+$mnJRoje@_H7)Z0VnmYG9HuD1IPyE z8Dij+$WqfJZiEJB+oABEwp91VkhtWH22UdOCJ?YctNrLY|FU(-8LY&%XwBGdR3$$DyE%O@)CP`ydhO7Pv}u%zIgRrsYl-B4#=&aI3)1 z@LCxKy<1eBGt}hsjG$B;5o6t4)QG*+9Z|3scV#*43k?Ay_11L}_sZum}t= zk}D6eTtXwHX#PTD(P6k#R-UkkO{dXjrnRqV@H!QkiF^TR zkd(EFTl))W1k_gYJS8G~p-vHzWq6+)I-+~ImkbvkbIHqP^&S&?*^l*L+yoC~d3c)^ z8ij>A;dLZ?(lGC&;TCzqasgZ1m@gzh#*kPhqldf=X3kHiWnR(2dP!})9uZI{hf3fO z;aN3Ups}M}!nY{U0RU_p30Z7|T@}=eajgJ%PXl*x?IiR1B;H=ko(A$g!m33D3?9~7 z1u?-l@7-_gHQ%KQXF)S3>M(*xM~Ft7Zgt;%7BqZU<1f6)z>O< zm-O}=F_;*x#Q&0SHM=ogTAfF?00kxoYYfZVMXvzzr!OqmbWoJ z=?3j@m!QdatoGl1|Ajm%d=kBq3lq!hgHkvf*GqN@y^eo>EQ%c6QPP25>G%THp%B~l z#jXl(a$@a{a)!{a9U>@1LM$NvH!1Y;Hw!yiN2<5=@p8Bxio+DnwP^o#dYHZ9w~UAh zbRT2BiR`a@j6@jJ2#uG|dFiSaFv=EXruk z53Yi%Z-j5rR*_!f%14I62ZwkK;LbsEhQ0z5;P_xCR7MNv8$*K3)==>YqB7A3h|*`< z`=j|Li@m|lt#o^>CwX^r5Qp$R7J(EO@3NipUOa6#m}`2cUKB`@iVQ%cGC+Gb-*(Zu zdO`lI%8_$`U4^nE=?5Q>Ck&fO8@RENpu;0w(TKdB6kH}eK~@w%_STdI$d>Z_%?DPM25=8R8- zI6j;>{3?nu1w14goPm=xB)qO2q|@u^*Z4DrG?@upYI$y6r7cAx4MW)gtMQ7H;g%{f zt{_2A>r#f0Tv4hCbEF$m#+H(H3&^tCn_Uq+XZfV`0Jv)s(ko_rPLTaqhS>9 zvF>19z4w++pz($y2(jD85EN_h3h`^Sr^em}%7owSJJGSNCg@VoztILn0|L|U`i=*} z)L$cB{)znPwf?CDh==QVeg5+XIMrI+*S3j~Q0eu0G{zp?|TmBqwd!T zQ-WO~3K-r3nU`8wk$(gSYe$I?0Ozuk^-33fZhb_;X);QhzkRXZl)9_MCp(Z)KL$wt zP-x>1l~EP|nxGd?b5P{DE85882lyxg1~t|Rm)zu4iB(KxR=Y6v*LsPR>Ss#rtL?fm z>fk}~{%$-d8=uP5xzydS)j$obW4fFjNPK9Km2MEeMDz6HCch8eCOQ(+XbSWBwM=DCeE!dD)pV4XRe zS4ZHj7BN)(^M*!I_5S8lk9aN7GYIb`4Jr`6PS4mM8@-<$?BrVHxJaF#VL|#_89Ti_ zeD_}6ggxJimT87GEFULD#UDU3TJD|}n@XT9jtD*Z;!^xNv0w2V)RMgAv@g+0_cqJG z2U%rf(6)SX+dfYorGJQLzlYa=hCoGM_Hl}9yLwRoY)lo?QDi1ER0KEqATmhg9mAeT zPY8rhsi(H3F7e2LmJbSXLnLP%GO?m)AsJ>6Rs@lys@W#QJ}C~RYpTh)QhSV9l3ZMB zi#@m!KhPR%BQX_38YAcH3I=BR0$y6KXQ31at21oX?7r#Xsw)LV;{qM+bt)gD1e067#`UHm{TCR-bpdEuF;YkcBZ-xZiW;Nx6E8nzn zoJ3#phmc)eX9IKq2h|X{p%c|KH)h}Mi23jabhnx;1PJdr3=+>&kGOO0pG9McTnGgS z&E|&!`dSey$0EMt&;T`&zEK3;2@Ev17FA!-$J#i`R}g5)O7|4tVMyd@5{7|l3ao}ZHI?vxkwMu5} zgY&%4wi2I`emSMM2ggs*(f1saj7ZKS$`MU1ZH$#cMu8iB zA=YyYu2zCtPzo65Bvg+Hr{o@3LrbfrGsZ9w;40{E>@-fupBL~3N3@+ zd98{)`w=%dA*KQqK~g2U)LB~{q!<|VF9S3Mr}(faP#`V*-BtlN}g|3wDjS1;}NbffBgPOx*>d!L2uiZvrEqd zbP~QDAJ-wQ)e7Q;O?0e0Q*1p%6!D7RYl3^|zhb0b=IajS5zq=RLYt{NGa*qE?&!LB zz#0+*2$R=F_9bQwmkEF9j)C@7%G9nbfP_<{fo?`8e69Kk+h)aa)ivR<&2f1p5oVtQ zDh;$x8;7rdR zzm*zIzKaa21glZ~byqz61Cz9O64ft{*|^1dbf^y7wpI`9;*OF&>7mB1@;VBjSQJ)a zQ18nglv(r4Z3=wN1 zI7lloG)qifc_3T*doWPxV#Y_fASKodFC35**IovvOIeu`%Yvfc#A{m=5GGosi$1eY z-mykP6MOn1T%Yf^QD>9Q#)II0tv+E{Ew;FO(8${qDx5*nHGrnG&Pum`Q0`$HD$4#q z@MUjHV5R21@|P)ZUExTu{oYk0$~-X;Ew9iEAB<*juXIdOv4R^A6sh2H*<$VBZJUzG z7=&tS$-2VQgfB_(UI;fhDSi1h|BtV5ekpaBp! z`?5Q0uU;?{$YGuvb%9N|3c!JGLv47iDNn~LTL%ctXnE0;Nk09Ikt+f?!=Yu3#Jt63 zvd93fk4D!0&uv992v~JOev)>2a2d_^FBdJ3pTdHk5)U* zDYnY~bI%C2w;5<=`iKs96dQ(MC1d^HLfI%R%D`iD`3 zpi;=?MpE%PT^63AI5gQK{Y4&irCV)tOQ^3$R+e~5!rok@xFmP52aDg0PpUQLOC(4 z1Bi;RT9MFATiwvIL<;1|BjnRtYRQCaIh2ycF;p+NB^LpML-OrL{8~N?VIV1pK5pJj zpVb65KP}Z*b`Q7o2`dOz@n%%lUs@;Fl#Jx&CUynsnO;0-ScaaU6^|RNXcI#~sm8=( zGY+_ocktGYSPN}PV(AZOmwia4oAugsoL-c6t+EzKW$CWH=>>+|#B>I4&9@HNEEhUx z>g7pBv-+)z%ovRh7Bi#AN&Py=S+X@mHd+$dY*V5w-w$_ zT>6smGFZT5YI~(i_#Q0H^D5vVflZv=xAUqCyr0Y7 z=eEz~$*oD7w0-t&ASd*s34BT$+G6vZm!#?ks&o$vRzp1sdW8`PP9UrNq?F6&wA zw|?ulez)~ozeUo21Es4a{D7z9pitz{71^bH4;8yP{|fbfieNLtw&TB*nmS41GXqGB zod@590k8l+MucM|F32{vMf@8c)@o3-DXXOBE(_+QK{Xbv$?WsS zPpL6NNl!D3Fc>~z0T#yFN+>=VTdF=LCk-S=r@C|^5=lT71Xdtm__jIUM=Z0ZN9?zk zEs&IkhijNVx2+I?IVBE6V1!bRKkfn}80n+T4(2dUG#7h}mKoxSb5&uW$(QOJ+PH>x zN9-W7iqwHKXQ^m>YXpXJQ?Wi4$KG(Nqoh|fr_-@WIDf3LaNrTyMse+1)^BZYWfBQ! z{*icLDE%*KWdI5OBTE?Xpr*a}GNBm6)!sG#y(P5mrUBWk?fr3+(8kE}Pit?2=pd1hS!_^Zw7c}cL2#!*S-@p<@5_$%CJ%LjO z<7ylZvxG~;z{H66m6L*dcW6#~vHi;YP442#s<#ntRx?6qbP`VQq4nkD@y@aQD9mvM zEfI%SgteDqOYMxGvRx7D<7et~6He*|!LW=4QK0ztL4(EX4oBTKIZj!u3oy;-a@=Q6 z+3Nw98b*A67{jB{?S!k33quQH3S}-Oi%{yh5xVF&R#S13DpzSMBc{VJ6aiU5Z8G7D z(e0)@8WLkONiZs*HkNV#Hn7Wd<2ae-isj~Z7kE(o2+t54KB+sWK2pyvP8~bCxaW?+ z?Bbh$?h7A(3;)i&X(n$g(yJy6et#`D5oa>dejm_FXd3@di z;0dg=i$6SU#l^uE9;#I}TMG{xtYZ$)54*&-J^Ex+7!3wY^%2A{^xQsfn+J*ZZjgb= zgp*X7!$ixx$UuGSJP`#!ap|r%>~9P3blYQ`$G?SAei}-fLMz;}%mq(g$YGqrdIU;H z&#Yn1=sDF>D^af4SA&K_oue97rZn1N4-R> z6z#W7-FGK)^9!nkfdp!rPZiev8BuHo5yb20llwk%`gQjWKbaD5e6l5d!Z}cMFMSkW zJoNC-efGp}zw40~F8<=1KmUWL{@t(r)WdCKpUc`$C(@^+=1ZUITb=#DVBPb|?*wy4 z!QHxcNdNl(_`gQiS@!>^P^^0&A1!hYIN%x7K_J~79}vUb-|>OB_MTV11_}W!SXqIL zv!lfXZ=^tL+u6QvL_^i*hlm-XqAgZ`%l*aTQ;Laem;O$wFZ$m0HlTX@@gaP-4=*@rOU&EcTi@dUe(CD=;+sC$Le;XoVX7>)X?P!{;t}^5TnM@X-V3zvkv={rrPNs756j zgNsG~#pP@6AB@m{9M-??+f1bRPXPUiEYZtbTjunZ7)|MSoM!(aSm`>Fl$(}U^LeM7nt4SQ0%|L|LX z_}L%$qj!Dij>Z3c`X|2p?kC>!>2FBQeh&E-AMZ^c?-_m^1he>OPyB-`i%-64F@BzW z=*eHnsy{3H%~3y@+7}|P&twB{7Samd~Hr|*4$#}BypQp z-FpJweu$mCH9pVf^a0@PiH4;O3xwt3G)bE#wgCQ^6?)~h-7OZLk>2W z3yjQw2lf-N4r`nhf3PF6mmEH|+A)xGg2HEDXT}p9iW__}7x{_$@!g%kU)5QeA zPfAyEq@;)~&zoQG+ObdBXhPT+8g{tJXuu`x!vjQqEE1SwC|$J+*=T`ib|`JrXjV)8 zj47MBhRKI6G~>++Eml7(3ZY?kxk^+rgNas+rq!)5D_k=;rgjlaFcdtN*52#vcdhwzRXzn z!BTk-94|uy6r2 z&TzGIh41xR>!;&UW7 zXyQv5LI?3yp>^J6A?Yh9m9Lim?L^p+2I{CoFK( z4bEl5X1{_L`VpcUGDdJfxX6ow6d@YaW3a(R$=-sibyWw<%Csq#T34>((FzXojxmLGNhLpWqZ7GFZqB^EeT? z?Pgv2(oK8g?qA~F84VD?EZzcL(j>#Uri7+88wPG~l9QjiD8B~6rd(p}JvE{((i@^L zPk3vw_|HI}$9Tj??vNg~;G_Rvp$~lw4nZ8-wCrHbv;;M2TDBn-n#5;JOem;bFo}uz zPftz8`5&2-l7VYQ8p&L)nTBazw$t!wvo1}>HM0}?WZskzic8sNn}{wN%O>b>YRc6t zH~}B!__96T+j%;ipr8nbC5k8zG0T>VRnv6aWsydPXf#w}uKW;FSEnDm#engl>M*fe zv5JE-Bkvqf!BLHKi2x#8@4em|ixlLCaWQV#2w0^}cNsvLm*lnkH>vEkU<>&h4p9OK zI5C*mCmCW|R*nq(b_YMh0O+Qm@L{OoG?3y~504!N10ELLmRa)=lwnUKm3gJ@C(hxO z0*I$-#35aFiw10-?sTfR(5JMYgWl)_eDZ7MVTwvcz|p3F$7_ONpW`5@OPv+=G(GbE z&88xv8rOEMlO-gp2ldqtM;7Z?cz)>-l!sCZ*xCCnLb}0@@gJF*o+^>t91T!yW9#DkL);|shi6MhElOrlS+>8^?a0J;@;2LuL7BUWhPGt&S zHY*eg_7$aPZ{ws5i$kGNoPnI++(T|jqF$nK4Z083-B4?)Z{FHRVF6M{QCBGnN6~w( zcwngc_;7%e-GMa&XDv&=&H&zg_Cr&C=|&xjxm z<`0p$D9zi7Tw2nUQF9VhTAS`dvuNX~G&sQnJnexF__VQ~o8Nv)b@Tv5YN_eof=D-Y zQS-^Cl;B$i8E*v@pq){@463@xXd;kGTh);^U@FuR4q&2un$4odW#^IyASqUry^2-k z*rGCBeVj_zd1ox!G}y8J>J6}pZ-e}jiO>PJ0Ef2h2w$0#%*L?SjkFE=T@&R8*NpSR zm24It2(8jL9n0zpH!!*dG{Ir?YZ*8P-s|BieR#ie4lfwkJfbYpxb}KI+Eu((AMW-( za30E8+7U-BYJ2pAC64>(AsRl{MO;tU>a*!C9GKw4$OJr-tX;=a^>w4Z z!d2J$-G$1vo{b{wl6*Tk6sQZf;A6e-5bXl(Bqrg)(X**4dLP4GU_aRZRu?5mb>JQ; zMtq3xGRBqa^6C&f2lfdGDhP}JP1&g47#PZHa68|0UkP!2r-~newJW~{V4w&m=__5% zUkYBm;z$4hkBRI~SmC-#?fE#8wL!0&hPl0Y7S)(A?3Ai=&NxSlkPx5pxZR=>AE711 zM$xQ6R>+toDG;L3K%?wlDb|oCit|^6)6jp6kGBv#EbCg?EaxJu0R9b)!pTiyS412r zbtQ^ro=UM1-;gzTvt|bmW?+Lvdp8HF(B>juk>=?&3k`hDpCirPm{x_#COG3DQ z+x1>Xhr#&&a61db$FB#TemM?)w;#;{2q@h0RrGpyb@H*cM_r}{9g(edhliM_Fr_R- zy$^S23Ivg_ku`uk$07-@HV_YJ#B$KVP{}c zA(q^gj4F^+eLxFwNNj+gsy?K6`Y6cOOK=kpBaWVj&G1~qJmttrknXE~*#m`3yZVCE z2qfXsBOJ|#zJrzP+(RW9EBAr?*o-s=@*JlRjHk%Qlmn>Q?mk=i44dwd9;!HUPJ{Fr zmzPC)BC3A@gckyfUo;1359*L5M4J^qwR5-I^kcC}$}nMcz#|~cN%x$kDs7~#B2{YG zVd~Oedg-b5VQM;}@;t_!bv=icuP*JQc;L~-Yzq_VP@W&7i)F)tQp}E$jAy4#_KU?V zNv{}qm;`&hPBLpx)4=j6JTbvvPpX$uZ?LqwU;#1WtFYh|e-a!aroAU~_ensU(=rG; zKj_9zPPj8@muTZW6n?=a^#k{#*)6B4FN_%iM7W46N<~_3P``PJZGvOgN@;?zj=EVP zZD(^#?c0J2YH+hWl!xY1GU3gj4&$V0Y8*NTcoy4_SYu5i7VO0xn(ZmIm$HifpI9L( z2tx?rcV*7vj~m&79jmm(A*hr?VsZymD1txtCopzcpOmRYY-2e3(G%hMT9BbhhFh;;&H(0FWKkbW; zrQ%UCDi=Ggk^Fq)B!XEYrrMZMXeW!KB^)4whf_$QR)Of#<>tMw3k3L3@l1hdN5OpcLHaUG`?e6p)_zH450g5g z71je5tYarDQhl_PJ3tfUE2yJ-6T{@}LQWDmV}MZa{p}dxoFp8f08BcZ)>F~2@ry*> zg0i{N844LY%Dgw#O>h&ok~E|;(`t!m|Ja1hn=5k&xEa`1**t$(U;w$KDGlogi7H$E zzHwXizHGiBeZfXlt6bY^`>9jj>D~MLd?XneeLxP7zDpks+>C19J+Zj-_hdZ6srC18euix|K_Q?3>j&N#Z%ZoP{tS@`{qP`LhBmA{>;)gi<7MWC-v zRsWfhWca^|6E3eA0=j0Ej1nP`F1-;x@EthbN~5oUs|(mS$Rqn}K( zvYmKY4!>ixIo`)*cMQlr-H`UHdrDlBnYU=$>7ypvi*4a?1puHT&D01$Y@YmE%{L-{ z^E6v>B5;Bw8l70EztHbyK1KXQxSr~1UOiF@eDkZ>^%Tge-Jm1LxawbKd)3^ zGYB8j{P9_rXEo2z6d!nA31v%S7nk(|{^fwO2kw6!UTB;O7yI(!vf|$95^wpF3R0qd zKk?)DQ$m))6Pou=@c>P7HSs`t$6IcqK$LCoEekZ@eDv*vt@R$7D!Rw#-2D1zmX^;u zt&g9ThG}T1bI)2QH9pp2^qy6O`d$_^IxI%GHwqJTyx3RlqsZ{VVAAKy&0Q9}a$*C&V*P>vs>@w8@=Di{_>6|B8W z6?E2AP?rd8D#_1i=$;eqf@LQ9+m?P5aQah=5UxImsWm_XM?4l5`oh5TKO0ZgP&Eq- zeK*#gQPo+hX(5SLZHO9&K(x2LA>v(d^bi7L=E)T2dc&c?*w*jHMjX5C)X@iVsm!?; z!j3%>Nwdbtde?BQxIUyFG8#qK@4E!X06)Bwf733&d^a%ysji7s7oL!bWh82KfWlltBhR7)+crgTmWrjKzv z$V}8R%h{Fny@C0O6N1LKPPh)gyg7Mvu=!{o6|bHowZ;;($=dLk^h=4s7H}aToq7vE zh6z&7c>mH}Wh(S8w9=x_Tpz+m~SR7(9Z0QJg_ckQMO1-MgQ)&8kYoB%8?V2`fOF*^Ka2o!$Y zYdV~5!)br@-SwEE3MZJCOvbu*h)!kS#Gf=5`FlJ~eK}WtbdVo9bu@yE1ZzzpCTwWV zOg->HVT<2Q`MO}747^3mCe?k)*gw^76^g^5{_$yZ94|ts3*-l2(+x7|I1wgEiRXrV zB>k-1Cwb{#i;`4X9gAj_kz8B46}JBf&XX_s)20QD;}ujNA4Y+dzj29_d<)Hc zDSq$puGrU{hz|y_^X~mt)hwW-``zPdAIlh(eK20k^P-`QA%LNE7R^H3V~y`!R}vEW zNK~eU@i~fVV+luioO~B>qEN3$K(xWX+g`N z!yRlpIB;Q+al;b9Ut}si+evVQf z--Kmx2pWfg)pNHt)vE`bzQx7#tKsgPg1oVwy|tNmH7t2nQ^iYMVZa4fbeuYYUVGknxVd1Z(vQKULOxg z<+e1KiQ-$>YQgjAC?3zxEXRi&>vN^5C=YbL&S!K59;EY>C={C&%? zuV2!VE8$A;CDi-aPPuXdojOYo(6E_U&_nfS!5AsC5pG<%o3edzcf7F3E3_3nr&V(S z7R02fzGk?m-i&0Zz;>FSjevnDnsTXQfR2avppeVj6yLPZq7hAHI3!h8udWMNw4Iou zjp`>bbFb@tp};xE%R@#*Hg9Hdrnvi2R-Ytvsu%1P-16VV zK@u9k*>E88pQciWPK?9fXl7SNvPZiNmu*;#2<%yy1!=j&m;0%ZZ7x@otx$#QZPQ zb=zrvhIouFFDBAO zZ^`SKs0k?fbXf&Ze1ivRwF6_l=DE$K^p-$TqKQ|COKxY$c=e^6b!NNdvQ_m!^2S*; z4_IsC!3ZJoRK^hfw|xQxZfE{g_cAI7sW`=9*z>l&0SP4}c;IEKv6mo=g;npG-^4tu z9%CSts4>20;4iuW0=HJLwT4JqI>eh(R{k;G+=qwhfWq}v3KdvaTq zq?nLE%O<6uK%9p|%F+h!geJakTg0!kJ9eZ4xh^7|c8a+|6(a=qnKDCV3_yM%Tb@01&gg&nI+g!a=U(GYkk3Bqm?@RR(%HAAU;B z;l}f(w+ADdM|eeL6lPYFWFjgP%C$gmrmzm{R+*u&qyJa#6ZvS?mtOr89uXT^@F2Lu zh)07LO8&w@#)n&$7BW_{p+2Cq{zsu+Hrr(Y$toua&YM3!$r8hHmls5nY^Ot&poM;4 zI=qgiCew4WAKjX86-}aY5R+1OJQpmY4JIRihUK~`zJ4^8qmUzQ=nS7gtv26=&NM8a zOh1#B;X}mD3^)e|1<4!FXRFZ@xGRmEu|^m+dH)_yK{JdN7+OX1@6b0;#ICMYl+&ja z#XsFgY;eM@sYdHST`Y)j*9VmV4hiUfg_nW5aKt)4aZ#oD$pHYqVY?+K@CufUAdQFh zPOM_K+pJ?(p{buI!6LHmme|L|Ma;x>Djteb*1YSkPUPCP(9Nh!ZdZ-GUuY3=mi#mm zb7uQAiZjh&w1sjBxHO1|1!$>pefX^rE6r>F0V*UIX^<4fn5CrDXo}I!lrh8%mNEnE zNKd3yB?yiBUPH@lmtpan<#V1i|BfTT$v0J(r`xiW{=H(FcYL~W5Lwpzgl|IJtMiw1DviTyU+SLNQ%Sk^H|TNCYJ0? z$~gj;dljz^VzoUXnh(*X;GpQ;vR9WVUq+=^>aF%|o5{2ws=Af4ej&qOGj$m>dx)Fq zL*_o`l#ywcB^j#CkuMX(z=IT0XD}e9*ab^sMGoZKRfZGH$oIB6WIom@QBoZXsDN=m zg+!mlX8I-eqchA2p9C4gcUmHB#X-Ag+1xJN1n>nZ0S3t`o8I<<~id>@#3~h|< z%C0Q)5{P&RJW&VNJgvSwHjNvQuQYM#fkUQ4sFa|blqMIrDHg@0L+iDYl%JKWNX(i_ z^XbM=4^?$=E(%w`79HlK78=Z|Kc~yqfxE$8vBOjpP6`WFuhEdC7A$ljcbV?SrwV`FN}bjVh(F~fMm zlqs6jU%&M`ylg>69p@rs$$(#oxfpx~Dj)J0nAf-R^haQRH;5TNSJGN`1WP=)KzTAe z_A_)cl44iH_yEB4w)ArN34QS8Jz5#Og|2-Pp?J-MVSiXv>MGse!Z^Nvwd^p@fS(dG z0G&liRn81OGu*WJ$C}6Q33nLE7>86=50b(AT)|jbxxeLAiqCt;r8eyBCi5SA>v1xP zO=P;q+Q>w~W+4S$7$Haqpx~zvLG|0gk65p*yM)&(l#*hypNLBpDCEX!;a`H~%8Q5A zJ#|j#@1-3^0&RRczM#Vk_?xD1<1IvKnJB=eqc-_SdTLJNXq|!1xOczzfXvnzxI>_2 zdBz89Zi}f17O4c=qM8ndBdwnnt`u92pyq zdGI%5oUBPY@|F8KmlucV)7x4G6AWnBN4wK}X$`Db=}U3OV*o}t{u!OH_z+AFDnFw% zOBgxl$c9HlKTbFNIBu%yGk=q05&i>+K5~oFhnQr4Z^tXJhsq3+q?wV=kB+RF#r9*&ZY$N&agIe#Wk_`I8=~|o z4$n=Cn@-`-%t^0}Gh$3Qb8A?&_93WRe3J{D3`^5v^r!aYL{sZ>{nxPNct0nG3~I8@Zq9iXa=^jwb#-?SYVy?c0uT zRT5(7MW^?dJshS2slX(rKH`{~&ayD)q$M2?P2UwHdP@n$&+sj%O%fk4qGj{Rh~hQ_ z1n-ynblLx!N8&N2y)y|i!UO9rQ8(a0c?{72Tfb;N`c=FtQM4g-HEB^_O`hOPa-hr> zyZ{t#t8fo#M59rYl7@azW+O`+W>VhB-aKx}O&1BC=pcUL5;YaiZH}{Mqr0s^HRb6@ zVc1IC^8pD*7(l%vI^;0;&3w+TO574<^YO1jQDR&b_ZYxA*Rm!LG{cK{#p(!ErNz{c zf$(NL&JZkE1$lsFI#X1}#~x=Hiebvw1p*@CD}Z5<|385T{_#pYBqUfvQ(YAA`Q5M+rQCtuN(UL>d$aSjGg8Vysjnuw0 zM6aYsqx}GTEh*6p2&r~|%|Aj)XO52aKcuZ#mWfINJutgOTZs-5ZQ-?rwkQ;|W$v5* zJ=$V8&qhO|enNa_kPR(9jcg)W`u`Hybk9yUsXI?68=ikXvKbQn2w-O2aL}{SJaI|3 zo#*Ta!pr$p9K5V2x3gUJj{@cGw+$lIn~z}}@+H`Z3{j@vW2E6S%1T;`bsEP7N0t;p zF3ILX_zCThdR>l^HP7VV#O?nEmgHI&Q#HSBx%mcGN+fs)pM@W{JK$#;&O_o7W5J`H zc1%!6;I=_ziSro%1XRrynqtpG6KM;xhU|Y$e*1DG6S?r3t+)9W3Qo+%Z9knLRudl= z&H1;>WdKI@hljviA=tUde?46n3KIbyFG+NnC^IS zZk6g_iw5@dLaHAqFCXI~Iw7M9?kB-_VDd#`@=$z8k!dKMv2z()_ki>tb@3-e4Y#1h z*})9*3Gv&Ahr~Vy6K0pfv?%s9%nSF+Lm$gWs3g1X@XbQXd`nO{Z-!8T$frPs=+V0u z(ORKu$PyD=Xl*SlTp30ZwPGZCdP|arK)n>3DC-G^Vq$gvw~T`ArdYpBw29yVrSaLp z0YJ%9Ie-HV-Ki}H`2}Yd8rgzOMl4yc!A*((Nc*5=IHNfj4xRqy;e>Y>q*bRUF|bst ztyAn1rxiQ#fS9X|?#W|NKuuc`tP4wd?I4fPJ!QmJ=5yA1xTw=}@0jkWIfG1Xg)6lc z$lqa=nAN9wnk0(a2*_6ZKIZfGkWq{KW21j;){)mGyEOl@V-l~UZR%|pk- zbp)9*)UP2~=@13xx`0=zMMswz`j%ym!7`yVSZ0=3CafZ{%!#4Njpm+ImLOn9@{P@$(~vQ zuE8yuWS;QeV{0n>lCTvzFw#=SmRr?n3+8+11nqz$HlI4+&}b5-RC=Zg;bN&OL;-B> z_r+il?mE>^geDp;cSKs|q9VdSmf~qGK8=~iM5Koe)4%uA-CG6Vy-$=$3tbsq)V+Zl*cxb$;0W@@)MGc!Of-*w&8A#{XdX+K$Q~C2 zCvF6*lN{wT$&_fQXII7=o=mG~{~LDEZ%;f?_OlY?TN&h`Vqz>L_noC{XQX+lBDq_9}j!r*PS9Ln)Koay%LR@*f@ zrm@j{CB~*Umz>vO8#pe>Sn+_8(GaBWF}`+i(4~vSCk&8s0zQ3;}uac2Z!e8mi+zTB*k;L^^d=%G=F#Tz29M_x{ zMU#Z@siM6G1dzQ!o7!^rs%Bh56`}^F>QKZMOP;RSX&wcPcLjziuQkj7-AKvudUFQR zbF|09UNQ7ty#1Z1lfy>pGFn1giJ7{_t^?JS2b_SK{-idk_^fS)!II&=6=SPttqW2+ ziQf{t;3-%vik+geof9q$FhO=@0u49s4ac&GB5Hw=m|vs>)egEQj*QPk zD1AL-hH~&!WU^QnN)=;&wvIvQ-DXGK6-`UcZtwvTOL#WQU*4ce!?T<3d!h^-nT!I$ z8rKs(<=)NfXCt8@tx$wS7Fm!C05W;_gg@X3rfddO$1yTqB&IxcJn)ol1TFNC2hE^S zk%}fcRz?aJPlpO@*fpVUCEH&8lP^Qv3N_CW==DKsXjV3?;enMM77yA3SQ=Sc1!@B? z&Z0H|bIi$+rIiiU2h6{H#lE3R0wJrRuG(2Ch)o*TtWhu(=oZjk7+I(<8d56Xkk%YAhO&@zwEx**0VkD3=wL7I&Z zBpntu6GbvCI^)m3l|2{3pc7^G{hzW3Uw6Z@{=LQ7_vIdBvxVQ4zA8L4C7yqTa5oNbBi=*bk8uy z9ER}ExU)0)XU5?gMDw48Yy2br8E{>UxJK)p>4wFayfcQrX5eASHO9~8nqhFWG~@%t z23@YlN3IzLELj-v4b2Y|{?sd zwvaMimga|6);ji}H<-Q?CWe+SC4Vp&3s>;KQF8@-BAmg5GO*+$^+=q_$N>ukQn05b z;CJdd5J)D=Kt0J2k$U2V&fs_fFl7@dLg}wYJu|Qsj2Hxz7G)tSo!*A^q}N=@Z^~8> zp~R43LufqUP|eXJ&64ZyDUzuC=g}6Lm;N7qjLr{)#xh4sThUNUTP3t*x}>KYvS}vh z`|Idq(vQ*TKS0V*F8Tl2E*$ko*iJFr{(&mx2 z@c9j`cl#B&ZDMdRfm1i_w2eU!GPZaMuM-uWL|ftcZ84&KnP@Axo)HWTC*Q86Ee0M& zA#EWcgIrqLBKBa-GQ(t07SR*<=T?$Je1Op11zuuSZ#$4QEgmI_*;_D-H(? z!sE)_P^*-MO2ewS54wu6 zCKf|^7n-*guT83l=wmW;C6>#wp7Hd%vWqbQV`|V3SqQdVtd730)O+jAL&-#pEsNIk?$<;Wm780p$bR!?^!U#BplNTP(1`2#bx=n9Fysh zPVeXQI1b9Voo$KPXr|u?#if%t=kAY`ow3$ zJ7BlcDDO9GUNQnW!>RtK!+#kn@F*wg)+lT>_odf|aoG&BC2o!7)82cg@|od2gzomN zxg+HP5cp^YFX|tJuWXDI^I&0YrW@~oc1L1VV05ASe8g*t=dSTP)%VEDj@m8uyo^4u z?`4*kjy2?lCb<=App2#tPqt#UVs)N~zs#`3`2;b!_86ARM4 zA+CTR!m2@7FWT&BJevpDO_VgxSDZ)CTW*eCJ41hY9G?#6s_!v~if|VLo=NARX34?@ zyE@R^J%?i+)QU*>u`Xv~LovUJJzL+Yf8iKV5w zH+(sU8iU8;D-48apP%U%NfciTmqBJR{KoGlr~;-Dx~!=b50d+iro0wRcz!8+kFsX3 zG0kCgvgLIfY=4S5J41vuH1Tjw^?Y-Y@#ecpVRli$53%V>=@GMG=!Rn&m3!)%8tCEfkv8eWhz{`oCZf|4m*~dQAqeuZM054n zX|RzFLLi{S_}{VSzh(z`UA#!9>YUA+i&_G!J~-KjLBLXZY(m;yp}y?O%_l)$wZ zbWX*S!-{p1+aBlojiC505UX)EiHFP|9P_Ddn$ik}?$UUpM21>v|bmVQi;7xT2Xzz zD?Y2=!3p!5d1MQ9anyN1q^>cRT;&bta(snA7}TibyM`4iKY%0+C^jrU3+#`0&3Vj^ zC9>p*K!yx;=yWrFdoy_$GKW;j@UYl9c|zMAJ_l8#^9&R9LAxYYXjoLi=h#$)HX3Fe zCD;e3aHG>%^Z04vfx6lmB;^_KBr$7>Ko!+5(49Brc=Zdq;ylz=gCiEpLbFu;Y~iL9 zxn8uxZeN)OMj_ETfJ8vE1AtiU=a3$XLbykLXTA&2O?!GctN##&pUgoktK5}M#8M?{ z17Bmh7z~}ct+(6zqhhpOc2aeM&-)X_zVshekL^DKM4Uy>3pS6v_Lo?Y;2O41XZS8=6;|ZuQ14}|4Pph3Z&|5G8GOq zSTb+aImcA0eeKRK4a`dx4j#~hBc=CPhY)T?MI$bxz{n%Rv;xYQpQq44eYb{_2&BSrNmadIf6wmW|zaavdA zFJ$H>;z%1VD7vM2WjZLm`V^wP{WPoIIM(Z(3$;*Bq8Z<9M@3|TJ)IKly9B^%l(L{g zEZmp7V8xVg=5JYY)<_-aR`=`cAz<6gvDM?qit48)dvDEIoh^<9s*;1{R9&3914W9j z@S>Aj2FyRVm{4hD6dvRtRwgB)Q=5k(ZnLlf7&gnm$h??F&TE8kv7FAVug4$M$4v2X zYDI5IO~K7PVqiZT-=%-6u@Wpx#Gr8tq?;*hmy|F5sR+p~NU3<##7B0vsD5@bbr4qn zAPzg8C|IL#-8p)BNye@pEa+n7YXt0b(}A=BF|)YCtc9YjuKGFov|Zc6E$HEG)YD*W zRPR)a1WQ@<3uA%v6tBl=bYh(uCieYgfLZFIMu$u)q?s{MOmeP9UGO~y|B7ro54+z0 zWyzTT<0Q(I*(d`6QAuGXh{n}QKpzNb*fAz7&Rnon-73fhKg9O1J1N~d?A07o)SUszv+B&fB*&8Ra@)q`usHci`jEktcb zOSvlQL$JD{_duH-mF#F^+cP;_Kso@^q>Kx#BC9@|!+>}r4=$@8%HhZ&HI-(Nu$_UM zPa->Ar+FM|;^^X3jv4#-&*Y?={Wmj=cQa1f>2X;)7?nTmiC{(N_{tBeGG*1rr{Xn? z7_eExMR3P92xf31Vv-uT+k=1>Mjow~;Y6V_l>Bs-5-=z(LWk{CuNq(*!-#1QjhZu^ zL6k>~E2yu?);TozA0s%^2N$dSXiV!0&?$;Uksn=|*VM_ItN4NSl8u}VnQE%3t;yFmN^97f9YT)^?&!Z5T&3${CuYG?msj`s+@&zquUG@Ss*sd|j^=4$v-;!w4efUW% zMIl|%yv+oFO}t}-tHQ2f6Rt7BuDiVla*W$zUpX4^45Raurfim#d7|year=^J3i z=D7~q$$o;&sEjGq`^E1pE<8SNKD_%e#MS{f^-f@fIqx``a-BqURlQCp)1?VRR@;6J%)NBYU%T zP!WU8skP0MtO(=AB>VCW9ExLf{i*7e(DIhF$#V;v0OCw?WVe1LOg248xYJxjfO*;u z8E&q~7U~Jt)Ac3Olf7YOy7ho?5JP{^j_>JPLP1Zl+S)mz+j1x1ho z%V@uKiCj=oe}WT=g5$8?n2&U%P?C%f9`#rE7>P-@K^fKOoF;2Tl2Op{A;bfy#caJI z+l`{9)g4L=<|dotVh1ajc*lFd2PfBR0G(U?=@_*H>w~9V#ej%@AJHKyB0lrfbCDmGXT zHtfoz1KBiG#d3pJ?V!x6!UPiA(-eWZ)j}u5E_E>%?8#N?sb%x)S@lCx-bd>9keS5! zgU@q)$Q+N7EM_#nX33UwL5iw6OgZM!MfJI??Lz>-OL01VT_A^RfD7a>Xc9D^6eRIW zC+y-kMi9h&ly8;?gME^_Gnnbi`PpkSjd&+}{1vAA3;0F(zKNfG%ZRU~^XhfG^P9q8 z0CrpzDn0qGYyoZ>-C)!uo;vL`56zol@{Ewsk+ja%nc;1?&HSk}D7UC5cIWf$c_H&q zshmABpD~6Kbi2R8K`apP@sV!R!pd5_~2_ z+Yt^B#%QKq_Fla(25?P(Fczu@nI6y~Uym%ZfIO7ru+dvJGx3PvD6|kVk0DEg#t~CU zFfxkD)M5Yaf9M;4jQkWP2xnepAu!b$2%=lIVFp@+^lKOE*l zP1G223{H%RaF<-^Nw$eQB#;oQdwmE_V8QBV%XZWvo5E<+@Rb4+EH?%Xmf#GV@&xCy zDRGfmX|UwWu~D}6H!wIb5gL#Z!udg{r3{yu0Tevmz`jv|NCc;*6L4sXo(TxUaB1BO z>4s3wxCH0;UTM4qHC@sYJLCZ6&h4fz==k!aIltu;bdcnnQ|Fu&uzLNAP|n#Gd__ifKMP&ed~qBBe-#hW0BErK2NHTt z;6gxXA^#Za&t`{@;5W!YYaw4zB+S>(I?=~!_3W?wu*3&jt7o_JjA?U?bEntuEoS|l zLz1iGG?^+9R)>KDaXb4vYSL^oWUP1rT2}8cDKKBj0=~T&pkJVX&bjz@Gl11QPV{#w zJ?Q-W58MOGgJTQE4&G5QU8?Mqw{tO#gtQE0}5?43C3~GFq#C8-)3h=1V0hd5ZOy$HH=@;2r zZ9+Y2*uAh z4|4dXPj9crFDdJLR(h*O4ubR5sH8tBB~UjH2Qm&|`Cn;s&|6yHvcPTtms2b=aE=~DxfWDx7V zQ}vun>|5&XHLA^}X_{+OL5WvYH0b3aa!p^+?zFj%uD;GIPv3epb|KI1W@?^p`6xzie}{Be?n8Vk?tnmkw_}k5 z_I3mf&zOF&xug1H0GMH)H@z~UqSrU`!lZobm+Nyp#)PJ^qIM=L%5K-gL^=rqTHRlR zUmNP|&Mrqe6hksZJ40{5Yht+L5v>{=pxh6C?GPBCJ3~!Jh9s|-?<044KomH&{<*8t}J% z7h3mw)T`ozTqUZ(XH%x6)!@&1am!dQvP}|ugrf_yYgFx27xBkF>4HI+FBOpr zz=}_{S5vnYGA`y%%1leOvHGC15cDkdtDu-k92eUen!k2vz}GqQpr%9$`&ww;#{~6=fb6_MHC)%RW^66sBQum z)PxsC1%s>IX%c>2(rw7yhc1Cppf6F|>cinCZNZg&0@C6}4}?PN+LJhHOK46P`3gc- zyu{N5p6Q`mNKZRV`QOao^Wd7y4`(ey|C-;(z=$P^U?jo4oG3F5PEBYz!-wSOamC28 z{;HA$e}+C-0CDQ*4l*f6oFynj8GQ_&xd$5=Mx9_NJXH^^T;4Qfjs$|C86tv`%E&4g zyT&yy7+Ff8WAuU*^$WZ9nf%`}{V?8{Z_n1*%O*2eHp4Lae_3O!}LmvpT|LY37H$gIW#RMaSY z8TL{UW@D#bkGest@SxU(1O383FiN6^tooxk#|{3RW*r=)dU^FJlHSNlT`8Hb{@5bn z0@e+@a(t0>59MTe>LlH{8VU9+MhL}1T46L5T$L9s6XJ=}9JK`kZQfoq-^;YAv`CP_ zQ}vGeS$8L=Qq21#?v0l!VYkdlQsjqm%iP4m(h%CAnogL4x>5?a!cskfH95~bVJ>Y+ zKMRV2i(u^50A?$ozYCt z8lJ+L02;u5a*6%ZC)qDr;^@$9fo16su0ru*W}HxPltq%4A{qsiaE2Yv&x148+~Wpn zR!+h$>Fr2Pzs}q;uqFBirgVq&1QPhFUOS1~#*A zqTJQVIE$eQcl;_Ga!}!VO3w>>j*=V*NLJb^@M-PtY@Y=aoyYP@tQ7-60nlw8%Rt)Z z#J)|K-w|1gpz`hZx@O`jks#!pq#*YbioBMu?8mZ6pZsV>=go4WY z;x?c*HE*mJ>_>8T8_|-v_P9mqLjW0H-Ux4k@_Y?b10B_k>`M(=9A%4(g(0S%*#UJ< zN7l}ecJuHe^Ua`QXVtgCKEOp<$G`!S{;Pfv7nIKy7+&nM<`;9Q!g4)S0Fr-cU%xI^ zKR8=K%wPxHf}$Vi)^dGw9Y?I8pfy!UIpH!V+RJ1xt9?dHhh7E!tYN27!TL5cm1E!l z*iZ3Ldo@wL74r~Oka)C>WciE-d}YrFNWxeE#2x7?M|1>anY74gW2i;Cc$Lwovw*>N zlSq)2z?dc35~Xf&oX%2sV=64&ggFiBNo>mTX{aU2lMQ0kuyfdTvSeVXH!x@5I+qnU z$Y2llIXB6>gRMyx3gQHjONxihenrSexeqRF{~W6X;ka}#t9=2LVUtz&O<_0hh%(>2H7@z&DIGL z)sONkb4YHRaml-_n1e!6#a{e0HIE~+UPhmH1Y%Kb6DdK6w}54SB;3L5P!r(6%@hin zVfJAn3L7gC8n>-w5Z}B+jg%QheR?Id)ftI;`Z@wcmirZ$L~GWw=YWG`6kv;zyal(G z#%gFXe1;WaMG_U+*cCCvoU~pKZfyL-3eFm4{R+E^A#+x@uouv(&V+jN8mKuOCFrr< z1R?g4(q)`b&73D7;KxmRm=v9ujt3!O#W?giiF@jz06KIHxTy=Yu-`p{O?X4~ZCuWR zk!~o;^3h(6ra0LFL&U{zECEKRSRV8x=gFEM*Q8K*E`WE0Tj2sV`V_}@Ha3eYx|#y9 zSMR*{L6+fJ|JmpS6tl2^@FbQ-Pz<==|YFX+PsOrsVf_ z1Y(XAN(il<)A&!$v35M5WkYBbed4!u>cnUXGr2BhFcx;=Qy|@rvFh#qIEvKG_uv+Y znh9+&YxrEcBRBgM*|vJKVgv-pLHTA<0)~j1Up|hqr?I~^4MQT{s~kN3wFq__&>84$ zH!EQ0v6$l+T~L><9f))?{#Ab$hZi8u#Jdllj(8pl6M9T08Q>aNRWq?H($JOC6r{ok zH}ATu)1O8$076+ySYk32K79eY0GtJe;E$PQ@vmgi_G@EPcGZ~hj@b>0Il6?aE-i2u zUIKr83Xjp@0P93&z-GhEO@%?I=2IlzAheH{@>0NUUoMxviL6Q6pdkc(xFNMMpLx%U&X>6_Q2kT5m}t)6G7d zrNY7L*zi9*`S7;={IJO|)G!ASSdg@<6dtOV=0D<>DS^=n84n^w9q@P*NlMg4x~``(zn%hCNoZ zcph5b5Il_AJ}h_|F(ADYB~&4ZrL4Y`^H3$u z&iX7sWEPglCT3y=GMRyF_!Ba_AB%_&Xn-a9bvbPxpGV=#mWdpDee8arOL*Xu!=p?x zcBZMD?LfjSy#>x2l{q8-I8C?@Q)S#}M%n&!?9;gLF}&6Hb|OsCdwRg<)KUs;qyjB6 zR)Q{Xo<~cr3GHnz6A|U=waZc@P-gNuzuSq-RhsGb#%9N@&hZkU4#f5tXm?c+no+CR zlr)(bWC_!LT9NGg2EO6?<}}yTV1Ji&WAi02Sh%qrt=;)~F|ukLj_$0FFpc|`84WWa zBreVS0*sfEHe*iNZOlK$yp92u21FwG6n~++)l=7+>h(;zKw{5iqTC5fZOJXjWYmGg z!9 z+lt1m9kKdlso3iRCs2;K8xqY2F>17k`bDd)* z%Y^^}n+@HbRny|&Oja^W>*<3rU4d91JnLv+VVi3W)IHUlbWt#_r_p$0O+>Z?zcRR! zk>w>ihS*0sgvTiYcV7`%(i28hOvlr7aKlZFuX?2e(;ly0%GMjeGHNw%e&IhVU{?4O zF)vy~=P(26ZVF`DA(MT8WJx_GxC#Z;m$7eRdvD2f1?rT9;1Q8CHr zJa@+UwhU^0Qhj#U%n#xi=c;c^MlG6=4%M2WB%2R54r_IgW5}`@c*mx?UdtUEvZd-{ z=z=5ch5|d6FdTauW}5S(6$H1fs61&OKn{Pb-G(nJ_@f5@`G69|(7V)kf@xBIv@SEJ zX0mGb$M<1J=|bIDZ?#uO2=L)ri$54{SmQJcBMt+a#nnCiX|P#F}U?krW;=nd(RL14hR|Jt?6-}s!_4=6XwANw5v1d?Gzw;1iM)!V}jLFe&?#%)C z#?S@yBf)YZ!O$^&Y^qP7pX%<^e)4#SYQ|a=Cm2+(>dzvF8fHU1zEvxxzYVrp^Y6k4 zFvSHh%_;DP8b89XzZ74B!o z!eyv~@@p)$=$1O_U_DKS#=5@VMlI#4y1Ff?t2Dp9z7W-+=`c5ntw-vO93s`cDN#j# z1I=NvhxMlCU`279hWc@=a$sX2vYA|JroICYkQUZ-jBL?gZ;sS=?;RzpJRoP|(k`Pc=FS*Rq9izj@~GAPna6)xr>t<;HDrq866^Qoa_ zML`Wu8TYIY0)uEEG|6%^L;h<0GG5MlnOK2V6zBgX=SLd(b;zhrQ;H37Rx`Ep+m1AE zZ>M*{ApHEidVR~NpT=)nHvNV8l7R~~RloVl3dRhUYxA{? zp%m+wZgL0A7cWN(Q^tp8JeYb;K3FVHE_RMCK8`bP?r!!4!5S!1Pq7B%3I&0I7}ZQD zb=O!F%5MyBoRc=W2s~>54tJ&kKFc9bFiHHIC`V~LOMEBzH&OrNKJ-cZ>hhJDzm5>q z;DoUQo9eC1Xq$jki_vN+qCHlE6!cID$=N_G+i^Gz!fvT~Bm4#I=Lu~WZ6V)5T(Z{z!&>0sJ)^h7qPDL zB%f*apw0s%JcB+IB~|Mk^_4KL&5pTc;kUOGLzRA z`Ld2s&%09uZKzlX0_`dc07t7=z18woZ$<&}jr}guKiEkevF&N;(xRJYZ(>{G`bAW3Op zv7$Yoi}RlCxatBF&bqE!KjCZWLOP!j@WVbsO#f(~!SEjU{?RC%CdQ++wSaSgcW!7q zA*8z)51}^0H1!0ev4KcYrjrGgAx}}TBZ^zCPlv3+DWrJf0$u&`GYrWlw}GtAL>bRo zWjl;JwQKs!YLkWI5djzd<9Yo!;Q%)f?2?3p3dOi1uSS_LP<n*r+i+N9ebkP1Y!h^I<3#Vl z+|7+}>7b{qAyp6SFR^=-p$<)!{xdMuA@XKCe|W?Wcj_vVpqxKg!aYlt~l`Yb2H4W2h<8sEpcpRosccsUyO)vZx#A5EckRG7YSz~9Mk?Hi5SY1|)44V#UXC=Rok61T@;+*{_z$BreCQXZiW8{3Oy%PiWu z%|0R;%4{UH5H5oF4Wa_cHw*-a|Z80_Z(!i>$gl)~)tSX$mdK@1F{)+_mY|0kIVqWefea*8$UgENw>$?&6Q z9N@C*zvWIb@aGnG(deH#6#lIG()b`xBy0^hSPIUvA@-^dS?9f@P(unS>OjVP#$qUa zS5=@cR%73nTW9mhdu7|#kjNzRDnWwkK3#D7p>Y|EAr=su53}aC-^Wc`m{zFey}Fmm zcrVY6{0&9#!EQd~oXK}(7qdf0TO~H=Hb^3Z^ni=)vb0M0{S+&doWV*o8ZNdSKQj}a~ah+9s1+0p)9unu69g@{51L}Q>be~07UIwO4EnrXxr)6O0rw@{a zh}ZtwTUnHj0Nd%5yEF(!A@K9Ki77nhS&6ws+3~gn|3QE>)w`OBsQ3V739nv2dFBo* ztDCLY_Ov#1H;PTl5*JIk>U)dc&-L=@mQn1=Cg}xKL;Q#R$@j}BuR-bL`(XrO#1fmR zkQFVeNRiL!BXk`$-0OkKP(}?=rRS8S#*5mO*-qN|8X|T}^MpY(Ik_kK1P0CNn<{Xc z_{~H=Gywo^{wkFc;yuCIc~*gV&narQFL}%`qn!nwDKi~q?A=|Y+lPQa7YaP7-?Qp; zo}TbF_7a4z4Iue& z+m6uWohxkVSh?%ywX~Tp*MyV-CK7O0wsA0vYR|PA9*eqw1!3O^FyJ7%&PK(>JBjYd z?_SJbjHLVRhdb5vO^@-yd);jwC9Rq)o8{Mee%M^Ueb{Yhi@8t7noB`5t}0@!6Sx{8F8bJiT%Kvr;azWb(>pGuZ~O%xjCgq20Hvt*nf#eXD`` zWCpdw-p9DeUc`$0CLNhwMz=_Sks5Wq8bq$F2Hj@s09gfhf)Z=9_&dN?WNZm!uP+)b zEWkh01EAjW45;(P%%Zr#Qy0_1;hpbT)1Xi6S zjei>A`Qoq3>eGRPVH&D76A^l-R#C({;5uAWi;LBvjmtyr8UK%3dT%T8G1Q;MC$l!S z(N!5kONBfdJ$n$XnN_hXGKQ3qBC8sEABmiA3R~`XLVXK?laE4`^P7_TP$IZ-agQ}) zBw)-RY`?5aIkbuZ>C`n-Tow zsIFzS!!WIoC(RaL_97MVdzN>DMGy~=un0tfqdiF+q z$r~a|WAm3ouo<99Ph{W+@Wug;oGT1l_4@({>*qgrUg33^c5lPp!JO*aO@rix=ShMV z0!~@O1857*XW3<0T_bmy4%W}VZtY&-z!NB(Z;IQSV!57XjyJFWeGnT;2SC;M z_3m}4$FE7z&TRv!LSZUlMF0X@*@RwP~|8a5s75GhYqKUuAwl#9#aq5Y6pZ9jzm zIbyh8e{e8PB~(W`PjW2{Aqd7pObwF^C^3X$+`BLG{q^jG@1f#!%{QB9^csk> zd*cylw0q!4sH}9|X{;KA0inS-qEq-HUR(!Wkv2|Stp5^HnRPD9nD=uG?mtZss9=Zy z6X&u26o!Iz6^EF+4-_v`R*zllHc-^K>a!&WX!n9dW0V3Y3>Ur$I!$92yU=`!atI5; zF(uOr9hSbhSBw#2-zTq86Z;czct;y1x?z=7X&D7egyrG6LU(Icel0X3o^F3-I`u&L zQ>3@O{o$>pl69fbV2NRxB4c$$+dTDobaJQVLMinP6#_W4RRWCsv2B!orfLx;Yn!z? z1+CzmzgV)qNEkD0i2=!91Xz~HBVHpx~w=FMXGC2KEMWkxBXefuVrE@M*Y!( zEt^Q>boWW_*hCy}9x0#zEz@@^;`8QBA9Wzs zg>KpA60<2SRRPs2S((ajQOpK94X%b62|W%yh(E7>5~V;@T?Zc$JKSktjcn`WaF=m0 z)X+Xp#t+}7{viz^x|#e*7*K{r3YPJ{6F-&HLfixcVIILra&6nw6<{@d7SmHWkgJ{LLB3toa+nl(miqZvTfJS_S0T)*YsrC`M_$uZNAs0C(d)Ayt>*E#mH^++nO6K0H~Oq-xjAu{1-bT0 z10ZYey{qHDCi>`d*6s7-*$EU0tqU@55TMKg*8-vIw3^xpaFh&S|A2D zZPJ7G*L4)M@eFp5V_@>aT2M?P5A6ZEEH~^scQ)NNg;$zMts%Dzu z0ZLi684`Lyo{NZSD@o4`_+@i(_|xK@#LpM`C||R8#hPr)iEN5QHpL)ngbC0{O5n^a zfeiZ{e$n!2pF3M&1eS!PyQVHDNQyXwfg_Q%L{a6fYc>5dYK2Rc$k0&=Xi@~ukq8qKP|aZ}0c>e4=FyksQ--JABtUK zTIUNHE#KCB_=n1+-MN}PMapnSmBHGhr2XYfwtS?->$o_B{kJ%(r%uzeGcvp5xjB6h zb~$++Zamzf*n=AGdSvOjN+>osb0zvBjmH|3?%ci(YH)$w8v}s2cEWXfPxOj$66+?$ zH?bYDW`|HMz{B^jcb+zY%e0~{jdQveQ;8a&ROmZgl+yWAuG15`Ck*NWB53X~k;{2e zcFOM9*!awJFSdKW?yLWkvv&cst11t5=VR@)*WPRG?3o7;NP=^%6R%Mc2}%)z)y!=k zAgI`?#h%_%Z^hP=aJ(f_%Do1%ArUwh73&kVHMX{3n^X`_rGhm+tJd3tRqL~Y7OZd4 zYKza@@B7DGd+&ff_Fh7==3~q;{_&50{IBtke*kdxrW{;TE5UXgoWP>;;v?8b(Y%EP zi;0C&gpQ$F4fKZ^BabJJ7~ASa_=*-^Of|(YOQ1yo!v?eF6i%DSiwrs`noZTE{iYl` zZ&CjEdoHo|C7^R{k~et6Mfaxepm z>gga?Np|*`Xnh29ILW(9=2JJNRG*HN>fofEAt9N@-9!f*s)0?BfuDY052n2Rc0xB) zj*_3-70i5Q%_G_3(Zpe`MKhuV(=LsKm`ZhmE+FQmPD&r?@rc53_^K;aY_REMRKUtHZfeuT_tzce2KjS3Pn=m%eNl36Zb&TJPefKsVti7-ow!> zLaHLvXhcDBh>fKU^QvfW`EX0m=pO36{1g4h(uQZj+KT2@@~}i*(Sg`ELS1&p$)*oa zIWWCrl$q&1VXo~JZFkfHqQra%S1!wj%}~uv^Z*(9Ah4i+A+f3iM2t&<%gzW`DiQgG z9kLRTg;a_$UQ$kF8F)&Y3?=UmyD-K`NLb*&Bw8m7QJyimcFZt>TyRk31OpCHCJJ#q zF_T~+uPDcWPln4r3j0#-sK%(o=(g+l5NyKSkE|+@bd4hdR|x>cEXJY?4>`OG^dKtg zqWY5}gu=#Vi#=fT*rooC*KK^XoxXP4gEN+lq*FPTUu1<;7c^PT<(HeC9JKrdFcLtY z`~L+HU(1haTU&G~4gI{9|IwBql$H;+v-@jm{7u$(Rxj;F;E1CRnDa@todar!aiURJ z#GrDm(1pqM{urkaKk!xFwkA?I+cFKLu!WMV4rAtq$zpmzl1w8>w$9~s{^-2AdNeb~ z;lAn5zWovC0Xk>q4$NP#Q=r&yOmSX4)eM+kTsU<4z4VLEt-ed*SD#_Ccklr~M~!)t z*d?llhwc_5%?7vR+Q6P?%2GGx_JZc`BA?k0!yycY`!2vh4zMH82H*5Nk;HAK`DE#! z=dzDL9X5&07#+hHc!C7oU3Uz^ab1}Yu>Q$A^MhibO#6#i$rFtnC~CQ%AD>ZSrb5l@|G!U7fiz z31o~lW+#YB5Q;8G=b(_VhHt*c*ny`F#HA2)M)_fL_wbw^YFEZ%k&iPA+e3>gemeXh zIv=_vdni2MFLH={%t;+XM=p6~EndAZVg|gr(0E5G4Fy6%NfstzC`OrYTcrSe?%Dg@}-J_-9phww@QrDDLo1j?HWeG#m{8gbPOlP>+x??SP>@OQ4o-vz!QE zti(8Y33w+va56>O^8gg9jtxF0A6GAsmXJ}clcU>zBDI3GEA~sxJJyVfSX$`)Ds_e& zuKqDjVBn^>v5^*7QNqPnR{xeXhw6V$#~~Kr`>*nmHcyV!Wh`L|eGcxx#ENJk#({_J z0)u`rG9U1ha`HoHMl%=i9qfRT$Upx>SK^d1n;q^k2N5BbaFJZsd$^PDz?&KO@m2AVHA#&;zNafJfVwIj0|oiu#P{S1 z1`$5Vc;JxbU>icV2r_bc`NteG?VQYrISMq@Pg=vTZ+CzoYQWBoj(|5-S0J@NEm0J> zgXRIqWm`N8EF%jbe-_qYQ7ZZmjdFk$n}+!WC#ENuKz+JL%j#`}0`)zBg-;nJJy#PK zp%Se!7k)${f|IlI;67*N$ZT;Wlchu~3~kDuKIB6k88PvVuLDgoGW;&gGKqJ$KB8Dr zBap7>&*wClOq@c&q})I$Rjo59HF7`YF}U)nq%DSRM!vjQF@iPFmqF+yl5jNc6Ru%d zw-)jih)Aj!=y!4L$a$LFKV|=#K{`~AY)>9TU^o_BDtC90@iIfW1gZ{EbX3}dA`0r? zHHuRZHtr(pEJWsc7y|};W5lKS8Jw4OlwF2``B>34%?QADaRf6G4f9+~(#P0)iWE>1 zKy|Yvu-CI{&AooUOJPoUXV9L$iFoteM(Pv<qOgbxW@KsD0i5o%un zAPJ9A5xAhT=*0@YMaLi&?T{V@Pa|vH4(1L;*f=_FY%pSN+NQ0qW`i3c6uaA$WwXs- z&v4cOpb~cx&Th#D{DABjM^-IZr9q?+QJbBYI!6?$hmfzQ&4oh`$#Gm=8NuMz16Hau z_aq_u1;{S)$C({=da9boRSzLme~G#SW|tC;WA?NEfMuwCHp?fbie9gn>~@ODqSQQW zzK9A&-!k&B6b@t0jet%+p1QvTjIcqRMH9|Z_l1wy3h%)lYX9@FUpHVYbhi)8c2N7=yBx;AyO~Xwf2R7yTrq_HTM$hsPA#X_W#iVI_1rF&nDksQ~#3LLR8MF)m z5=O&DFpjK`q`qCzt--6m{Y#DwA*vLe>6LRQtla4a?)0*(U41ty6S$R!7jcw3FdG zR-I~K*@m1I91g3S78q&KLDcWFDa*J*AJ_N~<)of?62=T};ulC(4hfD>te-xZrCt2q z%3OM@r>&z?7v2T)UU032KIVvqmxyUz(Bcw*U3vu)lJh(YqHrvF?6md6q=-`wSpaTf zS&6hJ)7?>xS7KO!QTh;(|VA5hv$yw`}fXmzPx4S#_+WNWeb5h^Q7Wf zGeXgxL-t+HwO7Bq28W=~LuwN{W$Ng6u_DiwUB|d^kqT6>c`@N~2@<3vgcIH4s7+$6 zT)tD6kNV1HC8`q7_?T+Iqrxb>{TZYIVw>ejyNfC=+J&QqXW#x%?$vI5$$YlNo=t8! z25UtW_1Hngd*)gIB%IfMJ)5Yc%ptml9s*D7_8&o81+9f7Y&|tlGbo5}&CLAm?<@q$@}<#Y#M5 z*i`X~fh#5WwDAoJO!ij4{}7r;?%AkTeE<-d4U~p!#ll>4XD0JUYp-msB31QOM4&=Q!BfuJ;P*I6mv7kfh)+V4Y2$)7 zKhR>{1`;XEiPq>kTe9uYB`ru5-23LYx1(tGo16bW!oK{>rYr_w<{~a^u*4ZQ9LhblH3+jL)hk9(I$8i1GRR!gObdh72zyL z?P5?nJ6lrTlJOWuDK-BAD>CI8kcACtojly0(2vDF2eDn7vU$eazF1?b8j%JT++7);1sW^l|OeGvg_8 z#m=zDaY<*6?L+Ct1=*z7|TI6e4 zNX$Ky=!Yh@92Q9q=f(GxTQ+gxX&uga6oXMt`(E$8XhIvxcUQkzEBvOJ$9&hPiJ$q$ z0(dBy>g35H2{cmFWiaU!YiW1_e`oo-n!mdJjC8~BFn$Hhc8&~-25n5z3imCTvjZL|EBVZ!Su3DZ~Pxbmp9))9V4-d@D$t--Avv3*I2SdCN4*-=?qt~ zF2dv0m_hu^V*K!P0`HrRoc_*P@9x{7jzS#+)v3>Rp8_x`0l?A690anajPH+WJKPRk z^9a`kQ_mP3)p^GS%#S}&9%h~^6TCG)*xQp5wKc=z&SmnQAKL7AuvVY82!J5(9>L*0KZ=WGs z6JM>pk&)Y_VzLq*vZ9%_^D7$|T(@2~H$6Xk$lRq@)a&++*4}6YMpi#$Zu+XZ{FlrZ zv39P!z!0_1ydq9FS9lXmxtl@z?7|b0yLjl!o%ab_ef((|ihsU;cyhgNxRzmOxyY8t zBg3DQX{|o_ipy`@1uL^Q9{pLVBFz=e_+}7rm}-eo4Zrl@u!QGHL*9=8pqGxx6r`&$znC* zCoK>wE+tH~xvzzzL&%mvR0+XiO*yPLh!k433mkhk6TE#VC?oi5uiV`-|I!JmOSN%B#S$ilGN;{!keG*pqgJCc!y?$edv z13YGWbwitwp<7+vilkWFNE%v)@s90qE1G3HhIuiT-uF)=??(u4a`U#rd(=Ek=nd_9 z(>wF#n}44JBC#UHniNsrJ2X6bjs#o$T~}_Uwv%18?ZQgsATiN-$QVNV@6OL%BPUsF z(uB3pCi8%j+`&*S-cAS17J9X=h7IjFyceMXhA$tUEK6IU3u%H;+dEh89j%-Do9tQb zc)`xun22Y8X1OQe2^)C{fj--L@o0)dxoKcBs9_xy%*nU2XRH}M1W*`$k76JR9S6mC z8O`VcGYL8fh^dDRx>wX|(YNhjauBSWEA}Fx1afZ+B(WkCi;AMP_owMf@ujFsd`eIA|yRpa%8k5wP%N>(&k-5WDC!bM_BZm`lQ1&X0Yiz(3% z1Q`2f=8UWPqGh@pif@p)!1wMkgL6({00HY%bveFf!hGo^cQ^vJjcHX!?*gzhEdev4 zLBjkqpqAM+0L!&2m|KCGOKt90i3{kPYd^|t20#mG6!6rF-LK0dmQ~^lbHq>qyd;?J z_4K=W*GFZz*W*%oR(z2%8c>GsI1hH-GOxPbGV|jy~^RZg!*$F z|7O#cj9}~fb%UGH_b-0>*3Ue?`m!T-k6ts|xBwx; z&-sbTlrpTfE!a2Rd&1mzKl@idx%;2)eCv^=wQt=WrC$EE?;iQe=Rf<`f4*<-bN}}J zZ`}2RZ+`0usrKo%^0QOrTaT$co4fPIH{X2EEiZawTj|+QU`einsPuKWe)*#}_;=r2 z{M`EGpR|<*wFByzsnX3{=8pMbI!8E#CW>RzfE4$o+hYfjGdJOAXm-vi!- zDp?zeTI22YcO7~0^}LPRrrXL^r^>1aR`$w&eeb8f^6A&NmBraGB;r`C44S$A%5h~( z*???As;q81tpG~V0Tb&p$Wo&S(p@{ZnFD{0qRpTpu!9#SOz=K3uX*=8ddyat@5oax2KXm@Dqhel4)n^<&HHnf=4U>98$Tbk`Fv z4BD)>?S0=XAA0zlKe~W>2KD-4*S5_QFTLlHM^8Cr+xvH{yX<+7c>9gjy-O(Y6e^3^ zD7vG%hy41%?`~iG{PuT!>N9uk{oF5Z+xU{Zp8NFaJ?~7PClY(`*T4fXGSt-i>u&JB zzk0&9bn&b^(&veo+Rs}us<&OY>+$Q}{oF4jOSd zM6m?;x;%xk84VZ8JqJs8%=_+p;&T?Rv+Oq&g!L^9>0E|_!Oc3#4qvzMvBeiFisHkz z_~r6I3b)PtFG`|A_2FYDk(Y5LG3w0;kz{&poB>4wvR!CdYc+k>&i!kC#oim6&FGKl z4$3-L%Vf=Dqs4ALBe*HrgC^t|#X(d{$PRfyuDBW-ovn~6f7Ur-4@2Jkg4~3C4%COJ zbCD4zu>6}v$F?#a9Q1+JEw*W;NHo@q>fU+GlI~OVG_%UeHHj=ZTPl5TQ`RO(t_sm$ zR&0fMd7vN!P(FaOTPW-;)*rU8KE-qjQ@X3I4GeFl@mSQFo{Yu+A8fqJ&%F> zzD&)cm*S$&y#>^0UEZ=Sh1;C$5P_Q_OterdY9Kcq0CfY-fMCrr2t65MH0i z#$2xX%MoaG=TJR3ym#;1EE+u8KItIXfTedPoEGS?7Cdjyn$Yimnf@lwL0rmXuXz^g zK54w*B9H^VTm4RUOIM7{)r7U(WK4rwQpa%E4BANcq&@Y@J=COAiDr<+-1JI3CMdH! zfHqHRHj{EJh7qE&{h)-Nb53j$=EX)6GN5Hd>+Q@5 zU&%}&Galh6wSBstq79X8+?2+z%C^J?5w6+Cd`&GSi5wL~2mXzt&Cq{uy%_)f_ z4YWBA@3C0Li#GPC1+_Dk>xtcT7;4K+B6kldMOcpj`RK_&eoyv%C}T4@1m!(%*mqH) zTNV`wR!OW_YPTp`HF%@N!& z0jl#EpTN5i(9wuU3a80TUQ47pNU(uqoz-uG{_*9Kmy!HhW3x|~X`MXm(a=jL^2za5 zwe?gHLA1rzI;&n00pj1jsaL%uZ;nf56GU4b%xQA$0Fm_uY(c2fL}aC9DI20;6`F&mz7kT;g2$@l>7AKsKHey8I*;-h2!PR1@ZnlB(}0Gp`ZSGY{Wtd#So z#vuVc^OMcJ*-qkQOeW*;=q$X)ZX4{;0Eo(Q(om4(W7p>xLjW{I1TBeCBf6bkwi664 zrg91)qN6NbBY*PhK2jiwYi3JgrrWQMa zZ1W+qDzCoXV{w%S)kRZSYprcq)h*#~H0LLIDWC(Ev4~eNg-qLCCf_Umx=f%tp^x2A* zC5$89c zomsknU< z{1+C2VGGLw?vRzG`dHR1H+~Y{RTJ>=YG&9|+{abDrpx?;gw=*RG;B|t>`lV%RbV)0LZAR8C)F8qJVe7h#dMH zeH<<&L@Uu`a4gS|s%OlG#sMqfh6H2Pk3oi;7A9RUnSnIvgo~2q$55&naBPLmS74sf zL2RlX@V$>OVx?HskfPH%53pCfG>VE7{6sqOay=hFeNAyG?wH`JOavDAz|=To1fRdh znzceCSYsgM{RtsxLRs}MJw|TfDPAs~YGdPq4{k_`ES#MsJDWW+TMq3>!PKm^9%x(- zauKNL@-3Vi_{)Hi(9IUSlt6D*?Xt8|JXH0pOg-S#7dKqNAjIZ< z!-F~IVziP4%jU;!yR$;YxPJ*{)IWR3xv^$DP(?Fqbo#14OU3@Y@p^XLG6{y=j*X|_RmL*IOtj(?=JjCw z{?{j|S1eJK zj5k9>xu-(Qx+Xa+D^x`*L62OZ1BS`ro=`B7sj0c|4mC~=x27CHa|IkN>I39}asOvQ86qBqH+p~)Z=4PEK-*$kD~H&h>#r`1 z{Sn!z#y|X|b(2QwSvpA5x6X?A7Bk92via7Oed&X1?i3rF{Q!jdfu3BNS^CYk^v%{| zz99?Xvs@BMNXC_6PPtU+JISA%>l~v5vNx4Dqj+}v`a6H>Yn*YshM}a_Eap8H)jL)2 z)p<)KuP^kU`jNI7fGTfn)Tj-muMe{^HKnk)7kkm-pGOdPAgHlq>!3PerGfp z*GOIuKA4^y_ENfJm|$aWg%O)7fB84X@xky`QzU?cVi4#JTsA0a@?6P?nieSMjNU**GqRq`uT3a9lf+g&UiVrq$CVM;yaj# z&+R)*a<=bKQ~PaOFF3NMwqAlw$MsV3wX8*V9-SAd-XomcaT)7~>O8pL3E_@v^QboS zIGxL2Czy6huU{E;K;QbhV|X8mlpcY5AnmPUDX}8X4}cu>dk) z9QEJ(>4Adx^2xZnR{15dz-~IryU@(S0(|15o~s5v??uUC^GHawv8Ix>no4LGo-ah} zJVSP)jy01A8d2o;ZtZOq9Q^&NB!pzvgm)Fqa;3`h=27&&Sxy7m6CpOOuljCU0U`+Y zwMF$*nEb%E<~-swlwaXXR%+P<5qXciEK~$h`_?N_v(QdD$v2*{&3sGtDu{;!nPeLa zU?bSstV4hokft%&E1}*Q3D((_XA~QR7fGquLkFBMuA4VpOWW{XVMPRjwCW!~*lnvj zGy96Ya<%|}r@Cn>sVez!nob+-HX>bU!;uBxhr1B1rRWG~ z-jY26rqIlD&N&G@nHtd5O>Cjr4Q<&jbA)ZkKD|VejH};P4tA_47|x?AljJQ7^$$M4=~~NsZix9F)~CIT>qUIMeuqG;V;dyb7^MslIC9BWQ3+svo;Zpz^tvF z-c9Zru>&r{%L(eX5Wt4=bj%2dQKn85pKK-~beH}~1TpgDIc=`H%0Wh!GREkAMBs)a zXR#2YM|LF(Av{wdvOCBF#4lunDv_{zUL@@kB$^ea5xx%OJ-{8r?uTqLo76l38kw1p zd_x-KTstm3!iOR{A~T=XLVf?=P(~1qE)015qc2S zZ-d|dldzw-z6dm*>~*KwuO9~5ge0{$p+NQj_~H^=Y@Y79j~+yp5@xdAXL!~{H5o8H zTL61ww_J}~b$2K^_8|tjF;8|kgXi;_2@a3-W_N$YG1_!nQtvgFT!h{h)E+brZ8y$U zAUZ31xKxN#s3#B2&EIyz!>`!OE(U3ajgH&d@(pr9(xN%cvp@uEcxrKC3R@KItw~0; zdC;1-z5<+zmtyCPZdWMDLEGYxI8`CFm^olEn389K=`Ej3seN#dFzaZj3#cv#UB4a*@jBh3J&>raU5OO<};Wp27&39PutZZ69}YMsHgd|K0uW@x>GBt+r5OA~>t+3$GMaJdgbX@{kq7C~EIw)Kzf?BMo4s#hEw zE!O?S=RiKoZ>HtBFp&IbAKyd04l)8T5%nT<=tqKiFz&5Qy5u@FEB|FfIDB5s=;)9B zcK?+h`fB#f$aO$?tsIMY9HA)P)BCDfceYpd;o*>#6azqsA20ovN%KYaGO&-in3*YO zW@b7w6G-T?`4^r}Ob#XnU2KtVbHg{Y>M8K=oLmhuE+vApFFY&UY=G%@PATh=*g5$2 zr(JjUdw&xG*p|(|yZ+(6C(k_>GMGy6Jc1t%jf2N%NHRl?#p$+e>xCbg{J}rZ9UPOz z6MjB+!7CUB>^LlZqn1gx`SW=N*>pQ{X#$Mf44xw1yUoYHOxFZ12DoK5Eoh17bT((F zv}5_2S4>QU5XmGxC92_1hb{rD!q|rru#@M6@pT_3y zQz!Eae>mq9Z8^k)#%2NbrNfln{T~~WaLYCK|Ec{|kyo7vGTms16>}Sm&t(zk&kdA4 zI&QeK#JqvsZg8(Z#@v?dAe;;?x$5%K%Ey$KjX84QN3|h19lW4xB?Dtg6GaBLlO%e%pfR0i<`MbngOC^qUAt8z zPSneP9+!E?Z&2zOLEBQ=&mz9^(1;_20xxs(ul({a?hUE2Z*CI7F*m8`04>j0lZ43? z^>HCXLYuqmYk4zO{Z>a(d7x&8kV)j0G&!tiR4lY zQ@5w~2{9An9t;ug72%th*;okE{a2j8fkr8`gN#Hqb_KriMXt7}c`iOP(&@o}YDkNv zVMP6?Sa#Nl$F=`;IxALm#y5+dWlFf1^nx*=S#iPSpya-3+5QDZZyl8coyi$_fOk^+p7Z;GG! z1`~yKGQUP9qkb~DW%K#4nbCugF-y@vJq%8}1CtiM1=sHvt5&TlRuy??6TQ?;>{(MyNjdK((NZFZkBijRExabTMnY{f#Tzhd7eGaF`N206-u3d5T$0a=D2VW5 z^V^Y>doJ=9!8{Q^#+r}o18EJXJOTG;#~POQYNGibVB!Z<%%9wpP&7^ci}z^IL94~! zcx@sUs;*&8fFyf8Sw8|1+8mZajHNff^JLxDV2C|QoQqaAUu7+?Y(C7=GtsoY=FpW?4ui%jkUD-*~gA``cfb|I+@lS>`{`-|#=-YhD}UwkgX~e`f|wsmna|2XDu)pmqZm zAiF)09FNI3Qr@Hh&(TzTcrF9s)-7f;1uw42Ooqu0R-Kq|9a0#v1)L&k;~z*qt>#qM ztGg!7lM3M{L{OZ=HF7DLCM3=CJ^>@$McQMRM4i@@!`m&9fO9}HF=m!$pc-qmWTaUu zgQ*L5r%~^SF?Hen`)Cd>K&qge>T*f|;S`ps2?WV` zI>zv#A+OAT)R8BW83KgRUHZq$sSeBV)AOs4SO%w4j;_Idg)cf;o}?E?MV zje?dkrE*9h=Cvs#!YzVNh0Xbn#s}lP(>|?*^LfyU1-3FRRMf5rO_N8Q@y>Un0lWw7 z1hjoKTDgMxpWx+m1^SL^XD@CrLtpsh8T=H9L|CKVqG{-)fJHN3RD$<8g5b&VFBBd) z4qqQ^8xGY%9y~6d(TVmg%!p1?p*Svf!8wA~GyHoX8&A!yWfOUpWh*JiL#tOvfOeY4 zhO`tmIYSa1fOYSf!Kax@E+^I+=t2?D=BK`mJ7~$|kIJwGD8Rh4>jCVXVOsczVT+IA zM0H@LUFeY+$S%|b&kzA44$Wn?tSn~PG`{cxfS}7DkloeItVw4rNs`;B4&s6vx_Ln| zlpV$80tGLQOkRCGhCb3a~ziOUM)oxdf^vSdoe_4;efaZn&gEH1YgTM zQzS537djKeg^dcuz+n97=jgHzcGN-U!es#=a*Qw#OX^O3VI)BEHZB#rfJMJE`t5IM ztgs^alBAB~G8V~Gzk_xcKd4KENt=zZ=sy~ABa=lqo*@--jO0hT>DwG%Ouumj#Dwuig*inT=Vs9~T@`DZQ^| zxfD325v_cF=7?b>y916fW8qj!yu@|3?jFQiuy|$Lrff1avuN;i&zI{20rCPtrXt`; zZfWOaT}GB0=C2-Z&^=}F-k07nPE!F5<9M>IqHU|(Gh(qoB`dc^@gLL6 z{$?-_J~tEK0I9~Ry2axGs3T)m3=Zc8GWJ`tW&KB_52^-qGp26;Ay=`h)>Jbfa5>#n zcNYDxKD;=A#01GITM;oqe3FfDMr9)tvy3WNq4Y8G>7RQjf?r3Fmnu3&Ii0b{*$PnTs$dg)^>AlBK^OghMs?UX6+^cJg{^%sl)syPA z2c+4O0(@6d@rYDDb&RlaEyx~1EFg{RRePiEkd73u?hnOx4OR4qC)LLTE)Agwd1Uo` z&8Y;Qt?nl*EP8-A-$yGR89pR17ylR^tO1BM2Sz8&<=2udyk6s;x^-GEgXWWGG524utBS7%vin8qNwx3by9q8f=< z8^qfs%`J~l2R;h$pn3;3X2J+po=BRp1I)Gfx?a2ge6ka|JhRr2&sZ%|Sz>FVG`HJf z3vGD?{C8#b-=_mBD|l=!PV(u2kjR9~%WH{>9O1V!cG+AO_67XCyul4MC&y7D;psxP5a5)k!n@^heBJ<+w3Z}(dt9eVoRhOS3MWUSkJ|_Bn z#X?K~IN%xx2T5A`)hKlCTT-wOAcWXx()~bj!9-0BfH7OSvoO|>LFCTa{eqw;ZXaF@ z=IZ~BZ)V)#Gdxlg-L*MmcT>EeIRo|p&x)arL3hZ3eoTt)5Ix}Z!{kVmAmSv3nO%t< zYEJEy?pHRCQd5jMWb6jlBoi!rq||n8sMq`%f{Cfg2;wrDFF1rneNsAy>X9iMnBh|V zga0H3!pM^s9{WQ#@dQ>0)lW2s5Tnq{rmWX&+=-O{46BR>NMkItk1@# zAS?_GC;Undy|b)exllw|@m(N)_+f)^tZ0H0NYaH>B9AtNM&Eotvt8=#B@LgWuent& zbnBTNduo=?Sj1F`fK?9J<3UNL>uA*`Xz#@44S?OLS8vKj(jh{NhkNm@>f4M#bs^F111~y`lIi;FM3n1g- zSG)D{BzBHdxDbOnEl&B6-Vc|t@oO!A*C5H)o?kD6=Nc9ZOr2Bn0jv)jP<3Sa+`*DG zw&q@)%Z6(t+m1nV?q}F1G|nA~k(pyJLNX9Sw%ChcMre0DjLtB1>FC6?m30PAH(H*Bug*q59F`OI(D^l3rs#7w=txm}RKu4`) zcrs`n%ZAt?j%XVoa6-R?l|$QzvihV0L)>H~%j0xm>2M=m_s53v=r~P>3ADhau{8+Ui+BxAciCZIGHd{_+AIh zgNC(ke@BfBT9LL{)P)2@05WW7J4OMRU4AuI%CFUi}3k{xe*xF>cg|%Fu1)-~zO-+PCC6(=MJ@>3PhN zc#uAHCdSdwO|OBCHmfftb2q3y^0DGQv7OoxlQ9LU5^+M6R(Nb{R3y0Z zwPygJL{lrIGD(opvWfacGms3}(IdhU{Jdlygg~Bkh!P0M=X!Rho9Elwk7S{d2-q0p zwzmN}h}i`*##s=z5y+pA)1nHPIxQN-l{hRhL{#6nWF0x$Wo--9WulfFg0zW>jX-0N zY5Ta_wX6702cLJUUxRUg z?s_HEqAe@`PYT102o%@Y2^{yj8M- zwG*@wCPX(a5D~#ZJHlmc^o~;$WR6He*;@e7>SS@9?2mR3lFr4*KfK(aT#qOjRIsn) z^(tx`O;+=hqvcG(Ibsbwg<|f&(&HwU6IX<G1)xiNo!Cb zJ|7NzR~!$BYT) zVT7CqvCiUWh?Lr1L&`maMJj%|>R|DehVYduZxRSjjIlUgWFqezXu5+OP2@;X@- z+QcpK&j}*bqoj$A9S$6ZuQ5QZ4C*EV$dp>=pQqYCHbyi zqi`^E(v<|9x7xOI&aq+%%0s1aP$+n~t8SctjN)FWc-+T(-~``GaAjx3*Ol`k%w8`Y zxRh<}v{1*8AEY2ld>g@%Vb}>ET^B%cBfaTxIh~;nXx;b(xIEg%>!nan3ALS^Ixl#A zuemA!fHehTN#@7#4yt;dA+R>afGZNg`CdX0P>vPRm0M52fC64c%xj=VM$%u;U>pelkN<~ zP^5m3A-3Y)HGO0f?_Zo36mJTPb;LWIum;jhD>YEgnU2T(3t3+NF4-_?zbZF$Gww9a&hg)hUc!jbI#B=FZzHTmf;!X74W#r9QgXOaD(&@-2tD3d0V}X-Zu^j}%B@A%#Gm(Mo2{h2W2e(nC z6DjjjJmEv~|M$=a^7veLeEUN<0buZqVr%I9p8i(8mn($j#WlzKkezrd5V^sNyh*+a zNaEedoww9bP>vO{{;WBx2}E4f6v&lo z2TwkjRTrJq-;vQ~a-5?H!-4;~5Za>Bxk2>s9h<5|d7K)3i`bT?}d*IGT@`dfs zo@GfF6S3yvIauyg{_ofjGTQU!SagL@O z`tXD5mtX@yI-vHMfxYV4C_W#wnxZMp^$ks2=88vMtkHxepD#T@pFntYJU0Sc@ggW8 ze6d_V4-~Ucv01UZo^S=EKcKFLw8UBUhk5@a#O|;UV^elAvkVZ^nhFJ8Sly6^io+rv z_-M5PE~#%(y&0m7md#y(f~@%>FwlMfK_5ZBkzU;h77Do1@W_09&_G+ebmpiGMjeOf zQTd4EY}Nnn&Q?Z;(xbXW2QJ0F?xWB*!B=>@c@SzzAp&G|A-gJbNAuxL23$72pFcT|NsuB8F*5 z`*lIKnM!nPVteVFD zQ<^Ycqt2Iw84t>=$$dl@Ve9mt&$zKHc3(yyO^Q~$EUI?z4|&DJ$?8-$4mX%Wv?z+0 zZak=|$3|J|V^Bc%d(^c*2{@awwQ1uw#4X9QZDf7c|A(CR+(G7<04wo4H?RNLcy%%p z^hYroP*2|cASKL~bXZGNY1naAj?i(l5Muym@@ecq;tNY*2W;a#mF!3ZCha~T+rL!d zM0(G;c|8DRKg$ZBBl+&C`Tqcf|Ig%*gnk_g~&AI#)Os zAN;4z31BbE&O~=|ve(P<2rlBg0We>QW7Zvj+I1~;_O3o~pw=e=^oQr_t67wZZl0E<`YdaOQJjms zeUSM8g5y!NSVT=$aKL9>Z-*s8O@SnQlq{0h<@hv}$^Cf#SpUQ=f8;1P@xuc)Ozl{6 z489jJ-1K%IPQbx8C4PiUGuYkam&QPHLzo)5pYMK2VW0rD^l!^KqmZe^A>FXGM3J(W zPID?cd9z_xbyqo>2uVNDym<9aX6a-)8$ohVBPHO9@C5WRIkZvAWGZHsCBAnZhdx&~ zg`bEiw<$Yy)ZGzE`v~9Tj#%;2V_)-yVT1gH#)-iyQ;%wF<8MAHMC{zU2|~xNa+3aK zkxzus*A*yFW705|0OHy`C+q17Bnan{=F`l@Njz^KV#2R+RmXS;2WCU@Y-h)av>VKq zUiF2L>Cc9P1+B}ii5t|4im(B$>TpE?LTb*&d}^*478Jeh9%_#db%!L}lCC+O5zpYM zk#Nv;xMZHte1HO?#a0A|w?DXSQou+2g#JWdWdEOV3)WUp1M53odh~X-=U4EGY(Llt*(jeYepQ(2JkAe}Syr9X-xB&mxm67!r|&=!p#l^I#2Ow=nl_bg zbfz|Th$&?bSX4zB`KkG%f~5w#A#zhm1ok;P#c$56^HbTp%@s|o= zAYdk=8NCdTCP3p&BK91ur2v$nUU=H5zTRtInOY9@FIq-5W`wfpjkHnC+eNAVeg?wd zc_~~Y6yAE*(O=&mp)10`-t|yQQ!G2X;lqgAP}~DuEblPRYOc-KP8sF}^`kUOOq;U* zqxvV!f#$}S_ajqJi)!|VH?+ejP!f|aZ6en)jE8*=R86MgTU9UMxmzK##B)#0NlpiA z*3ql5=Udz*o3eF$Tg?3w!Ma%_$W4l7KDLHqCnDiCSQHt}W0jn&A&Fb_m9%%<3Dsx; z)TQ>&IxvcY$_P<#b-%V zYs1bhNmGKZKki544eJTLzSr`~WEzq`<=%8Y_w~vi^$-sTuAXXzY1T zhKKxOU2-h!-X}98Z~gr=&|#Tn$OPxXbp^YnnM1f*A^?hkxJ`;QH1MnMl^Snhrm7Dm z!X)HOzV&bU#kw4`=B5&cf~gsKv{(|*0q6RL`uG$jqqsgUPRp)F<~8Gjy}lBrZX-lG zzBlpPZh1_A#76E4&=wchTg^SL1qTf9i%_~ujEAmA9JFR1%b5i zb$(bCcJJKuUNBQWlWid5Ky4;E4dhOS6Wzm5c+PVWdOX4nwIw@I(u4%16b@cyV*U*~ zcEpEBh$U#;2dtLp3_z-bs$ zK`i#uY+WG2lscz}JSk{1xag|WNv@HbqcN*KmgpI4+wht8z-ahM(SJOms@ONjLzc`& z`O-x*dpP%m{Wr#(0-c|R@1%qZoW7MZD)e7A0g)v=Ya-@+3=wmkkAOrHAEB&-51N}g zuq2_-Aj7UNZ#)H^VP$h`_{0jNG1CMeCtHNAB~&qvT!_!q&P9h#1J?ao{}>0A;$CyI z7S($_1V^@j$21{CTIMR`AJvK#+E2&ydF2@&G!u(ZC^aUU0GdBI%F)DFV&hOHrmqIq ztqh^lm`!S7Ln?h-jBp(%^uh6A$OGD8{z(}`CxsU?^XSYK_C632Ht+pLrheFxP=yb?vU z@MRq?AwDIB>S}Vp-yccS=ns)|6k3A)#bHCwqdDIVs_z9>+S@8_85*EqVnG6F5kiF1 zkG#4$@(Bv?_rV%(nd^{8AYw!EbK(4sT95+bu1CpqHQ-8LG}1h%0?*qEliSTOjo|4` zQW}y|M%P~%A{ubQ^#^f?8MS0p2XfN|M+Pt@u`Z$hOO*=c)&kJ+l|#K9^?6ZCAFM}q zC&)?&)}rMs=WEqS)y+Hs{Io$h>>4ggn6AEdzpJP!f)u%?>2ahh9f_#guy2ls`I63K&R;*2150vNv^{E@`q#j2ns2X!mc}LTW!0=#k2@vb(*g0MzisD%i8baYqq zyPL8zR2*>7uIC3BkWDF>L)~|Nk}g&Ncpnh}m+X3EZfqeChr)QtXqoTo09OJ^z_Xb0 zl43--=hZ}SuAvvu1)vWJ-%E#9c|d{T2QVC{o<&}k8Y7vDD!N7=<{hn15Ru>#Fw&Pk zw$ir<7b*9U)D7}=QR+Nk7^l33ed|SUZQ?&cy_~`qn7GgczCXP0-BYv2!0TMPLuP}> z1;G057l{p;xRP1`6951ku!Vz`Y?{H7yA3|I6kikEID-hnkKV8bq~ajO))RecrTM6Y zbVt6u|B5^&4@xdZmf2r;5jJ!lY|`^BuGOkYgJ(w<4ahf#c~5^=GgxqOuIlP{6~D>M z)z=j}PB&ngx(&`%w@9e(H)1P&avm7L;n0?0LcgV#j)uP*pVqW=%k*I+0SimX964bR(A&g>m?{2RJXBThEvxzP*?S9Q8xj! z%qW7FtV2?s<*!!etQiioHhz??IGZ+<|VO4s-nqrpE8hH zbNj~_LkN{hr>K-=Al4o@VA=2C2%}2i*(*azvT0Ytz))>O{#g;WM~Dr9S=_Tk!YjhZ zGQc2L&1eS2x*o*Gb>&1gp%%e4Lr?(ZSulL#etLymR3raI-@x9eM$9G zsro9_O7PCOR_mW)lI@A=2^J#V663D^1qRmxr2WbmFX>X!xRX78haa88C? z3u*%|Sk@;bjC~AD@U@H`ew_h7&^;Q82JIBzFv@%Rnc70a)o6g!#NUF`kE3dZd^oV` zjg+6(VEqsU{k_u7(Xv`TG4i zxb;0G4&H5P7v`fY4D^BCjAqX$E_9R`JQtf~*8^q}#5EHGKL|aLTEJ~Ml!;F^CTg^* zx}D7cMmMGHw=0@YW#of>GEKF^r_sKm`C+!SGxXW#)f=kz)|7v2-4wViMkJrem- zq@-`?(dsk^OLRFXi)aCE*(!-Ufa=kJ68eY?C+&3zSG=3M+7;>I2#Q0&67+eT;ljoH zvZs(H9HNs@GYK^y_Jdegq{hgHXgX!ovHq2I3NTf_U|u>4_&7jP|1Egx>^5W{j3(0{ zg7q^#O7hS}U)Kj?khK>J^lk0|AS?;C47KwSWQ||bM3vwp%t;T4jozK3;6&^f{p6kq z5$GINFb)Xg_Ibz{tX(ER4@&~Bcz5oh)SPhy_|TBw4Ms8gM9S=Z{dmS;^2GFoBfoto?y8oCADw1OW|>T<>(Rh*)?Rk5FY<((i;f#tmq>yZs5l7Z@$-`P*l`E~!O+*zFDcgTrf!VI@s?t>#+vDR=*|dvxd}W-cACE}Pm)H5B zF+x|3byPYqQ5`}Zg{DLaCIJsH+K9p>>B z&iZheM@_|cXGQYHRhK#BqAh-U$#q~ge(ou8ZhR=(wv!*vHWGFQ)!D)A!~}g+i-s@( z(tpZ}JFOeJtcAUM0LV7a$+CtkZQ!pBWr9WZVfaPXNn9#IfACTyj4I-#uN z${x1KfF6o^G3nu=-51r}%W;LSN`Z+GPF=F*?%^ao4=1U+3&)f2@ad8x({48;l5B72 zkh6E%r?_P#y_ zi64Q=vCy)=ijI*ew*S~trwm@ff18Ibm@hcI$n3if2GkDo0E|HQD@34lcU8w&{*NQY zHJ)OrN_w}NQbc0ol9VO9FR5E-t`;@Gl>Jx0X0uCA{=s`)R=(C4oEzeNF=ILv)1}z<8HX zggp!-;^Pp;SYn0kOLeyTUsMTRL8LZHSg_sMX%fgr|*YHC6(y~K%zat-s zPZ1C4uBU$G`g*(@c!$f!a_fy=Sf8%ZLpG!t>Wk`qZ6qul? zc-x}gx6zSRH1KH}hz&R!Sz0u8aK{?c)<%7u5xbt&P_F@N%71Vqv~m)b0~?KuPI2euGFIOkp?of7MM1O zW4t^S+De`4R!QY?WL!u1U_+K)Kau&eSY_#`zRsVPyd8HC&e2q=c9dzL&fUWS6amFv zV$Sf@DC$^VD22bnnklOORszR)e$tRZAslwNj4D~O*_0IqW%CER*`r_9RtrjHvmL{C0vw*8%<7!AT1eKmpBZ&5XU=_iqu&2 zK$LvbFptVW$uvyu%3(q>Mtg%22dsYVK&HANh4Iixye!h`HmBVgcQ6v=f=#;1ZaiJ$ z_6z_>Mn@au;DRH+Iach&6o`~L^`sCojMW#+q|C?xb^z!12_Qf8 zPxF-z=%bEynl~U;NQ`WghyW@PK)5DpfieC+6$E2u4IcHtJ%nPf%7tEyL-}ImcVRR{ zFFe(=5u5{?vTbr;cn1y81${Jl_US)pOUSZXjvS4K_!9oXw9_|Lm`O%Fg?s=y`S!zF z3&qOk=JSy7Vt)uK<|eNlEBO5{OcgWmie^P*XHLAGyaLV4x%L-qjo2T_E@x;8lxVM~ z17z^-u;?W!Qe-MOJb^+dYcyY%V+dh!J%nW~SqQQ*7W#Y5$_P;A`C~QVsnkdgUZX9^ z;Nxll&qQ}2uScN#gfuMe@KZcdPnrp7{un%kzycbjG;bj&d40CT$f*C`kp#02=8vJ?1$y~Jcp z3wMB|1W(WcTKeRe4|vD?Ykt&*bvY-Tm@`H5gHMhlz!C-=VHhYLU{ms-4+IWe@=iVU z*B+b2tLC6me()FJ5oP$;PbvZ-g+!HfV?-bli0j5vP`}M`*c5PG3SDtAb_Q_BAow*R zVT5`eLF{s~NlLN0h#DaO=sR~kH-`=`M;BEQq`(xMb~Ke->t#bi==r1B#q|{0nr$tU zzR)&t3@rUlrfZ$kdTfBk_y_757_L!qjC51T)~4+IDuWL;JYNdhOooqsbLT%K<{i7M ztGN|>BerRFKdWnTWXdFvIjve2$A}Q%k3Dm@X|_0JXcwNh>?|y*WjI5!Uix8#ju|6W za!d~^;%gMmPsG=Rjfi4!7e{l3SdPpVM3x%Mg)|7us_Qv^Mjr>3WKD3Fkh){IBqe5d zbKgR5T!E4wZXFk4{1eYFM%s6nsk*>RHS1~M0*nVKV9o-}q)_92%KpBdVa`mGXRQ*}N zNp4@}56RL#(=Yq`iYtn}$*5;>RArb1V+>y_V`Oz85i^)rRJzXEzLsaz6u~fJfMuod z8bZWA?4@ORiTGvbNN{LsoQk#0 z!T%n|ckCHS^aM+79%oyrk;e^LiyxSZJC3j~niIlvCIzN$xHaE!pY@6LM$#{;ohFPGd&fP6Qr|68M z%AiXXBA&nxWpAn(s$CIX8Ou2vU=5vSHP4&*pRx?WH(d5EjXSPZUrHQi5H|sob%%&X zgBMx=gz#ko}Huq{c{_xKH%m2k0as?=B^&88)A@<&a8_Q^0@G`~6OOKiiy+?NW0*v{pQ(Nt=|lq$ zZvIk-)woviUv~DI>S`QursLov9_$WXOa#!F>=m2CSrCn2F&;^1z`{5N4d~%%Y}iuG zBt3_09(1&wu899$bQoc{e5}tfDxK=3tew$>0A;(A8Nl;^G9C^_)4ZK-p#;f{XdE+C zPw#esKf4rT93syCOE3(Dko*KKuFL2gGyaJtv`&^jKB+;rH3&AQY!C?KL#BRg^2mBt z&M1m3Bc;*^3r97v-mA3N{#Tp{n;aISqy}+^tCt|;@uws1o0q(6$w&iaVs*44>xDlP zqq8wP95(_H zE*bs3RHh4 zf0;FI4B}@*v%w!TcpEg8`!n?%UZZzi$m>>AnT6GMiT)tqZd@NTLFZ-r-?eC?%)v|9!XW`8oq9FZ}h;+K48Q!d0xgr9PxrXJzY4f z>hej!;2>MRtut~QQ@xJ5T*UO(33yihmlQ#b;nJQvhqI4G@G0IkMfJ|2zrk|M%UHZM z`YEekO+`5|Dv46rJXqb0ev~LDqALSn(;ray9LNP!@WGiE?W+EQ5rm5jwg33!1Y6kAtQ5k;7-Lqkl7@E^D) zM)!E})ENTAZbJ^(M|>_g3Pb7UH`fg6k@LQucoNYAtk(rT=?T80(4 zLkiGPc`jO4+u^yR`Tn}YPqu$<^6CQ=ir}IMrxM+<*NZh;h3~RU_B2N|7DITaY8k`U zg4|;Z>HJA{e9^8S6-z#XPTE$fYmz-Qls7;{PznA{4Im;Wj<}X4&@Q4{kXI`%4JDFK zQaIekY$EAUsR>9xwn1TFL!t6(^`n4IkRMPKYoep_ek-VhkIsM}xbKvK}oXaAm=il}F>sxt_I8HB_Nq7Kh zJS=r633LBhp>1d!7l{s%AEspX7f0&c6(!huYo8`-)@H*2haEeV{;4VS6irdI~~r}q`C zGZk%W(e8Sn2k!QWQP909n-#HU$IztO?&UqG3>7Mh(O^MfH$_s!$WYWP;-lpur*Tom zN|Et@3W7NG8dGMq0gyg}4~J*pxXJ3DU=b*8K0^UcC$Az%^zdYi0ydB1$pW@FwPNgKJk$dQA{S4kA+hQLj^L7iIG>GUE93s&5jA@*}mw9^cXl6+F`aS z5%-1mk#skTx^8@D0tNpm{U!o9#s1RZD$@eih31a5gbkwhHi8g3^hCZ07X@?E^zP+Z7Ruz`_4eUM(nc3Y@3W(K$q?rN4M zCK93!N6GwUOUdZOWd`%6|AP+OHr&5y1Cey&kO?7;(rItmjGW zv3(`)zb1!;2?6|JZiD+RWF7@d6Q>rjEQPOuDlnJAesb=n4TxcHI8m5_DvILg=v{0Q zK(bWSS2QaWfbp2X4zOeA!FBbr=vPi+sn(o~9YRs^n}2HxK6Wrdb!>=@%~^19HfISD zz8V2VuVPzJ8t_h{^(4rOh2<&N~SRkoINh{ZCBi%i7SWWjsJ46V##+j6RP2;-;d? zCw`I|cz}9X^Q`Zed@N!_~FN-&v$Y=2$EM~f18Icy`s$D&F$q{{G z0_;SRo?hgZ>AQjr{`aRP={|`bNw)~VlX9FsqK2SE^az;OPdqWhT9C6iC`}&%V<%2_ zS1d{CQdmwrHYrS5jTg8x31m6ZW%kb8U;OnSzVd6Iyz?(VL7e1<^tR?P=Vz}XQO+!Z z41_g;aS#@tUcl6+Ut5!#yEKTKyoo6@5$oEqH}1@k7H87S$ZiUz2FNhft8k5zMHflW zd;t!+jFc>!m2p%i3aEt9tNyDaMucuJ7C7*gm2CPmMrx*cS{n~|(n zy=$RhM(lOKSe*koiEa?9K#!z|^oVcDsL%~(r}Oo4lqLh*ri@9g(+^=o(u8ckq?&2k zgEruYRAg#dqv$zG8%m2Mx5DSWdbw+J#`_V9A6q;ICb}LVKcX%BvYRjP#*9qvXkj8L zr4f?fFleFgxmma>Ab z#yfo}eiOi)O^G@U63)r=QsehND?b@uzGV85NZ7|avqZRScr7fn?wvh!s?z-n_+a`H z5H#J?=d6+KP!>Hn)q@9BYM`b8ZP{$lAw=r8XR@XzJ+t})Y|uV6S8R4oEsrP2PmPw3 zQNls1zY8=oVy-x1b6wJoeZ9&h7w7{q47Wv#0~CH%!&+khIGd0rqaCYK2k1M~jGi6O zG$1dzIV<0Yo5YAu^C0n(iy^c@vvgd_aB#-WN*=aMvrET^NbWQ~?cjg})^(v{t=ATt z+B_Z6n!5|J4NO~`$`L43+pOQzsVC@rRHF5;f-+<#S!dBx$_>?vr_ah)c|-h7^&y;v z$8!T<8=9lPP7@+}fR$BWOgz|z8ZxV{g_ETrO`}5L8bmDu7UR4uIWc?v-%?KDgFtrW zxH2*RaqdzPR^6^}3xW_gzo_B0j-%6~q?6`sG&WUqbd#L*qEHv$2?RgFAkWG-^Mg*y z9P9UA-i3R^)Yr-a)6(&jtiII`%nS}cs$%6_g-8DB(wmcoF<>;|+j=#OM;@3Dc7{=d zY)BsMbQl(;b5KWrJ*hE-mzT83MtpL`obf7lizoN*z~%^{$xde9g)kI41Ey58{E+R${@0W-o zsGvbn@zw@KK}C#;h)OjoAS%_URPoC1`+e4)IVa%d*Wc&&=WFE5%--wrtY$EC%?jz>C4$%7Tjkm_LV z=|YC8p2=x~leGrf1ffr637(HEjI}@w_H5!2M^k{S$`nxB%WoUFw|5*=QspAcy;?=Y zkF(71E+g#Su9fE{KnAsvjusWrD>>;DD3bmVVR9~pG|JH@l;?zs7~Gj@71VQ;;%M`^ ziK2ESaSv9=0$`02m*E97UHtuy6TuFKWy=w+hz}0zHQ50|Uxj>81*8c#I>U<}^Wkyq zbUrvXA0THER5zlb`ZTjr>i&F?bg4%D+AipK^*I5M5D{_V#$_%D{)zQbp$dAOINy&^ zv$bc)v=8M8`)C$Ka#r0kOOqxPv;`F3}Nsf8V6R`}Ld_WYEHJ45Ws^8jeETZMXV__H`c${$Fa@@OFQiSw* zZJNu1Hvbn_uEj1PXrRt0XYAOWRzysaZ8Rbd=$n~<8W^QzCwjREPXDMD6cEvRSuY3J z7Q`91yJvA{6?Dz^w)9C4wk#Da@RbJb0$5H( z)7%_XlF{b~j*KMikPQs~vOT7{J9(;vH zyV*t#UebtGJUFKHe)d4>1_k8F67gYij?`%^Wyb0^9_oh+4l*LrXrnwW_$ApJSJ90@ z)ajT3;!pt?89O0@MKgFSvPHPZ2#H4*x=b5fW*mM#M-hB`#f*XNVMZzez~O7nuL0_n z@2mwK0`Y;0;}HjTdVCn}LH2xQ)uYvQX8t7Qvhcy1+tnry9$?y?vSJ_(1S z=LIb`jI*3&qU295MTQ7-C6)(<6-QlBkjBdo7X1mubD*GuY4cm(R|L{Y_C!cX`ypKF zIt7z`Pwp)cDEml5q%H~^KN{Uhn2+BW{V*NMJ3f|CVYhTBQa(Who1r(CL(D~$+vqTN z2~RPm%6l+)n3QpCR_PM-sy;_b>1-4N|*IaOgvqBGcGvkD69iw;FvL16O`@G<_1z3nPa2j93$UpD=k6D+NdBw>%sh4 zkRVHaOUHXu-Z-&;)>te36G#YVVCHWLJ2b{!UfPU=nZjMZub9}@Oqp5}6A_P!nY{dR zgEo+vD_AC~+SQe38sFgiaKG2<4mNb6yl9YU9Z(u;smZ!D-)LlvhBk1*mU!TSlrcgb zDZbPVdo)3m70=F@)nSws3tm_^^vWkv7pBL+LfRsbpgeW)5Vd?)eX-SUg9CVdmY+)y z$3-(x*;L7&>!3es7p-b%G#z&n>8&GBscu!Lh8qqnq!BL2b$0PadVBgtKXc1pwG zvqc~6>w05$g-YZlrQ9xjWcVbaQzDG;3lKQWb~ek-unV+t)|s8U9^IWHK6*yZKnzv+ zw!ECtsIy9S|F7es4pS5?i`w*-Ha3D&Qm1uY`D*B5rhE;%nsp_j>1e#lA$H^WMkx@}ekLpQ{fNNDI@o&w*x6VoIz2gue|1FHOc;`@297fFnw2V}jP zLL|QZCm}rv$4P|x!5U#W<*ib%Aq!Bkcf(Z36wn6UKm zbTlFxWPZWi#M`;wHc~^|I_ACOvQ6k2k)qZJH=ufAERm2QYO{RZ)^CPDh-F^%+Q@3` zv*C%H$exxO>gJqN{`Yp+Lqo*&2{i+1JO%_E05`+qCR%2^mw`NlH?9Q48B@g_GF)Ke zOfylqTh94#US0TMRyc%%_JYq18IBQ;4yOm#yat`rOqwm31xjhnNC`o#lNX?XuW_b21#qV8nmWrcxCKU^_=Gm2YyWsu^)=siDh$GSOM zCWS(0Gh`Jh6sVCBA`CkX8OR9Ltz$;u-BJtuBe?P)Lo*m?EuWb9rgRyTgKftIk#8?Z zi=By!^72=(ns|zY^mAw4%fVt4(dew{jX7?XuWkFYd{Ssk>bbz0ax_r!nca-t6x-v+ zY#yChIyHL}51gv{NfbKKk|)_JpEu60LDO)GbDLD)6$+l*Rf7=O9rNu|6btv$746@a z8ZCvrQa&U3Xo8SYOUl263Hg_Eb&}*NIHiHatI|(B$$ch<&>R{YEniG;V3I48n$;oI zp^ zI?4i2x<6t$?bxO#rO`jKYTFM9XI9PPkckff`3Pvjp+ONN3|vCwVO0BmR(%gtcv%zL zuh{|urXpZU&Y1_o)JQN9wyK1fYmOi7a5!@fV0AjFyQ3-BsES?;XOIP)l^JRtIq=KB zq}FKpbpDQ&PoF3uhU#;!c3C1Y?#cJm0(skgjON1QiIgF^*`QzgNq+Ro%cM_FbLKOj|JVKsnckhT_2Cwx2i?5`j{|vg0v5pOVV{FYDKzL zs|KP|pwn7PZNxGCR<%_=kET>lpyt8ES7P;prz2}S8{Z9M%ov!92o<3PumuDiXQ$%m zww7(dt(>T&&?`d09}{+)E`&ZnO{^k=0gW`xdPdeL8lgRuK%EZ4dH?sxoou-VX% zrr0VC+bEoGk>E-lXI`3v>+M)g#>O6;=785cH_d^H&L^}_m}htATNqHm<)_ISjHa?8 zeQ?M>=`F2lC80QVQW%*V!e7r5lcR&GWxU%{A$}h6PM6xDkXeIyD>nz>*s*;h-H;rt zVpbZXVlgJJ!e1*u@@<$9Rd^_kgXzA$$~FL0n3SM zR}}5Q9G!LXt3FuU*}%_s3oPwhU%&d|xb&=1{rF>Ve%**ZkB`O7p%36MiV{5L%e}iU zc}p9AzzF04zDBrUyODttIj0>}E5T8-x{lhZS;8-nbujM&TBv8L!&GzY1G;WRqBNP+ zVxoYegcQXH<+VC&V|9v=$l%%acq#FsNcT?Fd^V+<82t`L5(~w*QQh;gOD=9hj@386 ze)W4tHW&f-t?zyGEq)Uv8{+bbPXLxN=?MP&?{9Ca?!EmottR1P$k+Q8>kT;LySmwL zB$})ays20Uiac&0X$>%BQ(lAIFITf;PeRBz2B}c1&ps9vOsRak z$?*|)9i<)1R}uMkGHvp3;%~8SyV<$}xnnX#itz4flp@!iW#cTEZbB ztB7;vwVrOYaY#=HUF+Mk7TE@)UPmTAwJbR|cOnKmEF#IAy=bJvn#L7*`h08NSnG>v zASA_*%br;#KZX~4G3({G@_@ZrzL(Jj(WSFOiCK55D^SL_G&JnFR))4FMM)ZNd0xSl zT45I~Fl3_2K^czv$7s>ktIa+H%PU_2>q@|~2H^zq4zptM^p^T5qWvbn@@SjzbIko3 zKlfRKCCukT)-*oiC-1k%=i&MFe9~5a#9`SEAN~9hYZ|xtjIi`8^8OO6nyM?)%%HTVMh7$a-~WIElFLrJ%O$9}eemJJX+WB`$@(3%PD zn6qHvlVZ?hQ;DT88SRuO_Q2r;p#-*0Uk)AT+`aG2t9JRUF1OIwbB*1O%0WhNFM1Wd z#g2Dk2=<14Ixs>>refSxfI{hS*FPY@z_0tP{_8Gb-X}>jv?cFzcw9YcA*c!%%J((7 zrnn}GqbCbW51^RzJP=@(uMFLd+(T(p?!JX#8ez$Vsie`xfzv)I>V-dezqHCJ)5I`qUaXQ?X zixlJLLQGg!1aB{cwa~C8Ba49$K70fycGVdh%vzKfS=_=zVP>oRdT86zx^cZ|(t3Rf zkpJ)xpoKupJ+#$`Ga*zUVjS4)O;S3Gt9wn$NuM|mN4bG*fs)F*3g?ADEG&=fEn-Fp zp6D({axEsWAQG1?@0sh^q+VndhVxb?|GIWh^gu3=g_N!Ol|%~m@hFK7AfRY}5r zAmsN#ZlybN?=Bqpuxt$=!q4W@%?jlw9dVFbciBec{`cH_*L7zX) z2^}quUDz zhQ0X2`uM$~OAH(KxT|6+5_y?>5yk-iW{kax-UNCv!k=klI@>|798=(_*kE$G)4hC$ z3oU-HhIx|rUohv5-kZZABBq4}9kVhA4)40WOHl%n_5d_qtl+YM1JY%d2`C6q;Od0Z zb3J%oWA}DN2dx1{xjh#4u1I`2QQiRGnka8EP^V&0inJPjLXA}Z zgAa@a7V3+Z<84T_$o#vl5zy^zcl z+YQToO+SLC+ttJoaDxeNLg==+-B4xVIM&_0Z%`uaP|idx5?QbhM|1`pHR{81jMs@} z3N6cXOq7VBVGEeYZ*=9YZ4M4*)dZZ6Yh@*+WrW=N$*h#&@1Haq9li0IgpL+4n{(uw zkHlWA>d-ere{+_?8fH1JLaaVR{~hA6LKib+&B^_6Ub1t8)1WaxQ_&@cYY|>0TFuuO7=0-&;=X0YOFf^2t3G-L&Ck`3$T15 ze##SI-xIjz=Cf_hG)KtNRj@|;XtM_@Bm}IZdu^o+yWfBUY`|Yu{TTQ=IB3grk)deG z$3%c#P;dDmR2G_2Ht>fni}Hi2nD(NY%=sjMy5MUzU`zqXKgXS_w=oU48g#DUPdW*e z?8-B_h|wR+>M*q)KTou+RmmyBgpNv$#`h)OCGJD>2Y&J$nUHkUm6S+>T_?Z$^xiO` zO}OivQVFlF^Ey#p5cv(sI7&M%umM}-zcpyNG<8UcAnYa4Y`?U1O{crr`0%raeCF%(}8wf>*itLZCKcTU2I^D3Vh^^Pa zZe+!frc&^c*yEpml&pexL2sbh<2v^gb4EfYGE1gf9ZMcxUe*#_5!G@}p$bZxTU9W0 zo-x=th|Q`c-DPYb$)&^k+2&-u{c4;|)i&BbL3Z5+@GbcSf=Iar^(u;`HVm}q(;&MK zX!``JNK|ByAL$YYcS{^|9my^HQN9XeEWRA&RL9qFmDUzo77?oKE(}UZ0uXkG59VeXxll(mE-T;A?#Gn} zC@C!|ur_LV_T7oRn z?GV+OYe+_lgl}-wGIW4CQ2wAu(Hc@hFj=-uwNNt`i3B)hB2EdB#T8B}Qd5_2#p-J) zo>TsH*GxRUO7Qk$N^v+9H^Mz@BSjd4xk~K7v+RJ39YDm&j!>do)qCWpy8eKR8ObP< zV1~SIguH&4OPBl6W`COGg9PgT2EWC^?sRuLeLG?K<-JUg#CxM97K;wt7Izd0s12|5 z=NHb(t55$j+<#8?05Lo!!#0|qFHJ07Woqg@U=lAV#)+%c2noc@A%r3W=?xND1vNKuK^wiGtT zD4)e*E1U`U$8}Oh)^2)xD5(vY&=h%RXmo-k(1Fj6#^nS$7;PTn(F+~(3}5FGqVA4XOsSjIsSR=H(E=V+kRD)&_nO0X{%HPSd(7gx(}Omc-*Lt>m|s}o zx-$k-%&caAvAjQhNU@Dx;&vRE^)!(1sO(^uJYbQ4%08TYQS}d6tUoh8j(7myHMysvPyuZ@YN@1;{t2k=;gi(Sgq?OhvFKqz| zRK@0d#jydrtxCWG^1_{YK~dh`=u?k`%wld$yB;Du)$m>zKK(C7M12bjzgCLLLD z-y5-z8UymIadas@fncXBf(G-2EYNv(f4irQtRz6>e0b`COX1S0{)~smg7h>Y$;*DL zQ*%aof4H+4Uqgrs54anOZ+@~tH7C0}4~1(azQhD{RyU4w!TS(yL^nQEiXIp9lju9{ zFv9cE?DU6~q0cUc6s*m8oGS-Ix}1V~WtJbx=F|P}Id~>VQgOb-}!jA${532pB?D+IV8T zyKyYYAFa-NsT2ec&Eb8)LtnLu2k7a}Lg@PN^8>QukC@ySh+fy`114}-c6?{wK{wSk zvoZ{q`@Xeq4s`=95Bn0P(i*PUMThAw8Zll`Nq8fnwodf>_6JQHYz{OYUwL#ZdfIzp z(C|?KyS0?yr}0+8u-`B}%Uk9z%wnU-fZx4toDZA8JtoLna*O*_TUc#$`3 z@nv?l`y?7@E0<>Vm8Z61O5gMtI6l~q+qzolX54k0z~+zzTxxk2w^4ah!IWYnf}56l<_A_u3%B4n;G0#~|C%9BV5e{YiZs9R$Y}{+^b~ovHMeXvxw`Q)$V1W#gWr=0}MU&#CAvTxcYFd_NT?T^Ql9Qu*jo(UqIpl?UZOMeWuW6A1KDoWx-zJxe4 z0@0FV1S$`%Lpz8woZebI{XMMjoedhM;jBR(#H|t#k$yJRZ$gfArQ*~`n*)+b=aKmz z^$O^gYgLBkqBY&;#!zu%;1FE$n>+%=X1=!LaEmQGvp5Z~C>8~g(>k$|#dWxY;--(K z46?tps(qNk`%&l@3l`GWdtZJ&XE;%w?pjrkH>wZa$r+D3>D@A4PH!V!caQb{x86+o zln9b&Rnv2Yk=ZN@?l5pkEDTiOpLBI1A!E#V6*b+M^Q}(v#dj!GwrT@XWGXt3popye z+dk-^r$~DpDl>CQ2X5tZJ4nfG2!q#kAbY(K)i{R?6SV=hlRs}WJ0f>-#r@Ms0eHofl1j_x(8EAbJai~wfs=~lsz=~%$CY-x zJ{%_lHqBz#f?fq)1Q&}<(02Li_THT(KsU%ymn0k%b9SSeh8sqZ_CV9K)mR~G8t3Xa zn`XSOkF(wVCQWBZdg`8w89+x@!i;NEY_XuHT`ho5S|&vH+w{w?YJB;M-4R6E%`ZZc zFl7&`Gh!JCvxY_(g+8TPfi9SZ&LV|AV_YR}L`C&TPu;N+xjvT(m3Gk|KwFig2wYBR z**yK*7Ke74)GB_(aA@$g-U&&DxuwaR!r=(AtIoY}PM2K)>VaXXx`x6>cb*7en%;Ho zYQrQxqhx)o=PNh2pd3tfxO9i{Ra@q@*xkKFxI>zEP+#T8ND6r`bK~A}$}ja$-yzg2 zc_PW*rGmHVTGjH2o+dhO!i3i1j_d-)3iE;7p3F{2wf&`mE;TQT0q3#`aXLBa3pb|4 zuIP*nFnwVracKmXV9u!l$5F+FMHrC4+%4}DgL*7HH7mEaY&2A^Eh-B?<~YwtwS^V8 z!L)ALywQ5^A-u#hw+fo??M0D05R5l6`7nToEblE3!x$;ss3!%5!iF@1FO^4GA?bte zutT5A`+M1dN`%~gw99s!)~wL-J*;--73aZuSpKPMZ?B2!^Mw3KD>r0aE-&1eY=(CA zE7FVg^#TwGSgZ{@BzP^JfUNrvI@qJToRC5$q`L>)7^-w`K*OHhJ!H(pn9VWf{&=EU zu`2L1D-yU;l*1Y};>Izom_e?nIN{Ka)3D5OUa+*Sg{sBkmk;lz0I=}1P4!Qbw1lP5 zobl{q1T#-E_@+)O__pJQk^e3*@ZSX(sO)L)85oVnfr}UJRH%dF3=9?pph6X%MLI_; zJfPqz{f9*B50n%+G;3S)k9{7ngcn3Jn?g)~%vK#h?0vT_ZVapfAppPG5VhcgAlN!m zyltN};}ryZ=#+P(iCPEYhCY@#Aim5AACn=ly{tVdgJ;D*KfE9-A)8%@{q?c*pkCtpvfk3h+V0*^7cc4v0G4?585TRZnn2C&FJOD5JU{O* z?Jn*59l5tLTs*u-tZI$W%Sd%SX46QuongMYnP{6=Z7p2y5b786W>BO;`&4sY+PTUlO#L2!hB|DrCi_J7hQe`aA@+luhsO0#91@^2NzJW7U>n?=IFFZ z2WK;{-b#d2>TZL<)9 zCWtagWFmGX4HYJqCSRT27`oH-#9$W-fEc&{A_bmubb*=DMgT; z80|J(0fAk%;51^`u-!9|3I2ev%WGC}vp-htdvrgpBJyYK;j`yWrmpI`?C}$Qj*PO! z%SjK0ktTq7D^NS#@dY-}c>_1)qP(8rVK$J@fd<)3IAv6qDc2+xU)k|w+aOG?`Uuo^ zG1La3e56R_F`>BI!~`FY-88s(6_bvMVx-)zs3J-eJ+x`RNiN(a0WI(_T|~+(sxH_0 zBo9^b-e^F?p_GLYu>k~Gpj^A^YPBHpUt^EQD=H+$&n9nHUTiFldZ;=w?4>OK3vt^m z2`^;zS8>`#R}!e1 z4De9E)(~MF-37W8Su0X3G#i)%{API(7Bn(u3;R28_+nq0DGi z7h-nMdbr&VrX$cCKqgKV>#(RkFdv-V0KIbXhHwN}+p~lFKZpzO4gscDkB(yc!N)<} zhT#`bL>Cf3c!7C0$Hj8G$!ItMNF{D631%X>BoR=pMg=wYt~nE|HL=4WoJe|Ijg=uC zaD4nFb$=h)e^pC|*8gNQuBSCY5d%6A%mKGtdBWy1DJy*+>5wC|Zj-+oXiJ`(5lAS|;$#PxH-jkd&4qLbet zO_wB}YDiNEU&c|sfml}W1*wBFLXW6VGYRcfci$kc-|eW~H?)JPjfwvv5I7b)lmzd{ z2{5Z##LdkUTOeB*(`^{hAVUX79vqrrRZMwCC@tCk5}6Ns%7=EB$aQ+oLBg_(tW}Y8 z53G=FniaW^I6SGhgl?KC;AS6cdGS_|^ojgPN=&uTIF5bnmiI#)XZU)u)^8AaO~@$G zs1Wk?Rb~!+G~_x~k|+3~a@CAQivuZ`*ex2tge>lO05iLh?I89m=a|`wfWO-tQh;C& zmVT0VG_#w$Lx}9-2yB0}yQ2HhG?o665za|gS}H;CZrBMFoYV&~!|^t2bR>*6PpMvp zk#az0@C*|vmUjzy?u8Pe_ael3v%6=~_pWfr$cMN3iTvHFA^XM{?^eevn!89cg(1qs z$Lfu@c{5kTrsg8p^YzVYML-i+R?$prEp>cN-QhMnygfSHHs~-X-q>>izYPb!wIA;2 zV$`4~bR8ypAe3FpJJn^WR(dShYNd_>K~V1jWa9M=Q0GYZ$|7w2?B(?ztQ>84QF+=h2ysDaSO(B}^<2-G zXdV<{9t<`72MLw1DiXVbh|{q*M?!m}n3(G98I+CDI}~?g6((9(oa)X!)?vC$SvxLF zHf)~3HNr;#a-mV=0Y|FoerE&EpR&6#8<3sz(Eyu{lM#ccBDukNFzwG)bujIC-!&S- z5okbeJ6gJSd4v!j$g+V3`=G&&rR6G*a>debc=#YJ2jrAOfaF}Qw!SoZKj=BD-v2t5 z)X97?59dGddDkz|l@6^R?8j%`-3!k(4cap7vX>3{$UGH-$u?jKKfxY$xJN=Zz8BIU zF&dO+Hm-2h;{DilVNqRhZ;p$hmsR!tGg;pzIZ$5R{j#tc==Nc1PU#5eRQ47y zO-L8B7I-dH-7W2l^oq2X!BzvOOWkq6_$Kw3)LLlt@ev0i(RsC1iA3=T=!yM>wXzB! zU@Pk5C5H_w=66`l1i+e{5oaotj_;=?f-3K6KOcyWIFFRVf!vl-1oD-63K$8E{zm*X zUEDbc1>7s3>=zAOMu=m!SR(-ui-5jr$E_^X11mfuC~FmPvg|SfA8zIa>NfNXnwZw4 zY%_JZz2&9U!10ZT3w<3gF8y#y4jd+jH3c}_HGrw34VZcnAbX5&sg)tLO~m&%r{#|=p@`@UGwoRs&tF0ufZGf zzQM^kw-8S4i7HO6*{+A`V$?)#jX80HP}pEiXj}BbjdS4?5GcCg<3YTnK7OdRJ6y<~ zu&n6}%MoKnvgZS`*9!7A-=TSkg@|_-9ax6qi?w>R#2fSE-eJQhU@lD+mDI6Vpq%z_ zVX5g>cU_yq9sG;`@Bp04?X+LrsS3A+NvLpgb;YIO^z^j1TYx<)vt>Z>y?$SD*q{O+ z=<((cGsX)w=qJPgltb;HNiy>@|A zCZypq(XBqn{AORxdT)<$k7KVN0kUWa&QR^Ts7{l#Gqtt#PTL~l&bHWeFiB%DZuqbm zZC7W*$3$Q)O(xkK3=TjqsD<-e*%7Uz>M$id+{rl`*-GHUSudlVtlBe-RS|matV?~^ zxFqj@km9d|;GMoSGJwHX9fL%iJOChf!DUGm%z=6X@Lj8bPpn?ALD%`P7nS+J5M&P` zm$7b7Lz%rvglta;sd-S15H}ZUYC^+-o}R!dmEgYNA?U-TNFl`__>%Q#CZ>Y#<&Oz1 z<+xBx`Ze`r5|86#?ug0U7X9s}54n$^o1|U>P_)08+yTYY=78cMb!GniVX}{b1VD3e zbzlub)&Z8!B@WuMfdIcri+(sU2zGbtTm{ln%ALp9^y9!LSUKD9{gTS__)vv}$8*eLkO~3bn8=PfyyfzloU!FCJs#P7SIz z+|;EKU*Uvm5V=o5Ks?TV z4;s$>=1!aHQH0rMG1%%y2ln#DTK~?ne@ z{uOS0Lsb(Jiouq4DA#Qg%vLY?jsa{qG_QOo;y`6(VRheKhBIc>Ykb5)MWurE2On91 z+E=>UVuTt`($2QfU34@g7do>xDJbwr5z?R6~10vX+cLt2l^p>x4I|#`h)Pq)#5RshDUVGcLo!u%l#@etgYcO6 z+DN07uCpaa4aqaqpyMX0B9KhGtXM9csjeapx0yGa?&OScJ37a^L%wyA0%I`~N~O7( z|CiG5itxvgY8nY(;7f08U5>zED;RQ9Wxt^?-GaZ8F3H|Z--Ynmf>R}oCQFh(j}ctX zO$9#d7TX!m9eKJV%(^Lc)=2dlU@fu+hl#86Z?d;DSf>D3Z_V1NDF?IaKo4c`Esrh3 z+mM)fi~yLUjl799%~H`x{omxSuWpQ8f?A@-BDjY92wp}uUKfPIEue8hI#c(%I3~<7hEbLt{834VNUB=po8pqG zLfKAt0_i836{jwwQmk*6s0wuU@{BrK^V6>8*b4 zSsc=5%R}8MK*pLB++zby5WLR4_Z2ftji+i>fP~F3-d6c}S61CxjSOy6%U(+!_UO{+ zo$+;soW=jnFq*72_`U1ngq3A{2!LtC<;`U4@88g z{ZUxL-Qa-)Q(?+SEoYfp&I;wEl6T)jISMIRBF*H{8Pkx~JtaAi zoHiU|4~FIAvWd0RJh;&;zd$SaVNDR=i-sq`V_~r+L0W)selTzBlg?sn8Q<8SWK6#9 zle+n|-tsOV*M^K=Cd=3gv4MC3r0B*6Boo90xIUZdb9kCPOf}y_*?4v%a5wjPv6nU_8c)O};Qzol>$7ae8HT!#S>|@0o2?=qO)~*7wX}GB8 z8lVr%OVYA08L+9X^vcq|T+)2Uss0HtOz;qCd_js5sZp$?9A$PC1a?-}GI_aNzK)a$b$_=3EXh z(R`Ha7v%?=)!{H#8m|t=4bIPH(qk;_>23^-EP^k&6zbyCvho=T8-!H1AWSJ>A z5@kK+1z_r)c)BMngP4y&k9M%s9IyhxqNsRdjisCz!nu?=o||$$8PAP?PuyU3W8Uu` zQrtHtnpdl!aU(VxQ>II0&e|yktEfKN)PyQf#>fk{;<4HwzT)wWCH30ZQ}nNS@eql8E8UV#U4S>j`EZOk}g`uiE*SQqIThXdo# zQw`f#_1!TtLNLi=)eWx;&5r7h#y?(H4mMY_+g+X=VLe58R^-}dHuq!PhZK-}-0@rR zi2&_h!J z|5g6W{1^Gp^ZW9j(qEeq(+^{z;yHBELTWc>b~cx_o>7ANjxMAI(3Ke>ne8 z{z2Yen|~nxV*dX8efc%{d-M0?SLfUEck|b0@5-;@zbo^1=I_YgUjMo(zaqape_MW8 z{?`00`K9@r^R4-t@;Byh$X}noE`M$Q8sNW^n^9iH^*@*7ugEVZFWJlUE&O{~eqsL7 z{DS-?`T6;I`MLQy`HS-xHqt0p7uG${MRS^)l>iS z_~W1QeY`v=urng@(~BD+W(LDTlw%mdf4$9F~1C@4RC8@M0fwNP>qK`;g;1lNa#}acy|HTZtI|aN}{qBWR;)!yFS` z`pWB>(6l1w2h}`i$#42WUdrmCu+64SZPYlIQ@X=#lrLt6{2O1(v!~&lMU7qAcxF%b z*hVB+GG(eyJLVL^vcUp$pB#aK^&>p;ZT63N9vih4JIt0eB}6>Xk%-2}pfoV&?FvvN z@|dCWxPef8GQsmZ%Oe&jnSg7ot%w>y`iO_8MQ(yRyt7;2?|;3Dm|hLuKDC>o>)4^f z^`4CIxFQgkF}d79ODIH@rEdgUTv5;W6Olvprfteh=9v3!_qwLokh|2hT%XQ)TM59EnC*oB`{dKIRqC%m+fsS+8|1Y#dqd3jmy&GdoiZ&0dX*ZL`a={hZj>;ruW=sT#FM@&P{AreCYm z2hknAJ1u=Ym*}zb@chrxFWiUm61S4>OBD6cRihPrQa)3YQ`Z$%K|$~d$}Oib9x zX{3*fk%~P>WCUgGhB?~U5~$OIaa6|fMNUYkszche8hJXdY-@MY1}D!*S>9UJPtiCe z!xRF6{jOIXngO`!*pp|y{ED-%cj{N_bS`53HLB5#Vm)XIXHw}gmOaov-Gzc6^d@C?dwM2-vzA)-yO`xilUu<<=8ozBL{k|Z6(^vibCI05u=*D=&pH;g20a$^ifQ zR_8^&sn?fJc@|ZpNO@M?IXl{pZqACYQ?3Pzitr4aW}P#A!4va;##-Wdd~io8wtC%00c-OO3`wD5|#F^}I1)W`{%)w^$XsQ9=xM5C-PQ+;U= z;8bkQl)u1G-gjO1+{;1UzL%%;P&^3dK;y}9FM{i4s*#P=w#UX8^4O&cY;iR;t5BAP zBc!(nx0p@N>X&Hgp{=&uo5yFIWTza3L$t(P+yiT`#?{{}9Pb+~vSlk>)X8l@C41qLu6{;)FkJuHh z8AS}v_$?_{3Y+w2769!qj^ZNL(dhY z%xvrc(w`vB6&Xn+h{gl;EEV%yW9izS*P(g9a%4|x54w8E5rE|=O?&cf<1yUJXa=`0#m>knLdOk9iohUePm0wfqd{I8FhoX^*ZV-y`Oue zhjS!Gz^)FoTK(W|J=ohB-Uj*s8nX^3oB#?w#$;2D0{Iwzx*DJ{3WnE?=0pcgIG2|; z0zYX&Q6AVzF^njG#~tT zJm6i~AtwpFH)&t=$X5d^wH(SiKdIj*ZfYS)hA0x4AIIB6<;#gF^Rnwm_*_wc#>n{H zOuqr4+!5UKM^QPL`mpkDg{v=RN}#zKyQ~3OWz|=C6R(jawpL;XI1tC6ypb-fT$G=S zDKt^1L^1Del#V&B%lucAVVVc^2PNnuwQ^6CsE2DGlnC)SC^_u!`*nYHTMsNZZ1H<@ za0T!ZohLs6u7t;x8xL0g?naV9oUM=;S?9a7kwA`aViL=rw-Y_58J!-|WQM6JDt1FV zBPs7gAZ4BJ_)-ilrq3 znsU|7tn;n-1(eOsH~E?{QvQrXbUS^+7?E?e9X9LnXI5S~k!M*wa2erAS_HAS8&M?B zZgjq3L*-9VZ8>#~ZQuENY8fIA97E~Nsa;ejLYgjbFHSsvi<2K4GrcK8rPP* z{2Dmsbyk0&U)0L1d`|kEC<~BgY;L=eA=lHI;TNzg8g3GVVujFy0&Oa#(Fl9g$&Nrl z+`IFiHMr<~|K0ASW5}6bzvc^C=q(DpB__N&)Vb@o+0ix)=3=-lbkHPH<=Q5CZTb$( z_mWTF)bD$D7uhW#vnc?I=&vx2`U`zRT{H1e%UCSPt!1_!O%@NS5PdM-U5wJw2Mb~% zB`braV(lo%XaS~BZx|EdYYG>F=>`Tf%wOpk8pST|AF9sBvC9@61Kki@H$tAs>$o7Y zWoPBhvW11DnEOeXW2YvL#rg8XvOR!sT;NPjfaH#SN6bP@Tn&ej7)>80^AVLXqD8Lt z6T;o*=jc$~;k>Ph@UHPGlITi5sda^)#Fo6Z{@kiyyaNMlq}qy9V|zhtL7VB=ou9OQ zfuFQ;uAj7Wwx6^zYwdU5YVFxn+cUs<`2mpN_^MC81SOB*5(ursx(H1m>^0a0y)44C z$D-!Q0D(h`SdYhazA7=G*r!D@R?D?M2ZK2GO?NEHnkI-4%~U!lf|Km7QXvX_qoP?rAI;%g0RA8sB+pa*4Fe-)5;z2U~Esvf;xB`n7wm{?MbCSZq{!jT;*pElhhfWhAqs`Tf`U1cv zcp?tTKpZLJ(9IS`Lc|>b28O7QF$bNmfS+1k_7)7VzSkVq7t~lU)qBVkStC+4+(pQd z$5=`D$RS?6aGuI40DE@U?W@jXy|e~hAoJ_JlPyj{Wgodj@$^SC^Y~ZN=NFH!zg2TZr9_?{#A0cC7G{aZ<@Q8qwmBXD0B0Q#ufh>R=mbsFRBRtX#ZUtoFppq> zQZi?b9QusQI*l8+JwuP-;?W8CF{j<*o15rDa3prZIGr*-<44A6zJgy9A<*fi+l_mA zmw3n#&!wIR2%6?wm?NKv{qYI*yyG(BB@m`#7&iKl2pF!)XKF6Yfq+Gj)8-cXvj;&U|+#_v}qT<#N=$5HT$6+hS=qH{xIfcy{mj zd!veiHVDmaWX^*pPEUS0nIC-&cWzp?;I6#?0Fg>O^Wr2Dm6^ep2nE$4#6iCBB_fQe z9CDY-+eyu9lrZKIQ^O*oj|l?0y&))*bY1Pu>Ng&sgk=jXHMPQ;)f<00dh7>vmWQ|G(9nVFF{@;>Qu%`F7i1=TKlT}?S5+7}y~z8> zJdxgiudb7mYyEw;nEVPaHRhAi#Abg8o9N>`huH+;K*;UHr-&goQY$?D>z$!i^=%{-4@_ne zX*pX$9WKPqFijawor1eJ;*1`<)0QAsKY8apRZqNZI%kBW<<1SYg92{IEHN`Bqnn!s zkU(ff<`iqWV|H_CGsu%30_c0|!R>;5Rabvq;0c0)$#%X>k%8zM7{dJpbE36%7(7v2(@y+fY=#+L)PSs*9$omV4+)(E;b0*y7Bd*Mtog}#Q2eS5(ytdXQyy| zWoHO`;2LOt135VwVQ8Z!HIJ@UvLMy{t4M7U;$x@A&ONVjWII7(YC+A`d9J0?LQb~W zKqx$Fo!p+y1^|=9RIqFq$jS!U9^he4rkP$H?WsB&NRygW%s5HjA!pgm_@ICuCC7A> z`q@c7j)?UKLn230yu8s*=*Ad&Kes#7pA#yaPKG1rqS!UQMhtHAlj>L2pI6kMkw1m% zTdjT-XA)34V+L6pcfK4o5H`Vx25!Sw*VSI(C)KuC?UwgjZA(;xO0=7zue0kyvwkuj zt_+Ij_xZ{1d;O#l&T2QScR}D#4>&edMz6<^t*fFDFpQKLt#>%Cb}_()pmcXxz^iyl zGJO%^T^(07fj}QQ?*i-tR9X^cpv>M%^V;R%sDQF|wL4$(k?r~8mIu85VViB#!Fzsu zA%5(|8IU*GkK!C#?T^g3XYPt z$>k-W;*AI1GC7q<6yEV{|i4cnZFflpL1a5 zdTDmjff1D5X6Li<^w5p5#!bcHFqyBH0fAx;wvGfGqU^9N@7xqsx>Sku1x(HH!?K@I z@5E1)cRmxPupM1v;Aeoo+EP*U$X5DeakEBbZRK#n(6@j`gUhl?l>a|h4ba2xqQiN+e z!Pi(d!2sxz-lpOWId?H_bz*#KUZ0}#`YdQ75)ahWVdugU+5`K?cF8qj6b`@U4sXht z4;9C2c87|iX+Sk5R16%bZo{eKG~(Cj@&Q;Y_+WZQ`QQq86aYyvB(gBOaj%n8Nh z9rc)QU`*VI^htTehR!GB*KMCjzdjM;odR;*_mBjGG4%!oua8$Te)$3Htn=}@bj*_{ zt!n&80`fxr~T)rgL<7i~Yx-7-TctG)$4jJ?omX zE0*DPI&?c9@#nDIhvOx)5a;BW!Z;|$d^k%iuH@8YOQTV(jAvtfOP;+B-@;Es+Mk%z zC5h9GD!Bc}`+J$#kar7MAB}3QqMmQCn+xRI8;oQPV{Rwwh25hma#^AMO|6IgOum=4 zr?_Ya%ZVghyjmjr%xRqc9Ss_Ov%lyUZ?EW}cTcG`64>7CPI(oLdl^wEm~KFjjDNg! zY*%59s?}qNcncH>i&F<_M2a(Tj0%cIr|M!#ptN(1MDz#?Pgw%z`jvw0XpMM1%`QK= zp5|UZxt``eWSHuqkp0SMoQIyZj)OQXyMV9N4R`bM6+T3>-AVfAHH}xtFLho8L;<5#v=njZ7ppR90)V_-S+ae*df4{RqL|=jWLDAzWxM@}L9lt-y%mcs?0!T zqv8>~zb@SjHLT8gZk!S!<2=uuWZc{~s3Yr-g9{*3EhXkSxhL9e7jo4!|IkWQ&|1s8 z3y9~0TP)BHq8=WM3G_p`tYznJlW}(*w)uSTu~@Qh8n+hin+E1D%RS>GD7M6##N^`B z*&V$yE`fn;aPsi4kwzV3JA!1S81dbXIZ30vWy6^YcBvzUrol9V+ zNC~=upTZOFi;!e2{_=|~-Fp2y?bxULHSnWn9T^Z8z|_AyYcUWXa-SsoAR*Zir~7SE z>5s0BC<(<%y_A)6pFDy0(?ieR#706{5l4zgyfuscGR3JT48SDxT7=HW(Tz3`F}=6#i0}#f=Wp+1io}EJa08qJlMm+xussO{vkIA z4nd^>$EZ2TfTQqcXNx5;#}0xSkYB&$@#fh774WPNmt|Jk+QDF`JTqtV;`>xNGx)l! z{5QUaB^}D945fkg*+u&-FavD|)rNZd3@EH=?(Qm0)L%#AY23Pkb>_=XIRpQIn|qX#}zZiP^3@lKgPDgs^ zlUFv(Z;RE3XIW$%o^4iNzAJ2&So9E~c3H$;K{Xg}AI0a+S{}d3Z8i2G|;wyoe$wYL~ho^k02G zOgN8_o`5Jkhb0$CkU`G}BN%N5E&f_`Xy#=x#~YAp>T^K13@t;t))+;ng;fU3q4E<2 zu8Kzig8f~t7)Y!F)*>J6@~T$ngEXRr6slx*V=O&XrOyy78 z=l#E}PP}Y~#-;7=_wYNGc{?p{XmfY_iRGW{ClqY4 z&7V%mfyW8h3{_%pj}V)XA=}Yvs~sUPJX~5EI#B~-yUFEac0Mq8a9`~pQjE3xTZ&qW&E5x|_CJs+}eM1V+a(!^TXdqFFOqY30K2&bP!uKXA2F)03Ye#Vp+9Zp^B$S>_wOddVMvHvQV+fQZWYbn ztyJTpZh=-7eAm#XU zo0@*wfr>t~iQy824af~jLZ~F441WsTLX{#Uq>sw0n;qNd!5kb<8~h9dru<)>x79Q!b57vgzmgQ!NoWTn14OEfqD+-{VVTK=#7y<5 zz|HP`jnd0t`0FR%s+HE{au|_lL1*Kw17!WKHfp_Mx0c@W+gf@{w8SXbOGYKy9g?|L zI+sQ{-1u-1yu_i-reU}W$~z6J7QJRCyq&8$-pR=Zgi(?imE78@LS~lwKd<}CdVargIkq4 z8y=5Ef`P&Q_hr5@oxlbdDV>6;)qeN|kJ4xgQj3*0QNBZVJXXFNCum@b@2n_9_3*t$ zvH=f+eX%T(`UH}OOIjSWq{Vyii1m|ime>+kW~B_K&z16KrYBska|<7c6Q2s#8nvX6 z1A|6}#gX649Xd0TKP-ZeQ`hZeLO3CA@n?UdMo&8&iNZ!P~R5 zrvhHqxj4$zv^=1id6Z$9i{_V^d-vra?w9jYdW!|iXA-&_m63ymd-Xv6B-RPBBg$R$ zt}jk3BvMQWB8&`4A^y%io0R^6!stR`9W9^M;g&QtoKTt2=F=MEd_jPb9y_mTx@yJc z(`-D3zoK(tDh6!f^y5>ntr}tSTC-xAkXRH{QvVoeH+LuqW0}2l*v3GiW06=eP+$uW z>h=PG<~?r&5dx}N!%K#3g*%c$;S1+8;Hw*}kqQX)FwT$m(o&{u;2iJ4Ail2w>$1-*@$q~D?XV_-wGx9oLaO8*9uAZP{k47BC7gd;woZZ za(O9ICWVEgmpfhfRYuU!BQ6}X6DhHNQYD{h?V&FyG)DX52WEMHUvFGtMLv>)fQEv! z4(AIDv9Xq7Ar>D?r;XFG(cSk9`+VPZ2fjd_iMe8~X?%^m&E2zkf1}Da;7s76vb$Ro z{e9PQB|>|1cVEqf*E3UBK4mj!toObAI@jSN=!vA5&byro-5q8s(Bk&1$E(;l`eqyY z@>U4M>u&*cShiK}B(zXxLi5?Mo`M`w4g$6xz8Z)eJde%v!`{P5z^w*Y@tiWcvO9X^ zy8Okb0dC{P<@*6saqgLhZlRtQkpb=vOj7wu%ltFjv#Z|*B>usH4ket^M z;_31X2WP(MxOH9q+}VgyvVKf&hj^sdCmR^x;%4p*RKbKbW@;i^P_w%0&Wzt%RWP8r5UfFd5DP9l8x64pQ0pg& zK-%|m=eFQNQ3B`p?m&vkaNNQ)RiE4{d6`CNJ|Hiqj08sPJw1f!FY!yUNz(E19-~pg zdL7CBBC0&#T!Z>9NYL?pZqTn>{p{#Ii4eVh#jIc)P8l=({3O?X7Aq-Uo?5@VkJLB3 z(;=T0$8&k{QrKVp-kd%^$wR%ZEkKTx^G?pE_d$t6ac-PTI>}iz6iSik=)}6AyC2xm zGX`}BT@h;-UCH0iOwGh8j;F?Ibs)Dz2?zT^-pdvE6P(66vpx&ZBHrOsaK>imj8txS z?os+K>zw}JHeTQ(Ccf;P7BWQXcU80VZ$8$Jj=6&nqI3Cw-9M!9DGj*J|FI-)pFzQ- z5!WxD?@PFQqRcslU$Z-#wZqiXsTS58x2aSweMw@0Cj(xecp%aa&jFs;x6!do52Kou#|9T}Qc{cqNM>0#cC7`M(&7VrHBnab-6 zUjG_KjXRa@qIWiW+qG6EceD4j<_D6VDxYk1{yAWFNLLAGcVhrcVae;+yT7dGxN}k( zr&2PFb97@G=bUQviB@N$h@-ux_w`5=gO=0MB_sd5*MoT$kgzuX$=7P~gW7-_FHWpq z*rG5#%ilp}|CrvSlZ*dQ|A=us(;sKJ&i>wS;S%~gzwx%&`CGpwk?(LE#L)TU^v)yr z+uNOISh`j`>f!I^{dsVWr>FJ<2SWV6{XM!d&gGSEp8U*VD*0XbhFPp=cdSz>zaF?gm63y~;;L5o^$o{Fm9jG{b4MQ!x`b%HcwgfZ<&eQYb zeI96gN?kc9Fzhk>L$MZ+QcoUmj|c$Mo)3hg>2{uMy<~4dwMnbgwKS;u7r(peU({XJ zsw3^t{EpDQ;{;Y>0-*}~wAnETk51C6i{eC7(-)Uw4g89Av?417jY4OlvIUhq>l`;j6uC%#ZLsvG-*#zos->0xTa}VghA%#H>N0kjPl_&d~h6lj(PyD zRqX7!jKeerijMo z-^5*-#%nzz#rS(<_ONPpd&Z6I52ODBvIDsO*nX_O)$^7go(Bj~EoFnaz5swOL&=)Hq|d4#>EB!ccm~Ov~bV zpeW8$>yD!$>R8hIc7(d5W;XCX4KdqFp7X~=SCW;z={p@zN!=N2;Q^h^F)AmzZs*S( z!tVGRuwcc%jYQ}(Vo##4Wj+lkAaPNwOLCSQ%E?hkWLhlEbzn1bK6{!Ym_U8`F{s-q zgowwgUqPAdq92}(b=D2>TKO$@Le}~%7|~<>77g_L2FSWZT_66F8Ii?2XgKYgvL+|W zuNiO3Th?Ef(iZUhivD=Ka+e2>>R6!@0WWBzV=&MGW=z~Yi*bgBZglCd9aC!au%#_-x0d@uegw~618dyJlPnC zVVSQ6isWaVbAopxWGY!_s3)Awh+G*%w#6zPwC-{??*f4?LdBM#j2Yl1`))su5Gg%` z&r>;kJ0On4GI{6g-sKbi;Bg(8vH@`&SxJ|m)5|7=4#9)0?LdjMiOcn6;sF5Y zmgsjHa)C`xshQblYz7+k?hJpW9rS>)N0Dw|-Ha2gmWq%;DsUlF%~B`y2ctF0f&NU& zabZFtoj;Y3;Z|yMLD}=Bakd%rXr0Gc?Cva;gUbraK=I_u!1pxp`3$&ow8;Ck6_`5R zHc%2IHQvQiCqs&T0K4s`)qnd)=Wx3XlZVft7L7d6@0Nk8=57_ljx(fz0vGK^Y9=Hc-mw{>)Eulsrz%{ogJlU!z#N`)H^NOqmvCjgrw$_xg)o&4p(7g7 z!LlZZTA`EjEOm%nt zBLeGo);~060)~W>ApJD2&I8Aa9}VnLfKb1BvdS;FI|m6!Ol?FsrpcQZqe=uT4d`o- zCEQLg&QypX-CR}NC_>1`W0`|Gh9Fq9ep|FJ7%Aae7-4gVfFqp)t+>cy7l^dWO&qi< zfR7*(I=Y>6EnB#=4z3XqXt0auRW2}yKxF-LrY{1HRFCTjM82X-{ox42G@9L_4+)DM zL?8a>z`5YV+gZH7E!GG|KtvIoGI4So;c*88>?9;bm3v05h>f~9IIEj2!i`}xq!pBF zg`d&8!9)^AC->(Cy_KF7ixZ~%aW<;I@8uv7*PWU7Z;D zQCg*{qUwz2xhaxyNj3!lw&b#FzR`A*%c^A+G#I6|6F=YPPU?6Vb0ej+xk}n)xhqbu z6HJi;NRQ@nU@!KAW4LD7I}M9zOYSu~Q!WpP=tlS?64oUFi|`aCF{Hrf{SZ62h);ps zF6yoC2vCzvKO#qIaif4A-6)S$RlXF3BU8WNvX?s7K8F~}Cv`Yq5a7kgrJp4{fZ7x0 z5|O2MUut(2&l}y`(CJjdS`-xrq{YMCNeXv(YPXhv6c{uiNiF2{Ao~Hww!lrl(D2~9 zCF3wZNQg;_&5&Je(K=h+XQ(nperB`^?9yP8#Pr5-K@CEh*bP;nmE(a_6;<{Geq(1v zjr$Oj7iUN+621*lHSi!G$q@cqd3s~m9|$t=9HXK&W+&)}vukG+-f$BU8q8#(s@-36 zA1*p!^{%vTp_JnX$l$ZaP%;*xHLcGW?e8r$5v7LJgEG%fD#{Aj<%GQC4EHhvJN<{}tz5i~d2aEi{MkJN2MEx{fe)#`X1P_xZZOV4;6 zAqTpboLHOib+DRvT~OO)Y5r@}2O10I^bU^CT-9yyfA*NJI_$gCq9^Y6VGWyR9(h5AhXa||SA0`4iB!RiXWr>#3JE=_LWd0?dSB+ILViLja_xQ{u1XJ1&57=Zo%!*dT{;+ga5)|VGE zEI5E8Cl+ab>k{7fvvtIL+XN*u2zk_en)Aiyx&FGga~?H&@?Tza^X3e3Xmiy0@9%*IE1(V93LtG*M-KnA_pg3l+Z zT+EsPnoko!n;_X(lJ4cG3kkfG8M;fyZm&&7A~x$5)lVMHlHOn|z zl($0DDOq)w!=LQUI&23U?3^!aS(xpk=%h`I1%&z8Tm?fAVi<@Tn}7~C);KG=D>S@{ z@+j}5;->9%hboN=Po{M3RPBkLISA=e72FL>92B%-axW9BOrn2&6gg3Lv+lC$O)(^L z-JKx*n*nJLE->l0dz64_bTm@kM8Nc9`6_mh%{a}wdvZ&i+bE9$V|+vW#fcjX?pxFc zmv!@!F#h!NzWFav3G4U9|5KHXV9`xp@$z4}M7&Gn`z)NO+A{8i3NOjY(cVRO_P#ty zmt6cbxT&k3d$Gq8A{+e^WHc*wf09{YS@j&e3(IOy4mIaYFE7?IKfH|GjkY@1X5)a2 z7WE}I%I~nW-8Ju}Yak}xx-eg8!uVZy`o^d6ddNGvIc0Nb22PY$U*DdW?@eKO>w6a>={7fWJ!NCpf{7p!*3BJIZ<5*{<vqUQPK9|iP2Kd2g z03!zYJ~F?$1#sXhk)rV9>TlRippEAY#WL6Cw4(=8K{84x0!k&P#+c!SK4gRlgDIX* zMe30ed`T15`v@@r!y5gObywZ;(RW^c^VhcBlO0mGPpk#y-~@B!s;hqRqHm7?Ks}xy zZwQM*NOc=^fD_n~jz@}vc1CNeg8{-B5cNbcWzZ+DPwX-juQBlNT8QEP-@JKr6YtoP z7a7YIwX+^$=s98>awkGVkpj4nwA%6 zc8p$I<(VKSf>|Og^dzMbOJzHN(G;IgB&74Cm?q(>Uj8eFP~ML#WfA}b@&LHHFwU^u zU&wHnS71a2ASfxw#|uXf&lWKrVUvOa{^}m2=NaYOivEbbnqDM;xdZlB9a=uV4^bxV zBdeBm7X!$uO6?{xOYaAOi>v&U^@n9ENl5lWmd)(MAw`$(cks0&C%(fjzcdQHtCR#r zz+sl|#_DpFMiY#1;a{+VD6lgx-@uI>ki3*xogTp^Ox$6aJ2iX|Z|#SxWyxWg$Ed~* z%Q$Ke`|yewfMEpHL(5yBL&yM2NSJH7lN`ld&juFC@3ft*cr`Gj+N;*iFtlxxm8Wp3gwzF)Yrj?5d5N55U z#%knt+bXxXa1O{k;fgcukvYkK(Zw(=+g|#$s4BT>^MH)2zfa!mRpHaHUoKT^0(=8K zqK&>x7L-Qy!dZ4???3CbC+fj=r7+bl8W<`}eG*J?YBU|ir@1NK*S$6D&Cbv{xC?jL z$w(&bX?Xw1oB29=O8ny6vQsv1M&0H-e=5DU4`~71TxqWGt4s4{P#QZ?N84zk)jC>o zx;u(;wGs^m=Mz#&HADb_T|oFhguLy!5RqK0JnKJ z|2vlBk3X(`*<8zOLN6L>rrqqg=IQG)D5{%vvvrR>r{8)}xAlU4YaL|s{LA4gkD4ht z&IQ4Z##Z|*oZv;(zt7?z+IZEv17Ca^wOn!WzcbD{8?~9T84Hjt;cm;t*B}pU^p%%i z#RTAfp*}tDS1iM^#Rqih$7sJ@-c$65FaQ#{d%OG|Lwr2dvm=-HymzmgKQ4>^?fm%P zGn_MeXhef2fBuhb_nh9%Uo(90_h3KYMzwkHP0(fb6zYN(yYVYZRyX@#fAsJ99DOD| zspiH#IgJSxOU7eBD7O?7Z*AmbYC#~c<$x5_+`gh7(QH7$tFo-m3?oNrKlBzasqV~_ zpHd5AHFac#=&A*fp$0R^i6^>;ZsqO>7q!{~S^rWC;|`f~QOGk};2Z1MjS3bvJBx>9 zi>0nk&w~Y!f?N*z!xQ5#tXKBsU@b)Rc-U@S;n(z(Ak>TE^+e9aVBH|-Phm^C+Id0T zH3D_v8o*nSPoamPLX3rWZ$PF7g~5vJ1wEj)xsBzinj>R}Q^9M2P+U*QlPb<3hWhFi zQFLUvIri|ItUUq;K`E=PF}KvTBWK5mzWQ7&&!4bP` zobKPpp%d}HZ%DoC(s%v>-r&WbKQq!m&ZA)!g2sc0c(nZNxV)vy_`=p>9lK@-Q&o&) zT%CmtoH902|4#xP@pP0~aG1$vDQ_N+!VXw^9^SFlOjCJg&RiyD!tfb_?tnBSLnIux z2$n~bt*aTqFh#~`NRJtLOh11j--xTqkCn))>)zWekER#2pa2?duBHHW_nyJ$Qa-t2 z7%V1?Ju{p%V-Zdq7gI^OqTHUt2^n{YBuXCHr<-ny^vcT%W1Z4=b=imLsG7j>2G2y7 zt}?zhk^spjevvmuxLB^?s-uxDVPiKS_E?vk^Jlg2{JsXcHC6Bj#ZVa`T-mYfFcJ&8 zB15$jFID46hK{&rP0|{6sa-@jxtG4>GM1H%<9e_~1?-fn1rIoZ?n39=lbHvR?4;8Q zc_xktWM}&o-Tqim%;{&T*|@liMVY1m*x@aa95Ueith0HIh$`Pj+p4&*p^OtUjsuKN zye(%1)j&bH5c7hfk!J&YwV4z}@VhE`0NJQZo4u%hK!zcQb>y1l8|ii86V)!Bq_d** zOC{e=;c&mBDDNz!uAH)kY6tK#GW?Q>Q=t{Yu*y5(YFT*)tS_y-zk%53PXm+U2+945 zSvUt*92KXngMo)N#=zGShaD8}{t22@R$Yu{KF#MnuVeDcD=}hu)Xi39ujKa=mM;Vq z6Q5|vM_B)GEbU#W=s0DG6oN^W-uy7%r1L0fEn1 zSf$mBtGBX-gT`R%H#|KRgRsVj!>hOo@tx{NpVN?MDl1`u*PO8j>SG6bv>!b$59;Sp~YS0z`!z~jQo%4G&vI=~Z(NH+0bBl&m@`G|bYe=@=&93Xd;z|C+= zRo}T8KJx!C_wM0(Rpp`YynNrf&9#!55G1%F%4FNx2kQGptaIsD{Z~C-q51;j<#MXRXD%jJLb36 z3Q(Wtoag*;2+21uV~)!^-tpeYJ6xMQT{RFxzZM;u8{%Pux9!vkG3SRHhEqFn__aUk zzJLQFn``GXRb;-CpS&q>Z=5-+!%mwW=?Zv*QtCCVn+mtrACAlve2V$2DF>*6)j(w6 zPpGzSIipDRZlOhw!YBb=w5cwm1#@ zihbYCTnJK=XU-00Y>~EwBlV*2TmZnRbu*8phFsq5vPqX;$A$$4jJc`^p<$NC6bApJ zk7qmTQ5T;UL$O%z91?8f@ek8;&~*%I)XESzt5CI|dXl+3ScW$v;_@w!K%t|vWKl>M zU=pV+2E@2&h>w<8G_AaxH5IvZ7{5U1r;p%6a9+1+%rKf9^s`C|)E{U5BftTJB&ve5 zOd(JfZB@3y3^QP;Ov22febt@JK*c%>)EOTzD$f%^Xv(WENGK9w6~K+f8?=W}m?tub zSL{b+S%AzzOD#PIDU1~qR$91XOgiF0g#0ifWCulwpj^=ZV>!*UJIBKmRz-Yu)FV%n7(ZBGUb&sPUD^A z3Qt#G&YrpSj>e$-S$hqy^Y#bv=~+Iw_kJlulezS`4trMBzW@Hxzr3N7LqJK1_O5tv zHlh?)QBX){T03)8kR>!|Q2ZD5{sr~&*A_7kT5o&zk`8d4I?&{-WTn2c`oLJxONR#| zxl7_ZwZUUvSnbT=%C_Jn58UHf{e_7Fc+M4DlJt|JDckq#jdYm3`g5M@8+@OhyYNSU ztcIkk0I3tA6vfUt2X&sb_zH0KiWz)GB#NORsar}`6kT1PO-VL+YLgJw06iQ=fv$}G z&28VHBT6a@FpYc`mUW(B!rhj{#Aqytq4Famr0!#|GY!Yj!R)QucS$z{dar%ul|;X% zzD+|vDmAiEry^}tbSYY%YHJK8zyXh*JsP6DPU6l&t}t!FYeCkt3u|#8}oOdXE$rSP`|k!+vwtmDmzLN8Sfv{1O;XM2Z~aB7nB9d31dXZpC40bWr1%}dJh^Qsv{s#o z1zle`mZr8y#jF4(U`3)6^;-SQr`jpB$%%jy(R& zLJkLT6uWt#`71Dxppitbt0!dvsXTU(PjR$%mggu4lpeD*-3&4smdQNKk}!d4h0ZEk zrq&u>e8)uf!%la+1=g0!23kUqdf0Ml|Cj=+?2Ql=FVSK5OJ82kRskmNm;%ct#l4z4 zp(KH@*rJ%_k5kIly+0|+%|fCBjF%In@`>5VX~q)i0|X_%)6aDyrzg%+ z?|1E{?iU=|uAueQVF48mykU%p!)SM5cqrN*1v)&H>Phg9^ zqxRnliK5D|8ON`gR)c^K1kH*O(pgAru`? zRw~)?|Ksx4;~{Es5z3*!^5C(QUK`TuB9adA8niR`R@;0)Z<;au^nV-4uK5Zb7`aJT zM?*G$vgpl}9tYXP{meEVj&IwAK^b=fa++3G4YVw!Yhl9BP#aD}hN_dKvA0)$8=8qp|H*p0v_gq=8AKY zfHfVqh39KqK!Quf?1#o&(dv~YV*n!p=pmHlsn48Y%^Q{icAl=-2zh!lsy7S=S2L9) z3n?rBj4?}`0bSS_AbcgvF&PzL@ya9-jKI#83AgAl7EAOmY&XV63it)z5PN|RdzxX} zj2JU={lN*l(P87rnu~u+kNBd~p`q);ZK4H=EF5m<}SH6BjJntKRM_f_9$A zsA+E8=CtTSa}njcC2u$o!wB18PVfX;lbRTI)pn+R>z6XBAZp@uA+Qi}pyPr}GHnJx z@CM1w>7cft_^9EdZ+yj%8b2a2KbM@kUVlR!3%>^P7DiviL?S(9HxSiUAK`WHphW$* z1a742$Bjx;N@}zsB>W4qV=bVdESS8K!r3oq=HvJiU%Lm~tp5Uo%1k+*4N#CsM{WjG zfImXayl}wI8(oi-Iheql^WFkdcGIckVF)9F9h%ToeGVN!J40{*mlUR$9-gAp_YmEP zh2s6q7Y_(;TbMNMa{D7*IDm)9y##n5Zl{|O`7){x( z2zy+3X~QNd2Q24e@dFWvSN8x6AiFVEYDpf1i|c?#B7X&k*yIR_kbp&!2aLz2Cpk2M zA5Io!)IvRA>bMg^%P}4V)5yX#@i3Tt2vEd#mq;K~hx6oA!p_G0+EDw-q?v?4ZpBm< zhOk&f4{bBbKnXuzBK#~)LVInhBG5Od4)Io)O2lZYqxP{vLu(5P7DHQtByk1@!2Eo9 z=+aCJ6FOZV#L_3+?}bhHy9dQGh%dA@D6O|h2JNLr>DX!?^d-G2lgA}u&xqpBFi)tu z^{08JTDw-Fyf}?c5ES4CP>QC4y@jB_bp9YTLh%W962J>G$2}SgG?O=y53JhT22%`| z^@S-`IC5o_PPZNip#ZC<P177v`SxZO-G*;nH zQVo8^AkhhdFL0%V@}M({yN=D5$;k4Ld6DlfF2ySv9*gY zSp+34-aXy@b08_H*bn()Y)P4Cu~X|oU+~Rdh}PKNy`)+R9}DF7iuvrhF#*Lh8*YEz zf2f~9H^r6ST)CHqG-x!%v%EjIE5Rt2mPr1J>r^73g5Wn(dKxnAYsOAX9#b%O95WP; z0WT`IJ*lt6i!9JET`8T?~uQ5g#m?*Cu#1_ZkkjDHr)AFfn_`y{jR z!TF6>-%u^%s)ZoeKZen7tDe-UH()o$F5sJiI!Mokq{mgcaMep!tkde3k{fYD=S591 zjfgXPB4L9!MYK*+@T(JBGrjZOGc)+gv;dF`dhOT$8p@O*YqYyr3&e?%mQCdESFgzF z=Hj0%lRy6H%$J{1oO)o()$huG{jPgXKXw0sEhqindGDRO{Eu$s^4u*~FFW_PzxL@R zzxJ(i<)=RxPtWzgkMeX>)t1X&ee63w`u=xQ(R1@x%$`5?HOt-p^5?$ktB=n%b9v_a zm#=x;iRD2qv-t0Or|y4C_0@jayEyNhj1atw#gGpYOU51^oahl5*KhB;^A(r(l(7Ky zqBr=8Zkg@5mt~6Cl?{?V-`hN@{Z?mn%RNuN@BaB?_icV*P{8ipUAqtPvfqB>^PjyR zOR~blJ3sp22TG$(sf1Mta`(4fbn