diff --git a/.github/workflows/test-modeling-commons.yml b/.github/workflows/test-modeling-commons.yml index 5da47a3f..bb6dd23f 100644 --- a/.github/workflows/test-modeling-commons.yml +++ b/.github/workflows/test-modeling-commons.yml @@ -154,6 +154,7 @@ jobs: deploy-staging: needs: test + if: github.ref == 'refs/heads/staging/modeling-commons' uses: ./.github/workflows/build-and-push-modeling-commons.yml with: environment: modeling-commons-staging \ No newline at end of file diff --git a/.gitignore b/.gitignore index d0f5807f..3ef3694c 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,6 @@ GITIGNORE_*/**/* .env.development .env.production -apps/modeling-commons-backend/prisma/archive-output -apps/modeling-commons-backend/prisma/avatars +apps/modeling-commons-backend/prisma/legacy-migration/output +apps/modeling-commons-backend/prisma/legacy-migration/avatars .nuxt diff --git a/apps/modeling-commons-backend/doc/legacy-migration-discussion-archive-plan.md b/apps/modeling-commons-backend/doc/legacy-migration-discussion-archive-plan.md index 4bd263b4..55d3eed7 100644 --- a/apps/modeling-commons-backend/doc/legacy-migration-discussion-archive-plan.md +++ b/apps/modeling-commons-backend/doc/legacy-migration-discussion-archive-plan.md @@ -106,7 +106,7 @@ src/modules/legacy-discussion/ Deliberately minimal: - **No `domain/`.** This module has no domain logic — the data is frozen. The mapper handles the tombstone projection. -- **No `.service.ts`.** No writes from the request path. The bulk importer lives in `prisma/archive.ts` (see §6) and is the only writer. +- **No `.service.ts`.** No writes from the request path. The bulk importer lives in `prisma/legacy-migration/initial-import.ts` (see §6) and is the only writer. - **No `patches/`.** Same reason. - **One query** (`list-legacy-postings`) is enough; deep-link `get-legacy-posting` is in Open Questions. @@ -184,7 +184,7 @@ Notes: - **No POST / PATCH** anywhere. Surface-area discipline: the archive is data, not a feature. - The list route piggybacks on `resolveModel('read')` instead of layering its own visibility logic. If you can't see the model, you can't see its archive. Anonymous viewers can read archives on public/unlisted models, same as they can read the model itself. -## 7. Importer (extends `prisma/archive.ts`) +## 7. Importer (extends `prisma/legacy-migration/initial-import.ts`) The bulk import is a new step in the existing seed script, called from `main()` after `migrateNodes` so `modelIdMap` and `userIdMap` are in scope: @@ -293,7 +293,7 @@ Idempotency: - Re-running the seed picks up new legacy rows (none expected — legacy DB is frozen — but the script supports it). Existing rows are skipped via the `legacyId` probe in pass 1; pass 2's update is no-op-safe (same parent uuid). - `WIPE_TARGET=true` already truncates the right cascade; add `"LegacyModelPosting"` to the truncate list in `wipeTarget`. -Report counters to add to the existing `report` object in `archive.ts`: +Report counters to add to the existing `report` object in `initial-import.ts`: ```ts legacyPostings: { @@ -371,7 +371,7 @@ Awilix auto-loads by filename. No service to register. ### Importer -- **`prisma/archive.legacy-postings.spec.ts`** (heavy; gated behind an integration flag because it touches the legacy DB) +- **`prisma/legacy-migration/legacy-postings.spec.ts`** (heavy; gated behind an integration flag because it touches the legacy DB) - Seed a small `postings` fixture in a test legacy DB; run the import step; assert row counts, parent links, tombstone bodies, orphan-skip behavior. - Re-run the import; assert `skipped_existing` increments and no duplicates appear. @@ -400,13 +400,13 @@ Awilix auto-loads by filename. No service to register. ## 13. Sequencing - **No dependency on `[[legacy-migration-discussion-plan]] / model-comment` landing first.** This module is independent. -- **Does depend on `prisma/archive.ts` Users/Models import** for the `userIdMap` / `modelIdMap`. Already in place — postings just get a new step downstream of those. +- **Does depend on `prisma/legacy-migration/initial-import.ts` Users/Models import** for the `userIdMap` / `modelIdMap`. Already in place — postings just get a new step downstream of those. - Land order, if both this plan and `model-comment` are picked up: either order is fine; they don't touch each other. ## 14. References - Legacy schema: `/Users/pas6148/Documents/netlogo/modelingcommons/db/schema.rb` (lines 240–259 — `postings` table). - Legacy model: `/Users/pas6148/Documents/netlogo/modelingcommons/app/models/posting.rb`. -- Existing importer: `apps/modeling-commons-backend/prisma/archive.ts` (extends in §7). +- Existing importer: `apps/modeling-commons-backend/prisma/legacy-migration/initial-import.ts` (extends in §7). - Mirror module shape: `src/modules/model-author/` (smallest existing module skeleton). - Cross-link: [[legacy-migration-discussion-plan]] (the active comment system). diff --git a/apps/modeling-commons-backend/generated/prisma/edge.js b/apps/modeling-commons-backend/generated/prisma/edge.js index 0c816b6b..a96d6d99 100644 --- a/apps/modeling-commons-backend/generated/prisma/edge.js +++ b/apps/modeling-commons-backend/generated/prisma/edge.js @@ -229,6 +229,18 @@ exports.Prisma.ModelAuthorScalarFieldEnum = { modelId: 'modelId', userId: 'userId', role: 'role', + collaboratorType: 'collaboratorType', + createdAt: 'createdAt' +}; + +exports.Prisma.NonMemberContributorScalarFieldEnum = { + id: 'id', + legacyId: 'legacyId', + modelId: 'modelId', + email: 'email', + name: 'name', + collaboratorType: 'collaboratorType', + addedByUserId: 'addedByUserId', createdAt: 'createdAt' }; @@ -365,6 +377,7 @@ exports.Prisma.ModelName = { ModelAdditionalFile: 'ModelAdditionalFile', Tag: 'Tag', ModelAuthor: 'ModelAuthor', + NonMemberContributor: 'NonMemberContributor', ModelPermission: 'ModelPermission', ModelLike: 'ModelLike', ModelInteraction: 'ModelInteraction', @@ -379,14 +392,14 @@ const config = { "clientVersion": "7.8.0", "engineVersion": "3c6e192761c0362d496ed980de936e2f3cebcd3a", "activeProvider": "postgresql", - "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\n// Enums\n\nenum ModelVisibility {\n public\n private\n unlisted\n}\n\nenum SystemRole {\n admin\n moderator\n user\n}\n\nenum UserKind {\n student\n teacher\n researcher\n other\n}\n\nenum AuthorRole {\n owner\n contributor\n}\n\nenum PermissionLevel {\n read\n write\n admin\n}\n\nenum ModelInteractionKind {\n view\n run\n download\n share\n}\n\nenum ModelFileKind {\n model\n additional\n}\n\n// Better Auth core tables\n\nmodel User {\n id String @id @default(uuid())\n name String?\n email String? @unique\n emailVerified Boolean @default(false)\n image String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n // Extended fields\n systemRole SystemRole @default(user)\n userKind UserKind @default(other)\n isProfilePublic Boolean @default(false)\n deletedAt DateTime?\n\n // User profile fields\n bio String?\n country String?\n socialLinks Json? // e.g. [{ platform: 'twitter', url: '...' }]\n dob DateTime? @db.Date\n affiliation String?\n\n // Better Auth relations\n accounts Account[]\n sessions Session[]\n verifications Verification[]\n\n // Domain relations\n authoredModels ModelAuthor[]\n grantedPermissions ModelPermission[]\n events Event[]\n modelLikes ModelLike[]\n modelInteractions ModelInteraction[]\n modelDrafts ModelDraft[]\n\n // Better Auth Admin plugin\n role String?\n banned Boolean?\n banReason String?\n banExpires DateTime? @db.Timestamptz(3)\n\n // Application behavior\n onboardedAt DateTime? @db.Timestamptz(3)\n legacyId Int? @unique\n\n // Passkey relations\n passkeys Passkey[]\n}\n\nmodel Account {\n id String @id @default(uuid())\n userId String\n accountId String\n providerId String\n accessToken String?\n refreshToken String?\n accessTokenExpiresAt DateTime? @db.Timestamptz(3)\n refreshTokenExpiresAt DateTime? @db.Timestamptz(3)\n scope String?\n idToken String?\n password String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId])\n}\n\nmodel Session {\n id String @id @default(uuid())\n userId String\n expiresAt DateTime\n token String @unique\n ipAddress String?\n userAgent String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Better Auth Admin plugin fields\n impersonatedBy String?\n\n @@index([userId])\n}\n\nmodel Verification {\n id String @id @default(uuid())\n identifier String\n value String\n expiresAt DateTime\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n updatedAt DateTime? @updatedAt @db.Timestamptz(3)\n\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n userId String?\n\n @@index([userId])\n}\n\nmodel Passkey {\n id String @id @default(uuid())\n name String?\n publicKey String\n userId String\n credentialID String\n counter Int\n deviceType String\n backedUp Boolean\n transports String?\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n aaguid String?\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\n// Domain models\n\nmodel Model {\n id String @id @default(uuid())\n legacyId Int? @unique\n latestVersionNumber Int?\n parentModelId String?\n parentVersionNumber Int?\n visibility ModelVisibility @default(public)\n isEndorsed Boolean @default(false)\n isLibraryModel Boolean @default(false)\n viewCount Int @default(0)\n runCount Int @default(0)\n downloadCount Int @default(0)\n shareCount Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n deletedAt DateTime?\n\n latestVersion ModelVersion? @relation(\"LatestVersion\", fields: [id, latestVersionNumber], references: [modelId, versionNumber])\n parentModel Model? @relation(\"ModelParent\", fields: [parentModelId], references: [id])\n childModels Model[] @relation(\"ModelParent\")\n parentVersion ModelVersion? @relation(\"ParentVersion\", fields: [parentModelId, parentVersionNumber], references: [modelId, versionNumber])\n\n versions ModelVersion[] @relation(\"ModelVersions\")\n authors ModelAuthor[]\n permissions ModelPermission[]\n additionalFiles ModelAdditionalFile[]\n likes ModelLike[]\n interactions ModelInteraction[]\n drafts ModelDraft[]\n\n @@unique([id, latestVersionNumber])\n @@index([parentModelId])\n @@index([parentModelId, parentVersionNumber])\n @@index([viewCount])\n @@index([runCount])\n @@index([downloadCount])\n}\n\nmodel ModelVersion {\n modelId String\n versionNumber Int\n title String\n description String?\n changeSummary String?\n previewImageFileKey String?\n netlogoFileKey String\n netlogoVersion String?\n infoTab String?\n createdAt DateTime @default(now())\n finalizedAt DateTime?\n\n model Model @relation(\"ModelVersions\", fields: [modelId], references: [id], onDelete: Cascade)\n\n // Reverse relations\n latestOfModel Model? @relation(\"LatestVersion\")\n parentOfModels Model[] @relation(\"ParentVersion\")\n\n tags ModelVersionTag[]\n taggedAdditionalFiles ModelAdditionalFile[]\n\n @@id([modelId, versionNumber])\n @@index([modelId])\n}\n\nmodel ModelVersionTag {\n modelId String\n versionNumber Int\n tagId String\n createdAt DateTime @default(now())\n\n modelVersion ModelVersion @relation(fields: [modelId, versionNumber], references: [modelId, versionNumber], onDelete: Cascade)\n tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)\n\n @@id([modelId, versionNumber, tagId])\n @@index([tagId])\n}\n\nmodel ModelAdditionalFile {\n id String @id @default(uuid())\n modelId String\n taggedVersionNumber Int\n fileKey String\n kind ModelFileKind @default(additional)\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n taggedVersion ModelVersion @relation(fields: [modelId, taggedVersionNumber], references: [modelId, versionNumber])\n\n @@index([modelId])\n @@index([modelId, taggedVersionNumber])\n}\n\nmodel Tag {\n id String @id @default(uuid())\n legacyId Int? @unique\n name String @unique\n displayName String?\n createdAt DateTime @default(now())\n\n modelVersions ModelVersionTag[]\n}\n\nmodel ModelAuthor {\n modelId String\n userId String\n role AuthorRole\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n}\n\nmodel ModelPermission {\n id String @id @default(uuid())\n modelId String\n granteeUserId String?\n permissionLevel PermissionLevel\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n granteeUser User? @relation(fields: [granteeUserId], references: [id], onDelete: Cascade)\n\n @@unique([modelId, granteeUserId])\n @@index([modelId])\n @@index([granteeUserId])\n}\n\nmodel ModelLike {\n modelId String\n userId String\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n @@index([modelId, createdAt])\n}\n\nmodel ModelInteraction {\n id String @id @default(uuid())\n modelId String\n versionNumber Int?\n kind ModelInteractionKind\n userId String?\n sessionId String?\n ipHash String?\n userAgent String?\n referer String?\n geo Json?\n cookie String?\n\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User? @relation(fields: [userId], references: [id], onDelete: SetNull)\n\n @@index([modelId, kind, createdAt])\n @@index([modelId, kind, userId])\n @@index([userId, createdAt])\n @@index([createdAt])\n}\n\nmodel ModelDraft {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n modelId String?\n model Model? @relation(fields: [modelId], references: [id], onDelete: Cascade)\n\n schemaVersion Int\n data Json\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@index([modelId])\n}\n\nmodel Event {\n id String @id @default(uuid())\n type String\n actorId String\n resourceType String\n resourceId String\n payload Json\n createdAt DateTime @default(now())\n processedAt DateTime?\n\n actor User @relation(fields: [actorId], references: [id])\n\n @@index([actorId])\n @@index([resourceType, resourceId])\n @@index([type])\n @@index([processedAt])\n}\n" + "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\n// Enums\n\nenum ModelVisibility {\n public\n private\n unlisted\n}\n\nenum SystemRole {\n admin\n moderator\n user\n}\n\nenum UserKind {\n student\n teacher\n researcher\n other\n}\n\nenum AuthorRole {\n owner\n contributor\n}\n\nenum PermissionLevel {\n read\n write\n admin\n}\n\nenum ModelInteractionKind {\n view\n run\n download\n share\n}\n\nenum ModelFileKind {\n model\n additional\n}\n\n// Better Auth core tables\n\nmodel User {\n id String @id @default(uuid())\n name String?\n email String? @unique\n emailVerified Boolean @default(false)\n image String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n // Extended fields\n systemRole SystemRole @default(user)\n userKind UserKind @default(other)\n isProfilePublic Boolean @default(false)\n deletedAt DateTime?\n\n // User profile fields\n bio String?\n country String?\n socialLinks Json? // e.g. [{ platform: 'twitter', url: '...' }]\n dob DateTime? @db.Date\n affiliation String?\n\n // Better Auth relations\n accounts Account[]\n sessions Session[]\n verifications Verification[]\n\n // Domain relations\n authoredModels ModelAuthor[]\n grantedPermissions ModelPermission[]\n events Event[]\n modelLikes ModelLike[]\n modelInteractions ModelInteraction[]\n modelDrafts ModelDraft[]\n\n // Better Auth Admin plugin\n role String?\n banned Boolean?\n banReason String?\n banExpires DateTime? @db.Timestamptz(3)\n\n // Application behavior\n onboardedAt DateTime? @db.Timestamptz(3)\n legacyId Int? @unique\n\n // Passkey relations\n passkeys Passkey[]\n}\n\nmodel Account {\n id String @id @default(uuid())\n userId String\n accountId String\n providerId String\n accessToken String?\n refreshToken String?\n accessTokenExpiresAt DateTime? @db.Timestamptz(3)\n refreshTokenExpiresAt DateTime? @db.Timestamptz(3)\n scope String?\n idToken String?\n password String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId])\n}\n\nmodel Session {\n id String @id @default(uuid())\n userId String\n expiresAt DateTime\n token String @unique\n ipAddress String?\n userAgent String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Better Auth Admin plugin fields\n impersonatedBy String?\n\n @@index([userId])\n}\n\nmodel Verification {\n id String @id @default(uuid())\n identifier String\n value String\n expiresAt DateTime\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n updatedAt DateTime? @updatedAt @db.Timestamptz(3)\n\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n userId String?\n\n @@index([userId])\n}\n\nmodel Passkey {\n id String @id @default(uuid())\n name String?\n publicKey String\n userId String\n credentialID String\n counter Int\n deviceType String\n backedUp Boolean\n transports String?\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n aaguid String?\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\n// Domain models\n\nmodel Model {\n id String @id @default(uuid())\n legacyId Int? @unique\n latestVersionNumber Int?\n parentModelId String?\n parentVersionNumber Int?\n visibility ModelVisibility @default(public)\n isEndorsed Boolean @default(false)\n isLibraryModel Boolean @default(false)\n viewCount Int @default(0)\n runCount Int @default(0)\n downloadCount Int @default(0)\n shareCount Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n deletedAt DateTime?\n\n latestVersion ModelVersion? @relation(\"LatestVersion\", fields: [id, latestVersionNumber], references: [modelId, versionNumber])\n parentModel Model? @relation(\"ModelParent\", fields: [parentModelId], references: [id])\n childModels Model[] @relation(\"ModelParent\")\n parentVersion ModelVersion? @relation(\"ParentVersion\", fields: [parentModelId, parentVersionNumber], references: [modelId, versionNumber])\n\n versions ModelVersion[] @relation(\"ModelVersions\")\n authors ModelAuthor[]\n nonMemberContributors NonMemberContributor[]\n permissions ModelPermission[]\n additionalFiles ModelAdditionalFile[]\n likes ModelLike[]\n interactions ModelInteraction[]\n drafts ModelDraft[]\n\n @@unique([id, latestVersionNumber])\n @@index([parentModelId])\n @@index([parentModelId, parentVersionNumber])\n @@index([viewCount])\n @@index([runCount])\n @@index([downloadCount])\n}\n\nmodel ModelVersion {\n modelId String\n versionNumber Int\n title String\n description String?\n changeSummary String?\n previewImageFileKey String?\n netlogoFileKey String\n netlogoVersion String?\n infoTab String?\n createdAt DateTime @default(now())\n finalizedAt DateTime?\n\n model Model @relation(\"ModelVersions\", fields: [modelId], references: [id], onDelete: Cascade)\n\n // Reverse relations\n latestOfModel Model? @relation(\"LatestVersion\")\n parentOfModels Model[] @relation(\"ParentVersion\")\n\n tags ModelVersionTag[]\n taggedAdditionalFiles ModelAdditionalFile[]\n\n @@id([modelId, versionNumber])\n @@index([modelId])\n}\n\nmodel ModelVersionTag {\n modelId String\n versionNumber Int\n tagId String\n createdAt DateTime @default(now())\n\n modelVersion ModelVersion @relation(fields: [modelId, versionNumber], references: [modelId, versionNumber], onDelete: Cascade)\n tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)\n\n @@id([modelId, versionNumber, tagId])\n @@index([tagId])\n}\n\nmodel ModelAdditionalFile {\n id String @id @default(uuid())\n modelId String\n taggedVersionNumber Int\n fileKey String\n kind ModelFileKind @default(additional)\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n taggedVersion ModelVersion @relation(fields: [modelId, taggedVersionNumber], references: [modelId, versionNumber])\n\n @@index([modelId])\n @@index([modelId, taggedVersionNumber])\n}\n\nmodel Tag {\n id String @id @default(uuid())\n legacyId Int? @unique\n name String @unique\n displayName String?\n createdAt DateTime @default(now())\n\n modelVersions ModelVersionTag[]\n}\n\nmodel ModelAuthor {\n modelId String\n userId String\n role AuthorRole\n // Legacy collaborator_types.name, kept for provenance. Nothing reads it.\n collaboratorType String?\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n}\n\n// Legacy non_member_collaborators joined onto non_member_collaborations: people\n// credited on a model who never held an account. Archival only, no business logic\n// reads this table.\nmodel NonMemberContributor {\n id String @id @default(uuid())\n legacyId Int @unique\n modelId String\n email String?\n name String?\n collaboratorType String?\n addedByUserId String?\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n\n @@index([modelId])\n @@index([email])\n}\n\nmodel ModelPermission {\n id String @id @default(uuid())\n modelId String\n granteeUserId String?\n permissionLevel PermissionLevel\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n granteeUser User? @relation(fields: [granteeUserId], references: [id], onDelete: Cascade)\n\n @@unique([modelId, granteeUserId])\n @@index([modelId])\n @@index([granteeUserId])\n}\n\nmodel ModelLike {\n modelId String\n userId String\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n @@index([modelId, createdAt])\n}\n\nmodel ModelInteraction {\n id String @id @default(uuid())\n modelId String\n versionNumber Int?\n kind ModelInteractionKind\n userId String?\n sessionId String?\n ipHash String?\n userAgent String?\n referer String?\n geo Json?\n cookie String?\n\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User? @relation(fields: [userId], references: [id], onDelete: SetNull)\n\n @@index([modelId, kind, createdAt])\n @@index([modelId, kind, userId])\n @@index([userId, createdAt])\n @@index([createdAt])\n}\n\nmodel ModelDraft {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n modelId String?\n model Model? @relation(fields: [modelId], references: [id], onDelete: Cascade)\n\n schemaVersion Int\n data Json\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@index([modelId])\n}\n\nmodel Event {\n id String @id @default(uuid())\n type String\n actorId String\n resourceType String\n resourceId String\n payload Json\n createdAt DateTime @default(now())\n processedAt DateTime?\n\n actor User @relation(fields: [actorId], references: [id])\n\n @@index([actorId])\n @@index([resourceType, resourceId])\n @@index([type])\n @@index([processedAt])\n}\n" } -config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"systemRole\",\"kind\":\"enum\",\"type\":\"SystemRole\"},{\"name\":\"userKind\",\"kind\":\"enum\",\"type\":\"UserKind\"},{\"name\":\"isProfilePublic\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"socialLinks\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"dob\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"affiliation\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accounts\",\"kind\":\"object\",\"type\":\"Account\",\"relationName\":\"AccountToUser\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"verifications\",\"kind\":\"object\",\"type\":\"Verification\",\"relationName\":\"UserToVerification\"},{\"name\":\"authoredModels\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelAuthorToUser\"},{\"name\":\"grantedPermissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelPermissionToUser\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToUser\"},{\"name\":\"modelLikes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelLikeToUser\"},{\"name\":\"modelInteractions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelInteractionToUser\"},{\"name\":\"modelDrafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"role\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banned\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"banReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banExpires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"onboardedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passkeys\",\"kind\":\"object\",\"type\":\"Passkey\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Account\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accountId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"providerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scope\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"idToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AccountToUser\"}],\"dbName\":null},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"},{\"name\":\"impersonatedBy\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Verification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"identifier\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToVerification\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Passkey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"publicKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"credentialID\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"counter\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"deviceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"backedUp\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"transports\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"aaguid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Model\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"latestVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentModelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"parentVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"visibility\",\"kind\":\"enum\",\"type\":\"ModelVisibility\"},{\"name\":\"isEndorsed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isLibraryModel\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"viewCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"runCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"downloadCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"shareCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"latestVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"childModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"parentVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ParentVersion\"},{\"name\":\"versions\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersions\"},{\"name\":\"authors\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"additionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"likes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"interactions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"drafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelToModelDraft\"}],\"dbName\":null},\"ModelVersion\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"changeSummary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"previewImageFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoVersion\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"infoTab\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"finalizedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelVersions\"},{\"name\":\"latestOfModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentOfModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ParentVersion\"},{\"name\":\"tags\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"taggedAdditionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"ModelVersionTag\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"tagId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"tag\",\"kind\":\"object\",\"type\":\"Tag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAdditionalFile\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"taggedVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"fileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelFileKind\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"taggedVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"Tag\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersions\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAuthor\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"AuthorRole\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelAuthorToUser\"}],\"dbName\":null},\"ModelPermission\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"granteeUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissionLevel\",\"kind\":\"enum\",\"type\":\"PermissionLevel\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"granteeUser\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelPermissionToUser\"}],\"dbName\":null},\"ModelLike\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelLikeToUser\"}],\"dbName\":null},\"ModelInteraction\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelInteractionKind\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"referer\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"geo\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"cookie\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelInteractionToUser\"}],\"dbName\":null},\"ModelDraft\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelDraft\"},{\"name\":\"schemaVersion\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"actor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventToUser\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"systemRole\",\"kind\":\"enum\",\"type\":\"SystemRole\"},{\"name\":\"userKind\",\"kind\":\"enum\",\"type\":\"UserKind\"},{\"name\":\"isProfilePublic\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"socialLinks\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"dob\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"affiliation\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accounts\",\"kind\":\"object\",\"type\":\"Account\",\"relationName\":\"AccountToUser\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"verifications\",\"kind\":\"object\",\"type\":\"Verification\",\"relationName\":\"UserToVerification\"},{\"name\":\"authoredModels\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelAuthorToUser\"},{\"name\":\"grantedPermissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelPermissionToUser\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToUser\"},{\"name\":\"modelLikes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelLikeToUser\"},{\"name\":\"modelInteractions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelInteractionToUser\"},{\"name\":\"modelDrafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"role\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banned\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"banReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banExpires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"onboardedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passkeys\",\"kind\":\"object\",\"type\":\"Passkey\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Account\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accountId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"providerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scope\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"idToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AccountToUser\"}],\"dbName\":null},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"},{\"name\":\"impersonatedBy\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Verification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"identifier\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToVerification\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Passkey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"publicKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"credentialID\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"counter\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"deviceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"backedUp\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"transports\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"aaguid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Model\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"latestVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentModelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"parentVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"visibility\",\"kind\":\"enum\",\"type\":\"ModelVisibility\"},{\"name\":\"isEndorsed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isLibraryModel\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"viewCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"runCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"downloadCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"shareCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"latestVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"childModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"parentVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ParentVersion\"},{\"name\":\"versions\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersions\"},{\"name\":\"authors\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"nonMemberContributors\",\"kind\":\"object\",\"type\":\"NonMemberContributor\",\"relationName\":\"ModelToNonMemberContributor\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"additionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"likes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"interactions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"drafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelToModelDraft\"}],\"dbName\":null},\"ModelVersion\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"changeSummary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"previewImageFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoVersion\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"infoTab\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"finalizedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelVersions\"},{\"name\":\"latestOfModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentOfModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ParentVersion\"},{\"name\":\"tags\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"taggedAdditionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"ModelVersionTag\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"tagId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"tag\",\"kind\":\"object\",\"type\":\"Tag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAdditionalFile\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"taggedVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"fileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelFileKind\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"taggedVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"Tag\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersions\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAuthor\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"AuthorRole\"},{\"name\":\"collaboratorType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelAuthorToUser\"}],\"dbName\":null},\"NonMemberContributor\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"collaboratorType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"addedByUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToNonMemberContributor\"}],\"dbName\":null},\"ModelPermission\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"granteeUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissionLevel\",\"kind\":\"enum\",\"type\":\"PermissionLevel\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"granteeUser\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelPermissionToUser\"}],\"dbName\":null},\"ModelLike\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelLikeToUser\"}],\"dbName\":null},\"ModelInteraction\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelInteractionKind\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"referer\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"geo\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"cookie\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelInteractionToUser\"}],\"dbName\":null},\"ModelDraft\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelDraft\"},{\"name\":\"schemaVersion\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"actor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventToUser\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") defineDmmfProperty(exports.Prisma, config.runtimeDataModel) config.parameterizationSchema = { - strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"accounts\",\"sessions\",\"verifications\",\"model\",\"latestOfModel\",\"parentOfModels\",\"modelVersion\",\"modelVersions\",\"_count\",\"tag\",\"tags\",\"taggedVersion\",\"taggedAdditionalFiles\",\"latestVersion\",\"parentModel\",\"childModels\",\"parentVersion\",\"versions\",\"authors\",\"granteeUser\",\"permissions\",\"additionalFiles\",\"likes\",\"interactions\",\"drafts\",\"authoredModels\",\"grantedPermissions\",\"actor\",\"events\",\"modelLikes\",\"modelInteractions\",\"modelDrafts\",\"passkeys\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Account.findUnique\",\"Account.findUniqueOrThrow\",\"Account.findFirst\",\"Account.findFirstOrThrow\",\"Account.findMany\",\"Account.createOne\",\"Account.createMany\",\"Account.createManyAndReturn\",\"Account.updateOne\",\"Account.updateMany\",\"Account.updateManyAndReturn\",\"Account.upsertOne\",\"Account.deleteOne\",\"Account.deleteMany\",\"Account.groupBy\",\"Account.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Verification.findUnique\",\"Verification.findUniqueOrThrow\",\"Verification.findFirst\",\"Verification.findFirstOrThrow\",\"Verification.findMany\",\"Verification.createOne\",\"Verification.createMany\",\"Verification.createManyAndReturn\",\"Verification.updateOne\",\"Verification.updateMany\",\"Verification.updateManyAndReturn\",\"Verification.upsertOne\",\"Verification.deleteOne\",\"Verification.deleteMany\",\"Verification.groupBy\",\"Verification.aggregate\",\"Passkey.findUnique\",\"Passkey.findUniqueOrThrow\",\"Passkey.findFirst\",\"Passkey.findFirstOrThrow\",\"Passkey.findMany\",\"Passkey.createOne\",\"Passkey.createMany\",\"Passkey.createManyAndReturn\",\"Passkey.updateOne\",\"Passkey.updateMany\",\"Passkey.updateManyAndReturn\",\"Passkey.upsertOne\",\"Passkey.deleteOne\",\"Passkey.deleteMany\",\"Passkey.groupBy\",\"Passkey.aggregate\",\"Model.findUnique\",\"Model.findUniqueOrThrow\",\"Model.findFirst\",\"Model.findFirstOrThrow\",\"Model.findMany\",\"Model.createOne\",\"Model.createMany\",\"Model.createManyAndReturn\",\"Model.updateOne\",\"Model.updateMany\",\"Model.updateManyAndReturn\",\"Model.upsertOne\",\"Model.deleteOne\",\"Model.deleteMany\",\"Model.groupBy\",\"Model.aggregate\",\"ModelVersion.findUnique\",\"ModelVersion.findUniqueOrThrow\",\"ModelVersion.findFirst\",\"ModelVersion.findFirstOrThrow\",\"ModelVersion.findMany\",\"ModelVersion.createOne\",\"ModelVersion.createMany\",\"ModelVersion.createManyAndReturn\",\"ModelVersion.updateOne\",\"ModelVersion.updateMany\",\"ModelVersion.updateManyAndReturn\",\"ModelVersion.upsertOne\",\"ModelVersion.deleteOne\",\"ModelVersion.deleteMany\",\"ModelVersion.groupBy\",\"ModelVersion.aggregate\",\"ModelVersionTag.findUnique\",\"ModelVersionTag.findUniqueOrThrow\",\"ModelVersionTag.findFirst\",\"ModelVersionTag.findFirstOrThrow\",\"ModelVersionTag.findMany\",\"ModelVersionTag.createOne\",\"ModelVersionTag.createMany\",\"ModelVersionTag.createManyAndReturn\",\"ModelVersionTag.updateOne\",\"ModelVersionTag.updateMany\",\"ModelVersionTag.updateManyAndReturn\",\"ModelVersionTag.upsertOne\",\"ModelVersionTag.deleteOne\",\"ModelVersionTag.deleteMany\",\"ModelVersionTag.groupBy\",\"ModelVersionTag.aggregate\",\"ModelAdditionalFile.findUnique\",\"ModelAdditionalFile.findUniqueOrThrow\",\"ModelAdditionalFile.findFirst\",\"ModelAdditionalFile.findFirstOrThrow\",\"ModelAdditionalFile.findMany\",\"ModelAdditionalFile.createOne\",\"ModelAdditionalFile.createMany\",\"ModelAdditionalFile.createManyAndReturn\",\"ModelAdditionalFile.updateOne\",\"ModelAdditionalFile.updateMany\",\"ModelAdditionalFile.updateManyAndReturn\",\"ModelAdditionalFile.upsertOne\",\"ModelAdditionalFile.deleteOne\",\"ModelAdditionalFile.deleteMany\",\"ModelAdditionalFile.groupBy\",\"ModelAdditionalFile.aggregate\",\"Tag.findUnique\",\"Tag.findUniqueOrThrow\",\"Tag.findFirst\",\"Tag.findFirstOrThrow\",\"Tag.findMany\",\"Tag.createOne\",\"Tag.createMany\",\"Tag.createManyAndReturn\",\"Tag.updateOne\",\"Tag.updateMany\",\"Tag.updateManyAndReturn\",\"Tag.upsertOne\",\"Tag.deleteOne\",\"Tag.deleteMany\",\"Tag.groupBy\",\"Tag.aggregate\",\"ModelAuthor.findUnique\",\"ModelAuthor.findUniqueOrThrow\",\"ModelAuthor.findFirst\",\"ModelAuthor.findFirstOrThrow\",\"ModelAuthor.findMany\",\"ModelAuthor.createOne\",\"ModelAuthor.createMany\",\"ModelAuthor.createManyAndReturn\",\"ModelAuthor.updateOne\",\"ModelAuthor.updateMany\",\"ModelAuthor.updateManyAndReturn\",\"ModelAuthor.upsertOne\",\"ModelAuthor.deleteOne\",\"ModelAuthor.deleteMany\",\"ModelAuthor.groupBy\",\"ModelAuthor.aggregate\",\"ModelPermission.findUnique\",\"ModelPermission.findUniqueOrThrow\",\"ModelPermission.findFirst\",\"ModelPermission.findFirstOrThrow\",\"ModelPermission.findMany\",\"ModelPermission.createOne\",\"ModelPermission.createMany\",\"ModelPermission.createManyAndReturn\",\"ModelPermission.updateOne\",\"ModelPermission.updateMany\",\"ModelPermission.updateManyAndReturn\",\"ModelPermission.upsertOne\",\"ModelPermission.deleteOne\",\"ModelPermission.deleteMany\",\"ModelPermission.groupBy\",\"ModelPermission.aggregate\",\"ModelLike.findUnique\",\"ModelLike.findUniqueOrThrow\",\"ModelLike.findFirst\",\"ModelLike.findFirstOrThrow\",\"ModelLike.findMany\",\"ModelLike.createOne\",\"ModelLike.createMany\",\"ModelLike.createManyAndReturn\",\"ModelLike.updateOne\",\"ModelLike.updateMany\",\"ModelLike.updateManyAndReturn\",\"ModelLike.upsertOne\",\"ModelLike.deleteOne\",\"ModelLike.deleteMany\",\"ModelLike.groupBy\",\"ModelLike.aggregate\",\"ModelInteraction.findUnique\",\"ModelInteraction.findUniqueOrThrow\",\"ModelInteraction.findFirst\",\"ModelInteraction.findFirstOrThrow\",\"ModelInteraction.findMany\",\"ModelInteraction.createOne\",\"ModelInteraction.createMany\",\"ModelInteraction.createManyAndReturn\",\"ModelInteraction.updateOne\",\"ModelInteraction.updateMany\",\"ModelInteraction.updateManyAndReturn\",\"ModelInteraction.upsertOne\",\"ModelInteraction.deleteOne\",\"ModelInteraction.deleteMany\",\"ModelInteraction.groupBy\",\"ModelInteraction.aggregate\",\"ModelDraft.findUnique\",\"ModelDraft.findUniqueOrThrow\",\"ModelDraft.findFirst\",\"ModelDraft.findFirstOrThrow\",\"ModelDraft.findMany\",\"ModelDraft.createOne\",\"ModelDraft.createMany\",\"ModelDraft.createManyAndReturn\",\"ModelDraft.updateOne\",\"ModelDraft.updateMany\",\"ModelDraft.updateManyAndReturn\",\"ModelDraft.upsertOne\",\"ModelDraft.deleteOne\",\"ModelDraft.deleteMany\",\"ModelDraft.groupBy\",\"ModelDraft.aggregate\",\"Event.findUnique\",\"Event.findUniqueOrThrow\",\"Event.findFirst\",\"Event.findFirstOrThrow\",\"Event.findMany\",\"Event.createOne\",\"Event.createMany\",\"Event.createManyAndReturn\",\"Event.updateOne\",\"Event.updateMany\",\"Event.updateManyAndReturn\",\"Event.upsertOne\",\"Event.deleteOne\",\"Event.deleteMany\",\"Event.groupBy\",\"Event.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"type\",\"actorId\",\"resourceType\",\"resourceId\",\"payload\",\"createdAt\",\"processedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"contains\",\"startsWith\",\"endsWith\",\"userId\",\"modelId\",\"schemaVersion\",\"updatedAt\",\"versionNumber\",\"ModelInteractionKind\",\"kind\",\"sessionId\",\"ipHash\",\"userAgent\",\"referer\",\"geo\",\"cookie\",\"granteeUserId\",\"PermissionLevel\",\"permissionLevel\",\"AuthorRole\",\"role\",\"legacyId\",\"name\",\"displayName\",\"every\",\"some\",\"none\",\"taggedVersionNumber\",\"fileKey\",\"ModelFileKind\",\"tagId\",\"title\",\"description\",\"changeSummary\",\"previewImageFileKey\",\"netlogoFileKey\",\"netlogoVersion\",\"infoTab\",\"finalizedAt\",\"latestVersionNumber\",\"parentModelId\",\"parentVersionNumber\",\"ModelVisibility\",\"visibility\",\"isEndorsed\",\"isLibraryModel\",\"viewCount\",\"runCount\",\"downloadCount\",\"shareCount\",\"deletedAt\",\"publicKey\",\"credentialID\",\"counter\",\"deviceType\",\"backedUp\",\"transports\",\"aaguid\",\"identifier\",\"value\",\"expiresAt\",\"token\",\"ipAddress\",\"impersonatedBy\",\"accountId\",\"providerId\",\"accessToken\",\"refreshToken\",\"accessTokenExpiresAt\",\"refreshTokenExpiresAt\",\"scope\",\"idToken\",\"password\",\"email\",\"emailVerified\",\"image\",\"SystemRole\",\"systemRole\",\"UserKind\",\"userKind\",\"isProfilePublic\",\"bio\",\"country\",\"socialLinks\",\"dob\",\"affiliation\",\"banned\",\"banReason\",\"banExpires\",\"onboardedAt\",\"modelId_userId\",\"modelId_granteeUserId\",\"modelId_versionNumber\",\"modelId_versionNumber_tagId\",\"id_latestVersionNumber\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "jwmXAYACIwQAAMoEACAFAADLBAAgBgAAzAQAIB0AAL4EACAeAAC_BAAgIAAAzQQAICEAAMAEACAiAADBBAAgIwAAwgQAICQAAM4EACCtAgAAxgQAMK4CAAAPABCvAgAAxgQAMLACAQAAAAG2AkAA_wMAIcwCQAD_AwAh2gIBAP4DACHbAgIAAAAB3AIBAP4DACH4AkAAnwQAIY8DAQAAAAGQAyAAngQAIZEDAQD-AwAhkwMAAMcEkwMilQMAAMgElQMilgMgAJ4EACGXAwEA_gMAIZgDAQD-AwAhmQMAAKcEACCaA0AAnwQAIZsDAQD-AwAhnAMgAMkEACGdAwEA_gMAIZ4DQACfBAAhnwNAAJ8EACEBAAAAAQAgEQMAAKAEACCtAgAA0QQAMK4CAAADABCvAgAA0QQAMLACAQD8AwAhtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAhhgMBAPwDACGHAwEA_AMAIYgDAQD-AwAhiQMBAP4DACGKA0AAnwQAIYsDQACfBAAhjAMBAP4DACGNAwEA_gMAIY4DAQD-AwAhCAMAAIAIACCIAwAA0gQAIIkDAADSBAAgigMAANIEACCLAwAA0gQAIIwDAADSBAAgjQMAANIEACCOAwAA0gQAIBEDAACgBAAgrQIAANEEADCuAgAAAwAQrwIAANEEADCwAgEAAAABtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAhhgMBAPwDACGHAwEA_AMAIYgDAQD-AwAhiQMBAP4DACGKA0AAnwQAIYsDQACfBAAhjAMBAP4DACGNAwEA_gMAIY4DAQD-AwAhAwAAAAMAIAEAAAQAMAIAAAUAIA0DAACgBAAgrQIAANAEADCuAgAABwAQrwIAANAEADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIdICAQD-AwAhggNAAP8DACGDAwEA_AMAIYQDAQD-AwAhhQMBAP4DACEEAwAAgAgAINICAADSBAAghAMAANIEACCFAwAA0gQAIA0DAACgBAAgrQIAANAEADCuAgAABwAQrwIAANAEADCwAgEAAAABtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAh0gIBAP4DACGCA0AA_wMAIYMDAQAAAAGEAwEA_gMAIYUDAQD-AwAhAwAAAAcAIAEAAAgAMAIAAAkAIAsDAACpBAAgrQIAAM8EADCuAgAACwAQrwIAAM8EADCwAgEA_AMAIbYCQACfBAAhyQIBAP4DACHMAkAAnwQAIYADAQD8AwAhgQMBAPwDACGCA0AA_wMAIQQDAACACAAgtgIAANIEACDJAgAA0gQAIMwCAADSBAAgCwMAAKkEACCtAgAAzwQAMK4CAAALABCvAgAAzwQAMLACAQAAAAG2AkAAnwQAIckCAQD-AwAhzAJAAJ8EACGAAwEA_AMAIYEDAQD8AwAhggNAAP8DACEDAAAACwAgAQAADAAwAgAADQAgIwQAAMoEACAFAADLBAAgBgAAzAQAIB0AAL4EACAeAAC_BAAgIAAAzQQAICEAAMAEACAiAADBBAAgIwAAwgQAICQAAM4EACCtAgAAxgQAMK4CAAAPABCvAgAAxgQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdoCAQD-AwAh2wICAP0DACHcAgEA_gMAIfgCQACfBAAhjwMBAP4DACGQAyAAngQAIZEDAQD-AwAhkwMAAMcEkwMilQMAAMgElQMilgMgAJ4EACGXAwEA_gMAIZgDAQD-AwAhmQMAAKcEACCaA0AAnwQAIZsDAQD-AwAhnAMgAMkEACGdAwEA_gMAIZ4DQACfBAAhnwNAAJ8EACEBAAAADwAgCQMAAKAEACAHAACoBAAgrQIAAMQEADCuAgAAEQAQrwIAAMQEADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACHaAgAAxQTaAiICAwAAgAgAIAcAAIEIACAKAwAAoAQAIAcAAKgEACCtAgAAxAQAMK4CAAARABCvAgAAxAQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIdoCAADFBNoCIqADAADDBAAgAwAAABEAIAEAABIAMAIAABMAIBMHAACoBAAgCAAApAQAIAkAALEEACAOAACABAAgEAAAsgQAIK0CAACwBAAwrgIAABUAEK8CAACwBAAwtgJAAP8DACHKAgEA_AMAIc0CAgCdBAAh5QIBAPwDACHmAgEA_gMAIecCAQD-AwAh6AIBAP4DACHpAgEA_AMAIeoCAQD-AwAh6wIBAP4DACHsAkAAnwQAIQEAAAAVACAdEQAAvAQAIBIAAKQEACATAACxBAAgFAAAvAQAIBUAAL0EACAWAAC-BAAgGAAAvwQAIBkAALIEACAaAADABAAgGwAAwQQAIBwAAMIEACCtAgAAugQAMK4CAAAXABCvAgAAugQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdsCAgD9AwAh7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACEBAAAAFwAgEBEAAIQIACASAACBCAAgEwAAgggAIBQAAIQIACAVAACGCAAgFgAA-QcAIBgAAPoHACAZAACDCAAgGgAA_AcAIBsAAP0HACAcAAD-BwAg2wIAANIEACDtAgAA0gQAIO4CAADSBAAg7wIAANIEACD4AgAA0gQAIB4RAAC8BAAgEgAApAQAIBMAALEEACAUAAC8BAAgFQAAvQQAIBYAAL4EACAYAAC_BAAgGQAAsgQAIBoAAMAEACAbAADBBAAgHAAAwgQAIK0CAAC6BAAwrgIAABcAEK8CAAC6BAAwsAIBAAAAAbYCQAD_AwAhzAJAAP8DACHbAgIAAAAB7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACGkAwAAuQQAIAMAAAAXACABAAAZADACAAAaACAJCgAAtQQAIA0AALgEACCtAgAAtwQAMK4CAAAcABCvAgAAtwQAMLYCQAD_AwAhygIBAPwDACHNAgIAnQQAIeQCAQD8AwAhAgoAAIQIACANAACFCAAgCgoAALUEACANAAC4BAAgrQIAALcEADCuAgAAHAAQrwIAALcEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHkAgEA_AMAIaMDAAC2BAAgAwAAABwAIAEAAB0AMAIAAB4AIAMAAAAcACABAAAdADACAAAeACABAAAAHAAgCwcAAKgEACAPAAC1BAAgrQIAALMEADCuAgAAIgAQrwIAALMEADCwAgEA_AMAIbYCQAD_AwAhygIBAPwDACHPAgAAtATkAiLhAgIAnQQAIeICAQD8AwAhAgcAAIEIACAPAACECAAgCwcAAKgEACAPAAC1BAAgrQIAALMEADCuAgAAIgAQrwIAALMEADCwAgEAAAABtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACEDAAAAIgAgAQAAIwAwAgAAJAAgAQAAABcAIAEAAAAcACABAAAAIgAgAQAAABcAIAMAAAAXACABAAAZADACAAAaACABAAAAFQAgCwcAAIEIACAIAACBCAAgCQAAgggAIA4AAJ0FACAQAACDCAAg5gIAANIEACDnAgAA0gQAIOgCAADSBAAg6gIAANIEACDrAgAA0gQAIOwCAADSBAAgFAcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhogMAAK8EACADAAAAFQAgAQAALAAwAgAALQAgAwAAABEAIAEAABIAMAIAABMAIAoHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIDBwAAgQgAIBcAAIAIACDWAgAA0gQAIAsHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAAAAAbYCQAD_AwAhygIBAPwDACHWAgEA_gMAIdgCAACuBNgCIqEDAACsBAAgAwAAADAAIAEAADEAMAIAADIAIAEAAAAPACADAAAAIgAgAQAAIwAwAgAAJAAgCAMAAKAEACAHAACoBAAgrQIAAKsEADCuAgAANgAQrwIAAKsEADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACECAwAAgAgAIAcAAIEIACAJAwAAoAQAIAcAAKgEACCtAgAAqwQAMK4CAAA2ABCvAgAAqwQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIaADAACqBAAgAwAAADYAIAEAADcAMAIAADgAIBEDAACpBAAgBwAAqAQAIK0CAAClBAAwrgIAADoAEK8CAAClBAAwsAIBAPwDACG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQoDAACACAAgBwAAgQgAIMkCAADSBAAgzQIAANIEACDQAgAA0gQAINECAADSBAAg0gIAANIEACDTAgAA0gQAINQCAADSBAAg1QIAANIEACARAwAAqQQAIAcAAKgEACCtAgAApQQAMK4CAAA6ABCvAgAApQQAMLACAQAAAAG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQMAAAA6ACABAAA7ADACAAA8ACABAAAADwAgDAMAAKAEACAHAACkBAAgKgAAogQAIK0CAACjBAAwrgIAAD8AEK8CAACjBAAwsAIBAPwDACG2AkAA_wMAIckCAQD8AwAhygIBAP4DACHLAgIAnQQAIcwCQAD_AwAhAwMAAIAIACAHAACBCAAgygIAANIEACAMAwAAoAQAIAcAAKQEACAqAACiBAAgrQIAAKMEADCuAgAAPwAQrwIAAKMEADCwAgEAAAABtgJAAP8DACHJAgEA_AMAIcoCAQD-AwAhywICAJ0EACHMAkAA_wMAIQMAAAA_ACABAABAADACAABBACABAAAAFwAgAQAAABcAIAEAAAAVACABAAAAEQAgAQAAADAAIAEAAAAiACABAAAANgAgAQAAADoAIAEAAAA_ACADAAAAMAAgAQAAMQAwAgAAMgAgDB8AAKAEACCtAgAAoQQAMK4CAABNABCvAgAAoQQAMLACAQD8AwAhsQIBAPwDACGyAgEA_AMAIbMCAQD8AwAhtAIBAPwDACG1AgAAogQAILYCQAD_AwAhtwJAAJ8EACECHwAAgAgAILcCAADSBAAgDB8AAKAEACCtAgAAoQQAMK4CAABNABCvAgAAoQQAMLACAQAAAAGxAgEA_AMAIbICAQD8AwAhswIBAPwDACG0AgEA_AMAIbUCAACiBAAgtgJAAP8DACG3AkAAnwQAIQMAAABNACABAABOADACAABPACADAAAANgAgAQAANwAwAgAAOAAgAwAAADoAIAEAADsAMAIAADwAIAMAAAA_ACABAABAADACAABBACAPAwAAoAQAIK0CAACcBAAwrgIAAFQAEK8CAACcBAAwsAIBAPwDACG2AkAAnwQAIckCAQD8AwAh3AIBAP4DACH5AgEA_AMAIfoCAQD8AwAh-wICAJ0EACH8AgEA_AMAIf0CIACeBAAh_gIBAP4DACH_AgEA_gMAIQUDAACACAAgtgIAANIEACDcAgAA0gQAIP4CAADSBAAg_wIAANIEACAPAwAAoAQAIK0CAACcBAAwrgIAAFQAEK8CAACcBAAwsAIBAAAAAbYCQACfBAAhyQIBAPwDACHcAgEA_gMAIfkCAQD8AwAh-gIBAPwDACH7AgIAnQQAIfwCAQD8AwAh_QIgAJ4EACH-AgEA_gMAIf8CAQD-AwAhAwAAAFQAIAEAAFUAMAIAAFYAIAEAAAADACABAAAABwAgAQAAAAsAIAEAAAARACABAAAAMAAgAQAAAE0AIAEAAAA2ACABAAAAOgAgAQAAAD8AIAEAAABUACABAAAAAQAgGQQAAPYHACAFAAD3BwAgBgAA-AcAIB0AAPkHACAeAAD6BwAgIAAA-wcAICEAAPwHACAiAAD9BwAgIwAA_gcAICQAAP8HACDaAgAA0gQAINsCAADSBAAg3AIAANIEACD4AgAA0gQAII8DAADSBAAgkQMAANIEACCXAwAA0gQAIJgDAADSBAAgmQMAANIEACCaAwAA0gQAIJsDAADSBAAgnAMAANIEACCdAwAA0gQAIJ4DAADSBAAgnwMAANIEACADAAAADwAgAQAAYwAwAgAAAQAgAwAAAA8AIAEAAGMAMAIAAAEAIAMAAAAPACABAABjADACAAABACAgBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAgAADxBwAgIQAA8gcAICIAAPMHACAjAAD0BwAgJAAA9QcAILACAQAAAAG2AkAAAAABzAJAAAAAAdoCAQAAAAHbAgIAAAAB3AIBAAAAAfgCQAAAAAGPAwEAAAABkAMgAAAAAZEDAQAAAAGTAwAAAJMDApUDAAAAlQMClgMgAAAAAZcDAQAAAAGYAwEAAAABmQOAAAAAAZoDQAAAAAGbAwEAAAABnAMgAAAAAZ0DAQAAAAGeA0AAAAABnwNAAAAAAQEqAABnACAWsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABASoAAGkAMAEqAABpADAgBAAA-QYAIAUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQIAAAABACAqAABsACAWsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhAgAAAA8AICoAAG4AIAIAAAAPACAqAABuACADAAAAAQAgMQAAZwAgMgAAbAAgAQAAAAEAIAEAAAAPACAUDAAA8QYAIDcAAPIGACA4AAD1BgAgOQAA9AYAIDoAAPMGACDaAgAA0gQAINsCAADSBAAg3AIAANIEACD4AgAA0gQAII8DAADSBAAgkQMAANIEACCXAwAA0gQAIJgDAADSBAAgmQMAANIEACCaAwAA0gQAIJsDAADSBAAgnAMAANIEACCdAwAA0gQAIJ4DAADSBAAgnwMAANIEACAZrQIAAJIEADCuAgAAdQAQrwIAAJIEADCwAgEA1AMAIbYCQADWAwAhzAJAANYDACHaAgEA4gMAIdsCAgDpAwAh3AIBAOIDACH4AkAA1wMAIY8DAQDiAwAhkAMgAIkEACGRAwEA4gMAIZMDAACTBJMDIpUDAACUBJUDIpYDIACJBAAhlwMBAOIDACGYAwEA4gMAIZkDAADrAwAgmgNAANcDACGbAwEA4gMAIZwDIACVBAAhnQMBAOIDACGeA0AA1wMAIZ8DQADXAwAhAwAAAA8AIAEAAHQAMDYAAHUAIAMAAAAPACABAABjADACAAABACABAAAABQAgAQAAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIA4DAADwBgAgsAIBAAAAAbYCQAAAAAHJAgEAAAABzAJAAAAAAYYDAQAAAAGHAwEAAAABiAMBAAAAAYkDAQAAAAGKA0AAAAABiwNAAAAAAYwDAQAAAAGNAwEAAAABjgMBAAAAAQEqAAB9ACANsAIBAAAAAbYCQAAAAAHJAgEAAAABzAJAAAAAAYYDAQAAAAGHAwEAAAABiAMBAAAAAYkDAQAAAAGKA0AAAAABiwNAAAAAAYwDAQAAAAGNAwEAAAABjgMBAAAAAQEqAAB_ADABKgAAfwAwDgMAAO8GACCwAgEA1gQAIbYCQADXBAAhyQIBANYEACHMAkAA1wQAIYYDAQDWBAAhhwMBANYEACGIAwEA4QQAIYkDAQDhBAAhigNAANgEACGLA0AA2AQAIYwDAQDhBAAhjQMBAOEEACGOAwEA4QQAIQIAAAAFACAqAACCAQAgDbACAQDWBAAhtgJAANcEACHJAgEA1gQAIcwCQADXBAAhhgMBANYEACGHAwEA1gQAIYgDAQDhBAAhiQMBAOEEACGKA0AA2AQAIYsDQADYBAAhjAMBAOEEACGNAwEA4QQAIY4DAQDhBAAhAgAAAAMAICoAAIQBACACAAAAAwAgKgAAhAEAIAMAAAAFACAxAAB9ACAyAACCAQAgAQAAAAUAIAEAAAADACAKDAAA7AYAIDkAAO4GACA6AADtBgAgiAMAANIEACCJAwAA0gQAIIoDAADSBAAgiwMAANIEACCMAwAA0gQAII0DAADSBAAgjgMAANIEACAQrQIAAJEEADCuAgAAiwEAEK8CAACRBAAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhzAJAANYDACGGAwEA1AMAIYcDAQDUAwAhiAMBAOIDACGJAwEA4gMAIYoDQADXAwAhiwNAANcDACGMAwEA4gMAIY0DAQDiAwAhjgMBAOIDACEDAAAAAwAgAQAAigEAMDYAAIsBACADAAAAAwAgAQAABAAwAgAABQAgAQAAAAkAIAEAAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACAKAwAA6wYAILACAQAAAAG2AkAAAAAByQIBAAAAAcwCQAAAAAHSAgEAAAABggNAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAQEqAACTAQAgCbACAQAAAAG2AkAAAAAByQIBAAAAAcwCQAAAAAHSAgEAAAABggNAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAQEqAACVAQAwASoAAJUBADAKAwAA6gYAILACAQDWBAAhtgJAANcEACHJAgEA1gQAIcwCQADXBAAh0gIBAOEEACGCA0AA1wQAIYMDAQDWBAAhhAMBAOEEACGFAwEA4QQAIQIAAAAJACAqAACYAQAgCbACAQDWBAAhtgJAANcEACHJAgEA1gQAIcwCQADXBAAh0gIBAOEEACGCA0AA1wQAIYMDAQDWBAAhhAMBAOEEACGFAwEA4QQAIQIAAAAHACAqAACaAQAgAgAAAAcAICoAAJoBACADAAAACQAgMQAAkwEAIDIAAJgBACABAAAACQAgAQAAAAcAIAYMAADnBgAgOQAA6QYAIDoAAOgGACDSAgAA0gQAIIQDAADSBAAghQMAANIEACAMrQIAAJAEADCuAgAAoQEAEK8CAACQBAAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhzAJAANYDACHSAgEA4gMAIYIDQADWAwAhgwMBANQDACGEAwEA4gMAIYUDAQDiAwAhAwAAAAcAIAEAAKABADA2AAChAQAgAwAAAAcAIAEAAAgAMAIAAAkAIAEAAAANACABAAAADQAgAwAAAAsAIAEAAAwAMAIAAA0AIAMAAAALACABAAAMADACAAANACADAAAACwAgAQAADAAwAgAADQAgCAMAAOYGACCwAgEAAAABtgJAAAAAAckCAQAAAAHMAkAAAAABgAMBAAAAAYEDAQAAAAGCA0AAAAABASoAAKkBACAHsAIBAAAAAbYCQAAAAAHJAgEAAAABzAJAAAAAAYADAQAAAAGBAwEAAAABggNAAAAAAQEqAACrAQAwASoAAKsBADABAAAADwAgCAMAAOUGACCwAgEA1gQAIbYCQADYBAAhyQIBAOEEACHMAkAA2AQAIYADAQDWBAAhgQMBANYEACGCA0AA1wQAIQIAAAANACAqAACvAQAgB7ACAQDWBAAhtgJAANgEACHJAgEA4QQAIcwCQADYBAAhgAMBANYEACGBAwEA1gQAIYIDQADXBAAhAgAAAAsAICoAALEBACACAAAACwAgKgAAsQEAIAEAAAAPACADAAAADQAgMQAAqQEAIDIAAK8BACABAAAADQAgAQAAAAsAIAYMAADiBgAgOQAA5AYAIDoAAOMGACC2AgAA0gQAIMkCAADSBAAgzAIAANIEACAKrQIAAI8EADCuAgAAuQEAEK8CAACPBAAwsAIBANQDACG2AkAA1wMAIckCAQDiAwAhzAJAANcDACGAAwEA1AMAIYEDAQDUAwAhggNAANYDACEDAAAACwAgAQAAuAEAMDYAALkBACADAAAACwAgAQAADAAwAgAADQAgAQAAAFYAIAEAAABWACADAAAAVAAgAQAAVQAwAgAAVgAgAwAAAFQAIAEAAFUAMAIAAFYAIAMAAABUACABAABVADACAABWACAMAwAA4QYAILACAQAAAAG2AkAAAAAByQIBAAAAAdwCAQAAAAH5AgEAAAAB-gIBAAAAAfsCAgAAAAH8AgEAAAAB_QIgAAAAAf4CAQAAAAH_AgEAAAABASoAAMEBACALsAIBAAAAAbYCQAAAAAHJAgEAAAAB3AIBAAAAAfkCAQAAAAH6AgEAAAAB-wICAAAAAfwCAQAAAAH9AiAAAAAB_gIBAAAAAf8CAQAAAAEBKgAAwwEAMAEqAADDAQAwDAMAAOAGACCwAgEA1gQAIbYCQADYBAAhyQIBANYEACHcAgEA4QQAIfkCAQDWBAAh-gIBANYEACH7AgIA4AQAIfwCAQDWBAAh_QIgANkFACH-AgEA4QQAIf8CAQDhBAAhAgAAAFYAICoAAMYBACALsAIBANYEACG2AkAA2AQAIckCAQDWBAAh3AIBAOEEACH5AgEA1gQAIfoCAQDWBAAh-wICAOAEACH8AgEA1gQAIf0CIADZBQAh_gIBAOEEACH_AgEA4QQAIQIAAABUACAqAADIAQAgAgAAAFQAICoAAMgBACADAAAAVgAgMQAAwQEAIDIAAMYBACABAAAAVgAgAQAAAFQAIAkMAADbBgAgNwAA3AYAIDgAAN8GACA5AADeBgAgOgAA3QYAILYCAADSBAAg3AIAANIEACD-AgAA0gQAIP8CAADSBAAgDq0CAACOBAAwrgIAAM8BABCvAgAAjgQAMLACAQDUAwAhtgJAANcDACHJAgEA1AMAIdwCAQDiAwAh-QIBANQDACH6AgEA1AMAIfsCAgDjAwAh_AIBANQDACH9AiAAiQQAIf4CAQDiAwAh_wIBAOIDACEDAAAAVAAgAQAAzgEAMDYAAM8BACADAAAAVAAgAQAAVQAwAgAAVgAgAQAAABoAIAEAAAAaACADAAAAFwAgAQAAGQAwAgAAGgAgAwAAABcAIAEAABkAMAIAABoAIAMAAAAXACABAAAZADACAAAaACAaEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgGwAAxAYAIBwAAMUGACCwAgEAAAABtgJAAAAAAcwCQAAAAAHbAgIAAAAB7QICAAAAAe4CAQAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABASoAANcBACAPsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHuAgEAAAAB7wICAAAAAfECAAAA8QIC8gIgAAAAAfMCIAAAAAH0AgIAAAAB9QICAAAAAfYCAgAAAAH3AgIAAAAB-AJAAAAAAQEqAADZAQAwASoAANkBADABAAAAFQAgAQAAABcAIAEAAAAVACAaEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAIBwAAOQFACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhAgAAABoAICoAAN8BACAPsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIQIAAAAXACAqAADhAQAgAgAAABcAICoAAOEBACABAAAAFQAgAQAAABcAIAEAAAAVACADAAAAGgAgMQAA1wEAIDIAAN8BACABAAAAGgAgAQAAABcAIAoMAADWBgAgNwAA1wYAIDgAANoGACA5AADZBgAgOgAA2AYAINsCAADSBAAg7QIAANIEACDuAgAA0gQAIO8CAADSBAAg-AIAANIEACASrQIAAIcEADCuAgAA6wEAEK8CAACHBAAwsAIBANQDACG2AkAA1gMAIcwCQADWAwAh2wICAOkDACHtAgIA6QMAIe4CAQDiAwAh7wICAOkDACHxAgAAiATxAiLyAiAAiQQAIfMCIACJBAAh9AICAOMDACH1AgIA4wMAIfYCAgDjAwAh9wICAOMDACH4AkAA1wMAIQMAAAAXACABAADqAQAwNgAA6wEAIAMAAAAXACABAAAZADACAAAaACABAAAALQAgAQAAAC0AIAMAAAAVACABAAAsADACAAAtACADAAAAFQAgAQAALAAwAgAALQAgAwAAABUAIAEAACwAMAIAAC0AIBAHAADVBgAgCAAAtgYAIAkAALcGACAOAAC4BgAgEAAAuQYAILYCQAAAAAHKAgEAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABASoAAPMBACALtgJAAAAAAcoCAQAAAAHNAgIAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAekCAQAAAAHqAgEAAAAB6wIBAAAAAewCQAAAAAEBKgAA9QEAMAEqAAD1AQAwEAcAALQFACAIAAC1BQAgCQAAtgUAIA4AALcFACAQAAC4BQAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQIAAAAtACAqAAD4AQAgC7YCQADXBAAhygIBANYEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACECAAAAFQAgKgAA-gEAIAIAAAAVACAqAAD6AQAgAwAAAC0AIDEAAPMBACAyAAD4AQAgAQAAAC0AIAEAAAAVACALDAAArwUAIDcAALAFACA4AACzBQAgOQAAsgUAIDoAALEFACDmAgAA0gQAIOcCAADSBAAg6AIAANIEACDqAgAA0gQAIOsCAADSBAAg7AIAANIEACAOrQIAAIYEADCuAgAAgQIAEK8CAACGBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5QIBANQDACHmAgEA4gMAIecCAQDiAwAh6AIBAOIDACHpAgEA1AMAIeoCAQDiAwAh6wIBAOIDACHsAkAA1wMAIQMAAAAVACABAACAAgAwNgAAgQIAIAMAAAAVACABAAAsADACAAAtACABAAAAHgAgAQAAAB4AIAMAAAAcACABAAAdADACAAAeACADAAAAHAAgAQAAHQAwAgAAHgAgAwAAABwAIAEAAB0AMAIAAB4AIAYKAACbBQAgDQAArgUAILYCQAAAAAHKAgEAAAABzQICAAAAAeQCAQAAAAEBKgAAiQIAIAS2AkAAAAABygIBAAAAAc0CAgAAAAHkAgEAAAABASoAAIsCADABKgAAiwIAMAYKAACZBQAgDQAArQUAILYCQADXBAAhygIBANYEACHNAgIA4AQAIeQCAQDWBAAhAgAAAB4AICoAAI4CACAEtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5AIBANYEACECAAAAHAAgKgAAkAIAIAIAAAAcACAqAACQAgAgAwAAAB4AIDEAAIkCACAyAACOAgAgAQAAAB4AIAEAAAAcACAFDAAAqAUAIDcAAKkFACA4AACsBQAgOQAAqwUAIDoAAKoFACAHrQIAAIUEADCuAgAAlwIAEK8CAACFBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5AIBANQDACEDAAAAHAAgAQAAlgIAMDYAAJcCACADAAAAHAAgAQAAHQAwAgAAHgAgAQAAACQAIAEAAAAkACADAAAAIgAgAQAAIwAwAgAAJAAgAwAAACIAIAEAACMAMAIAACQAIAMAAAAiACABAAAjADACAAAkACAIBwAApgUAIA8AAKcFACCwAgEAAAABtgJAAAAAAcoCAQAAAAHPAgAAAOQCAuECAgAAAAHiAgEAAAABASoAAJ8CACAGsAIBAAAAAbYCQAAAAAHKAgEAAAABzwIAAADkAgLhAgIAAAAB4gIBAAAAAQEqAAChAgAwASoAAKECADAIBwAApAUAIA8AAKUFACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHPAgAAowXkAiLhAgIA4AQAIeICAQDWBAAhAgAAACQAICoAAKQCACAGsAIBANYEACG2AkAA1wQAIcoCAQDWBAAhzwIAAKMF5AIi4QICAOAEACHiAgEA1gQAIQIAAAAiACAqAACmAgAgAgAAACIAICoAAKYCACADAAAAJAAgMQAAnwIAIDIAAKQCACABAAAAJAAgAQAAACIAIAUMAACeBQAgNwAAnwUAIDgAAKIFACA5AAChBQAgOgAAoAUAIAmtAgAAgQQAMK4CAACtAgAQrwIAAIEEADCwAgEA1AMAIbYCQADWAwAhygIBANQDACHPAgAAggTkAiLhAgIA4wMAIeICAQDUAwAhAwAAACIAIAEAAKwCADA2AACtAgAgAwAAACIAIAEAACMAMAIAACQAIAkLAACABAAgrQIAAPsDADCuAgAAswIAEK8CAAD7AwAwsAIBAAAAAbYCQAD_AwAh2wICAAAAAdwCAQAAAAHdAgEA_gMAIQEAAACwAgAgAQAAALACACAJCwAAgAQAIK0CAAD7AwAwrgIAALMCABCvAgAA-wMAMLACAQD8AwAhtgJAAP8DACHbAgIA_QMAIdwCAQD8AwAh3QIBAP4DACEDCwAAnQUAINsCAADSBAAg3QIAANIEACADAAAAswIAIAEAALQCADACAACwAgAgAwAAALMCACABAAC0AgAwAgAAsAIAIAMAAACzAgAgAQAAtAIAMAIAALACACAGCwAAnAUAILACAQAAAAG2AkAAAAAB2wICAAAAAdwCAQAAAAHdAgEAAAABASoAALgCACAFsAIBAAAAAbYCQAAAAAHbAgIAAAAB3AIBAAAAAd0CAQAAAAEBKgAAugIAMAEqAAC6AgAwBgsAAI0FACCwAgEA1gQAIbYCQADXBAAh2wICAOsEACHcAgEA1gQAId0CAQDhBAAhAgAAALACACAqAAC9AgAgBbACAQDWBAAhtgJAANcEACHbAgIA6wQAIdwCAQDWBAAh3QIBAOEEACECAAAAswIAICoAAL8CACACAAAAswIAICoAAL8CACADAAAAsAIAIDEAALgCACAyAAC9AgAgAQAAALACACABAAAAswIAIAcMAACIBQAgNwAAiQUAIDgAAIwFACA5AACLBQAgOgAAigUAINsCAADSBAAg3QIAANIEACAIrQIAAPoDADCuAgAAxgIAEK8CAAD6AwAwsAIBANQDACG2AkAA1gMAIdsCAgDpAwAh3AIBANQDACHdAgEA4gMAIQMAAACzAgAgAQAAxQIAMDYAAMYCACADAAAAswIAIAEAALQCADACAACwAgAgAQAAABMAIAEAAAATACADAAAAEQAgAQAAEgAwAgAAEwAgAwAAABEAIAEAABIAMAIAABMAIAMAAAARACABAAASADACAAATACAGAwAAhwUAIAcAAIYFACC2AkAAAAAByQIBAAAAAcoCAQAAAAHaAgAAANoCAgEqAADOAgAgBLYCQAAAAAHJAgEAAAABygIBAAAAAdoCAAAA2gICASoAANACADABKgAA0AIAMAYDAACFBQAgBwAAhAUAILYCQADXBAAhyQIBANYEACHKAgEA1gQAIdoCAACDBdoCIgIAAAATACAqAADTAgAgBLYCQADXBAAhyQIBANYEACHKAgEA1gQAIdoCAACDBdoCIgIAAAARACAqAADVAgAgAgAAABEAICoAANUCACADAAAAEwAgMQAAzgIAIDIAANMCACABAAAAEwAgAQAAABEAIAMMAACABQAgOQAAggUAIDoAAIEFACAHrQIAAPYDADCuAgAA3AIAEK8CAAD2AwAwtgJAANYDACHJAgEA1AMAIcoCAQDUAwAh2gIAAPcD2gIiAwAAABEAIAEAANsCADA2AADcAgAgAwAAABEAIAEAABIAMAIAABMAIAEAAAAyACABAAAAMgAgAwAAADAAIAEAADEAMAIAADIAIAMAAAAwACABAAAxADACAAAyACADAAAAMAAgAQAAMQAwAgAAMgAgBwcAAP4EACAXAAD_BAAgsAIBAAAAAbYCQAAAAAHKAgEAAAAB1gIBAAAAAdgCAAAA2AICASoAAOQCACAFsAIBAAAAAbYCQAAAAAHKAgEAAAAB1gIBAAAAAdgCAAAA2AICASoAAOYCADABKgAA5gIAMAEAAAAPACAHBwAA_AQAIBcAAP0EACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHWAgEA4QQAIdgCAAD7BNgCIgIAAAAyACAqAADqAgAgBbACAQDWBAAhtgJAANcEACHKAgEA1gQAIdYCAQDhBAAh2AIAAPsE2AIiAgAAADAAICoAAOwCACACAAAAMAAgKgAA7AIAIAEAAAAPACADAAAAMgAgMQAA5AIAIDIAAOoCACABAAAAMgAgAQAAADAAIAQMAAD4BAAgOQAA-gQAIDoAAPkEACDWAgAA0gQAIAitAgAA8gMAMK4CAAD0AgAQrwIAAPIDADCwAgEA1AMAIbYCQADWAwAhygIBANQDACHWAgEA4gMAIdgCAADzA9gCIgMAAAAwACABAADzAgAwNgAA9AIAIAMAAAAwACABAAAxADACAAAyACABAAAAOAAgAQAAADgAIAMAAAA2ACABAAA3ADACAAA4ACADAAAANgAgAQAANwAwAgAAOAAgAwAAADYAIAEAADcAMAIAADgAIAUDAAD3BAAgBwAA9gQAILYCQAAAAAHJAgEAAAABygIBAAAAAQEqAAD8AgAgA7YCQAAAAAHJAgEAAAABygIBAAAAAQEqAAD-AgAwASoAAP4CADAFAwAA9QQAIAcAAPQEACC2AkAA1wQAIckCAQDWBAAhygIBANYEACECAAAAOAAgKgAAgQMAIAO2AkAA1wQAIckCAQDWBAAhygIBANYEACECAAAANgAgKgAAgwMAIAIAAAA2ACAqAACDAwAgAwAAADgAIDEAAPwCACAyAACBAwAgAQAAADgAIAEAAAA2ACADDAAA8QQAIDkAAPMEACA6AADyBAAgBq0CAADxAwAwrgIAAIoDABCvAgAA8QMAMLYCQADWAwAhyQIBANQDACHKAgEA1AMAIQMAAAA2ACABAACJAwAwNgAAigMAIAMAAAA2ACABAAA3ADACAAA4ACABAAAAPAAgAQAAADwAIAMAAAA6ACABAAA7ADACAAA8ACADAAAAOgAgAQAAOwAwAgAAPAAgAwAAADoAIAEAADsAMAIAADwAIA4DAADwBAAgBwAA7wQAILACAQAAAAG2AkAAAAAByQIBAAAAAcoCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEBKgAAkgMAIAywAgEAAAABtgJAAAAAAckCAQAAAAHKAgEAAAABzQICAAAAAc8CAAAAzwIC0AIBAAAAAdECAQAAAAHSAgEAAAAB0wIBAAAAAdQCgAAAAAHVAgEAAAABASoAAJQDADABKgAAlAMAMAEAAAAPACAOAwAA7gQAIAcAAO0EACCwAgEA1gQAIbYCQADXBAAhyQIBAOEEACHKAgEA1gQAIc0CAgDrBAAhzwIAAOwEzwIi0AIBAOEEACHRAgEA4QQAIdICAQDhBAAh0wIBAOEEACHUAoAAAAAB1QIBAOEEACECAAAAPAAgKgAAmAMAIAywAgEA1gQAIbYCQADXBAAhyQIBAOEEACHKAgEA1gQAIc0CAgDrBAAhzwIAAOwEzwIi0AIBAOEEACHRAgEA4QQAIdICAQDhBAAh0wIBAOEEACHUAoAAAAAB1QIBAOEEACECAAAAOgAgKgAAmgMAIAIAAAA6ACAqAACaAwAgAQAAAA8AIAMAAAA8ACAxAACSAwAgMgAAmAMAIAEAAAA8ACABAAAAOgAgDQwAAOYEACA3AADnBAAgOAAA6gQAIDkAAOkEACA6AADoBAAgyQIAANIEACDNAgAA0gQAINACAADSBAAg0QIAANIEACDSAgAA0gQAINMCAADSBAAg1AIAANIEACDVAgAA0gQAIA-tAgAA6AMAMK4CAACiAwAQrwIAAOgDADCwAgEA1AMAIbYCQADWAwAhyQIBAOIDACHKAgEA1AMAIc0CAgDpAwAhzwIAAOoDzwIi0AIBAOIDACHRAgEA4gMAIdICAQDiAwAh0wIBAOIDACHUAgAA6wMAINUCAQDiAwAhAwAAADoAIAEAAKEDADA2AACiAwAgAwAAADoAIAEAADsAMAIAADwAIAEAAABBACABAAAAQQAgAwAAAD8AIAEAAEAAMAIAAEEAIAMAAAA_ACABAABAADACAABBACADAAAAPwAgAQAAQAAwAgAAQQAgCQMAAOQEACAHAADlBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABygIBAAAAAcsCAgAAAAHMAkAAAAABASoAAKoDACAHKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABygIBAAAAAcsCAgAAAAHMAkAAAAABASoAAKwDADABKgAArAMAMAEAAAAXACAJAwAA4gQAIAcAAOMEACAqgAAAAAGwAgEA1gQAIbYCQADXBAAhyQIBANYEACHKAgEA4QQAIcsCAgDgBAAhzAJAANcEACECAAAAQQAgKgAAsAMAIAcqgAAAAAGwAgEA1gQAIbYCQADXBAAhyQIBANYEACHKAgEA4QQAIcsCAgDgBAAhzAJAANcEACECAAAAPwAgKgAAsgMAIAIAAAA_ACAqAACyAwAgAQAAABcAIAMAAABBACAxAACqAwAgMgAAsAMAIAEAAABBACABAAAAPwAgBgwAANsEACA3AADcBAAgOAAA3wQAIDkAAN4EACA6AADdBAAgygIAANIEACAKKgAA1QMAIK0CAADhAwAwrgIAALoDABCvAgAA4QMAMLACAQDUAwAhtgJAANYDACHJAgEA1AMAIcoCAQDiAwAhywICAOMDACHMAkAA1gMAIQMAAAA_ACABAAC5AwAwNgAAugMAIAMAAAA_ACABAABAADACAABBACABAAAATwAgAQAAAE8AIAMAAABNACABAABOADACAABPACADAAAATQAgAQAATgAwAgAATwAgAwAAAE0AIAEAAE4AMAIAAE8AIAkfAADaBAAgsAIBAAAAAbECAQAAAAGyAgEAAAABswIBAAAAAbQCAQAAAAG1AoAAAAABtgJAAAAAAbcCQAAAAAEBKgAAwgMAIAiwAgEAAAABsQIBAAAAAbICAQAAAAGzAgEAAAABtAIBAAAAAbUCgAAAAAG2AkAAAAABtwJAAAAAAQEqAADEAwAwASoAAMQDADAJHwAA2QQAILACAQDWBAAhsQIBANYEACGyAgEA1gQAIbMCAQDWBAAhtAIBANYEACG1AoAAAAABtgJAANcEACG3AkAA2AQAIQIAAABPACAqAADHAwAgCLACAQDWBAAhsQIBANYEACGyAgEA1gQAIbMCAQDWBAAhtAIBANYEACG1AoAAAAABtgJAANcEACG3AkAA2AQAIQIAAABNACAqAADJAwAgAgAAAE0AICoAAMkDACADAAAATwAgMQAAwgMAIDIAAMcDACABAAAATwAgAQAAAE0AIAQMAADTBAAgOQAA1QQAIDoAANQEACC3AgAA0gQAIAutAgAA0wMAMK4CAADQAwAQrwIAANMDADCwAgEA1AMAIbECAQDUAwAhsgIBANQDACGzAgEA1AMAIbQCAQDUAwAhtQIAANUDACC2AkAA1gMAIbcCQADXAwAhAwAAAE0AIAEAAM8DADA2AADQAwAgAwAAAE0AIAEAAE4AMAIAAE8AIAutAgAA0wMAMK4CAADQAwAQrwIAANMDADCwAgEA1AMAIbECAQDUAwAhsgIBANQDACGzAgEA1AMAIbQCAQDUAwAhtQIAANUDACC2AkAA1gMAIbcCQADXAwAhDgwAANwDACA5AADgAwAgOgAA4AMAILgCAQAAAAG5AgEAAAAEugIBAAAABLsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA3wMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQ8MAADcAwAgOQAA3gMAIDoAAN4DACC4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAELDAAA3AMAIDkAAN0DACA6AADdAwAguAJAAAAAAbkCQAAAAAS6AkAAAAAEuwJAAAAAAbwCQAAAAAG9AkAAAAABvgJAAAAAAb8CQADbAwAhCwwAANkDACA5AADaAwAgOgAA2gMAILgCQAAAAAG5AkAAAAAFugJAAAAABbsCQAAAAAG8AkAAAAABvQJAAAAAAb4CQAAAAAG_AkAA2AMAIQsMAADZAwAgOQAA2gMAIDoAANoDACC4AkAAAAABuQJAAAAABboCQAAAAAW7AkAAAAABvAJAAAAAAb0CQAAAAAG-AkAAAAABvwJAANgDACEIuAICAAAAAbkCAgAAAAW6AgIAAAAFuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDZAwAhCLgCQAAAAAG5AkAAAAAFugJAAAAABbsCQAAAAAG8AkAAAAABvQJAAAAAAb4CQAAAAAG_AkAA2gMAIQsMAADcAwAgOQAA3QMAIDoAAN0DACC4AkAAAAABuQJAAAAABLoCQAAAAAS7AkAAAAABvAJAAAAAAb0CQAAAAAG-AkAAAAABvwJAANsDACEIuAICAAAAAbkCAgAAAAS6AgIAAAAEuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDcAwAhCLgCQAAAAAG5AkAAAAAEugJAAAAABLsCQAAAAAG8AkAAAAABvQJAAAAAAb4CQAAAAAG_AkAA3QMAIQy4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAEODAAA3AMAIDkAAOADACA6AADgAwAguAIBAAAAAbkCAQAAAAS6AgEAAAAEuwIBAAAAAbwCAQAAAAG9AgEAAAABvgIBAAAAAb8CAQDfAwAhxgIBAAAAAccCAQAAAAHIAgEAAAABC7gCAQAAAAG5AgEAAAAEugIBAAAABLsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA4AMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQoqAADVAwAgrQIAAOEDADCuAgAAugMAEK8CAADhAwAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhygIBAOIDACHLAgIA4wMAIcwCQADWAwAhDgwAANkDACA5AADnAwAgOgAA5wMAILgCAQAAAAG5AgEAAAAFugIBAAAABbsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA5gMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQ0MAADcAwAgNwAA5QMAIDgAANwDACA5AADcAwAgOgAA3AMAILgCAgAAAAG5AgIAAAAEugICAAAABLsCAgAAAAG8AgIAAAABvQICAAAAAb4CAgAAAAG_AgIA5AMAIQ0MAADcAwAgNwAA5QMAIDgAANwDACA5AADcAwAgOgAA3AMAILgCAgAAAAG5AgIAAAAEugICAAAABLsCAgAAAAG8AgIAAAABvQICAAAAAb4CAgAAAAG_AgIA5AMAIQi4AggAAAABuQIIAAAABLoCCAAAAAS7AggAAAABvAIIAAAAAb0CCAAAAAG-AggAAAABvwIIAOUDACEODAAA2QMAIDkAAOcDACA6AADnAwAguAIBAAAAAbkCAQAAAAW6AgEAAAAFuwIBAAAAAbwCAQAAAAG9AgEAAAABvgIBAAAAAb8CAQDmAwAhxgIBAAAAAccCAQAAAAHIAgEAAAABC7gCAQAAAAG5AgEAAAAFugIBAAAABbsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA5wMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQ-tAgAA6AMAMK4CAACiAwAQrwIAAOgDADCwAgEA1AMAIbYCQADWAwAhyQIBAOIDACHKAgEA1AMAIc0CAgDpAwAhzwIAAOoDzwIi0AIBAOIDACHRAgEA4gMAIdICAQDiAwAh0wIBAOIDACHUAgAA6wMAINUCAQDiAwAhDQwAANkDACA3AADwAwAgOAAA2QMAIDkAANkDACA6AADZAwAguAICAAAAAbkCAgAAAAW6AgIAAAAFuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDvAwAhBwwAANwDACA5AADuAwAgOgAA7gMAILgCAAAAzwICuQIAAADPAgi6AgAAAM8CCL8CAADtA88CIg8MAADZAwAgOQAA7AMAIDoAAOwDACC4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAEMuAKAAAAAAbsCgAAAAAG8AoAAAAABvQKAAAAAAb4CgAAAAAG_AoAAAAABwAIBAAAAAcECAQAAAAHCAgEAAAABwwKAAAAAAcQCgAAAAAHFAoAAAAABBwwAANwDACA5AADuAwAgOgAA7gMAILgCAAAAzwICuQIAAADPAgi6AgAAAM8CCL8CAADtA88CIgS4AgAAAM8CArkCAAAAzwIIugIAAADPAgi_AgAA7gPPAiINDAAA2QMAIDcAAPADACA4AADZAwAgOQAA2QMAIDoAANkDACC4AgIAAAABuQICAAAABboCAgAAAAW7AgIAAAABvAICAAAAAb0CAgAAAAG-AgIAAAABvwICAO8DACEIuAIIAAAAAbkCCAAAAAW6AggAAAAFuwIIAAAAAbwCCAAAAAG9AggAAAABvgIIAAAAAb8CCADwAwAhBq0CAADxAwAwrgIAAIoDABCvAgAA8QMAMLYCQADWAwAhyQIBANQDACHKAgEA1AMAIQitAgAA8gMAMK4CAAD0AgAQrwIAAPIDADCwAgEA1AMAIbYCQADWAwAhygIBANQDACHWAgEA4gMAIdgCAADzA9gCIgcMAADcAwAgOQAA9QMAIDoAAPUDACC4AgAAANgCArkCAAAA2AIIugIAAADYAgi_AgAA9APYAiIHDAAA3AMAIDkAAPUDACA6AAD1AwAguAIAAADYAgK5AgAAANgCCLoCAAAA2AIIvwIAAPQD2AIiBLgCAAAA2AICuQIAAADYAgi6AgAAANgCCL8CAAD1A9gCIgetAgAA9gMAMK4CAADcAgAQrwIAAPYDADC2AkAA1gMAIckCAQDUAwAhygIBANQDACHaAgAA9wPaAiIHDAAA3AMAIDkAAPkDACA6AAD5AwAguAIAAADaAgK5AgAAANoCCLoCAAAA2gIIvwIAAPgD2gIiBwwAANwDACA5AAD5AwAgOgAA-QMAILgCAAAA2gICuQIAAADaAgi6AgAAANoCCL8CAAD4A9oCIgS4AgAAANoCArkCAAAA2gIIugIAAADaAgi_AgAA-QPaAiIIrQIAAPoDADCuAgAAxgIAEK8CAAD6AwAwsAIBANQDACG2AkAA1gMAIdsCAgDpAwAh3AIBANQDACHdAgEA4gMAIQkLAACABAAgrQIAAPsDADCuAgAAswIAEK8CAAD7AwAwsAIBAPwDACG2AkAA_wMAIdsCAgD9AwAh3AIBAPwDACHdAgEA_gMAIQu4AgEAAAABuQIBAAAABLoCAQAAAAS7AgEAAAABvAIBAAAAAb0CAQAAAAG-AgEAAAABvwIBAOADACHGAgEAAAABxwIBAAAAAcgCAQAAAAEIuAICAAAAAbkCAgAAAAW6AgIAAAAFuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDZAwAhC7gCAQAAAAG5AgEAAAAFugIBAAAABbsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA5wMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQi4AkAAAAABuQJAAAAABLoCQAAAAAS7AkAAAAABvAJAAAAAAb0CQAAAAAG-AkAAAAABvwJAAN0DACED3gIAABwAIN8CAAAcACDgAgAAHAAgCa0CAACBBAAwrgIAAK0CABCvAgAAgQQAMLACAQDUAwAhtgJAANYDACHKAgEA1AMAIc8CAACCBOQCIuECAgDjAwAh4gIBANQDACEHDAAA3AMAIDkAAIQEACA6AACEBAAguAIAAADkAgK5AgAAAOQCCLoCAAAA5AIIvwIAAIME5AIiBwwAANwDACA5AACEBAAgOgAAhAQAILgCAAAA5AICuQIAAADkAgi6AgAAAOQCCL8CAACDBOQCIgS4AgAAAOQCArkCAAAA5AIIugIAAADkAgi_AgAAhATkAiIHrQIAAIUEADCuAgAAlwIAEK8CAACFBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5AIBANQDACEOrQIAAIYEADCuAgAAgQIAEK8CAACGBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5QIBANQDACHmAgEA4gMAIecCAQDiAwAh6AIBAOIDACHpAgEA1AMAIeoCAQDiAwAh6wIBAOIDACHsAkAA1wMAIRKtAgAAhwQAMK4CAADrAQAQrwIAAIcEADCwAgEA1AMAIbYCQADWAwAhzAJAANYDACHbAgIA6QMAIe0CAgDpAwAh7gIBAOIDACHvAgIA6QMAIfECAACIBPECIvICIACJBAAh8wIgAIkEACH0AgIA4wMAIfUCAgDjAwAh9gICAOMDACH3AgIA4wMAIfgCQADXAwAhBwwAANwDACA5AACNBAAgOgAAjQQAILgCAAAA8QICuQIAAADxAgi6AgAAAPECCL8CAACMBPECIgUMAADcAwAgOQAAiwQAIDoAAIsEACC4AiAAAAABvwIgAIoEACEFDAAA3AMAIDkAAIsEACA6AACLBAAguAIgAAAAAb8CIACKBAAhArgCIAAAAAG_AiAAiwQAIQcMAADcAwAgOQAAjQQAIDoAAI0EACC4AgAAAPECArkCAAAA8QIIugIAAADxAgi_AgAAjATxAiIEuAIAAADxAgK5AgAAAPECCLoCAAAA8QIIvwIAAI0E8QIiDq0CAACOBAAwrgIAAM8BABCvAgAAjgQAMLACAQDUAwAhtgJAANcDACHJAgEA1AMAIdwCAQDiAwAh-QIBANQDACH6AgEA1AMAIfsCAgDjAwAh_AIBANQDACH9AiAAiQQAIf4CAQDiAwAh_wIBAOIDACEKrQIAAI8EADCuAgAAuQEAEK8CAACPBAAwsAIBANQDACG2AkAA1wMAIckCAQDiAwAhzAJAANcDACGAAwEA1AMAIYEDAQDUAwAhggNAANYDACEMrQIAAJAEADCuAgAAoQEAEK8CAACQBAAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhzAJAANYDACHSAgEA4gMAIYIDQADWAwAhgwMBANQDACGEAwEA4gMAIYUDAQDiAwAhEK0CAACRBAAwrgIAAIsBABCvAgAAkQQAMLACAQDUAwAhtgJAANYDACHJAgEA1AMAIcwCQADWAwAhhgMBANQDACGHAwEA1AMAIYgDAQDiAwAhiQMBAOIDACGKA0AA1wMAIYsDQADXAwAhjAMBAOIDACGNAwEA4gMAIY4DAQDiAwAhGa0CAACSBAAwrgIAAHUAEK8CAACSBAAwsAIBANQDACG2AkAA1gMAIcwCQADWAwAh2gIBAOIDACHbAgIA6QMAIdwCAQDiAwAh-AJAANcDACGPAwEA4gMAIZADIACJBAAhkQMBAOIDACGTAwAAkwSTAyKVAwAAlASVAyKWAyAAiQQAIZcDAQDiAwAhmAMBAOIDACGZAwAA6wMAIJoDQADXAwAhmwMBAOIDACGcAyAAlQQAIZ0DAQDiAwAhngNAANcDACGfA0AA1wMAIQcMAADcAwAgOQAAmwQAIDoAAJsEACC4AgAAAJMDArkCAAAAkwMIugIAAACTAwi_AgAAmgSTAyIHDAAA3AMAIDkAAJkEACA6AACZBAAguAIAAACVAwK5AgAAAJUDCLoCAAAAlQMIvwIAAJgElQMiBQwAANkDACA5AACXBAAgOgAAlwQAILgCIAAAAAG_AiAAlgQAIQUMAADZAwAgOQAAlwQAIDoAAJcEACC4AiAAAAABvwIgAJYEACECuAIgAAAAAb8CIACXBAAhBwwAANwDACA5AACZBAAgOgAAmQQAILgCAAAAlQMCuQIAAACVAwi6AgAAAJUDCL8CAACYBJUDIgS4AgAAAJUDArkCAAAAlQMIugIAAACVAwi_AgAAmQSVAyIHDAAA3AMAIDkAAJsEACA6AACbBAAguAIAAACTAwK5AgAAAJMDCLoCAAAAkwMIvwIAAJoEkwMiBLgCAAAAkwMCuQIAAACTAwi6AgAAAJMDCL8CAACbBJMDIg8DAACgBAAgrQIAAJwEADCuAgAAVAAQrwIAAJwEADCwAgEA_AMAIbYCQACfBAAhyQIBAPwDACHcAgEA_gMAIfkCAQD8AwAh-gIBAPwDACH7AgIAnQQAIfwCAQD8AwAh_QIgAJ4EACH-AgEA_gMAIf8CAQD-AwAhCLgCAgAAAAG5AgIAAAAEugICAAAABLsCAgAAAAG8AgIAAAABvQICAAAAAb4CAgAAAAG_AgIA3AMAIQK4AiAAAAABvwIgAIsEACEIuAJAAAAAAbkCQAAAAAW6AkAAAAAFuwJAAAAAAbwCQAAAAAG9AkAAAAABvgJAAAAAAb8CQADaAwAhJQQAAMoEACAFAADLBAAgBgAAzAQAIB0AAL4EACAeAAC_BAAgIAAAzQQAICEAAMAEACAiAADBBAAgIwAAwgQAICQAAM4EACCtAgAAxgQAMK4CAAAPABCvAgAAxgQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdoCAQD-AwAh2wICAP0DACHcAgEA_gMAIfgCQACfBAAhjwMBAP4DACGQAyAAngQAIZEDAQD-AwAhkwMAAMcEkwMilQMAAMgElQMilgMgAJ4EACGXAwEA_gMAIZgDAQD-AwAhmQMAAKcEACCaA0AAnwQAIZsDAQD-AwAhnAMgAMkEACGdAwEA_gMAIZ4DQACfBAAhnwNAAJ8EACGlAwAADwAgpgMAAA8AIAwfAACgBAAgrQIAAKEEADCuAgAATQAQrwIAAKEEADCwAgEA_AMAIbECAQD8AwAhsgIBAPwDACGzAgEA_AMAIbQCAQD8AwAhtQIAAKIEACC2AkAA_wMAIbcCQACfBAAhDLgCgAAAAAG7AoAAAAABvAKAAAAAAb0CgAAAAAG-AoAAAAABvwKAAAAAAcACAQAAAAHBAgEAAAABwgIBAAAAAcMCgAAAAAHEAoAAAAABxQKAAAAAAQwDAACgBAAgBwAApAQAICoAAKIEACCtAgAAowQAMK4CAAA_ABCvAgAAowQAMLACAQD8AwAhtgJAAP8DACHJAgEA_AMAIcoCAQD-AwAhywICAJ0EACHMAkAA_wMAIR8RAAC8BAAgEgAApAQAIBMAALEEACAUAAC8BAAgFQAAvQQAIBYAAL4EACAYAAC_BAAgGQAAsgQAIBoAAMAEACAbAADBBAAgHAAAwgQAIK0CAAC6BAAwrgIAABcAEK8CAAC6BAAwsAIBAPwDACG2AkAA_wMAIcwCQAD_AwAh2wICAP0DACHtAgIA_QMAIe4CAQD-AwAh7wICAP0DACHxAgAAuwTxAiLyAiAAngQAIfMCIACeBAAh9AICAJ0EACH1AgIAnQQAIfYCAgCdBAAh9wICAJ0EACH4AkAAnwQAIaUDAAAXACCmAwAAFwAgEQMAAKkEACAHAACoBAAgrQIAAKUEADCuAgAAOgAQrwIAAKUEADCwAgEA_AMAIbYCQAD_AwAhyQIBAP4DACHKAgEA_AMAIc0CAgD9AwAhzwIAAKYEzwIi0AIBAP4DACHRAgEA_gMAIdICAQD-AwAh0wIBAP4DACHUAgAApwQAINUCAQD-AwAhBLgCAAAAzwICuQIAAADPAgi6AgAAAM8CCL8CAADuA88CIgy4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAEfEQAAvAQAIBIAAKQEACATAACxBAAgFAAAvAQAIBUAAL0EACAWAAC-BAAgGAAAvwQAIBkAALIEACAaAADABAAgGwAAwQQAIBwAAMIEACCtAgAAugQAMK4CAAAXABCvAgAAugQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdsCAgD9AwAh7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACGlAwAAFwAgpgMAABcAICUEAADKBAAgBQAAywQAIAYAAMwEACAdAAC-BAAgHgAAvwQAICAAAM0EACAhAADABAAgIgAAwQQAICMAAMIEACAkAADOBAAgrQIAAMYEADCuAgAADwAQrwIAAMYEADCwAgEA_AMAIbYCQAD_AwAhzAJAAP8DACHaAgEA_gMAIdsCAgD9AwAh3AIBAP4DACH4AkAAnwQAIY8DAQD-AwAhkAMgAJ4EACGRAwEA_gMAIZMDAADHBJMDIpUDAADIBJUDIpYDIACeBAAhlwMBAP4DACGYAwEA_gMAIZkDAACnBAAgmgNAAJ8EACGbAwEA_gMAIZwDIADJBAAhnQMBAP4DACGeA0AAnwQAIZ8DQACfBAAhpQMAAA8AIKYDAAAPACACyQIBAAAAAcoCAQAAAAEIAwAAoAQAIAcAAKgEACCtAgAAqwQAMK4CAAA2ABCvAgAAqwQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIQLKAgEAAAAB1gIBAAAAAQoHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIEuAIAAADYAgK5AgAAANgCCLoCAAAA2AIIvwIAAPUD2AIiAsoCAQAAAAHNAgIAAAABEwcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhA94CAAAXACDfAgAAFwAg4AIAABcAIAPeAgAAIgAg3wIAACIAIOACAAAiACALBwAAqAQAIA8AALUEACCtAgAAswQAMK4CAAAiABCvAgAAswQAMLACAQD8AwAhtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACEEuAIAAADkAgK5AgAAAOQCCLoCAAAA5AIIvwIAAIQE5AIiFQcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhpQMAABUAIKYDAAAVACADygIBAAAAAc0CAgAAAAHkAgEAAAABCQoAALUEACANAAC4BAAgrQIAALcEADCuAgAAHAAQrwIAALcEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHkAgEA_AMAIQsLAACABAAgrQIAAPsDADCuAgAAswIAEK8CAAD7AwAwsAIBAPwDACG2AkAA_wMAIdsCAgD9AwAh3AIBAPwDACHdAgEA_gMAIaUDAACzAgAgpgMAALMCACACsAIBAAAAAe0CAgAAAAEdEQAAvAQAIBIAAKQEACATAACxBAAgFAAAvAQAIBUAAL0EACAWAAC-BAAgGAAAvwQAIBkAALIEACAaAADABAAgGwAAwQQAIBwAAMIEACCtAgAAugQAMK4CAAAXABCvAgAAugQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdsCAgD9AwAh7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACEEuAIAAADxAgK5AgAAAPECCLoCAAAA8QIIvwIAAI0E8QIiFQcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhpQMAABUAIKYDAAAVACAD3gIAABUAIN8CAAAVACDgAgAAFQAgA94CAAARACDfAgAAEQAg4AIAABEAIAPeAgAAMAAg3wIAADAAIOACAAAwACAD3gIAADYAIN8CAAA2ACDgAgAANgAgA94CAAA6ACDfAgAAOgAg4AIAADoAIAPeAgAAPwAg3wIAAD8AIOACAAA_ACACyQIBAAAAAcoCAQAAAAEJAwAAoAQAIAcAAKgEACCtAgAAxAQAMK4CAAARABCvAgAAxAQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIdoCAADFBNoCIgS4AgAAANoCArkCAAAA2gIIugIAAADaAgi_AgAA-QPaAiIjBAAAygQAIAUAAMsEACAGAADMBAAgHQAAvgQAIB4AAL8EACAgAADNBAAgIQAAwAQAICIAAMEEACAjAADCBAAgJAAAzgQAIK0CAADGBAAwrgIAAA8AEK8CAADGBAAwsAIBAPwDACG2AkAA_wMAIcwCQAD_AwAh2gIBAP4DACHbAgIA_QMAIdwCAQD-AwAh-AJAAJ8EACGPAwEA_gMAIZADIACeBAAhkQMBAP4DACGTAwAAxwSTAyKVAwAAyASVAyKWAyAAngQAIZcDAQD-AwAhmAMBAP4DACGZAwAApwQAIJoDQACfBAAhmwMBAP4DACGcAyAAyQQAIZ0DAQD-AwAhngNAAJ8EACGfA0AAnwQAIQS4AgAAAJMDArkCAAAAkwMIugIAAACTAwi_AgAAmwSTAyIEuAIAAACVAwK5AgAAAJUDCLoCAAAAlQMIvwIAAJkElQMiArgCIAAAAAG_AiAAlwQAIQPeAgAAAwAg3wIAAAMAIOACAAADACAD3gIAAAcAIN8CAAAHACDgAgAABwAgA94CAAALACDfAgAACwAg4AIAAAsAIAPeAgAATQAg3wIAAE0AIOACAABNACAD3gIAAFQAIN8CAABUACDgAgAAVAAgCwMAAKkEACCtAgAAzwQAMK4CAAALABCvAgAAzwQAMLACAQD8AwAhtgJAAJ8EACHJAgEA_gMAIcwCQACfBAAhgAMBAPwDACGBAwEA_AMAIYIDQAD_AwAhDQMAAKAEACCtAgAA0AQAMK4CAAAHABCvAgAA0AQAMLACAQD8AwAhtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAh0gIBAP4DACGCA0AA_wMAIYMDAQD8AwAhhAMBAP4DACGFAwEA_gMAIREDAACgBAAgrQIAANEEADCuAgAAAwAQrwIAANEEADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIYYDAQD8AwAhhwMBAPwDACGIAwEA_gMAIYkDAQD-AwAhigNAAJ8EACGLA0AAnwQAIYwDAQD-AwAhjQMBAP4DACGOAwEA_gMAIQAAAAABqgMBAAAAAQGqA0AAAAABAaoDQAAAAAEFMQAAiwkAIDIAAI4JACCnAwAAjAkAIKgDAACNCQAgrQMAAAEAIAMxAACLCQAgpwMAAIwJACCtAwAAAQAgAAAAAAAFqgMCAAAAAbADAgAAAAGxAwIAAAABsgMCAAAAAbMDAgAAAAEBqgMBAAAAAQUxAACDCQAgMgAAiQkAIKcDAACECQAgqAMAAIgJACCtAwAAAQAgBzEAAIEJACAyAACGCQAgpwMAAIIJACCoAwAAhQkAIKsDAAAXACCsAwAAFwAgrQMAABoAIAMxAACDCQAgpwMAAIQJACCtAwAAAQAgAzEAAIEJACCnAwAAggkAIK0DAAAaACAAAAAAAAWqAwIAAAABsAMCAAAAAbEDAgAAAAGyAwIAAAABswMCAAAAAQGqAwAAAM8CAgUxAAD5CAAgMgAA_wgAIKcDAAD6CAAgqAMAAP4IACCtAwAAGgAgBzEAAPcIACAyAAD8CAAgpwMAAPgIACCoAwAA-wgAIKsDAAAPACCsAwAADwAgrQMAAAEAIAMxAAD5CAAgpwMAAPoIACCtAwAAGgAgAzEAAPcIACCnAwAA-AgAIK0DAAABACAAAAAFMQAA7wgAIDIAAPUIACCnAwAA8AgAIKgDAAD0CAAgrQMAABoAIAUxAADtCAAgMgAA8ggAIKcDAADuCAAgqAMAAPEIACCtAwAAAQAgAzEAAO8IACCnAwAA8AgAIK0DAAAaACADMQAA7QgAIKcDAADuCAAgrQMAAAEAIAAAAAGqAwAAANgCAgUxAADlCAAgMgAA6wgAIKcDAADmCAAgqAMAAOoIACCtAwAAGgAgBzEAAOMIACAyAADoCAAgpwMAAOQIACCoAwAA5wgAIKsDAAAPACCsAwAADwAgrQMAAAEAIAMxAADlCAAgpwMAAOYIACCtAwAAGgAgAzEAAOMIACCnAwAA5AgAIK0DAAABACAAAAABqgMAAADaAgIFMQAA2wgAIDIAAOEIACCnAwAA3AgAIKgDAADgCAAgrQMAABoAIAUxAADZCAAgMgAA3ggAIKcDAADaCAAgqAMAAN0IACCtAwAAAQAgAzEAANsIACCnAwAA3AgAIK0DAAAaACADMQAA2QgAIKcDAADaCAAgrQMAAAEAIAAAAAAACzEAAI4FADAyAACTBQAwpwMAAI8FADCoAwAAkAUAMKkDAACRBQAgqgMAAJIFADCrAwAAkgUAMKwDAACSBQAwrQMAAJIFADCuAwAAlAUAMK8DAACVBQAwBAoAAJsFACC2AkAAAAABygIBAAAAAc0CAgAAAAECAAAAHgAgMQAAmgUAIAMAAAAeACAxAACaBQAgMgAAmAUAIAEqAADYCAAwCgoAALUEACANAAC4BAAgrQIAALcEADCuAgAAHAAQrwIAALcEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHkAgEA_AMAIaMDAAC2BAAgAgAAAB4AICoAAJgFACACAAAAlgUAICoAAJcFACAHrQIAAJUFADCuAgAAlgUAEK8CAACVBQAwtgJAAP8DACHKAgEA_AMAIc0CAgCdBAAh5AIBAPwDACEHrQIAAJUFADCuAgAAlgUAEK8CAACVBQAwtgJAAP8DACHKAgEA_AMAIc0CAgCdBAAh5AIBAPwDACEDtgJAANcEACHKAgEA1gQAIc0CAgDgBAAhBAoAAJkFACC2AkAA1wQAIcoCAQDWBAAhzQICAOAEACEFMQAA0wgAIDIAANYIACCnAwAA1AgAIKgDAADVCAAgrQMAAC0AIAQKAACbBQAgtgJAAAAAAcoCAQAAAAHNAgIAAAABAzEAANMIACCnAwAA1AgAIK0DAAAtACAEMQAAjgUAMKcDAACPBQAwqQMAAJEFACCtAwAAkgUAMAAAAAAAAAGqAwAAAOQCAgUxAADLCAAgMgAA0QgAIKcDAADMCAAgqAMAANAIACCtAwAAGgAgBTEAAMkIACAyAADOCAAgpwMAAMoIACCoAwAAzQgAIK0DAAAtACADMQAAywgAIKcDAADMCAAgrQMAABoAIAMxAADJCAAgpwMAAMoIACCtAwAALQAgAAAAAAAFMQAAxAgAIDIAAMcIACCnAwAAxQgAIKgDAADGCAAgrQMAALACACADMQAAxAgAIKcDAADFCAAgrQMAALACACAAAAAAAAUxAAClCAAgMgAAwggAIKcDAACmCAAgqAMAAMEIACCtAwAAGgAgBzEAALoGACAyAADTBgAgpwMAALsGACCoAwAA0gYAIKsDAAAXACCsAwAAFwAgrQMAABoAIAsxAADOBQAwMgAA0wUAMKcDAADPBQAwqAMAANAFADCpAwAA0QUAIKoDAADSBQAwqwMAANIFADCsAwAA0gUAMK0DAADSBQAwrgMAANQFADCvAwAA1QUAMAsxAADFBQAwMgAAyQUAMKcDAADGBQAwqAMAAMcFADCpAwAAyAUAIKoDAACSBQAwqwMAAJIFADCsAwAAkgUAMK0DAACSBQAwrgMAAMoFADCvAwAAlQUAMAsxAAC5BQAwMgAAvgUAMKcDAAC6BQAwqAMAALsFADCpAwAAvAUAIKoDAAC9BQAwqwMAAL0FADCsAwAAvQUAMK0DAAC9BQAwrgMAAL8FADCvAwAAwAUAMAUHAACmBQAgsAIBAAAAAbYCQAAAAAHPAgAAAOQCAuICAQAAAAECAAAAJAAgMQAAxAUAIAMAAAAkACAxAADEBQAgMgAAwwUAIAEqAADACAAwCwcAAKgEACAPAAC1BAAgrQIAALMEADCuAgAAIgAQrwIAALMEADCwAgEAAAABtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACECAAAAJAAgKgAAwwUAIAIAAADBBQAgKgAAwgUAIAmtAgAAwAUAMK4CAADBBQAQrwIAAMAFADCwAgEA_AMAIbYCQAD_AwAhygIBAPwDACHPAgAAtATkAiLhAgIAnQQAIeICAQD8AwAhCa0CAADABQAwrgIAAMEFABCvAgAAwAUAMLACAQD8AwAhtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACEEsAIBANYEACG2AkAA1wQAIc8CAACjBeQCIuICAQDWBAAhBQcAAKQFACCwAgEA1gQAIbYCQADXBAAhzwIAAKMF5AIi4gIBANYEACEFBwAApgUAILACAQAAAAG2AkAAAAABzwIAAADkAgLiAgEAAAABAw0AAK4FACC2AkAAAAAB5AIBAAAAAQIAAAAeACAxAADNBQAgAwAAAB4AIDEAAM0FACAyAADMBQAgASoAAL8IADACAAAAHgAgKgAAzAUAIAIAAACWBQAgKgAAywUAIAK2AkAA1wQAIeQCAQDWBAAhAw0AAK0FACC2AkAA1wQAIeQCAQDWBAAhAw0AAK4FACC2AkAAAAAB5AIBAAAAARcRAADKBgAgEgAAvAYAIBMAAL0GACAVAAC_BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA0QYAIAMAAAAaACAxAADRBgAgMgAA2gUAIAEqAAC-CAAwHhEAALwEACASAACkBAAgEwAAsQQAIBQAALwEACAVAAC9BAAgFgAAvgQAIBgAAL8EACAZAACyBAAgGgAAwAQAIBsAAMEEACAcAADCBAAgrQIAALoEADCuAgAAFwAQrwIAALoEADCwAgEAAAABtgJAAP8DACHMAkAA_wMAIdsCAgAAAAHtAgIA_QMAIe4CAQD-AwAh7wICAP0DACHxAgAAuwTxAiLyAiAAngQAIfMCIACeBAAh9AICAJ0EACH1AgIAnQQAIfYCAgCdBAAh9wICAJ0EACH4AkAAnwQAIaQDAAC5BAAgAgAAABoAICoAANoFACACAAAA1gUAICoAANcFACASrQIAANUFADCuAgAA1gUAEK8CAADVBQAwsAIBAPwDACG2AkAA_wMAIcwCQAD_AwAh2wICAP0DACHtAgIA_QMAIe4CAQD-AwAh7wICAP0DACHxAgAAuwTxAiLyAiAAngQAIfMCIACeBAAh9AICAJ0EACH1AgIAnQQAIfYCAgCdBAAh9wICAJ0EACH4AkAAnwQAIRKtAgAA1QUAMK4CAADWBQAQrwIAANUFADCwAgEA_AMAIbYCQAD_AwAhzAJAAP8DACHbAgIA_QMAIe0CAgD9AwAh7gIBAP4DACHvAgIA_QMAIfECAAC7BPECIvICIACeBAAh8wIgAJ4EACH0AgIAnQQAIfUCAgCdBAAh9gICAJ0EACH3AgIAnQQAIfgCQACfBAAhDbACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIQGqAwAAAPECAgGqAyAAAAABFxEAANsFACASAADcBQAgEwAA3QUAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAIBwAAOQFACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEHMQAArAgAIDIAALwIACCnAwAArQgAIKgDAAC7CAAgqwMAABUAIKwDAAAVACCtAwAALQAgBzEAAK8IACAyAAC5CAAgpwMAALAIACCoAwAAuAgAIKsDAAAXACCsAwAAFwAgrQMAABoAIAsxAADGBgAwMgAAzAYAMKcDAADHBgAwqAMAAMsGADCpAwAAyAYAIKoDAADSBQAwqwMAANIFADCsAwAA0gUAMK0DAADSBQAwrgMAAM0GADCvAwAA1QUAMAsxAACqBgAwMgAArwYAMKcDAACrBgAwqAMAAKwGADCpAwAArQYAIKoDAACuBgAwqwMAAK4GADCsAwAArgYAMK0DAACuBgAwrgMAALAGADCvAwAAsQYAMAsxAACeBgAwMgAAowYAMKcDAACfBgAwqAMAAKAGADCpAwAAoQYAIKoDAACiBgAwqwMAAKIGADCsAwAAogYAMK0DAACiBgAwrgMAAKQGADCvAwAApQYAMAsxAACSBgAwMgAAlwYAMKcDAACTBgAwqAMAAJQGADCpAwAAlQYAIKoDAACWBgAwqwMAAJYGADCsAwAAlgYAMK0DAACWBgAwrgMAAJgGADCvAwAAmQYAMAsxAACJBgAwMgAAjQYAMKcDAACKBgAwqAMAAIsGADCpAwAAjAYAIKoDAAC9BQAwqwMAAL0FADCsAwAAvQUAMK0DAAC9BQAwrgMAAI4GADCvAwAAwAUAMAsxAAD9BQAwMgAAggYAMKcDAAD-BQAwqAMAAP8FADCpAwAAgAYAIKoDAACBBgAwqwMAAIEGADCsAwAAgQYAMK0DAACBBgAwrgMAAIMGADCvAwAAhAYAMAsxAADxBQAwMgAA9gUAMKcDAADyBQAwqAMAAPMFADCpAwAA9AUAIKoDAAD1BQAwqwMAAPUFADCsAwAA9QUAMK0DAAD1BQAwrgMAAPcFADCvAwAA-AUAMAsxAADlBQAwMgAA6gUAMKcDAADmBQAwqAMAAOcFADCpAwAA6AUAIKoDAADpBQAwqwMAAOkFADCsAwAA6QUAMK0DAADpBQAwrgMAAOsFADCvAwAA7AUAMAcDAADkBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABywICAAAAAcwCQAAAAAECAAAAQQAgMQAA8AUAIAMAAABBACAxAADwBQAgMgAA7wUAIAEqAAC3CAAwDAMAAKAEACAHAACkBAAgKgAAogQAIK0CAACjBAAwrgIAAD8AEK8CAACjBAAwsAIBAAAAAbYCQAD_AwAhyQIBAPwDACHKAgEA_gMAIcsCAgCdBAAhzAJAAP8DACECAAAAQQAgKgAA7wUAIAIAAADtBQAgKgAA7gUAIAoqAACiBAAgrQIAAOwFADCuAgAA7QUAEK8CAADsBQAwsAIBAPwDACG2AkAA_wMAIckCAQD8AwAhygIBAP4DACHLAgIAnQQAIcwCQAD_AwAhCioAAKIEACCtAgAA7AUAMK4CAADtBQAQrwIAAOwFADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHKAgEA_gMAIcsCAgCdBAAhzAJAAP8DACEGKoAAAAABsAIBANYEACG2AkAA1wQAIckCAQDWBAAhywICAOAEACHMAkAA1wQAIQcDAADiBAAgKoAAAAABsAIBANYEACG2AkAA1wQAIckCAQDWBAAhywICAOAEACHMAkAA1wQAIQcDAADkBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABywICAAAAAcwCQAAAAAEMAwAA8AQAILACAQAAAAG2AkAAAAAByQIBAAAAAc0CAgAAAAHPAgAAAM8CAtACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QIBAAAAAQIAAAA8ACAxAAD8BQAgAwAAADwAIDEAAPwFACAyAAD7BQAgASoAALYIADARAwAAqQQAIAcAAKgEACCtAgAApQQAMK4CAAA6ABCvAgAApQQAMLACAQAAAAG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQIAAAA8ACAqAAD7BQAgAgAAAPkFACAqAAD6BQAgD60CAAD4BQAwrgIAAPkFABCvAgAA-AUAMLACAQD8AwAhtgJAAP8DACHJAgEA_gMAIcoCAQD8AwAhzQICAP0DACHPAgAApgTPAiLQAgEA_gMAIdECAQD-AwAh0gIBAP4DACHTAgEA_gMAIdQCAACnBAAg1QIBAP4DACEPrQIAAPgFADCuAgAA-QUAEK8CAAD4BQAwsAIBAPwDACG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQuwAgEA1gQAIbYCQADXBAAhyQIBAOEEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAMAAO4EACCwAgEA1gQAIbYCQADXBAAhyQIBAOEEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAMAAPAEACCwAgEAAAABtgJAAAAAAckCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEDAwAA9wQAILYCQAAAAAHJAgEAAAABAgAAADgAIDEAAIgGACADAAAAOAAgMQAAiAYAIDIAAIcGACABKgAAtQgAMAkDAACgBAAgBwAAqAQAIK0CAACrBAAwrgIAADYAEK8CAACrBAAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAhoAMAAKoEACACAAAAOAAgKgAAhwYAIAIAAACFBgAgKgAAhgYAIAatAgAAhAYAMK4CAACFBgAQrwIAAIQGADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACEGrQIAAIQGADCuAgAAhQYAEK8CAACEBgAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAhArYCQADXBAAhyQIBANYEACEDAwAA9QQAILYCQADXBAAhyQIBANYEACEDAwAA9wQAILYCQAAAAAHJAgEAAAABBg8AAKcFACCwAgEAAAABtgJAAAAAAc8CAAAA5AIC4QICAAAAAeICAQAAAAECAAAAJAAgMQAAkQYAIAMAAAAkACAxAACRBgAgMgAAkAYAIAEqAAC0CAAwAgAAACQAICoAAJAGACACAAAAwQUAICoAAI8GACAFsAIBANYEACG2AkAA1wQAIc8CAACjBeQCIuECAgDgBAAh4gIBANYEACEGDwAApQUAILACAQDWBAAhtgJAANcEACHPAgAAowXkAiLhAgIA4AQAIeICAQDWBAAhBg8AAKcFACCwAgEAAAABtgJAAAAAAc8CAAAA5AIC4QICAAAAAeICAQAAAAEFFwAA_wQAILACAQAAAAG2AkAAAAAB1gIBAAAAAdgCAAAA2AICAgAAADIAIDEAAJ0GACADAAAAMgAgMQAAnQYAIDIAAJwGACABKgAAswgAMAsHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAAAAAbYCQAD_AwAhygIBAPwDACHWAgEA_gMAIdgCAACuBNgCIqEDAACsBAAgAgAAADIAICoAAJwGACACAAAAmgYAICoAAJsGACAIrQIAAJkGADCuAgAAmgYAEK8CAACZBgAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIIrQIAAJkGADCuAgAAmgYAEK8CAACZBgAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIEsAIBANYEACG2AkAA1wQAIdYCAQDhBAAh2AIAAPsE2AIiBRcAAP0EACCwAgEA1gQAIbYCQADXBAAh1gIBAOEEACHYAgAA-wTYAiIFFwAA_wQAILACAQAAAAG2AkAAAAAB1gIBAAAAAdgCAAAA2AICBAMAAIcFACC2AkAAAAAByQIBAAAAAdoCAAAA2gICAgAAABMAIDEAAKkGACADAAAAEwAgMQAAqQYAIDIAAKgGACABKgAAsggAMAoDAACgBAAgBwAAqAQAIK0CAADEBAAwrgIAABEAEK8CAADEBAAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAh2gIAAMUE2gIioAMAAMMEACACAAAAEwAgKgAAqAYAIAIAAACmBgAgKgAApwYAIAetAgAApQYAMK4CAACmBgAQrwIAAKUGADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACHaAgAAxQTaAiIHrQIAAKUGADCuAgAApgYAEK8CAAClBgAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAh2gIAAMUE2gIiA7YCQADXBAAhyQIBANYEACHaAgAAgwXaAiIEAwAAhQUAILYCQADXBAAhyQIBANYEACHaAgAAgwXaAiIEAwAAhwUAILYCQAAAAAHJAgEAAAAB2gIAAADaAgIOCAAAtgYAIAkAALcGACAOAAC4BgAgEAAAuQYAILYCQAAAAAHNAgIAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAekCAQAAAAHqAgEAAAAB6wIBAAAAAewCQAAAAAECAAAALQAgMQAAtQYAIAMAAAAtACAxAAC1BgAgMgAAtAYAIAEqAACxCAAwFAcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhogMAAK8EACACAAAALQAgKgAAtAYAIAIAAACyBgAgKgAAswYAIA6tAgAAsQYAMK4CAACyBgAQrwIAALEGADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhDq0CAACxBgAwrgIAALIGABCvAgAAsQYAMLYCQAD_AwAhygIBAPwDACHNAgIAnQQAIeUCAQD8AwAh5gIBAP4DACHnAgEA_gMAIegCAQD-AwAh6QIBAPwDACHqAgEA_gMAIesCAQD-AwAh7AJAAJ8EACEKtgJAANcEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACEOCAAAtQUAIAkAALYFACAOAAC3BQAgEAAAuAUAILYCQADXBAAhzQICAOAEACHlAgEA1gQAIeYCAQDhBAAh5wIBAOEEACHoAgEA4QQAIekCAQDWBAAh6gIBAOEEACHrAgEA4QQAIewCQADYBAAhDggAALYGACAJAAC3BgAgDgAAuAYAIBAAALkGACC2AkAAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABAzEAALoGACCnAwAAuwYAIK0DAAAaACAEMQAAzgUAMKcDAADPBQAwqQMAANEFACCtAwAA0gUAMAQxAADFBQAwpwMAAMYFADCpAwAAyAUAIK0DAACSBQAwBDEAALkFADCnAwAAugUAMKkDAAC8BQAgrQMAAL0FADAXEgAAvAYAIBMAAL0GACAUAAC-BgAgFQAAvwYAIBYAAMAGACAYAADBBgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILYCQAAAAAHMAkAAAAAB2wICAAAAAe4CAQAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABAgAAABoAIDEAALoGACADMQAArwgAIKcDAACwCAAgrQMAABoAIAQxAADGBgAwpwMAAMcGADCpAwAAyAYAIK0DAADSBQAwAzEAAKcIACCnAwAAqAgAIK0DAAAtACAEMQAAqgYAMKcDAACrBgAwqQMAAK0GACCtAwAArgYAMAQxAACeBgAwpwMAAJ8GADCpAwAAoQYAIK0DAACiBgAwBDEAAJIGADCnAwAAkwYAMKkDAACVBgAgrQMAAJYGADAEMQAAiQYAMKcDAACKBgAwqQMAAIwGACCtAwAAvQUAMAQxAAD9BQAwpwMAAP4FADCpAwAAgAYAIK0DAACBBgAwBDEAAPEFADCnAwAA8gUAMKkDAAD0BQAgrQMAAPUFADAEMQAA5QUAMKcDAADmBQAwqQMAAOgFACCtAwAA6QUAMBgRAADKBgAgEwAAvQYAIBQAAL4GACAVAAC_BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABAgAAABoAIDEAAMkGACABKgAArggAMBgRAADKBgAgEwAAvQYAIBQAAL4GACAVAAC_BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABAzEAAKwIACCnAwAArQgAIK0DAAAtACADAAAAGgAgMQAAyQYAIDIAAM8GACACAAAAGgAgKgAAzwYAIAIAAADWBQAgKgAAzgYAIA6wAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIRgRAADbBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEHMQAApwgAIDIAAKoIACCnAwAAqAgAIKgDAACpCAAgqwMAABUAIKwDAAAVACCtAwAALQAgFxEAAMoGACASAAC8BgAgEwAAvQYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgGwAAxAYAIBwAAMUGACCwAgEAAAABtgJAAAAAAcwCQAAAAAHbAgIAAAAB7QICAAAAAfECAAAA8QIC8gIgAAAAAfMCIAAAAAH0AgIAAAAB9QICAAAAAfYCAgAAAAH3AgIAAAAB-AJAAAAAAQMAAAAXACAxAAC6BgAgMgAA1AYAIBkAAAAXACASAADcBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAA1AYAILYCQADXBAAhzAJAANcEACHbAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIRcSAADcBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhAzEAAKUIACCnAwAApggAIK0DAAAaACAAAAAAAAAAAAAABTEAAKAIACAyAACjCAAgpwMAAKEIACCoAwAAoggAIK0DAAABACADMQAAoAgAIKcDAAChCAAgrQMAAAEAIAAAAAcxAACbCAAgMgAAnggAIKcDAACcCAAgqAMAAJ0IACCrAwAADwAgrAMAAA8AIK0DAAABACADMQAAmwgAIKcDAACcCAAgrQMAAAEAIAAAAAUxAACWCAAgMgAAmQgAIKcDAACXCAAgqAMAAJgIACCtAwAAAQAgAzEAAJYIACCnAwAAlwgAIK0DAAABACAAAAAFMQAAkQgAIDIAAJQIACCnAwAAkggAIKgDAACTCAAgrQMAAAEAIAMxAACRCAAgpwMAAJIIACCtAwAAAQAgAAAAAAABqgMAAACTAwIBqgMAAACVAwIBqgMgAAAAAQsxAADgBwAwMgAA5QcAMKcDAADhBwAwqAMAAOIHADCpAwAA4wcAIKoDAADkBwAwqwMAAOQHADCsAwAA5AcAMK0DAADkBwAwrgMAAOYHADCvAwAA5wcAMAsxAADUBwAwMgAA2QcAMKcDAADVBwAwqAMAANYHADCpAwAA1wcAIKoDAADYBwAwqwMAANgHADCsAwAA2AcAMK0DAADYBwAwrgMAANoHADCvAwAA2wcAMAsxAADIBwAwMgAAzQcAMKcDAADJBwAwqAMAAMoHADCpAwAAywcAIKoDAADMBwAwqwMAAMwHADCsAwAAzAcAMK0DAADMBwAwrgMAAM4HADCvAwAAzwcAMAsxAAC_BwAwMgAAwwcAMKcDAADABwAwqAMAAMEHADCpAwAAwgcAIKoDAACiBgAwqwMAAKIGADCsAwAAogYAMK0DAACiBgAwrgMAAMQHADCvAwAApQYAMAsxAAC2BwAwMgAAugcAMKcDAAC3BwAwqAMAALgHADCpAwAAuQcAIKoDAACWBgAwqwMAAJYGADCsAwAAlgYAMK0DAACWBgAwrgMAALsHADCvAwAAmQYAMAsxAACqBwAwMgAArwcAMKcDAACrBwAwqAMAAKwHADCpAwAArQcAIKoDAACuBwAwqwMAAK4HADCsAwAArgcAMK0DAACuBwAwrgMAALAHADCvAwAAsQcAMAsxAAChBwAwMgAApQcAMKcDAACiBwAwqAMAAKMHADCpAwAApAcAIKoDAACBBgAwqwMAAIEGADCsAwAAgQYAMK0DAACBBgAwrgMAAKYHADCvAwAAhAYAMAsxAACYBwAwMgAAnAcAMKcDAACZBwAwqAMAAJoHADCpAwAAmwcAIKoDAAD1BQAwqwMAAPUFADCsAwAA9QUAMK0DAAD1BQAwrgMAAJ0HADCvAwAA-AUAMAsxAACPBwAwMgAAkwcAMKcDAACQBwAwqAMAAJEHADCpAwAAkgcAIKoDAADpBQAwqwMAAOkFADCsAwAA6QUAMK0DAADpBQAwrgMAAJQHADCvAwAA7AUAMAsxAACDBwAwMgAAiAcAMKcDAACEBwAwqAMAAIUHADCpAwAAhgcAIKoDAACHBwAwqwMAAIcHADCsAwAAhwcAMK0DAACHBwAwrgMAAIkHADCvAwAAigcAMAqwAgEAAAABtgJAAAAAAdwCAQAAAAH5AgEAAAAB-gIBAAAAAfsCAgAAAAH8AgEAAAAB_QIgAAAAAf4CAQAAAAH_AgEAAAABAgAAAFYAIDEAAI4HACADAAAAVgAgMQAAjgcAIDIAAI0HACABKgAAkAgAMA8DAACgBAAgrQIAAJwEADCuAgAAVAAQrwIAAJwEADCwAgEAAAABtgJAAJ8EACHJAgEA_AMAIdwCAQD-AwAh-QIBAPwDACH6AgEA_AMAIfsCAgCdBAAh_AIBAPwDACH9AiAAngQAIf4CAQD-AwAh_wIBAP4DACECAAAAVgAgKgAAjQcAIAIAAACLBwAgKgAAjAcAIA6tAgAAigcAMK4CAACLBwAQrwIAAIoHADCwAgEA_AMAIbYCQACfBAAhyQIBAPwDACHcAgEA_gMAIfkCAQD8AwAh-gIBAPwDACH7AgIAnQQAIfwCAQD8AwAh_QIgAJ4EACH-AgEA_gMAIf8CAQD-AwAhDq0CAACKBwAwrgIAAIsHABCvAgAAigcAMLACAQD8AwAhtgJAAJ8EACHJAgEA_AMAIdwCAQD-AwAh-QIBAPwDACH6AgEA_AMAIfsCAgCdBAAh_AIBAPwDACH9AiAAngQAIf4CAQD-AwAh_wIBAP4DACEKsAIBANYEACG2AkAA2AQAIdwCAQDhBAAh-QIBANYEACH6AgEA1gQAIfsCAgDgBAAh_AIBANYEACH9AiAA2QUAIf4CAQDhBAAh_wIBAOEEACEKsAIBANYEACG2AkAA2AQAIdwCAQDhBAAh-QIBANYEACH6AgEA1gQAIfsCAgDgBAAh_AIBANYEACH9AiAA2QUAIf4CAQDhBAAh_wIBAOEEACEKsAIBAAAAAbYCQAAAAAHcAgEAAAAB-QIBAAAAAfoCAQAAAAH7AgIAAAAB_AIBAAAAAf0CIAAAAAH-AgEAAAAB_wIBAAAAAQcHAADlBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHKAgEAAAABywICAAAAAcwCQAAAAAECAAAAQQAgMQAAlwcAIAMAAABBACAxAACXBwAgMgAAlgcAIAEqAACPCAAwAgAAAEEAICoAAJYHACACAAAA7QUAICoAAJUHACAGKoAAAAABsAIBANYEACG2AkAA1wQAIcoCAQDhBAAhywICAOAEACHMAkAA1wQAIQcHAADjBAAgKoAAAAABsAIBANYEACG2AkAA1wQAIcoCAQDhBAAhywICAOAEACHMAkAA1wQAIQcHAADlBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHKAgEAAAABywICAAAAAcwCQAAAAAEMBwAA7wQAILACAQAAAAG2AkAAAAABygIBAAAAAc0CAgAAAAHPAgAAAM8CAtACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QIBAAAAAQIAAAA8ACAxAACgBwAgAwAAADwAIDEAAKAHACAyAACfBwAgASoAAI4IADACAAAAPAAgKgAAnwcAIAIAAAD5BQAgKgAAngcAIAuwAgEA1gQAIbYCQADXBAAhygIBANYEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAcAAO0EACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAcAAO8EACCwAgEAAAABtgJAAAAAAcoCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEDBwAA9gQAILYCQAAAAAHKAgEAAAABAgAAADgAIDEAAKkHACADAAAAOAAgMQAAqQcAIDIAAKgHACABKgAAjQgAMAIAAAA4ACAqAACoBwAgAgAAAIUGACAqAACnBwAgArYCQADXBAAhygIBANYEACEDBwAA9AQAILYCQADXBAAhygIBANYEACEDBwAA9gQAILYCQAAAAAHKAgEAAAABB7ACAQAAAAGxAgEAAAABswIBAAAAAbQCAQAAAAG1AoAAAAABtgJAAAAAAbcCQAAAAAECAAAATwAgMQAAtQcAIAMAAABPACAxAAC1BwAgMgAAtAcAIAEqAACMCAAwDB8AAKAEACCtAgAAoQQAMK4CAABNABCvAgAAoQQAMLACAQAAAAGxAgEA_AMAIbICAQD8AwAhswIBAPwDACG0AgEA_AMAIbUCAACiBAAgtgJAAP8DACG3AkAAnwQAIQIAAABPACAqAAC0BwAgAgAAALIHACAqAACzBwAgC60CAACxBwAwrgIAALIHABCvAgAAsQcAMLACAQD8AwAhsQIBAPwDACGyAgEA_AMAIbMCAQD8AwAhtAIBAPwDACG1AgAAogQAILYCQAD_AwAhtwJAAJ8EACELrQIAALEHADCuAgAAsgcAEK8CAACxBwAwsAIBAPwDACGxAgEA_AMAIbICAQD8AwAhswIBAPwDACG0AgEA_AMAIbUCAACiBAAgtgJAAP8DACG3AkAAnwQAIQewAgEA1gQAIbECAQDWBAAhswIBANYEACG0AgEA1gQAIbUCgAAAAAG2AkAA1wQAIbcCQADYBAAhB7ACAQDWBAAhsQIBANYEACGzAgEA1gQAIbQCAQDWBAAhtQKAAAAAAbYCQADXBAAhtwJAANgEACEHsAIBAAAAAbECAQAAAAGzAgEAAAABtAIBAAAAAbUCgAAAAAG2AkAAAAABtwJAAAAAAQUHAAD-BAAgsAIBAAAAAbYCQAAAAAHKAgEAAAAB2AIAAADYAgICAAAAMgAgMQAAvgcAIAMAAAAyACAxAAC-BwAgMgAAvQcAIAEqAACLCAAwAgAAADIAICoAAL0HACACAAAAmgYAICoAALwHACAEsAIBANYEACG2AkAA1wQAIcoCAQDWBAAh2AIAAPsE2AIiBQcAAPwEACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHYAgAA-wTYAiIFBwAA_gQAILACAQAAAAG2AkAAAAABygIBAAAAAdgCAAAA2AICBAcAAIYFACC2AkAAAAABygIBAAAAAdoCAAAA2gICAgAAABMAIDEAAMcHACADAAAAEwAgMQAAxwcAIDIAAMYHACABKgAAiggAMAIAAAATACAqAADGBwAgAgAAAKYGACAqAADFBwAgA7YCQADXBAAhygIBANYEACHaAgAAgwXaAiIEBwAAhAUAILYCQADXBAAhygIBANYEACHaAgAAgwXaAiIEBwAAhgUAILYCQAAAAAHKAgEAAAAB2gIAAADaAgIGsAIBAAAAAbYCQAAAAAHMAkAAAAABgAMBAAAAAYEDAQAAAAGCA0AAAAABAgAAAA0AIDEAANMHACADAAAADQAgMQAA0wcAIDIAANIHACABKgAAiQgAMAsDAACpBAAgrQIAAM8EADCuAgAACwAQrwIAAM8EADCwAgEAAAABtgJAAJ8EACHJAgEA_gMAIcwCQACfBAAhgAMBAPwDACGBAwEA_AMAIYIDQAD_AwAhAgAAAA0AICoAANIHACACAAAA0AcAICoAANEHACAKrQIAAM8HADCuAgAA0AcAEK8CAADPBwAwsAIBAPwDACG2AkAAnwQAIckCAQD-AwAhzAJAAJ8EACGAAwEA_AMAIYEDAQD8AwAhggNAAP8DACEKrQIAAM8HADCuAgAA0AcAEK8CAADPBwAwsAIBAPwDACG2AkAAnwQAIckCAQD-AwAhzAJAAJ8EACGAAwEA_AMAIYEDAQD8AwAhggNAAP8DACEGsAIBANYEACG2AkAA2AQAIcwCQADYBAAhgAMBANYEACGBAwEA1gQAIYIDQADXBAAhBrACAQDWBAAhtgJAANgEACHMAkAA2AQAIYADAQDWBAAhgQMBANYEACGCA0AA1wQAIQawAgEAAAABtgJAAAAAAcwCQAAAAAGAAwEAAAABgQMBAAAAAYIDQAAAAAEIsAIBAAAAAbYCQAAAAAHMAkAAAAAB0gIBAAAAAYIDQAAAAAGDAwEAAAABhAMBAAAAAYUDAQAAAAECAAAACQAgMQAA3wcAIAMAAAAJACAxAADfBwAgMgAA3gcAIAEqAACICAAwDQMAAKAEACCtAgAA0AQAMK4CAAAHABCvAgAA0AQAMLACAQAAAAG2AkAA_wMAIckCAQD8AwAhzAJAAP8DACHSAgEA_gMAIYIDQAD_AwAhgwMBAAAAAYQDAQD-AwAhhQMBAP4DACECAAAACQAgKgAA3gcAIAIAAADcBwAgKgAA3QcAIAytAgAA2wcAMK4CAADcBwAQrwIAANsHADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIdICAQD-AwAhggNAAP8DACGDAwEA_AMAIYQDAQD-AwAhhQMBAP4DACEMrQIAANsHADCuAgAA3AcAEK8CAADbBwAwsAIBAPwDACG2AkAA_wMAIckCAQD8AwAhzAJAAP8DACHSAgEA_gMAIYIDQAD_AwAhgwMBAPwDACGEAwEA_gMAIYUDAQD-AwAhCLACAQDWBAAhtgJAANcEACHMAkAA1wQAIdICAQDhBAAhggNAANcEACGDAwEA1gQAIYQDAQDhBAAhhQMBAOEEACEIsAIBANYEACG2AkAA1wQAIcwCQADXBAAh0gIBAOEEACGCA0AA1wQAIYMDAQDWBAAhhAMBAOEEACGFAwEA4QQAIQiwAgEAAAABtgJAAAAAAcwCQAAAAAHSAgEAAAABggNAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAQywAgEAAAABtgJAAAAAAcwCQAAAAAGGAwEAAAABhwMBAAAAAYgDAQAAAAGJAwEAAAABigNAAAAAAYsDQAAAAAGMAwEAAAABjQMBAAAAAY4DAQAAAAECAAAABQAgMQAA6wcAIAMAAAAFACAxAADrBwAgMgAA6gcAIAEqAACHCAAwEQMAAKAEACCtAgAA0QQAMK4CAAADABCvAgAA0QQAMLACAQAAAAG2AkAA_wMAIckCAQD8AwAhzAJAAP8DACGGAwEA_AMAIYcDAQD8AwAhiAMBAP4DACGJAwEA_gMAIYoDQACfBAAhiwNAAJ8EACGMAwEA_gMAIY0DAQD-AwAhjgMBAP4DACECAAAABQAgKgAA6gcAIAIAAADoBwAgKgAA6QcAIBCtAgAA5wcAMK4CAADoBwAQrwIAAOcHADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIYYDAQD8AwAhhwMBAPwDACGIAwEA_gMAIYkDAQD-AwAhigNAAJ8EACGLA0AAnwQAIYwDAQD-AwAhjQMBAP4DACGOAwEA_gMAIRCtAgAA5wcAMK4CAADoBwAQrwIAAOcHADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIYYDAQD8AwAhhwMBAPwDACGIAwEA_gMAIYkDAQD-AwAhigNAAJ8EACGLA0AAnwQAIYwDAQD-AwAhjQMBAP4DACGOAwEA_gMAIQywAgEA1gQAIbYCQADXBAAhzAJAANcEACGGAwEA1gQAIYcDAQDWBAAhiAMBAOEEACGJAwEA4QQAIYoDQADYBAAhiwNAANgEACGMAwEA4QQAIY0DAQDhBAAhjgMBAOEEACEMsAIBANYEACG2AkAA1wQAIcwCQADXBAAhhgMBANYEACGHAwEA1gQAIYgDAQDhBAAhiQMBAOEEACGKA0AA2AQAIYsDQADYBAAhjAMBAOEEACGNAwEA4QQAIY4DAQDhBAAhDLACAQAAAAG2AkAAAAABzAJAAAAAAYYDAQAAAAGHAwEAAAABiAMBAAAAAYkDAQAAAAGKA0AAAAABiwNAAAAAAYwDAQAAAAGNAwEAAAABjgMBAAAAAQQxAADgBwAwpwMAAOEHADCpAwAA4wcAIK0DAADkBwAwBDEAANQHADCnAwAA1QcAMKkDAADXBwAgrQMAANgHADAEMQAAyAcAMKcDAADJBwAwqQMAAMsHACCtAwAAzAcAMAQxAAC_BwAwpwMAAMAHADCpAwAAwgcAIK0DAACiBgAwBDEAALYHADCnAwAAtwcAMKkDAAC5BwAgrQMAAJYGADAEMQAAqgcAMKcDAACrBwAwqQMAAK0HACCtAwAArgcAMAQxAAChBwAwpwMAAKIHADCpAwAApAcAIK0DAACBBgAwBDEAAJgHADCnAwAAmQcAMKkDAACbBwAgrQMAAPUFADAEMQAAjwcAMKcDAACQBwAwqQMAAJIHACCtAwAA6QUAMAQxAACDBwAwpwMAAIQHADCpAwAAhgcAIK0DAACHBwAwAAAAAAAAAAAAABkEAAD2BwAgBQAA9wcAIAYAAPgHACAdAAD5BwAgHgAA-gcAICAAAPsHACAhAAD8BwAgIgAA_QcAICMAAP4HACAkAAD_BwAg2gIAANIEACDbAgAA0gQAINwCAADSBAAg-AIAANIEACCPAwAA0gQAIJEDAADSBAAglwMAANIEACCYAwAA0gQAIJkDAADSBAAgmgMAANIEACCbAwAA0gQAIJwDAADSBAAgnQMAANIEACCeAwAA0gQAIJ8DAADSBAAgEBEAAIQIACASAACBCAAgEwAAgggAIBQAAIQIACAVAACGCAAgFgAA-QcAIBgAAPoHACAZAACDCAAgGgAA_AcAIBsAAP0HACAcAAD-BwAg2wIAANIEACDtAgAA0gQAIO4CAADSBAAg7wIAANIEACD4AgAA0gQAIAAACwcAAIEIACAIAACBCAAgCQAAgggAIA4AAJ0FACAQAACDCAAg5gIAANIEACDnAgAA0gQAIOgCAADSBAAg6gIAANIEACDrAgAA0gQAIOwCAADSBAAgAwsAAJ0FACDbAgAA0gQAIN0CAADSBAAgAAywAgEAAAABtgJAAAAAAcwCQAAAAAGGAwEAAAABhwMBAAAAAYgDAQAAAAGJAwEAAAABigNAAAAAAYsDQAAAAAGMAwEAAAABjQMBAAAAAY4DAQAAAAEIsAIBAAAAAbYCQAAAAAHMAkAAAAAB0gIBAAAAAYIDQAAAAAGDAwEAAAABhAMBAAAAAYUDAQAAAAEGsAIBAAAAAbYCQAAAAAHMAkAAAAABgAMBAAAAAYEDAQAAAAGCA0AAAAABA7YCQAAAAAHKAgEAAAAB2gIAAADaAgIEsAIBAAAAAbYCQAAAAAHKAgEAAAAB2AIAAADYAgIHsAIBAAAAAbECAQAAAAGzAgEAAAABtAIBAAAAAbUCgAAAAAG2AkAAAAABtwJAAAAAAQK2AkAAAAABygIBAAAAAQuwAgEAAAABtgJAAAAAAcoCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEGKoAAAAABsAIBAAAAAbYCQAAAAAHKAgEAAAABywICAAAAAcwCQAAAAAEKsAIBAAAAAbYCQAAAAAHcAgEAAAAB-QIBAAAAAfoCAQAAAAH7AgIAAAAB_AIBAAAAAf0CIAAAAAH-AgEAAAAB_wIBAAAAAR8FAADtBwAgBgAA7gcAIB0AAO8HACAeAADwBwAgIAAA8QcAICEAAPIHACAiAADzBwAgIwAA9AcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAkQgAIAMAAAAPACAxAACRCAAgMgAAlQgAICEAAAAPACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAACVCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAADsBwAgBgAA7gcAIB0AAO8HACAeAADwBwAgIAAA8QcAICEAAPIHACAiAADzBwAgIwAA9AcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAlggAIAMAAAAPACAxAACWCAAgMgAAmggAICEAAAAPACAEAAD5BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAACaCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAADsBwAgBQAA7QcAIB0AAO8HACAeAADwBwAgIAAA8QcAICEAAPIHACAiAADzBwAgIwAA9AcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAmwgAIAMAAAAPACAxAACbCAAgMgAAnwgAICEAAAAPACAEAAD5BgAgBQAA-gYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAACfCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAADsBwAgBQAA7QcAIAYAAO4HACAdAADvBwAgHgAA8AcAICAAAPEHACAhAADyBwAgIgAA8wcAICMAAPQHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAoAgAIAMAAAAPACAxAACgCAAgMgAApAgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAhAAD_BgAgIgAAgAcAICMAAIEHACAqAACkCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIRkRAADKBgAgEgAAvAYAIBMAAL0GACAUAAC-BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHuAgEAAAAB7wICAAAAAfECAAAA8QIC8gIgAAAAAfMCIAAAAAH0AgIAAAAB9QICAAAAAfYCAgAAAAH3AgIAAAAB-AJAAAAAAQIAAAAaACAxAAClCAAgDwcAANUGACAIAAC2BgAgDgAAuAYAIBAAALkGACC2AkAAAAABygIBAAAAAc0CAgAAAAHlAgEAAAAB5gIBAAAAAecCAQAAAAHoAgEAAAAB6QIBAAAAAeoCAQAAAAHrAgEAAAAB7AJAAAAAAQIAAAAtACAxAACnCAAgAwAAABUAIDEAAKcIACAyAACrCAAgEQAAABUAIAcAALQFACAIAAC1BQAgDgAAtwUAIBAAALgFACAqAACrCAAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQ8HAAC0BQAgCAAAtQUAIA4AALcFACAQAAC4BQAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQ8HAADVBgAgCQAAtwYAIA4AALgGACAQAAC5BgAgtgJAAAAAAcoCAQAAAAHNAgIAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAekCAQAAAAHqAgEAAAAB6wIBAAAAAewCQAAAAAECAAAALQAgMQAArAgAIA6wAgEAAAABtgJAAAAAAcwCQAAAAAHbAgIAAAAB7QICAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAEZEQAAygYAIBIAALwGACAUAAC-BgAgFQAAvwYAIBYAAMAGACAYAADBBgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAArwgAIAq2AkAAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABA7YCQAAAAAHJAgEAAAAB2gIAAADaAgIEsAIBAAAAAbYCQAAAAAHWAgEAAAAB2AIAAADYAgIFsAIBAAAAAbYCQAAAAAHPAgAAAOQCAuECAgAAAAHiAgEAAAABArYCQAAAAAHJAgEAAAABC7ACAQAAAAG2AkAAAAAByQIBAAAAAc0CAgAAAAHPAgAAAM8CAtACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QIBAAAAAQYqgAAAAAGwAgEAAAABtgJAAAAAAckCAQAAAAHLAgIAAAABzAJAAAAAAQMAAAAXACAxAACvCAAgMgAAuggAIBsAAAAXACARAADbBQAgEgAA3AUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAAuggAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEDAAAAFQAgMQAArAgAIDIAAL0IACARAAAAFQAgBwAAtAUAIAkAALYFACAOAAC3BQAgEAAAuAUAICoAAL0IACC2AkAA1wQAIcoCAQDWBAAhzQICAOAEACHlAgEA1gQAIeYCAQDhBAAh5wIBAOEEACHoAgEA4QQAIekCAQDWBAAh6gIBAOEEACHrAgEA4QQAIewCQADYBAAhDwcAALQFACAJAAC2BQAgDgAAtwUAIBAAALgFACC2AkAA1wQAIcoCAQDWBAAhzQICAOAEACHlAgEA1gQAIeYCAQDhBAAh5wIBAOEEACHoAgEA4QQAIekCAQDWBAAh6gIBAOEEACHrAgEA4QQAIewCQADYBAAhDbACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABArYCQAAAAAHkAgEAAAABBLACAQAAAAG2AkAAAAABzwIAAADkAgLiAgEAAAABAwAAABcAIDEAAKUIACAyAADDCAAgGwAAABcAIBEAANsFACASAADcBQAgEwAA3QUAIBQAANAGACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAIBwAAOQFACAqAADDCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIRkRAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIQWwAgEAAAABtgJAAAAAAdsCAgAAAAHcAgEAAAAB3QIBAAAAAQIAAACwAgAgMQAAxAgAIAMAAACzAgAgMQAAxAgAIDIAAMgIACAHAAAAswIAICoAAMgIACCwAgEA1gQAIbYCQADXBAAh2wICAOsEACHcAgEA1gQAId0CAQDhBAAhBbACAQDWBAAhtgJAANcEACHbAgIA6wQAIdwCAQDWBAAh3QIBAOEEACEPBwAA1QYAIAgAALYGACAJAAC3BgAgDgAAuAYAILYCQAAAAAHKAgEAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABAgAAAC0AIDEAAMkIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAAywgAIAMAAAAVACAxAADJCAAgMgAAzwgAIBEAAAAVACAHAAC0BQAgCAAAtQUAIAkAALYFACAOAAC3BQAgKgAAzwgAILYCQADXBAAhygIBANYEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACEPBwAAtAUAIAgAALUFACAJAAC2BQAgDgAAtwUAILYCQADXBAAhygIBANYEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACEDAAAAFwAgMQAAywgAIDIAANIIACAbAAAAFwAgEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBoAAOIFACAbAADjBQAgHAAA5AUAICoAANIIACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhGREAANsFACASAADcBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAaAADiBQAgGwAA4wUAIBwAAOQFACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhDwcAANUGACAIAAC2BgAgCQAAtwYAIBAAALkGACC2AkAAAAABygIBAAAAAc0CAgAAAAHlAgEAAAAB5gIBAAAAAecCAQAAAAHoAgEAAAAB6QIBAAAAAeoCAQAAAAHrAgEAAAAB7AJAAAAAAQIAAAAtACAxAADTCAAgAwAAABUAIDEAANMIACAyAADXCAAgEQAAABUAIAcAALQFACAIAAC1BQAgCQAAtgUAIBAAALgFACAqAADXCAAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQ8HAAC0BQAgCAAAtQUAIAkAALYFACAQAAC4BQAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQO2AkAAAAABygIBAAAAAc0CAgAAAAEfBAAA7AcAIAUAAO0HACAGAADuBwAgHgAA8AcAICAAAPEHACAhAADyBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAANkIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAYAADBBgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA2wgAIAMAAAAPACAxAADZCAAgMgAA3wgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAADfCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAADbCAAgMgAA4ggAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAA4ggAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAYAADgBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAICAAAPEHACAhAADyBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAOMIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA5QgAIAMAAAAPACAxAADjCAAgMgAA6QgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAADpCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAADlCAAgMgAA7AgAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAA7AgAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAgAADxBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAO0IACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA7wgAIAMAAAAPACAxAADtCAAgMgAA8wgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAiAACABwAgIwAAgQcAICQAAIIHACAqAADzCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAADvCAAgMgAA9ggAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBsAAOMFACAcAADkBQAgKgAA9ggAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAgAADxBwAgIQAA8gcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAPcIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA-QgAIAMAAAAPACAxAAD3CAAgMgAA_QgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAhAAD_BgAgIwAAgQcAICQAAIIHACAqAAD9CAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAAD5CAAgMgAAgAkAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBoAAOIFACAcAADkBQAgKgAAgAkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgGwAAxAYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAAgQkAIB8EAADsBwAgBQAA7QcAIAYAAO4HACAdAADvBwAgHgAA8AcAICAAAPEHACAhAADyBwAgIgAA8wcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAgwkAIAMAAAAXACAxAACBCQAgMgAAhwkAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgKgAAhwkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEDAAAADwAgMQAAgwkAIDIAAIoJACAhAAAADwAgBAAA-QYAIAUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAkAACCBwAgKgAAigkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAhAAD_BgAgIgAAgAcAICQAAIIHACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHaAgEA4QQAIdsCAgDrBAAh3AIBAOEEACH4AkAA2AQAIY8DAQDhBAAhkAMgANkFACGRAwEA4QQAIZMDAAD2BpMDIpUDAAD3BpUDIpYDIADZBQAhlwMBAOEEACGYAwEA4QQAIZkDgAAAAAGaA0AA2AQAIZsDAQDhBAAhnAMgAPgGACGdAwEA4QQAIZ4DQADYBAAhnwNAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAhAADyBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAIsJACADAAAADwAgMQAAiwkAIDIAAI8JACAhAAAADwAgBAAA-QYAIAUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAhAAD_BgAgIgAAgAcAICMAAIEHACAkAACCBwAgKgAAjwkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHaAgEA4QQAIdsCAgDrBAAh3AIBAOEEACH4AkAA2AQAIY8DAQDhBAAhkAMgANkFACGRAwEA4QQAIZMDAAD2BpMDIpUDAAD3BpUDIpYDIADZBQAhlwMBAOEEACGYAwEA4QQAIZkDgAAAAAGaA0AA2AQAIZsDAQDhBAAhnAMgAPgGACGdAwEA4QQAIZ4DQADYBAAhnwNAANgEACELBAYCBQoDBg4EDAAUHRQFHkwNIFASIVEOIlIPI1MQJFcTAQMAAQEDAAEBAxABAgMAAQcABgwMABERFgcSKQYTKgYUKwcVLgcWLwUYMw0ZNQsaOQ4bPQ8cQhAGBwAGCBgGCRsGDAAMDh8IECULAgoABw0ACQILIAgMAAoBCyEAAgcABg8ABwMJJgAOJwAQKAACBwAGFzQBAgMAAQcABgIDPgEHAAYCAwABB0MGCBNEABVFABZGABhHABlIABpJABtKABxLAAEfAAEBAwABCgRYAAVZAAZaAB1bAB5cACBdACFeACJfACNgACRhAAAAAAUMABk3ABo4ABs5ABw6AB0AAAAAAAUMABk3ABo4ABs5ABw6AB0BAwABAQMAAQMMACI5ACM6ACQAAAADDAAiOQAjOgAkAQMAAQEDAAEDDAApOQAqOgArAAAAAwwAKTkAKjoAKwEDrgEBAQO0AQEDDAAwOQAxOgAyAAAAAwwAMDkAMToAMgEDAAEBAwABBQwANzcAODgAOTkAOjoAOwAAAAAABQwANzcAODgAOTkAOjoAOwMR3AEHEt0BBhTeAQcDEeQBBxLlAQYU5gEHBQwAQDcAQTgAQjkAQzoARAAAAAAABQwAQDcAQTgAQjkAQzoARAEHAAYBBwAGBQwASTcASjgASzkATDoATQAAAAAABQwASTcASjgASzkATDoATQIKAAcNAAkCCgAHDQAJBQwAUjcAUzgAVDkAVToAVgAAAAAABQwAUjcAUzgAVDkAVToAVgIHAAYPAAcCBwAGDwAHBQwAWzcAXDgAXTkAXjoAXwAAAAAABQwAWzcAXDgAXTkAXjoAXwAABQwAZDcAZTgAZjkAZzoAaAAAAAAABQwAZDcAZTgAZjkAZzoAaAIDAAEHAAYCAwABBwAGAwwAbTkAbjoAbwAAAAMMAG05AG46AG8CBwAGF-kCAQIHAAYX7wIBAwwAdDkAdToAdgAAAAMMAHQ5AHU6AHYCAwABBwAGAgMAAQcABgMMAHs5AHw6AH0AAAADDAB7OQB8OgB9AgOXAwEHAAYCA50DAQcABgUMAIIBNwCDATgAhAE5AIUBOgCGAQAAAAAABQwAggE3AIMBOACEATkAhQE6AIYBAgMAAQevAwYCAwABB7UDBgUMAIsBNwCMATgAjQE5AI4BOgCPAQAAAAAABQwAiwE3AIwBOACNATkAjgE6AI8BAR8AAQEfAAEDDACUATkAlQE6AJYBAAAAAwwAlAE5AJUBOgCWASUCASZiASdkAShlASlmAStoASxqFS1rFi5tAS9vFTBwFzNxATRyATVzFTt2GDx3Hj14Aj55Aj96AkB7AkF8AkJ-AkOAARVEgQEfRYMBAkaFARVHhgEgSIcBAkmIAQJKiQEVS4wBIUyNASVNjgEDTo8BA0-QAQNQkQEDUZIBA1KUAQNTlgEVVJcBJlWZAQNWmwEVV5wBJ1idAQNZngEDWp8BFVuiAShcowEsXaQBBF6lAQRfpgEEYKcBBGGoAQRiqgEEY6wBFWStAS1lsAEEZrIBFWezAS5otQEEabYBBGq3ARVrugEvbLsBM228ARNuvQETb74BE3C_ARNxwAETcsIBE3PEARV0xQE0dccBE3bJARV3ygE1eMsBE3nMARN6zQEVe9ABNnzRATx90gEGftMBBn_UAQaAAdUBBoEB1gEGggHYAQaDAdoBFYQB2wE9hQHgAQaGAeIBFYcB4wE-iAHnAQaJAegBBooB6QEViwHsAT-MAe0BRY0B7gEHjgHvAQePAfABB5AB8QEHkQHyAQeSAfQBB5MB9gEVlAH3AUaVAfkBB5YB-wEVlwH8AUeYAf0BB5kB_gEHmgH_ARWbAYICSJwBgwJOnQGEAgieAYUCCJ8BhgIIoAGHAgihAYgCCKIBigIIowGMAhWkAY0CT6UBjwIIpgGRAhWnAZICUKgBkwIIqQGUAgiqAZUCFasBmAJRrAGZAletAZoCC64BmwILrwGcAguwAZ0CC7EBngILsgGgAguzAaICFbQBowJYtQGlAgu2AacCFbcBqAJZuAGpAgu5AaoCC7oBqwIVuwGuAlq8Aa8CYL0BsQIJvgGyAgm_AbUCCcABtgIJwQG3AgnCAbkCCcMBuwIVxAG8AmHFAb4CCcYBwAIVxwHBAmLIAcICCckBwwIJygHEAhXLAccCY8wByAJpzQHJAgXOAcoCBc8BywIF0AHMAgXRAc0CBdIBzwIF0wHRAhXUAdICatUB1AIF1gHWAhXXAdcCa9gB2AIF2QHZAgXaAdoCFdsB3QJs3AHeAnDdAd8CDd4B4AIN3wHhAg3gAeICDeEB4wIN4gHlAg3jAecCFeQB6AJx5QHrAg3mAe0CFecB7gJy6AHwAg3pAfECDeoB8gIV6wH1AnPsAfYCd-0B9wIO7gH4Ag7vAfkCDvAB-gIO8QH7Ag7yAf0CDvMB_wIV9AGAA3j1AYIDDvYBhAMV9wGFA3n4AYYDDvkBhwMO-gGIAxX7AYsDevwBjAN-_QGNAw_-AY4DD_8BjwMPgAKQAw-BApEDD4ICkwMPgwKVAxWEApYDf4UCmQMPhgKbAxWHApwDgAGIAp4DD4kCnwMPigKgAxWLAqMDgQGMAqQDhwGNAqUDEI4CpgMQjwKnAxCQAqgDEJECqQMQkgKrAxCTAq0DFZQCrgOIAZUCsQMQlgKzAxWXArQDiQGYArYDEJkCtwMQmgK4AxWbArsDigGcArwDkAGdAr0DEp4CvgMSnwK_AxKgAsADEqECwQMSogLDAxKjAsUDFaQCxgORAaUCyAMSpgLKAxWnAssDkgGoAswDEqkCzQMSqgLOAxWrAtEDkwGsAtIDlwE" + strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"accounts\",\"sessions\",\"verifications\",\"model\",\"latestOfModel\",\"parentOfModels\",\"modelVersion\",\"modelVersions\",\"_count\",\"tag\",\"tags\",\"taggedVersion\",\"taggedAdditionalFiles\",\"latestVersion\",\"parentModel\",\"childModels\",\"parentVersion\",\"versions\",\"authors\",\"nonMemberContributors\",\"granteeUser\",\"permissions\",\"additionalFiles\",\"likes\",\"interactions\",\"drafts\",\"authoredModels\",\"grantedPermissions\",\"actor\",\"events\",\"modelLikes\",\"modelInteractions\",\"modelDrafts\",\"passkeys\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Account.findUnique\",\"Account.findUniqueOrThrow\",\"Account.findFirst\",\"Account.findFirstOrThrow\",\"Account.findMany\",\"Account.createOne\",\"Account.createMany\",\"Account.createManyAndReturn\",\"Account.updateOne\",\"Account.updateMany\",\"Account.updateManyAndReturn\",\"Account.upsertOne\",\"Account.deleteOne\",\"Account.deleteMany\",\"Account.groupBy\",\"Account.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Verification.findUnique\",\"Verification.findUniqueOrThrow\",\"Verification.findFirst\",\"Verification.findFirstOrThrow\",\"Verification.findMany\",\"Verification.createOne\",\"Verification.createMany\",\"Verification.createManyAndReturn\",\"Verification.updateOne\",\"Verification.updateMany\",\"Verification.updateManyAndReturn\",\"Verification.upsertOne\",\"Verification.deleteOne\",\"Verification.deleteMany\",\"Verification.groupBy\",\"Verification.aggregate\",\"Passkey.findUnique\",\"Passkey.findUniqueOrThrow\",\"Passkey.findFirst\",\"Passkey.findFirstOrThrow\",\"Passkey.findMany\",\"Passkey.createOne\",\"Passkey.createMany\",\"Passkey.createManyAndReturn\",\"Passkey.updateOne\",\"Passkey.updateMany\",\"Passkey.updateManyAndReturn\",\"Passkey.upsertOne\",\"Passkey.deleteOne\",\"Passkey.deleteMany\",\"Passkey.groupBy\",\"Passkey.aggregate\",\"Model.findUnique\",\"Model.findUniqueOrThrow\",\"Model.findFirst\",\"Model.findFirstOrThrow\",\"Model.findMany\",\"Model.createOne\",\"Model.createMany\",\"Model.createManyAndReturn\",\"Model.updateOne\",\"Model.updateMany\",\"Model.updateManyAndReturn\",\"Model.upsertOne\",\"Model.deleteOne\",\"Model.deleteMany\",\"Model.groupBy\",\"Model.aggregate\",\"ModelVersion.findUnique\",\"ModelVersion.findUniqueOrThrow\",\"ModelVersion.findFirst\",\"ModelVersion.findFirstOrThrow\",\"ModelVersion.findMany\",\"ModelVersion.createOne\",\"ModelVersion.createMany\",\"ModelVersion.createManyAndReturn\",\"ModelVersion.updateOne\",\"ModelVersion.updateMany\",\"ModelVersion.updateManyAndReturn\",\"ModelVersion.upsertOne\",\"ModelVersion.deleteOne\",\"ModelVersion.deleteMany\",\"ModelVersion.groupBy\",\"ModelVersion.aggregate\",\"ModelVersionTag.findUnique\",\"ModelVersionTag.findUniqueOrThrow\",\"ModelVersionTag.findFirst\",\"ModelVersionTag.findFirstOrThrow\",\"ModelVersionTag.findMany\",\"ModelVersionTag.createOne\",\"ModelVersionTag.createMany\",\"ModelVersionTag.createManyAndReturn\",\"ModelVersionTag.updateOne\",\"ModelVersionTag.updateMany\",\"ModelVersionTag.updateManyAndReturn\",\"ModelVersionTag.upsertOne\",\"ModelVersionTag.deleteOne\",\"ModelVersionTag.deleteMany\",\"ModelVersionTag.groupBy\",\"ModelVersionTag.aggregate\",\"ModelAdditionalFile.findUnique\",\"ModelAdditionalFile.findUniqueOrThrow\",\"ModelAdditionalFile.findFirst\",\"ModelAdditionalFile.findFirstOrThrow\",\"ModelAdditionalFile.findMany\",\"ModelAdditionalFile.createOne\",\"ModelAdditionalFile.createMany\",\"ModelAdditionalFile.createManyAndReturn\",\"ModelAdditionalFile.updateOne\",\"ModelAdditionalFile.updateMany\",\"ModelAdditionalFile.updateManyAndReturn\",\"ModelAdditionalFile.upsertOne\",\"ModelAdditionalFile.deleteOne\",\"ModelAdditionalFile.deleteMany\",\"ModelAdditionalFile.groupBy\",\"ModelAdditionalFile.aggregate\",\"Tag.findUnique\",\"Tag.findUniqueOrThrow\",\"Tag.findFirst\",\"Tag.findFirstOrThrow\",\"Tag.findMany\",\"Tag.createOne\",\"Tag.createMany\",\"Tag.createManyAndReturn\",\"Tag.updateOne\",\"Tag.updateMany\",\"Tag.updateManyAndReturn\",\"Tag.upsertOne\",\"Tag.deleteOne\",\"Tag.deleteMany\",\"Tag.groupBy\",\"Tag.aggregate\",\"ModelAuthor.findUnique\",\"ModelAuthor.findUniqueOrThrow\",\"ModelAuthor.findFirst\",\"ModelAuthor.findFirstOrThrow\",\"ModelAuthor.findMany\",\"ModelAuthor.createOne\",\"ModelAuthor.createMany\",\"ModelAuthor.createManyAndReturn\",\"ModelAuthor.updateOne\",\"ModelAuthor.updateMany\",\"ModelAuthor.updateManyAndReturn\",\"ModelAuthor.upsertOne\",\"ModelAuthor.deleteOne\",\"ModelAuthor.deleteMany\",\"ModelAuthor.groupBy\",\"ModelAuthor.aggregate\",\"NonMemberContributor.findUnique\",\"NonMemberContributor.findUniqueOrThrow\",\"NonMemberContributor.findFirst\",\"NonMemberContributor.findFirstOrThrow\",\"NonMemberContributor.findMany\",\"NonMemberContributor.createOne\",\"NonMemberContributor.createMany\",\"NonMemberContributor.createManyAndReturn\",\"NonMemberContributor.updateOne\",\"NonMemberContributor.updateMany\",\"NonMemberContributor.updateManyAndReturn\",\"NonMemberContributor.upsertOne\",\"NonMemberContributor.deleteOne\",\"NonMemberContributor.deleteMany\",\"NonMemberContributor.groupBy\",\"NonMemberContributor.aggregate\",\"ModelPermission.findUnique\",\"ModelPermission.findUniqueOrThrow\",\"ModelPermission.findFirst\",\"ModelPermission.findFirstOrThrow\",\"ModelPermission.findMany\",\"ModelPermission.createOne\",\"ModelPermission.createMany\",\"ModelPermission.createManyAndReturn\",\"ModelPermission.updateOne\",\"ModelPermission.updateMany\",\"ModelPermission.updateManyAndReturn\",\"ModelPermission.upsertOne\",\"ModelPermission.deleteOne\",\"ModelPermission.deleteMany\",\"ModelPermission.groupBy\",\"ModelPermission.aggregate\",\"ModelLike.findUnique\",\"ModelLike.findUniqueOrThrow\",\"ModelLike.findFirst\",\"ModelLike.findFirstOrThrow\",\"ModelLike.findMany\",\"ModelLike.createOne\",\"ModelLike.createMany\",\"ModelLike.createManyAndReturn\",\"ModelLike.updateOne\",\"ModelLike.updateMany\",\"ModelLike.updateManyAndReturn\",\"ModelLike.upsertOne\",\"ModelLike.deleteOne\",\"ModelLike.deleteMany\",\"ModelLike.groupBy\",\"ModelLike.aggregate\",\"ModelInteraction.findUnique\",\"ModelInteraction.findUniqueOrThrow\",\"ModelInteraction.findFirst\",\"ModelInteraction.findFirstOrThrow\",\"ModelInteraction.findMany\",\"ModelInteraction.createOne\",\"ModelInteraction.createMany\",\"ModelInteraction.createManyAndReturn\",\"ModelInteraction.updateOne\",\"ModelInteraction.updateMany\",\"ModelInteraction.updateManyAndReturn\",\"ModelInteraction.upsertOne\",\"ModelInteraction.deleteOne\",\"ModelInteraction.deleteMany\",\"ModelInteraction.groupBy\",\"ModelInteraction.aggregate\",\"ModelDraft.findUnique\",\"ModelDraft.findUniqueOrThrow\",\"ModelDraft.findFirst\",\"ModelDraft.findFirstOrThrow\",\"ModelDraft.findMany\",\"ModelDraft.createOne\",\"ModelDraft.createMany\",\"ModelDraft.createManyAndReturn\",\"ModelDraft.updateOne\",\"ModelDraft.updateMany\",\"ModelDraft.updateManyAndReturn\",\"ModelDraft.upsertOne\",\"ModelDraft.deleteOne\",\"ModelDraft.deleteMany\",\"ModelDraft.groupBy\",\"ModelDraft.aggregate\",\"Event.findUnique\",\"Event.findUniqueOrThrow\",\"Event.findFirst\",\"Event.findFirstOrThrow\",\"Event.findMany\",\"Event.createOne\",\"Event.createMany\",\"Event.createManyAndReturn\",\"Event.updateOne\",\"Event.updateMany\",\"Event.updateManyAndReturn\",\"Event.upsertOne\",\"Event.deleteOne\",\"Event.deleteMany\",\"Event.groupBy\",\"Event.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"type\",\"actorId\",\"resourceType\",\"resourceId\",\"payload\",\"createdAt\",\"processedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"contains\",\"startsWith\",\"endsWith\",\"userId\",\"modelId\",\"schemaVersion\",\"updatedAt\",\"versionNumber\",\"ModelInteractionKind\",\"kind\",\"sessionId\",\"ipHash\",\"userAgent\",\"referer\",\"geo\",\"cookie\",\"granteeUserId\",\"PermissionLevel\",\"permissionLevel\",\"legacyId\",\"email\",\"name\",\"collaboratorType\",\"addedByUserId\",\"AuthorRole\",\"role\",\"displayName\",\"every\",\"some\",\"none\",\"taggedVersionNumber\",\"fileKey\",\"ModelFileKind\",\"tagId\",\"title\",\"description\",\"changeSummary\",\"previewImageFileKey\",\"netlogoFileKey\",\"netlogoVersion\",\"infoTab\",\"finalizedAt\",\"latestVersionNumber\",\"parentModelId\",\"parentVersionNumber\",\"ModelVisibility\",\"visibility\",\"isEndorsed\",\"isLibraryModel\",\"viewCount\",\"runCount\",\"downloadCount\",\"shareCount\",\"deletedAt\",\"publicKey\",\"credentialID\",\"counter\",\"deviceType\",\"backedUp\",\"transports\",\"aaguid\",\"identifier\",\"value\",\"expiresAt\",\"token\",\"ipAddress\",\"impersonatedBy\",\"accountId\",\"providerId\",\"accessToken\",\"refreshToken\",\"accessTokenExpiresAt\",\"refreshTokenExpiresAt\",\"scope\",\"idToken\",\"password\",\"emailVerified\",\"image\",\"SystemRole\",\"systemRole\",\"UserKind\",\"userKind\",\"isProfilePublic\",\"bio\",\"country\",\"socialLinks\",\"dob\",\"affiliation\",\"banned\",\"banReason\",\"banExpires\",\"onboardedAt\",\"modelId_userId\",\"modelId_granteeUserId\",\"modelId_versionNumber\",\"modelId_versionNumber_tagId\",\"id_latestVersionNumber\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "yQmhAZACIwQAAOgEACAFAADpBAAgBgAA6gQAIB4AANsEACAfAADdBAAgIQAA6wQAICIAAN4EACAjAADfBAAgJAAA4AQAICUAAOwEACC-AgAA5AQAML8CAAAPABDAAgAA5AQAMMECAQAAAAHHAkAAmwQAId0CQACbBAAh6gICAAAAAesCAQAAAAHsAgEAmgQAIfACAQCaBAAhjANAALsEACGjAyAAugQAIaQDAQCaBAAhpgMAAOUEpgMiqAMAAOYEqAMiqQMgALoEACGqAwEAmgQAIasDAQCaBAAhrAMAAMMEACCtA0AAuwQAIa4DAQCaBAAhrwMgAOcEACGwAwEAmgQAIbEDQAC7BAAhsgNAALsEACEBAAAAAQAgEQMAALwEACC-AgAA7wQAML8CAAADABDAAgAA7wQAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhCAMAALMIACCcAwAA8AQAIJ0DAADwBAAgngMAAPAEACCfAwAA8AQAIKADAADwBAAgoQMAAPAEACCiAwAA8AQAIBEDAAC8BAAgvgIAAO8EADC_AgAAAwAQwAIAAO8EADDBAgEAAAABxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhAwAAAAMAIAEAAAQAMAIAAAUAIA0DAAC8BAAgvgIAAO4EADC_AgAABwAQwAIAAO4EADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHdAkAAmwQAIeMCAQCaBAAhlgNAAJsEACGXAwEAmAQAIZgDAQCaBAAhmQMBAJoEACEEAwAAswgAIOMCAADwBAAgmAMAAPAEACCZAwAA8AQAIA0DAAC8BAAgvgIAAO4EADC_AgAABwAQwAIAAO4EADDBAgEAAAABxwJAAJsEACHaAgEAmAQAId0CQACbBAAh4wIBAJoEACGWA0AAmwQAIZcDAQAAAAGYAwEAmgQAIZkDAQCaBAAhAwAAAAcAIAEAAAgAMAIAAAkAIAsDAADFBAAgvgIAAO0EADC_AgAACwAQwAIAAO0EADDBAgEAmAQAIccCQAC7BAAh2gIBAJoEACHdAkAAuwQAIZQDAQCYBAAhlQMBAJgEACGWA0AAmwQAIQQDAACzCAAgxwIAAPAEACDaAgAA8AQAIN0CAADwBAAgCwMAAMUEACC-AgAA7QQAML8CAAALABDAAgAA7QQAMMECAQAAAAHHAkAAuwQAIdoCAQCaBAAh3QJAALsEACGUAwEAmAQAIZUDAQCYBAAhlgNAAJsEACEDAAAACwAgAQAADAAwAgAADQAgIwQAAOgEACAFAADpBAAgBgAA6gQAIB4AANsEACAfAADdBAAgIQAA6wQAICIAAN4EACAjAADfBAAgJAAA4AQAICUAAOwEACC-AgAA5AQAML8CAAAPABDAAgAA5AQAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAh6wIBAJoEACHsAgEAmgQAIfACAQCaBAAhjANAALsEACGjAyAAugQAIaQDAQCaBAAhpgMAAOUEpgMiqAMAAOYEqAMiqQMgALoEACGqAwEAmgQAIasDAQCaBAAhrAMAAMMEACCtA0AAuwQAIa4DAQCaBAAhrwMgAOcEACGwAwEAmgQAIbEDQAC7BAAhsgNAALsEACEBAAAADwAgCgMAALwEACAHAADEBAAgvgIAAOIEADC_AgAAEQAQwAIAAOIEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACHtAgEAmgQAIfACAADjBPACIgMDAACzCAAgBwAAtAgAIO0CAADwBAAgCwMAALwEACAHAADEBAAgvgIAAOIEADC_AgAAEQAQwAIAAOIEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACHtAgEAmgQAIfACAADjBPACIrMDAADhBAAgAwAAABEAIAEAABIAMAIAABMAIBMHAADEBAAgCAAAwAQAIAkAAM4EACAOAACcBAAgEAAAzwQAIL4CAADNBAAwvwIAABUAEMACAADNBAAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-QIBAJgEACH6AgEAmgQAIfsCAQCaBAAh_AIBAJoEACH9AgEAmAQAIf4CAQCaBAAh_wIBAJoEACGAA0AAuwQAIQEAAAAVACAeEQAA2QQAIBIAAMAEACATAADOBAAgFAAA2QQAIBUAANoEACAWAADbBAAgFwAA3AQAIBkAAN0EACAaAADPBAAgGwAA3gQAIBwAAN8EACAdAADgBAAgvgIAANcEADC_AgAAFwAQwAIAANcEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhAQAAABcAIBERAAC3CAAgEgAAtAgAIBMAALUIACAUAAC3CAAgFQAAuQgAIBYAAKwIACAXAAC6CAAgGQAArQgAIBoAALYIACAbAACvCAAgHAAAsAgAIB0AALEIACDqAgAA8AQAIIEDAADwBAAgggMAAPAEACCDAwAA8AQAIIwDAADwBAAgHxEAANkEACASAADABAAgEwAAzgQAIBQAANkEACAVAADaBAAgFgAA2wQAIBcAANwEACAZAADdBAAgGgAAzwQAIBsAAN4EACAcAADfBAAgHQAA4AQAIL4CAADXBAAwvwIAABcAEMACAADXBAAwwQIBAAAAAccCQACbBAAh3QJAAJsEACHqAgIAAAABgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACG3AwAA1gQAIAMAAAAXACABAAAZADACAAAaACAJCgAA0gQAIA0AANUEACC-AgAA1AQAML8CAAAcABDAAgAA1AQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfgCAQCYBAAhAgoAALcIACANAAC4CAAgCgoAANIEACANAADVBAAgvgIAANQEADC_AgAAHAAQwAIAANQEADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH4AgEAmAQAIbYDAADTBAAgAwAAABwAIAEAAB0AMAIAAB4AIAMAAAAcACABAAAdADACAAAeACABAAAAHAAgCwcAAMQEACAPAADSBAAgvgIAANAEADC_AgAAIgAQwAIAANAEADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHgAgAA0QT4AiL1AgIAuQQAIfYCAQCYBAAhAgcAALQIACAPAAC3CAAgCwcAAMQEACAPAADSBAAgvgIAANAEADC_AgAAIgAQwAIAANAEADDBAgEAAAABxwJAAJsEACHbAgEAmAQAIeACAADRBPgCIvUCAgC5BAAh9gIBAJgEACEDAAAAIgAgAQAAIwAwAgAAJAAgAQAAABcAIAEAAAAcACABAAAAIgAgAQAAABcAIAMAAAAXACABAAAZADACAAAaACABAAAAFQAgCwcAALQIACAIAAC0CAAgCQAAtQgAIA4AAMIFACAQAAC2CAAg-gIAAPAEACD7AgAA8AQAIPwCAADwBAAg_gIAAPAEACD_AgAA8AQAIIADAADwBAAgFAcAAMQEACAIAADABAAgCQAAzgQAIA4AAJwEACAQAADPBAAgvgIAAM0EADC_AgAAFQAQwAIAAM0EADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH5AgEAmAQAIfoCAQCaBAAh-wIBAJoEACH8AgEAmgQAIf0CAQCYBAAh_gIBAJoEACH_AgEAmgQAIYADQAC7BAAhtQMAAMwEACADAAAAFQAgAQAALAAwAgAALQAgAwAAABEAIAEAABIAMAIAABMAIAwHAADEBAAgvgIAAMsEADC_AgAAMAAQwAIAAMsEADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHqAgIAuQQAIesCAQCaBAAh7AIBAJoEACHtAgEAmgQAIe4CAQCaBAAhBQcAALQIACDrAgAA8AQAIOwCAADwBAAg7QIAAPAEACDuAgAA8AQAIAwHAADEBAAgvgIAAMsEADC_AgAAMAAQwAIAAMsEADDBAgEAAAABxwJAAJsEACHbAgEAmAQAIeoCAgAAAAHrAgEAmgQAIewCAQCaBAAh7QIBAJoEACHuAgEAmgQAIQMAAAAwACABAAAxADACAAAyACAKBwAAxAQAIBgAAMUEACC-AgAAyQQAML8CAAA0ABDAAgAAyQQAMMECAQCYBAAhxwJAAJsEACHbAgEAmAQAIecCAQCaBAAh6QIAAMoE6QIiAwcAALQIACAYAACzCAAg5wIAAPAEACALBwAAxAQAIBgAAMUEACC-AgAAyQQAML8CAAA0ABDAAgAAyQQAMMECAQAAAAHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiK0AwAAyAQAIAMAAAA0ACABAAA1ADACAAA2ACABAAAADwAgAwAAACIAIAEAACMAMAIAACQAIAgDAAC8BAAgBwAAxAQAIL4CAADHBAAwvwIAADoAEMACAADHBAAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAhAgMAALMIACAHAAC0CAAgCQMAALwEACAHAADEBAAgvgIAAMcEADC_AgAAOgAQwAIAAMcEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACGzAwAAxgQAIAMAAAA6ACABAAA7ADACAAA8ACARAwAAxQQAIAcAAMQEACC-AgAAwQQAML8CAAA-ABDAAgAAwQQAMMECAQCYBAAhxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEKAwAAswgAIAcAALQIACDaAgAA8AQAIN4CAADwBAAg4QIAAPAEACDiAgAA8AQAIOMCAADwBAAg5AIAAPAEACDlAgAA8AQAIOYCAADwBAAgEQMAAMUEACAHAADEBAAgvgIAAMEEADC_AgAAPgAQwAIAAMEEADDBAgEAAAABxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEDAAAAPgAgAQAAPwAwAgAAQAAgAQAAAA8AIAwDAAC8BAAgBwAAwAQAICsAAL4EACC-AgAAvwQAML8CAABDABDAAgAAvwQAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAIdsCAQCaBAAh3AICALkEACHdAkAAmwQAIQMDAACzCAAgBwAAtAgAINsCAADwBAAgDAMAALwEACAHAADABAAgKwAAvgQAIL4CAAC_BAAwvwIAAEMAEMACAAC_BAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACEDAAAAQwAgAQAARAAwAgAARQAgAQAAABcAIAEAAAAXACABAAAAFQAgAQAAABEAIAEAAAAwACABAAAANAAgAQAAACIAIAEAAAA6ACABAAAAPgAgAQAAAEMAIAMAAAA0ACABAAA1ADACAAA2ACAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAJgEACHCAgEAmAQAIcMCAQCYBAAhxAIBAJgEACHFAgEAmAQAIcYCAAC-BAAgxwJAAJsEACHIAkAAuwQAIQIgAACzCAAgyAIAAPAEACAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAAAAAcICAQCYBAAhwwIBAJgEACHEAgEAmAQAIcUCAQCYBAAhxgIAAL4EACDHAkAAmwQAIcgCQAC7BAAhAwAAAFIAIAEAAFMAMAIAAFQAIAMAAAA6ACABAAA7ADACAAA8ACADAAAAPgAgAQAAPwAwAgAAQAAgAwAAAEMAIAEAAEQAMAIAAEUAIA8DAAC8BAAgvgIAALgEADC_AgAAWQAQwAIAALgEADDBAgEAmAQAIccCQAC7BAAh2gIBAJgEACHsAgEAmgQAIY0DAQCYBAAhjgMBAJgEACGPAwIAuQQAIZADAQCYBAAhkQMgALoEACGSAwEAmgQAIZMDAQCaBAAhBQMAALMIACDHAgAA8AQAIOwCAADwBAAgkgMAAPAEACCTAwAA8AQAIA8DAAC8BAAgvgIAALgEADC_AgAAWQAQwAIAALgEADDBAgEAAAABxwJAALsEACHaAgEAmAQAIewCAQCaBAAhjQMBAJgEACGOAwEAmAQAIY8DAgC5BAAhkAMBAJgEACGRAyAAugQAIZIDAQCaBAAhkwMBAJoEACEDAAAAWQAgAQAAWgAwAgAAWwAgAQAAAAMAIAEAAAAHACABAAAACwAgAQAAABEAIAEAAAA0ACABAAAAUgAgAQAAADoAIAEAAAA-ACABAAAAQwAgAQAAAFkAIAEAAAABACAZBAAAqQgAIAUAAKoIACAGAACrCAAgHgAArAgAIB8AAK0IACAhAACuCAAgIgAArwgAICMAALAIACAkAACxCAAgJQAAsggAIOoCAADwBAAg6wIAAPAEACDsAgAA8AQAIPACAADwBAAgjAMAAPAEACCkAwAA8AQAIKoDAADwBAAgqwMAAPAEACCsAwAA8AQAIK0DAADwBAAgrgMAAPAEACCvAwAA8AQAILADAADwBAAgsQMAAPAEACCyAwAA8AQAIAMAAAAPACABAABoADACAAABACADAAAADwAgAQAAaAAwAgAAAQAgAwAAAA8AIAEAAGgAMAIAAAEAICAEAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAiAAClCAAgIwAApggAICQAAKcIACAlAACoCAAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAesCAQAAAAHsAgEAAAAB8AIBAAAAAYwDQAAAAAGjAyAAAAABpAMBAAAAAaYDAAAApgMCqAMAAACoAwKpAyAAAAABqgMBAAAAAasDAQAAAAGsA4AAAAABrQNAAAAAAa4DAQAAAAGvAyAAAAABsAMBAAAAAbEDQAAAAAGyA0AAAAABASsAAGwAIBbBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAEBKwAAbgAwASsAAG4AMCAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhAgAAAAEAICsAAHEAIBbBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACECAAAADwAgKwAAcwAgAgAAAA8AICsAAHMAIAMAAAABACAyAABsACAzAABxACABAAAAAQAgAQAAAA8AIBQMAACkBwAgOAAApQcAIDkAAKgHACA6AACnBwAgOwAApgcAIOoCAADwBAAg6wIAAPAEACDsAgAA8AQAIPACAADwBAAgjAMAAPAEACCkAwAA8AQAIKoDAADwBAAgqwMAAPAEACCsAwAA8AQAIK0DAADwBAAgrgMAAPAEACCvAwAA8AQAILADAADwBAAgsQMAAPAEACCyAwAA8AQAIBm-AgAArgQAML8CAAB6ABDAAgAArgQAMMECAQDvAwAhxwJAAPEDACHdAkAA8QMAIeoCAgCEBAAh6wIBAP0DACHsAgEA_QMAIfACAQD9AwAhjANAAPIDACGjAyAApQQAIaQDAQD9AwAhpgMAAK8EpgMiqAMAALAEqAMiqQMgAKUEACGqAwEA_QMAIasDAQD9AwAhrAMAAIYEACCtA0AA8gMAIa4DAQD9AwAhrwMgALEEACGwAwEA_QMAIbEDQADyAwAhsgNAAPIDACEDAAAADwAgAQAAeQAwNwAAegAgAwAAAA8AIAEAAGgAMAIAAAEAIAEAAAAFACABAAAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgDgMAAKMHACDBAgEAAAABxwJAAAAAAdoCAQAAAAHdAkAAAAABmgMBAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABASsAAIIBACANwQIBAAAAAccCQAAAAAHaAgEAAAAB3QJAAAAAAZoDAQAAAAGbAwEAAAABnAMBAAAAAZ0DAQAAAAGeA0AAAAABnwNAAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAQErAACEAQAwASsAAIQBADAOAwAAogcAIMECAQD0BAAhxwJAAPUEACHaAgEA9AQAId0CQAD1BAAhmgMBAPQEACGbAwEA9AQAIZwDAQD_BAAhnQMBAP8EACGeA0AA9gQAIZ8DQAD2BAAhoAMBAP8EACGhAwEA_wQAIaIDAQD_BAAhAgAAAAUAICsAAIcBACANwQIBAPQEACHHAkAA9QQAIdoCAQD0BAAh3QJAAPUEACGaAwEA9AQAIZsDAQD0BAAhnAMBAP8EACGdAwEA_wQAIZ4DQAD2BAAhnwNAAPYEACGgAwEA_wQAIaEDAQD_BAAhogMBAP8EACECAAAAAwAgKwAAiQEAIAIAAAADACArAACJAQAgAwAAAAUAIDIAAIIBACAzAACHAQAgAQAAAAUAIAEAAAADACAKDAAAnwcAIDoAAKEHACA7AACgBwAgnAMAAPAEACCdAwAA8AQAIJ4DAADwBAAgnwMAAPAEACCgAwAA8AQAIKEDAADwBAAgogMAAPAEACAQvgIAAK0EADC_AgAAkAEAEMACAACtBAAwwQIBAO8DACHHAkAA8QMAIdoCAQDvAwAh3QJAAPEDACGaAwEA7wMAIZsDAQDvAwAhnAMBAP0DACGdAwEA_QMAIZ4DQADyAwAhnwNAAPIDACGgAwEA_QMAIaEDAQD9AwAhogMBAP0DACEDAAAAAwAgAQAAjwEAMDcAAJABACADAAAAAwAgAQAABAAwAgAABQAgAQAAAAkAIAEAAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACAKAwAAngcAIMECAQAAAAHHAkAAAAAB2gIBAAAAAd0CQAAAAAHjAgEAAAABlgNAAAAAAZcDAQAAAAGYAwEAAAABmQMBAAAAAQErAACYAQAgCcECAQAAAAHHAkAAAAAB2gIBAAAAAd0CQAAAAAHjAgEAAAABlgNAAAAAAZcDAQAAAAGYAwEAAAABmQMBAAAAAQErAACaAQAwASsAAJoBADAKAwAAnQcAIMECAQD0BAAhxwJAAPUEACHaAgEA9AQAId0CQAD1BAAh4wIBAP8EACGWA0AA9QQAIZcDAQD0BAAhmAMBAP8EACGZAwEA_wQAIQIAAAAJACArAACdAQAgCcECAQD0BAAhxwJAAPUEACHaAgEA9AQAId0CQAD1BAAh4wIBAP8EACGWA0AA9QQAIZcDAQD0BAAhmAMBAP8EACGZAwEA_wQAIQIAAAAHACArAACfAQAgAgAAAAcAICsAAJ8BACADAAAACQAgMgAAmAEAIDMAAJ0BACABAAAACQAgAQAAAAcAIAYMAACaBwAgOgAAnAcAIDsAAJsHACDjAgAA8AQAIJgDAADwBAAgmQMAAPAEACAMvgIAAKwEADC_AgAApgEAEMACAACsBAAwwQIBAO8DACHHAkAA8QMAIdoCAQDvAwAh3QJAAPEDACHjAgEA_QMAIZYDQADxAwAhlwMBAO8DACGYAwEA_QMAIZkDAQD9AwAhAwAAAAcAIAEAAKUBADA3AACmAQAgAwAAAAcAIAEAAAgAMAIAAAkAIAEAAAANACABAAAADQAgAwAAAAsAIAEAAAwAMAIAAA0AIAMAAAALACABAAAMADACAAANACADAAAACwAgAQAADAAwAgAADQAgCAMAAJkHACDBAgEAAAABxwJAAAAAAdoCAQAAAAHdAkAAAAABlAMBAAAAAZUDAQAAAAGWA0AAAAABASsAAK4BACAHwQIBAAAAAccCQAAAAAHaAgEAAAAB3QJAAAAAAZQDAQAAAAGVAwEAAAABlgNAAAAAAQErAACwAQAwASsAALABADABAAAADwAgCAMAAJgHACDBAgEA9AQAIccCQAD2BAAh2gIBAP8EACHdAkAA9gQAIZQDAQD0BAAhlQMBAPQEACGWA0AA9QQAIQIAAAANACArAAC0AQAgB8ECAQD0BAAhxwJAAPYEACHaAgEA_wQAId0CQAD2BAAhlAMBAPQEACGVAwEA9AQAIZYDQAD1BAAhAgAAAAsAICsAALYBACACAAAACwAgKwAAtgEAIAEAAAAPACADAAAADQAgMgAArgEAIDMAALQBACABAAAADQAgAQAAAAsAIAYMAACVBwAgOgAAlwcAIDsAAJYHACDHAgAA8AQAINoCAADwBAAg3QIAAPAEACAKvgIAAKsEADC_AgAAvgEAEMACAACrBAAwwQIBAO8DACHHAkAA8gMAIdoCAQD9AwAh3QJAAPIDACGUAwEA7wMAIZUDAQDvAwAhlgNAAPEDACEDAAAACwAgAQAAvQEAMDcAAL4BACADAAAACwAgAQAADAAwAgAADQAgAQAAAFsAIAEAAABbACADAAAAWQAgAQAAWgAwAgAAWwAgAwAAAFkAIAEAAFoAMAIAAFsAIAMAAABZACABAABaADACAABbACAMAwAAlAcAIMECAQAAAAHHAkAAAAAB2gIBAAAAAewCAQAAAAGNAwEAAAABjgMBAAAAAY8DAgAAAAGQAwEAAAABkQMgAAAAAZIDAQAAAAGTAwEAAAABASsAAMYBACALwQIBAAAAAccCQAAAAAHaAgEAAAAB7AIBAAAAAY0DAQAAAAGOAwEAAAABjwMCAAAAAZADAQAAAAGRAyAAAAABkgMBAAAAAZMDAQAAAAEBKwAAyAEAMAErAADIAQAwDAMAAJMHACDBAgEA9AQAIccCQAD2BAAh2gIBAPQEACHsAgEA_wQAIY0DAQD0BAAhjgMBAPQEACGPAwIA_gQAIZADAQD0BAAhkQMgAP4FACGSAwEA_wQAIZMDAQD_BAAhAgAAAFsAICsAAMsBACALwQIBAPQEACHHAkAA9gQAIdoCAQD0BAAh7AIBAP8EACGNAwEA9AQAIY4DAQD0BAAhjwMCAP4EACGQAwEA9AQAIZEDIAD-BQAhkgMBAP8EACGTAwEA_wQAIQIAAABZACArAADNAQAgAgAAAFkAICsAAM0BACADAAAAWwAgMgAAxgEAIDMAAMsBACABAAAAWwAgAQAAAFkAIAkMAACOBwAgOAAAjwcAIDkAAJIHACA6AACRBwAgOwAAkAcAIMcCAADwBAAg7AIAAPAEACCSAwAA8AQAIJMDAADwBAAgDr4CAACqBAAwvwIAANQBABDAAgAAqgQAMMECAQDvAwAhxwJAAPIDACHaAgEA7wMAIewCAQD9AwAhjQMBAO8DACGOAwEA7wMAIY8DAgD-AwAhkAMBAO8DACGRAyAApQQAIZIDAQD9AwAhkwMBAP0DACEDAAAAWQAgAQAA0wEAMDcAANQBACADAAAAWQAgAQAAWgAwAgAAWwAgAQAAABoAIAEAAAAaACADAAAAFwAgAQAAGQAwAgAAGgAgAwAAABcAIAEAABkAMAIAABoAIAMAAAAXACABAAAZADACAAAaACAbEQAA_QYAIBIAAO4GACATAADvBgAgFAAA8AYAIBUAAPEGACAWAADyBgAgFwAA8wYAIBkAAPQGACAaAAD1BgAgGwAA9gYAIBwAAPcGACAdAAD4BgAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAYEDAgAAAAGCAwEAAAABgwMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQErAADcAQAgD8ECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAEBKwAA3gEAMAErAADeAQAwAQAAABUAIAEAAAAXACABAAAAFQAgGxEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACECAAAAGgAgKwAA5AEAIA_BAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhAgAAABcAICsAAOYBACACAAAAFwAgKwAA5gEAIAEAAAAVACABAAAAFwAgAQAAABUAIAMAAAAaACAyAADcAQAgMwAA5AEAIAEAAAAaACABAAAAFwAgCgwAAIkHACA4AACKBwAgOQAAjQcAIDoAAIwHACA7AACLBwAg6gIAAPAEACCBAwAA8AQAIIIDAADwBAAggwMAAPAEACCMAwAA8AQAIBK-AgAAowQAML8CAADwAQAQwAIAAKMEADDBAgEA7wMAIccCQADxAwAh3QJAAPEDACHqAgIAhAQAIYEDAgCEBAAhggMBAP0DACGDAwIAhAQAIYUDAACkBIUDIoYDIAClBAAhhwMgAKUEACGIAwIA_gMAIYkDAgD-AwAhigMCAP4DACGLAwIA_gMAIYwDQADyAwAhAwAAABcAIAEAAO8BADA3AADwAQAgAwAAABcAIAEAABkAMAIAABoAIAEAAAAtACABAAAALQAgAwAAABUAIAEAACwAMAIAAC0AIAMAAAAVACABAAAsADACAAAtACADAAAAFQAgAQAALAAwAgAALQAgEAcAAIgHACAIAADoBgAgCQAA6QYAIA4AAOoGACAQAADrBgAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAEBKwAA-AEAIAvHAkAAAAAB2wIBAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQErAAD6AQAwASsAAPoBADAQBwAA2QUAIAgAANoFACAJAADbBQAgDgAA3AUAIBAAAN0FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhAgAAAC0AICsAAP0BACALxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQIAAAAVACArAAD_AQAgAgAAABUAICsAAP8BACADAAAALQAgMgAA-AEAIDMAAP0BACABAAAALQAgAQAAABUAIAsMAADUBQAgOAAA1QUAIDkAANgFACA6AADXBQAgOwAA1gUAIPoCAADwBAAg-wIAAPAEACD8AgAA8AQAIP4CAADwBAAg_wIAAPAEACCAAwAA8AQAIA6-AgAAogQAML8CAACGAgAQwAIAAKIEADDHAkAA8QMAIdsCAQDvAwAh3gICAP4DACH5AgEA7wMAIfoCAQD9AwAh-wIBAP0DACH8AgEA_QMAIf0CAQDvAwAh_gIBAP0DACH_AgEA_QMAIYADQADyAwAhAwAAABUAIAEAAIUCADA3AACGAgAgAwAAABUAIAEAACwAMAIAAC0AIAEAAAAeACABAAAAHgAgAwAAABwAIAEAAB0AMAIAAB4AIAMAAAAcACABAAAdADACAAAeACADAAAAHAAgAQAAHQAwAgAAHgAgBgoAAMAFACANAADTBQAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-AIBAAAAAQErAACOAgAgBMcCQAAAAAHbAgEAAAAB3gICAAAAAfgCAQAAAAEBKwAAkAIAMAErAACQAgAwBgoAAL4FACANAADSBQAgxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-AIBAPQEACECAAAAHgAgKwAAkwIAIATHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH4AgEA9AQAIQIAAAAcACArAACVAgAgAgAAABwAICsAAJUCACADAAAAHgAgMgAAjgIAIDMAAJMCACABAAAAHgAgAQAAABwAIAUMAADNBQAgOAAAzgUAIDkAANEFACA6AADQBQAgOwAAzwUAIAe-AgAAoQQAML8CAACcAgAQwAIAAKEEADDHAkAA8QMAIdsCAQDvAwAh3gICAP4DACH4AgEA7wMAIQMAAAAcACABAACbAgAwNwAAnAIAIAMAAAAcACABAAAdADACAAAeACABAAAAJAAgAQAAACQAIAMAAAAiACABAAAjADACAAAkACADAAAAIgAgAQAAIwAwAgAAJAAgAwAAACIAIAEAACMAMAIAACQAIAgHAADLBQAgDwAAzAUAIMECAQAAAAHHAkAAAAAB2wIBAAAAAeACAAAA-AIC9QICAAAAAfYCAQAAAAEBKwAApAIAIAbBAgEAAAABxwJAAAAAAdsCAQAAAAHgAgAAAPgCAvUCAgAAAAH2AgEAAAABASsAAKYCADABKwAApgIAMAgHAADJBQAgDwAAygUAIMECAQD0BAAhxwJAAPUEACHbAgEA9AQAIeACAADIBfgCIvUCAgD-BAAh9gIBAPQEACECAAAAJAAgKwAAqQIAIAbBAgEA9AQAIccCQAD1BAAh2wIBAPQEACHgAgAAyAX4AiL1AgIA_gQAIfYCAQD0BAAhAgAAACIAICsAAKsCACACAAAAIgAgKwAAqwIAIAMAAAAkACAyAACkAgAgMwAAqQIAIAEAAAAkACABAAAAIgAgBQwAAMMFACA4AADEBQAgOQAAxwUAIDoAAMYFACA7AADFBQAgCb4CAACdBAAwvwIAALICABDAAgAAnQQAMMECAQDvAwAhxwJAAPEDACHbAgEA7wMAIeACAACeBPgCIvUCAgD-AwAh9gIBAO8DACEDAAAAIgAgAQAAsQIAMDcAALICACADAAAAIgAgAQAAIwAwAgAAJAAgCQsAAJwEACC-AgAAlwQAML8CAAC4AgAQwAIAAJcEADDBAgEAAAABxwJAAJsEACHqAgIAAAAB7AIBAAAAAfECAQCaBAAhAQAAALUCACABAAAAtQIAIAkLAACcBAAgvgIAAJcEADC_AgAAuAIAEMACAACXBAAwwQIBAJgEACHHAkAAmwQAIeoCAgCZBAAh7AIBAJgEACHxAgEAmgQAIQMLAADCBQAg6gIAAPAEACDxAgAA8AQAIAMAAAC4AgAgAQAAuQIAMAIAALUCACADAAAAuAIAIAEAALkCADACAAC1AgAgAwAAALgCACABAAC5AgAwAgAAtQIAIAYLAADBBQAgwQIBAAAAAccCQAAAAAHqAgIAAAAB7AIBAAAAAfECAQAAAAEBKwAAvQIAIAXBAgEAAAABxwJAAAAAAeoCAgAAAAHsAgEAAAAB8QIBAAAAAQErAAC_AgAwASsAAL8CADAGCwAAsgUAIMECAQD0BAAhxwJAAPUEACHqAgIAiQUAIewCAQD0BAAh8QIBAP8EACECAAAAtQIAICsAAMICACAFwQIBAPQEACHHAkAA9QQAIeoCAgCJBQAh7AIBAPQEACHxAgEA_wQAIQIAAAC4AgAgKwAAxAIAIAIAAAC4AgAgKwAAxAIAIAMAAAC1AgAgMgAAvQIAIDMAAMICACABAAAAtQIAIAEAAAC4AgAgBwwAAK0FACA4AACuBQAgOQAAsQUAIDoAALAFACA7AACvBQAg6gIAAPAEACDxAgAA8AQAIAi-AgAAlgQAML8CAADLAgAQwAIAAJYEADDBAgEA7wMAIccCQADxAwAh6gICAIQEACHsAgEA7wMAIfECAQD9AwAhAwAAALgCACABAADKAgAwNwAAywIAIAMAAAC4AgAgAQAAuQIAMAIAALUCACABAAAAEwAgAQAAABMAIAMAAAARACABAAASADACAAATACADAAAAEQAgAQAAEgAwAgAAEwAgAwAAABEAIAEAABIAMAIAABMAIAcDAACsBQAgBwAAqwUAIMcCQAAAAAHaAgEAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgErAADTAgAgBccCQAAAAAHaAgEAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgErAADVAgAwASsAANUCADAHAwAAqgUAIAcAAKkFACDHAkAA9QQAIdoCAQD0BAAh2wIBAPQEACHtAgEA_wQAIfACAACoBfACIgIAAAATACArAADYAgAgBccCQAD1BAAh2gIBAPQEACHbAgEA9AQAIe0CAQD_BAAh8AIAAKgF8AIiAgAAABEAICsAANoCACACAAAAEQAgKwAA2gIAIAMAAAATACAyAADTAgAgMwAA2AIAIAEAAAATACABAAAAEQAgBAwAAKUFACA6AACnBQAgOwAApgUAIO0CAADwBAAgCL4CAACSBAAwvwIAAOECABDAAgAAkgQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIe0CAQD9AwAh8AIAAJME8AIiAwAAABEAIAEAAOACADA3AADhAgAgAwAAABEAIAEAABIAMAIAABMAIAEAAAAyACABAAAAMgAgAwAAADAAIAEAADEAMAIAADIAIAMAAAAwACABAAAxADACAAAyACADAAAAMAAgAQAAMQAwAgAAMgAgCQcAAKQFACDBAgEAAAABxwJAAAAAAdsCAQAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHtAgEAAAAB7gIBAAAAAQErAADpAgAgCMECAQAAAAHHAkAAAAAB2wIBAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAe0CAQAAAAHuAgEAAAABASsAAOsCADABKwAA6wIAMAkHAACjBQAgwQIBAPQEACHHAkAA9QQAIdsCAQD0BAAh6gICAP4EACHrAgEA_wQAIewCAQD_BAAh7QIBAP8EACHuAgEA_wQAIQIAAAAyACArAADuAgAgCMECAQD0BAAhxwJAAPUEACHbAgEA9AQAIeoCAgD-BAAh6wIBAP8EACHsAgEA_wQAIe0CAQD_BAAh7gIBAP8EACECAAAAMAAgKwAA8AIAIAIAAAAwACArAADwAgAgAwAAADIAIDIAAOkCACAzAADuAgAgAQAAADIAIAEAAAAwACAJDAAAngUAIDgAAJ8FACA5AACiBQAgOgAAoQUAIDsAAKAFACDrAgAA8AQAIOwCAADwBAAg7QIAAPAEACDuAgAA8AQAIAu-AgAAkQQAML8CAAD3AgAQwAIAAJEEADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHqAgIA_gMAIesCAQD9AwAh7AIBAP0DACHtAgEA_QMAIe4CAQD9AwAhAwAAADAAIAEAAPYCADA3AAD3AgAgAwAAADAAIAEAADEAMAIAADIAIAEAAAA2ACABAAAANgAgAwAAADQAIAEAADUAMAIAADYAIAMAAAA0ACABAAA1ADACAAA2ACADAAAANAAgAQAANQAwAgAANgAgBwcAAJwFACAYAACdBQAgwQIBAAAAAccCQAAAAAHbAgEAAAAB5wIBAAAAAekCAAAA6QICASsAAP8CACAFwQIBAAAAAccCQAAAAAHbAgEAAAAB5wIBAAAAAekCAAAA6QICASsAAIEDADABKwAAgQMAMAEAAAAPACAHBwAAmgUAIBgAAJsFACDBAgEA9AQAIccCQAD1BAAh2wIBAPQEACHnAgEA_wQAIekCAACZBekCIgIAAAA2ACArAACFAwAgBcECAQD0BAAhxwJAAPUEACHbAgEA9AQAIecCAQD_BAAh6QIAAJkF6QIiAgAAADQAICsAAIcDACACAAAANAAgKwAAhwMAIAEAAAAPACADAAAANgAgMgAA_wIAIDMAAIUDACABAAAANgAgAQAAADQAIAQMAACWBQAgOgAAmAUAIDsAAJcFACDnAgAA8AQAIAi-AgAAjQQAML8CAACPAwAQwAIAAI0EADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHnAgEA_QMAIekCAACOBOkCIgMAAAA0ACABAACOAwAwNwAAjwMAIAMAAAA0ACABAAA1ADACAAA2ACABAAAAPAAgAQAAADwAIAMAAAA6ACABAAA7ADACAAA8ACADAAAAOgAgAQAAOwAwAgAAPAAgAwAAADoAIAEAADsAMAIAADwAIAUDAACVBQAgBwAAlAUAIMcCQAAAAAHaAgEAAAAB2wIBAAAAAQErAACXAwAgA8cCQAAAAAHaAgEAAAAB2wIBAAAAAQErAACZAwAwASsAAJkDADAFAwAAkwUAIAcAAJIFACDHAkAA9QQAIdoCAQD0BAAh2wIBAPQEACECAAAAPAAgKwAAnAMAIAPHAkAA9QQAIdoCAQD0BAAh2wIBAPQEACECAAAAOgAgKwAAngMAIAIAAAA6ACArAACeAwAgAwAAADwAIDIAAJcDACAzAACcAwAgAQAAADwAIAEAAAA6ACADDAAAjwUAIDoAAJEFACA7AACQBQAgBr4CAACMBAAwvwIAAKUDABDAAgAAjAQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIQMAAAA6ACABAACkAwAwNwAApQMAIAMAAAA6ACABAAA7ADACAAA8ACABAAAAQAAgAQAAAEAAIAMAAAA-ACABAAA_ADACAABAACADAAAAPgAgAQAAPwAwAgAAQAAgAwAAAD4AIAEAAD8AMAIAAEAAIA4DAACOBQAgBwAAjQUAIMECAQAAAAHHAkAAAAAB2gIBAAAAAdsCAQAAAAHeAgIAAAAB4AIAAADgAgLhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QKAAAAAAeYCAQAAAAEBKwAArQMAIAzBAgEAAAABxwJAAAAAAdoCAQAAAAHbAgEAAAAB3gICAAAAAeACAAAA4AIC4QIBAAAAAeICAQAAAAHjAgEAAAAB5AIBAAAAAeUCgAAAAAHmAgEAAAABASsAAK8DADABKwAArwMAMAEAAAAPACAOAwAAjAUAIAcAAIsFACDBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACECAAAAQAAgKwAAswMAIAzBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACECAAAAPgAgKwAAtQMAIAIAAAA-ACArAAC1AwAgAQAAAA8AIAMAAABAACAyAACtAwAgMwAAswMAIAEAAABAACABAAAAPgAgDQwAAIQFACA4AACFBQAgOQAAiAUAIDoAAIcFACA7AACGBQAg2gIAAPAEACDeAgAA8AQAIOECAADwBAAg4gIAAPAEACDjAgAA8AQAIOQCAADwBAAg5QIAAPAEACDmAgAA8AQAIA--AgAAgwQAML8CAAC9AwAQwAIAAIMEADDBAgEA7wMAIccCQADxAwAh2gIBAP0DACHbAgEA7wMAId4CAgCEBAAh4AIAAIUE4AIi4QIBAP0DACHiAgEA_QMAIeMCAQD9AwAh5AIBAP0DACHlAgAAhgQAIOYCAQD9AwAhAwAAAD4AIAEAALwDADA3AAC9AwAgAwAAAD4AIAEAAD8AMAIAAEAAIAEAAABFACABAAAARQAgAwAAAEMAIAEAAEQAMAIAAEUAIAMAAABDACABAABEADACAABFACADAAAAQwAgAQAARAAwAgAARQAgCQMAAIIFACAHAACDBQAgK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB2wIBAAAAAdwCAgAAAAHdAkAAAAABASsAAMUDACAHK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB2wIBAAAAAdwCAgAAAAHdAkAAAAABASsAAMcDADABKwAAxwMAMAEAAAAXACAJAwAAgAUAIAcAAIEFACArgAAAAAHBAgEA9AQAIccCQAD1BAAh2gIBAPQEACHbAgEA_wQAIdwCAgD-BAAh3QJAAPUEACECAAAARQAgKwAAywMAIAcrgAAAAAHBAgEA9AQAIccCQAD1BAAh2gIBAPQEACHbAgEA_wQAIdwCAgD-BAAh3QJAAPUEACECAAAAQwAgKwAAzQMAIAIAAABDACArAADNAwAgAQAAABcAIAMAAABFACAyAADFAwAgMwAAywMAIAEAAABFACABAAAAQwAgBgwAAPkEACA4AAD6BAAgOQAA_QQAIDoAAPwEACA7AAD7BAAg2wIAAPAEACAKKwAA8AMAIL4CAAD8AwAwvwIAANUDABDAAgAA_AMAMMECAQDvAwAhxwJAAPEDACHaAgEA7wMAIdsCAQD9AwAh3AICAP4DACHdAkAA8QMAIQMAAABDACABAADUAwAwNwAA1QMAIAMAAABDACABAABEADACAABFACABAAAAVAAgAQAAAFQAIAMAAABSACABAABTADACAABUACADAAAAUgAgAQAAUwAwAgAAVAAgAwAAAFIAIAEAAFMAMAIAAFQAIAkgAAD4BAAgwQIBAAAAAcICAQAAAAHDAgEAAAABxAIBAAAAAcUCAQAAAAHGAoAAAAABxwJAAAAAAcgCQAAAAAEBKwAA3QMAIAjBAgEAAAABwgIBAAAAAcMCAQAAAAHEAgEAAAABxQIBAAAAAcYCgAAAAAHHAkAAAAAByAJAAAAAAQErAADfAwAwASsAAN8DADAJIAAA9wQAIMECAQD0BAAhwgIBAPQEACHDAgEA9AQAIcQCAQD0BAAhxQIBAPQEACHGAoAAAAABxwJAAPUEACHIAkAA9gQAIQIAAABUACArAADiAwAgCMECAQD0BAAhwgIBAPQEACHDAgEA9AQAIcQCAQD0BAAhxQIBAPQEACHGAoAAAAABxwJAAPUEACHIAkAA9gQAIQIAAABSACArAADkAwAgAgAAAFIAICsAAOQDACADAAAAVAAgMgAA3QMAIDMAAOIDACABAAAAVAAgAQAAAFIAIAQMAADxBAAgOgAA8wQAIDsAAPIEACDIAgAA8AQAIAu-AgAA7gMAML8CAADrAwAQwAIAAO4DADDBAgEA7wMAIcICAQDvAwAhwwIBAO8DACHEAgEA7wMAIcUCAQDvAwAhxgIAAPADACDHAkAA8QMAIcgCQADyAwAhAwAAAFIAIAEAAOoDADA3AADrAwAgAwAAAFIAIAEAAFMAMAIAAFQAIAu-AgAA7gMAML8CAADrAwAQwAIAAO4DADDBAgEA7wMAIcICAQDvAwAhwwIBAO8DACHEAgEA7wMAIcUCAQDvAwAhxgIAAPADACDHAkAA8QMAIcgCQADyAwAhDgwAAPcDACA6AAD7AwAgOwAA-wMAIMkCAQAAAAHKAgEAAAAEywIBAAAABMwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEA-gMAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQ8MAAD3AwAgOgAA-QMAIDsAAPkDACDJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAELDAAA9wMAIDoAAPgDACA7AAD4AwAgyQJAAAAAAcoCQAAAAATLAkAAAAAEzAJAAAAAAc0CQAAAAAHOAkAAAAABzwJAAAAAAdACQAD2AwAhCwwAAPQDACA6AAD1AwAgOwAA9QMAIMkCQAAAAAHKAkAAAAAFywJAAAAABcwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA8wMAIQsMAAD0AwAgOgAA9QMAIDsAAPUDACDJAkAAAAABygJAAAAABcsCQAAAAAXMAkAAAAABzQJAAAAAAc4CQAAAAAHPAkAAAAAB0AJAAPMDACEIyQICAAAAAcoCAgAAAAXLAgIAAAAFzAICAAAAAc0CAgAAAAHOAgIAAAABzwICAAAAAdACAgD0AwAhCMkCQAAAAAHKAkAAAAAFywJAAAAABcwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA9QMAIQsMAAD3AwAgOgAA-AMAIDsAAPgDACDJAkAAAAABygJAAAAABMsCQAAAAATMAkAAAAABzQJAAAAAAc4CQAAAAAHPAkAAAAAB0AJAAPYDACEIyQICAAAAAcoCAgAAAATLAgIAAAAEzAICAAAAAc0CAgAAAAHOAgIAAAABzwICAAAAAdACAgD3AwAhCMkCQAAAAAHKAkAAAAAEywJAAAAABMwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA-AMAIQzJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAEODAAA9wMAIDoAAPsDACA7AAD7AwAgyQIBAAAAAcoCAQAAAATLAgEAAAAEzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQD6AwAh1wIBAAAAAdgCAQAAAAHZAgEAAAABC8kCAQAAAAHKAgEAAAAEywIBAAAABMwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEA-wMAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQorAADwAwAgvgIAAPwDADC_AgAA1QMAEMACAAD8AwAwwQIBAO8DACHHAkAA8QMAIdoCAQDvAwAh2wIBAP0DACHcAgIA_gMAId0CQADxAwAhDgwAAPQDACA6AACCBAAgOwAAggQAIMkCAQAAAAHKAgEAAAAFywIBAAAABcwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEAgQQAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQ0MAAD3AwAgOAAAgAQAIDkAAPcDACA6AAD3AwAgOwAA9wMAIMkCAgAAAAHKAgIAAAAEywICAAAABMwCAgAAAAHNAgIAAAABzgICAAAAAc8CAgAAAAHQAgIA_wMAIQ0MAAD3AwAgOAAAgAQAIDkAAPcDACA6AAD3AwAgOwAA9wMAIMkCAgAAAAHKAgIAAAAEywICAAAABMwCAgAAAAHNAgIAAAABzgICAAAAAc8CAgAAAAHQAgIA_wMAIQjJAggAAAABygIIAAAABMsCCAAAAATMAggAAAABzQIIAAAAAc4CCAAAAAHPAggAAAAB0AIIAIAEACEODAAA9AMAIDoAAIIEACA7AACCBAAgyQIBAAAAAcoCAQAAAAXLAgEAAAAFzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQCBBAAh1wIBAAAAAdgCAQAAAAHZAgEAAAABC8kCAQAAAAHKAgEAAAAFywIBAAAABcwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEAggQAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQ--AgAAgwQAML8CAAC9AwAQwAIAAIMEADDBAgEA7wMAIccCQADxAwAh2gIBAP0DACHbAgEA7wMAId4CAgCEBAAh4AIAAIUE4AIi4QIBAP0DACHiAgEA_QMAIeMCAQD9AwAh5AIBAP0DACHlAgAAhgQAIOYCAQD9AwAhDQwAAPQDACA4AACLBAAgOQAA9AMAIDoAAPQDACA7AAD0AwAgyQICAAAAAcoCAgAAAAXLAgIAAAAFzAICAAAAAc0CAgAAAAHOAgIAAAABzwICAAAAAdACAgCKBAAhBwwAAPcDACA6AACJBAAgOwAAiQQAIMkCAAAA4AICygIAAADgAgjLAgAAAOACCNACAACIBOACIg8MAAD0AwAgOgAAhwQAIDsAAIcEACDJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAEMyQKAAAAAAcwCgAAAAAHNAoAAAAABzgKAAAAAAc8CgAAAAAHQAoAAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCgAAAAAHWAoAAAAABBwwAAPcDACA6AACJBAAgOwAAiQQAIMkCAAAA4AICygIAAADgAgjLAgAAAOACCNACAACIBOACIgTJAgAAAOACAsoCAAAA4AIIywIAAADgAgjQAgAAiQTgAiINDAAA9AMAIDgAAIsEACA5AAD0AwAgOgAA9AMAIDsAAPQDACDJAgIAAAABygICAAAABcsCAgAAAAXMAgIAAAABzQICAAAAAc4CAgAAAAHPAgIAAAAB0AICAIoEACEIyQIIAAAAAcoCCAAAAAXLAggAAAAFzAIIAAAAAc0CCAAAAAHOAggAAAABzwIIAAAAAdACCACLBAAhBr4CAACMBAAwvwIAAKUDABDAAgAAjAQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIQi-AgAAjQQAML8CAACPAwAQwAIAAI0EADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHnAgEA_QMAIekCAACOBOkCIgcMAAD3AwAgOgAAkAQAIDsAAJAEACDJAgAAAOkCAsoCAAAA6QIIywIAAADpAgjQAgAAjwTpAiIHDAAA9wMAIDoAAJAEACA7AACQBAAgyQIAAADpAgLKAgAAAOkCCMsCAAAA6QII0AIAAI8E6QIiBMkCAAAA6QICygIAAADpAgjLAgAAAOkCCNACAACQBOkCIgu-AgAAkQQAML8CAAD3AgAQwAIAAJEEADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHqAgIA_gMAIesCAQD9AwAh7AIBAP0DACHtAgEA_QMAIe4CAQD9AwAhCL4CAACSBAAwvwIAAOECABDAAgAAkgQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIe0CAQD9AwAh8AIAAJME8AIiBwwAAPcDACA6AACVBAAgOwAAlQQAIMkCAAAA8AICygIAAADwAgjLAgAAAPACCNACAACUBPACIgcMAAD3AwAgOgAAlQQAIDsAAJUEACDJAgAAAPACAsoCAAAA8AIIywIAAADwAgjQAgAAlATwAiIEyQIAAADwAgLKAgAAAPACCMsCAAAA8AII0AIAAJUE8AIiCL4CAACWBAAwvwIAAMsCABDAAgAAlgQAMMECAQDvAwAhxwJAAPEDACHqAgIAhAQAIewCAQDvAwAh8QIBAP0DACEJCwAAnAQAIL4CAACXBAAwvwIAALgCABDAAgAAlwQAMMECAQCYBAAhxwJAAJsEACHqAgIAmQQAIewCAQCYBAAh8QIBAJoEACELyQIBAAAAAcoCAQAAAATLAgEAAAAEzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQD7AwAh1wIBAAAAAdgCAQAAAAHZAgEAAAABCMkCAgAAAAHKAgIAAAAFywICAAAABcwCAgAAAAHNAgIAAAABzgICAAAAAc8CAgAAAAHQAgIA9AMAIQvJAgEAAAABygIBAAAABcsCAQAAAAXMAgEAAAABzQIBAAAAAc4CAQAAAAHPAgEAAAAB0AIBAIIEACHXAgEAAAAB2AIBAAAAAdkCAQAAAAEIyQJAAAAAAcoCQAAAAATLAkAAAAAEzAJAAAAAAc0CQAAAAAHOAkAAAAABzwJAAAAAAdACQAD4AwAhA_ICAAAcACDzAgAAHAAg9AIAABwAIAm-AgAAnQQAML8CAACyAgAQwAIAAJ0EADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHgAgAAngT4AiL1AgIA_gMAIfYCAQDvAwAhBwwAAPcDACA6AACgBAAgOwAAoAQAIMkCAAAA-AICygIAAAD4AgjLAgAAAPgCCNACAACfBPgCIgcMAAD3AwAgOgAAoAQAIDsAAKAEACDJAgAAAPgCAsoCAAAA-AIIywIAAAD4AgjQAgAAnwT4AiIEyQIAAAD4AgLKAgAAAPgCCMsCAAAA-AII0AIAAKAE-AIiB74CAAChBAAwvwIAAJwCABDAAgAAoQQAMMcCQADxAwAh2wIBAO8DACHeAgIA_gMAIfgCAQDvAwAhDr4CAACiBAAwvwIAAIYCABDAAgAAogQAMMcCQADxAwAh2wIBAO8DACHeAgIA_gMAIfkCAQDvAwAh-gIBAP0DACH7AgEA_QMAIfwCAQD9AwAh_QIBAO8DACH-AgEA_QMAIf8CAQD9AwAhgANAAPIDACESvgIAAKMEADC_AgAA8AEAEMACAACjBAAwwQIBAO8DACHHAkAA8QMAId0CQADxAwAh6gICAIQEACGBAwIAhAQAIYIDAQD9AwAhgwMCAIQEACGFAwAApASFAyKGAyAApQQAIYcDIAClBAAhiAMCAP4DACGJAwIA_gMAIYoDAgD-AwAhiwMCAP4DACGMA0AA8gMAIQcMAAD3AwAgOgAAqQQAIDsAAKkEACDJAgAAAIUDAsoCAAAAhQMIywIAAACFAwjQAgAAqASFAyIFDAAA9wMAIDoAAKcEACA7AACnBAAgyQIgAAAAAdACIACmBAAhBQwAAPcDACA6AACnBAAgOwAApwQAIMkCIAAAAAHQAiAApgQAIQLJAiAAAAAB0AIgAKcEACEHDAAA9wMAIDoAAKkEACA7AACpBAAgyQIAAACFAwLKAgAAAIUDCMsCAAAAhQMI0AIAAKgEhQMiBMkCAAAAhQMCygIAAACFAwjLAgAAAIUDCNACAACpBIUDIg6-AgAAqgQAML8CAADUAQAQwAIAAKoEADDBAgEA7wMAIccCQADyAwAh2gIBAO8DACHsAgEA_QMAIY0DAQDvAwAhjgMBAO8DACGPAwIA_gMAIZADAQDvAwAhkQMgAKUEACGSAwEA_QMAIZMDAQD9AwAhCr4CAACrBAAwvwIAAL4BABDAAgAAqwQAMMECAQDvAwAhxwJAAPIDACHaAgEA_QMAId0CQADyAwAhlAMBAO8DACGVAwEA7wMAIZYDQADxAwAhDL4CAACsBAAwvwIAAKYBABDAAgAArAQAMMECAQDvAwAhxwJAAPEDACHaAgEA7wMAId0CQADxAwAh4wIBAP0DACGWA0AA8QMAIZcDAQDvAwAhmAMBAP0DACGZAwEA_QMAIRC-AgAArQQAML8CAACQAQAQwAIAAK0EADDBAgEA7wMAIccCQADxAwAh2gIBAO8DACHdAkAA8QMAIZoDAQDvAwAhmwMBAO8DACGcAwEA_QMAIZ0DAQD9AwAhngNAAPIDACGfA0AA8gMAIaADAQD9AwAhoQMBAP0DACGiAwEA_QMAIRm-AgAArgQAML8CAAB6ABDAAgAArgQAMMECAQDvAwAhxwJAAPEDACHdAkAA8QMAIeoCAgCEBAAh6wIBAP0DACHsAgEA_QMAIfACAQD9AwAhjANAAPIDACGjAyAApQQAIaQDAQD9AwAhpgMAAK8EpgMiqAMAALAEqAMiqQMgAKUEACGqAwEA_QMAIasDAQD9AwAhrAMAAIYEACCtA0AA8gMAIa4DAQD9AwAhrwMgALEEACGwAwEA_QMAIbEDQADyAwAhsgNAAPIDACEHDAAA9wMAIDoAALcEACA7AAC3BAAgyQIAAACmAwLKAgAAAKYDCMsCAAAApgMI0AIAALYEpgMiBwwAAPcDACA6AAC1BAAgOwAAtQQAIMkCAAAAqAMCygIAAACoAwjLAgAAAKgDCNACAAC0BKgDIgUMAAD0AwAgOgAAswQAIDsAALMEACDJAiAAAAAB0AIgALIEACEFDAAA9AMAIDoAALMEACA7AACzBAAgyQIgAAAAAdACIACyBAAhAskCIAAAAAHQAiAAswQAIQcMAAD3AwAgOgAAtQQAIDsAALUEACDJAgAAAKgDAsoCAAAAqAMIywIAAACoAwjQAgAAtASoAyIEyQIAAACoAwLKAgAAAKgDCMsCAAAAqAMI0AIAALUEqAMiBwwAAPcDACA6AAC3BAAgOwAAtwQAIMkCAAAApgMCygIAAACmAwjLAgAAAKYDCNACAAC2BKYDIgTJAgAAAKYDAsoCAAAApgMIywIAAACmAwjQAgAAtwSmAyIPAwAAvAQAIL4CAAC4BAAwvwIAAFkAEMACAAC4BAAwwQIBAJgEACHHAkAAuwQAIdoCAQCYBAAh7AIBAJoEACGNAwEAmAQAIY4DAQCYBAAhjwMCALkEACGQAwEAmAQAIZEDIAC6BAAhkgMBAJoEACGTAwEAmgQAIQjJAgIAAAABygICAAAABMsCAgAAAATMAgIAAAABzQICAAAAAc4CAgAAAAHPAgIAAAAB0AICAPcDACECyQIgAAAAAdACIACnBAAhCMkCQAAAAAHKAkAAAAAFywJAAAAABcwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA9QMAISUEAADoBAAgBQAA6QQAIAYAAOoEACAeAADbBAAgHwAA3QQAICEAAOsEACAiAADeBAAgIwAA3wQAICQAAOAEACAlAADsBAAgvgIAAOQEADC_AgAADwAQwAIAAOQEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIesCAQCaBAAh7AIBAJoEACHwAgEAmgQAIYwDQAC7BAAhowMgALoEACGkAwEAmgQAIaYDAADlBKYDIqgDAADmBKgDIqkDIAC6BAAhqgMBAJoEACGrAwEAmgQAIawDAADDBAAgrQNAALsEACGuAwEAmgQAIa8DIADnBAAhsAMBAJoEACGxA0AAuwQAIbIDQAC7BAAhuAMAAA8AILkDAAAPACAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAJgEACHCAgEAmAQAIcMCAQCYBAAhxAIBAJgEACHFAgEAmAQAIcYCAAC-BAAgxwJAAJsEACHIAkAAuwQAIQzJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAEMAwAAvAQAIAcAAMAEACArAAC-BAAgvgIAAL8EADC_AgAAQwAQwAIAAL8EADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACEgEQAA2QQAIBIAAMAEACATAADOBAAgFAAA2QQAIBUAANoEACAWAADbBAAgFwAA3AQAIBkAAN0EACAaAADPBAAgGwAA3gQAIBwAAN8EACAdAADgBAAgvgIAANcEADC_AgAAFwAQwAIAANcEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhuAMAABcAILkDAAAXACARAwAAxQQAIAcAAMQEACC-AgAAwQQAML8CAAA-ABDAAgAAwQQAMMECAQCYBAAhxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEEyQIAAADgAgLKAgAAAOACCMsCAAAA4AII0AIAAIkE4AIiDMkCgAAAAAHMAoAAAAABzQKAAAAAAc4CgAAAAAHPAoAAAAAB0AKAAAAAAdECAQAAAAHSAgEAAAAB0wIBAAAAAdQCgAAAAAHVAoAAAAAB1gKAAAAAASARAADZBAAgEgAAwAQAIBMAAM4EACAUAADZBAAgFQAA2gQAIBYAANsEACAXAADcBAAgGQAA3QQAIBoAAM8EACAbAADeBAAgHAAA3wQAIB0AAOAEACC-AgAA1wQAML8CAAAXABDAAgAA1wQAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAhgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACG4AwAAFwAguQMAABcAICUEAADoBAAgBQAA6QQAIAYAAOoEACAeAADbBAAgHwAA3QQAICEAAOsEACAiAADeBAAgIwAA3wQAICQAAOAEACAlAADsBAAgvgIAAOQEADC_AgAADwAQwAIAAOQEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIesCAQCaBAAh7AIBAJoEACHwAgEAmgQAIYwDQAC7BAAhowMgALoEACGkAwEAmgQAIaYDAADlBKYDIqgDAADmBKgDIqkDIAC6BAAhqgMBAJoEACGrAwEAmgQAIawDAADDBAAgrQNAALsEACGuAwEAmgQAIa8DIADnBAAhsAMBAJoEACGxA0AAuwQAIbIDQAC7BAAhuAMAAA8AILkDAAAPACAC2gIBAAAAAdsCAQAAAAEIAwAAvAQAIAcAAMQEACC-AgAAxwQAML8CAAA6ABDAAgAAxwQAMMcCQACbBAAh2gIBAJgEACHbAgEAmAQAIQLbAgEAAAAB5wIBAAAAAQoHAADEBAAgGAAAxQQAIL4CAADJBAAwvwIAADQAEMACAADJBAAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiIEyQIAAADpAgLKAgAAAOkCCMsCAAAA6QII0AIAAJAE6QIiDAcAAMQEACC-AgAAywQAML8CAAAwABDAAgAAywQAMMECAQCYBAAhxwJAAJsEACHbAgEAmAQAIeoCAgC5BAAh6wIBAJoEACHsAgEAmgQAIe0CAQCaBAAh7gIBAJoEACEC2wIBAAAAAd4CAgAAAAETBwAAxAQAIAgAAMAEACAJAADOBAAgDgAAnAQAIBAAAM8EACC-AgAAzQQAML8CAAAVABDAAgAAzQQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACED8gIAABcAIPMCAAAXACD0AgAAFwAgA_ICAAAiACDzAgAAIgAg9AIAACIAIAsHAADEBAAgDwAA0gQAIL4CAADQBAAwvwIAACIAEMACAADQBAAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh4AIAANEE-AIi9QICALkEACH2AgEAmAQAIQTJAgAAAPgCAsoCAAAA-AIIywIAAAD4AgjQAgAAoAT4AiIVBwAAxAQAIAgAAMAEACAJAADOBAAgDgAAnAQAIBAAAM8EACC-AgAAzQQAML8CAAAVABDAAgAAzQQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACG4AwAAFQAguQMAABUAIAPbAgEAAAAB3gICAAAAAfgCAQAAAAEJCgAA0gQAIA0AANUEACC-AgAA1AQAML8CAAAcABDAAgAA1AQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfgCAQCYBAAhCwsAAJwEACC-AgAAlwQAML8CAAC4AgAQwAIAAJcEADDBAgEAmAQAIccCQACbBAAh6gICAJkEACHsAgEAmAQAIfECAQCaBAAhuAMAALgCACC5AwAAuAIAIALBAgEAAAABgQMCAAAAAR4RAADZBAAgEgAAwAQAIBMAAM4EACAUAADZBAAgFQAA2gQAIBYAANsEACAXAADcBAAgGQAA3QQAIBoAAM8EACAbAADeBAAgHAAA3wQAIB0AAOAEACC-AgAA1wQAML8CAAAXABDAAgAA1wQAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAhgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACEEyQIAAACFAwLKAgAAAIUDCMsCAAAAhQMI0AIAAKkEhQMiFQcAAMQEACAIAADABAAgCQAAzgQAIA4AAJwEACAQAADPBAAgvgIAAM0EADC_AgAAFQAQwAIAAM0EADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH5AgEAmAQAIfoCAQCaBAAh-wIBAJoEACH8AgEAmgQAIf0CAQCYBAAh_gIBAJoEACH_AgEAmgQAIYADQAC7BAAhuAMAABUAILkDAAAVACAD8gIAABUAIPMCAAAVACD0AgAAFQAgA_ICAAARACDzAgAAEQAg9AIAABEAIAPyAgAAMAAg8wIAADAAIPQCAAAwACAD8gIAADQAIPMCAAA0ACD0AgAANAAgA_ICAAA6ACDzAgAAOgAg9AIAADoAIAPyAgAAPgAg8wIAAD4AIPQCAAA-ACAD8gIAAEMAIPMCAABDACD0AgAAQwAgAtoCAQAAAAHbAgEAAAABCgMAALwEACAHAADEBAAgvgIAAOIEADC_AgAAEQAQwAIAAOIEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACHtAgEAmgQAIfACAADjBPACIgTJAgAAAPACAsoCAAAA8AIIywIAAADwAgjQAgAAlQTwAiIjBAAA6AQAIAUAAOkEACAGAADqBAAgHgAA2wQAIB8AAN0EACAhAADrBAAgIgAA3gQAICMAAN8EACAkAADgBAAgJQAA7AQAIL4CAADkBAAwvwIAAA8AEMACAADkBAAwwQIBAJgEACHHAkAAmwQAId0CQACbBAAh6gICAJkEACHrAgEAmgQAIewCAQCaBAAh8AIBAJoEACGMA0AAuwQAIaMDIAC6BAAhpAMBAJoEACGmAwAA5QSmAyKoAwAA5gSoAyKpAyAAugQAIaoDAQCaBAAhqwMBAJoEACGsAwAAwwQAIK0DQAC7BAAhrgMBAJoEACGvAyAA5wQAIbADAQCaBAAhsQNAALsEACGyA0AAuwQAIQTJAgAAAKYDAsoCAAAApgMIywIAAACmAwjQAgAAtwSmAyIEyQIAAACoAwLKAgAAAKgDCMsCAAAAqAMI0AIAALUEqAMiAskCIAAAAAHQAiAAswQAIQPyAgAAAwAg8wIAAAMAIPQCAAADACAD8gIAAAcAIPMCAAAHACD0AgAABwAgA_ICAAALACDzAgAACwAg9AIAAAsAIAPyAgAAUgAg8wIAAFIAIPQCAABSACAD8gIAAFkAIPMCAABZACD0AgAAWQAgCwMAAMUEACC-AgAA7QQAML8CAAALABDAAgAA7QQAMMECAQCYBAAhxwJAALsEACHaAgEAmgQAId0CQAC7BAAhlAMBAJgEACGVAwEAmAQAIZYDQACbBAAhDQMAALwEACC-AgAA7gQAML8CAAAHABDAAgAA7gQAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAh4wIBAJoEACGWA0AAmwQAIZcDAQCYBAAhmAMBAJoEACGZAwEAmgQAIREDAAC8BAAgvgIAAO8EADC_AgAAAwAQwAIAAO8EADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHdAkAAmwQAIZoDAQCYBAAhmwMBAJgEACGcAwEAmgQAIZ0DAQCaBAAhngNAALsEACGfA0AAuwQAIaADAQCaBAAhoQMBAJoEACGiAwEAmgQAIQAAAAABvQMBAAAAAQG9A0AAAAABAb0DQAAAAAEFMgAAxQkAIDMAAMgJACC6AwAAxgkAILsDAADHCQAgwAMAAAEAIAMyAADFCQAgugMAAMYJACDAAwAAAQAgAAAAAAAFvQMCAAAAAcMDAgAAAAHEAwIAAAABxQMCAAAAAcYDAgAAAAEBvQMBAAAAAQUyAAC9CQAgMwAAwwkAILoDAAC-CQAguwMAAMIJACDAAwAAAQAgBzIAALsJACAzAADACQAgugMAALwJACC7AwAAvwkAIL4DAAAXACC_AwAAFwAgwAMAABoAIAMyAAC9CQAgugMAAL4JACDAAwAAAQAgAzIAALsJACC6AwAAvAkAIMADAAAaACAAAAAAAAW9AwIAAAABwwMCAAAAAcQDAgAAAAHFAwIAAAABxgMCAAAAAQG9AwAAAOACAgUyAACzCQAgMwAAuQkAILoDAAC0CQAguwMAALgJACDAAwAAGgAgBzIAALEJACAzAAC2CQAgugMAALIJACC7AwAAtQkAIL4DAAAPACC_AwAADwAgwAMAAAEAIAMyAACzCQAgugMAALQJACDAAwAAGgAgAzIAALEJACC6AwAAsgkAIMADAAABACAAAAAFMgAAqQkAIDMAAK8JACC6AwAAqgkAILsDAACuCQAgwAMAABoAIAUyAACnCQAgMwAArAkAILoDAACoCQAguwMAAKsJACDAAwAAAQAgAzIAAKkJACC6AwAAqgkAIMADAAAaACADMgAApwkAILoDAACoCQAgwAMAAAEAIAAAAAG9AwAAAOkCAgUyAACfCQAgMwAApQkAILoDAACgCQAguwMAAKQJACDAAwAAGgAgBzIAAJ0JACAzAACiCQAgugMAAJ4JACC7AwAAoQkAIL4DAAAPACC_AwAADwAgwAMAAAEAIAMyAACfCQAgugMAAKAJACDAAwAAGgAgAzIAAJ0JACC6AwAAngkAIMADAAABACAAAAAAAAUyAACYCQAgMwAAmwkAILoDAACZCQAguwMAAJoJACDAAwAAGgAgAzIAAJgJACC6AwAAmQkAIMADAAAaACAAAAABvQMAAADwAgIFMgAAkAkAIDMAAJYJACC6AwAAkQkAILsDAACVCQAgwAMAABoAIAUyAACOCQAgMwAAkwkAILoDAACPCQAguwMAAJIJACDAAwAAAQAgAzIAAJAJACC6AwAAkQkAIMADAAAaACADMgAAjgkAILoDAACPCQAgwAMAAAEAIAAAAAAACzIAALMFADAzAAC4BQAwugMAALQFADC7AwAAtQUAMLwDAAC2BQAgvQMAALcFADC-AwAAtwUAML8DAAC3BQAwwAMAALcFADDBAwAAuQUAMMIDAAC6BQAwBAoAAMAFACDHAkAAAAAB2wIBAAAAAd4CAgAAAAECAAAAHgAgMgAAvwUAIAMAAAAeACAyAAC_BQAgMwAAvQUAIAErAACNCQAwCgoAANIEACANAADVBAAgvgIAANQEADC_AgAAHAAQwAIAANQEADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH4AgEAmAQAIbYDAADTBAAgAgAAAB4AICsAAL0FACACAAAAuwUAICsAALwFACAHvgIAALoFADC_AgAAuwUAEMACAAC6BQAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-AIBAJgEACEHvgIAALoFADC_AgAAuwUAEMACAAC6BQAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-AIBAJgEACEDxwJAAPUEACHbAgEA9AQAId4CAgD-BAAhBAoAAL4FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACEFMgAAiAkAIDMAAIsJACC6AwAAiQkAILsDAACKCQAgwAMAAC0AIAQKAADABQAgxwJAAAAAAdsCAQAAAAHeAgIAAAABAzIAAIgJACC6AwAAiQkAIMADAAAtACAEMgAAswUAMLoDAAC0BQAwvAMAALYFACDAAwAAtwUAMAAAAAAAAAG9AwAAAPgCAgUyAACACQAgMwAAhgkAILoDAACBCQAguwMAAIUJACDAAwAAGgAgBTIAAP4IACAzAACDCQAgugMAAP8IACC7AwAAggkAIMADAAAtACADMgAAgAkAILoDAACBCQAgwAMAABoAIAMyAAD-CAAgugMAAP8IACDAAwAALQAgAAAAAAAFMgAA-QgAIDMAAPwIACC6AwAA-ggAILsDAAD7CAAgwAMAALUCACADMgAA-QgAILoDAAD6CAAgwAMAALUCACAAAAAAAAUyAADZCAAgMwAA9wgAILoDAADaCAAguwMAAPYIACDAAwAAGgAgBzIAAOwGACAzAACGBwAgugMAAO0GACC7AwAAhQcAIL4DAAAXACC_AwAAFwAgwAMAABoAIAsyAADzBQAwMwAA-AUAMLoDAAD0BQAwuwMAAPUFADC8AwAA9gUAIL0DAAD3BQAwvgMAAPcFADC_AwAA9wUAMMADAAD3BQAwwQMAAPkFADDCAwAA-gUAMAsyAADqBQAwMwAA7gUAMLoDAADrBQAwuwMAAOwFADC8AwAA7QUAIL0DAAC3BQAwvgMAALcFADC_AwAAtwUAMMADAAC3BQAwwQMAAO8FADDCAwAAugUAMAsyAADeBQAwMwAA4wUAMLoDAADfBQAwuwMAAOAFADC8AwAA4QUAIL0DAADiBQAwvgMAAOIFADC_AwAA4gUAMMADAADiBQAwwQMAAOQFADDCAwAA5QUAMAUHAADLBQAgwQIBAAAAAccCQAAAAAHgAgAAAPgCAvYCAQAAAAECAAAAJAAgMgAA6QUAIAMAAAAkACAyAADpBQAgMwAA6AUAIAErAAD1CAAwCwcAAMQEACAPAADSBAAgvgIAANAEADC_AgAAIgAQwAIAANAEADDBAgEAAAABxwJAAJsEACHbAgEAmAQAIeACAADRBPgCIvUCAgC5BAAh9gIBAJgEACECAAAAJAAgKwAA6AUAIAIAAADmBQAgKwAA5wUAIAm-AgAA5QUAML8CAADmBQAQwAIAAOUFADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHgAgAA0QT4AiL1AgIAuQQAIfYCAQCYBAAhCb4CAADlBQAwvwIAAOYFABDAAgAA5QUAMMECAQCYBAAhxwJAAJsEACHbAgEAmAQAIeACAADRBPgCIvUCAgC5BAAh9gIBAJgEACEEwQIBAPQEACHHAkAA9QQAIeACAADIBfgCIvYCAQD0BAAhBQcAAMkFACDBAgEA9AQAIccCQAD1BAAh4AIAAMgF-AIi9gIBAPQEACEFBwAAywUAIMECAQAAAAHHAkAAAAAB4AIAAAD4AgL2AgEAAAABAw0AANMFACDHAkAAAAAB-AIBAAAAAQIAAAAeACAyAADyBQAgAwAAAB4AIDIAAPIFACAzAADxBQAgASsAAPQIADACAAAAHgAgKwAA8QUAIAIAAAC7BQAgKwAA8AUAIALHAkAA9QQAIfgCAQD0BAAhAw0AANIFACDHAkAA9QQAIfgCAQD0BAAhAw0AANMFACDHAkAAAAAB-AIBAAAAARgRAAD9BgAgEgAA7gYAIBMAAO8GACAVAADxBgAgFgAA8gYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAIQHACADAAAAGgAgMgAAhAcAIDMAAP8FACABKwAA8wgAMB8RAADZBAAgEgAAwAQAIBMAAM4EACAUAADZBAAgFQAA2gQAIBYAANsEACAXAADcBAAgGQAA3QQAIBoAAM8EACAbAADeBAAgHAAA3wQAIB0AAOAEACC-AgAA1wQAML8CAAAXABDAAgAA1wQAMMECAQAAAAHHAkAAmwQAId0CQACbBAAh6gICAAAAAYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhtwMAANYEACACAAAAGgAgKwAA_wUAIAIAAAD7BQAgKwAA_AUAIBK-AgAA-gUAML8CAAD7BQAQwAIAAPoFADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhEr4CAAD6BQAwvwIAAPsFABDAAgAA-gUAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAhgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACENwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhAb0DAAAAhQMCAb0DIAAAAAEYEQAAgAYAIBIAAIEGACATAACCBgAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEHMgAA4AgAIDMAAPEIACC6AwAA4QgAILsDAADwCAAgvgMAABUAIL8DAAAVACDAAwAALQAgBzIAAOMIACAzAADuCAAgugMAAOQIACC7AwAA7QgAIL4DAAAXACC_AwAAFwAgwAMAABoAIAsyAAD5BgAwMwAA_wYAMLoDAAD6BgAwuwMAAP4GADC8AwAA-wYAIL0DAAD3BQAwvgMAAPcFADC_AwAA9wUAMMADAAD3BQAwwQMAAIAHADDCAwAA-gUAMAsyAADcBgAwMwAA4QYAMLoDAADdBgAwuwMAAN4GADC8AwAA3wYAIL0DAADgBgAwvgMAAOAGADC_AwAA4AYAMMADAADgBgAwwQMAAOIGADDCAwAA4wYAMAsyAADQBgAwMwAA1QYAMLoDAADRBgAwuwMAANIGADC8AwAA0wYAIL0DAADUBgAwvgMAANQGADC_AwAA1AYAMMADAADUBgAwwQMAANYGADDCAwAA1wYAMAsyAADEBgAwMwAAyQYAMLoDAADFBgAwuwMAAMYGADC8AwAAxwYAIL0DAADIBgAwvgMAAMgGADC_AwAAyAYAMMADAADIBgAwwQMAAMoGADDCAwAAywYAMAsyAAC4BgAwMwAAvQYAMLoDAAC5BgAwuwMAALoGADC8AwAAuwYAIL0DAAC8BgAwvgMAALwGADC_AwAAvAYAMMADAAC8BgAwwQMAAL4GADDCAwAAvwYAMAsyAACvBgAwMwAAswYAMLoDAACwBgAwuwMAALEGADC8AwAAsgYAIL0DAADiBQAwvgMAAOIFADC_AwAA4gUAMMADAADiBQAwwQMAALQGADDCAwAA5QUAMAsyAACjBgAwMwAAqAYAMLoDAACkBgAwuwMAAKUGADC8AwAApgYAIL0DAACnBgAwvgMAAKcGADC_AwAApwYAMMADAACnBgAwwQMAAKkGADDCAwAAqgYAMAsyAACXBgAwMwAAnAYAMLoDAACYBgAwuwMAAJkGADC8AwAAmgYAIL0DAACbBgAwvgMAAJsGADC_AwAAmwYAMMADAACbBgAwwQMAAJ0GADDCAwAAngYAMAsyAACLBgAwMwAAkAYAMLoDAACMBgAwuwMAAI0GADC8AwAAjgYAIL0DAACPBgAwvgMAAI8GADC_AwAAjwYAMMADAACPBgAwwQMAAJEGADDCAwAAkgYAMAcDAACCBQAgK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB3AICAAAAAd0CQAAAAAECAAAARQAgMgAAlgYAIAMAAABFACAyAACWBgAgMwAAlQYAIAErAADsCAAwDAMAALwEACAHAADABAAgKwAAvgQAIL4CAAC_BAAwvwIAAEMAEMACAAC_BAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACECAAAARQAgKwAAlQYAIAIAAACTBgAgKwAAlAYAIAorAAC-BAAgvgIAAJIGADC_AgAAkwYAEMACAACSBgAwwQIBAJgEACHHAkAAmwQAIdoCAQCYBAAh2wIBAJoEACHcAgIAuQQAId0CQACbBAAhCisAAL4EACC-AgAAkgYAML8CAACTBgAQwAIAAJIGADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACEGK4AAAAABwQIBAPQEACHHAkAA9QQAIdoCAQD0BAAh3AICAP4EACHdAkAA9QQAIQcDAACABQAgK4AAAAABwQIBAPQEACHHAkAA9QQAIdoCAQD0BAAh3AICAP4EACHdAkAA9QQAIQcDAACCBQAgK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB3AICAAAAAd0CQAAAAAEMAwAAjgUAIMECAQAAAAHHAkAAAAAB2gIBAAAAAd4CAgAAAAHgAgAAAOACAuECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAoAAAAAB5gIBAAAAAQIAAABAACAyAACiBgAgAwAAAEAAIDIAAKIGACAzAAChBgAgASsAAOsIADARAwAAxQQAIAcAAMQEACC-AgAAwQQAML8CAAA-ABDAAgAAwQQAMMECAQAAAAHHAkAAmwQAIdoCAQCaBAAh2wIBAJgEACHeAgIAmQQAIeACAADCBOACIuECAQCaBAAh4gIBAJoEACHjAgEAmgQAIeQCAQCaBAAh5QIAAMMEACDmAgEAmgQAIQIAAABAACArAAChBgAgAgAAAJ8GACArAACgBgAgD74CAACeBgAwvwIAAJ8GABDAAgAAngYAMMECAQCYBAAhxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEPvgIAAJ4GADC_AgAAnwYAEMACAACeBgAwwQIBAJgEACHHAkAAmwQAIdoCAQCaBAAh2wIBAJgEACHeAgIAmQQAIeACAADCBOACIuECAQCaBAAh4gIBAJoEACHjAgEAmgQAIeQCAQCaBAAh5QIAAMMEACDmAgEAmgQAIQvBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHeAgIAiQUAIeACAACKBeACIuECAQD_BAAh4gIBAP8EACHjAgEA_wQAIeQCAQD_BAAh5QKAAAAAAeYCAQD_BAAhDAMAAIwFACDBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHeAgIAiQUAIeACAACKBeACIuECAQD_BAAh4gIBAP8EACHjAgEA_wQAIeQCAQD_BAAh5QKAAAAAAeYCAQD_BAAhDAMAAI4FACDBAgEAAAABxwJAAAAAAdoCAQAAAAHeAgIAAAAB4AIAAADgAgLhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QKAAAAAAeYCAQAAAAEDAwAAlQUAIMcCQAAAAAHaAgEAAAABAgAAADwAIDIAAK4GACADAAAAPAAgMgAArgYAIDMAAK0GACABKwAA6ggAMAkDAAC8BAAgBwAAxAQAIL4CAADHBAAwvwIAADoAEMACAADHBAAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAhswMAAMYEACACAAAAPAAgKwAArQYAIAIAAACrBgAgKwAArAYAIAa-AgAAqgYAML8CAACrBgAQwAIAAKoGADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACEGvgIAAKoGADC_AgAAqwYAEMACAACqBgAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAhAscCQAD1BAAh2gIBAPQEACEDAwAAkwUAIMcCQAD1BAAh2gIBAPQEACEDAwAAlQUAIMcCQAAAAAHaAgEAAAABBg8AAMwFACDBAgEAAAABxwJAAAAAAeACAAAA-AIC9QICAAAAAfYCAQAAAAECAAAAJAAgMgAAtwYAIAMAAAAkACAyAAC3BgAgMwAAtgYAIAErAADpCAAwAgAAACQAICsAALYGACACAAAA5gUAICsAALUGACAFwQIBAPQEACHHAkAA9QQAIeACAADIBfgCIvUCAgD-BAAh9gIBAPQEACEGDwAAygUAIMECAQD0BAAhxwJAAPUEACHgAgAAyAX4AiL1AgIA_gQAIfYCAQD0BAAhBg8AAMwFACDBAgEAAAABxwJAAAAAAeACAAAA-AIC9QICAAAAAfYCAQAAAAEFGAAAnQUAIMECAQAAAAHHAkAAAAAB5wIBAAAAAekCAAAA6QICAgAAADYAIDIAAMMGACADAAAANgAgMgAAwwYAIDMAAMIGACABKwAA6AgAMAsHAADEBAAgGAAAxQQAIL4CAADJBAAwvwIAADQAEMACAADJBAAwwQIBAAAAAccCQACbBAAh2wIBAJgEACHnAgEAmgQAIekCAADKBOkCIrQDAADIBAAgAgAAADYAICsAAMIGACACAAAAwAYAICsAAMEGACAIvgIAAL8GADC_AgAAwAYAEMACAAC_BgAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiIIvgIAAL8GADC_AgAAwAYAEMACAAC_BgAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiIEwQIBAPQEACHHAkAA9QQAIecCAQD_BAAh6QIAAJkF6QIiBRgAAJsFACDBAgEA9AQAIccCQAD1BAAh5wIBAP8EACHpAgAAmQXpAiIFGAAAnQUAIMECAQAAAAHHAkAAAAAB5wIBAAAAAekCAAAA6QICB8ECAQAAAAHHAkAAAAAB6gICAAAAAesCAQAAAAHsAgEAAAAB7QIBAAAAAe4CAQAAAAECAAAAMgAgMgAAzwYAIAMAAAAyACAyAADPBgAgMwAAzgYAIAErAADnCAAwDAcAAMQEACC-AgAAywQAML8CAAAwABDAAgAAywQAMMECAQAAAAHHAkAAmwQAIdsCAQCYBAAh6gICAAAAAesCAQCaBAAh7AIBAJoEACHtAgEAmgQAIe4CAQCaBAAhAgAAADIAICsAAM4GACACAAAAzAYAICsAAM0GACALvgIAAMsGADC_AgAAzAYAEMACAADLBgAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh6gICALkEACHrAgEAmgQAIewCAQCaBAAh7QIBAJoEACHuAgEAmgQAIQu-AgAAywYAML8CAADMBgAQwAIAAMsGADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHqAgIAuQQAIesCAQCaBAAh7AIBAJoEACHtAgEAmgQAIe4CAQCaBAAhB8ECAQD0BAAhxwJAAPUEACHqAgIA_gQAIesCAQD_BAAh7AIBAP8EACHtAgEA_wQAIe4CAQD_BAAhB8ECAQD0BAAhxwJAAPUEACHqAgIA_gQAIesCAQD_BAAh7AIBAP8EACHtAgEA_wQAIe4CAQD_BAAhB8ECAQAAAAHHAkAAAAAB6gICAAAAAesCAQAAAAHsAgEAAAAB7QIBAAAAAe4CAQAAAAEFAwAArAUAIMcCQAAAAAHaAgEAAAAB7QIBAAAAAfACAAAA8AICAgAAABMAIDIAANsGACADAAAAEwAgMgAA2wYAIDMAANoGACABKwAA5ggAMAsDAAC8BAAgBwAAxAQAIL4CAADiBAAwvwIAABEAEMACAADiBAAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAh7QIBAJoEACHwAgAA4wTwAiKzAwAA4QQAIAIAAAATACArAADaBgAgAgAAANgGACArAADZBgAgCL4CAADXBgAwvwIAANgGABDAAgAA1wYAMMcCQACbBAAh2gIBAJgEACHbAgEAmAQAIe0CAQCaBAAh8AIAAOME8AIiCL4CAADXBgAwvwIAANgGABDAAgAA1wYAMMcCQACbBAAh2gIBAJgEACHbAgEAmAQAIe0CAQCaBAAh8AIAAOME8AIiBMcCQAD1BAAh2gIBAPQEACHtAgEA_wQAIfACAACoBfACIgUDAACqBQAgxwJAAPUEACHaAgEA9AQAIe0CAQD_BAAh8AIAAKgF8AIiBQMAAKwFACDHAkAAAAAB2gIBAAAAAe0CAQAAAAHwAgAAAPACAg4IAADoBgAgCQAA6QYAIA4AAOoGACAQAADrBgAgxwJAAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQIAAAAtACAyAADnBgAgAwAAAC0AIDIAAOcGACAzAADmBgAgASsAAOUIADAUBwAAxAQAIAgAAMAEACAJAADOBAAgDgAAnAQAIBAAAM8EACC-AgAAzQQAML8CAAAVABDAAgAAzQQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACG1AwAAzAQAIAIAAAAtACArAADmBgAgAgAAAOQGACArAADlBgAgDr4CAADjBgAwvwIAAOQGABDAAgAA4wYAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACEOvgIAAOMGADC_AgAA5AYAEMACAADjBgAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-QIBAJgEACH6AgEAmgQAIfsCAQCaBAAh_AIBAJoEACH9AgEAmAQAIf4CAQCaBAAh_wIBAJoEACGAA0AAuwQAIQrHAkAA9QQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQ4IAADaBQAgCQAA2wUAIA4AANwFACAQAADdBQAgxwJAAPUEACHeAgIA_gQAIfkCAQD0BAAh-gIBAP8EACH7AgEA_wQAIfwCAQD_BAAh_QIBAPQEACH-AgEA_wQAIf8CAQD_BAAhgANAAPYEACEOCAAA6AYAIAkAAOkGACAOAADqBgAgEAAA6wYAIMcCQAAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAEDMgAA7AYAILoDAADtBgAgwAMAABoAIAQyAADzBQAwugMAAPQFADC8AwAA9gUAIMADAAD3BQAwBDIAAOoFADC6AwAA6wUAMLwDAADtBQAgwAMAALcFADAEMgAA3gUAMLoDAADfBQAwvAMAAOEFACDAAwAA4gUAMBgSAADuBgAgEwAA7wYAIBQAAPAGACAVAADxBgAgFgAA8gYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMcCQAAAAAHdAkAAAAAB6gICAAAAAYIDAQAAAAGDAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAOwGACADMgAA4wgAILoDAADkCAAgwAMAABoAIAQyAAD5BgAwugMAAPoGADC8AwAA-wYAIMADAAD3BQAwAzIAANsIACC6AwAA3AgAIMADAAAtACAEMgAA3AYAMLoDAADdBgAwvAMAAN8GACDAAwAA4AYAMAQyAADQBgAwugMAANEGADC8AwAA0wYAIMADAADUBgAwBDIAAMQGADC6AwAAxQYAMLwDAADHBgAgwAMAAMgGADAEMgAAuAYAMLoDAAC5BgAwvAMAALsGACDAAwAAvAYAMAQyAACvBgAwugMAALAGADC8AwAAsgYAIMADAADiBQAwBDIAAKMGADC6AwAApAYAMLwDAACmBgAgwAMAAKcGADAEMgAAlwYAMLoDAACYBgAwvAMAAJoGACDAAwAAmwYAMAQyAACLBgAwugMAAIwGADC8AwAAjgYAIMADAACPBgAwGREAAP0GACATAADvBgAgFAAA8AYAIBUAAPEGACAWAADyBgAgFwAA8wYAIBkAAPQGACAaAAD1BgAgGwAA9gYAIBwAAPcGACAdAAD4BgAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAYEDAgAAAAGDAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAPwGACABKwAA4ggAMBkRAAD9BgAgEwAA7wYAIBQAAPAGACAVAADxBgAgFgAA8gYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABgwMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQMyAADgCAAgugMAAOEIACDAAwAALQAgAwAAABoAIDIAAPwGACAzAACCBwAgAgAAABoAICsAAIIHACACAAAA-wUAICsAAIEHACAOwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEZEQAAgAYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIQcyAADbCAAgMwAA3ggAILoDAADcCAAguwMAAN0IACC-AwAAFQAgvwMAABUAIMADAAAtACAYEQAA_QYAIBIAAO4GACATAADvBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHAAA9wYAIB0AAPgGACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAABgQMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQMAAAAXACAyAADsBgAgMwAAhwcAIBoAAAAXACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAIcHACDHAkAA9QQAId0CQAD1BAAh6gICAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEYEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDHAkAA9QQAId0CQAD1BAAh6gICAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEDMgAA2QgAILoDAADaCAAgwAMAABoAIAAAAAAAAAAAAAAFMgAA1AgAIDMAANcIACC6AwAA1QgAILsDAADWCAAgwAMAAAEAIAMyAADUCAAgugMAANUIACDAAwAAAQAgAAAABzIAAM8IACAzAADSCAAgugMAANAIACC7AwAA0QgAIL4DAAAPACC_AwAADwAgwAMAAAEAIAMyAADPCAAgugMAANAIACDAAwAAAQAgAAAABTIAAMoIACAzAADNCAAgugMAAMsIACC7AwAAzAgAIMADAAABACADMgAAyggAILoDAADLCAAgwAMAAAEAIAAAAAUyAADFCAAgMwAAyAgAILoDAADGCAAguwMAAMcIACDAAwAAAQAgAzIAAMUIACC6AwAAxggAIMADAAABACAAAAAAAAG9AwAAAKYDAgG9AwAAAKgDAgG9AyAAAAABCzIAAJMIADAzAACYCAAwugMAAJQIADC7AwAAlQgAMLwDAACWCAAgvQMAAJcIADC-AwAAlwgAML8DAACXCAAwwAMAAJcIADDBAwAAmQgAMMIDAACaCAAwCzIAAIcIADAzAACMCAAwugMAAIgIADC7AwAAiQgAMLwDAACKCAAgvQMAAIsIADC-AwAAiwgAML8DAACLCAAwwAMAAIsIADDBAwAAjQgAMMIDAACOCAAwCzIAAPsHADAzAACACAAwugMAAPwHADC7AwAA_QcAMLwDAAD-BwAgvQMAAP8HADC-AwAA_wcAML8DAAD_BwAwwAMAAP8HADDBAwAAgQgAMMIDAACCCAAwCzIAAPIHADAzAAD2BwAwugMAAPMHADC7AwAA9AcAMLwDAAD1BwAgvQMAANQGADC-AwAA1AYAML8DAADUBgAwwAMAANQGADDBAwAA9wcAMMIDAADXBgAwCzIAAOkHADAzAADtBwAwugMAAOoHADC7AwAA6wcAMLwDAADsBwAgvQMAALwGADC-AwAAvAYAML8DAAC8BgAwwAMAALwGADDBAwAA7gcAMMIDAAC_BgAwCzIAAN0HADAzAADiBwAwugMAAN4HADC7AwAA3wcAMLwDAADgBwAgvQMAAOEHADC-AwAA4QcAML8DAADhBwAwwAMAAOEHADDBAwAA4wcAMMIDAADkBwAwCzIAANQHADAzAADYBwAwugMAANUHADC7AwAA1gcAMLwDAADXBwAgvQMAAKcGADC-AwAApwYAML8DAACnBgAwwAMAAKcGADDBAwAA2QcAMMIDAACqBgAwCzIAAMsHADAzAADPBwAwugMAAMwHADC7AwAAzQcAMLwDAADOBwAgvQMAAJsGADC-AwAAmwYAML8DAACbBgAwwAMAAJsGADDBAwAA0AcAMMIDAACeBgAwCzIAAMIHADAzAADGBwAwugMAAMMHADC7AwAAxAcAMLwDAADFBwAgvQMAAI8GADC-AwAAjwYAML8DAACPBgAwwAMAAI8GADDBAwAAxwcAMMIDAACSBgAwCzIAALYHADAzAAC7BwAwugMAALcHADC7AwAAuAcAMLwDAAC5BwAgvQMAALoHADC-AwAAugcAML8DAAC6BwAwwAMAALoHADDBAwAAvAcAMMIDAAC9BwAwCsECAQAAAAHHAkAAAAAB7AIBAAAAAY0DAQAAAAGOAwEAAAABjwMCAAAAAZADAQAAAAGRAyAAAAABkgMBAAAAAZMDAQAAAAECAAAAWwAgMgAAwQcAIAMAAABbACAyAADBBwAgMwAAwAcAIAErAADECAAwDwMAALwEACC-AgAAuAQAML8CAABZABDAAgAAuAQAMMECAQAAAAHHAkAAuwQAIdoCAQCYBAAh7AIBAJoEACGNAwEAmAQAIY4DAQCYBAAhjwMCALkEACGQAwEAmAQAIZEDIAC6BAAhkgMBAJoEACGTAwEAmgQAIQIAAABbACArAADABwAgAgAAAL4HACArAAC_BwAgDr4CAAC9BwAwvwIAAL4HABDAAgAAvQcAMMECAQCYBAAhxwJAALsEACHaAgEAmAQAIewCAQCaBAAhjQMBAJgEACGOAwEAmAQAIY8DAgC5BAAhkAMBAJgEACGRAyAAugQAIZIDAQCaBAAhkwMBAJoEACEOvgIAAL0HADC_AgAAvgcAEMACAAC9BwAwwQIBAJgEACHHAkAAuwQAIdoCAQCYBAAh7AIBAJoEACGNAwEAmAQAIY4DAQCYBAAhjwMCALkEACGQAwEAmAQAIZEDIAC6BAAhkgMBAJoEACGTAwEAmgQAIQrBAgEA9AQAIccCQAD2BAAh7AIBAP8EACGNAwEA9AQAIY4DAQD0BAAhjwMCAP4EACGQAwEA9AQAIZEDIAD-BQAhkgMBAP8EACGTAwEA_wQAIQrBAgEA9AQAIccCQAD2BAAh7AIBAP8EACGNAwEA9AQAIY4DAQD0BAAhjwMCAP4EACGQAwEA9AQAIZEDIAD-BQAhkgMBAP8EACGTAwEA_wQAIQrBAgEAAAABxwJAAAAAAewCAQAAAAGNAwEAAAABjgMBAAAAAY8DAgAAAAGQAwEAAAABkQMgAAAAAZIDAQAAAAGTAwEAAAABBwcAAIMFACArgAAAAAHBAgEAAAABxwJAAAAAAdsCAQAAAAHcAgIAAAAB3QJAAAAAAQIAAABFACAyAADKBwAgAwAAAEUAIDIAAMoHACAzAADJBwAgASsAAMMIADACAAAARQAgKwAAyQcAIAIAAACTBgAgKwAAyAcAIAYrgAAAAAHBAgEA9AQAIccCQAD1BAAh2wIBAP8EACHcAgIA_gQAId0CQAD1BAAhBwcAAIEFACArgAAAAAHBAgEA9AQAIccCQAD1BAAh2wIBAP8EACHcAgIA_gQAId0CQAD1BAAhBwcAAIMFACArgAAAAAHBAgEAAAABxwJAAAAAAdsCAQAAAAHcAgIAAAAB3QJAAAAAAQwHAACNBQAgwQIBAAAAAccCQAAAAAHbAgEAAAAB3gICAAAAAeACAAAA4AIC4QIBAAAAAeICAQAAAAHjAgEAAAAB5AIBAAAAAeUCgAAAAAHmAgEAAAABAgAAAEAAIDIAANMHACADAAAAQAAgMgAA0wcAIDMAANIHACABKwAAwggAMAIAAABAACArAADSBwAgAgAAAJ8GACArAADRBwAgC8ECAQD0BAAhxwJAAPUEACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACEMBwAAiwUAIMECAQD0BAAhxwJAAPUEACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACEMBwAAjQUAIMECAQAAAAHHAkAAAAAB2wIBAAAAAd4CAgAAAAHgAgAAAOACAuECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAoAAAAAB5gIBAAAAAQMHAACUBQAgxwJAAAAAAdsCAQAAAAECAAAAPAAgMgAA3AcAIAMAAAA8ACAyAADcBwAgMwAA2wcAIAErAADBCAAwAgAAADwAICsAANsHACACAAAAqwYAICsAANoHACACxwJAAPUEACHbAgEA9AQAIQMHAACSBQAgxwJAAPUEACHbAgEA9AQAIQMHAACUBQAgxwJAAAAAAdsCAQAAAAEHwQIBAAAAAcICAQAAAAHEAgEAAAABxQIBAAAAAcYCgAAAAAHHAkAAAAAByAJAAAAAAQIAAABUACAyAADoBwAgAwAAAFQAIDIAAOgHACAzAADnBwAgASsAAMAIADAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAAAAAcICAQCYBAAhwwIBAJgEACHEAgEAmAQAIcUCAQCYBAAhxgIAAL4EACDHAkAAmwQAIcgCQAC7BAAhAgAAAFQAICsAAOcHACACAAAA5QcAICsAAOYHACALvgIAAOQHADC_AgAA5QcAEMACAADkBwAwwQIBAJgEACHCAgEAmAQAIcMCAQCYBAAhxAIBAJgEACHFAgEAmAQAIcYCAAC-BAAgxwJAAJsEACHIAkAAuwQAIQu-AgAA5AcAML8CAADlBwAQwAIAAOQHADDBAgEAmAQAIcICAQCYBAAhwwIBAJgEACHEAgEAmAQAIcUCAQCYBAAhxgIAAL4EACDHAkAAmwQAIcgCQAC7BAAhB8ECAQD0BAAhwgIBAPQEACHEAgEA9AQAIcUCAQD0BAAhxgKAAAAAAccCQAD1BAAhyAJAAPYEACEHwQIBAPQEACHCAgEA9AQAIcQCAQD0BAAhxQIBAPQEACHGAoAAAAABxwJAAPUEACHIAkAA9gQAIQfBAgEAAAABwgIBAAAAAcQCAQAAAAHFAgEAAAABxgKAAAAAAccCQAAAAAHIAkAAAAABBQcAAJwFACDBAgEAAAABxwJAAAAAAdsCAQAAAAHpAgAAAOkCAgIAAAA2ACAyAADxBwAgAwAAADYAIDIAAPEHACAzAADwBwAgASsAAL8IADACAAAANgAgKwAA8AcAIAIAAADABgAgKwAA7wcAIATBAgEA9AQAIccCQAD1BAAh2wIBAPQEACHpAgAAmQXpAiIFBwAAmgUAIMECAQD0BAAhxwJAAPUEACHbAgEA9AQAIekCAACZBekCIgUHAACcBQAgwQIBAAAAAccCQAAAAAHbAgEAAAAB6QIAAADpAgIFBwAAqwUAIMcCQAAAAAHbAgEAAAAB7QIBAAAAAfACAAAA8AICAgAAABMAIDIAAPoHACADAAAAEwAgMgAA-gcAIDMAAPkHACABKwAAvggAMAIAAAATACArAAD5BwAgAgAAANgGACArAAD4BwAgBMcCQAD1BAAh2wIBAPQEACHtAgEA_wQAIfACAACoBfACIgUHAACpBQAgxwJAAPUEACHbAgEA9AQAIe0CAQD_BAAh8AIAAKgF8AIiBQcAAKsFACDHAkAAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgbBAgEAAAABxwJAAAAAAd0CQAAAAAGUAwEAAAABlQMBAAAAAZYDQAAAAAECAAAADQAgMgAAhggAIAMAAAANACAyAACGCAAgMwAAhQgAIAErAAC9CAAwCwMAAMUEACC-AgAA7QQAML8CAAALABDAAgAA7QQAMMECAQAAAAHHAkAAuwQAIdoCAQCaBAAh3QJAALsEACGUAwEAmAQAIZUDAQCYBAAhlgNAAJsEACECAAAADQAgKwAAhQgAIAIAAACDCAAgKwAAhAgAIAq-AgAAgggAML8CAACDCAAQwAIAAIIIADDBAgEAmAQAIccCQAC7BAAh2gIBAJoEACHdAkAAuwQAIZQDAQCYBAAhlQMBAJgEACGWA0AAmwQAIQq-AgAAgggAML8CAACDCAAQwAIAAIIIADDBAgEAmAQAIccCQAC7BAAh2gIBAJoEACHdAkAAuwQAIZQDAQCYBAAhlQMBAJgEACGWA0AAmwQAIQbBAgEA9AQAIccCQAD2BAAh3QJAAPYEACGUAwEA9AQAIZUDAQD0BAAhlgNAAPUEACEGwQIBAPQEACHHAkAA9gQAId0CQAD2BAAhlAMBAPQEACGVAwEA9AQAIZYDQAD1BAAhBsECAQAAAAHHAkAAAAAB3QJAAAAAAZQDAQAAAAGVAwEAAAABlgNAAAAAAQjBAgEAAAABxwJAAAAAAd0CQAAAAAHjAgEAAAABlgNAAAAAAZcDAQAAAAGYAwEAAAABmQMBAAAAAQIAAAAJACAyAACSCAAgAwAAAAkAIDIAAJIIACAzAACRCAAgASsAALwIADANAwAAvAQAIL4CAADuBAAwvwIAAAcAEMACAADuBAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHdAkAAmwQAIeMCAQCaBAAhlgNAAJsEACGXAwEAAAABmAMBAJoEACGZAwEAmgQAIQIAAAAJACArAACRCAAgAgAAAI8IACArAACQCAAgDL4CAACOCAAwvwIAAI8IABDAAgAAjggAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAh4wIBAJoEACGWA0AAmwQAIZcDAQCYBAAhmAMBAJoEACGZAwEAmgQAIQy-AgAAjggAML8CAACPCAAQwAIAAI4IADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHdAkAAmwQAIeMCAQCaBAAhlgNAAJsEACGXAwEAmAQAIZgDAQCaBAAhmQMBAJoEACEIwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh4wIBAP8EACGWA0AA9QQAIZcDAQD0BAAhmAMBAP8EACGZAwEA_wQAIQjBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHjAgEA_wQAIZYDQAD1BAAhlwMBAPQEACGYAwEA_wQAIZkDAQD_BAAhCMECAQAAAAHHAkAAAAAB3QJAAAAAAeMCAQAAAAGWA0AAAAABlwMBAAAAAZgDAQAAAAGZAwEAAAABDMECAQAAAAHHAkAAAAAB3QJAAAAAAZoDAQAAAAGbAwEAAAABnAMBAAAAAZ0DAQAAAAGeA0AAAAABnwNAAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAQIAAAAFACAyAACeCAAgAwAAAAUAIDIAAJ4IACAzAACdCAAgASsAALsIADARAwAAvAQAIL4CAADvBAAwvwIAAAMAEMACAADvBAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHdAkAAmwQAIZoDAQCYBAAhmwMBAJgEACGcAwEAmgQAIZ0DAQCaBAAhngNAALsEACGfA0AAuwQAIaADAQCaBAAhoQMBAJoEACGiAwEAmgQAIQIAAAAFACArAACdCAAgAgAAAJsIACArAACcCAAgEL4CAACaCAAwvwIAAJsIABDAAgAAmggAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhEL4CAACaCAAwvwIAAJsIABDAAgAAmggAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhDMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIZoDAQD0BAAhmwMBAPQEACGcAwEA_wQAIZ0DAQD_BAAhngNAAPYEACGfA0AA9gQAIaADAQD_BAAhoQMBAP8EACGiAwEA_wQAIQzBAgEA9AQAIccCQAD1BAAh3QJAAPUEACGaAwEA9AQAIZsDAQD0BAAhnAMBAP8EACGdAwEA_wQAIZ4DQAD2BAAhnwNAAPYEACGgAwEA_wQAIaEDAQD_BAAhogMBAP8EACEMwQIBAAAAAccCQAAAAAHdAkAAAAABmgMBAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABBDIAAJMIADC6AwAAlAgAMLwDAACWCAAgwAMAAJcIADAEMgAAhwgAMLoDAACICAAwvAMAAIoIACDAAwAAiwgAMAQyAAD7BwAwugMAAPwHADC8AwAA_gcAIMADAAD_BwAwBDIAAPIHADC6AwAA8wcAMLwDAAD1BwAgwAMAANQGADAEMgAA6QcAMLoDAADqBwAwvAMAAOwHACDAAwAAvAYAMAQyAADdBwAwugMAAN4HADC8AwAA4AcAIMADAADhBwAwBDIAANQHADC6AwAA1QcAMLwDAADXBwAgwAMAAKcGADAEMgAAywcAMLoDAADMBwAwvAMAAM4HACDAAwAAmwYAMAQyAADCBwAwugMAAMMHADC8AwAAxQcAIMADAACPBgAwBDIAALYHADC6AwAAtwcAMLwDAAC5BwAgwAMAALoHADAAAAAAAAAAAAAAGQQAAKkIACAFAACqCAAgBgAAqwgAIB4AAKwIACAfAACtCAAgIQAArggAICIAAK8IACAjAACwCAAgJAAAsQgAICUAALIIACDqAgAA8AQAIOsCAADwBAAg7AIAAPAEACDwAgAA8AQAIIwDAADwBAAgpAMAAPAEACCqAwAA8AQAIKsDAADwBAAgrAMAAPAEACCtAwAA8AQAIK4DAADwBAAgrwMAAPAEACCwAwAA8AQAILEDAADwBAAgsgMAAPAEACAREQAAtwgAIBIAALQIACATAAC1CAAgFAAAtwgAIBUAALkIACAWAACsCAAgFwAAuggAIBkAAK0IACAaAAC2CAAgGwAArwgAIBwAALAIACAdAACxCAAg6gIAAPAEACCBAwAA8AQAIIIDAADwBAAggwMAAPAEACCMAwAA8AQAIAAACwcAALQIACAIAAC0CAAgCQAAtQgAIA4AAMIFACAQAAC2CAAg-gIAAPAEACD7AgAA8AQAIPwCAADwBAAg_gIAAPAEACD_AgAA8AQAIIADAADwBAAgAwsAAMIFACDqAgAA8AQAIPECAADwBAAgAAAMwQIBAAAAAccCQAAAAAHdAkAAAAABmgMBAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABCMECAQAAAAHHAkAAAAAB3QJAAAAAAeMCAQAAAAGWA0AAAAABlwMBAAAAAZgDAQAAAAGZAwEAAAABBsECAQAAAAHHAkAAAAAB3QJAAAAAAZQDAQAAAAGVAwEAAAABlgNAAAAAAQTHAkAAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgTBAgEAAAABxwJAAAAAAdsCAQAAAAHpAgAAAOkCAgfBAgEAAAABwgIBAAAAAcQCAQAAAAHFAgEAAAABxgKAAAAAAccCQAAAAAHIAkAAAAABAscCQAAAAAHbAgEAAAABC8ECAQAAAAHHAkAAAAAB2wIBAAAAAd4CAgAAAAHgAgAAAOACAuECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAoAAAAAB5gIBAAAAAQYrgAAAAAHBAgEAAAABxwJAAAAAAdsCAQAAAAHcAgIAAAAB3QJAAAAAAQrBAgEAAAABxwJAAAAAAewCAQAAAAGNAwEAAAABjgMBAAAAAY8DAgAAAAGQAwEAAAABkQMgAAAAAZIDAQAAAAGTAwEAAAABHwUAAKAIACAGAAChCAAgHgAAoggAIB8AAKMIACAhAACkCAAgIgAApQgAICMAAKYIACAkAACnCAAgJQAAqAgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADFCAAgAwAAAA8AIDIAAMUIACAzAADJCAAgIQAAAA8AIAUAAK0HACAGAACuBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAICsAAMkIACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAJ8IACAGAAChCAAgHgAAoggAIB8AAKMIACAhAACkCAAgIgAApQgAICMAAKYIACAkAACnCAAgJQAAqAgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADKCAAgAwAAAA8AIDIAAMoIACAzAADOCAAgIQAAAA8AIAQAAKwHACAGAACuBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAICsAAM4IACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBAAArAcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAJ8IACAFAACgCAAgHgAAoggAIB8AAKMIACAhAACkCAAgIgAApQgAICMAAKYIACAkAACnCAAgJQAAqAgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADPCAAgAwAAAA8AIDIAAM8IACAzAADTCAAgIQAAAA8AIAQAAKwHACAFAACtBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAICsAANMIACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBAAArAcAIAUAAK0HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAJ8IACAFAACgCAAgBgAAoQgAIB4AAKIIACAfAACjCAAgIQAApAgAICIAAKUIACAjAACmCAAgJAAApwgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADUCAAgAwAAAA8AIDIAANQIACAzAADYCAAgIQAAAA8AIAQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICIAALIHACAjAACzBwAgJAAAtAcAICsAANgIACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBAAArAcAIAUAAK0HACAGAACuBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhGhEAAP0GACASAADuBgAgEwAA7wYAIBQAAPAGACAWAADyBgAgFwAA8wYAIBkAAPQGACAaAAD1BgAgGwAA9gYAIBwAAPcGACAdAAD4BgAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAYEDAgAAAAGCAwEAAAABgwMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQIAAAAaACAyAADZCAAgDwcAAIgHACAIAADoBgAgDgAA6gYAIBAAAOsGACDHAkAAAAAB2wIBAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQIAAAAtACAyAADbCAAgAwAAABUAIDIAANsIACAzAADfCAAgEQAAABUAIAcAANkFACAIAADaBQAgDgAA3AUAIBAAAN0FACArAADfCAAgxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQ8HAADZBQAgCAAA2gUAIA4AANwFACAQAADdBQAgxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQ8HAACIBwAgCQAA6QYAIA4AAOoGACAQAADrBgAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAECAAAALQAgMgAA4AgAIA7BAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAABgQMCAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAEaEQAA_QYAIBIAAO4GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHAAA9wYAIB0AAPgGACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAABgQMCAAAAAYIDAQAAAAGDAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAOMIACAKxwJAAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQTHAkAAAAAB2gIBAAAAAe0CAQAAAAHwAgAAAPACAgfBAgEAAAABxwJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAe0CAQAAAAHuAgEAAAABBMECAQAAAAHHAkAAAAAB5wIBAAAAAekCAAAA6QICBcECAQAAAAHHAkAAAAAB4AIAAAD4AgL1AgIAAAAB9gIBAAAAAQLHAkAAAAAB2gIBAAAAAQvBAgEAAAABxwJAAAAAAdoCAQAAAAHeAgIAAAAB4AIAAADgAgLhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QKAAAAAAeYCAQAAAAEGK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB3AICAAAAAd0CQAAAAAEDAAAAFwAgMgAA4wgAIDMAAO8IACAcAAAAFwAgEQAAgAYAIBIAAIEGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACArAADvCAAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAACABgAgEgAAgQYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEDAAAAFQAgMgAA4AgAIDMAAPIIACARAAAAFQAgBwAA2QUAIAkAANsFACAOAADcBQAgEAAA3QUAICsAAPIIACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhDwcAANkFACAJAADbBQAgDgAA3AUAIBAAAN0FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhDcECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAscCQAAAAAH4AgEAAAABBMECAQAAAAHHAkAAAAAB4AIAAAD4AgL2AgEAAAABAwAAABcAIDIAANkIACAzAAD4CAAgHAAAABcAIBEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAWAACEBgAgFwAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgKwAA-AgAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEaEQAAgAYAIBIAAIEGACATAACCBgAgFAAAgwcAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhBcECAQAAAAHHAkAAAAAB6gICAAAAAewCAQAAAAHxAgEAAAABAgAAALUCACAyAAD5CAAgAwAAALgCACAyAAD5CAAgMwAA_QgAIAcAAAC4AgAgKwAA_QgAIMECAQD0BAAhxwJAAPUEACHqAgIAiQUAIewCAQD0BAAh8QIBAP8EACEFwQIBAPQEACHHAkAA9QQAIeoCAgCJBQAh7AIBAPQEACHxAgEA_wQAIQ8HAACIBwAgCAAA6AYAIAkAAOkGACAOAADqBgAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAECAAAALQAgMgAA_ggAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAgAkAIAMAAAAVACAyAAD-CAAgMwAAhAkAIBEAAAAVACAHAADZBQAgCAAA2gUAIAkAANsFACAOAADcBQAgKwAAhAkAIMcCQAD1BAAh2wIBAPQEACHeAgIA_gQAIfkCAQD0BAAh-gIBAP8EACH7AgEA_wQAIfwCAQD_BAAh_QIBAPQEACH-AgEA_wQAIf8CAQD_BAAhgANAAPYEACEPBwAA2QUAIAgAANoFACAJAADbBQAgDgAA3AUAIMcCQAD1BAAh2wIBAPQEACHeAgIA_gQAIfkCAQD0BAAh-gIBAP8EACH7AgEA_wQAIfwCAQD_BAAh_QIBAPQEACH-AgEA_wQAIf8CAQD_BAAhgANAAPYEACEDAAAAFwAgMgAAgAkAIDMAAIcJACAcAAAAFwAgEQAAgAYAIBIAAIEGACATAACCBgAgFAAAgwcAIBUAAIMGACAWAACEBgAgFwAAhQYAIBkAAIYGACAbAACIBgAgHAAAiQYAIB0AAIoGACArAACHCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBsAAIgGACAcAACJBgAgHQAAigYAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEPBwAAiAcAIAgAAOgGACAJAADpBgAgEAAA6wYAIMcCQAAAAAHbAgEAAAAB3gICAAAAAfkCAQAAAAH6AgEAAAAB-wIBAAAAAfwCAQAAAAH9AgEAAAAB_gIBAAAAAf8CAQAAAAGAA0AAAAABAgAAAC0AIDIAAIgJACADAAAAFQAgMgAAiAkAIDMAAIwJACARAAAAFQAgBwAA2QUAIAgAANoFACAJAADbBQAgEAAA3QUAICsAAIwJACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhDwcAANkFACAIAADaBQAgCQAA2wUAIBAAAN0FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhA8cCQAAAAAHbAgEAAAAB3gICAAAAAR8EAACfCAAgBQAAoAgAIAYAAKEIACAfAACjCAAgIQAApAgAICIAAKUIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAjgkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAkAkAIAMAAAAPACAyAACOCQAgMwAAlAkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAfAACwBwAgIQAAsQcAICIAALIHACAjAACzBwAgJAAAtAcAICUAALUHACArAACUCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACQCQAgMwAAlwkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAJcJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFwAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAmAkAIAMAAAAXACAyAACYCQAgMwAAnAkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAJwJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBkAAIYGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgIQAApAgAICIAAKUIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAnQkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAnwkAIAMAAAAPACAyAACdCQAgMwAAowkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgIQAAsQcAICIAALIHACAjAACzBwAgJAAAtAcAICUAALUHACArAACjCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACfCQAgMwAApgkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAKYJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAApwkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAqQkAIAMAAAAPACAyAACnCQAgMwAArQkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAjAACzBwAgJAAAtAcAICUAALUHACArAACtCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACpCQAgMwAAsAkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAcAACJBgAgHQAAigYAICsAALAJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAiAAClCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAsQkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAswkAIAMAAAAPACAyAACxCQAgMwAAtwkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgJAAAtAcAICUAALUHACArAAC3CQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICIAALIHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACzCQAgMwAAugkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHQAAigYAICsAALoJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHAAA9wYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAuwkAIB8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAiAAClCAAgIwAApggAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAvQkAIAMAAAAXACAyAAC7CQAgMwAAwQkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAICsAAMEJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIQMAAAAPACAyAAC9CQAgMwAAxAkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICUAALUHACArAADECQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICIAALIHACAjAACzBwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICIAAKUIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAxQkAIAMAAAAPACAyAADFCQAgMwAAyQkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICIAALIHACAjAACzBwAgJAAAtAcAICUAALUHACArAADJCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQsEBgIFCgMGDgQMABUeFAUfUQ4hVRMiVg8jVxAkWBElXBQBAwABAQMAAQEDEAECAwABBwAGDQwAEhEWBxIpBhMqBhQrBxUuBxYvBRczDRk3Dho5Cxs9DxxBEB1GEQYHAAYIGAYJGwYMAAwOHwgQJQsCCgAHDQAJAgsgCAwACgELIQACBwAGDwAHAwkmAA4nABAoAAEHAAYCBwAGGDgBAgMAAQcABgIDQgEHAAYCAwABB0cGCRNIABVJABZKABdLABlMABpNABtOABxPAB1QAAEgAAEBAwABCgRdAAVeAAZfAB5gAB9hACFiACJjACNkACRlACVmAAAAAAUMABo4ABs5ABw6AB07AB4AAAAAAAUMABo4ABs5ABw6AB07AB4BAwABAQMAAQMMACM6ACQ7ACUAAAADDAAjOgAkOwAlAQMAAQEDAAEDDAAqOgArOwAsAAAAAwwAKjoAKzsALAEDswEBAQO5AQEDDAAxOgAyOwAzAAAAAwwAMToAMjsAMwEDAAEBAwABBQwAODgAOTkAOjoAOzsAPAAAAAAABQwAODgAOTkAOjoAOzsAPAMR4QEHEuIBBhTjAQcDEekBBxLqAQYU6wEHBQwAQTgAQjkAQzoARDsARQAAAAAABQwAQTgAQjkAQzoARDsARQEHAAYBBwAGBQwASjgASzkATDoATTsATgAAAAAABQwASjgASzkATDoATTsATgIKAAcNAAkCCgAHDQAJBQwAUzgAVDkAVToAVjsAVwAAAAAABQwAUzgAVDkAVToAVjsAVwIHAAYPAAcCBwAGDwAHBQwAXDgAXTkAXjoAXzsAYAAAAAAABQwAXDgAXTkAXjoAXzsAYAAABQwAZTgAZjkAZzoAaDsAaQAAAAAABQwAZTgAZjkAZzoAaDsAaQIDAAEHAAYCAwABBwAGAwwAbjoAbzsAcAAAAAMMAG46AG87AHABBwAGAQcABgUMAHU4AHY5AHc6AHg7AHkAAAAAAAUMAHU4AHY5AHc6AHg7AHkCBwAGGIQDAQIHAAYYigMBAwwAfjoAfzsAgAEAAAADDAB-OgB_OwCAAQIDAAEHAAYCAwABBwAGAwwAhQE6AIYBOwCHAQAAAAMMAIUBOgCGATsAhwECA7IDAQcABgIDuAMBBwAGBQwAjAE4AI0BOQCOAToAjwE7AJABAAAAAAAFDACMATgAjQE5AI4BOgCPATsAkAECAwABB8oDBgIDAAEH0AMGBQwAlQE4AJYBOQCXAToAmAE7AJkBAAAAAAAFDACVATgAlgE5AJcBOgCYATsAmQEBIAABASAAAQMMAJ4BOgCfATsAoAEAAAADDACeAToAnwE7AKABJgIBJ2cBKGkBKWoBKmsBLG0BLW8WLnAXL3IBMHQWMXUYNHYBNXcBNngWPHsZPXwfPn0CP34CQH8CQYABAkKBAQJDgwECRIUBFkWGASBGiAECR4oBFkiLASFJjAECSo0BAkuOARZMkQEiTZIBJk6TAQNPlAEDUJUBA1GWAQNSlwEDU5kBA1SbARZVnAEnVp4BA1egARZYoQEoWaIBA1qjAQNbpAEWXKcBKV2oAS1eqQEEX6oBBGCrAQRhrAEEYq0BBGOvAQRksQEWZbIBLma1AQRntwEWaLgBL2m6AQRquwEEa7wBFmy_ATBtwAE0bsEBFG_CARRwwwEUccQBFHLFARRzxwEUdMkBFnXKATV2zAEUd84BFnjPATZ50AEUetEBFHvSARZ81QE3fdYBPX7XAQZ_2AEGgAHZAQaBAdoBBoIB2wEGgwHdAQaEAd8BFoUB4AE-hgHlAQaHAecBFogB6AE_iQHsAQaKAe0BBosB7gEWjAHxAUCNAfIBRo4B8wEHjwH0AQeQAfUBB5EB9gEHkgH3AQeTAfkBB5QB-wEWlQH8AUeWAf4BB5cBgAIWmAGBAkiZAYICB5oBgwIHmwGEAhacAYcCSZ0BiAJPngGJAgifAYoCCKABiwIIoQGMAgiiAY0CCKMBjwIIpAGRAhalAZICUKYBlAIIpwGWAhaoAZcCUakBmAIIqgGZAgirAZoCFqwBnQJSrQGeAliuAZ8CC68BoAILsAGhAguxAaICC7IBowILswGlAgu0AacCFrUBqAJZtgGqAgu3AawCFrgBrQJauQGuAgu6Aa8CC7sBsAIWvAGzAlu9AbQCYb4BtgIJvwG3AgnAAboCCcEBuwIJwgG8AgnDAb4CCcQBwAIWxQHBAmLGAcMCCccBxQIWyAHGAmPJAccCCcoByAIJywHJAhbMAcwCZM0BzQJqzgHOAgXPAc8CBdAB0AIF0QHRAgXSAdICBdMB1AIF1AHWAhbVAdcCa9YB2QIF1wHbAhbYAdwCbNkB3QIF2gHeAgXbAd8CFtwB4gJt3QHjAnHeAeQCDd8B5QIN4AHmAg3hAecCDeIB6AIN4wHqAg3kAewCFuUB7QJy5gHvAg3nAfECFugB8gJz6QHzAg3qAfQCDesB9QIW7AH4AnTtAfkCeu4B-gIO7wH7Ag7wAfwCDvEB_QIO8gH-Ag7zAYADDvQBggMW9QGDA3v2AYYDDvcBiAMW-AGJA3z5AYsDDvoBjAMO-wGNAxb8AZADff0BkQOBAf4BkgMP_wGTAw-AApQDD4EClQMPggKWAw-DApgDD4QCmgMWhQKbA4IBhgKdAw-HAp8DFogCoAODAYkCoQMPigKiAw-LAqMDFowCpgOEAY0CpwOIAY4CqAMQjwKpAxCQAqoDEJECqwMQkgKsAxCTAq4DEJQCsAMWlQKxA4kBlgK0AxCXArYDFpgCtwOKAZkCuQMQmgK6AxCbArsDFpwCvgOLAZ0CvwORAZ4CwAMRnwLBAxGgAsIDEaECwwMRogLEAxGjAsYDEaQCyAMWpQLJA5IBpgLMAxGnAs4DFqgCzwOTAakC0QMRqgLSAxGrAtMDFqwC1gOUAa0C1wOaAa4C2AMTrwLZAxOwAtoDE7EC2wMTsgLcAxOzAt4DE7QC4AMWtQLhA5sBtgLjAxO3AuUDFrgC5gOcAbkC5wMTugLoAxO7AukDFrwC7AOdAb0C7QOhAQ" } config.compilerWasm = { getRuntime: async () => require('./query_compiler_fast_bg.js'), diff --git a/apps/modeling-commons-backend/generated/prisma/index-browser.js b/apps/modeling-commons-backend/generated/prisma/index-browser.js index 336afaf2..287d073d 100644 --- a/apps/modeling-commons-backend/generated/prisma/index-browser.js +++ b/apps/modeling-commons-backend/generated/prisma/index-browser.js @@ -257,6 +257,18 @@ exports.Prisma.ModelAuthorScalarFieldEnum = { modelId: 'modelId', userId: 'userId', role: 'role', + collaboratorType: 'collaboratorType', + createdAt: 'createdAt' +}; + +exports.Prisma.NonMemberContributorScalarFieldEnum = { + id: 'id', + legacyId: 'legacyId', + modelId: 'modelId', + email: 'email', + name: 'name', + collaboratorType: 'collaboratorType', + addedByUserId: 'addedByUserId', createdAt: 'createdAt' }; @@ -393,6 +405,7 @@ exports.Prisma.ModelName = { ModelAdditionalFile: 'ModelAdditionalFile', Tag: 'Tag', ModelAuthor: 'ModelAuthor', + NonMemberContributor: 'NonMemberContributor', ModelPermission: 'ModelPermission', ModelLike: 'ModelLike', ModelInteraction: 'ModelInteraction', diff --git a/apps/modeling-commons-backend/generated/prisma/index.d.ts b/apps/modeling-commons-backend/generated/prisma/index.d.ts index 19fb5cd9..a8ffbcbf 100644 --- a/apps/modeling-commons-backend/generated/prisma/index.d.ts +++ b/apps/modeling-commons-backend/generated/prisma/index.d.ts @@ -68,6 +68,11 @@ export type Tag = $Result.DefaultSelection * */ export type ModelAuthor = $Result.DefaultSelection +/** + * Model NonMemberContributor + * + */ +export type NonMemberContributor = $Result.DefaultSelection /** * Model ModelPermission * @@ -421,6 +426,16 @@ export class PrismaClient< */ get modelAuthor(): Prisma.ModelAuthorDelegate; + /** + * `prisma.nonMemberContributor`: Exposes CRUD operations for the **NonMemberContributor** model. + * Example usage: + * ```ts + * // Fetch zero or more NonMemberContributors + * const nonMemberContributors = await prisma.nonMemberContributor.findMany() + * ``` + */ + get nonMemberContributor(): Prisma.NonMemberContributorDelegate; + /** * `prisma.modelPermission`: Exposes CRUD operations for the **ModelPermission** model. * Example usage: @@ -915,6 +930,7 @@ export namespace Prisma { ModelAdditionalFile: 'ModelAdditionalFile', Tag: 'Tag', ModelAuthor: 'ModelAuthor', + NonMemberContributor: 'NonMemberContributor', ModelPermission: 'ModelPermission', ModelLike: 'ModelLike', ModelInteraction: 'ModelInteraction', @@ -935,7 +951,7 @@ export namespace Prisma { omit: GlobalOmitOptions } meta: { - modelProps: "user" | "account" | "session" | "verification" | "passkey" | "model" | "modelVersion" | "modelVersionTag" | "modelAdditionalFile" | "tag" | "modelAuthor" | "modelPermission" | "modelLike" | "modelInteraction" | "modelDraft" | "event" + modelProps: "user" | "account" | "session" | "verification" | "passkey" | "model" | "modelVersion" | "modelVersionTag" | "modelAdditionalFile" | "tag" | "modelAuthor" | "nonMemberContributor" | "modelPermission" | "modelLike" | "modelInteraction" | "modelDraft" | "event" txIsolationLevel: Prisma.TransactionIsolationLevel } model: { @@ -1753,6 +1769,80 @@ export namespace Prisma { } } } + NonMemberContributor: { + payload: Prisma.$NonMemberContributorPayload + fields: Prisma.NonMemberContributorFieldRefs + operations: { + findUnique: { + args: Prisma.NonMemberContributorFindUniqueArgs + result: $Utils.PayloadToResult | null + } + findUniqueOrThrow: { + args: Prisma.NonMemberContributorFindUniqueOrThrowArgs + result: $Utils.PayloadToResult + } + findFirst: { + args: Prisma.NonMemberContributorFindFirstArgs + result: $Utils.PayloadToResult | null + } + findFirstOrThrow: { + args: Prisma.NonMemberContributorFindFirstOrThrowArgs + result: $Utils.PayloadToResult + } + findMany: { + args: Prisma.NonMemberContributorFindManyArgs + result: $Utils.PayloadToResult[] + } + create: { + args: Prisma.NonMemberContributorCreateArgs + result: $Utils.PayloadToResult + } + createMany: { + args: Prisma.NonMemberContributorCreateManyArgs + result: BatchPayload + } + createManyAndReturn: { + args: Prisma.NonMemberContributorCreateManyAndReturnArgs + result: $Utils.PayloadToResult[] + } + delete: { + args: Prisma.NonMemberContributorDeleteArgs + result: $Utils.PayloadToResult + } + update: { + args: Prisma.NonMemberContributorUpdateArgs + result: $Utils.PayloadToResult + } + deleteMany: { + args: Prisma.NonMemberContributorDeleteManyArgs + result: BatchPayload + } + updateMany: { + args: Prisma.NonMemberContributorUpdateManyArgs + result: BatchPayload + } + updateManyAndReturn: { + args: Prisma.NonMemberContributorUpdateManyAndReturnArgs + result: $Utils.PayloadToResult[] + } + upsert: { + args: Prisma.NonMemberContributorUpsertArgs + result: $Utils.PayloadToResult + } + aggregate: { + args: Prisma.NonMemberContributorAggregateArgs + result: $Utils.Optional + } + groupBy: { + args: Prisma.NonMemberContributorGroupByArgs + result: $Utils.Optional[] + } + count: { + args: Prisma.NonMemberContributorCountArgs + result: $Utils.Optional | number + } + } + } ModelPermission: { payload: Prisma.$ModelPermissionPayload fields: Prisma.ModelPermissionFieldRefs @@ -2242,6 +2332,7 @@ export namespace Prisma { modelAdditionalFile?: ModelAdditionalFileOmit tag?: TagOmit modelAuthor?: ModelAuthorOmit + nonMemberContributor?: NonMemberContributorOmit modelPermission?: ModelPermissionOmit modelLike?: ModelLikeOmit modelInteraction?: ModelInteractionOmit @@ -2442,6 +2533,7 @@ export namespace Prisma { childModels: number versions: number authors: number + nonMemberContributors: number permissions: number additionalFiles: number likes: number @@ -2453,6 +2545,7 @@ export namespace Prisma { childModels?: boolean | ModelCountOutputTypeCountChildModelsArgs versions?: boolean | ModelCountOutputTypeCountVersionsArgs authors?: boolean | ModelCountOutputTypeCountAuthorsArgs + nonMemberContributors?: boolean | ModelCountOutputTypeCountNonMemberContributorsArgs permissions?: boolean | ModelCountOutputTypeCountPermissionsArgs additionalFiles?: boolean | ModelCountOutputTypeCountAdditionalFilesArgs likes?: boolean | ModelCountOutputTypeCountLikesArgs @@ -2492,6 +2585,13 @@ export namespace Prisma { where?: ModelAuthorWhereInput } + /** + * ModelCountOutputType without action + */ + export type ModelCountOutputTypeCountNonMemberContributorsArgs = { + where?: NonMemberContributorWhereInput + } + /** * ModelCountOutputType without action */ @@ -9063,6 +9163,7 @@ export namespace Prisma { parentVersion?: boolean | Model$parentVersionArgs versions?: boolean | Model$versionsArgs authors?: boolean | Model$authorsArgs + nonMemberContributors?: boolean | Model$nonMemberContributorsArgs permissions?: boolean | Model$permissionsArgs additionalFiles?: boolean | Model$additionalFilesArgs likes?: boolean | Model$likesArgs @@ -9139,6 +9240,7 @@ export namespace Prisma { parentVersion?: boolean | Model$parentVersionArgs versions?: boolean | Model$versionsArgs authors?: boolean | Model$authorsArgs + nonMemberContributors?: boolean | Model$nonMemberContributorsArgs permissions?: boolean | Model$permissionsArgs additionalFiles?: boolean | Model$additionalFilesArgs likes?: boolean | Model$likesArgs @@ -9166,6 +9268,7 @@ export namespace Prisma { parentVersion: Prisma.$ModelVersionPayload | null versions: Prisma.$ModelVersionPayload[] authors: Prisma.$ModelAuthorPayload[] + nonMemberContributors: Prisma.$NonMemberContributorPayload[] permissions: Prisma.$ModelPermissionPayload[] additionalFiles: Prisma.$ModelAdditionalFilePayload[] likes: Prisma.$ModelLikePayload[] @@ -9588,6 +9691,7 @@ export namespace Prisma { parentVersion = {}>(args?: Subset>): Prisma__ModelVersionClient<$Result.GetResult, T, "findUniqueOrThrow", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> versions = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions> | Null> authors = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions> | Null> + nonMemberContributors = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions> | Null> permissions = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions> | Null> additionalFiles = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions> | Null> likes = {}>(args?: Subset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions> | Null> @@ -10166,6 +10270,30 @@ export namespace Prisma { distinct?: ModelAuthorScalarFieldEnum | ModelAuthorScalarFieldEnum[] } + /** + * Model.nonMemberContributors + */ + export type Model$nonMemberContributorsArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + where?: NonMemberContributorWhereInput + orderBy?: NonMemberContributorOrderByWithRelationInput | NonMemberContributorOrderByWithRelationInput[] + cursor?: NonMemberContributorWhereUniqueInput + take?: number + skip?: number + distinct?: NonMemberContributorScalarFieldEnum | NonMemberContributorScalarFieldEnum[] + } + /** * Model.permissions */ @@ -14922,6 +15050,7 @@ export namespace Prisma { modelId: string | null userId: string | null role: $Enums.AuthorRole | null + collaboratorType: string | null createdAt: Date | null } @@ -14929,6 +15058,7 @@ export namespace Prisma { modelId: string | null userId: string | null role: $Enums.AuthorRole | null + collaboratorType: string | null createdAt: Date | null } @@ -14936,6 +15066,7 @@ export namespace Prisma { modelId: number userId: number role: number + collaboratorType: number createdAt: number _all: number } @@ -14945,6 +15076,7 @@ export namespace Prisma { modelId?: true userId?: true role?: true + collaboratorType?: true createdAt?: true } @@ -14952,6 +15084,7 @@ export namespace Prisma { modelId?: true userId?: true role?: true + collaboratorType?: true createdAt?: true } @@ -14959,6 +15092,7 @@ export namespace Prisma { modelId?: true userId?: true role?: true + collaboratorType?: true createdAt?: true _all?: true } @@ -15039,6 +15173,7 @@ export namespace Prisma { modelId: string userId: string role: $Enums.AuthorRole + collaboratorType: string | null createdAt: Date _count: ModelAuthorCountAggregateOutputType | null _min: ModelAuthorMinAggregateOutputType | null @@ -15063,6 +15198,7 @@ export namespace Prisma { modelId?: boolean userId?: boolean role?: boolean + collaboratorType?: boolean createdAt?: boolean model?: boolean | ModelDefaultArgs user?: boolean | UserDefaultArgs @@ -15072,6 +15208,7 @@ export namespace Prisma { modelId?: boolean userId?: boolean role?: boolean + collaboratorType?: boolean createdAt?: boolean model?: boolean | ModelDefaultArgs user?: boolean | UserDefaultArgs @@ -15081,6 +15218,7 @@ export namespace Prisma { modelId?: boolean userId?: boolean role?: boolean + collaboratorType?: boolean createdAt?: boolean model?: boolean | ModelDefaultArgs user?: boolean | UserDefaultArgs @@ -15090,10 +15228,11 @@ export namespace Prisma { modelId?: boolean userId?: boolean role?: boolean + collaboratorType?: boolean createdAt?: boolean } - export type ModelAuthorOmit = $Extensions.GetOmit<"modelId" | "userId" | "role" | "createdAt", ExtArgs["result"]["modelAuthor"]> + export type ModelAuthorOmit = $Extensions.GetOmit<"modelId" | "userId" | "role" | "collaboratorType" | "createdAt", ExtArgs["result"]["modelAuthor"]> export type ModelAuthorInclude = { model?: boolean | ModelDefaultArgs user?: boolean | UserDefaultArgs @@ -15117,6 +15256,7 @@ export namespace Prisma { modelId: string userId: string role: $Enums.AuthorRole + collaboratorType: string | null createdAt: Date }, ExtArgs["result"]["modelAuthor"]> composites: {} @@ -15546,6 +15686,7 @@ export namespace Prisma { readonly modelId: FieldRef<"ModelAuthor", 'String'> readonly userId: FieldRef<"ModelAuthor", 'String'> readonly role: FieldRef<"ModelAuthor", 'AuthorRole'> + readonly collaboratorType: FieldRef<"ModelAuthor", 'String'> readonly createdAt: FieldRef<"ModelAuthor", 'DateTime'> } @@ -15967,357 +16108,420 @@ export namespace Prisma { /** - * Model ModelPermission + * Model NonMemberContributor */ - export type AggregateModelPermission = { - _count: ModelPermissionCountAggregateOutputType | null - _min: ModelPermissionMinAggregateOutputType | null - _max: ModelPermissionMaxAggregateOutputType | null + export type AggregateNonMemberContributor = { + _count: NonMemberContributorCountAggregateOutputType | null + _avg: NonMemberContributorAvgAggregateOutputType | null + _sum: NonMemberContributorSumAggregateOutputType | null + _min: NonMemberContributorMinAggregateOutputType | null + _max: NonMemberContributorMaxAggregateOutputType | null } - export type ModelPermissionMinAggregateOutputType = { + export type NonMemberContributorAvgAggregateOutputType = { + legacyId: number | null + } + + export type NonMemberContributorSumAggregateOutputType = { + legacyId: number | null + } + + export type NonMemberContributorMinAggregateOutputType = { id: string | null + legacyId: number | null modelId: string | null - granteeUserId: string | null - permissionLevel: $Enums.PermissionLevel | null + email: string | null + name: string | null + collaboratorType: string | null + addedByUserId: string | null createdAt: Date | null } - export type ModelPermissionMaxAggregateOutputType = { + export type NonMemberContributorMaxAggregateOutputType = { id: string | null + legacyId: number | null modelId: string | null - granteeUserId: string | null - permissionLevel: $Enums.PermissionLevel | null + email: string | null + name: string | null + collaboratorType: string | null + addedByUserId: string | null createdAt: Date | null } - export type ModelPermissionCountAggregateOutputType = { + export type NonMemberContributorCountAggregateOutputType = { id: number + legacyId: number modelId: number - granteeUserId: number - permissionLevel: number + email: number + name: number + collaboratorType: number + addedByUserId: number createdAt: number _all: number } - export type ModelPermissionMinAggregateInputType = { + export type NonMemberContributorAvgAggregateInputType = { + legacyId?: true + } + + export type NonMemberContributorSumAggregateInputType = { + legacyId?: true + } + + export type NonMemberContributorMinAggregateInputType = { id?: true + legacyId?: true modelId?: true - granteeUserId?: true - permissionLevel?: true + email?: true + name?: true + collaboratorType?: true + addedByUserId?: true createdAt?: true } - export type ModelPermissionMaxAggregateInputType = { + export type NonMemberContributorMaxAggregateInputType = { id?: true + legacyId?: true modelId?: true - granteeUserId?: true - permissionLevel?: true + email?: true + name?: true + collaboratorType?: true + addedByUserId?: true createdAt?: true } - export type ModelPermissionCountAggregateInputType = { + export type NonMemberContributorCountAggregateInputType = { id?: true + legacyId?: true modelId?: true - granteeUserId?: true - permissionLevel?: true + email?: true + name?: true + collaboratorType?: true + addedByUserId?: true createdAt?: true _all?: true } - export type ModelPermissionAggregateArgs = { + export type NonMemberContributorAggregateArgs = { /** - * Filter which ModelPermission to aggregate. + * Filter which NonMemberContributor to aggregate. */ - where?: ModelPermissionWhereInput + where?: NonMemberContributorWhereInput /** * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} * - * Determine the order of ModelPermissions to fetch. + * Determine the order of NonMemberContributors to fetch. */ - orderBy?: ModelPermissionOrderByWithRelationInput | ModelPermissionOrderByWithRelationInput[] + orderBy?: NonMemberContributorOrderByWithRelationInput | NonMemberContributorOrderByWithRelationInput[] /** * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} * * Sets the start position */ - cursor?: ModelPermissionWhereUniqueInput + cursor?: NonMemberContributorWhereUniqueInput /** * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} * - * Take `±n` ModelPermissions from the position of the cursor. + * Take `±n` NonMemberContributors from the position of the cursor. */ take?: number /** * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} * - * Skip the first `n` ModelPermissions. + * Skip the first `n` NonMemberContributors. */ skip?: number /** * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} * - * Count returned ModelPermissions + * Count returned NonMemberContributors **/ - _count?: true | ModelPermissionCountAggregateInputType + _count?: true | NonMemberContributorCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to average + **/ + _avg?: NonMemberContributorAvgAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to sum + **/ + _sum?: NonMemberContributorSumAggregateInputType /** * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} * * Select which fields to find the minimum value **/ - _min?: ModelPermissionMinAggregateInputType + _min?: NonMemberContributorMinAggregateInputType /** * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} * * Select which fields to find the maximum value **/ - _max?: ModelPermissionMaxAggregateInputType + _max?: NonMemberContributorMaxAggregateInputType } - export type GetModelPermissionAggregateType = { - [P in keyof T & keyof AggregateModelPermission]: P extends '_count' | 'count' + export type GetNonMemberContributorAggregateType = { + [P in keyof T & keyof AggregateNonMemberContributor]: P extends '_count' | 'count' ? T[P] extends true ? number - : GetScalarType - : GetScalarType + : GetScalarType + : GetScalarType } - export type ModelPermissionGroupByArgs = { - where?: ModelPermissionWhereInput - orderBy?: ModelPermissionOrderByWithAggregationInput | ModelPermissionOrderByWithAggregationInput[] - by: ModelPermissionScalarFieldEnum[] | ModelPermissionScalarFieldEnum - having?: ModelPermissionScalarWhereWithAggregatesInput + export type NonMemberContributorGroupByArgs = { + where?: NonMemberContributorWhereInput + orderBy?: NonMemberContributorOrderByWithAggregationInput | NonMemberContributorOrderByWithAggregationInput[] + by: NonMemberContributorScalarFieldEnum[] | NonMemberContributorScalarFieldEnum + having?: NonMemberContributorScalarWhereWithAggregatesInput take?: number skip?: number - _count?: ModelPermissionCountAggregateInputType | true - _min?: ModelPermissionMinAggregateInputType - _max?: ModelPermissionMaxAggregateInputType + _count?: NonMemberContributorCountAggregateInputType | true + _avg?: NonMemberContributorAvgAggregateInputType + _sum?: NonMemberContributorSumAggregateInputType + _min?: NonMemberContributorMinAggregateInputType + _max?: NonMemberContributorMaxAggregateInputType } - export type ModelPermissionGroupByOutputType = { + export type NonMemberContributorGroupByOutputType = { id: string + legacyId: number modelId: string - granteeUserId: string | null - permissionLevel: $Enums.PermissionLevel + email: string | null + name: string | null + collaboratorType: string | null + addedByUserId: string | null createdAt: Date - _count: ModelPermissionCountAggregateOutputType | null - _min: ModelPermissionMinAggregateOutputType | null - _max: ModelPermissionMaxAggregateOutputType | null + _count: NonMemberContributorCountAggregateOutputType | null + _avg: NonMemberContributorAvgAggregateOutputType | null + _sum: NonMemberContributorSumAggregateOutputType | null + _min: NonMemberContributorMinAggregateOutputType | null + _max: NonMemberContributorMaxAggregateOutputType | null } - type GetModelPermissionGroupByPayload = Prisma.PrismaPromise< + type GetNonMemberContributorGroupByPayload = Prisma.PrismaPromise< Array< - PickEnumerable & + PickEnumerable & { - [P in ((keyof T) & (keyof ModelPermissionGroupByOutputType))]: P extends '_count' + [P in ((keyof T) & (keyof NonMemberContributorGroupByOutputType))]: P extends '_count' ? T[P] extends boolean ? number - : GetScalarType - : GetScalarType + : GetScalarType + : GetScalarType } > > - export type ModelPermissionSelect = $Extensions.GetSelect<{ + export type NonMemberContributorSelect = $Extensions.GetSelect<{ id?: boolean + legacyId?: boolean modelId?: boolean - granteeUserId?: boolean - permissionLevel?: boolean + email?: boolean + name?: boolean + collaboratorType?: boolean + addedByUserId?: boolean createdAt?: boolean model?: boolean | ModelDefaultArgs - granteeUser?: boolean | ModelPermission$granteeUserArgs - }, ExtArgs["result"]["modelPermission"]> + }, ExtArgs["result"]["nonMemberContributor"]> - export type ModelPermissionSelectCreateManyAndReturn = $Extensions.GetSelect<{ + export type NonMemberContributorSelectCreateManyAndReturn = $Extensions.GetSelect<{ id?: boolean + legacyId?: boolean modelId?: boolean - granteeUserId?: boolean - permissionLevel?: boolean + email?: boolean + name?: boolean + collaboratorType?: boolean + addedByUserId?: boolean createdAt?: boolean model?: boolean | ModelDefaultArgs - granteeUser?: boolean | ModelPermission$granteeUserArgs - }, ExtArgs["result"]["modelPermission"]> + }, ExtArgs["result"]["nonMemberContributor"]> - export type ModelPermissionSelectUpdateManyAndReturn = $Extensions.GetSelect<{ + export type NonMemberContributorSelectUpdateManyAndReturn = $Extensions.GetSelect<{ id?: boolean + legacyId?: boolean modelId?: boolean - granteeUserId?: boolean - permissionLevel?: boolean + email?: boolean + name?: boolean + collaboratorType?: boolean + addedByUserId?: boolean createdAt?: boolean model?: boolean | ModelDefaultArgs - granteeUser?: boolean | ModelPermission$granteeUserArgs - }, ExtArgs["result"]["modelPermission"]> + }, ExtArgs["result"]["nonMemberContributor"]> - export type ModelPermissionSelectScalar = { + export type NonMemberContributorSelectScalar = { id?: boolean + legacyId?: boolean modelId?: boolean - granteeUserId?: boolean - permissionLevel?: boolean + email?: boolean + name?: boolean + collaboratorType?: boolean + addedByUserId?: boolean createdAt?: boolean } - export type ModelPermissionOmit = $Extensions.GetOmit<"id" | "modelId" | "granteeUserId" | "permissionLevel" | "createdAt", ExtArgs["result"]["modelPermission"]> - export type ModelPermissionInclude = { + export type NonMemberContributorOmit = $Extensions.GetOmit<"id" | "legacyId" | "modelId" | "email" | "name" | "collaboratorType" | "addedByUserId" | "createdAt", ExtArgs["result"]["nonMemberContributor"]> + export type NonMemberContributorInclude = { model?: boolean | ModelDefaultArgs - granteeUser?: boolean | ModelPermission$granteeUserArgs } - export type ModelPermissionIncludeCreateManyAndReturn = { + export type NonMemberContributorIncludeCreateManyAndReturn = { model?: boolean | ModelDefaultArgs - granteeUser?: boolean | ModelPermission$granteeUserArgs } - export type ModelPermissionIncludeUpdateManyAndReturn = { + export type NonMemberContributorIncludeUpdateManyAndReturn = { model?: boolean | ModelDefaultArgs - granteeUser?: boolean | ModelPermission$granteeUserArgs } - export type $ModelPermissionPayload = { - name: "ModelPermission" + export type $NonMemberContributorPayload = { + name: "NonMemberContributor" objects: { model: Prisma.$ModelPayload - granteeUser: Prisma.$UserPayload | null } scalars: $Extensions.GetPayloadResult<{ id: string + legacyId: number modelId: string - granteeUserId: string | null - permissionLevel: $Enums.PermissionLevel + email: string | null + name: string | null + collaboratorType: string | null + addedByUserId: string | null createdAt: Date - }, ExtArgs["result"]["modelPermission"]> + }, ExtArgs["result"]["nonMemberContributor"]> composites: {} } - type ModelPermissionGetPayload = $Result.GetResult + type NonMemberContributorGetPayload = $Result.GetResult - type ModelPermissionCountArgs = - Omit & { - select?: ModelPermissionCountAggregateInputType | true + type NonMemberContributorCountArgs = + Omit & { + select?: NonMemberContributorCountAggregateInputType | true } - export interface ModelPermissionDelegate { - [K: symbol]: { types: Prisma.TypeMap['model']['ModelPermission'], meta: { name: 'ModelPermission' } } + export interface NonMemberContributorDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['NonMemberContributor'], meta: { name: 'NonMemberContributor' } } /** - * Find zero or one ModelPermission that matches the filter. - * @param {ModelPermissionFindUniqueArgs} args - Arguments to find a ModelPermission + * Find zero or one NonMemberContributor that matches the filter. + * @param {NonMemberContributorFindUniqueArgs} args - Arguments to find a NonMemberContributor * @example - * // Get one ModelPermission - * const modelPermission = await prisma.modelPermission.findUnique({ + * // Get one NonMemberContributor + * const nonMemberContributor = await prisma.nonMemberContributor.findUnique({ * where: { * // ... provide filter here * } * }) */ - findUnique(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + findUnique(args: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> /** - * Find one ModelPermission that matches the filter or throw an error with `error.code='P2025'` + * Find one NonMemberContributor that matches the filter or throw an error with `error.code='P2025'` * if no matches were found. - * @param {ModelPermissionFindUniqueOrThrowArgs} args - Arguments to find a ModelPermission + * @param {NonMemberContributorFindUniqueOrThrowArgs} args - Arguments to find a NonMemberContributor * @example - * // Get one ModelPermission - * const modelPermission = await prisma.modelPermission.findUniqueOrThrow({ + * // Get one NonMemberContributor + * const nonMemberContributor = await prisma.nonMemberContributor.findUniqueOrThrow({ * where: { * // ... provide filter here * } * }) */ - findUniqueOrThrow(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + findUniqueOrThrow(args: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> /** - * Find the first ModelPermission that matches the filter. + * Find the first NonMemberContributor that matches the filter. * Note, that providing `undefined` is treated as the value not being there. * Read more here: https://pris.ly/d/null-undefined - * @param {ModelPermissionFindFirstArgs} args - Arguments to find a ModelPermission + * @param {NonMemberContributorFindFirstArgs} args - Arguments to find a NonMemberContributor * @example - * // Get one ModelPermission - * const modelPermission = await prisma.modelPermission.findFirst({ + * // Get one NonMemberContributor + * const nonMemberContributor = await prisma.nonMemberContributor.findFirst({ * where: { * // ... provide filter here * } * }) */ - findFirst(args?: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + findFirst(args?: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> /** - * Find the first ModelPermission that matches the filter or + * Find the first NonMemberContributor that matches the filter or * throw `PrismaKnownClientError` with `P2025` code if no matches were found. * Note, that providing `undefined` is treated as the value not being there. * Read more here: https://pris.ly/d/null-undefined - * @param {ModelPermissionFindFirstOrThrowArgs} args - Arguments to find a ModelPermission + * @param {NonMemberContributorFindFirstOrThrowArgs} args - Arguments to find a NonMemberContributor * @example - * // Get one ModelPermission - * const modelPermission = await prisma.modelPermission.findFirstOrThrow({ + * // Get one NonMemberContributor + * const nonMemberContributor = await prisma.nonMemberContributor.findFirstOrThrow({ * where: { * // ... provide filter here * } * }) */ - findFirstOrThrow(args?: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + findFirstOrThrow(args?: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> /** - * Find zero or more ModelPermissions that matches the filter. + * Find zero or more NonMemberContributors that matches the filter. * Note, that providing `undefined` is treated as the value not being there. * Read more here: https://pris.ly/d/null-undefined - * @param {ModelPermissionFindManyArgs} args - Arguments to filter and select certain fields only. + * @param {NonMemberContributorFindManyArgs} args - Arguments to filter and select certain fields only. * @example - * // Get all ModelPermissions - * const modelPermissions = await prisma.modelPermission.findMany() + * // Get all NonMemberContributors + * const nonMemberContributors = await prisma.nonMemberContributor.findMany() * - * // Get first 10 ModelPermissions - * const modelPermissions = await prisma.modelPermission.findMany({ take: 10 }) + * // Get first 10 NonMemberContributors + * const nonMemberContributors = await prisma.nonMemberContributor.findMany({ take: 10 }) * * // Only select the `id` - * const modelPermissionWithIdOnly = await prisma.modelPermission.findMany({ select: { id: true } }) + * const nonMemberContributorWithIdOnly = await prisma.nonMemberContributor.findMany({ select: { id: true } }) * */ - findMany(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions>> + findMany(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions>> /** - * Create a ModelPermission. - * @param {ModelPermissionCreateArgs} args - Arguments to create a ModelPermission. + * Create a NonMemberContributor. + * @param {NonMemberContributorCreateArgs} args - Arguments to create a NonMemberContributor. * @example - * // Create one ModelPermission - * const ModelPermission = await prisma.modelPermission.create({ + * // Create one NonMemberContributor + * const NonMemberContributor = await prisma.nonMemberContributor.create({ * data: { - * // ... data to create a ModelPermission + * // ... data to create a NonMemberContributor * } * }) * */ - create(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + create(args: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> /** - * Create many ModelPermissions. - * @param {ModelPermissionCreateManyArgs} args - Arguments to create many ModelPermissions. + * Create many NonMemberContributors. + * @param {NonMemberContributorCreateManyArgs} args - Arguments to create many NonMemberContributors. * @example - * // Create many ModelPermissions - * const modelPermission = await prisma.modelPermission.createMany({ + * // Create many NonMemberContributors + * const nonMemberContributor = await prisma.nonMemberContributor.createMany({ * data: [ * // ... provide data here * ] * }) * */ - createMany(args?: SelectSubset>): Prisma.PrismaPromise + createMany(args?: SelectSubset>): Prisma.PrismaPromise /** - * Create many ModelPermissions and returns the data saved in the database. - * @param {ModelPermissionCreateManyAndReturnArgs} args - Arguments to create many ModelPermissions. + * Create many NonMemberContributors and returns the data saved in the database. + * @param {NonMemberContributorCreateManyAndReturnArgs} args - Arguments to create many NonMemberContributors. * @example - * // Create many ModelPermissions - * const modelPermission = await prisma.modelPermission.createManyAndReturn({ + * // Create many NonMemberContributors + * const nonMemberContributor = await prisma.nonMemberContributor.createManyAndReturn({ * data: [ * // ... provide data here * ] * }) * - * // Create many ModelPermissions and only return the `id` - * const modelPermissionWithIdOnly = await prisma.modelPermission.createManyAndReturn({ + * // Create many NonMemberContributors and only return the `id` + * const nonMemberContributorWithIdOnly = await prisma.nonMemberContributor.createManyAndReturn({ * select: { id: true }, * data: [ * // ... provide data here @@ -16327,28 +16531,28 @@ export namespace Prisma { * Read more here: https://pris.ly/d/null-undefined * */ - createManyAndReturn(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "createManyAndReturn", GlobalOmitOptions>> + createManyAndReturn(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "createManyAndReturn", GlobalOmitOptions>> /** - * Delete a ModelPermission. - * @param {ModelPermissionDeleteArgs} args - Arguments to delete one ModelPermission. + * Delete a NonMemberContributor. + * @param {NonMemberContributorDeleteArgs} args - Arguments to delete one NonMemberContributor. * @example - * // Delete one ModelPermission - * const ModelPermission = await prisma.modelPermission.delete({ + * // Delete one NonMemberContributor + * const NonMemberContributor = await prisma.nonMemberContributor.delete({ * where: { - * // ... filter to delete one ModelPermission + * // ... filter to delete one NonMemberContributor * } * }) * */ - delete(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + delete(args: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> /** - * Update one ModelPermission. - * @param {ModelPermissionUpdateArgs} args - Arguments to update one ModelPermission. + * Update one NonMemberContributor. + * @param {NonMemberContributorUpdateArgs} args - Arguments to update one NonMemberContributor. * @example - * // Update one ModelPermission - * const modelPermission = await prisma.modelPermission.update({ + * // Update one NonMemberContributor + * const nonMemberContributor = await prisma.nonMemberContributor.update({ * where: { * // ... provide filter here * }, @@ -16358,30 +16562,30 @@ export namespace Prisma { * }) * */ - update(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + update(args: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> /** - * Delete zero or more ModelPermissions. - * @param {ModelPermissionDeleteManyArgs} args - Arguments to filter ModelPermissions to delete. + * Delete zero or more NonMemberContributors. + * @param {NonMemberContributorDeleteManyArgs} args - Arguments to filter NonMemberContributors to delete. * @example - * // Delete a few ModelPermissions - * const { count } = await prisma.modelPermission.deleteMany({ + * // Delete a few NonMemberContributors + * const { count } = await prisma.nonMemberContributor.deleteMany({ * where: { * // ... provide filter here * } * }) * */ - deleteMany(args?: SelectSubset>): Prisma.PrismaPromise + deleteMany(args?: SelectSubset>): Prisma.PrismaPromise /** - * Update zero or more ModelPermissions. + * Update zero or more NonMemberContributors. * Note, that providing `undefined` is treated as the value not being there. * Read more here: https://pris.ly/d/null-undefined - * @param {ModelPermissionUpdateManyArgs} args - Arguments to update one or more rows. + * @param {NonMemberContributorUpdateManyArgs} args - Arguments to update one or more rows. * @example - * // Update many ModelPermissions - * const modelPermission = await prisma.modelPermission.updateMany({ + * // Update many NonMemberContributors + * const nonMemberContributor = await prisma.nonMemberContributor.updateMany({ * where: { * // ... provide filter here * }, @@ -16391,14 +16595,14 @@ export namespace Prisma { * }) * */ - updateMany(args: SelectSubset>): Prisma.PrismaPromise + updateMany(args: SelectSubset>): Prisma.PrismaPromise /** - * Update zero or more ModelPermissions and returns the data updated in the database. - * @param {ModelPermissionUpdateManyAndReturnArgs} args - Arguments to update many ModelPermissions. + * Update zero or more NonMemberContributors and returns the data updated in the database. + * @param {NonMemberContributorUpdateManyAndReturnArgs} args - Arguments to update many NonMemberContributors. * @example - * // Update many ModelPermissions - * const modelPermission = await prisma.modelPermission.updateManyAndReturn({ + * // Update many NonMemberContributors + * const nonMemberContributor = await prisma.nonMemberContributor.updateManyAndReturn({ * where: { * // ... provide filter here * }, @@ -16407,8 +16611,8 @@ export namespace Prisma { * ] * }) * - * // Update zero or more ModelPermissions and only return the `id` - * const modelPermissionWithIdOnly = await prisma.modelPermission.updateManyAndReturn({ + * // Update zero or more NonMemberContributors and only return the `id` + * const nonMemberContributorWithIdOnly = await prisma.nonMemberContributor.updateManyAndReturn({ * select: { id: true }, * where: { * // ... provide filter here @@ -16421,56 +16625,56 @@ export namespace Prisma { * Read more here: https://pris.ly/d/null-undefined * */ - updateManyAndReturn(args: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "updateManyAndReturn", GlobalOmitOptions>> + updateManyAndReturn(args: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "updateManyAndReturn", GlobalOmitOptions>> /** - * Create or update one ModelPermission. - * @param {ModelPermissionUpsertArgs} args - Arguments to update or create a ModelPermission. + * Create or update one NonMemberContributor. + * @param {NonMemberContributorUpsertArgs} args - Arguments to update or create a NonMemberContributor. * @example - * // Update or create a ModelPermission - * const modelPermission = await prisma.modelPermission.upsert({ + * // Update or create a NonMemberContributor + * const nonMemberContributor = await prisma.nonMemberContributor.upsert({ * create: { - * // ... data to create a ModelPermission + * // ... data to create a NonMemberContributor * }, * update: { * // ... in case it already exists, update * }, * where: { - * // ... the filter for the ModelPermission we want to update + * // ... the filter for the NonMemberContributor we want to update * } * }) */ - upsert(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + upsert(args: SelectSubset>): Prisma__NonMemberContributorClient<$Result.GetResult, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> /** - * Count the number of ModelPermissions. + * Count the number of NonMemberContributors. * Note, that providing `undefined` is treated as the value not being there. * Read more here: https://pris.ly/d/null-undefined - * @param {ModelPermissionCountArgs} args - Arguments to filter ModelPermissions to count. + * @param {NonMemberContributorCountArgs} args - Arguments to filter NonMemberContributors to count. * @example - * // Count the number of ModelPermissions - * const count = await prisma.modelPermission.count({ + * // Count the number of NonMemberContributors + * const count = await prisma.nonMemberContributor.count({ * where: { - * // ... the filter for the ModelPermissions we want to count + * // ... the filter for the NonMemberContributors we want to count * } * }) **/ - count( - args?: Subset, + count( + args?: Subset, ): Prisma.PrismaPromise< T extends $Utils.Record<'select', any> ? T['select'] extends true ? number - : GetScalarType + : GetScalarType : number > /** - * Allows you to perform aggregations operations on a ModelPermission. + * Allows you to perform aggregations operations on a NonMemberContributor. * Note, that providing `undefined` is treated as the value not being there. * Read more here: https://pris.ly/d/null-undefined - * @param {ModelPermissionAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @param {NonMemberContributorAggregateArgs} args - Select which aggregations you would like to apply and on what fields. * @example * // Ordered by age ascending * // Where email contains prisma.io @@ -16490,13 +16694,13 @@ export namespace Prisma { * take: 10, * }) **/ - aggregate(args: Subset): Prisma.PrismaPromise> + aggregate(args: Subset): Prisma.PrismaPromise> /** - * Group by ModelPermission. + * Group by NonMemberContributor. * Note, that providing `undefined` is treated as the value not being there. * Read more here: https://pris.ly/d/null-undefined - * @param {ModelPermissionGroupByArgs} args - Group by arguments. + * @param {NonMemberContributorGroupByArgs} args - Group by arguments. * @example * // Group by city, order by createdAt, get count * const result = await prisma.user.groupBy({ @@ -16511,14 +16715,1087 @@ export namespace Prisma { * **/ groupBy< - T extends ModelPermissionGroupByArgs, + T extends NonMemberContributorGroupByArgs, HasSelectOrTake extends Or< Extends<'skip', Keys>, Extends<'take', Keys> >, OrderByArg extends True extends HasSelectOrTake - ? { orderBy: ModelPermissionGroupByArgs['orderBy'] } - : { orderBy?: ModelPermissionGroupByArgs['orderBy'] }, + ? { orderBy: NonMemberContributorGroupByArgs['orderBy'] } + : { orderBy?: NonMemberContributorGroupByArgs['orderBy'] }, + OrderFields extends ExcludeUnderscoreKeys>>, + ByFields extends MaybeTupleToUnion, + ByValid extends Has, + HavingFields extends GetHavingFields, + HavingValid extends Has, + ByEmpty extends T['by'] extends never[] ? True : False, + InputErrors extends ByEmpty extends True + ? `Error: "by" must not be empty.` + : HavingValid extends False + ? { + [P in HavingFields]: P extends ByFields + ? never + : P extends string + ? `Error: Field "${P}" used in "having" needs to be provided in "by".` + : [ + Error, + 'Field ', + P, + ` in "having" needs to be provided in "by"`, + ] + }[HavingFields] + : 'take' extends Keys + ? 'orderBy' extends Keys + ? ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "take", you also need to provide "orderBy"' + : 'skip' extends Keys + ? 'orderBy' extends Keys + ? ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + : 'Error: If you provide "skip", you also need to provide "orderBy"' + : ByValid extends True + ? {} + : { + [P in OrderFields]: P extends ByFields + ? never + : `Error: Field "${P}" in "orderBy" needs to be provided in "by"` + }[OrderFields] + >(args: SubsetIntersection & InputErrors): {} extends InputErrors ? GetNonMemberContributorGroupByPayload : Prisma.PrismaPromise + /** + * Fields of the NonMemberContributor model + */ + readonly fields: NonMemberContributorFieldRefs; + } + + /** + * The delegate class that acts as a "Promise-like" for NonMemberContributor. + * Why is this prefixed with `Prisma__`? + * Because we want to prevent naming conflicts as mentioned in + * https://github.com/prisma/prisma-client-js/issues/707 + */ + export interface Prisma__NonMemberContributorClient extends Prisma.PrismaPromise { + readonly [Symbol.toStringTag]: "PrismaPromise" + model = {}>(args?: Subset>): Prisma__ModelClient<$Result.GetResult, T, "findUniqueOrThrow", GlobalOmitOptions> | Null, Null, ExtArgs, GlobalOmitOptions> + /** + * Attaches callbacks for the resolution and/or rejection of the Promise. + * @param onfulfilled The callback to execute when the Promise is resolved. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of which ever callback is executed. + */ + then(onfulfilled?: ((value: T) => TResult1 | PromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike) | undefined | null): $Utils.JsPromise + /** + * Attaches a callback for only the rejection of the Promise. + * @param onrejected The callback to execute when the Promise is rejected. + * @returns A Promise for the completion of the callback. + */ + catch(onrejected?: ((reason: any) => TResult | PromiseLike) | undefined | null): $Utils.JsPromise + /** + * Attaches a callback that is invoked when the Promise is settled (fulfilled or rejected). The + * resolved value cannot be modified from the callback. + * @param onfinally The callback to execute when the Promise is settled (fulfilled or rejected). + * @returns A Promise for the completion of the callback. + */ + finally(onfinally?: (() => void) | undefined | null): $Utils.JsPromise + } + + + + + /** + * Fields of the NonMemberContributor model + */ + interface NonMemberContributorFieldRefs { + readonly id: FieldRef<"NonMemberContributor", 'String'> + readonly legacyId: FieldRef<"NonMemberContributor", 'Int'> + readonly modelId: FieldRef<"NonMemberContributor", 'String'> + readonly email: FieldRef<"NonMemberContributor", 'String'> + readonly name: FieldRef<"NonMemberContributor", 'String'> + readonly collaboratorType: FieldRef<"NonMemberContributor", 'String'> + readonly addedByUserId: FieldRef<"NonMemberContributor", 'String'> + readonly createdAt: FieldRef<"NonMemberContributor", 'DateTime'> + } + + + // Custom InputTypes + /** + * NonMemberContributor findUnique + */ + export type NonMemberContributorFindUniqueArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * Filter, which NonMemberContributor to fetch. + */ + where: NonMemberContributorWhereUniqueInput + } + + /** + * NonMemberContributor findUniqueOrThrow + */ + export type NonMemberContributorFindUniqueOrThrowArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * Filter, which NonMemberContributor to fetch. + */ + where: NonMemberContributorWhereUniqueInput + } + + /** + * NonMemberContributor findFirst + */ + export type NonMemberContributorFindFirstArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * Filter, which NonMemberContributor to fetch. + */ + where?: NonMemberContributorWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of NonMemberContributors to fetch. + */ + orderBy?: NonMemberContributorOrderByWithRelationInput | NonMemberContributorOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for NonMemberContributors. + */ + cursor?: NonMemberContributorWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` NonMemberContributors from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` NonMemberContributors. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of NonMemberContributors. + */ + distinct?: NonMemberContributorScalarFieldEnum | NonMemberContributorScalarFieldEnum[] + } + + /** + * NonMemberContributor findFirstOrThrow + */ + export type NonMemberContributorFindFirstOrThrowArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * Filter, which NonMemberContributor to fetch. + */ + where?: NonMemberContributorWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of NonMemberContributors to fetch. + */ + orderBy?: NonMemberContributorOrderByWithRelationInput | NonMemberContributorOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for searching for NonMemberContributors. + */ + cursor?: NonMemberContributorWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` NonMemberContributors from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` NonMemberContributors. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of NonMemberContributors. + */ + distinct?: NonMemberContributorScalarFieldEnum | NonMemberContributorScalarFieldEnum[] + } + + /** + * NonMemberContributor findMany + */ + export type NonMemberContributorFindManyArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * Filter, which NonMemberContributors to fetch. + */ + where?: NonMemberContributorWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of NonMemberContributors to fetch. + */ + orderBy?: NonMemberContributorOrderByWithRelationInput | NonMemberContributorOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the position for listing NonMemberContributors. + */ + cursor?: NonMemberContributorWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` NonMemberContributors from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` NonMemberContributors. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/distinct Distinct Docs} + * + * Filter by unique combinations of NonMemberContributors. + */ + distinct?: NonMemberContributorScalarFieldEnum | NonMemberContributorScalarFieldEnum[] + } + + /** + * NonMemberContributor create + */ + export type NonMemberContributorCreateArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * The data needed to create a NonMemberContributor. + */ + data: XOR + } + + /** + * NonMemberContributor createMany + */ + export type NonMemberContributorCreateManyArgs = { + /** + * The data used to create many NonMemberContributors. + */ + data: NonMemberContributorCreateManyInput | NonMemberContributorCreateManyInput[] + skipDuplicates?: boolean + } + + /** + * NonMemberContributor createManyAndReturn + */ + export type NonMemberContributorCreateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelectCreateManyAndReturn | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * The data used to create many NonMemberContributors. + */ + data: NonMemberContributorCreateManyInput | NonMemberContributorCreateManyInput[] + skipDuplicates?: boolean + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorIncludeCreateManyAndReturn | null + } + + /** + * NonMemberContributor update + */ + export type NonMemberContributorUpdateArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * The data needed to update a NonMemberContributor. + */ + data: XOR + /** + * Choose, which NonMemberContributor to update. + */ + where: NonMemberContributorWhereUniqueInput + } + + /** + * NonMemberContributor updateMany + */ + export type NonMemberContributorUpdateManyArgs = { + /** + * The data used to update NonMemberContributors. + */ + data: XOR + /** + * Filter which NonMemberContributors to update + */ + where?: NonMemberContributorWhereInput + /** + * Limit how many NonMemberContributors to update. + */ + limit?: number + } + + /** + * NonMemberContributor updateManyAndReturn + */ + export type NonMemberContributorUpdateManyAndReturnArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelectUpdateManyAndReturn | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * The data used to update NonMemberContributors. + */ + data: XOR + /** + * Filter which NonMemberContributors to update + */ + where?: NonMemberContributorWhereInput + /** + * Limit how many NonMemberContributors to update. + */ + limit?: number + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorIncludeUpdateManyAndReturn | null + } + + /** + * NonMemberContributor upsert + */ + export type NonMemberContributorUpsertArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * The filter to search for the NonMemberContributor to update in case it exists. + */ + where: NonMemberContributorWhereUniqueInput + /** + * In case the NonMemberContributor found by the `where` argument doesn't exist, create a new NonMemberContributor with this data. + */ + create: XOR + /** + * In case the NonMemberContributor was found with the provided `where` argument, update it with this data. + */ + update: XOR + } + + /** + * NonMemberContributor delete + */ + export type NonMemberContributorDeleteArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + /** + * Filter which NonMemberContributor to delete. + */ + where: NonMemberContributorWhereUniqueInput + } + + /** + * NonMemberContributor deleteMany + */ + export type NonMemberContributorDeleteManyArgs = { + /** + * Filter which NonMemberContributors to delete + */ + where?: NonMemberContributorWhereInput + /** + * Limit how many NonMemberContributors to delete. + */ + limit?: number + } + + /** + * NonMemberContributor without action + */ + export type NonMemberContributorDefaultArgs = { + /** + * Select specific fields to fetch from the NonMemberContributor + */ + select?: NonMemberContributorSelect | null + /** + * Omit specific fields from the NonMemberContributor + */ + omit?: NonMemberContributorOmit | null + /** + * Choose, which related nodes to fetch as well + */ + include?: NonMemberContributorInclude | null + } + + + /** + * Model ModelPermission + */ + + export type AggregateModelPermission = { + _count: ModelPermissionCountAggregateOutputType | null + _min: ModelPermissionMinAggregateOutputType | null + _max: ModelPermissionMaxAggregateOutputType | null + } + + export type ModelPermissionMinAggregateOutputType = { + id: string | null + modelId: string | null + granteeUserId: string | null + permissionLevel: $Enums.PermissionLevel | null + createdAt: Date | null + } + + export type ModelPermissionMaxAggregateOutputType = { + id: string | null + modelId: string | null + granteeUserId: string | null + permissionLevel: $Enums.PermissionLevel | null + createdAt: Date | null + } + + export type ModelPermissionCountAggregateOutputType = { + id: number + modelId: number + granteeUserId: number + permissionLevel: number + createdAt: number + _all: number + } + + + export type ModelPermissionMinAggregateInputType = { + id?: true + modelId?: true + granteeUserId?: true + permissionLevel?: true + createdAt?: true + } + + export type ModelPermissionMaxAggregateInputType = { + id?: true + modelId?: true + granteeUserId?: true + permissionLevel?: true + createdAt?: true + } + + export type ModelPermissionCountAggregateInputType = { + id?: true + modelId?: true + granteeUserId?: true + permissionLevel?: true + createdAt?: true + _all?: true + } + + export type ModelPermissionAggregateArgs = { + /** + * Filter which ModelPermission to aggregate. + */ + where?: ModelPermissionWhereInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/sorting Sorting Docs} + * + * Determine the order of ModelPermissions to fetch. + */ + orderBy?: ModelPermissionOrderByWithRelationInput | ModelPermissionOrderByWithRelationInput[] + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination#cursor-based-pagination Cursor Docs} + * + * Sets the start position + */ + cursor?: ModelPermissionWhereUniqueInput + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Take `±n` ModelPermissions from the position of the cursor. + */ + take?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/pagination Pagination Docs} + * + * Skip the first `n` ModelPermissions. + */ + skip?: number + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Count returned ModelPermissions + **/ + _count?: true | ModelPermissionCountAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the minimum value + **/ + _min?: ModelPermissionMinAggregateInputType + /** + * {@link https://www.prisma.io/docs/concepts/components/prisma-client/aggregations Aggregation Docs} + * + * Select which fields to find the maximum value + **/ + _max?: ModelPermissionMaxAggregateInputType + } + + export type GetModelPermissionAggregateType = { + [P in keyof T & keyof AggregateModelPermission]: P extends '_count' | 'count' + ? T[P] extends true + ? number + : GetScalarType + : GetScalarType + } + + + + + export type ModelPermissionGroupByArgs = { + where?: ModelPermissionWhereInput + orderBy?: ModelPermissionOrderByWithAggregationInput | ModelPermissionOrderByWithAggregationInput[] + by: ModelPermissionScalarFieldEnum[] | ModelPermissionScalarFieldEnum + having?: ModelPermissionScalarWhereWithAggregatesInput + take?: number + skip?: number + _count?: ModelPermissionCountAggregateInputType | true + _min?: ModelPermissionMinAggregateInputType + _max?: ModelPermissionMaxAggregateInputType + } + + export type ModelPermissionGroupByOutputType = { + id: string + modelId: string + granteeUserId: string | null + permissionLevel: $Enums.PermissionLevel + createdAt: Date + _count: ModelPermissionCountAggregateOutputType | null + _min: ModelPermissionMinAggregateOutputType | null + _max: ModelPermissionMaxAggregateOutputType | null + } + + type GetModelPermissionGroupByPayload = Prisma.PrismaPromise< + Array< + PickEnumerable & + { + [P in ((keyof T) & (keyof ModelPermissionGroupByOutputType))]: P extends '_count' + ? T[P] extends boolean + ? number + : GetScalarType + : GetScalarType + } + > + > + + + export type ModelPermissionSelect = $Extensions.GetSelect<{ + id?: boolean + modelId?: boolean + granteeUserId?: boolean + permissionLevel?: boolean + createdAt?: boolean + model?: boolean | ModelDefaultArgs + granteeUser?: boolean | ModelPermission$granteeUserArgs + }, ExtArgs["result"]["modelPermission"]> + + export type ModelPermissionSelectCreateManyAndReturn = $Extensions.GetSelect<{ + id?: boolean + modelId?: boolean + granteeUserId?: boolean + permissionLevel?: boolean + createdAt?: boolean + model?: boolean | ModelDefaultArgs + granteeUser?: boolean | ModelPermission$granteeUserArgs + }, ExtArgs["result"]["modelPermission"]> + + export type ModelPermissionSelectUpdateManyAndReturn = $Extensions.GetSelect<{ + id?: boolean + modelId?: boolean + granteeUserId?: boolean + permissionLevel?: boolean + createdAt?: boolean + model?: boolean | ModelDefaultArgs + granteeUser?: boolean | ModelPermission$granteeUserArgs + }, ExtArgs["result"]["modelPermission"]> + + export type ModelPermissionSelectScalar = { + id?: boolean + modelId?: boolean + granteeUserId?: boolean + permissionLevel?: boolean + createdAt?: boolean + } + + export type ModelPermissionOmit = $Extensions.GetOmit<"id" | "modelId" | "granteeUserId" | "permissionLevel" | "createdAt", ExtArgs["result"]["modelPermission"]> + export type ModelPermissionInclude = { + model?: boolean | ModelDefaultArgs + granteeUser?: boolean | ModelPermission$granteeUserArgs + } + export type ModelPermissionIncludeCreateManyAndReturn = { + model?: boolean | ModelDefaultArgs + granteeUser?: boolean | ModelPermission$granteeUserArgs + } + export type ModelPermissionIncludeUpdateManyAndReturn = { + model?: boolean | ModelDefaultArgs + granteeUser?: boolean | ModelPermission$granteeUserArgs + } + + export type $ModelPermissionPayload = { + name: "ModelPermission" + objects: { + model: Prisma.$ModelPayload + granteeUser: Prisma.$UserPayload | null + } + scalars: $Extensions.GetPayloadResult<{ + id: string + modelId: string + granteeUserId: string | null + permissionLevel: $Enums.PermissionLevel + createdAt: Date + }, ExtArgs["result"]["modelPermission"]> + composites: {} + } + + type ModelPermissionGetPayload = $Result.GetResult + + type ModelPermissionCountArgs = + Omit & { + select?: ModelPermissionCountAggregateInputType | true + } + + export interface ModelPermissionDelegate { + [K: symbol]: { types: Prisma.TypeMap['model']['ModelPermission'], meta: { name: 'ModelPermission' } } + /** + * Find zero or one ModelPermission that matches the filter. + * @param {ModelPermissionFindUniqueArgs} args - Arguments to find a ModelPermission + * @example + * // Get one ModelPermission + * const modelPermission = await prisma.modelPermission.findUnique({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUnique(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findUnique", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find one ModelPermission that matches the filter or throw an error with `error.code='P2025'` + * if no matches were found. + * @param {ModelPermissionFindUniqueOrThrowArgs} args - Arguments to find a ModelPermission + * @example + * // Get one ModelPermission + * const modelPermission = await prisma.modelPermission.findUniqueOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findUniqueOrThrow(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findUniqueOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find the first ModelPermission that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ModelPermissionFindFirstArgs} args - Arguments to find a ModelPermission + * @example + * // Get one ModelPermission + * const modelPermission = await prisma.modelPermission.findFirst({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirst(args?: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findFirst", GlobalOmitOptions> | null, null, ExtArgs, GlobalOmitOptions> + + /** + * Find the first ModelPermission that matches the filter or + * throw `PrismaKnownClientError` with `P2025` code if no matches were found. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ModelPermissionFindFirstOrThrowArgs} args - Arguments to find a ModelPermission + * @example + * // Get one ModelPermission + * const modelPermission = await prisma.modelPermission.findFirstOrThrow({ + * where: { + * // ... provide filter here + * } + * }) + */ + findFirstOrThrow(args?: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "findFirstOrThrow", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Find zero or more ModelPermissions that matches the filter. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ModelPermissionFindManyArgs} args - Arguments to filter and select certain fields only. + * @example + * // Get all ModelPermissions + * const modelPermissions = await prisma.modelPermission.findMany() + * + * // Get first 10 ModelPermissions + * const modelPermissions = await prisma.modelPermission.findMany({ take: 10 }) + * + * // Only select the `id` + * const modelPermissionWithIdOnly = await prisma.modelPermission.findMany({ select: { id: true } }) + * + */ + findMany(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "findMany", GlobalOmitOptions>> + + /** + * Create a ModelPermission. + * @param {ModelPermissionCreateArgs} args - Arguments to create a ModelPermission. + * @example + * // Create one ModelPermission + * const ModelPermission = await prisma.modelPermission.create({ + * data: { + * // ... data to create a ModelPermission + * } + * }) + * + */ + create(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "create", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Create many ModelPermissions. + * @param {ModelPermissionCreateManyArgs} args - Arguments to create many ModelPermissions. + * @example + * // Create many ModelPermissions + * const modelPermission = await prisma.modelPermission.createMany({ + * data: [ + * // ... provide data here + * ] + * }) + * + */ + createMany(args?: SelectSubset>): Prisma.PrismaPromise + + /** + * Create many ModelPermissions and returns the data saved in the database. + * @param {ModelPermissionCreateManyAndReturnArgs} args - Arguments to create many ModelPermissions. + * @example + * // Create many ModelPermissions + * const modelPermission = await prisma.modelPermission.createManyAndReturn({ + * data: [ + * // ... provide data here + * ] + * }) + * + * // Create many ModelPermissions and only return the `id` + * const modelPermissionWithIdOnly = await prisma.modelPermission.createManyAndReturn({ + * select: { id: true }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + createManyAndReturn(args?: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "createManyAndReturn", GlobalOmitOptions>> + + /** + * Delete a ModelPermission. + * @param {ModelPermissionDeleteArgs} args - Arguments to delete one ModelPermission. + * @example + * // Delete one ModelPermission + * const ModelPermission = await prisma.modelPermission.delete({ + * where: { + * // ... filter to delete one ModelPermission + * } + * }) + * + */ + delete(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "delete", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Update one ModelPermission. + * @param {ModelPermissionUpdateArgs} args - Arguments to update one ModelPermission. + * @example + * // Update one ModelPermission + * const modelPermission = await prisma.modelPermission.update({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + update(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "update", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + /** + * Delete zero or more ModelPermissions. + * @param {ModelPermissionDeleteManyArgs} args - Arguments to filter ModelPermissions to delete. + * @example + * // Delete a few ModelPermissions + * const { count } = await prisma.modelPermission.deleteMany({ + * where: { + * // ... provide filter here + * } + * }) + * + */ + deleteMany(args?: SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more ModelPermissions. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ModelPermissionUpdateManyArgs} args - Arguments to update one or more rows. + * @example + * // Update many ModelPermissions + * const modelPermission = await prisma.modelPermission.updateMany({ + * where: { + * // ... provide filter here + * }, + * data: { + * // ... provide data here + * } + * }) + * + */ + updateMany(args: SelectSubset>): Prisma.PrismaPromise + + /** + * Update zero or more ModelPermissions and returns the data updated in the database. + * @param {ModelPermissionUpdateManyAndReturnArgs} args - Arguments to update many ModelPermissions. + * @example + * // Update many ModelPermissions + * const modelPermission = await prisma.modelPermission.updateManyAndReturn({ + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * + * // Update zero or more ModelPermissions and only return the `id` + * const modelPermissionWithIdOnly = await prisma.modelPermission.updateManyAndReturn({ + * select: { id: true }, + * where: { + * // ... provide filter here + * }, + * data: [ + * // ... provide data here + * ] + * }) + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * + */ + updateManyAndReturn(args: SelectSubset>): Prisma.PrismaPromise<$Result.GetResult, T, "updateManyAndReturn", GlobalOmitOptions>> + + /** + * Create or update one ModelPermission. + * @param {ModelPermissionUpsertArgs} args - Arguments to update or create a ModelPermission. + * @example + * // Update or create a ModelPermission + * const modelPermission = await prisma.modelPermission.upsert({ + * create: { + * // ... data to create a ModelPermission + * }, + * update: { + * // ... in case it already exists, update + * }, + * where: { + * // ... the filter for the ModelPermission we want to update + * } + * }) + */ + upsert(args: SelectSubset>): Prisma__ModelPermissionClient<$Result.GetResult, T, "upsert", GlobalOmitOptions>, never, ExtArgs, GlobalOmitOptions> + + + /** + * Count the number of ModelPermissions. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ModelPermissionCountArgs} args - Arguments to filter ModelPermissions to count. + * @example + * // Count the number of ModelPermissions + * const count = await prisma.modelPermission.count({ + * where: { + * // ... the filter for the ModelPermissions we want to count + * } + * }) + **/ + count( + args?: Subset, + ): Prisma.PrismaPromise< + T extends $Utils.Record<'select', any> + ? T['select'] extends true + ? number + : GetScalarType + : number + > + + /** + * Allows you to perform aggregations operations on a ModelPermission. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ModelPermissionAggregateArgs} args - Select which aggregations you would like to apply and on what fields. + * @example + * // Ordered by age ascending + * // Where email contains prisma.io + * // Limited to the 10 users + * const aggregations = await prisma.user.aggregate({ + * _avg: { + * age: true, + * }, + * where: { + * email: { + * contains: "prisma.io", + * }, + * }, + * orderBy: { + * age: "asc", + * }, + * take: 10, + * }) + **/ + aggregate(args: Subset): Prisma.PrismaPromise> + + /** + * Group by ModelPermission. + * Note, that providing `undefined` is treated as the value not being there. + * Read more here: https://pris.ly/d/null-undefined + * @param {ModelPermissionGroupByArgs} args - Group by arguments. + * @example + * // Group by city, order by createdAt, get count + * const result = await prisma.user.groupBy({ + * by: ['city', 'createdAt'], + * orderBy: { + * createdAt: true + * }, + * _count: { + * _all: true + * }, + * }) + * + **/ + groupBy< + T extends ModelPermissionGroupByArgs, + HasSelectOrTake extends Or< + Extends<'skip', Keys>, + Extends<'take', Keys> + >, + OrderByArg extends True extends HasSelectOrTake + ? { orderBy: ModelPermissionGroupByArgs['orderBy'] } + : { orderBy?: ModelPermissionGroupByArgs['orderBy'] }, OrderFields extends ExcludeUnderscoreKeys>>, ByFields extends MaybeTupleToUnion, ByValid extends Has, @@ -21737,12 +23014,27 @@ export namespace Prisma { modelId: 'modelId', userId: 'userId', role: 'role', + collaboratorType: 'collaboratorType', createdAt: 'createdAt' }; export type ModelAuthorScalarFieldEnum = (typeof ModelAuthorScalarFieldEnum)[keyof typeof ModelAuthorScalarFieldEnum] + export const NonMemberContributorScalarFieldEnum: { + id: 'id', + legacyId: 'legacyId', + modelId: 'modelId', + email: 'email', + name: 'name', + collaboratorType: 'collaboratorType', + addedByUserId: 'addedByUserId', + createdAt: 'createdAt' + }; + + export type NonMemberContributorScalarFieldEnum = (typeof NonMemberContributorScalarFieldEnum)[keyof typeof NonMemberContributorScalarFieldEnum] + + export const ModelPermissionScalarFieldEnum: { id: 'id', modelId: 'modelId', @@ -22555,6 +23847,7 @@ export namespace Prisma { parentVersion?: XOR | null versions?: ModelVersionListRelationFilter authors?: ModelAuthorListRelationFilter + nonMemberContributors?: NonMemberContributorListRelationFilter permissions?: ModelPermissionListRelationFilter additionalFiles?: ModelAdditionalFileListRelationFilter likes?: ModelLikeListRelationFilter @@ -22584,6 +23877,7 @@ export namespace Prisma { parentVersion?: ModelVersionOrderByWithRelationInput versions?: ModelVersionOrderByRelationAggregateInput authors?: ModelAuthorOrderByRelationAggregateInput + nonMemberContributors?: NonMemberContributorOrderByRelationAggregateInput permissions?: ModelPermissionOrderByRelationAggregateInput additionalFiles?: ModelAdditionalFileOrderByRelationAggregateInput likes?: ModelLikeOrderByRelationAggregateInput @@ -22617,6 +23911,7 @@ export namespace Prisma { parentVersion?: XOR | null versions?: ModelVersionListRelationFilter authors?: ModelAuthorListRelationFilter + nonMemberContributors?: NonMemberContributorListRelationFilter permissions?: ModelPermissionListRelationFilter additionalFiles?: ModelAdditionalFileListRelationFilter likes?: ModelLikeListRelationFilter @@ -22953,6 +24248,7 @@ export namespace Prisma { modelId?: StringFilter<"ModelAuthor"> | string userId?: StringFilter<"ModelAuthor"> | string role?: EnumAuthorRoleFilter<"ModelAuthor"> | $Enums.AuthorRole + collaboratorType?: StringNullableFilter<"ModelAuthor"> | string | null createdAt?: DateTimeFilter<"ModelAuthor"> | Date | string model?: XOR user?: XOR @@ -22962,6 +24258,7 @@ export namespace Prisma { modelId?: SortOrder userId?: SortOrder role?: SortOrder + collaboratorType?: SortOrderInput | SortOrder createdAt?: SortOrder model?: ModelOrderByWithRelationInput user?: UserOrderByWithRelationInput @@ -22975,6 +24272,7 @@ export namespace Prisma { modelId?: StringFilter<"ModelAuthor"> | string userId?: StringFilter<"ModelAuthor"> | string role?: EnumAuthorRoleFilter<"ModelAuthor"> | $Enums.AuthorRole + collaboratorType?: StringNullableFilter<"ModelAuthor"> | string | null createdAt?: DateTimeFilter<"ModelAuthor"> | Date | string model?: XOR user?: XOR @@ -22984,6 +24282,7 @@ export namespace Prisma { modelId?: SortOrder userId?: SortOrder role?: SortOrder + collaboratorType?: SortOrderInput | SortOrder createdAt?: SortOrder _count?: ModelAuthorCountOrderByAggregateInput _max?: ModelAuthorMaxOrderByAggregateInput @@ -22997,9 +24296,82 @@ export namespace Prisma { modelId?: StringWithAggregatesFilter<"ModelAuthor"> | string userId?: StringWithAggregatesFilter<"ModelAuthor"> | string role?: EnumAuthorRoleWithAggregatesFilter<"ModelAuthor"> | $Enums.AuthorRole + collaboratorType?: StringNullableWithAggregatesFilter<"ModelAuthor"> | string | null createdAt?: DateTimeWithAggregatesFilter<"ModelAuthor"> | Date | string } + export type NonMemberContributorWhereInput = { + AND?: NonMemberContributorWhereInput | NonMemberContributorWhereInput[] + OR?: NonMemberContributorWhereInput[] + NOT?: NonMemberContributorWhereInput | NonMemberContributorWhereInput[] + id?: StringFilter<"NonMemberContributor"> | string + legacyId?: IntFilter<"NonMemberContributor"> | number + modelId?: StringFilter<"NonMemberContributor"> | string + email?: StringNullableFilter<"NonMemberContributor"> | string | null + name?: StringNullableFilter<"NonMemberContributor"> | string | null + collaboratorType?: StringNullableFilter<"NonMemberContributor"> | string | null + addedByUserId?: StringNullableFilter<"NonMemberContributor"> | string | null + createdAt?: DateTimeFilter<"NonMemberContributor"> | Date | string + model?: XOR + } + + export type NonMemberContributorOrderByWithRelationInput = { + id?: SortOrder + legacyId?: SortOrder + modelId?: SortOrder + email?: SortOrderInput | SortOrder + name?: SortOrderInput | SortOrder + collaboratorType?: SortOrderInput | SortOrder + addedByUserId?: SortOrderInput | SortOrder + createdAt?: SortOrder + model?: ModelOrderByWithRelationInput + } + + export type NonMemberContributorWhereUniqueInput = Prisma.AtLeast<{ + id?: string + legacyId?: number + AND?: NonMemberContributorWhereInput | NonMemberContributorWhereInput[] + OR?: NonMemberContributorWhereInput[] + NOT?: NonMemberContributorWhereInput | NonMemberContributorWhereInput[] + modelId?: StringFilter<"NonMemberContributor"> | string + email?: StringNullableFilter<"NonMemberContributor"> | string | null + name?: StringNullableFilter<"NonMemberContributor"> | string | null + collaboratorType?: StringNullableFilter<"NonMemberContributor"> | string | null + addedByUserId?: StringNullableFilter<"NonMemberContributor"> | string | null + createdAt?: DateTimeFilter<"NonMemberContributor"> | Date | string + model?: XOR + }, "id" | "legacyId"> + + export type NonMemberContributorOrderByWithAggregationInput = { + id?: SortOrder + legacyId?: SortOrder + modelId?: SortOrder + email?: SortOrderInput | SortOrder + name?: SortOrderInput | SortOrder + collaboratorType?: SortOrderInput | SortOrder + addedByUserId?: SortOrderInput | SortOrder + createdAt?: SortOrder + _count?: NonMemberContributorCountOrderByAggregateInput + _avg?: NonMemberContributorAvgOrderByAggregateInput + _max?: NonMemberContributorMaxOrderByAggregateInput + _min?: NonMemberContributorMinOrderByAggregateInput + _sum?: NonMemberContributorSumOrderByAggregateInput + } + + export type NonMemberContributorScalarWhereWithAggregatesInput = { + AND?: NonMemberContributorScalarWhereWithAggregatesInput | NonMemberContributorScalarWhereWithAggregatesInput[] + OR?: NonMemberContributorScalarWhereWithAggregatesInput[] + NOT?: NonMemberContributorScalarWhereWithAggregatesInput | NonMemberContributorScalarWhereWithAggregatesInput[] + id?: StringWithAggregatesFilter<"NonMemberContributor"> | string + legacyId?: IntWithAggregatesFilter<"NonMemberContributor"> | number + modelId?: StringWithAggregatesFilter<"NonMemberContributor"> | string + email?: StringNullableWithAggregatesFilter<"NonMemberContributor"> | string | null + name?: StringNullableWithAggregatesFilter<"NonMemberContributor"> | string | null + collaboratorType?: StringNullableWithAggregatesFilter<"NonMemberContributor"> | string | null + addedByUserId?: StringNullableWithAggregatesFilter<"NonMemberContributor"> | string | null + createdAt?: DateTimeWithAggregatesFilter<"NonMemberContributor"> | Date | string + } + export type ModelPermissionWhereInput = { AND?: ModelPermissionWhereInput | ModelPermissionWhereInput[] OR?: ModelPermissionWhereInput[] @@ -23936,6 +25308,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -23962,6 +25335,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -23987,6 +25361,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -24013,6 +25388,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -24350,6 +25726,7 @@ export namespace Prisma { export type ModelAuthorCreateInput = { role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string model: ModelCreateNestedOneWithoutAuthorsInput user: UserCreateNestedOneWithoutAuthoredModelsInput @@ -24359,11 +25736,13 @@ export namespace Prisma { modelId: string userId: string role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string } export type ModelAuthorUpdateInput = { role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string model?: ModelUpdateOneRequiredWithoutAuthorsNestedInput user?: UserUpdateOneRequiredWithoutAuthoredModelsNestedInput @@ -24373,6 +25752,7 @@ export namespace Prisma { modelId?: StringFieldUpdateOperationsInput | string userId?: StringFieldUpdateOperationsInput | string role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -24380,11 +25760,13 @@ export namespace Prisma { modelId: string userId: string role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string } export type ModelAuthorUpdateManyMutationInput = { role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -24392,6 +25774,83 @@ export namespace Prisma { modelId?: StringFieldUpdateOperationsInput | string userId?: StringFieldUpdateOperationsInput | string role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type NonMemberContributorCreateInput = { + id?: string + legacyId: number + email?: string | null + name?: string | null + collaboratorType?: string | null + addedByUserId?: string | null + createdAt?: Date | string + model: ModelCreateNestedOneWithoutNonMemberContributorsInput + } + + export type NonMemberContributorUncheckedCreateInput = { + id?: string + legacyId: number + modelId: string + email?: string | null + name?: string | null + collaboratorType?: string | null + addedByUserId?: string | null + createdAt?: Date | string + } + + export type NonMemberContributorUpdateInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: IntFieldUpdateOperationsInput | number + email?: NullableStringFieldUpdateOperationsInput | string | null + name?: NullableStringFieldUpdateOperationsInput | string | null + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + addedByUserId?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + model?: ModelUpdateOneRequiredWithoutNonMemberContributorsNestedInput + } + + export type NonMemberContributorUncheckedUpdateInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: IntFieldUpdateOperationsInput | number + modelId?: StringFieldUpdateOperationsInput | string + email?: NullableStringFieldUpdateOperationsInput | string | null + name?: NullableStringFieldUpdateOperationsInput | string | null + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + addedByUserId?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type NonMemberContributorCreateManyInput = { + id?: string + legacyId: number + modelId: string + email?: string | null + name?: string | null + collaboratorType?: string | null + addedByUserId?: string | null + createdAt?: Date | string + } + + export type NonMemberContributorUpdateManyMutationInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: IntFieldUpdateOperationsInput | number + email?: NullableStringFieldUpdateOperationsInput | string | null + name?: NullableStringFieldUpdateOperationsInput | string | null + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + addedByUserId?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type NonMemberContributorUncheckedUpdateManyInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: IntFieldUpdateOperationsInput | number + modelId?: StringFieldUpdateOperationsInput | string + email?: NullableStringFieldUpdateOperationsInput | string | null + name?: NullableStringFieldUpdateOperationsInput | string | null + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + addedByUserId?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -25404,6 +26863,12 @@ export namespace Prisma { none?: ModelVersionWhereInput } + export type NonMemberContributorListRelationFilter = { + every?: NonMemberContributorWhereInput + some?: NonMemberContributorWhereInput + none?: NonMemberContributorWhereInput + } + export type ModelAdditionalFileListRelationFilter = { every?: ModelAdditionalFileWhereInput some?: ModelAdditionalFileWhereInput @@ -25418,6 +26883,10 @@ export namespace Prisma { _count?: SortOrder } + export type NonMemberContributorOrderByRelationAggregateInput = { + _count?: SortOrder + } + export type ModelAdditionalFileOrderByRelationAggregateInput = { _count?: SortOrder } @@ -25726,6 +27195,7 @@ export namespace Prisma { modelId?: SortOrder userId?: SortOrder role?: SortOrder + collaboratorType?: SortOrder createdAt?: SortOrder } @@ -25733,6 +27203,7 @@ export namespace Prisma { modelId?: SortOrder userId?: SortOrder role?: SortOrder + collaboratorType?: SortOrder createdAt?: SortOrder } @@ -25740,6 +27211,7 @@ export namespace Prisma { modelId?: SortOrder userId?: SortOrder role?: SortOrder + collaboratorType?: SortOrder createdAt?: SortOrder } @@ -25753,6 +27225,47 @@ export namespace Prisma { _max?: NestedEnumAuthorRoleFilter<$PrismaModel> } + export type NonMemberContributorCountOrderByAggregateInput = { + id?: SortOrder + legacyId?: SortOrder + modelId?: SortOrder + email?: SortOrder + name?: SortOrder + collaboratorType?: SortOrder + addedByUserId?: SortOrder + createdAt?: SortOrder + } + + export type NonMemberContributorAvgOrderByAggregateInput = { + legacyId?: SortOrder + } + + export type NonMemberContributorMaxOrderByAggregateInput = { + id?: SortOrder + legacyId?: SortOrder + modelId?: SortOrder + email?: SortOrder + name?: SortOrder + collaboratorType?: SortOrder + addedByUserId?: SortOrder + createdAt?: SortOrder + } + + export type NonMemberContributorMinOrderByAggregateInput = { + id?: SortOrder + legacyId?: SortOrder + modelId?: SortOrder + email?: SortOrder + name?: SortOrder + collaboratorType?: SortOrder + addedByUserId?: SortOrder + createdAt?: SortOrder + } + + export type NonMemberContributorSumOrderByAggregateInput = { + legacyId?: SortOrder + } + export type EnumPermissionLevelFilter<$PrismaModel = never> = { equals?: $Enums.PermissionLevel | EnumPermissionLevelFieldRefInput<$PrismaModel> in?: $Enums.PermissionLevel[] | ListEnumPermissionLevelFieldRefInput<$PrismaModel> @@ -26571,6 +28084,13 @@ export namespace Prisma { connect?: ModelAuthorWhereUniqueInput | ModelAuthorWhereUniqueInput[] } + export type NonMemberContributorCreateNestedManyWithoutModelInput = { + create?: XOR | NonMemberContributorCreateWithoutModelInput[] | NonMemberContributorUncheckedCreateWithoutModelInput[] + connectOrCreate?: NonMemberContributorCreateOrConnectWithoutModelInput | NonMemberContributorCreateOrConnectWithoutModelInput[] + createMany?: NonMemberContributorCreateManyModelInputEnvelope + connect?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + } + export type ModelPermissionCreateNestedManyWithoutModelInput = { create?: XOR | ModelPermissionCreateWithoutModelInput[] | ModelPermissionUncheckedCreateWithoutModelInput[] connectOrCreate?: ModelPermissionCreateOrConnectWithoutModelInput | ModelPermissionCreateOrConnectWithoutModelInput[] @@ -26627,6 +28147,13 @@ export namespace Prisma { connect?: ModelAuthorWhereUniqueInput | ModelAuthorWhereUniqueInput[] } + export type NonMemberContributorUncheckedCreateNestedManyWithoutModelInput = { + create?: XOR | NonMemberContributorCreateWithoutModelInput[] | NonMemberContributorUncheckedCreateWithoutModelInput[] + connectOrCreate?: NonMemberContributorCreateOrConnectWithoutModelInput | NonMemberContributorCreateOrConnectWithoutModelInput[] + createMany?: NonMemberContributorCreateManyModelInputEnvelope + connect?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + } + export type ModelPermissionUncheckedCreateNestedManyWithoutModelInput = { create?: XOR | ModelPermissionCreateWithoutModelInput[] | ModelPermissionUncheckedCreateWithoutModelInput[] connectOrCreate?: ModelPermissionCreateOrConnectWithoutModelInput | ModelPermissionCreateOrConnectWithoutModelInput[] @@ -26738,6 +28265,20 @@ export namespace Prisma { deleteMany?: ModelAuthorScalarWhereInput | ModelAuthorScalarWhereInput[] } + export type NonMemberContributorUpdateManyWithoutModelNestedInput = { + create?: XOR | NonMemberContributorCreateWithoutModelInput[] | NonMemberContributorUncheckedCreateWithoutModelInput[] + connectOrCreate?: NonMemberContributorCreateOrConnectWithoutModelInput | NonMemberContributorCreateOrConnectWithoutModelInput[] + upsert?: NonMemberContributorUpsertWithWhereUniqueWithoutModelInput | NonMemberContributorUpsertWithWhereUniqueWithoutModelInput[] + createMany?: NonMemberContributorCreateManyModelInputEnvelope + set?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + disconnect?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + delete?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + connect?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + update?: NonMemberContributorUpdateWithWhereUniqueWithoutModelInput | NonMemberContributorUpdateWithWhereUniqueWithoutModelInput[] + updateMany?: NonMemberContributorUpdateManyWithWhereWithoutModelInput | NonMemberContributorUpdateManyWithWhereWithoutModelInput[] + deleteMany?: NonMemberContributorScalarWhereInput | NonMemberContributorScalarWhereInput[] + } + export type ModelPermissionUpdateManyWithoutModelNestedInput = { create?: XOR | ModelPermissionCreateWithoutModelInput[] | ModelPermissionUncheckedCreateWithoutModelInput[] connectOrCreate?: ModelPermissionCreateOrConnectWithoutModelInput | ModelPermissionCreateOrConnectWithoutModelInput[] @@ -26850,6 +28391,20 @@ export namespace Prisma { deleteMany?: ModelAuthorScalarWhereInput | ModelAuthorScalarWhereInput[] } + export type NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput = { + create?: XOR | NonMemberContributorCreateWithoutModelInput[] | NonMemberContributorUncheckedCreateWithoutModelInput[] + connectOrCreate?: NonMemberContributorCreateOrConnectWithoutModelInput | NonMemberContributorCreateOrConnectWithoutModelInput[] + upsert?: NonMemberContributorUpsertWithWhereUniqueWithoutModelInput | NonMemberContributorUpsertWithWhereUniqueWithoutModelInput[] + createMany?: NonMemberContributorCreateManyModelInputEnvelope + set?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + disconnect?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + delete?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + connect?: NonMemberContributorWhereUniqueInput | NonMemberContributorWhereUniqueInput[] + update?: NonMemberContributorUpdateWithWhereUniqueWithoutModelInput | NonMemberContributorUpdateWithWhereUniqueWithoutModelInput[] + updateMany?: NonMemberContributorUpdateManyWithWhereWithoutModelInput | NonMemberContributorUpdateManyWithWhereWithoutModelInput[] + deleteMany?: NonMemberContributorScalarWhereInput | NonMemberContributorScalarWhereInput[] + } + export type ModelPermissionUncheckedUpdateManyWithoutModelNestedInput = { create?: XOR | ModelPermissionCreateWithoutModelInput[] | ModelPermissionUncheckedCreateWithoutModelInput[] connectOrCreate?: ModelPermissionCreateOrConnectWithoutModelInput | ModelPermissionCreateOrConnectWithoutModelInput[] @@ -27226,6 +28781,20 @@ export namespace Prisma { update?: XOR, UserUncheckedUpdateWithoutAuthoredModelsInput> } + export type ModelCreateNestedOneWithoutNonMemberContributorsInput = { + create?: XOR + connectOrCreate?: ModelCreateOrConnectWithoutNonMemberContributorsInput + connect?: ModelWhereUniqueInput + } + + export type ModelUpdateOneRequiredWithoutNonMemberContributorsNestedInput = { + create?: XOR + connectOrCreate?: ModelCreateOrConnectWithoutNonMemberContributorsInput + upsert?: ModelUpsertWithoutNonMemberContributorsInput + connect?: ModelWhereUniqueInput + update?: XOR, ModelUncheckedUpdateWithoutNonMemberContributorsInput> + } + export type ModelCreateNestedOneWithoutPermissionsInput = { create?: XOR connectOrCreate?: ModelCreateOrConnectWithoutPermissionsInput @@ -27847,6 +29416,7 @@ export namespace Prisma { export type ModelAuthorCreateWithoutUserInput = { role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string model: ModelCreateNestedOneWithoutAuthorsInput } @@ -27854,6 +29424,7 @@ export namespace Prisma { export type ModelAuthorUncheckedCreateWithoutUserInput = { modelId: string role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string } @@ -28161,6 +29732,7 @@ export namespace Prisma { modelId?: StringFilter<"ModelAuthor"> | string userId?: StringFilter<"ModelAuthor"> | string role?: EnumAuthorRoleFilter<"ModelAuthor"> | $Enums.AuthorRole + collaboratorType?: StringNullableFilter<"ModelAuthor"> | string | null createdAt?: DateTimeFilter<"ModelAuthor"> | Date | string } @@ -29006,6 +30578,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -29031,6 +30604,7 @@ export namespace Prisma { deletedAt?: Date | string | null versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -29060,6 +30634,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -29085,6 +30660,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -29187,6 +30763,7 @@ export namespace Prisma { export type ModelAuthorCreateWithoutModelInput = { role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string user: UserCreateNestedOneWithoutAuthoredModelsInput } @@ -29194,6 +30771,7 @@ export namespace Prisma { export type ModelAuthorUncheckedCreateWithoutModelInput = { userId: string role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string } @@ -29207,6 +30785,36 @@ export namespace Prisma { skipDuplicates?: boolean } + export type NonMemberContributorCreateWithoutModelInput = { + id?: string + legacyId: number + email?: string | null + name?: string | null + collaboratorType?: string | null + addedByUserId?: string | null + createdAt?: Date | string + } + + export type NonMemberContributorUncheckedCreateWithoutModelInput = { + id?: string + legacyId: number + email?: string | null + name?: string | null + collaboratorType?: string | null + addedByUserId?: string | null + createdAt?: Date | string + } + + export type NonMemberContributorCreateOrConnectWithoutModelInput = { + where: NonMemberContributorWhereUniqueInput + create: XOR + } + + export type NonMemberContributorCreateManyModelInputEnvelope = { + data: NonMemberContributorCreateManyModelInput | NonMemberContributorCreateManyModelInput[] + skipDuplicates?: boolean + } + export type ModelPermissionCreateWithoutModelInput = { id?: string permissionLevel: $Enums.PermissionLevel @@ -29416,6 +31024,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -29441,6 +31050,7 @@ export namespace Prisma { deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -29579,6 +31189,36 @@ export namespace Prisma { data: XOR } + export type NonMemberContributorUpsertWithWhereUniqueWithoutModelInput = { + where: NonMemberContributorWhereUniqueInput + update: XOR + create: XOR + } + + export type NonMemberContributorUpdateWithWhereUniqueWithoutModelInput = { + where: NonMemberContributorWhereUniqueInput + data: XOR + } + + export type NonMemberContributorUpdateManyWithWhereWithoutModelInput = { + where: NonMemberContributorScalarWhereInput + data: XOR + } + + export type NonMemberContributorScalarWhereInput = { + AND?: NonMemberContributorScalarWhereInput | NonMemberContributorScalarWhereInput[] + OR?: NonMemberContributorScalarWhereInput[] + NOT?: NonMemberContributorScalarWhereInput | NonMemberContributorScalarWhereInput[] + id?: StringFilter<"NonMemberContributor"> | string + legacyId?: IntFilter<"NonMemberContributor"> | number + modelId?: StringFilter<"NonMemberContributor"> | string + email?: StringNullableFilter<"NonMemberContributor"> | string | null + name?: StringNullableFilter<"NonMemberContributor"> | string | null + collaboratorType?: StringNullableFilter<"NonMemberContributor"> | string | null + addedByUserId?: StringNullableFilter<"NonMemberContributor"> | string | null + createdAt?: DateTimeFilter<"NonMemberContributor"> | Date | string + } + export type ModelPermissionUpsertWithWhereUniqueWithoutModelInput = { where: ModelPermissionWhereUniqueInput update: XOR @@ -29688,6 +31328,7 @@ export namespace Prisma { childModels?: ModelCreateNestedManyWithoutParentModelInput parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -29713,6 +31354,7 @@ export namespace Prisma { deletedAt?: Date | string | null childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -29742,6 +31384,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -29766,6 +31409,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -29795,6 +31439,7 @@ export namespace Prisma { childModels?: ModelCreateNestedManyWithoutParentModelInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -29819,6 +31464,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -29909,6 +31555,7 @@ export namespace Prisma { childModels?: ModelUpdateManyWithoutParentModelNestedInput parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -29934,6 +31581,7 @@ export namespace Prisma { deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -29969,6 +31617,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -29993,6 +31642,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -30208,6 +31858,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput interactions?: ModelInteractionCreateNestedManyWithoutModelInput @@ -30233,6 +31884,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput interactions?: ModelInteractionUncheckedCreateNestedManyWithoutModelInput @@ -30312,6 +31964,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput interactions?: ModelInteractionUpdateManyWithoutModelNestedInput @@ -30337,6 +31990,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput interactions?: ModelInteractionUncheckedUpdateManyWithoutModelNestedInput @@ -30442,6 +32096,7 @@ export namespace Prisma { childModels?: ModelCreateNestedManyWithoutParentModelInput parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -30467,6 +32122,7 @@ export namespace Prisma { deletedAt?: Date | string | null childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -30580,6 +32236,7 @@ export namespace Prisma { childModels?: ModelUpdateManyWithoutParentModelNestedInput parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -30605,6 +32262,7 @@ export namespace Prisma { deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -30691,6 +32349,124 @@ export namespace Prisma { passkeys?: PasskeyUncheckedUpdateManyWithoutUserNestedInput } + export type ModelCreateWithoutNonMemberContributorsInput = { + legacyId?: number | null + visibility?: $Enums.ModelVisibility + isEndorsed?: boolean + isLibraryModel?: boolean + viewCount?: number + runCount?: number + downloadCount?: number + shareCount?: number + createdAt?: Date | string + updatedAt?: Date | string + deletedAt?: Date | string | null + latestVersion?: ModelVersionCreateNestedOneWithoutLatestOfModelInput + parentModel?: ModelCreateNestedOneWithoutChildModelsInput + childModels?: ModelCreateNestedManyWithoutParentModelInput + parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput + versions?: ModelVersionCreateNestedManyWithoutModelInput + authors?: ModelAuthorCreateNestedManyWithoutModelInput + permissions?: ModelPermissionCreateNestedManyWithoutModelInput + additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput + likes?: ModelLikeCreateNestedManyWithoutModelInput + interactions?: ModelInteractionCreateNestedManyWithoutModelInput + drafts?: ModelDraftCreateNestedManyWithoutModelInput + } + + export type ModelUncheckedCreateWithoutNonMemberContributorsInput = { + id?: string + legacyId?: number | null + latestVersionNumber?: number | null + parentModelId?: string | null + parentVersionNumber?: number | null + visibility?: $Enums.ModelVisibility + isEndorsed?: boolean + isLibraryModel?: boolean + viewCount?: number + runCount?: number + downloadCount?: number + shareCount?: number + createdAt?: Date | string + updatedAt?: Date | string + deletedAt?: Date | string | null + childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput + versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput + authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput + additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput + likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput + interactions?: ModelInteractionUncheckedCreateNestedManyWithoutModelInput + drafts?: ModelDraftUncheckedCreateNestedManyWithoutModelInput + } + + export type ModelCreateOrConnectWithoutNonMemberContributorsInput = { + where: ModelWhereUniqueInput + create: XOR + } + + export type ModelUpsertWithoutNonMemberContributorsInput = { + update: XOR + create: XOR + where?: ModelWhereInput + } + + export type ModelUpdateToOneWithWhereWithoutNonMemberContributorsInput = { + where?: ModelWhereInput + data: XOR + } + + export type ModelUpdateWithoutNonMemberContributorsInput = { + legacyId?: NullableIntFieldUpdateOperationsInput | number | null + visibility?: EnumModelVisibilityFieldUpdateOperationsInput | $Enums.ModelVisibility + isEndorsed?: BoolFieldUpdateOperationsInput | boolean + isLibraryModel?: BoolFieldUpdateOperationsInput | boolean + viewCount?: IntFieldUpdateOperationsInput | number + runCount?: IntFieldUpdateOperationsInput | number + downloadCount?: IntFieldUpdateOperationsInput | number + shareCount?: IntFieldUpdateOperationsInput | number + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + latestVersion?: ModelVersionUpdateOneWithoutLatestOfModelNestedInput + parentModel?: ModelUpdateOneWithoutChildModelsNestedInput + childModels?: ModelUpdateManyWithoutParentModelNestedInput + parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput + versions?: ModelVersionUpdateManyWithoutModelNestedInput + authors?: ModelAuthorUpdateManyWithoutModelNestedInput + permissions?: ModelPermissionUpdateManyWithoutModelNestedInput + additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput + likes?: ModelLikeUpdateManyWithoutModelNestedInput + interactions?: ModelInteractionUpdateManyWithoutModelNestedInput + drafts?: ModelDraftUpdateManyWithoutModelNestedInput + } + + export type ModelUncheckedUpdateWithoutNonMemberContributorsInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: NullableIntFieldUpdateOperationsInput | number | null + latestVersionNumber?: NullableIntFieldUpdateOperationsInput | number | null + parentModelId?: NullableStringFieldUpdateOperationsInput | string | null + parentVersionNumber?: NullableIntFieldUpdateOperationsInput | number | null + visibility?: EnumModelVisibilityFieldUpdateOperationsInput | $Enums.ModelVisibility + isEndorsed?: BoolFieldUpdateOperationsInput | boolean + isLibraryModel?: BoolFieldUpdateOperationsInput | boolean + viewCount?: IntFieldUpdateOperationsInput | number + runCount?: IntFieldUpdateOperationsInput | number + downloadCount?: IntFieldUpdateOperationsInput | number + shareCount?: IntFieldUpdateOperationsInput | number + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + updatedAt?: DateTimeFieldUpdateOperationsInput | Date | string + deletedAt?: NullableDateTimeFieldUpdateOperationsInput | Date | string | null + childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput + versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput + authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput + additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput + likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput + interactions?: ModelInteractionUncheckedUpdateManyWithoutModelNestedInput + drafts?: ModelDraftUncheckedUpdateManyWithoutModelNestedInput + } + export type ModelCreateWithoutPermissionsInput = { legacyId?: number | null visibility?: $Enums.ModelVisibility @@ -30709,6 +32485,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput interactions?: ModelInteractionCreateNestedManyWithoutModelInput @@ -30734,6 +32511,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput interactions?: ModelInteractionUncheckedCreateNestedManyWithoutModelInput @@ -30847,6 +32625,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput interactions?: ModelInteractionUpdateManyWithoutModelNestedInput @@ -30872,6 +32651,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput interactions?: ModelInteractionUncheckedUpdateManyWithoutModelNestedInput @@ -30975,6 +32755,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput interactions?: ModelInteractionCreateNestedManyWithoutModelInput @@ -31000,6 +32781,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput interactions?: ModelInteractionUncheckedCreateNestedManyWithoutModelInput @@ -31113,6 +32895,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput interactions?: ModelInteractionUpdateManyWithoutModelNestedInput @@ -31138,6 +32921,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput interactions?: ModelInteractionUncheckedUpdateManyWithoutModelNestedInput @@ -31241,6 +33025,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -31266,6 +33051,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -31379,6 +33165,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -31404,6 +33191,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -31580,6 +33368,7 @@ export namespace Prisma { parentVersion?: ModelVersionCreateNestedOneWithoutParentOfModelsInput versions?: ModelVersionCreateNestedManyWithoutModelInput authors?: ModelAuthorCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorCreateNestedManyWithoutModelInput permissions?: ModelPermissionCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileCreateNestedManyWithoutModelInput likes?: ModelLikeCreateNestedManyWithoutModelInput @@ -31605,6 +33394,7 @@ export namespace Prisma { childModels?: ModelUncheckedCreateNestedManyWithoutParentModelInput versions?: ModelVersionUncheckedCreateNestedManyWithoutModelInput authors?: ModelAuthorUncheckedCreateNestedManyWithoutModelInput + nonMemberContributors?: NonMemberContributorUncheckedCreateNestedManyWithoutModelInput permissions?: ModelPermissionUncheckedCreateNestedManyWithoutModelInput additionalFiles?: ModelAdditionalFileUncheckedCreateNestedManyWithoutModelInput likes?: ModelLikeUncheckedCreateNestedManyWithoutModelInput @@ -31724,6 +33514,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -31749,6 +33540,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -31945,6 +33737,7 @@ export namespace Prisma { export type ModelAuthorCreateManyUserInput = { modelId: string role: $Enums.AuthorRole + collaboratorType?: string | null createdAt?: Date | string } @@ -32113,6 +33906,7 @@ export namespace Prisma { export type ModelAuthorUpdateWithoutUserInput = { role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string model?: ModelUpdateOneRequiredWithoutAuthorsNestedInput } @@ -32120,12 +33914,14 @@ export namespace Prisma { export type ModelAuthorUncheckedUpdateWithoutUserInput = { modelId?: StringFieldUpdateOperationsInput | string role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string } export type ModelAuthorUncheckedUpdateManyWithoutUserInput = { modelId?: StringFieldUpdateOperationsInput | string role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -32336,6 +34132,17 @@ export namespace Prisma { export type ModelAuthorCreateManyModelInput = { userId: string role: $Enums.AuthorRole + collaboratorType?: string | null + createdAt?: Date | string + } + + export type NonMemberContributorCreateManyModelInput = { + id?: string + legacyId: number + email?: string | null + name?: string | null + collaboratorType?: string | null + addedByUserId?: string | null createdAt?: Date | string } @@ -32399,6 +34206,7 @@ export namespace Prisma { parentVersion?: ModelVersionUpdateOneWithoutParentOfModelsNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -32424,6 +34232,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput @@ -32497,6 +34306,7 @@ export namespace Prisma { export type ModelAuthorUpdateWithoutModelInput = { role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string user?: UserUpdateOneRequiredWithoutAuthoredModelsNestedInput } @@ -32504,12 +34314,44 @@ export namespace Prisma { export type ModelAuthorUncheckedUpdateWithoutModelInput = { userId?: StringFieldUpdateOperationsInput | string role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string } export type ModelAuthorUncheckedUpdateManyWithoutModelInput = { userId?: StringFieldUpdateOperationsInput | string role?: EnumAuthorRoleFieldUpdateOperationsInput | $Enums.AuthorRole + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type NonMemberContributorUpdateWithoutModelInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: IntFieldUpdateOperationsInput | number + email?: NullableStringFieldUpdateOperationsInput | string | null + name?: NullableStringFieldUpdateOperationsInput | string | null + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + addedByUserId?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type NonMemberContributorUncheckedUpdateWithoutModelInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: IntFieldUpdateOperationsInput | number + email?: NullableStringFieldUpdateOperationsInput | string | null + name?: NullableStringFieldUpdateOperationsInput | string | null + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + addedByUserId?: NullableStringFieldUpdateOperationsInput | string | null + createdAt?: DateTimeFieldUpdateOperationsInput | Date | string + } + + export type NonMemberContributorUncheckedUpdateManyWithoutModelInput = { + id?: StringFieldUpdateOperationsInput | string + legacyId?: IntFieldUpdateOperationsInput | number + email?: NullableStringFieldUpdateOperationsInput | string | null + name?: NullableStringFieldUpdateOperationsInput | string | null + collaboratorType?: NullableStringFieldUpdateOperationsInput | string | null + addedByUserId?: NullableStringFieldUpdateOperationsInput | string | null createdAt?: DateTimeFieldUpdateOperationsInput | Date | string } @@ -32687,6 +34529,7 @@ export namespace Prisma { childModels?: ModelUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUpdateManyWithoutModelNestedInput authors?: ModelAuthorUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUpdateManyWithoutModelNestedInput likes?: ModelLikeUpdateManyWithoutModelNestedInput @@ -32711,6 +34554,7 @@ export namespace Prisma { childModels?: ModelUncheckedUpdateManyWithoutParentModelNestedInput versions?: ModelVersionUncheckedUpdateManyWithoutModelNestedInput authors?: ModelAuthorUncheckedUpdateManyWithoutModelNestedInput + nonMemberContributors?: NonMemberContributorUncheckedUpdateManyWithoutModelNestedInput permissions?: ModelPermissionUncheckedUpdateManyWithoutModelNestedInput additionalFiles?: ModelAdditionalFileUncheckedUpdateManyWithoutModelNestedInput likes?: ModelLikeUncheckedUpdateManyWithoutModelNestedInput diff --git a/apps/modeling-commons-backend/generated/prisma/index.js b/apps/modeling-commons-backend/generated/prisma/index.js index f31a743b..19f6bd39 100644 --- a/apps/modeling-commons-backend/generated/prisma/index.js +++ b/apps/modeling-commons-backend/generated/prisma/index.js @@ -230,6 +230,18 @@ exports.Prisma.ModelAuthorScalarFieldEnum = { modelId: 'modelId', userId: 'userId', role: 'role', + collaboratorType: 'collaboratorType', + createdAt: 'createdAt' +}; + +exports.Prisma.NonMemberContributorScalarFieldEnum = { + id: 'id', + legacyId: 'legacyId', + modelId: 'modelId', + email: 'email', + name: 'name', + collaboratorType: 'collaboratorType', + addedByUserId: 'addedByUserId', createdAt: 'createdAt' }; @@ -366,6 +378,7 @@ exports.Prisma.ModelName = { ModelAdditionalFile: 'ModelAdditionalFile', Tag: 'Tag', ModelAuthor: 'ModelAuthor', + NonMemberContributor: 'NonMemberContributor', ModelPermission: 'ModelPermission', ModelLike: 'ModelLike', ModelInteraction: 'ModelInteraction', @@ -380,14 +393,14 @@ const config = { "clientVersion": "7.8.0", "engineVersion": "3c6e192761c0362d496ed980de936e2f3cebcd3a", "activeProvider": "postgresql", - "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\n// Enums\n\nenum ModelVisibility {\n public\n private\n unlisted\n}\n\nenum SystemRole {\n admin\n moderator\n user\n}\n\nenum UserKind {\n student\n teacher\n researcher\n other\n}\n\nenum AuthorRole {\n owner\n contributor\n}\n\nenum PermissionLevel {\n read\n write\n admin\n}\n\nenum ModelInteractionKind {\n view\n run\n download\n share\n}\n\nenum ModelFileKind {\n model\n additional\n}\n\n// Better Auth core tables\n\nmodel User {\n id String @id @default(uuid())\n name String?\n email String? @unique\n emailVerified Boolean @default(false)\n image String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n // Extended fields\n systemRole SystemRole @default(user)\n userKind UserKind @default(other)\n isProfilePublic Boolean @default(false)\n deletedAt DateTime?\n\n // User profile fields\n bio String?\n country String?\n socialLinks Json? // e.g. [{ platform: 'twitter', url: '...' }]\n dob DateTime? @db.Date\n affiliation String?\n\n // Better Auth relations\n accounts Account[]\n sessions Session[]\n verifications Verification[]\n\n // Domain relations\n authoredModels ModelAuthor[]\n grantedPermissions ModelPermission[]\n events Event[]\n modelLikes ModelLike[]\n modelInteractions ModelInteraction[]\n modelDrafts ModelDraft[]\n\n // Better Auth Admin plugin\n role String?\n banned Boolean?\n banReason String?\n banExpires DateTime? @db.Timestamptz(3)\n\n // Application behavior\n onboardedAt DateTime? @db.Timestamptz(3)\n legacyId Int? @unique\n\n // Passkey relations\n passkeys Passkey[]\n}\n\nmodel Account {\n id String @id @default(uuid())\n userId String\n accountId String\n providerId String\n accessToken String?\n refreshToken String?\n accessTokenExpiresAt DateTime? @db.Timestamptz(3)\n refreshTokenExpiresAt DateTime? @db.Timestamptz(3)\n scope String?\n idToken String?\n password String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId])\n}\n\nmodel Session {\n id String @id @default(uuid())\n userId String\n expiresAt DateTime\n token String @unique\n ipAddress String?\n userAgent String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Better Auth Admin plugin fields\n impersonatedBy String?\n\n @@index([userId])\n}\n\nmodel Verification {\n id String @id @default(uuid())\n identifier String\n value String\n expiresAt DateTime\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n updatedAt DateTime? @updatedAt @db.Timestamptz(3)\n\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n userId String?\n\n @@index([userId])\n}\n\nmodel Passkey {\n id String @id @default(uuid())\n name String?\n publicKey String\n userId String\n credentialID String\n counter Int\n deviceType String\n backedUp Boolean\n transports String?\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n aaguid String?\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\n// Domain models\n\nmodel Model {\n id String @id @default(uuid())\n legacyId Int? @unique\n latestVersionNumber Int?\n parentModelId String?\n parentVersionNumber Int?\n visibility ModelVisibility @default(public)\n isEndorsed Boolean @default(false)\n isLibraryModel Boolean @default(false)\n viewCount Int @default(0)\n runCount Int @default(0)\n downloadCount Int @default(0)\n shareCount Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n deletedAt DateTime?\n\n latestVersion ModelVersion? @relation(\"LatestVersion\", fields: [id, latestVersionNumber], references: [modelId, versionNumber])\n parentModel Model? @relation(\"ModelParent\", fields: [parentModelId], references: [id])\n childModels Model[] @relation(\"ModelParent\")\n parentVersion ModelVersion? @relation(\"ParentVersion\", fields: [parentModelId, parentVersionNumber], references: [modelId, versionNumber])\n\n versions ModelVersion[] @relation(\"ModelVersions\")\n authors ModelAuthor[]\n permissions ModelPermission[]\n additionalFiles ModelAdditionalFile[]\n likes ModelLike[]\n interactions ModelInteraction[]\n drafts ModelDraft[]\n\n @@unique([id, latestVersionNumber])\n @@index([parentModelId])\n @@index([parentModelId, parentVersionNumber])\n @@index([viewCount])\n @@index([runCount])\n @@index([downloadCount])\n}\n\nmodel ModelVersion {\n modelId String\n versionNumber Int\n title String\n description String?\n changeSummary String?\n previewImageFileKey String?\n netlogoFileKey String\n netlogoVersion String?\n infoTab String?\n createdAt DateTime @default(now())\n finalizedAt DateTime?\n\n model Model @relation(\"ModelVersions\", fields: [modelId], references: [id], onDelete: Cascade)\n\n // Reverse relations\n latestOfModel Model? @relation(\"LatestVersion\")\n parentOfModels Model[] @relation(\"ParentVersion\")\n\n tags ModelVersionTag[]\n taggedAdditionalFiles ModelAdditionalFile[]\n\n @@id([modelId, versionNumber])\n @@index([modelId])\n}\n\nmodel ModelVersionTag {\n modelId String\n versionNumber Int\n tagId String\n createdAt DateTime @default(now())\n\n modelVersion ModelVersion @relation(fields: [modelId, versionNumber], references: [modelId, versionNumber], onDelete: Cascade)\n tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)\n\n @@id([modelId, versionNumber, tagId])\n @@index([tagId])\n}\n\nmodel ModelAdditionalFile {\n id String @id @default(uuid())\n modelId String\n taggedVersionNumber Int\n fileKey String\n kind ModelFileKind @default(additional)\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n taggedVersion ModelVersion @relation(fields: [modelId, taggedVersionNumber], references: [modelId, versionNumber])\n\n @@index([modelId])\n @@index([modelId, taggedVersionNumber])\n}\n\nmodel Tag {\n id String @id @default(uuid())\n legacyId Int? @unique\n name String @unique\n displayName String?\n createdAt DateTime @default(now())\n\n modelVersions ModelVersionTag[]\n}\n\nmodel ModelAuthor {\n modelId String\n userId String\n role AuthorRole\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n}\n\nmodel ModelPermission {\n id String @id @default(uuid())\n modelId String\n granteeUserId String?\n permissionLevel PermissionLevel\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n granteeUser User? @relation(fields: [granteeUserId], references: [id], onDelete: Cascade)\n\n @@unique([modelId, granteeUserId])\n @@index([modelId])\n @@index([granteeUserId])\n}\n\nmodel ModelLike {\n modelId String\n userId String\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n @@index([modelId, createdAt])\n}\n\nmodel ModelInteraction {\n id String @id @default(uuid())\n modelId String\n versionNumber Int?\n kind ModelInteractionKind\n userId String?\n sessionId String?\n ipHash String?\n userAgent String?\n referer String?\n geo Json?\n cookie String?\n\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User? @relation(fields: [userId], references: [id], onDelete: SetNull)\n\n @@index([modelId, kind, createdAt])\n @@index([modelId, kind, userId])\n @@index([userId, createdAt])\n @@index([createdAt])\n}\n\nmodel ModelDraft {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n modelId String?\n model Model? @relation(fields: [modelId], references: [id], onDelete: Cascade)\n\n schemaVersion Int\n data Json\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@index([modelId])\n}\n\nmodel Event {\n id String @id @default(uuid())\n type String\n actorId String\n resourceType String\n resourceId String\n payload Json\n createdAt DateTime @default(now())\n processedAt DateTime?\n\n actor User @relation(fields: [actorId], references: [id])\n\n @@index([actorId])\n @@index([resourceType, resourceId])\n @@index([type])\n @@index([processedAt])\n}\n" + "inlineSchema": "generator client {\n provider = \"prisma-client-js\"\n output = \"../generated/prisma\"\n}\n\ndatasource db {\n provider = \"postgresql\"\n}\n\n// Enums\n\nenum ModelVisibility {\n public\n private\n unlisted\n}\n\nenum SystemRole {\n admin\n moderator\n user\n}\n\nenum UserKind {\n student\n teacher\n researcher\n other\n}\n\nenum AuthorRole {\n owner\n contributor\n}\n\nenum PermissionLevel {\n read\n write\n admin\n}\n\nenum ModelInteractionKind {\n view\n run\n download\n share\n}\n\nenum ModelFileKind {\n model\n additional\n}\n\n// Better Auth core tables\n\nmodel User {\n id String @id @default(uuid())\n name String?\n email String? @unique\n emailVerified Boolean @default(false)\n image String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n // Extended fields\n systemRole SystemRole @default(user)\n userKind UserKind @default(other)\n isProfilePublic Boolean @default(false)\n deletedAt DateTime?\n\n // User profile fields\n bio String?\n country String?\n socialLinks Json? // e.g. [{ platform: 'twitter', url: '...' }]\n dob DateTime? @db.Date\n affiliation String?\n\n // Better Auth relations\n accounts Account[]\n sessions Session[]\n verifications Verification[]\n\n // Domain relations\n authoredModels ModelAuthor[]\n grantedPermissions ModelPermission[]\n events Event[]\n modelLikes ModelLike[]\n modelInteractions ModelInteraction[]\n modelDrafts ModelDraft[]\n\n // Better Auth Admin plugin\n role String?\n banned Boolean?\n banReason String?\n banExpires DateTime? @db.Timestamptz(3)\n\n // Application behavior\n onboardedAt DateTime? @db.Timestamptz(3)\n legacyId Int? @unique\n\n // Passkey relations\n passkeys Passkey[]\n}\n\nmodel Account {\n id String @id @default(uuid())\n userId String\n accountId String\n providerId String\n accessToken String?\n refreshToken String?\n accessTokenExpiresAt DateTime? @db.Timestamptz(3)\n refreshTokenExpiresAt DateTime? @db.Timestamptz(3)\n scope String?\n idToken String?\n password String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@index([userId])\n}\n\nmodel Session {\n id String @id @default(uuid())\n userId String\n expiresAt DateTime\n token String @unique\n ipAddress String?\n userAgent String?\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n updatedAt DateTime @updatedAt @db.Timestamptz(3)\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n // Better Auth Admin plugin fields\n impersonatedBy String?\n\n @@index([userId])\n}\n\nmodel Verification {\n id String @id @default(uuid())\n identifier String\n value String\n expiresAt DateTime\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n updatedAt DateTime? @updatedAt @db.Timestamptz(3)\n\n user User? @relation(fields: [userId], references: [id], onDelete: Cascade)\n userId String?\n\n @@index([userId])\n}\n\nmodel Passkey {\n id String @id @default(uuid())\n name String?\n publicKey String\n userId String\n credentialID String\n counter Int\n deviceType String\n backedUp Boolean\n transports String?\n createdAt DateTime? @default(now()) @db.Timestamptz(3)\n aaguid String?\n\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n}\n\n// Domain models\n\nmodel Model {\n id String @id @default(uuid())\n legacyId Int? @unique\n latestVersionNumber Int?\n parentModelId String?\n parentVersionNumber Int?\n visibility ModelVisibility @default(public)\n isEndorsed Boolean @default(false)\n isLibraryModel Boolean @default(false)\n viewCount Int @default(0)\n runCount Int @default(0)\n downloadCount Int @default(0)\n shareCount Int @default(0)\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n deletedAt DateTime?\n\n latestVersion ModelVersion? @relation(\"LatestVersion\", fields: [id, latestVersionNumber], references: [modelId, versionNumber])\n parentModel Model? @relation(\"ModelParent\", fields: [parentModelId], references: [id])\n childModels Model[] @relation(\"ModelParent\")\n parentVersion ModelVersion? @relation(\"ParentVersion\", fields: [parentModelId, parentVersionNumber], references: [modelId, versionNumber])\n\n versions ModelVersion[] @relation(\"ModelVersions\")\n authors ModelAuthor[]\n nonMemberContributors NonMemberContributor[]\n permissions ModelPermission[]\n additionalFiles ModelAdditionalFile[]\n likes ModelLike[]\n interactions ModelInteraction[]\n drafts ModelDraft[]\n\n @@unique([id, latestVersionNumber])\n @@index([parentModelId])\n @@index([parentModelId, parentVersionNumber])\n @@index([viewCount])\n @@index([runCount])\n @@index([downloadCount])\n}\n\nmodel ModelVersion {\n modelId String\n versionNumber Int\n title String\n description String?\n changeSummary String?\n previewImageFileKey String?\n netlogoFileKey String\n netlogoVersion String?\n infoTab String?\n createdAt DateTime @default(now())\n finalizedAt DateTime?\n\n model Model @relation(\"ModelVersions\", fields: [modelId], references: [id], onDelete: Cascade)\n\n // Reverse relations\n latestOfModel Model? @relation(\"LatestVersion\")\n parentOfModels Model[] @relation(\"ParentVersion\")\n\n tags ModelVersionTag[]\n taggedAdditionalFiles ModelAdditionalFile[]\n\n @@id([modelId, versionNumber])\n @@index([modelId])\n}\n\nmodel ModelVersionTag {\n modelId String\n versionNumber Int\n tagId String\n createdAt DateTime @default(now())\n\n modelVersion ModelVersion @relation(fields: [modelId, versionNumber], references: [modelId, versionNumber], onDelete: Cascade)\n tag Tag @relation(fields: [tagId], references: [id], onDelete: Cascade)\n\n @@id([modelId, versionNumber, tagId])\n @@index([tagId])\n}\n\nmodel ModelAdditionalFile {\n id String @id @default(uuid())\n modelId String\n taggedVersionNumber Int\n fileKey String\n kind ModelFileKind @default(additional)\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n taggedVersion ModelVersion @relation(fields: [modelId, taggedVersionNumber], references: [modelId, versionNumber])\n\n @@index([modelId])\n @@index([modelId, taggedVersionNumber])\n}\n\nmodel Tag {\n id String @id @default(uuid())\n legacyId Int? @unique\n name String @unique\n displayName String?\n createdAt DateTime @default(now())\n\n modelVersions ModelVersionTag[]\n}\n\nmodel ModelAuthor {\n modelId String\n userId String\n role AuthorRole\n // Legacy collaborator_types.name, kept for provenance. Nothing reads it.\n collaboratorType String?\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n}\n\n// Legacy non_member_collaborators joined onto non_member_collaborations: people\n// credited on a model who never held an account. Archival only, no business logic\n// reads this table.\nmodel NonMemberContributor {\n id String @id @default(uuid())\n legacyId Int @unique\n modelId String\n email String?\n name String?\n collaboratorType String?\n addedByUserId String?\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n\n @@index([modelId])\n @@index([email])\n}\n\nmodel ModelPermission {\n id String @id @default(uuid())\n modelId String\n granteeUserId String?\n permissionLevel PermissionLevel\n createdAt DateTime @default(now())\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n granteeUser User? @relation(fields: [granteeUserId], references: [id], onDelete: Cascade)\n\n @@unique([modelId, granteeUserId])\n @@index([modelId])\n @@index([granteeUserId])\n}\n\nmodel ModelLike {\n modelId String\n userId String\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n @@id([modelId, userId])\n @@index([userId])\n @@index([modelId, createdAt])\n}\n\nmodel ModelInteraction {\n id String @id @default(uuid())\n modelId String\n versionNumber Int?\n kind ModelInteractionKind\n userId String?\n sessionId String?\n ipHash String?\n userAgent String?\n referer String?\n geo Json?\n cookie String?\n\n createdAt DateTime @default(now()) @db.Timestamptz(3)\n\n model Model @relation(fields: [modelId], references: [id], onDelete: Cascade)\n user User? @relation(fields: [userId], references: [id], onDelete: SetNull)\n\n @@index([modelId, kind, createdAt])\n @@index([modelId, kind, userId])\n @@index([userId, createdAt])\n @@index([createdAt])\n}\n\nmodel ModelDraft {\n id String @id @default(cuid())\n userId String\n user User @relation(fields: [userId], references: [id], onDelete: Cascade)\n\n modelId String?\n model Model? @relation(fields: [modelId], references: [id], onDelete: Cascade)\n\n schemaVersion Int\n data Json\n\n createdAt DateTime @default(now())\n updatedAt DateTime @updatedAt\n\n @@index([userId])\n @@index([modelId])\n}\n\nmodel Event {\n id String @id @default(uuid())\n type String\n actorId String\n resourceType String\n resourceId String\n payload Json\n createdAt DateTime @default(now())\n processedAt DateTime?\n\n actor User @relation(fields: [actorId], references: [id])\n\n @@index([actorId])\n @@index([resourceType, resourceId])\n @@index([type])\n @@index([processedAt])\n}\n" } -config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"systemRole\",\"kind\":\"enum\",\"type\":\"SystemRole\"},{\"name\":\"userKind\",\"kind\":\"enum\",\"type\":\"UserKind\"},{\"name\":\"isProfilePublic\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"socialLinks\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"dob\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"affiliation\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accounts\",\"kind\":\"object\",\"type\":\"Account\",\"relationName\":\"AccountToUser\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"verifications\",\"kind\":\"object\",\"type\":\"Verification\",\"relationName\":\"UserToVerification\"},{\"name\":\"authoredModels\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelAuthorToUser\"},{\"name\":\"grantedPermissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelPermissionToUser\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToUser\"},{\"name\":\"modelLikes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelLikeToUser\"},{\"name\":\"modelInteractions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelInteractionToUser\"},{\"name\":\"modelDrafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"role\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banned\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"banReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banExpires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"onboardedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passkeys\",\"kind\":\"object\",\"type\":\"Passkey\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Account\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accountId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"providerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scope\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"idToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AccountToUser\"}],\"dbName\":null},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"},{\"name\":\"impersonatedBy\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Verification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"identifier\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToVerification\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Passkey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"publicKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"credentialID\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"counter\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"deviceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"backedUp\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"transports\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"aaguid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Model\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"latestVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentModelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"parentVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"visibility\",\"kind\":\"enum\",\"type\":\"ModelVisibility\"},{\"name\":\"isEndorsed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isLibraryModel\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"viewCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"runCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"downloadCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"shareCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"latestVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"childModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"parentVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ParentVersion\"},{\"name\":\"versions\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersions\"},{\"name\":\"authors\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"additionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"likes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"interactions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"drafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelToModelDraft\"}],\"dbName\":null},\"ModelVersion\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"changeSummary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"previewImageFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoVersion\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"infoTab\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"finalizedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelVersions\"},{\"name\":\"latestOfModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentOfModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ParentVersion\"},{\"name\":\"tags\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"taggedAdditionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"ModelVersionTag\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"tagId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"tag\",\"kind\":\"object\",\"type\":\"Tag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAdditionalFile\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"taggedVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"fileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelFileKind\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"taggedVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"Tag\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersions\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAuthor\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"AuthorRole\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelAuthorToUser\"}],\"dbName\":null},\"ModelPermission\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"granteeUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissionLevel\",\"kind\":\"enum\",\"type\":\"PermissionLevel\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"granteeUser\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelPermissionToUser\"}],\"dbName\":null},\"ModelLike\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelLikeToUser\"}],\"dbName\":null},\"ModelInteraction\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelInteractionKind\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"referer\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"geo\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"cookie\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelInteractionToUser\"}],\"dbName\":null},\"ModelDraft\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelDraft\"},{\"name\":\"schemaVersion\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"actor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventToUser\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") +config.runtimeDataModel = JSON.parse("{\"models\":{\"User\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"emailVerified\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"image\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"systemRole\",\"kind\":\"enum\",\"type\":\"SystemRole\"},{\"name\":\"userKind\",\"kind\":\"enum\",\"type\":\"UserKind\"},{\"name\":\"isProfilePublic\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"bio\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"country\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"socialLinks\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"dob\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"affiliation\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accounts\",\"kind\":\"object\",\"type\":\"Account\",\"relationName\":\"AccountToUser\"},{\"name\":\"sessions\",\"kind\":\"object\",\"type\":\"Session\",\"relationName\":\"SessionToUser\"},{\"name\":\"verifications\",\"kind\":\"object\",\"type\":\"Verification\",\"relationName\":\"UserToVerification\"},{\"name\":\"authoredModels\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelAuthorToUser\"},{\"name\":\"grantedPermissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelPermissionToUser\"},{\"name\":\"events\",\"kind\":\"object\",\"type\":\"Event\",\"relationName\":\"EventToUser\"},{\"name\":\"modelLikes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelLikeToUser\"},{\"name\":\"modelInteractions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelInteractionToUser\"},{\"name\":\"modelDrafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"role\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banned\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"banReason\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"banExpires\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"onboardedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"passkeys\",\"kind\":\"object\",\"type\":\"Passkey\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Account\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accountId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"providerId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"refreshToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"accessTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"refreshTokenExpiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"scope\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"idToken\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"password\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"AccountToUser\"}],\"dbName\":null},\"Session\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"token\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipAddress\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"SessionToUser\"},{\"name\":\"impersonatedBy\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Verification\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"identifier\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"value\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"expiresAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"UserToVerification\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"}],\"dbName\":null},\"Passkey\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"publicKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"credentialID\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"counter\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"deviceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"backedUp\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"transports\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"aaguid\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"PasskeyToUser\"}],\"dbName\":null},\"Model\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"latestVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"parentModelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"parentVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"visibility\",\"kind\":\"enum\",\"type\":\"ModelVisibility\"},{\"name\":\"isEndorsed\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"isLibraryModel\",\"kind\":\"scalar\",\"type\":\"Boolean\"},{\"name\":\"viewCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"runCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"downloadCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"shareCount\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"deletedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"latestVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"childModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelParent\"},{\"name\":\"parentVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ParentVersion\"},{\"name\":\"versions\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersions\"},{\"name\":\"authors\",\"kind\":\"object\",\"type\":\"ModelAuthor\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"nonMemberContributors\",\"kind\":\"object\",\"type\":\"NonMemberContributor\",\"relationName\":\"ModelToNonMemberContributor\"},{\"name\":\"permissions\",\"kind\":\"object\",\"type\":\"ModelPermission\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"additionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"likes\",\"kind\":\"object\",\"type\":\"ModelLike\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"interactions\",\"kind\":\"object\",\"type\":\"ModelInteraction\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"drafts\",\"kind\":\"object\",\"type\":\"ModelDraft\",\"relationName\":\"ModelToModelDraft\"}],\"dbName\":null},\"ModelVersion\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"title\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"description\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"changeSummary\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"previewImageFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoFileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"netlogoVersion\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"infoTab\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"finalizedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelVersions\"},{\"name\":\"latestOfModel\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"LatestVersion\"},{\"name\":\"parentOfModels\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ParentVersion\"},{\"name\":\"tags\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"taggedAdditionalFiles\",\"kind\":\"object\",\"type\":\"ModelAdditionalFile\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"ModelVersionTag\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"tagId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelVersionToModelVersionTag\"},{\"name\":\"tag\",\"kind\":\"object\",\"type\":\"Tag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAdditionalFile\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"taggedVersionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"fileKey\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelFileKind\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAdditionalFile\"},{\"name\":\"taggedVersion\",\"kind\":\"object\",\"type\":\"ModelVersion\",\"relationName\":\"ModelAdditionalFileToModelVersion\"}],\"dbName\":null},\"Tag\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"displayName\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"modelVersions\",\"kind\":\"object\",\"type\":\"ModelVersionTag\",\"relationName\":\"ModelVersionTagToTag\"}],\"dbName\":null},\"ModelAuthor\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"role\",\"kind\":\"enum\",\"type\":\"AuthorRole\"},{\"name\":\"collaboratorType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelAuthor\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelAuthorToUser\"}],\"dbName\":null},\"NonMemberContributor\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"legacyId\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"email\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"name\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"collaboratorType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"addedByUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToNonMemberContributor\"}],\"dbName\":null},\"ModelPermission\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"granteeUserId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"permissionLevel\",\"kind\":\"enum\",\"type\":\"PermissionLevel\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelPermission\"},{\"name\":\"granteeUser\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelPermissionToUser\"}],\"dbName\":null},\"ModelLike\":{\"fields\":[{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelLike\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelLikeToUser\"}],\"dbName\":null},\"ModelInteraction\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"versionNumber\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"kind\",\"kind\":\"enum\",\"type\":\"ModelInteractionKind\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"sessionId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"ipHash\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userAgent\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"referer\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"geo\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"cookie\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelInteraction\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelInteractionToUser\"}],\"dbName\":null},\"ModelDraft\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"userId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"user\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"ModelDraftToUser\"},{\"name\":\"modelId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"model\",\"kind\":\"object\",\"type\":\"Model\",\"relationName\":\"ModelToModelDraft\"},{\"name\":\"schemaVersion\",\"kind\":\"scalar\",\"type\":\"Int\"},{\"name\":\"data\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"updatedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"}],\"dbName\":null},\"Event\":{\"fields\":[{\"name\":\"id\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"type\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"actorId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceType\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"resourceId\",\"kind\":\"scalar\",\"type\":\"String\"},{\"name\":\"payload\",\"kind\":\"scalar\",\"type\":\"Json\"},{\"name\":\"createdAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"processedAt\",\"kind\":\"scalar\",\"type\":\"DateTime\"},{\"name\":\"actor\",\"kind\":\"object\",\"type\":\"User\",\"relationName\":\"EventToUser\"}],\"dbName\":null}},\"enums\":{},\"types\":{}}") defineDmmfProperty(exports.Prisma, config.runtimeDataModel) config.parameterizationSchema = { - strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"accounts\",\"sessions\",\"verifications\",\"model\",\"latestOfModel\",\"parentOfModels\",\"modelVersion\",\"modelVersions\",\"_count\",\"tag\",\"tags\",\"taggedVersion\",\"taggedAdditionalFiles\",\"latestVersion\",\"parentModel\",\"childModels\",\"parentVersion\",\"versions\",\"authors\",\"granteeUser\",\"permissions\",\"additionalFiles\",\"likes\",\"interactions\",\"drafts\",\"authoredModels\",\"grantedPermissions\",\"actor\",\"events\",\"modelLikes\",\"modelInteractions\",\"modelDrafts\",\"passkeys\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Account.findUnique\",\"Account.findUniqueOrThrow\",\"Account.findFirst\",\"Account.findFirstOrThrow\",\"Account.findMany\",\"Account.createOne\",\"Account.createMany\",\"Account.createManyAndReturn\",\"Account.updateOne\",\"Account.updateMany\",\"Account.updateManyAndReturn\",\"Account.upsertOne\",\"Account.deleteOne\",\"Account.deleteMany\",\"Account.groupBy\",\"Account.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Verification.findUnique\",\"Verification.findUniqueOrThrow\",\"Verification.findFirst\",\"Verification.findFirstOrThrow\",\"Verification.findMany\",\"Verification.createOne\",\"Verification.createMany\",\"Verification.createManyAndReturn\",\"Verification.updateOne\",\"Verification.updateMany\",\"Verification.updateManyAndReturn\",\"Verification.upsertOne\",\"Verification.deleteOne\",\"Verification.deleteMany\",\"Verification.groupBy\",\"Verification.aggregate\",\"Passkey.findUnique\",\"Passkey.findUniqueOrThrow\",\"Passkey.findFirst\",\"Passkey.findFirstOrThrow\",\"Passkey.findMany\",\"Passkey.createOne\",\"Passkey.createMany\",\"Passkey.createManyAndReturn\",\"Passkey.updateOne\",\"Passkey.updateMany\",\"Passkey.updateManyAndReturn\",\"Passkey.upsertOne\",\"Passkey.deleteOne\",\"Passkey.deleteMany\",\"Passkey.groupBy\",\"Passkey.aggregate\",\"Model.findUnique\",\"Model.findUniqueOrThrow\",\"Model.findFirst\",\"Model.findFirstOrThrow\",\"Model.findMany\",\"Model.createOne\",\"Model.createMany\",\"Model.createManyAndReturn\",\"Model.updateOne\",\"Model.updateMany\",\"Model.updateManyAndReturn\",\"Model.upsertOne\",\"Model.deleteOne\",\"Model.deleteMany\",\"Model.groupBy\",\"Model.aggregate\",\"ModelVersion.findUnique\",\"ModelVersion.findUniqueOrThrow\",\"ModelVersion.findFirst\",\"ModelVersion.findFirstOrThrow\",\"ModelVersion.findMany\",\"ModelVersion.createOne\",\"ModelVersion.createMany\",\"ModelVersion.createManyAndReturn\",\"ModelVersion.updateOne\",\"ModelVersion.updateMany\",\"ModelVersion.updateManyAndReturn\",\"ModelVersion.upsertOne\",\"ModelVersion.deleteOne\",\"ModelVersion.deleteMany\",\"ModelVersion.groupBy\",\"ModelVersion.aggregate\",\"ModelVersionTag.findUnique\",\"ModelVersionTag.findUniqueOrThrow\",\"ModelVersionTag.findFirst\",\"ModelVersionTag.findFirstOrThrow\",\"ModelVersionTag.findMany\",\"ModelVersionTag.createOne\",\"ModelVersionTag.createMany\",\"ModelVersionTag.createManyAndReturn\",\"ModelVersionTag.updateOne\",\"ModelVersionTag.updateMany\",\"ModelVersionTag.updateManyAndReturn\",\"ModelVersionTag.upsertOne\",\"ModelVersionTag.deleteOne\",\"ModelVersionTag.deleteMany\",\"ModelVersionTag.groupBy\",\"ModelVersionTag.aggregate\",\"ModelAdditionalFile.findUnique\",\"ModelAdditionalFile.findUniqueOrThrow\",\"ModelAdditionalFile.findFirst\",\"ModelAdditionalFile.findFirstOrThrow\",\"ModelAdditionalFile.findMany\",\"ModelAdditionalFile.createOne\",\"ModelAdditionalFile.createMany\",\"ModelAdditionalFile.createManyAndReturn\",\"ModelAdditionalFile.updateOne\",\"ModelAdditionalFile.updateMany\",\"ModelAdditionalFile.updateManyAndReturn\",\"ModelAdditionalFile.upsertOne\",\"ModelAdditionalFile.deleteOne\",\"ModelAdditionalFile.deleteMany\",\"ModelAdditionalFile.groupBy\",\"ModelAdditionalFile.aggregate\",\"Tag.findUnique\",\"Tag.findUniqueOrThrow\",\"Tag.findFirst\",\"Tag.findFirstOrThrow\",\"Tag.findMany\",\"Tag.createOne\",\"Tag.createMany\",\"Tag.createManyAndReturn\",\"Tag.updateOne\",\"Tag.updateMany\",\"Tag.updateManyAndReturn\",\"Tag.upsertOne\",\"Tag.deleteOne\",\"Tag.deleteMany\",\"Tag.groupBy\",\"Tag.aggregate\",\"ModelAuthor.findUnique\",\"ModelAuthor.findUniqueOrThrow\",\"ModelAuthor.findFirst\",\"ModelAuthor.findFirstOrThrow\",\"ModelAuthor.findMany\",\"ModelAuthor.createOne\",\"ModelAuthor.createMany\",\"ModelAuthor.createManyAndReturn\",\"ModelAuthor.updateOne\",\"ModelAuthor.updateMany\",\"ModelAuthor.updateManyAndReturn\",\"ModelAuthor.upsertOne\",\"ModelAuthor.deleteOne\",\"ModelAuthor.deleteMany\",\"ModelAuthor.groupBy\",\"ModelAuthor.aggregate\",\"ModelPermission.findUnique\",\"ModelPermission.findUniqueOrThrow\",\"ModelPermission.findFirst\",\"ModelPermission.findFirstOrThrow\",\"ModelPermission.findMany\",\"ModelPermission.createOne\",\"ModelPermission.createMany\",\"ModelPermission.createManyAndReturn\",\"ModelPermission.updateOne\",\"ModelPermission.updateMany\",\"ModelPermission.updateManyAndReturn\",\"ModelPermission.upsertOne\",\"ModelPermission.deleteOne\",\"ModelPermission.deleteMany\",\"ModelPermission.groupBy\",\"ModelPermission.aggregate\",\"ModelLike.findUnique\",\"ModelLike.findUniqueOrThrow\",\"ModelLike.findFirst\",\"ModelLike.findFirstOrThrow\",\"ModelLike.findMany\",\"ModelLike.createOne\",\"ModelLike.createMany\",\"ModelLike.createManyAndReturn\",\"ModelLike.updateOne\",\"ModelLike.updateMany\",\"ModelLike.updateManyAndReturn\",\"ModelLike.upsertOne\",\"ModelLike.deleteOne\",\"ModelLike.deleteMany\",\"ModelLike.groupBy\",\"ModelLike.aggregate\",\"ModelInteraction.findUnique\",\"ModelInteraction.findUniqueOrThrow\",\"ModelInteraction.findFirst\",\"ModelInteraction.findFirstOrThrow\",\"ModelInteraction.findMany\",\"ModelInteraction.createOne\",\"ModelInteraction.createMany\",\"ModelInteraction.createManyAndReturn\",\"ModelInteraction.updateOne\",\"ModelInteraction.updateMany\",\"ModelInteraction.updateManyAndReturn\",\"ModelInteraction.upsertOne\",\"ModelInteraction.deleteOne\",\"ModelInteraction.deleteMany\",\"ModelInteraction.groupBy\",\"ModelInteraction.aggregate\",\"ModelDraft.findUnique\",\"ModelDraft.findUniqueOrThrow\",\"ModelDraft.findFirst\",\"ModelDraft.findFirstOrThrow\",\"ModelDraft.findMany\",\"ModelDraft.createOne\",\"ModelDraft.createMany\",\"ModelDraft.createManyAndReturn\",\"ModelDraft.updateOne\",\"ModelDraft.updateMany\",\"ModelDraft.updateManyAndReturn\",\"ModelDraft.upsertOne\",\"ModelDraft.deleteOne\",\"ModelDraft.deleteMany\",\"ModelDraft.groupBy\",\"ModelDraft.aggregate\",\"Event.findUnique\",\"Event.findUniqueOrThrow\",\"Event.findFirst\",\"Event.findFirstOrThrow\",\"Event.findMany\",\"Event.createOne\",\"Event.createMany\",\"Event.createManyAndReturn\",\"Event.updateOne\",\"Event.updateMany\",\"Event.updateManyAndReturn\",\"Event.upsertOne\",\"Event.deleteOne\",\"Event.deleteMany\",\"Event.groupBy\",\"Event.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"type\",\"actorId\",\"resourceType\",\"resourceId\",\"payload\",\"createdAt\",\"processedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"contains\",\"startsWith\",\"endsWith\",\"userId\",\"modelId\",\"schemaVersion\",\"updatedAt\",\"versionNumber\",\"ModelInteractionKind\",\"kind\",\"sessionId\",\"ipHash\",\"userAgent\",\"referer\",\"geo\",\"cookie\",\"granteeUserId\",\"PermissionLevel\",\"permissionLevel\",\"AuthorRole\",\"role\",\"legacyId\",\"name\",\"displayName\",\"every\",\"some\",\"none\",\"taggedVersionNumber\",\"fileKey\",\"ModelFileKind\",\"tagId\",\"title\",\"description\",\"changeSummary\",\"previewImageFileKey\",\"netlogoFileKey\",\"netlogoVersion\",\"infoTab\",\"finalizedAt\",\"latestVersionNumber\",\"parentModelId\",\"parentVersionNumber\",\"ModelVisibility\",\"visibility\",\"isEndorsed\",\"isLibraryModel\",\"viewCount\",\"runCount\",\"downloadCount\",\"shareCount\",\"deletedAt\",\"publicKey\",\"credentialID\",\"counter\",\"deviceType\",\"backedUp\",\"transports\",\"aaguid\",\"identifier\",\"value\",\"expiresAt\",\"token\",\"ipAddress\",\"impersonatedBy\",\"accountId\",\"providerId\",\"accessToken\",\"refreshToken\",\"accessTokenExpiresAt\",\"refreshTokenExpiresAt\",\"scope\",\"idToken\",\"password\",\"email\",\"emailVerified\",\"image\",\"SystemRole\",\"systemRole\",\"UserKind\",\"userKind\",\"isProfilePublic\",\"bio\",\"country\",\"socialLinks\",\"dob\",\"affiliation\",\"banned\",\"banReason\",\"banExpires\",\"onboardedAt\",\"modelId_userId\",\"modelId_granteeUserId\",\"modelId_versionNumber\",\"modelId_versionNumber_tagId\",\"id_latestVersionNumber\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), - graph: "jwmXAYACIwQAAMoEACAFAADLBAAgBgAAzAQAIB0AAL4EACAeAAC_BAAgIAAAzQQAICEAAMAEACAiAADBBAAgIwAAwgQAICQAAM4EACCtAgAAxgQAMK4CAAAPABCvAgAAxgQAMLACAQAAAAG2AkAA_wMAIcwCQAD_AwAh2gIBAP4DACHbAgIAAAAB3AIBAP4DACH4AkAAnwQAIY8DAQAAAAGQAyAAngQAIZEDAQD-AwAhkwMAAMcEkwMilQMAAMgElQMilgMgAJ4EACGXAwEA_gMAIZgDAQD-AwAhmQMAAKcEACCaA0AAnwQAIZsDAQD-AwAhnAMgAMkEACGdAwEA_gMAIZ4DQACfBAAhnwNAAJ8EACEBAAAAAQAgEQMAAKAEACCtAgAA0QQAMK4CAAADABCvAgAA0QQAMLACAQD8AwAhtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAhhgMBAPwDACGHAwEA_AMAIYgDAQD-AwAhiQMBAP4DACGKA0AAnwQAIYsDQACfBAAhjAMBAP4DACGNAwEA_gMAIY4DAQD-AwAhCAMAAIAIACCIAwAA0gQAIIkDAADSBAAgigMAANIEACCLAwAA0gQAIIwDAADSBAAgjQMAANIEACCOAwAA0gQAIBEDAACgBAAgrQIAANEEADCuAgAAAwAQrwIAANEEADCwAgEAAAABtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAhhgMBAPwDACGHAwEA_AMAIYgDAQD-AwAhiQMBAP4DACGKA0AAnwQAIYsDQACfBAAhjAMBAP4DACGNAwEA_gMAIY4DAQD-AwAhAwAAAAMAIAEAAAQAMAIAAAUAIA0DAACgBAAgrQIAANAEADCuAgAABwAQrwIAANAEADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIdICAQD-AwAhggNAAP8DACGDAwEA_AMAIYQDAQD-AwAhhQMBAP4DACEEAwAAgAgAINICAADSBAAghAMAANIEACCFAwAA0gQAIA0DAACgBAAgrQIAANAEADCuAgAABwAQrwIAANAEADCwAgEAAAABtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAh0gIBAP4DACGCA0AA_wMAIYMDAQAAAAGEAwEA_gMAIYUDAQD-AwAhAwAAAAcAIAEAAAgAMAIAAAkAIAsDAACpBAAgrQIAAM8EADCuAgAACwAQrwIAAM8EADCwAgEA_AMAIbYCQACfBAAhyQIBAP4DACHMAkAAnwQAIYADAQD8AwAhgQMBAPwDACGCA0AA_wMAIQQDAACACAAgtgIAANIEACDJAgAA0gQAIMwCAADSBAAgCwMAAKkEACCtAgAAzwQAMK4CAAALABCvAgAAzwQAMLACAQAAAAG2AkAAnwQAIckCAQD-AwAhzAJAAJ8EACGAAwEA_AMAIYEDAQD8AwAhggNAAP8DACEDAAAACwAgAQAADAAwAgAADQAgIwQAAMoEACAFAADLBAAgBgAAzAQAIB0AAL4EACAeAAC_BAAgIAAAzQQAICEAAMAEACAiAADBBAAgIwAAwgQAICQAAM4EACCtAgAAxgQAMK4CAAAPABCvAgAAxgQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdoCAQD-AwAh2wICAP0DACHcAgEA_gMAIfgCQACfBAAhjwMBAP4DACGQAyAAngQAIZEDAQD-AwAhkwMAAMcEkwMilQMAAMgElQMilgMgAJ4EACGXAwEA_gMAIZgDAQD-AwAhmQMAAKcEACCaA0AAnwQAIZsDAQD-AwAhnAMgAMkEACGdAwEA_gMAIZ4DQACfBAAhnwNAAJ8EACEBAAAADwAgCQMAAKAEACAHAACoBAAgrQIAAMQEADCuAgAAEQAQrwIAAMQEADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACHaAgAAxQTaAiICAwAAgAgAIAcAAIEIACAKAwAAoAQAIAcAAKgEACCtAgAAxAQAMK4CAAARABCvAgAAxAQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIdoCAADFBNoCIqADAADDBAAgAwAAABEAIAEAABIAMAIAABMAIBMHAACoBAAgCAAApAQAIAkAALEEACAOAACABAAgEAAAsgQAIK0CAACwBAAwrgIAABUAEK8CAACwBAAwtgJAAP8DACHKAgEA_AMAIc0CAgCdBAAh5QIBAPwDACHmAgEA_gMAIecCAQD-AwAh6AIBAP4DACHpAgEA_AMAIeoCAQD-AwAh6wIBAP4DACHsAkAAnwQAIQEAAAAVACAdEQAAvAQAIBIAAKQEACATAACxBAAgFAAAvAQAIBUAAL0EACAWAAC-BAAgGAAAvwQAIBkAALIEACAaAADABAAgGwAAwQQAIBwAAMIEACCtAgAAugQAMK4CAAAXABCvAgAAugQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdsCAgD9AwAh7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACEBAAAAFwAgEBEAAIQIACASAACBCAAgEwAAgggAIBQAAIQIACAVAACGCAAgFgAA-QcAIBgAAPoHACAZAACDCAAgGgAA_AcAIBsAAP0HACAcAAD-BwAg2wIAANIEACDtAgAA0gQAIO4CAADSBAAg7wIAANIEACD4AgAA0gQAIB4RAAC8BAAgEgAApAQAIBMAALEEACAUAAC8BAAgFQAAvQQAIBYAAL4EACAYAAC_BAAgGQAAsgQAIBoAAMAEACAbAADBBAAgHAAAwgQAIK0CAAC6BAAwrgIAABcAEK8CAAC6BAAwsAIBAAAAAbYCQAD_AwAhzAJAAP8DACHbAgIAAAAB7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACGkAwAAuQQAIAMAAAAXACABAAAZADACAAAaACAJCgAAtQQAIA0AALgEACCtAgAAtwQAMK4CAAAcABCvAgAAtwQAMLYCQAD_AwAhygIBAPwDACHNAgIAnQQAIeQCAQD8AwAhAgoAAIQIACANAACFCAAgCgoAALUEACANAAC4BAAgrQIAALcEADCuAgAAHAAQrwIAALcEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHkAgEA_AMAIaMDAAC2BAAgAwAAABwAIAEAAB0AMAIAAB4AIAMAAAAcACABAAAdADACAAAeACABAAAAHAAgCwcAAKgEACAPAAC1BAAgrQIAALMEADCuAgAAIgAQrwIAALMEADCwAgEA_AMAIbYCQAD_AwAhygIBAPwDACHPAgAAtATkAiLhAgIAnQQAIeICAQD8AwAhAgcAAIEIACAPAACECAAgCwcAAKgEACAPAAC1BAAgrQIAALMEADCuAgAAIgAQrwIAALMEADCwAgEAAAABtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACEDAAAAIgAgAQAAIwAwAgAAJAAgAQAAABcAIAEAAAAcACABAAAAIgAgAQAAABcAIAMAAAAXACABAAAZADACAAAaACABAAAAFQAgCwcAAIEIACAIAACBCAAgCQAAgggAIA4AAJ0FACAQAACDCAAg5gIAANIEACDnAgAA0gQAIOgCAADSBAAg6gIAANIEACDrAgAA0gQAIOwCAADSBAAgFAcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhogMAAK8EACADAAAAFQAgAQAALAAwAgAALQAgAwAAABEAIAEAABIAMAIAABMAIAoHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIDBwAAgQgAIBcAAIAIACDWAgAA0gQAIAsHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAAAAAbYCQAD_AwAhygIBAPwDACHWAgEA_gMAIdgCAACuBNgCIqEDAACsBAAgAwAAADAAIAEAADEAMAIAADIAIAEAAAAPACADAAAAIgAgAQAAIwAwAgAAJAAgCAMAAKAEACAHAACoBAAgrQIAAKsEADCuAgAANgAQrwIAAKsEADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACECAwAAgAgAIAcAAIEIACAJAwAAoAQAIAcAAKgEACCtAgAAqwQAMK4CAAA2ABCvAgAAqwQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIaADAACqBAAgAwAAADYAIAEAADcAMAIAADgAIBEDAACpBAAgBwAAqAQAIK0CAAClBAAwrgIAADoAEK8CAAClBAAwsAIBAPwDACG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQoDAACACAAgBwAAgQgAIMkCAADSBAAgzQIAANIEACDQAgAA0gQAINECAADSBAAg0gIAANIEACDTAgAA0gQAINQCAADSBAAg1QIAANIEACARAwAAqQQAIAcAAKgEACCtAgAApQQAMK4CAAA6ABCvAgAApQQAMLACAQAAAAG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQMAAAA6ACABAAA7ADACAAA8ACABAAAADwAgDAMAAKAEACAHAACkBAAgKgAAogQAIK0CAACjBAAwrgIAAD8AEK8CAACjBAAwsAIBAPwDACG2AkAA_wMAIckCAQD8AwAhygIBAP4DACHLAgIAnQQAIcwCQAD_AwAhAwMAAIAIACAHAACBCAAgygIAANIEACAMAwAAoAQAIAcAAKQEACAqAACiBAAgrQIAAKMEADCuAgAAPwAQrwIAAKMEADCwAgEAAAABtgJAAP8DACHJAgEA_AMAIcoCAQD-AwAhywICAJ0EACHMAkAA_wMAIQMAAAA_ACABAABAADACAABBACABAAAAFwAgAQAAABcAIAEAAAAVACABAAAAEQAgAQAAADAAIAEAAAAiACABAAAANgAgAQAAADoAIAEAAAA_ACADAAAAMAAgAQAAMQAwAgAAMgAgDB8AAKAEACCtAgAAoQQAMK4CAABNABCvAgAAoQQAMLACAQD8AwAhsQIBAPwDACGyAgEA_AMAIbMCAQD8AwAhtAIBAPwDACG1AgAAogQAILYCQAD_AwAhtwJAAJ8EACECHwAAgAgAILcCAADSBAAgDB8AAKAEACCtAgAAoQQAMK4CAABNABCvAgAAoQQAMLACAQAAAAGxAgEA_AMAIbICAQD8AwAhswIBAPwDACG0AgEA_AMAIbUCAACiBAAgtgJAAP8DACG3AkAAnwQAIQMAAABNACABAABOADACAABPACADAAAANgAgAQAANwAwAgAAOAAgAwAAADoAIAEAADsAMAIAADwAIAMAAAA_ACABAABAADACAABBACAPAwAAoAQAIK0CAACcBAAwrgIAAFQAEK8CAACcBAAwsAIBAPwDACG2AkAAnwQAIckCAQD8AwAh3AIBAP4DACH5AgEA_AMAIfoCAQD8AwAh-wICAJ0EACH8AgEA_AMAIf0CIACeBAAh_gIBAP4DACH_AgEA_gMAIQUDAACACAAgtgIAANIEACDcAgAA0gQAIP4CAADSBAAg_wIAANIEACAPAwAAoAQAIK0CAACcBAAwrgIAAFQAEK8CAACcBAAwsAIBAAAAAbYCQACfBAAhyQIBAPwDACHcAgEA_gMAIfkCAQD8AwAh-gIBAPwDACH7AgIAnQQAIfwCAQD8AwAh_QIgAJ4EACH-AgEA_gMAIf8CAQD-AwAhAwAAAFQAIAEAAFUAMAIAAFYAIAEAAAADACABAAAABwAgAQAAAAsAIAEAAAARACABAAAAMAAgAQAAAE0AIAEAAAA2ACABAAAAOgAgAQAAAD8AIAEAAABUACABAAAAAQAgGQQAAPYHACAFAAD3BwAgBgAA-AcAIB0AAPkHACAeAAD6BwAgIAAA-wcAICEAAPwHACAiAAD9BwAgIwAA_gcAICQAAP8HACDaAgAA0gQAINsCAADSBAAg3AIAANIEACD4AgAA0gQAII8DAADSBAAgkQMAANIEACCXAwAA0gQAIJgDAADSBAAgmQMAANIEACCaAwAA0gQAIJsDAADSBAAgnAMAANIEACCdAwAA0gQAIJ4DAADSBAAgnwMAANIEACADAAAADwAgAQAAYwAwAgAAAQAgAwAAAA8AIAEAAGMAMAIAAAEAIAMAAAAPACABAABjADACAAABACAgBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAgAADxBwAgIQAA8gcAICIAAPMHACAjAAD0BwAgJAAA9QcAILACAQAAAAG2AkAAAAABzAJAAAAAAdoCAQAAAAHbAgIAAAAB3AIBAAAAAfgCQAAAAAGPAwEAAAABkAMgAAAAAZEDAQAAAAGTAwAAAJMDApUDAAAAlQMClgMgAAAAAZcDAQAAAAGYAwEAAAABmQOAAAAAAZoDQAAAAAGbAwEAAAABnAMgAAAAAZ0DAQAAAAGeA0AAAAABnwNAAAAAAQEqAABnACAWsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABASoAAGkAMAEqAABpADAgBAAA-QYAIAUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQIAAAABACAqAABsACAWsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhAgAAAA8AICoAAG4AIAIAAAAPACAqAABuACADAAAAAQAgMQAAZwAgMgAAbAAgAQAAAAEAIAEAAAAPACAUDAAA8QYAIDcAAPIGACA4AAD1BgAgOQAA9AYAIDoAAPMGACDaAgAA0gQAINsCAADSBAAg3AIAANIEACD4AgAA0gQAII8DAADSBAAgkQMAANIEACCXAwAA0gQAIJgDAADSBAAgmQMAANIEACCaAwAA0gQAIJsDAADSBAAgnAMAANIEACCdAwAA0gQAIJ4DAADSBAAgnwMAANIEACAZrQIAAJIEADCuAgAAdQAQrwIAAJIEADCwAgEA1AMAIbYCQADWAwAhzAJAANYDACHaAgEA4gMAIdsCAgDpAwAh3AIBAOIDACH4AkAA1wMAIY8DAQDiAwAhkAMgAIkEACGRAwEA4gMAIZMDAACTBJMDIpUDAACUBJUDIpYDIACJBAAhlwMBAOIDACGYAwEA4gMAIZkDAADrAwAgmgNAANcDACGbAwEA4gMAIZwDIACVBAAhnQMBAOIDACGeA0AA1wMAIZ8DQADXAwAhAwAAAA8AIAEAAHQAMDYAAHUAIAMAAAAPACABAABjADACAAABACABAAAABQAgAQAAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIA4DAADwBgAgsAIBAAAAAbYCQAAAAAHJAgEAAAABzAJAAAAAAYYDAQAAAAGHAwEAAAABiAMBAAAAAYkDAQAAAAGKA0AAAAABiwNAAAAAAYwDAQAAAAGNAwEAAAABjgMBAAAAAQEqAAB9ACANsAIBAAAAAbYCQAAAAAHJAgEAAAABzAJAAAAAAYYDAQAAAAGHAwEAAAABiAMBAAAAAYkDAQAAAAGKA0AAAAABiwNAAAAAAYwDAQAAAAGNAwEAAAABjgMBAAAAAQEqAAB_ADABKgAAfwAwDgMAAO8GACCwAgEA1gQAIbYCQADXBAAhyQIBANYEACHMAkAA1wQAIYYDAQDWBAAhhwMBANYEACGIAwEA4QQAIYkDAQDhBAAhigNAANgEACGLA0AA2AQAIYwDAQDhBAAhjQMBAOEEACGOAwEA4QQAIQIAAAAFACAqAACCAQAgDbACAQDWBAAhtgJAANcEACHJAgEA1gQAIcwCQADXBAAhhgMBANYEACGHAwEA1gQAIYgDAQDhBAAhiQMBAOEEACGKA0AA2AQAIYsDQADYBAAhjAMBAOEEACGNAwEA4QQAIY4DAQDhBAAhAgAAAAMAICoAAIQBACACAAAAAwAgKgAAhAEAIAMAAAAFACAxAAB9ACAyAACCAQAgAQAAAAUAIAEAAAADACAKDAAA7AYAIDkAAO4GACA6AADtBgAgiAMAANIEACCJAwAA0gQAIIoDAADSBAAgiwMAANIEACCMAwAA0gQAII0DAADSBAAgjgMAANIEACAQrQIAAJEEADCuAgAAiwEAEK8CAACRBAAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhzAJAANYDACGGAwEA1AMAIYcDAQDUAwAhiAMBAOIDACGJAwEA4gMAIYoDQADXAwAhiwNAANcDACGMAwEA4gMAIY0DAQDiAwAhjgMBAOIDACEDAAAAAwAgAQAAigEAMDYAAIsBACADAAAAAwAgAQAABAAwAgAABQAgAQAAAAkAIAEAAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACAKAwAA6wYAILACAQAAAAG2AkAAAAAByQIBAAAAAcwCQAAAAAHSAgEAAAABggNAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAQEqAACTAQAgCbACAQAAAAG2AkAAAAAByQIBAAAAAcwCQAAAAAHSAgEAAAABggNAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAQEqAACVAQAwASoAAJUBADAKAwAA6gYAILACAQDWBAAhtgJAANcEACHJAgEA1gQAIcwCQADXBAAh0gIBAOEEACGCA0AA1wQAIYMDAQDWBAAhhAMBAOEEACGFAwEA4QQAIQIAAAAJACAqAACYAQAgCbACAQDWBAAhtgJAANcEACHJAgEA1gQAIcwCQADXBAAh0gIBAOEEACGCA0AA1wQAIYMDAQDWBAAhhAMBAOEEACGFAwEA4QQAIQIAAAAHACAqAACaAQAgAgAAAAcAICoAAJoBACADAAAACQAgMQAAkwEAIDIAAJgBACABAAAACQAgAQAAAAcAIAYMAADnBgAgOQAA6QYAIDoAAOgGACDSAgAA0gQAIIQDAADSBAAghQMAANIEACAMrQIAAJAEADCuAgAAoQEAEK8CAACQBAAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhzAJAANYDACHSAgEA4gMAIYIDQADWAwAhgwMBANQDACGEAwEA4gMAIYUDAQDiAwAhAwAAAAcAIAEAAKABADA2AAChAQAgAwAAAAcAIAEAAAgAMAIAAAkAIAEAAAANACABAAAADQAgAwAAAAsAIAEAAAwAMAIAAA0AIAMAAAALACABAAAMADACAAANACADAAAACwAgAQAADAAwAgAADQAgCAMAAOYGACCwAgEAAAABtgJAAAAAAckCAQAAAAHMAkAAAAABgAMBAAAAAYEDAQAAAAGCA0AAAAABASoAAKkBACAHsAIBAAAAAbYCQAAAAAHJAgEAAAABzAJAAAAAAYADAQAAAAGBAwEAAAABggNAAAAAAQEqAACrAQAwASoAAKsBADABAAAADwAgCAMAAOUGACCwAgEA1gQAIbYCQADYBAAhyQIBAOEEACHMAkAA2AQAIYADAQDWBAAhgQMBANYEACGCA0AA1wQAIQIAAAANACAqAACvAQAgB7ACAQDWBAAhtgJAANgEACHJAgEA4QQAIcwCQADYBAAhgAMBANYEACGBAwEA1gQAIYIDQADXBAAhAgAAAAsAICoAALEBACACAAAACwAgKgAAsQEAIAEAAAAPACADAAAADQAgMQAAqQEAIDIAAK8BACABAAAADQAgAQAAAAsAIAYMAADiBgAgOQAA5AYAIDoAAOMGACC2AgAA0gQAIMkCAADSBAAgzAIAANIEACAKrQIAAI8EADCuAgAAuQEAEK8CAACPBAAwsAIBANQDACG2AkAA1wMAIckCAQDiAwAhzAJAANcDACGAAwEA1AMAIYEDAQDUAwAhggNAANYDACEDAAAACwAgAQAAuAEAMDYAALkBACADAAAACwAgAQAADAAwAgAADQAgAQAAAFYAIAEAAABWACADAAAAVAAgAQAAVQAwAgAAVgAgAwAAAFQAIAEAAFUAMAIAAFYAIAMAAABUACABAABVADACAABWACAMAwAA4QYAILACAQAAAAG2AkAAAAAByQIBAAAAAdwCAQAAAAH5AgEAAAAB-gIBAAAAAfsCAgAAAAH8AgEAAAAB_QIgAAAAAf4CAQAAAAH_AgEAAAABASoAAMEBACALsAIBAAAAAbYCQAAAAAHJAgEAAAAB3AIBAAAAAfkCAQAAAAH6AgEAAAAB-wICAAAAAfwCAQAAAAH9AiAAAAAB_gIBAAAAAf8CAQAAAAEBKgAAwwEAMAEqAADDAQAwDAMAAOAGACCwAgEA1gQAIbYCQADYBAAhyQIBANYEACHcAgEA4QQAIfkCAQDWBAAh-gIBANYEACH7AgIA4AQAIfwCAQDWBAAh_QIgANkFACH-AgEA4QQAIf8CAQDhBAAhAgAAAFYAICoAAMYBACALsAIBANYEACG2AkAA2AQAIckCAQDWBAAh3AIBAOEEACH5AgEA1gQAIfoCAQDWBAAh-wICAOAEACH8AgEA1gQAIf0CIADZBQAh_gIBAOEEACH_AgEA4QQAIQIAAABUACAqAADIAQAgAgAAAFQAICoAAMgBACADAAAAVgAgMQAAwQEAIDIAAMYBACABAAAAVgAgAQAAAFQAIAkMAADbBgAgNwAA3AYAIDgAAN8GACA5AADeBgAgOgAA3QYAILYCAADSBAAg3AIAANIEACD-AgAA0gQAIP8CAADSBAAgDq0CAACOBAAwrgIAAM8BABCvAgAAjgQAMLACAQDUAwAhtgJAANcDACHJAgEA1AMAIdwCAQDiAwAh-QIBANQDACH6AgEA1AMAIfsCAgDjAwAh_AIBANQDACH9AiAAiQQAIf4CAQDiAwAh_wIBAOIDACEDAAAAVAAgAQAAzgEAMDYAAM8BACADAAAAVAAgAQAAVQAwAgAAVgAgAQAAABoAIAEAAAAaACADAAAAFwAgAQAAGQAwAgAAGgAgAwAAABcAIAEAABkAMAIAABoAIAMAAAAXACABAAAZADACAAAaACAaEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgGwAAxAYAIBwAAMUGACCwAgEAAAABtgJAAAAAAcwCQAAAAAHbAgIAAAAB7QICAAAAAe4CAQAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABASoAANcBACAPsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHuAgEAAAAB7wICAAAAAfECAAAA8QIC8gIgAAAAAfMCIAAAAAH0AgIAAAAB9QICAAAAAfYCAgAAAAH3AgIAAAAB-AJAAAAAAQEqAADZAQAwASoAANkBADABAAAAFQAgAQAAABcAIAEAAAAVACAaEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAIBwAAOQFACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhAgAAABoAICoAAN8BACAPsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIQIAAAAXACAqAADhAQAgAgAAABcAICoAAOEBACABAAAAFQAgAQAAABcAIAEAAAAVACADAAAAGgAgMQAA1wEAIDIAAN8BACABAAAAGgAgAQAAABcAIAoMAADWBgAgNwAA1wYAIDgAANoGACA5AADZBgAgOgAA2AYAINsCAADSBAAg7QIAANIEACDuAgAA0gQAIO8CAADSBAAg-AIAANIEACASrQIAAIcEADCuAgAA6wEAEK8CAACHBAAwsAIBANQDACG2AkAA1gMAIcwCQADWAwAh2wICAOkDACHtAgIA6QMAIe4CAQDiAwAh7wICAOkDACHxAgAAiATxAiLyAiAAiQQAIfMCIACJBAAh9AICAOMDACH1AgIA4wMAIfYCAgDjAwAh9wICAOMDACH4AkAA1wMAIQMAAAAXACABAADqAQAwNgAA6wEAIAMAAAAXACABAAAZADACAAAaACABAAAALQAgAQAAAC0AIAMAAAAVACABAAAsADACAAAtACADAAAAFQAgAQAALAAwAgAALQAgAwAAABUAIAEAACwAMAIAAC0AIBAHAADVBgAgCAAAtgYAIAkAALcGACAOAAC4BgAgEAAAuQYAILYCQAAAAAHKAgEAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABASoAAPMBACALtgJAAAAAAcoCAQAAAAHNAgIAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAekCAQAAAAHqAgEAAAAB6wIBAAAAAewCQAAAAAEBKgAA9QEAMAEqAAD1AQAwEAcAALQFACAIAAC1BQAgCQAAtgUAIA4AALcFACAQAAC4BQAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQIAAAAtACAqAAD4AQAgC7YCQADXBAAhygIBANYEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACECAAAAFQAgKgAA-gEAIAIAAAAVACAqAAD6AQAgAwAAAC0AIDEAAPMBACAyAAD4AQAgAQAAAC0AIAEAAAAVACALDAAArwUAIDcAALAFACA4AACzBQAgOQAAsgUAIDoAALEFACDmAgAA0gQAIOcCAADSBAAg6AIAANIEACDqAgAA0gQAIOsCAADSBAAg7AIAANIEACAOrQIAAIYEADCuAgAAgQIAEK8CAACGBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5QIBANQDACHmAgEA4gMAIecCAQDiAwAh6AIBAOIDACHpAgEA1AMAIeoCAQDiAwAh6wIBAOIDACHsAkAA1wMAIQMAAAAVACABAACAAgAwNgAAgQIAIAMAAAAVACABAAAsADACAAAtACABAAAAHgAgAQAAAB4AIAMAAAAcACABAAAdADACAAAeACADAAAAHAAgAQAAHQAwAgAAHgAgAwAAABwAIAEAAB0AMAIAAB4AIAYKAACbBQAgDQAArgUAILYCQAAAAAHKAgEAAAABzQICAAAAAeQCAQAAAAEBKgAAiQIAIAS2AkAAAAABygIBAAAAAc0CAgAAAAHkAgEAAAABASoAAIsCADABKgAAiwIAMAYKAACZBQAgDQAArQUAILYCQADXBAAhygIBANYEACHNAgIA4AQAIeQCAQDWBAAhAgAAAB4AICoAAI4CACAEtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5AIBANYEACECAAAAHAAgKgAAkAIAIAIAAAAcACAqAACQAgAgAwAAAB4AIDEAAIkCACAyAACOAgAgAQAAAB4AIAEAAAAcACAFDAAAqAUAIDcAAKkFACA4AACsBQAgOQAAqwUAIDoAAKoFACAHrQIAAIUEADCuAgAAlwIAEK8CAACFBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5AIBANQDACEDAAAAHAAgAQAAlgIAMDYAAJcCACADAAAAHAAgAQAAHQAwAgAAHgAgAQAAACQAIAEAAAAkACADAAAAIgAgAQAAIwAwAgAAJAAgAwAAACIAIAEAACMAMAIAACQAIAMAAAAiACABAAAjADACAAAkACAIBwAApgUAIA8AAKcFACCwAgEAAAABtgJAAAAAAcoCAQAAAAHPAgAAAOQCAuECAgAAAAHiAgEAAAABASoAAJ8CACAGsAIBAAAAAbYCQAAAAAHKAgEAAAABzwIAAADkAgLhAgIAAAAB4gIBAAAAAQEqAAChAgAwASoAAKECADAIBwAApAUAIA8AAKUFACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHPAgAAowXkAiLhAgIA4AQAIeICAQDWBAAhAgAAACQAICoAAKQCACAGsAIBANYEACG2AkAA1wQAIcoCAQDWBAAhzwIAAKMF5AIi4QICAOAEACHiAgEA1gQAIQIAAAAiACAqAACmAgAgAgAAACIAICoAAKYCACADAAAAJAAgMQAAnwIAIDIAAKQCACABAAAAJAAgAQAAACIAIAUMAACeBQAgNwAAnwUAIDgAAKIFACA5AAChBQAgOgAAoAUAIAmtAgAAgQQAMK4CAACtAgAQrwIAAIEEADCwAgEA1AMAIbYCQADWAwAhygIBANQDACHPAgAAggTkAiLhAgIA4wMAIeICAQDUAwAhAwAAACIAIAEAAKwCADA2AACtAgAgAwAAACIAIAEAACMAMAIAACQAIAkLAACABAAgrQIAAPsDADCuAgAAswIAEK8CAAD7AwAwsAIBAAAAAbYCQAD_AwAh2wICAAAAAdwCAQAAAAHdAgEA_gMAIQEAAACwAgAgAQAAALACACAJCwAAgAQAIK0CAAD7AwAwrgIAALMCABCvAgAA-wMAMLACAQD8AwAhtgJAAP8DACHbAgIA_QMAIdwCAQD8AwAh3QIBAP4DACEDCwAAnQUAINsCAADSBAAg3QIAANIEACADAAAAswIAIAEAALQCADACAACwAgAgAwAAALMCACABAAC0AgAwAgAAsAIAIAMAAACzAgAgAQAAtAIAMAIAALACACAGCwAAnAUAILACAQAAAAG2AkAAAAAB2wICAAAAAdwCAQAAAAHdAgEAAAABASoAALgCACAFsAIBAAAAAbYCQAAAAAHbAgIAAAAB3AIBAAAAAd0CAQAAAAEBKgAAugIAMAEqAAC6AgAwBgsAAI0FACCwAgEA1gQAIbYCQADXBAAh2wICAOsEACHcAgEA1gQAId0CAQDhBAAhAgAAALACACAqAAC9AgAgBbACAQDWBAAhtgJAANcEACHbAgIA6wQAIdwCAQDWBAAh3QIBAOEEACECAAAAswIAICoAAL8CACACAAAAswIAICoAAL8CACADAAAAsAIAIDEAALgCACAyAAC9AgAgAQAAALACACABAAAAswIAIAcMAACIBQAgNwAAiQUAIDgAAIwFACA5AACLBQAgOgAAigUAINsCAADSBAAg3QIAANIEACAIrQIAAPoDADCuAgAAxgIAEK8CAAD6AwAwsAIBANQDACG2AkAA1gMAIdsCAgDpAwAh3AIBANQDACHdAgEA4gMAIQMAAACzAgAgAQAAxQIAMDYAAMYCACADAAAAswIAIAEAALQCADACAACwAgAgAQAAABMAIAEAAAATACADAAAAEQAgAQAAEgAwAgAAEwAgAwAAABEAIAEAABIAMAIAABMAIAMAAAARACABAAASADACAAATACAGAwAAhwUAIAcAAIYFACC2AkAAAAAByQIBAAAAAcoCAQAAAAHaAgAAANoCAgEqAADOAgAgBLYCQAAAAAHJAgEAAAABygIBAAAAAdoCAAAA2gICASoAANACADABKgAA0AIAMAYDAACFBQAgBwAAhAUAILYCQADXBAAhyQIBANYEACHKAgEA1gQAIdoCAACDBdoCIgIAAAATACAqAADTAgAgBLYCQADXBAAhyQIBANYEACHKAgEA1gQAIdoCAACDBdoCIgIAAAARACAqAADVAgAgAgAAABEAICoAANUCACADAAAAEwAgMQAAzgIAIDIAANMCACABAAAAEwAgAQAAABEAIAMMAACABQAgOQAAggUAIDoAAIEFACAHrQIAAPYDADCuAgAA3AIAEK8CAAD2AwAwtgJAANYDACHJAgEA1AMAIcoCAQDUAwAh2gIAAPcD2gIiAwAAABEAIAEAANsCADA2AADcAgAgAwAAABEAIAEAABIAMAIAABMAIAEAAAAyACABAAAAMgAgAwAAADAAIAEAADEAMAIAADIAIAMAAAAwACABAAAxADACAAAyACADAAAAMAAgAQAAMQAwAgAAMgAgBwcAAP4EACAXAAD_BAAgsAIBAAAAAbYCQAAAAAHKAgEAAAAB1gIBAAAAAdgCAAAA2AICASoAAOQCACAFsAIBAAAAAbYCQAAAAAHKAgEAAAAB1gIBAAAAAdgCAAAA2AICASoAAOYCADABKgAA5gIAMAEAAAAPACAHBwAA_AQAIBcAAP0EACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHWAgEA4QQAIdgCAAD7BNgCIgIAAAAyACAqAADqAgAgBbACAQDWBAAhtgJAANcEACHKAgEA1gQAIdYCAQDhBAAh2AIAAPsE2AIiAgAAADAAICoAAOwCACACAAAAMAAgKgAA7AIAIAEAAAAPACADAAAAMgAgMQAA5AIAIDIAAOoCACABAAAAMgAgAQAAADAAIAQMAAD4BAAgOQAA-gQAIDoAAPkEACDWAgAA0gQAIAitAgAA8gMAMK4CAAD0AgAQrwIAAPIDADCwAgEA1AMAIbYCQADWAwAhygIBANQDACHWAgEA4gMAIdgCAADzA9gCIgMAAAAwACABAADzAgAwNgAA9AIAIAMAAAAwACABAAAxADACAAAyACABAAAAOAAgAQAAADgAIAMAAAA2ACABAAA3ADACAAA4ACADAAAANgAgAQAANwAwAgAAOAAgAwAAADYAIAEAADcAMAIAADgAIAUDAAD3BAAgBwAA9gQAILYCQAAAAAHJAgEAAAABygIBAAAAAQEqAAD8AgAgA7YCQAAAAAHJAgEAAAABygIBAAAAAQEqAAD-AgAwASoAAP4CADAFAwAA9QQAIAcAAPQEACC2AkAA1wQAIckCAQDWBAAhygIBANYEACECAAAAOAAgKgAAgQMAIAO2AkAA1wQAIckCAQDWBAAhygIBANYEACECAAAANgAgKgAAgwMAIAIAAAA2ACAqAACDAwAgAwAAADgAIDEAAPwCACAyAACBAwAgAQAAADgAIAEAAAA2ACADDAAA8QQAIDkAAPMEACA6AADyBAAgBq0CAADxAwAwrgIAAIoDABCvAgAA8QMAMLYCQADWAwAhyQIBANQDACHKAgEA1AMAIQMAAAA2ACABAACJAwAwNgAAigMAIAMAAAA2ACABAAA3ADACAAA4ACABAAAAPAAgAQAAADwAIAMAAAA6ACABAAA7ADACAAA8ACADAAAAOgAgAQAAOwAwAgAAPAAgAwAAADoAIAEAADsAMAIAADwAIA4DAADwBAAgBwAA7wQAILACAQAAAAG2AkAAAAAByQIBAAAAAcoCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEBKgAAkgMAIAywAgEAAAABtgJAAAAAAckCAQAAAAHKAgEAAAABzQICAAAAAc8CAAAAzwIC0AIBAAAAAdECAQAAAAHSAgEAAAAB0wIBAAAAAdQCgAAAAAHVAgEAAAABASoAAJQDADABKgAAlAMAMAEAAAAPACAOAwAA7gQAIAcAAO0EACCwAgEA1gQAIbYCQADXBAAhyQIBAOEEACHKAgEA1gQAIc0CAgDrBAAhzwIAAOwEzwIi0AIBAOEEACHRAgEA4QQAIdICAQDhBAAh0wIBAOEEACHUAoAAAAAB1QIBAOEEACECAAAAPAAgKgAAmAMAIAywAgEA1gQAIbYCQADXBAAhyQIBAOEEACHKAgEA1gQAIc0CAgDrBAAhzwIAAOwEzwIi0AIBAOEEACHRAgEA4QQAIdICAQDhBAAh0wIBAOEEACHUAoAAAAAB1QIBAOEEACECAAAAOgAgKgAAmgMAIAIAAAA6ACAqAACaAwAgAQAAAA8AIAMAAAA8ACAxAACSAwAgMgAAmAMAIAEAAAA8ACABAAAAOgAgDQwAAOYEACA3AADnBAAgOAAA6gQAIDkAAOkEACA6AADoBAAgyQIAANIEACDNAgAA0gQAINACAADSBAAg0QIAANIEACDSAgAA0gQAINMCAADSBAAg1AIAANIEACDVAgAA0gQAIA-tAgAA6AMAMK4CAACiAwAQrwIAAOgDADCwAgEA1AMAIbYCQADWAwAhyQIBAOIDACHKAgEA1AMAIc0CAgDpAwAhzwIAAOoDzwIi0AIBAOIDACHRAgEA4gMAIdICAQDiAwAh0wIBAOIDACHUAgAA6wMAINUCAQDiAwAhAwAAADoAIAEAAKEDADA2AACiAwAgAwAAADoAIAEAADsAMAIAADwAIAEAAABBACABAAAAQQAgAwAAAD8AIAEAAEAAMAIAAEEAIAMAAAA_ACABAABAADACAABBACADAAAAPwAgAQAAQAAwAgAAQQAgCQMAAOQEACAHAADlBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABygIBAAAAAcsCAgAAAAHMAkAAAAABASoAAKoDACAHKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABygIBAAAAAcsCAgAAAAHMAkAAAAABASoAAKwDADABKgAArAMAMAEAAAAXACAJAwAA4gQAIAcAAOMEACAqgAAAAAGwAgEA1gQAIbYCQADXBAAhyQIBANYEACHKAgEA4QQAIcsCAgDgBAAhzAJAANcEACECAAAAQQAgKgAAsAMAIAcqgAAAAAGwAgEA1gQAIbYCQADXBAAhyQIBANYEACHKAgEA4QQAIcsCAgDgBAAhzAJAANcEACECAAAAPwAgKgAAsgMAIAIAAAA_ACAqAACyAwAgAQAAABcAIAMAAABBACAxAACqAwAgMgAAsAMAIAEAAABBACABAAAAPwAgBgwAANsEACA3AADcBAAgOAAA3wQAIDkAAN4EACA6AADdBAAgygIAANIEACAKKgAA1QMAIK0CAADhAwAwrgIAALoDABCvAgAA4QMAMLACAQDUAwAhtgJAANYDACHJAgEA1AMAIcoCAQDiAwAhywICAOMDACHMAkAA1gMAIQMAAAA_ACABAAC5AwAwNgAAugMAIAMAAAA_ACABAABAADACAABBACABAAAATwAgAQAAAE8AIAMAAABNACABAABOADACAABPACADAAAATQAgAQAATgAwAgAATwAgAwAAAE0AIAEAAE4AMAIAAE8AIAkfAADaBAAgsAIBAAAAAbECAQAAAAGyAgEAAAABswIBAAAAAbQCAQAAAAG1AoAAAAABtgJAAAAAAbcCQAAAAAEBKgAAwgMAIAiwAgEAAAABsQIBAAAAAbICAQAAAAGzAgEAAAABtAIBAAAAAbUCgAAAAAG2AkAAAAABtwJAAAAAAQEqAADEAwAwASoAAMQDADAJHwAA2QQAILACAQDWBAAhsQIBANYEACGyAgEA1gQAIbMCAQDWBAAhtAIBANYEACG1AoAAAAABtgJAANcEACG3AkAA2AQAIQIAAABPACAqAADHAwAgCLACAQDWBAAhsQIBANYEACGyAgEA1gQAIbMCAQDWBAAhtAIBANYEACG1AoAAAAABtgJAANcEACG3AkAA2AQAIQIAAABNACAqAADJAwAgAgAAAE0AICoAAMkDACADAAAATwAgMQAAwgMAIDIAAMcDACABAAAATwAgAQAAAE0AIAQMAADTBAAgOQAA1QQAIDoAANQEACC3AgAA0gQAIAutAgAA0wMAMK4CAADQAwAQrwIAANMDADCwAgEA1AMAIbECAQDUAwAhsgIBANQDACGzAgEA1AMAIbQCAQDUAwAhtQIAANUDACC2AkAA1gMAIbcCQADXAwAhAwAAAE0AIAEAAM8DADA2AADQAwAgAwAAAE0AIAEAAE4AMAIAAE8AIAutAgAA0wMAMK4CAADQAwAQrwIAANMDADCwAgEA1AMAIbECAQDUAwAhsgIBANQDACGzAgEA1AMAIbQCAQDUAwAhtQIAANUDACC2AkAA1gMAIbcCQADXAwAhDgwAANwDACA5AADgAwAgOgAA4AMAILgCAQAAAAG5AgEAAAAEugIBAAAABLsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA3wMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQ8MAADcAwAgOQAA3gMAIDoAAN4DACC4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAELDAAA3AMAIDkAAN0DACA6AADdAwAguAJAAAAAAbkCQAAAAAS6AkAAAAAEuwJAAAAAAbwCQAAAAAG9AkAAAAABvgJAAAAAAb8CQADbAwAhCwwAANkDACA5AADaAwAgOgAA2gMAILgCQAAAAAG5AkAAAAAFugJAAAAABbsCQAAAAAG8AkAAAAABvQJAAAAAAb4CQAAAAAG_AkAA2AMAIQsMAADZAwAgOQAA2gMAIDoAANoDACC4AkAAAAABuQJAAAAABboCQAAAAAW7AkAAAAABvAJAAAAAAb0CQAAAAAG-AkAAAAABvwJAANgDACEIuAICAAAAAbkCAgAAAAW6AgIAAAAFuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDZAwAhCLgCQAAAAAG5AkAAAAAFugJAAAAABbsCQAAAAAG8AkAAAAABvQJAAAAAAb4CQAAAAAG_AkAA2gMAIQsMAADcAwAgOQAA3QMAIDoAAN0DACC4AkAAAAABuQJAAAAABLoCQAAAAAS7AkAAAAABvAJAAAAAAb0CQAAAAAG-AkAAAAABvwJAANsDACEIuAICAAAAAbkCAgAAAAS6AgIAAAAEuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDcAwAhCLgCQAAAAAG5AkAAAAAEugJAAAAABLsCQAAAAAG8AkAAAAABvQJAAAAAAb4CQAAAAAG_AkAA3QMAIQy4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAEODAAA3AMAIDkAAOADACA6AADgAwAguAIBAAAAAbkCAQAAAAS6AgEAAAAEuwIBAAAAAbwCAQAAAAG9AgEAAAABvgIBAAAAAb8CAQDfAwAhxgIBAAAAAccCAQAAAAHIAgEAAAABC7gCAQAAAAG5AgEAAAAEugIBAAAABLsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA4AMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQoqAADVAwAgrQIAAOEDADCuAgAAugMAEK8CAADhAwAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhygIBAOIDACHLAgIA4wMAIcwCQADWAwAhDgwAANkDACA5AADnAwAgOgAA5wMAILgCAQAAAAG5AgEAAAAFugIBAAAABbsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA5gMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQ0MAADcAwAgNwAA5QMAIDgAANwDACA5AADcAwAgOgAA3AMAILgCAgAAAAG5AgIAAAAEugICAAAABLsCAgAAAAG8AgIAAAABvQICAAAAAb4CAgAAAAG_AgIA5AMAIQ0MAADcAwAgNwAA5QMAIDgAANwDACA5AADcAwAgOgAA3AMAILgCAgAAAAG5AgIAAAAEugICAAAABLsCAgAAAAG8AgIAAAABvQICAAAAAb4CAgAAAAG_AgIA5AMAIQi4AggAAAABuQIIAAAABLoCCAAAAAS7AggAAAABvAIIAAAAAb0CCAAAAAG-AggAAAABvwIIAOUDACEODAAA2QMAIDkAAOcDACA6AADnAwAguAIBAAAAAbkCAQAAAAW6AgEAAAAFuwIBAAAAAbwCAQAAAAG9AgEAAAABvgIBAAAAAb8CAQDmAwAhxgIBAAAAAccCAQAAAAHIAgEAAAABC7gCAQAAAAG5AgEAAAAFugIBAAAABbsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA5wMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQ-tAgAA6AMAMK4CAACiAwAQrwIAAOgDADCwAgEA1AMAIbYCQADWAwAhyQIBAOIDACHKAgEA1AMAIc0CAgDpAwAhzwIAAOoDzwIi0AIBAOIDACHRAgEA4gMAIdICAQDiAwAh0wIBAOIDACHUAgAA6wMAINUCAQDiAwAhDQwAANkDACA3AADwAwAgOAAA2QMAIDkAANkDACA6AADZAwAguAICAAAAAbkCAgAAAAW6AgIAAAAFuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDvAwAhBwwAANwDACA5AADuAwAgOgAA7gMAILgCAAAAzwICuQIAAADPAgi6AgAAAM8CCL8CAADtA88CIg8MAADZAwAgOQAA7AMAIDoAAOwDACC4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAEMuAKAAAAAAbsCgAAAAAG8AoAAAAABvQKAAAAAAb4CgAAAAAG_AoAAAAABwAIBAAAAAcECAQAAAAHCAgEAAAABwwKAAAAAAcQCgAAAAAHFAoAAAAABBwwAANwDACA5AADuAwAgOgAA7gMAILgCAAAAzwICuQIAAADPAgi6AgAAAM8CCL8CAADtA88CIgS4AgAAAM8CArkCAAAAzwIIugIAAADPAgi_AgAA7gPPAiINDAAA2QMAIDcAAPADACA4AADZAwAgOQAA2QMAIDoAANkDACC4AgIAAAABuQICAAAABboCAgAAAAW7AgIAAAABvAICAAAAAb0CAgAAAAG-AgIAAAABvwICAO8DACEIuAIIAAAAAbkCCAAAAAW6AggAAAAFuwIIAAAAAbwCCAAAAAG9AggAAAABvgIIAAAAAb8CCADwAwAhBq0CAADxAwAwrgIAAIoDABCvAgAA8QMAMLYCQADWAwAhyQIBANQDACHKAgEA1AMAIQitAgAA8gMAMK4CAAD0AgAQrwIAAPIDADCwAgEA1AMAIbYCQADWAwAhygIBANQDACHWAgEA4gMAIdgCAADzA9gCIgcMAADcAwAgOQAA9QMAIDoAAPUDACC4AgAAANgCArkCAAAA2AIIugIAAADYAgi_AgAA9APYAiIHDAAA3AMAIDkAAPUDACA6AAD1AwAguAIAAADYAgK5AgAAANgCCLoCAAAA2AIIvwIAAPQD2AIiBLgCAAAA2AICuQIAAADYAgi6AgAAANgCCL8CAAD1A9gCIgetAgAA9gMAMK4CAADcAgAQrwIAAPYDADC2AkAA1gMAIckCAQDUAwAhygIBANQDACHaAgAA9wPaAiIHDAAA3AMAIDkAAPkDACA6AAD5AwAguAIAAADaAgK5AgAAANoCCLoCAAAA2gIIvwIAAPgD2gIiBwwAANwDACA5AAD5AwAgOgAA-QMAILgCAAAA2gICuQIAAADaAgi6AgAAANoCCL8CAAD4A9oCIgS4AgAAANoCArkCAAAA2gIIugIAAADaAgi_AgAA-QPaAiIIrQIAAPoDADCuAgAAxgIAEK8CAAD6AwAwsAIBANQDACG2AkAA1gMAIdsCAgDpAwAh3AIBANQDACHdAgEA4gMAIQkLAACABAAgrQIAAPsDADCuAgAAswIAEK8CAAD7AwAwsAIBAPwDACG2AkAA_wMAIdsCAgD9AwAh3AIBAPwDACHdAgEA_gMAIQu4AgEAAAABuQIBAAAABLoCAQAAAAS7AgEAAAABvAIBAAAAAb0CAQAAAAG-AgEAAAABvwIBAOADACHGAgEAAAABxwIBAAAAAcgCAQAAAAEIuAICAAAAAbkCAgAAAAW6AgIAAAAFuwICAAAAAbwCAgAAAAG9AgIAAAABvgICAAAAAb8CAgDZAwAhC7gCAQAAAAG5AgEAAAAFugIBAAAABbsCAQAAAAG8AgEAAAABvQIBAAAAAb4CAQAAAAG_AgEA5wMAIcYCAQAAAAHHAgEAAAAByAIBAAAAAQi4AkAAAAABuQJAAAAABLoCQAAAAAS7AkAAAAABvAJAAAAAAb0CQAAAAAG-AkAAAAABvwJAAN0DACED3gIAABwAIN8CAAAcACDgAgAAHAAgCa0CAACBBAAwrgIAAK0CABCvAgAAgQQAMLACAQDUAwAhtgJAANYDACHKAgEA1AMAIc8CAACCBOQCIuECAgDjAwAh4gIBANQDACEHDAAA3AMAIDkAAIQEACA6AACEBAAguAIAAADkAgK5AgAAAOQCCLoCAAAA5AIIvwIAAIME5AIiBwwAANwDACA5AACEBAAgOgAAhAQAILgCAAAA5AICuQIAAADkAgi6AgAAAOQCCL8CAACDBOQCIgS4AgAAAOQCArkCAAAA5AIIugIAAADkAgi_AgAAhATkAiIHrQIAAIUEADCuAgAAlwIAEK8CAACFBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5AIBANQDACEOrQIAAIYEADCuAgAAgQIAEK8CAACGBAAwtgJAANYDACHKAgEA1AMAIc0CAgDjAwAh5QIBANQDACHmAgEA4gMAIecCAQDiAwAh6AIBAOIDACHpAgEA1AMAIeoCAQDiAwAh6wIBAOIDACHsAkAA1wMAIRKtAgAAhwQAMK4CAADrAQAQrwIAAIcEADCwAgEA1AMAIbYCQADWAwAhzAJAANYDACHbAgIA6QMAIe0CAgDpAwAh7gIBAOIDACHvAgIA6QMAIfECAACIBPECIvICIACJBAAh8wIgAIkEACH0AgIA4wMAIfUCAgDjAwAh9gICAOMDACH3AgIA4wMAIfgCQADXAwAhBwwAANwDACA5AACNBAAgOgAAjQQAILgCAAAA8QICuQIAAADxAgi6AgAAAPECCL8CAACMBPECIgUMAADcAwAgOQAAiwQAIDoAAIsEACC4AiAAAAABvwIgAIoEACEFDAAA3AMAIDkAAIsEACA6AACLBAAguAIgAAAAAb8CIACKBAAhArgCIAAAAAG_AiAAiwQAIQcMAADcAwAgOQAAjQQAIDoAAI0EACC4AgAAAPECArkCAAAA8QIIugIAAADxAgi_AgAAjATxAiIEuAIAAADxAgK5AgAAAPECCLoCAAAA8QIIvwIAAI0E8QIiDq0CAACOBAAwrgIAAM8BABCvAgAAjgQAMLACAQDUAwAhtgJAANcDACHJAgEA1AMAIdwCAQDiAwAh-QIBANQDACH6AgEA1AMAIfsCAgDjAwAh_AIBANQDACH9AiAAiQQAIf4CAQDiAwAh_wIBAOIDACEKrQIAAI8EADCuAgAAuQEAEK8CAACPBAAwsAIBANQDACG2AkAA1wMAIckCAQDiAwAhzAJAANcDACGAAwEA1AMAIYEDAQDUAwAhggNAANYDACEMrQIAAJAEADCuAgAAoQEAEK8CAACQBAAwsAIBANQDACG2AkAA1gMAIckCAQDUAwAhzAJAANYDACHSAgEA4gMAIYIDQADWAwAhgwMBANQDACGEAwEA4gMAIYUDAQDiAwAhEK0CAACRBAAwrgIAAIsBABCvAgAAkQQAMLACAQDUAwAhtgJAANYDACHJAgEA1AMAIcwCQADWAwAhhgMBANQDACGHAwEA1AMAIYgDAQDiAwAhiQMBAOIDACGKA0AA1wMAIYsDQADXAwAhjAMBAOIDACGNAwEA4gMAIY4DAQDiAwAhGa0CAACSBAAwrgIAAHUAEK8CAACSBAAwsAIBANQDACG2AkAA1gMAIcwCQADWAwAh2gIBAOIDACHbAgIA6QMAIdwCAQDiAwAh-AJAANcDACGPAwEA4gMAIZADIACJBAAhkQMBAOIDACGTAwAAkwSTAyKVAwAAlASVAyKWAyAAiQQAIZcDAQDiAwAhmAMBAOIDACGZAwAA6wMAIJoDQADXAwAhmwMBAOIDACGcAyAAlQQAIZ0DAQDiAwAhngNAANcDACGfA0AA1wMAIQcMAADcAwAgOQAAmwQAIDoAAJsEACC4AgAAAJMDArkCAAAAkwMIugIAAACTAwi_AgAAmgSTAyIHDAAA3AMAIDkAAJkEACA6AACZBAAguAIAAACVAwK5AgAAAJUDCLoCAAAAlQMIvwIAAJgElQMiBQwAANkDACA5AACXBAAgOgAAlwQAILgCIAAAAAG_AiAAlgQAIQUMAADZAwAgOQAAlwQAIDoAAJcEACC4AiAAAAABvwIgAJYEACECuAIgAAAAAb8CIACXBAAhBwwAANwDACA5AACZBAAgOgAAmQQAILgCAAAAlQMCuQIAAACVAwi6AgAAAJUDCL8CAACYBJUDIgS4AgAAAJUDArkCAAAAlQMIugIAAACVAwi_AgAAmQSVAyIHDAAA3AMAIDkAAJsEACA6AACbBAAguAIAAACTAwK5AgAAAJMDCLoCAAAAkwMIvwIAAJoEkwMiBLgCAAAAkwMCuQIAAACTAwi6AgAAAJMDCL8CAACbBJMDIg8DAACgBAAgrQIAAJwEADCuAgAAVAAQrwIAAJwEADCwAgEA_AMAIbYCQACfBAAhyQIBAPwDACHcAgEA_gMAIfkCAQD8AwAh-gIBAPwDACH7AgIAnQQAIfwCAQD8AwAh_QIgAJ4EACH-AgEA_gMAIf8CAQD-AwAhCLgCAgAAAAG5AgIAAAAEugICAAAABLsCAgAAAAG8AgIAAAABvQICAAAAAb4CAgAAAAG_AgIA3AMAIQK4AiAAAAABvwIgAIsEACEIuAJAAAAAAbkCQAAAAAW6AkAAAAAFuwJAAAAAAbwCQAAAAAG9AkAAAAABvgJAAAAAAb8CQADaAwAhJQQAAMoEACAFAADLBAAgBgAAzAQAIB0AAL4EACAeAAC_BAAgIAAAzQQAICEAAMAEACAiAADBBAAgIwAAwgQAICQAAM4EACCtAgAAxgQAMK4CAAAPABCvAgAAxgQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdoCAQD-AwAh2wICAP0DACHcAgEA_gMAIfgCQACfBAAhjwMBAP4DACGQAyAAngQAIZEDAQD-AwAhkwMAAMcEkwMilQMAAMgElQMilgMgAJ4EACGXAwEA_gMAIZgDAQD-AwAhmQMAAKcEACCaA0AAnwQAIZsDAQD-AwAhnAMgAMkEACGdAwEA_gMAIZ4DQACfBAAhnwNAAJ8EACGlAwAADwAgpgMAAA8AIAwfAACgBAAgrQIAAKEEADCuAgAATQAQrwIAAKEEADCwAgEA_AMAIbECAQD8AwAhsgIBAPwDACGzAgEA_AMAIbQCAQD8AwAhtQIAAKIEACC2AkAA_wMAIbcCQACfBAAhDLgCgAAAAAG7AoAAAAABvAKAAAAAAb0CgAAAAAG-AoAAAAABvwKAAAAAAcACAQAAAAHBAgEAAAABwgIBAAAAAcMCgAAAAAHEAoAAAAABxQKAAAAAAQwDAACgBAAgBwAApAQAICoAAKIEACCtAgAAowQAMK4CAAA_ABCvAgAAowQAMLACAQD8AwAhtgJAAP8DACHJAgEA_AMAIcoCAQD-AwAhywICAJ0EACHMAkAA_wMAIR8RAAC8BAAgEgAApAQAIBMAALEEACAUAAC8BAAgFQAAvQQAIBYAAL4EACAYAAC_BAAgGQAAsgQAIBoAAMAEACAbAADBBAAgHAAAwgQAIK0CAAC6BAAwrgIAABcAEK8CAAC6BAAwsAIBAPwDACG2AkAA_wMAIcwCQAD_AwAh2wICAP0DACHtAgIA_QMAIe4CAQD-AwAh7wICAP0DACHxAgAAuwTxAiLyAiAAngQAIfMCIACeBAAh9AICAJ0EACH1AgIAnQQAIfYCAgCdBAAh9wICAJ0EACH4AkAAnwQAIaUDAAAXACCmAwAAFwAgEQMAAKkEACAHAACoBAAgrQIAAKUEADCuAgAAOgAQrwIAAKUEADCwAgEA_AMAIbYCQAD_AwAhyQIBAP4DACHKAgEA_AMAIc0CAgD9AwAhzwIAAKYEzwIi0AIBAP4DACHRAgEA_gMAIdICAQD-AwAh0wIBAP4DACHUAgAApwQAINUCAQD-AwAhBLgCAAAAzwICuQIAAADPAgi6AgAAAM8CCL8CAADuA88CIgy4AoAAAAABuwKAAAAAAbwCgAAAAAG9AoAAAAABvgKAAAAAAb8CgAAAAAHAAgEAAAABwQIBAAAAAcICAQAAAAHDAoAAAAABxAKAAAAAAcUCgAAAAAEfEQAAvAQAIBIAAKQEACATAACxBAAgFAAAvAQAIBUAAL0EACAWAAC-BAAgGAAAvwQAIBkAALIEACAaAADABAAgGwAAwQQAIBwAAMIEACCtAgAAugQAMK4CAAAXABCvAgAAugQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdsCAgD9AwAh7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACGlAwAAFwAgpgMAABcAICUEAADKBAAgBQAAywQAIAYAAMwEACAdAAC-BAAgHgAAvwQAICAAAM0EACAhAADABAAgIgAAwQQAICMAAMIEACAkAADOBAAgrQIAAMYEADCuAgAADwAQrwIAAMYEADCwAgEA_AMAIbYCQAD_AwAhzAJAAP8DACHaAgEA_gMAIdsCAgD9AwAh3AIBAP4DACH4AkAAnwQAIY8DAQD-AwAhkAMgAJ4EACGRAwEA_gMAIZMDAADHBJMDIpUDAADIBJUDIpYDIACeBAAhlwMBAP4DACGYAwEA_gMAIZkDAACnBAAgmgNAAJ8EACGbAwEA_gMAIZwDIADJBAAhnQMBAP4DACGeA0AAnwQAIZ8DQACfBAAhpQMAAA8AIKYDAAAPACACyQIBAAAAAcoCAQAAAAEIAwAAoAQAIAcAAKgEACCtAgAAqwQAMK4CAAA2ABCvAgAAqwQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIQLKAgEAAAAB1gIBAAAAAQoHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIEuAIAAADYAgK5AgAAANgCCLoCAAAA2AIIvwIAAPUD2AIiAsoCAQAAAAHNAgIAAAABEwcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhA94CAAAXACDfAgAAFwAg4AIAABcAIAPeAgAAIgAg3wIAACIAIOACAAAiACALBwAAqAQAIA8AALUEACCtAgAAswQAMK4CAAAiABCvAgAAswQAMLACAQD8AwAhtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACEEuAIAAADkAgK5AgAAAOQCCLoCAAAA5AIIvwIAAIQE5AIiFQcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhpQMAABUAIKYDAAAVACADygIBAAAAAc0CAgAAAAHkAgEAAAABCQoAALUEACANAAC4BAAgrQIAALcEADCuAgAAHAAQrwIAALcEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHkAgEA_AMAIQsLAACABAAgrQIAAPsDADCuAgAAswIAEK8CAAD7AwAwsAIBAPwDACG2AkAA_wMAIdsCAgD9AwAh3AIBAPwDACHdAgEA_gMAIaUDAACzAgAgpgMAALMCACACsAIBAAAAAe0CAgAAAAEdEQAAvAQAIBIAAKQEACATAACxBAAgFAAAvAQAIBUAAL0EACAWAAC-BAAgGAAAvwQAIBkAALIEACAaAADABAAgGwAAwQQAIBwAAMIEACCtAgAAugQAMK4CAAAXABCvAgAAugQAMLACAQD8AwAhtgJAAP8DACHMAkAA_wMAIdsCAgD9AwAh7QICAP0DACHuAgEA_gMAIe8CAgD9AwAh8QIAALsE8QIi8gIgAJ4EACHzAiAAngQAIfQCAgCdBAAh9QICAJ0EACH2AgIAnQQAIfcCAgCdBAAh-AJAAJ8EACEEuAIAAADxAgK5AgAAAPECCLoCAAAA8QIIvwIAAI0E8QIiFQcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhpQMAABUAIKYDAAAVACAD3gIAABUAIN8CAAAVACDgAgAAFQAgA94CAAARACDfAgAAEQAg4AIAABEAIAPeAgAAMAAg3wIAADAAIOACAAAwACAD3gIAADYAIN8CAAA2ACDgAgAANgAgA94CAAA6ACDfAgAAOgAg4AIAADoAIAPeAgAAPwAg3wIAAD8AIOACAAA_ACACyQIBAAAAAcoCAQAAAAEJAwAAoAQAIAcAAKgEACCtAgAAxAQAMK4CAAARABCvAgAAxAQAMLYCQAD_AwAhyQIBAPwDACHKAgEA_AMAIdoCAADFBNoCIgS4AgAAANoCArkCAAAA2gIIugIAAADaAgi_AgAA-QPaAiIjBAAAygQAIAUAAMsEACAGAADMBAAgHQAAvgQAIB4AAL8EACAgAADNBAAgIQAAwAQAICIAAMEEACAjAADCBAAgJAAAzgQAIK0CAADGBAAwrgIAAA8AEK8CAADGBAAwsAIBAPwDACG2AkAA_wMAIcwCQAD_AwAh2gIBAP4DACHbAgIA_QMAIdwCAQD-AwAh-AJAAJ8EACGPAwEA_gMAIZADIACeBAAhkQMBAP4DACGTAwAAxwSTAyKVAwAAyASVAyKWAyAAngQAIZcDAQD-AwAhmAMBAP4DACGZAwAApwQAIJoDQACfBAAhmwMBAP4DACGcAyAAyQQAIZ0DAQD-AwAhngNAAJ8EACGfA0AAnwQAIQS4AgAAAJMDArkCAAAAkwMIugIAAACTAwi_AgAAmwSTAyIEuAIAAACVAwK5AgAAAJUDCLoCAAAAlQMIvwIAAJkElQMiArgCIAAAAAG_AiAAlwQAIQPeAgAAAwAg3wIAAAMAIOACAAADACAD3gIAAAcAIN8CAAAHACDgAgAABwAgA94CAAALACDfAgAACwAg4AIAAAsAIAPeAgAATQAg3wIAAE0AIOACAABNACAD3gIAAFQAIN8CAABUACDgAgAAVAAgCwMAAKkEACCtAgAAzwQAMK4CAAALABCvAgAAzwQAMLACAQD8AwAhtgJAAJ8EACHJAgEA_gMAIcwCQACfBAAhgAMBAPwDACGBAwEA_AMAIYIDQAD_AwAhDQMAAKAEACCtAgAA0AQAMK4CAAAHABCvAgAA0AQAMLACAQD8AwAhtgJAAP8DACHJAgEA_AMAIcwCQAD_AwAh0gIBAP4DACGCA0AA_wMAIYMDAQD8AwAhhAMBAP4DACGFAwEA_gMAIREDAACgBAAgrQIAANEEADCuAgAAAwAQrwIAANEEADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIYYDAQD8AwAhhwMBAPwDACGIAwEA_gMAIYkDAQD-AwAhigNAAJ8EACGLA0AAnwQAIYwDAQD-AwAhjQMBAP4DACGOAwEA_gMAIQAAAAABqgMBAAAAAQGqA0AAAAABAaoDQAAAAAEFMQAAiwkAIDIAAI4JACCnAwAAjAkAIKgDAACNCQAgrQMAAAEAIAMxAACLCQAgpwMAAIwJACCtAwAAAQAgAAAAAAAFqgMCAAAAAbADAgAAAAGxAwIAAAABsgMCAAAAAbMDAgAAAAEBqgMBAAAAAQUxAACDCQAgMgAAiQkAIKcDAACECQAgqAMAAIgJACCtAwAAAQAgBzEAAIEJACAyAACGCQAgpwMAAIIJACCoAwAAhQkAIKsDAAAXACCsAwAAFwAgrQMAABoAIAMxAACDCQAgpwMAAIQJACCtAwAAAQAgAzEAAIEJACCnAwAAggkAIK0DAAAaACAAAAAAAAWqAwIAAAABsAMCAAAAAbEDAgAAAAGyAwIAAAABswMCAAAAAQGqAwAAAM8CAgUxAAD5CAAgMgAA_wgAIKcDAAD6CAAgqAMAAP4IACCtAwAAGgAgBzEAAPcIACAyAAD8CAAgpwMAAPgIACCoAwAA-wgAIKsDAAAPACCsAwAADwAgrQMAAAEAIAMxAAD5CAAgpwMAAPoIACCtAwAAGgAgAzEAAPcIACCnAwAA-AgAIK0DAAABACAAAAAFMQAA7wgAIDIAAPUIACCnAwAA8AgAIKgDAAD0CAAgrQMAABoAIAUxAADtCAAgMgAA8ggAIKcDAADuCAAgqAMAAPEIACCtAwAAAQAgAzEAAO8IACCnAwAA8AgAIK0DAAAaACADMQAA7QgAIKcDAADuCAAgrQMAAAEAIAAAAAGqAwAAANgCAgUxAADlCAAgMgAA6wgAIKcDAADmCAAgqAMAAOoIACCtAwAAGgAgBzEAAOMIACAyAADoCAAgpwMAAOQIACCoAwAA5wgAIKsDAAAPACCsAwAADwAgrQMAAAEAIAMxAADlCAAgpwMAAOYIACCtAwAAGgAgAzEAAOMIACCnAwAA5AgAIK0DAAABACAAAAABqgMAAADaAgIFMQAA2wgAIDIAAOEIACCnAwAA3AgAIKgDAADgCAAgrQMAABoAIAUxAADZCAAgMgAA3ggAIKcDAADaCAAgqAMAAN0IACCtAwAAAQAgAzEAANsIACCnAwAA3AgAIK0DAAAaACADMQAA2QgAIKcDAADaCAAgrQMAAAEAIAAAAAAACzEAAI4FADAyAACTBQAwpwMAAI8FADCoAwAAkAUAMKkDAACRBQAgqgMAAJIFADCrAwAAkgUAMKwDAACSBQAwrQMAAJIFADCuAwAAlAUAMK8DAACVBQAwBAoAAJsFACC2AkAAAAABygIBAAAAAc0CAgAAAAECAAAAHgAgMQAAmgUAIAMAAAAeACAxAACaBQAgMgAAmAUAIAEqAADYCAAwCgoAALUEACANAAC4BAAgrQIAALcEADCuAgAAHAAQrwIAALcEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHkAgEA_AMAIaMDAAC2BAAgAgAAAB4AICoAAJgFACACAAAAlgUAICoAAJcFACAHrQIAAJUFADCuAgAAlgUAEK8CAACVBQAwtgJAAP8DACHKAgEA_AMAIc0CAgCdBAAh5AIBAPwDACEHrQIAAJUFADCuAgAAlgUAEK8CAACVBQAwtgJAAP8DACHKAgEA_AMAIc0CAgCdBAAh5AIBAPwDACEDtgJAANcEACHKAgEA1gQAIc0CAgDgBAAhBAoAAJkFACC2AkAA1wQAIcoCAQDWBAAhzQICAOAEACEFMQAA0wgAIDIAANYIACCnAwAA1AgAIKgDAADVCAAgrQMAAC0AIAQKAACbBQAgtgJAAAAAAcoCAQAAAAHNAgIAAAABAzEAANMIACCnAwAA1AgAIK0DAAAtACAEMQAAjgUAMKcDAACPBQAwqQMAAJEFACCtAwAAkgUAMAAAAAAAAAGqAwAAAOQCAgUxAADLCAAgMgAA0QgAIKcDAADMCAAgqAMAANAIACCtAwAAGgAgBTEAAMkIACAyAADOCAAgpwMAAMoIACCoAwAAzQgAIK0DAAAtACADMQAAywgAIKcDAADMCAAgrQMAABoAIAMxAADJCAAgpwMAAMoIACCtAwAALQAgAAAAAAAFMQAAxAgAIDIAAMcIACCnAwAAxQgAIKgDAADGCAAgrQMAALACACADMQAAxAgAIKcDAADFCAAgrQMAALACACAAAAAAAAUxAAClCAAgMgAAwggAIKcDAACmCAAgqAMAAMEIACCtAwAAGgAgBzEAALoGACAyAADTBgAgpwMAALsGACCoAwAA0gYAIKsDAAAXACCsAwAAFwAgrQMAABoAIAsxAADOBQAwMgAA0wUAMKcDAADPBQAwqAMAANAFADCpAwAA0QUAIKoDAADSBQAwqwMAANIFADCsAwAA0gUAMK0DAADSBQAwrgMAANQFADCvAwAA1QUAMAsxAADFBQAwMgAAyQUAMKcDAADGBQAwqAMAAMcFADCpAwAAyAUAIKoDAACSBQAwqwMAAJIFADCsAwAAkgUAMK0DAACSBQAwrgMAAMoFADCvAwAAlQUAMAsxAAC5BQAwMgAAvgUAMKcDAAC6BQAwqAMAALsFADCpAwAAvAUAIKoDAAC9BQAwqwMAAL0FADCsAwAAvQUAMK0DAAC9BQAwrgMAAL8FADCvAwAAwAUAMAUHAACmBQAgsAIBAAAAAbYCQAAAAAHPAgAAAOQCAuICAQAAAAECAAAAJAAgMQAAxAUAIAMAAAAkACAxAADEBQAgMgAAwwUAIAEqAADACAAwCwcAAKgEACAPAAC1BAAgrQIAALMEADCuAgAAIgAQrwIAALMEADCwAgEAAAABtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACECAAAAJAAgKgAAwwUAIAIAAADBBQAgKgAAwgUAIAmtAgAAwAUAMK4CAADBBQAQrwIAAMAFADCwAgEA_AMAIbYCQAD_AwAhygIBAPwDACHPAgAAtATkAiLhAgIAnQQAIeICAQD8AwAhCa0CAADABQAwrgIAAMEFABCvAgAAwAUAMLACAQD8AwAhtgJAAP8DACHKAgEA_AMAIc8CAAC0BOQCIuECAgCdBAAh4gIBAPwDACEEsAIBANYEACG2AkAA1wQAIc8CAACjBeQCIuICAQDWBAAhBQcAAKQFACCwAgEA1gQAIbYCQADXBAAhzwIAAKMF5AIi4gIBANYEACEFBwAApgUAILACAQAAAAG2AkAAAAABzwIAAADkAgLiAgEAAAABAw0AAK4FACC2AkAAAAAB5AIBAAAAAQIAAAAeACAxAADNBQAgAwAAAB4AIDEAAM0FACAyAADMBQAgASoAAL8IADACAAAAHgAgKgAAzAUAIAIAAACWBQAgKgAAywUAIAK2AkAA1wQAIeQCAQDWBAAhAw0AAK0FACC2AkAA1wQAIeQCAQDWBAAhAw0AAK4FACC2AkAAAAAB5AIBAAAAARcRAADKBgAgEgAAvAYAIBMAAL0GACAVAAC_BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA0QYAIAMAAAAaACAxAADRBgAgMgAA2gUAIAEqAAC-CAAwHhEAALwEACASAACkBAAgEwAAsQQAIBQAALwEACAVAAC9BAAgFgAAvgQAIBgAAL8EACAZAACyBAAgGgAAwAQAIBsAAMEEACAcAADCBAAgrQIAALoEADCuAgAAFwAQrwIAALoEADCwAgEAAAABtgJAAP8DACHMAkAA_wMAIdsCAgAAAAHtAgIA_QMAIe4CAQD-AwAh7wICAP0DACHxAgAAuwTxAiLyAiAAngQAIfMCIACeBAAh9AICAJ0EACH1AgIAnQQAIfYCAgCdBAAh9wICAJ0EACH4AkAAnwQAIaQDAAC5BAAgAgAAABoAICoAANoFACACAAAA1gUAICoAANcFACASrQIAANUFADCuAgAA1gUAEK8CAADVBQAwsAIBAPwDACG2AkAA_wMAIcwCQAD_AwAh2wICAP0DACHtAgIA_QMAIe4CAQD-AwAh7wICAP0DACHxAgAAuwTxAiLyAiAAngQAIfMCIACeBAAh9AICAJ0EACH1AgIAnQQAIfYCAgCdBAAh9wICAJ0EACH4AkAAnwQAIRKtAgAA1QUAMK4CAADWBQAQrwIAANUFADCwAgEA_AMAIbYCQAD_AwAhzAJAAP8DACHbAgIA_QMAIe0CAgD9AwAh7gIBAP4DACHvAgIA_QMAIfECAAC7BPECIvICIACeBAAh8wIgAJ4EACH0AgIAnQQAIfUCAgCdBAAh9gICAJ0EACH3AgIAnQQAIfgCQACfBAAhDbACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIQGqAwAAAPECAgGqAyAAAAABFxEAANsFACASAADcBQAgEwAA3QUAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAIBwAAOQFACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEHMQAArAgAIDIAALwIACCnAwAArQgAIKgDAAC7CAAgqwMAABUAIKwDAAAVACCtAwAALQAgBzEAAK8IACAyAAC5CAAgpwMAALAIACCoAwAAuAgAIKsDAAAXACCsAwAAFwAgrQMAABoAIAsxAADGBgAwMgAAzAYAMKcDAADHBgAwqAMAAMsGADCpAwAAyAYAIKoDAADSBQAwqwMAANIFADCsAwAA0gUAMK0DAADSBQAwrgMAAM0GADCvAwAA1QUAMAsxAACqBgAwMgAArwYAMKcDAACrBgAwqAMAAKwGADCpAwAArQYAIKoDAACuBgAwqwMAAK4GADCsAwAArgYAMK0DAACuBgAwrgMAALAGADCvAwAAsQYAMAsxAACeBgAwMgAAowYAMKcDAACfBgAwqAMAAKAGADCpAwAAoQYAIKoDAACiBgAwqwMAAKIGADCsAwAAogYAMK0DAACiBgAwrgMAAKQGADCvAwAApQYAMAsxAACSBgAwMgAAlwYAMKcDAACTBgAwqAMAAJQGADCpAwAAlQYAIKoDAACWBgAwqwMAAJYGADCsAwAAlgYAMK0DAACWBgAwrgMAAJgGADCvAwAAmQYAMAsxAACJBgAwMgAAjQYAMKcDAACKBgAwqAMAAIsGADCpAwAAjAYAIKoDAAC9BQAwqwMAAL0FADCsAwAAvQUAMK0DAAC9BQAwrgMAAI4GADCvAwAAwAUAMAsxAAD9BQAwMgAAggYAMKcDAAD-BQAwqAMAAP8FADCpAwAAgAYAIKoDAACBBgAwqwMAAIEGADCsAwAAgQYAMK0DAACBBgAwrgMAAIMGADCvAwAAhAYAMAsxAADxBQAwMgAA9gUAMKcDAADyBQAwqAMAAPMFADCpAwAA9AUAIKoDAAD1BQAwqwMAAPUFADCsAwAA9QUAMK0DAAD1BQAwrgMAAPcFADCvAwAA-AUAMAsxAADlBQAwMgAA6gUAMKcDAADmBQAwqAMAAOcFADCpAwAA6AUAIKoDAADpBQAwqwMAAOkFADCsAwAA6QUAMK0DAADpBQAwrgMAAOsFADCvAwAA7AUAMAcDAADkBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABywICAAAAAcwCQAAAAAECAAAAQQAgMQAA8AUAIAMAAABBACAxAADwBQAgMgAA7wUAIAEqAAC3CAAwDAMAAKAEACAHAACkBAAgKgAAogQAIK0CAACjBAAwrgIAAD8AEK8CAACjBAAwsAIBAAAAAbYCQAD_AwAhyQIBAPwDACHKAgEA_gMAIcsCAgCdBAAhzAJAAP8DACECAAAAQQAgKgAA7wUAIAIAAADtBQAgKgAA7gUAIAoqAACiBAAgrQIAAOwFADCuAgAA7QUAEK8CAADsBQAwsAIBAPwDACG2AkAA_wMAIckCAQD8AwAhygIBAP4DACHLAgIAnQQAIcwCQAD_AwAhCioAAKIEACCtAgAA7AUAMK4CAADtBQAQrwIAAOwFADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHKAgEA_gMAIcsCAgCdBAAhzAJAAP8DACEGKoAAAAABsAIBANYEACG2AkAA1wQAIckCAQDWBAAhywICAOAEACHMAkAA1wQAIQcDAADiBAAgKoAAAAABsAIBANYEACG2AkAA1wQAIckCAQDWBAAhywICAOAEACHMAkAA1wQAIQcDAADkBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHJAgEAAAABywICAAAAAcwCQAAAAAEMAwAA8AQAILACAQAAAAG2AkAAAAAByQIBAAAAAc0CAgAAAAHPAgAAAM8CAtACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QIBAAAAAQIAAAA8ACAxAAD8BQAgAwAAADwAIDEAAPwFACAyAAD7BQAgASoAALYIADARAwAAqQQAIAcAAKgEACCtAgAApQQAMK4CAAA6ABCvAgAApQQAMLACAQAAAAG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQIAAAA8ACAqAAD7BQAgAgAAAPkFACAqAAD6BQAgD60CAAD4BQAwrgIAAPkFABCvAgAA-AUAMLACAQD8AwAhtgJAAP8DACHJAgEA_gMAIcoCAQD8AwAhzQICAP0DACHPAgAApgTPAiLQAgEA_gMAIdECAQD-AwAh0gIBAP4DACHTAgEA_gMAIdQCAACnBAAg1QIBAP4DACEPrQIAAPgFADCuAgAA-QUAEK8CAAD4BQAwsAIBAPwDACG2AkAA_wMAIckCAQD-AwAhygIBAPwDACHNAgIA_QMAIc8CAACmBM8CItACAQD-AwAh0QIBAP4DACHSAgEA_gMAIdMCAQD-AwAh1AIAAKcEACDVAgEA_gMAIQuwAgEA1gQAIbYCQADXBAAhyQIBAOEEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAMAAO4EACCwAgEA1gQAIbYCQADXBAAhyQIBAOEEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAMAAPAEACCwAgEAAAABtgJAAAAAAckCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEDAwAA9wQAILYCQAAAAAHJAgEAAAABAgAAADgAIDEAAIgGACADAAAAOAAgMQAAiAYAIDIAAIcGACABKgAAtQgAMAkDAACgBAAgBwAAqAQAIK0CAACrBAAwrgIAADYAEK8CAACrBAAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAhoAMAAKoEACACAAAAOAAgKgAAhwYAIAIAAACFBgAgKgAAhgYAIAatAgAAhAYAMK4CAACFBgAQrwIAAIQGADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACEGrQIAAIQGADCuAgAAhQYAEK8CAACEBgAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAhArYCQADXBAAhyQIBANYEACEDAwAA9QQAILYCQADXBAAhyQIBANYEACEDAwAA9wQAILYCQAAAAAHJAgEAAAABBg8AAKcFACCwAgEAAAABtgJAAAAAAc8CAAAA5AIC4QICAAAAAeICAQAAAAECAAAAJAAgMQAAkQYAIAMAAAAkACAxAACRBgAgMgAAkAYAIAEqAAC0CAAwAgAAACQAICoAAJAGACACAAAAwQUAICoAAI8GACAFsAIBANYEACG2AkAA1wQAIc8CAACjBeQCIuECAgDgBAAh4gIBANYEACEGDwAApQUAILACAQDWBAAhtgJAANcEACHPAgAAowXkAiLhAgIA4AQAIeICAQDWBAAhBg8AAKcFACCwAgEAAAABtgJAAAAAAc8CAAAA5AIC4QICAAAAAeICAQAAAAEFFwAA_wQAILACAQAAAAG2AkAAAAAB1gIBAAAAAdgCAAAA2AICAgAAADIAIDEAAJ0GACADAAAAMgAgMQAAnQYAIDIAAJwGACABKgAAswgAMAsHAACoBAAgFwAAqQQAIK0CAACtBAAwrgIAADAAEK8CAACtBAAwsAIBAAAAAbYCQAD_AwAhygIBAPwDACHWAgEA_gMAIdgCAACuBNgCIqEDAACsBAAgAgAAADIAICoAAJwGACACAAAAmgYAICoAAJsGACAIrQIAAJkGADCuAgAAmgYAEK8CAACZBgAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIIrQIAAJkGADCuAgAAmgYAEK8CAACZBgAwsAIBAPwDACG2AkAA_wMAIcoCAQD8AwAh1gIBAP4DACHYAgAArgTYAiIEsAIBANYEACG2AkAA1wQAIdYCAQDhBAAh2AIAAPsE2AIiBRcAAP0EACCwAgEA1gQAIbYCQADXBAAh1gIBAOEEACHYAgAA-wTYAiIFFwAA_wQAILACAQAAAAG2AkAAAAAB1gIBAAAAAdgCAAAA2AICBAMAAIcFACC2AkAAAAAByQIBAAAAAdoCAAAA2gICAgAAABMAIDEAAKkGACADAAAAEwAgMQAAqQYAIDIAAKgGACABKgAAsggAMAoDAACgBAAgBwAAqAQAIK0CAADEBAAwrgIAABEAEK8CAADEBAAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAh2gIAAMUE2gIioAMAAMMEACACAAAAEwAgKgAAqAYAIAIAAACmBgAgKgAApwYAIAetAgAApQYAMK4CAACmBgAQrwIAAKUGADC2AkAA_wMAIckCAQD8AwAhygIBAPwDACHaAgAAxQTaAiIHrQIAAKUGADCuAgAApgYAEK8CAAClBgAwtgJAAP8DACHJAgEA_AMAIcoCAQD8AwAh2gIAAMUE2gIiA7YCQADXBAAhyQIBANYEACHaAgAAgwXaAiIEAwAAhQUAILYCQADXBAAhyQIBANYEACHaAgAAgwXaAiIEAwAAhwUAILYCQAAAAAHJAgEAAAAB2gIAAADaAgIOCAAAtgYAIAkAALcGACAOAAC4BgAgEAAAuQYAILYCQAAAAAHNAgIAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAekCAQAAAAHqAgEAAAAB6wIBAAAAAewCQAAAAAECAAAALQAgMQAAtQYAIAMAAAAtACAxAAC1BgAgMgAAtAYAIAEqAACxCAAwFAcAAKgEACAIAACkBAAgCQAAsQQAIA4AAIAEACAQAACyBAAgrQIAALAEADCuAgAAFQAQrwIAALAEADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhogMAAK8EACACAAAALQAgKgAAtAYAIAIAAACyBgAgKgAAswYAIA6tAgAAsQYAMK4CAACyBgAQrwIAALEGADC2AkAA_wMAIcoCAQD8AwAhzQICAJ0EACHlAgEA_AMAIeYCAQD-AwAh5wIBAP4DACHoAgEA_gMAIekCAQD8AwAh6gIBAP4DACHrAgEA_gMAIewCQACfBAAhDq0CAACxBgAwrgIAALIGABCvAgAAsQYAMLYCQAD_AwAhygIBAPwDACHNAgIAnQQAIeUCAQD8AwAh5gIBAP4DACHnAgEA_gMAIegCAQD-AwAh6QIBAPwDACHqAgEA_gMAIesCAQD-AwAh7AJAAJ8EACEKtgJAANcEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACEOCAAAtQUAIAkAALYFACAOAAC3BQAgEAAAuAUAILYCQADXBAAhzQICAOAEACHlAgEA1gQAIeYCAQDhBAAh5wIBAOEEACHoAgEA4QQAIekCAQDWBAAh6gIBAOEEACHrAgEA4QQAIewCQADYBAAhDggAALYGACAJAAC3BgAgDgAAuAYAIBAAALkGACC2AkAAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABAzEAALoGACCnAwAAuwYAIK0DAAAaACAEMQAAzgUAMKcDAADPBQAwqQMAANEFACCtAwAA0gUAMAQxAADFBQAwpwMAAMYFADCpAwAAyAUAIK0DAACSBQAwBDEAALkFADCnAwAAugUAMKkDAAC8BQAgrQMAAL0FADAXEgAAvAYAIBMAAL0GACAUAAC-BgAgFQAAvwYAIBYAAMAGACAYAADBBgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILYCQAAAAAHMAkAAAAAB2wICAAAAAe4CAQAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABAgAAABoAIDEAALoGACADMQAArwgAIKcDAACwCAAgrQMAABoAIAQxAADGBgAwpwMAAMcGADCpAwAAyAYAIK0DAADSBQAwAzEAAKcIACCnAwAAqAgAIK0DAAAtACAEMQAAqgYAMKcDAACrBgAwqQMAAK0GACCtAwAArgYAMAQxAACeBgAwpwMAAJ8GADCpAwAAoQYAIK0DAACiBgAwBDEAAJIGADCnAwAAkwYAMKkDAACVBgAgrQMAAJYGADAEMQAAiQYAMKcDAACKBgAwqQMAAIwGACCtAwAAvQUAMAQxAAD9BQAwpwMAAP4FADCpAwAAgAYAIK0DAACBBgAwBDEAAPEFADCnAwAA8gUAMKkDAAD0BQAgrQMAAPUFADAEMQAA5QUAMKcDAADmBQAwqQMAAOgFACCtAwAA6QUAMBgRAADKBgAgEwAAvQYAIBQAAL4GACAVAAC_BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABAgAAABoAIDEAAMkGACABKgAArggAMBgRAADKBgAgEwAAvQYAIBQAAL4GACAVAAC_BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHvAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABAzEAAKwIACCnAwAArQgAIK0DAAAtACADAAAAGgAgMQAAyQYAIDIAAM8GACACAAAAGgAgKgAAzwYAIAIAAADWBQAgKgAAzgYAIA6wAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIRgRAADbBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEHMQAApwgAIDIAAKoIACCnAwAAqAgAIKgDAACpCAAgqwMAABUAIKwDAAAVACCtAwAALQAgFxEAAMoGACASAAC8BgAgEwAAvQYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgGwAAxAYAIBwAAMUGACCwAgEAAAABtgJAAAAAAcwCQAAAAAHbAgIAAAAB7QICAAAAAfECAAAA8QIC8gIgAAAAAfMCIAAAAAH0AgIAAAAB9QICAAAAAfYCAgAAAAH3AgIAAAAB-AJAAAAAAQMAAAAXACAxAAC6BgAgMgAA1AYAIBkAAAAXACASAADcBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAA1AYAILYCQADXBAAhzAJAANcEACHbAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIRcSAADcBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhAzEAAKUIACCnAwAApggAIK0DAAAaACAAAAAAAAAAAAAABTEAAKAIACAyAACjCAAgpwMAAKEIACCoAwAAoggAIK0DAAABACADMQAAoAgAIKcDAAChCAAgrQMAAAEAIAAAAAcxAACbCAAgMgAAnggAIKcDAACcCAAgqAMAAJ0IACCrAwAADwAgrAMAAA8AIK0DAAABACADMQAAmwgAIKcDAACcCAAgrQMAAAEAIAAAAAUxAACWCAAgMgAAmQgAIKcDAACXCAAgqAMAAJgIACCtAwAAAQAgAzEAAJYIACCnAwAAlwgAIK0DAAABACAAAAAFMQAAkQgAIDIAAJQIACCnAwAAkggAIKgDAACTCAAgrQMAAAEAIAMxAACRCAAgpwMAAJIIACCtAwAAAQAgAAAAAAABqgMAAACTAwIBqgMAAACVAwIBqgMgAAAAAQsxAADgBwAwMgAA5QcAMKcDAADhBwAwqAMAAOIHADCpAwAA4wcAIKoDAADkBwAwqwMAAOQHADCsAwAA5AcAMK0DAADkBwAwrgMAAOYHADCvAwAA5wcAMAsxAADUBwAwMgAA2QcAMKcDAADVBwAwqAMAANYHADCpAwAA1wcAIKoDAADYBwAwqwMAANgHADCsAwAA2AcAMK0DAADYBwAwrgMAANoHADCvAwAA2wcAMAsxAADIBwAwMgAAzQcAMKcDAADJBwAwqAMAAMoHADCpAwAAywcAIKoDAADMBwAwqwMAAMwHADCsAwAAzAcAMK0DAADMBwAwrgMAAM4HADCvAwAAzwcAMAsxAAC_BwAwMgAAwwcAMKcDAADABwAwqAMAAMEHADCpAwAAwgcAIKoDAACiBgAwqwMAAKIGADCsAwAAogYAMK0DAACiBgAwrgMAAMQHADCvAwAApQYAMAsxAAC2BwAwMgAAugcAMKcDAAC3BwAwqAMAALgHADCpAwAAuQcAIKoDAACWBgAwqwMAAJYGADCsAwAAlgYAMK0DAACWBgAwrgMAALsHADCvAwAAmQYAMAsxAACqBwAwMgAArwcAMKcDAACrBwAwqAMAAKwHADCpAwAArQcAIKoDAACuBwAwqwMAAK4HADCsAwAArgcAMK0DAACuBwAwrgMAALAHADCvAwAAsQcAMAsxAAChBwAwMgAApQcAMKcDAACiBwAwqAMAAKMHADCpAwAApAcAIKoDAACBBgAwqwMAAIEGADCsAwAAgQYAMK0DAACBBgAwrgMAAKYHADCvAwAAhAYAMAsxAACYBwAwMgAAnAcAMKcDAACZBwAwqAMAAJoHADCpAwAAmwcAIKoDAAD1BQAwqwMAAPUFADCsAwAA9QUAMK0DAAD1BQAwrgMAAJ0HADCvAwAA-AUAMAsxAACPBwAwMgAAkwcAMKcDAACQBwAwqAMAAJEHADCpAwAAkgcAIKoDAADpBQAwqwMAAOkFADCsAwAA6QUAMK0DAADpBQAwrgMAAJQHADCvAwAA7AUAMAsxAACDBwAwMgAAiAcAMKcDAACEBwAwqAMAAIUHADCpAwAAhgcAIKoDAACHBwAwqwMAAIcHADCsAwAAhwcAMK0DAACHBwAwrgMAAIkHADCvAwAAigcAMAqwAgEAAAABtgJAAAAAAdwCAQAAAAH5AgEAAAAB-gIBAAAAAfsCAgAAAAH8AgEAAAAB_QIgAAAAAf4CAQAAAAH_AgEAAAABAgAAAFYAIDEAAI4HACADAAAAVgAgMQAAjgcAIDIAAI0HACABKgAAkAgAMA8DAACgBAAgrQIAAJwEADCuAgAAVAAQrwIAAJwEADCwAgEAAAABtgJAAJ8EACHJAgEA_AMAIdwCAQD-AwAh-QIBAPwDACH6AgEA_AMAIfsCAgCdBAAh_AIBAPwDACH9AiAAngQAIf4CAQD-AwAh_wIBAP4DACECAAAAVgAgKgAAjQcAIAIAAACLBwAgKgAAjAcAIA6tAgAAigcAMK4CAACLBwAQrwIAAIoHADCwAgEA_AMAIbYCQACfBAAhyQIBAPwDACHcAgEA_gMAIfkCAQD8AwAh-gIBAPwDACH7AgIAnQQAIfwCAQD8AwAh_QIgAJ4EACH-AgEA_gMAIf8CAQD-AwAhDq0CAACKBwAwrgIAAIsHABCvAgAAigcAMLACAQD8AwAhtgJAAJ8EACHJAgEA_AMAIdwCAQD-AwAh-QIBAPwDACH6AgEA_AMAIfsCAgCdBAAh_AIBAPwDACH9AiAAngQAIf4CAQD-AwAh_wIBAP4DACEKsAIBANYEACG2AkAA2AQAIdwCAQDhBAAh-QIBANYEACH6AgEA1gQAIfsCAgDgBAAh_AIBANYEACH9AiAA2QUAIf4CAQDhBAAh_wIBAOEEACEKsAIBANYEACG2AkAA2AQAIdwCAQDhBAAh-QIBANYEACH6AgEA1gQAIfsCAgDgBAAh_AIBANYEACH9AiAA2QUAIf4CAQDhBAAh_wIBAOEEACEKsAIBAAAAAbYCQAAAAAHcAgEAAAAB-QIBAAAAAfoCAQAAAAH7AgIAAAAB_AIBAAAAAf0CIAAAAAH-AgEAAAAB_wIBAAAAAQcHAADlBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHKAgEAAAABywICAAAAAcwCQAAAAAECAAAAQQAgMQAAlwcAIAMAAABBACAxAACXBwAgMgAAlgcAIAEqAACPCAAwAgAAAEEAICoAAJYHACACAAAA7QUAICoAAJUHACAGKoAAAAABsAIBANYEACG2AkAA1wQAIcoCAQDhBAAhywICAOAEACHMAkAA1wQAIQcHAADjBAAgKoAAAAABsAIBANYEACG2AkAA1wQAIcoCAQDhBAAhywICAOAEACHMAkAA1wQAIQcHAADlBAAgKoAAAAABsAIBAAAAAbYCQAAAAAHKAgEAAAABywICAAAAAcwCQAAAAAEMBwAA7wQAILACAQAAAAG2AkAAAAABygIBAAAAAc0CAgAAAAHPAgAAAM8CAtACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QIBAAAAAQIAAAA8ACAxAACgBwAgAwAAADwAIDEAAKAHACAyAACfBwAgASoAAI4IADACAAAAPAAgKgAAnwcAIAIAAAD5BQAgKgAAngcAIAuwAgEA1gQAIbYCQADXBAAhygIBANYEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAcAAO0EACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHNAgIA6wQAIc8CAADsBM8CItACAQDhBAAh0QIBAOEEACHSAgEA4QQAIdMCAQDhBAAh1AKAAAAAAdUCAQDhBAAhDAcAAO8EACCwAgEAAAABtgJAAAAAAcoCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEDBwAA9gQAILYCQAAAAAHKAgEAAAABAgAAADgAIDEAAKkHACADAAAAOAAgMQAAqQcAIDIAAKgHACABKgAAjQgAMAIAAAA4ACAqAACoBwAgAgAAAIUGACAqAACnBwAgArYCQADXBAAhygIBANYEACEDBwAA9AQAILYCQADXBAAhygIBANYEACEDBwAA9gQAILYCQAAAAAHKAgEAAAABB7ACAQAAAAGxAgEAAAABswIBAAAAAbQCAQAAAAG1AoAAAAABtgJAAAAAAbcCQAAAAAECAAAATwAgMQAAtQcAIAMAAABPACAxAAC1BwAgMgAAtAcAIAEqAACMCAAwDB8AAKAEACCtAgAAoQQAMK4CAABNABCvAgAAoQQAMLACAQAAAAGxAgEA_AMAIbICAQD8AwAhswIBAPwDACG0AgEA_AMAIbUCAACiBAAgtgJAAP8DACG3AkAAnwQAIQIAAABPACAqAAC0BwAgAgAAALIHACAqAACzBwAgC60CAACxBwAwrgIAALIHABCvAgAAsQcAMLACAQD8AwAhsQIBAPwDACGyAgEA_AMAIbMCAQD8AwAhtAIBAPwDACG1AgAAogQAILYCQAD_AwAhtwJAAJ8EACELrQIAALEHADCuAgAAsgcAEK8CAACxBwAwsAIBAPwDACGxAgEA_AMAIbICAQD8AwAhswIBAPwDACG0AgEA_AMAIbUCAACiBAAgtgJAAP8DACG3AkAAnwQAIQewAgEA1gQAIbECAQDWBAAhswIBANYEACG0AgEA1gQAIbUCgAAAAAG2AkAA1wQAIbcCQADYBAAhB7ACAQDWBAAhsQIBANYEACGzAgEA1gQAIbQCAQDWBAAhtQKAAAAAAbYCQADXBAAhtwJAANgEACEHsAIBAAAAAbECAQAAAAGzAgEAAAABtAIBAAAAAbUCgAAAAAG2AkAAAAABtwJAAAAAAQUHAAD-BAAgsAIBAAAAAbYCQAAAAAHKAgEAAAAB2AIAAADYAgICAAAAMgAgMQAAvgcAIAMAAAAyACAxAAC-BwAgMgAAvQcAIAEqAACLCAAwAgAAADIAICoAAL0HACACAAAAmgYAICoAALwHACAEsAIBANYEACG2AkAA1wQAIcoCAQDWBAAh2AIAAPsE2AIiBQcAAPwEACCwAgEA1gQAIbYCQADXBAAhygIBANYEACHYAgAA-wTYAiIFBwAA_gQAILACAQAAAAG2AkAAAAABygIBAAAAAdgCAAAA2AICBAcAAIYFACC2AkAAAAABygIBAAAAAdoCAAAA2gICAgAAABMAIDEAAMcHACADAAAAEwAgMQAAxwcAIDIAAMYHACABKgAAiggAMAIAAAATACAqAADGBwAgAgAAAKYGACAqAADFBwAgA7YCQADXBAAhygIBANYEACHaAgAAgwXaAiIEBwAAhAUAILYCQADXBAAhygIBANYEACHaAgAAgwXaAiIEBwAAhgUAILYCQAAAAAHKAgEAAAAB2gIAAADaAgIGsAIBAAAAAbYCQAAAAAHMAkAAAAABgAMBAAAAAYEDAQAAAAGCA0AAAAABAgAAAA0AIDEAANMHACADAAAADQAgMQAA0wcAIDIAANIHACABKgAAiQgAMAsDAACpBAAgrQIAAM8EADCuAgAACwAQrwIAAM8EADCwAgEAAAABtgJAAJ8EACHJAgEA_gMAIcwCQACfBAAhgAMBAPwDACGBAwEA_AMAIYIDQAD_AwAhAgAAAA0AICoAANIHACACAAAA0AcAICoAANEHACAKrQIAAM8HADCuAgAA0AcAEK8CAADPBwAwsAIBAPwDACG2AkAAnwQAIckCAQD-AwAhzAJAAJ8EACGAAwEA_AMAIYEDAQD8AwAhggNAAP8DACEKrQIAAM8HADCuAgAA0AcAEK8CAADPBwAwsAIBAPwDACG2AkAAnwQAIckCAQD-AwAhzAJAAJ8EACGAAwEA_AMAIYEDAQD8AwAhggNAAP8DACEGsAIBANYEACG2AkAA2AQAIcwCQADYBAAhgAMBANYEACGBAwEA1gQAIYIDQADXBAAhBrACAQDWBAAhtgJAANgEACHMAkAA2AQAIYADAQDWBAAhgQMBANYEACGCA0AA1wQAIQawAgEAAAABtgJAAAAAAcwCQAAAAAGAAwEAAAABgQMBAAAAAYIDQAAAAAEIsAIBAAAAAbYCQAAAAAHMAkAAAAAB0gIBAAAAAYIDQAAAAAGDAwEAAAABhAMBAAAAAYUDAQAAAAECAAAACQAgMQAA3wcAIAMAAAAJACAxAADfBwAgMgAA3gcAIAEqAACICAAwDQMAAKAEACCtAgAA0AQAMK4CAAAHABCvAgAA0AQAMLACAQAAAAG2AkAA_wMAIckCAQD8AwAhzAJAAP8DACHSAgEA_gMAIYIDQAD_AwAhgwMBAAAAAYQDAQD-AwAhhQMBAP4DACECAAAACQAgKgAA3gcAIAIAAADcBwAgKgAA3QcAIAytAgAA2wcAMK4CAADcBwAQrwIAANsHADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIdICAQD-AwAhggNAAP8DACGDAwEA_AMAIYQDAQD-AwAhhQMBAP4DACEMrQIAANsHADCuAgAA3AcAEK8CAADbBwAwsAIBAPwDACG2AkAA_wMAIckCAQD8AwAhzAJAAP8DACHSAgEA_gMAIYIDQAD_AwAhgwMBAPwDACGEAwEA_gMAIYUDAQD-AwAhCLACAQDWBAAhtgJAANcEACHMAkAA1wQAIdICAQDhBAAhggNAANcEACGDAwEA1gQAIYQDAQDhBAAhhQMBAOEEACEIsAIBANYEACG2AkAA1wQAIcwCQADXBAAh0gIBAOEEACGCA0AA1wQAIYMDAQDWBAAhhAMBAOEEACGFAwEA4QQAIQiwAgEAAAABtgJAAAAAAcwCQAAAAAHSAgEAAAABggNAAAAAAYMDAQAAAAGEAwEAAAABhQMBAAAAAQywAgEAAAABtgJAAAAAAcwCQAAAAAGGAwEAAAABhwMBAAAAAYgDAQAAAAGJAwEAAAABigNAAAAAAYsDQAAAAAGMAwEAAAABjQMBAAAAAY4DAQAAAAECAAAABQAgMQAA6wcAIAMAAAAFACAxAADrBwAgMgAA6gcAIAEqAACHCAAwEQMAAKAEACCtAgAA0QQAMK4CAAADABCvAgAA0QQAMLACAQAAAAG2AkAA_wMAIckCAQD8AwAhzAJAAP8DACGGAwEA_AMAIYcDAQD8AwAhiAMBAP4DACGJAwEA_gMAIYoDQACfBAAhiwNAAJ8EACGMAwEA_gMAIY0DAQD-AwAhjgMBAP4DACECAAAABQAgKgAA6gcAIAIAAADoBwAgKgAA6QcAIBCtAgAA5wcAMK4CAADoBwAQrwIAAOcHADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIYYDAQD8AwAhhwMBAPwDACGIAwEA_gMAIYkDAQD-AwAhigNAAJ8EACGLA0AAnwQAIYwDAQD-AwAhjQMBAP4DACGOAwEA_gMAIRCtAgAA5wcAMK4CAADoBwAQrwIAAOcHADCwAgEA_AMAIbYCQAD_AwAhyQIBAPwDACHMAkAA_wMAIYYDAQD8AwAhhwMBAPwDACGIAwEA_gMAIYkDAQD-AwAhigNAAJ8EACGLA0AAnwQAIYwDAQD-AwAhjQMBAP4DACGOAwEA_gMAIQywAgEA1gQAIbYCQADXBAAhzAJAANcEACGGAwEA1gQAIYcDAQDWBAAhiAMBAOEEACGJAwEA4QQAIYoDQADYBAAhiwNAANgEACGMAwEA4QQAIY0DAQDhBAAhjgMBAOEEACEMsAIBANYEACG2AkAA1wQAIcwCQADXBAAhhgMBANYEACGHAwEA1gQAIYgDAQDhBAAhiQMBAOEEACGKA0AA2AQAIYsDQADYBAAhjAMBAOEEACGNAwEA4QQAIY4DAQDhBAAhDLACAQAAAAG2AkAAAAABzAJAAAAAAYYDAQAAAAGHAwEAAAABiAMBAAAAAYkDAQAAAAGKA0AAAAABiwNAAAAAAYwDAQAAAAGNAwEAAAABjgMBAAAAAQQxAADgBwAwpwMAAOEHADCpAwAA4wcAIK0DAADkBwAwBDEAANQHADCnAwAA1QcAMKkDAADXBwAgrQMAANgHADAEMQAAyAcAMKcDAADJBwAwqQMAAMsHACCtAwAAzAcAMAQxAAC_BwAwpwMAAMAHADCpAwAAwgcAIK0DAACiBgAwBDEAALYHADCnAwAAtwcAMKkDAAC5BwAgrQMAAJYGADAEMQAAqgcAMKcDAACrBwAwqQMAAK0HACCtAwAArgcAMAQxAAChBwAwpwMAAKIHADCpAwAApAcAIK0DAACBBgAwBDEAAJgHADCnAwAAmQcAMKkDAACbBwAgrQMAAPUFADAEMQAAjwcAMKcDAACQBwAwqQMAAJIHACCtAwAA6QUAMAQxAACDBwAwpwMAAIQHADCpAwAAhgcAIK0DAACHBwAwAAAAAAAAAAAAABkEAAD2BwAgBQAA9wcAIAYAAPgHACAdAAD5BwAgHgAA-gcAICAAAPsHACAhAAD8BwAgIgAA_QcAICMAAP4HACAkAAD_BwAg2gIAANIEACDbAgAA0gQAINwCAADSBAAg-AIAANIEACCPAwAA0gQAIJEDAADSBAAglwMAANIEACCYAwAA0gQAIJkDAADSBAAgmgMAANIEACCbAwAA0gQAIJwDAADSBAAgnQMAANIEACCeAwAA0gQAIJ8DAADSBAAgEBEAAIQIACASAACBCAAgEwAAgggAIBQAAIQIACAVAACGCAAgFgAA-QcAIBgAAPoHACAZAACDCAAgGgAA_AcAIBsAAP0HACAcAAD-BwAg2wIAANIEACDtAgAA0gQAIO4CAADSBAAg7wIAANIEACD4AgAA0gQAIAAACwcAAIEIACAIAACBCAAgCQAAgggAIA4AAJ0FACAQAACDCAAg5gIAANIEACDnAgAA0gQAIOgCAADSBAAg6gIAANIEACDrAgAA0gQAIOwCAADSBAAgAwsAAJ0FACDbAgAA0gQAIN0CAADSBAAgAAywAgEAAAABtgJAAAAAAcwCQAAAAAGGAwEAAAABhwMBAAAAAYgDAQAAAAGJAwEAAAABigNAAAAAAYsDQAAAAAGMAwEAAAABjQMBAAAAAY4DAQAAAAEIsAIBAAAAAbYCQAAAAAHMAkAAAAAB0gIBAAAAAYIDQAAAAAGDAwEAAAABhAMBAAAAAYUDAQAAAAEGsAIBAAAAAbYCQAAAAAHMAkAAAAABgAMBAAAAAYEDAQAAAAGCA0AAAAABA7YCQAAAAAHKAgEAAAAB2gIAAADaAgIEsAIBAAAAAbYCQAAAAAHKAgEAAAAB2AIAAADYAgIHsAIBAAAAAbECAQAAAAGzAgEAAAABtAIBAAAAAbUCgAAAAAG2AkAAAAABtwJAAAAAAQK2AkAAAAABygIBAAAAAQuwAgEAAAABtgJAAAAAAcoCAQAAAAHNAgIAAAABzwIAAADPAgLQAgEAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCAQAAAAEGKoAAAAABsAIBAAAAAbYCQAAAAAHKAgEAAAABywICAAAAAcwCQAAAAAEKsAIBAAAAAbYCQAAAAAHcAgEAAAAB-QIBAAAAAfoCAQAAAAH7AgIAAAAB_AIBAAAAAf0CIAAAAAH-AgEAAAAB_wIBAAAAAR8FAADtBwAgBgAA7gcAIB0AAO8HACAeAADwBwAgIAAA8QcAICEAAPIHACAiAADzBwAgIwAA9AcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAkQgAIAMAAAAPACAxAACRCAAgMgAAlQgAICEAAAAPACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAACVCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAADsBwAgBgAA7gcAIB0AAO8HACAeAADwBwAgIAAA8QcAICEAAPIHACAiAADzBwAgIwAA9AcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAlggAIAMAAAAPACAxAACWCAAgMgAAmggAICEAAAAPACAEAAD5BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAACaCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAADsBwAgBQAA7QcAIB0AAO8HACAeAADwBwAgIAAA8QcAICEAAPIHACAiAADzBwAgIwAA9AcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAmwgAIAMAAAAPACAxAACbCAAgMgAAnwgAICEAAAAPACAEAAD5BgAgBQAA-gYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAACfCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAADsBwAgBQAA7QcAIAYAAO4HACAdAADvBwAgHgAA8AcAICAAAPEHACAhAADyBwAgIgAA8wcAICMAAPQHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAoAgAIAMAAAAPACAxAACgCAAgMgAApAgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAhAAD_BgAgIgAAgAcAICMAAIEHACAqAACkCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIRkRAADKBgAgEgAAvAYAIBMAAL0GACAUAAC-BgAgFgAAwAYAIBgAAMEGACAZAADCBgAgGgAAwwYAIBsAAMQGACAcAADFBgAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2wICAAAAAe0CAgAAAAHuAgEAAAAB7wICAAAAAfECAAAA8QIC8gIgAAAAAfMCIAAAAAH0AgIAAAAB9QICAAAAAfYCAgAAAAH3AgIAAAAB-AJAAAAAAQIAAAAaACAxAAClCAAgDwcAANUGACAIAAC2BgAgDgAAuAYAIBAAALkGACC2AkAAAAABygIBAAAAAc0CAgAAAAHlAgEAAAAB5gIBAAAAAecCAQAAAAHoAgEAAAAB6QIBAAAAAeoCAQAAAAHrAgEAAAAB7AJAAAAAAQIAAAAtACAxAACnCAAgAwAAABUAIDEAAKcIACAyAACrCAAgEQAAABUAIAcAALQFACAIAAC1BQAgDgAAtwUAIBAAALgFACAqAACrCAAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQ8HAAC0BQAgCAAAtQUAIA4AALcFACAQAAC4BQAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQ8HAADVBgAgCQAAtwYAIA4AALgGACAQAAC5BgAgtgJAAAAAAcoCAQAAAAHNAgIAAAAB5QIBAAAAAeYCAQAAAAHnAgEAAAAB6AIBAAAAAekCAQAAAAHqAgEAAAAB6wIBAAAAAewCQAAAAAECAAAALQAgMQAArAgAIA6wAgEAAAABtgJAAAAAAcwCQAAAAAHbAgIAAAAB7QICAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAEZEQAAygYAIBIAALwGACAUAAC-BgAgFQAAvwYAIBYAAMAGACAYAADBBgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAArwgAIAq2AkAAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABA7YCQAAAAAHJAgEAAAAB2gIAAADaAgIEsAIBAAAAAbYCQAAAAAHWAgEAAAAB2AIAAADYAgIFsAIBAAAAAbYCQAAAAAHPAgAAAOQCAuECAgAAAAHiAgEAAAABArYCQAAAAAHJAgEAAAABC7ACAQAAAAG2AkAAAAAByQIBAAAAAc0CAgAAAAHPAgAAAM8CAtACAQAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QIBAAAAAQYqgAAAAAGwAgEAAAABtgJAAAAAAckCAQAAAAHLAgIAAAABzAJAAAAAAQMAAAAXACAxAACvCAAgMgAAuggAIBsAAAAXACARAADbBQAgEgAA3AUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAAuggAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEDAAAAFQAgMQAArAgAIDIAAL0IACARAAAAFQAgBwAAtAUAIAkAALYFACAOAAC3BQAgEAAAuAUAICoAAL0IACC2AkAA1wQAIcoCAQDWBAAhzQICAOAEACHlAgEA1gQAIeYCAQDhBAAh5wIBAOEEACHoAgEA4QQAIekCAQDWBAAh6gIBAOEEACHrAgEA4QQAIewCQADYBAAhDwcAALQFACAJAAC2BQAgDgAAtwUAIBAAALgFACC2AkAA1wQAIcoCAQDWBAAhzQICAOAEACHlAgEA1gQAIeYCAQDhBAAh5wIBAOEEACHoAgEA4QQAIekCAQDWBAAh6gIBAOEEACHrAgEA4QQAIewCQADYBAAhDbACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB8QIAAADxAgLyAiAAAAAB8wIgAAAAAfQCAgAAAAH1AgIAAAAB9gICAAAAAfcCAgAAAAH4AkAAAAABArYCQAAAAAHkAgEAAAABBLACAQAAAAG2AkAAAAABzwIAAADkAgLiAgEAAAABAwAAABcAIDEAAKUIACAyAADDCAAgGwAAABcAIBEAANsFACASAADcBQAgEwAA3QUAIBQAANAGACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAIBwAAOQFACAqAADDCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIRkRAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFgAA3wUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2wICAOsEACHtAgIA6wQAIe4CAQDhBAAh7wICAOsEACHxAgAA2AXxAiLyAiAA2QUAIfMCIADZBQAh9AICAOAEACH1AgIA4AQAIfYCAgDgBAAh9wICAOAEACH4AkAA2AQAIQWwAgEAAAABtgJAAAAAAdsCAgAAAAHcAgEAAAAB3QIBAAAAAQIAAACwAgAgMQAAxAgAIAMAAACzAgAgMQAAxAgAIDIAAMgIACAHAAAAswIAICoAAMgIACCwAgEA1gQAIbYCQADXBAAh2wICAOsEACHcAgEA1gQAId0CAQDhBAAhBbACAQDWBAAhtgJAANcEACHbAgIA6wQAIdwCAQDWBAAh3QIBAOEEACEPBwAA1QYAIAgAALYGACAJAAC3BgAgDgAAuAYAILYCQAAAAAHKAgEAAAABzQICAAAAAeUCAQAAAAHmAgEAAAAB5wIBAAAAAegCAQAAAAHpAgEAAAAB6gIBAAAAAesCAQAAAAHsAkAAAAABAgAAAC0AIDEAAMkIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAAywgAIAMAAAAVACAxAADJCAAgMgAAzwgAIBEAAAAVACAHAAC0BQAgCAAAtQUAIAkAALYFACAOAAC3BQAgKgAAzwgAILYCQADXBAAhygIBANYEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACEPBwAAtAUAIAgAALUFACAJAAC2BQAgDgAAtwUAILYCQADXBAAhygIBANYEACHNAgIA4AQAIeUCAQDWBAAh5gIBAOEEACHnAgEA4QQAIegCAQDhBAAh6QIBANYEACHqAgEA4QQAIesCAQDhBAAh7AJAANgEACEDAAAAFwAgMQAAywgAIDIAANIIACAbAAAAFwAgEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBoAAOIFACAbAADjBQAgHAAA5AUAICoAANIIACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhGREAANsFACASAADcBQAgEwAA3QUAIBQAANAGACAVAADeBQAgFgAA3wUAIBgAAOAFACAaAADiBQAgGwAA4wUAIBwAAOQFACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHbAgIA6wQAIe0CAgDrBAAh7gIBAOEEACHvAgIA6wQAIfECAADYBfECIvICIADZBQAh8wIgANkFACH0AgIA4AQAIfUCAgDgBAAh9gICAOAEACH3AgIA4AQAIfgCQADYBAAhDwcAANUGACAIAAC2BgAgCQAAtwYAIBAAALkGACC2AkAAAAABygIBAAAAAc0CAgAAAAHlAgEAAAAB5gIBAAAAAecCAQAAAAHoAgEAAAAB6QIBAAAAAeoCAQAAAAHrAgEAAAAB7AJAAAAAAQIAAAAtACAxAADTCAAgAwAAABUAIDEAANMIACAyAADXCAAgEQAAABUAIAcAALQFACAIAAC1BQAgCQAAtgUAIBAAALgFACAqAADXCAAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQ8HAAC0BQAgCAAAtQUAIAkAALYFACAQAAC4BQAgtgJAANcEACHKAgEA1gQAIc0CAgDgBAAh5QIBANYEACHmAgEA4QQAIecCAQDhBAAh6AIBAOEEACHpAgEA1gQAIeoCAQDhBAAh6wIBAOEEACHsAkAA2AQAIQO2AkAAAAABygIBAAAAAc0CAgAAAAEfBAAA7AcAIAUAAO0HACAGAADuBwAgHgAA8AcAICAAAPEHACAhAADyBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAANkIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAYAADBBgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA2wgAIAMAAAAPACAxAADZCAAgMgAA3wgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAeAAD9BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAADfCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAADbCAAgMgAA4ggAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBgAAOAFACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAA4ggAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAYAADgBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAICAAAPEHACAhAADyBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAOMIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGQAAwgYAIBoAAMMGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA5QgAIAMAAAAPACAxAADjCAAgMgAA6QgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgIAAA_gYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACAqAADpCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAgAAD-BgAgIQAA_wYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAADlCAAgMgAA7AgAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAZAADhBQAgGgAA4gUAIBsAAOMFACAcAADkBQAgKgAA7AgAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAgAADxBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAO0IACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAbAADEBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA7wgAIAMAAAAPACAxAADtCAAgMgAA8wgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAiAACABwAgIwAAgQcAICQAAIIHACAqAADzCAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICIAAIAHACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAADvCAAgMgAA9ggAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBsAAOMFACAcAADkBQAgKgAA9ggAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAbAADjBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAgAADxBwAgIQAA8gcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAPcIACAZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgHAAAxQYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAA-QgAIAMAAAAPACAxAAD3CAAgMgAA_QgAICEAAAAPACAEAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAhAAD_BgAgIwAAgQcAICQAAIIHACAqAAD9CAAgsAIBANYEACG2AkAA1wQAIcwCQADXBAAh2gIBAOEEACHbAgIA6wQAIdwCAQDhBAAh-AJAANgEACGPAwEA4QQAIZADIADZBQAhkQMBAOEEACGTAwAA9gaTAyKVAwAA9waVAyKWAyAA2QUAIZcDAQDhBAAhmAMBAOEEACGZA4AAAAABmgNAANgEACGbAwEA4QQAIZwDIAD4BgAhnQMBAOEEACGeA0AA2AQAIZ8DQADYBAAhHwQAAPkGACAFAAD6BgAgBgAA-wYAIB0AAPwGACAeAAD9BgAgIAAA_gYAICEAAP8GACAjAACBBwAgJAAAggcAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIQMAAAAXACAxAAD5CAAgMgAAgAkAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBoAAOIFACAcAADkBQAgKgAAgAkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgHAAA5AUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAAygYAIBIAALwGACATAAC9BgAgFAAAvgYAIBUAAL8GACAWAADABgAgGAAAwQYAIBkAAMIGACAaAADDBgAgGwAAxAYAILACAQAAAAG2AkAAAAABzAJAAAAAAdsCAgAAAAHtAgIAAAAB7gIBAAAAAe8CAgAAAAHxAgAAAPECAvICIAAAAAHzAiAAAAAB9AICAAAAAfUCAgAAAAH2AgIAAAAB9wICAAAAAfgCQAAAAAECAAAAGgAgMQAAgQkAIB8EAADsBwAgBQAA7QcAIAYAAO4HACAdAADvBwAgHgAA8AcAICAAAPEHACAhAADyBwAgIgAA8wcAICQAAPUHACCwAgEAAAABtgJAAAAAAcwCQAAAAAHaAgEAAAAB2wICAAAAAdwCAQAAAAH4AkAAAAABjwMBAAAAAZADIAAAAAGRAwEAAAABkwMAAACTAwKVAwAAAJUDApYDIAAAAAGXAwEAAAABmAMBAAAAAZkDgAAAAAGaA0AAAAABmwMBAAAAAZwDIAAAAAGdAwEAAAABngNAAAAAAZ8DQAAAAAECAAAAAQAgMQAAgwkAIAMAAAAXACAxAACBCQAgMgAAhwkAIBsAAAAXACARAADbBQAgEgAA3AUAIBMAAN0FACAUAADQBgAgFQAA3gUAIBYAAN8FACAYAADgBQAgGQAA4QUAIBoAAOIFACAbAADjBQAgKgAAhwkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEZEQAA2wUAIBIAANwFACATAADdBQAgFAAA0AYAIBUAAN4FACAWAADfBQAgGAAA4AUAIBkAAOEFACAaAADiBQAgGwAA4wUAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdsCAgDrBAAh7QICAOsEACHuAgEA4QQAIe8CAgDrBAAh8QIAANgF8QIi8gIgANkFACHzAiAA2QUAIfQCAgDgBAAh9QICAOAEACH2AgIA4AQAIfcCAgDgBAAh-AJAANgEACEDAAAADwAgMQAAgwkAIDIAAIoJACAhAAAADwAgBAAA-QYAIAUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAgAAD-BgAgIQAA_wYAICIAAIAHACAkAACCBwAgKgAAigkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICAAAP4GACAhAAD_BgAgIgAAgAcAICQAAIIHACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHaAgEA4QQAIdsCAgDrBAAh3AIBAOEEACH4AkAA2AQAIY8DAQDhBAAhkAMgANkFACGRAwEA4QQAIZMDAAD2BpMDIpUDAAD3BpUDIpYDIADZBQAhlwMBAOEEACGYAwEA4QQAIZkDgAAAAAGaA0AA2AQAIZsDAQDhBAAhnAMgAPgGACGdAwEA4QQAIZ4DQADYBAAhnwNAANgEACEfBAAA7AcAIAUAAO0HACAGAADuBwAgHQAA7wcAIB4AAPAHACAhAADyBwAgIgAA8wcAICMAAPQHACAkAAD1BwAgsAIBAAAAAbYCQAAAAAHMAkAAAAAB2gIBAAAAAdsCAgAAAAHcAgEAAAAB-AJAAAAAAY8DAQAAAAGQAyAAAAABkQMBAAAAAZMDAAAAkwMClQMAAACVAwKWAyAAAAABlwMBAAAAAZgDAQAAAAGZA4AAAAABmgNAAAAAAZsDAQAAAAGcAyAAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABAgAAAAEAIDEAAIsJACADAAAADwAgMQAAiwkAIDIAAI8JACAhAAAADwAgBAAA-QYAIAUAAPoGACAGAAD7BgAgHQAA_AYAIB4AAP0GACAhAAD_BgAgIgAAgAcAICMAAIEHACAkAACCBwAgKgAAjwkAILACAQDWBAAhtgJAANcEACHMAkAA1wQAIdoCAQDhBAAh2wICAOsEACHcAgEA4QQAIfgCQADYBAAhjwMBAOEEACGQAyAA2QUAIZEDAQDhBAAhkwMAAPYGkwMilQMAAPcGlQMilgMgANkFACGXAwEA4QQAIZgDAQDhBAAhmQOAAAAAAZoDQADYBAAhmwMBAOEEACGcAyAA-AYAIZ0DAQDhBAAhngNAANgEACGfA0AA2AQAIR8EAAD5BgAgBQAA-gYAIAYAAPsGACAdAAD8BgAgHgAA_QYAICEAAP8GACAiAACABwAgIwAAgQcAICQAAIIHACCwAgEA1gQAIbYCQADXBAAhzAJAANcEACHaAgEA4QQAIdsCAgDrBAAh3AIBAOEEACH4AkAA2AQAIY8DAQDhBAAhkAMgANkFACGRAwEA4QQAIZMDAAD2BpMDIpUDAAD3BpUDIpYDIADZBQAhlwMBAOEEACGYAwEA4QQAIZkDgAAAAAGaA0AA2AQAIZsDAQDhBAAhnAMgAPgGACGdAwEA4QQAIZ4DQADYBAAhnwNAANgEACELBAYCBQoDBg4EDAAUHRQFHkwNIFASIVEOIlIPI1MQJFcTAQMAAQEDAAEBAxABAgMAAQcABgwMABERFgcSKQYTKgYUKwcVLgcWLwUYMw0ZNQsaOQ4bPQ8cQhAGBwAGCBgGCRsGDAAMDh8IECULAgoABw0ACQILIAgMAAoBCyEAAgcABg8ABwMJJgAOJwAQKAACBwAGFzQBAgMAAQcABgIDPgEHAAYCAwABB0MGCBNEABVFABZGABhHABlIABpJABtKABxLAAEfAAEBAwABCgRYAAVZAAZaAB1bAB5cACBdACFeACJfACNgACRhAAAAAAUMABk3ABo4ABs5ABw6AB0AAAAAAAUMABk3ABo4ABs5ABw6AB0BAwABAQMAAQMMACI5ACM6ACQAAAADDAAiOQAjOgAkAQMAAQEDAAEDDAApOQAqOgArAAAAAwwAKTkAKjoAKwEDrgEBAQO0AQEDDAAwOQAxOgAyAAAAAwwAMDkAMToAMgEDAAEBAwABBQwANzcAODgAOTkAOjoAOwAAAAAABQwANzcAODgAOTkAOjoAOwMR3AEHEt0BBhTeAQcDEeQBBxLlAQYU5gEHBQwAQDcAQTgAQjkAQzoARAAAAAAABQwAQDcAQTgAQjkAQzoARAEHAAYBBwAGBQwASTcASjgASzkATDoATQAAAAAABQwASTcASjgASzkATDoATQIKAAcNAAkCCgAHDQAJBQwAUjcAUzgAVDkAVToAVgAAAAAABQwAUjcAUzgAVDkAVToAVgIHAAYPAAcCBwAGDwAHBQwAWzcAXDgAXTkAXjoAXwAAAAAABQwAWzcAXDgAXTkAXjoAXwAABQwAZDcAZTgAZjkAZzoAaAAAAAAABQwAZDcAZTgAZjkAZzoAaAIDAAEHAAYCAwABBwAGAwwAbTkAbjoAbwAAAAMMAG05AG46AG8CBwAGF-kCAQIHAAYX7wIBAwwAdDkAdToAdgAAAAMMAHQ5AHU6AHYCAwABBwAGAgMAAQcABgMMAHs5AHw6AH0AAAADDAB7OQB8OgB9AgOXAwEHAAYCA50DAQcABgUMAIIBNwCDATgAhAE5AIUBOgCGAQAAAAAABQwAggE3AIMBOACEATkAhQE6AIYBAgMAAQevAwYCAwABB7UDBgUMAIsBNwCMATgAjQE5AI4BOgCPAQAAAAAABQwAiwE3AIwBOACNATkAjgE6AI8BAR8AAQEfAAEDDACUATkAlQE6AJYBAAAAAwwAlAE5AJUBOgCWASUCASZiASdkAShlASlmAStoASxqFS1rFi5tAS9vFTBwFzNxATRyATVzFTt2GDx3Hj14Aj55Aj96AkB7AkF8AkJ-AkOAARVEgQEfRYMBAkaFARVHhgEgSIcBAkmIAQJKiQEVS4wBIUyNASVNjgEDTo8BA0-QAQNQkQEDUZIBA1KUAQNTlgEVVJcBJlWZAQNWmwEVV5wBJ1idAQNZngEDWp8BFVuiAShcowEsXaQBBF6lAQRfpgEEYKcBBGGoAQRiqgEEY6wBFWStAS1lsAEEZrIBFWezAS5otQEEabYBBGq3ARVrugEvbLsBM228ARNuvQETb74BE3C_ARNxwAETcsIBE3PEARV0xQE0dccBE3bJARV3ygE1eMsBE3nMARN6zQEVe9ABNnzRATx90gEGftMBBn_UAQaAAdUBBoEB1gEGggHYAQaDAdoBFYQB2wE9hQHgAQaGAeIBFYcB4wE-iAHnAQaJAegBBooB6QEViwHsAT-MAe0BRY0B7gEHjgHvAQePAfABB5AB8QEHkQHyAQeSAfQBB5MB9gEVlAH3AUaVAfkBB5YB-wEVlwH8AUeYAf0BB5kB_gEHmgH_ARWbAYICSJwBgwJOnQGEAgieAYUCCJ8BhgIIoAGHAgihAYgCCKIBigIIowGMAhWkAY0CT6UBjwIIpgGRAhWnAZICUKgBkwIIqQGUAgiqAZUCFasBmAJRrAGZAletAZoCC64BmwILrwGcAguwAZ0CC7EBngILsgGgAguzAaICFbQBowJYtQGlAgu2AacCFbcBqAJZuAGpAgu5AaoCC7oBqwIVuwGuAlq8Aa8CYL0BsQIJvgGyAgm_AbUCCcABtgIJwQG3AgnCAbkCCcMBuwIVxAG8AmHFAb4CCcYBwAIVxwHBAmLIAcICCckBwwIJygHEAhXLAccCY8wByAJpzQHJAgXOAcoCBc8BywIF0AHMAgXRAc0CBdIBzwIF0wHRAhXUAdICatUB1AIF1gHWAhXXAdcCa9gB2AIF2QHZAgXaAdoCFdsB3QJs3AHeAnDdAd8CDd4B4AIN3wHhAg3gAeICDeEB4wIN4gHlAg3jAecCFeQB6AJx5QHrAg3mAe0CFecB7gJy6AHwAg3pAfECDeoB8gIV6wH1AnPsAfYCd-0B9wIO7gH4Ag7vAfkCDvAB-gIO8QH7Ag7yAf0CDvMB_wIV9AGAA3j1AYIDDvYBhAMV9wGFA3n4AYYDDvkBhwMO-gGIAxX7AYsDevwBjAN-_QGNAw_-AY4DD_8BjwMPgAKQAw-BApEDD4ICkwMPgwKVAxWEApYDf4UCmQMPhgKbAxWHApwDgAGIAp4DD4kCnwMPigKgAxWLAqMDgQGMAqQDhwGNAqUDEI4CpgMQjwKnAxCQAqgDEJECqQMQkgKrAxCTAq0DFZQCrgOIAZUCsQMQlgKzAxWXArQDiQGYArYDEJkCtwMQmgK4AxWbArsDigGcArwDkAGdAr0DEp4CvgMSnwK_AxKgAsADEqECwQMSogLDAxKjAsUDFaQCxgORAaUCyAMSpgLKAxWnAssDkgGoAswDEqkCzQMSqgLOAxWrAtEDkwGsAtIDlwE" + strings: JSON.parse("[\"where\",\"orderBy\",\"cursor\",\"user\",\"accounts\",\"sessions\",\"verifications\",\"model\",\"latestOfModel\",\"parentOfModels\",\"modelVersion\",\"modelVersions\",\"_count\",\"tag\",\"tags\",\"taggedVersion\",\"taggedAdditionalFiles\",\"latestVersion\",\"parentModel\",\"childModels\",\"parentVersion\",\"versions\",\"authors\",\"nonMemberContributors\",\"granteeUser\",\"permissions\",\"additionalFiles\",\"likes\",\"interactions\",\"drafts\",\"authoredModels\",\"grantedPermissions\",\"actor\",\"events\",\"modelLikes\",\"modelInteractions\",\"modelDrafts\",\"passkeys\",\"User.findUnique\",\"User.findUniqueOrThrow\",\"User.findFirst\",\"User.findFirstOrThrow\",\"User.findMany\",\"data\",\"User.createOne\",\"User.createMany\",\"User.createManyAndReturn\",\"User.updateOne\",\"User.updateMany\",\"User.updateManyAndReturn\",\"create\",\"update\",\"User.upsertOne\",\"User.deleteOne\",\"User.deleteMany\",\"having\",\"_avg\",\"_sum\",\"_min\",\"_max\",\"User.groupBy\",\"User.aggregate\",\"Account.findUnique\",\"Account.findUniqueOrThrow\",\"Account.findFirst\",\"Account.findFirstOrThrow\",\"Account.findMany\",\"Account.createOne\",\"Account.createMany\",\"Account.createManyAndReturn\",\"Account.updateOne\",\"Account.updateMany\",\"Account.updateManyAndReturn\",\"Account.upsertOne\",\"Account.deleteOne\",\"Account.deleteMany\",\"Account.groupBy\",\"Account.aggregate\",\"Session.findUnique\",\"Session.findUniqueOrThrow\",\"Session.findFirst\",\"Session.findFirstOrThrow\",\"Session.findMany\",\"Session.createOne\",\"Session.createMany\",\"Session.createManyAndReturn\",\"Session.updateOne\",\"Session.updateMany\",\"Session.updateManyAndReturn\",\"Session.upsertOne\",\"Session.deleteOne\",\"Session.deleteMany\",\"Session.groupBy\",\"Session.aggregate\",\"Verification.findUnique\",\"Verification.findUniqueOrThrow\",\"Verification.findFirst\",\"Verification.findFirstOrThrow\",\"Verification.findMany\",\"Verification.createOne\",\"Verification.createMany\",\"Verification.createManyAndReturn\",\"Verification.updateOne\",\"Verification.updateMany\",\"Verification.updateManyAndReturn\",\"Verification.upsertOne\",\"Verification.deleteOne\",\"Verification.deleteMany\",\"Verification.groupBy\",\"Verification.aggregate\",\"Passkey.findUnique\",\"Passkey.findUniqueOrThrow\",\"Passkey.findFirst\",\"Passkey.findFirstOrThrow\",\"Passkey.findMany\",\"Passkey.createOne\",\"Passkey.createMany\",\"Passkey.createManyAndReturn\",\"Passkey.updateOne\",\"Passkey.updateMany\",\"Passkey.updateManyAndReturn\",\"Passkey.upsertOne\",\"Passkey.deleteOne\",\"Passkey.deleteMany\",\"Passkey.groupBy\",\"Passkey.aggregate\",\"Model.findUnique\",\"Model.findUniqueOrThrow\",\"Model.findFirst\",\"Model.findFirstOrThrow\",\"Model.findMany\",\"Model.createOne\",\"Model.createMany\",\"Model.createManyAndReturn\",\"Model.updateOne\",\"Model.updateMany\",\"Model.updateManyAndReturn\",\"Model.upsertOne\",\"Model.deleteOne\",\"Model.deleteMany\",\"Model.groupBy\",\"Model.aggregate\",\"ModelVersion.findUnique\",\"ModelVersion.findUniqueOrThrow\",\"ModelVersion.findFirst\",\"ModelVersion.findFirstOrThrow\",\"ModelVersion.findMany\",\"ModelVersion.createOne\",\"ModelVersion.createMany\",\"ModelVersion.createManyAndReturn\",\"ModelVersion.updateOne\",\"ModelVersion.updateMany\",\"ModelVersion.updateManyAndReturn\",\"ModelVersion.upsertOne\",\"ModelVersion.deleteOne\",\"ModelVersion.deleteMany\",\"ModelVersion.groupBy\",\"ModelVersion.aggregate\",\"ModelVersionTag.findUnique\",\"ModelVersionTag.findUniqueOrThrow\",\"ModelVersionTag.findFirst\",\"ModelVersionTag.findFirstOrThrow\",\"ModelVersionTag.findMany\",\"ModelVersionTag.createOne\",\"ModelVersionTag.createMany\",\"ModelVersionTag.createManyAndReturn\",\"ModelVersionTag.updateOne\",\"ModelVersionTag.updateMany\",\"ModelVersionTag.updateManyAndReturn\",\"ModelVersionTag.upsertOne\",\"ModelVersionTag.deleteOne\",\"ModelVersionTag.deleteMany\",\"ModelVersionTag.groupBy\",\"ModelVersionTag.aggregate\",\"ModelAdditionalFile.findUnique\",\"ModelAdditionalFile.findUniqueOrThrow\",\"ModelAdditionalFile.findFirst\",\"ModelAdditionalFile.findFirstOrThrow\",\"ModelAdditionalFile.findMany\",\"ModelAdditionalFile.createOne\",\"ModelAdditionalFile.createMany\",\"ModelAdditionalFile.createManyAndReturn\",\"ModelAdditionalFile.updateOne\",\"ModelAdditionalFile.updateMany\",\"ModelAdditionalFile.updateManyAndReturn\",\"ModelAdditionalFile.upsertOne\",\"ModelAdditionalFile.deleteOne\",\"ModelAdditionalFile.deleteMany\",\"ModelAdditionalFile.groupBy\",\"ModelAdditionalFile.aggregate\",\"Tag.findUnique\",\"Tag.findUniqueOrThrow\",\"Tag.findFirst\",\"Tag.findFirstOrThrow\",\"Tag.findMany\",\"Tag.createOne\",\"Tag.createMany\",\"Tag.createManyAndReturn\",\"Tag.updateOne\",\"Tag.updateMany\",\"Tag.updateManyAndReturn\",\"Tag.upsertOne\",\"Tag.deleteOne\",\"Tag.deleteMany\",\"Tag.groupBy\",\"Tag.aggregate\",\"ModelAuthor.findUnique\",\"ModelAuthor.findUniqueOrThrow\",\"ModelAuthor.findFirst\",\"ModelAuthor.findFirstOrThrow\",\"ModelAuthor.findMany\",\"ModelAuthor.createOne\",\"ModelAuthor.createMany\",\"ModelAuthor.createManyAndReturn\",\"ModelAuthor.updateOne\",\"ModelAuthor.updateMany\",\"ModelAuthor.updateManyAndReturn\",\"ModelAuthor.upsertOne\",\"ModelAuthor.deleteOne\",\"ModelAuthor.deleteMany\",\"ModelAuthor.groupBy\",\"ModelAuthor.aggregate\",\"NonMemberContributor.findUnique\",\"NonMemberContributor.findUniqueOrThrow\",\"NonMemberContributor.findFirst\",\"NonMemberContributor.findFirstOrThrow\",\"NonMemberContributor.findMany\",\"NonMemberContributor.createOne\",\"NonMemberContributor.createMany\",\"NonMemberContributor.createManyAndReturn\",\"NonMemberContributor.updateOne\",\"NonMemberContributor.updateMany\",\"NonMemberContributor.updateManyAndReturn\",\"NonMemberContributor.upsertOne\",\"NonMemberContributor.deleteOne\",\"NonMemberContributor.deleteMany\",\"NonMemberContributor.groupBy\",\"NonMemberContributor.aggregate\",\"ModelPermission.findUnique\",\"ModelPermission.findUniqueOrThrow\",\"ModelPermission.findFirst\",\"ModelPermission.findFirstOrThrow\",\"ModelPermission.findMany\",\"ModelPermission.createOne\",\"ModelPermission.createMany\",\"ModelPermission.createManyAndReturn\",\"ModelPermission.updateOne\",\"ModelPermission.updateMany\",\"ModelPermission.updateManyAndReturn\",\"ModelPermission.upsertOne\",\"ModelPermission.deleteOne\",\"ModelPermission.deleteMany\",\"ModelPermission.groupBy\",\"ModelPermission.aggregate\",\"ModelLike.findUnique\",\"ModelLike.findUniqueOrThrow\",\"ModelLike.findFirst\",\"ModelLike.findFirstOrThrow\",\"ModelLike.findMany\",\"ModelLike.createOne\",\"ModelLike.createMany\",\"ModelLike.createManyAndReturn\",\"ModelLike.updateOne\",\"ModelLike.updateMany\",\"ModelLike.updateManyAndReturn\",\"ModelLike.upsertOne\",\"ModelLike.deleteOne\",\"ModelLike.deleteMany\",\"ModelLike.groupBy\",\"ModelLike.aggregate\",\"ModelInteraction.findUnique\",\"ModelInteraction.findUniqueOrThrow\",\"ModelInteraction.findFirst\",\"ModelInteraction.findFirstOrThrow\",\"ModelInteraction.findMany\",\"ModelInteraction.createOne\",\"ModelInteraction.createMany\",\"ModelInteraction.createManyAndReturn\",\"ModelInteraction.updateOne\",\"ModelInteraction.updateMany\",\"ModelInteraction.updateManyAndReturn\",\"ModelInteraction.upsertOne\",\"ModelInteraction.deleteOne\",\"ModelInteraction.deleteMany\",\"ModelInteraction.groupBy\",\"ModelInteraction.aggregate\",\"ModelDraft.findUnique\",\"ModelDraft.findUniqueOrThrow\",\"ModelDraft.findFirst\",\"ModelDraft.findFirstOrThrow\",\"ModelDraft.findMany\",\"ModelDraft.createOne\",\"ModelDraft.createMany\",\"ModelDraft.createManyAndReturn\",\"ModelDraft.updateOne\",\"ModelDraft.updateMany\",\"ModelDraft.updateManyAndReturn\",\"ModelDraft.upsertOne\",\"ModelDraft.deleteOne\",\"ModelDraft.deleteMany\",\"ModelDraft.groupBy\",\"ModelDraft.aggregate\",\"Event.findUnique\",\"Event.findUniqueOrThrow\",\"Event.findFirst\",\"Event.findFirstOrThrow\",\"Event.findMany\",\"Event.createOne\",\"Event.createMany\",\"Event.createManyAndReturn\",\"Event.updateOne\",\"Event.updateMany\",\"Event.updateManyAndReturn\",\"Event.upsertOne\",\"Event.deleteOne\",\"Event.deleteMany\",\"Event.groupBy\",\"Event.aggregate\",\"AND\",\"OR\",\"NOT\",\"id\",\"type\",\"actorId\",\"resourceType\",\"resourceId\",\"payload\",\"createdAt\",\"processedAt\",\"equals\",\"in\",\"notIn\",\"lt\",\"lte\",\"gt\",\"gte\",\"not\",\"string_contains\",\"string_starts_with\",\"string_ends_with\",\"array_starts_with\",\"array_ends_with\",\"array_contains\",\"contains\",\"startsWith\",\"endsWith\",\"userId\",\"modelId\",\"schemaVersion\",\"updatedAt\",\"versionNumber\",\"ModelInteractionKind\",\"kind\",\"sessionId\",\"ipHash\",\"userAgent\",\"referer\",\"geo\",\"cookie\",\"granteeUserId\",\"PermissionLevel\",\"permissionLevel\",\"legacyId\",\"email\",\"name\",\"collaboratorType\",\"addedByUserId\",\"AuthorRole\",\"role\",\"displayName\",\"every\",\"some\",\"none\",\"taggedVersionNumber\",\"fileKey\",\"ModelFileKind\",\"tagId\",\"title\",\"description\",\"changeSummary\",\"previewImageFileKey\",\"netlogoFileKey\",\"netlogoVersion\",\"infoTab\",\"finalizedAt\",\"latestVersionNumber\",\"parentModelId\",\"parentVersionNumber\",\"ModelVisibility\",\"visibility\",\"isEndorsed\",\"isLibraryModel\",\"viewCount\",\"runCount\",\"downloadCount\",\"shareCount\",\"deletedAt\",\"publicKey\",\"credentialID\",\"counter\",\"deviceType\",\"backedUp\",\"transports\",\"aaguid\",\"identifier\",\"value\",\"expiresAt\",\"token\",\"ipAddress\",\"impersonatedBy\",\"accountId\",\"providerId\",\"accessToken\",\"refreshToken\",\"accessTokenExpiresAt\",\"refreshTokenExpiresAt\",\"scope\",\"idToken\",\"password\",\"emailVerified\",\"image\",\"SystemRole\",\"systemRole\",\"UserKind\",\"userKind\",\"isProfilePublic\",\"bio\",\"country\",\"socialLinks\",\"dob\",\"affiliation\",\"banned\",\"banReason\",\"banExpires\",\"onboardedAt\",\"modelId_userId\",\"modelId_granteeUserId\",\"modelId_versionNumber\",\"modelId_versionNumber_tagId\",\"id_latestVersionNumber\",\"is\",\"isNot\",\"connectOrCreate\",\"upsert\",\"createMany\",\"set\",\"disconnect\",\"delete\",\"connect\",\"updateMany\",\"deleteMany\",\"increment\",\"decrement\",\"multiply\",\"divide\"]"), + graph: "yQmhAZACIwQAAOgEACAFAADpBAAgBgAA6gQAIB4AANsEACAfAADdBAAgIQAA6wQAICIAAN4EACAjAADfBAAgJAAA4AQAICUAAOwEACC-AgAA5AQAML8CAAAPABDAAgAA5AQAMMECAQAAAAHHAkAAmwQAId0CQACbBAAh6gICAAAAAesCAQAAAAHsAgEAmgQAIfACAQCaBAAhjANAALsEACGjAyAAugQAIaQDAQCaBAAhpgMAAOUEpgMiqAMAAOYEqAMiqQMgALoEACGqAwEAmgQAIasDAQCaBAAhrAMAAMMEACCtA0AAuwQAIa4DAQCaBAAhrwMgAOcEACGwAwEAmgQAIbEDQAC7BAAhsgNAALsEACEBAAAAAQAgEQMAALwEACC-AgAA7wQAML8CAAADABDAAgAA7wQAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhCAMAALMIACCcAwAA8AQAIJ0DAADwBAAgngMAAPAEACCfAwAA8AQAIKADAADwBAAgoQMAAPAEACCiAwAA8AQAIBEDAAC8BAAgvgIAAO8EADC_AgAAAwAQwAIAAO8EADDBAgEAAAABxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhAwAAAAMAIAEAAAQAMAIAAAUAIA0DAAC8BAAgvgIAAO4EADC_AgAABwAQwAIAAO4EADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHdAkAAmwQAIeMCAQCaBAAhlgNAAJsEACGXAwEAmAQAIZgDAQCaBAAhmQMBAJoEACEEAwAAswgAIOMCAADwBAAgmAMAAPAEACCZAwAA8AQAIA0DAAC8BAAgvgIAAO4EADC_AgAABwAQwAIAAO4EADDBAgEAAAABxwJAAJsEACHaAgEAmAQAId0CQACbBAAh4wIBAJoEACGWA0AAmwQAIZcDAQAAAAGYAwEAmgQAIZkDAQCaBAAhAwAAAAcAIAEAAAgAMAIAAAkAIAsDAADFBAAgvgIAAO0EADC_AgAACwAQwAIAAO0EADDBAgEAmAQAIccCQAC7BAAh2gIBAJoEACHdAkAAuwQAIZQDAQCYBAAhlQMBAJgEACGWA0AAmwQAIQQDAACzCAAgxwIAAPAEACDaAgAA8AQAIN0CAADwBAAgCwMAAMUEACC-AgAA7QQAML8CAAALABDAAgAA7QQAMMECAQAAAAHHAkAAuwQAIdoCAQCaBAAh3QJAALsEACGUAwEAmAQAIZUDAQCYBAAhlgNAAJsEACEDAAAACwAgAQAADAAwAgAADQAgIwQAAOgEACAFAADpBAAgBgAA6gQAIB4AANsEACAfAADdBAAgIQAA6wQAICIAAN4EACAjAADfBAAgJAAA4AQAICUAAOwEACC-AgAA5AQAML8CAAAPABDAAgAA5AQAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAh6wIBAJoEACHsAgEAmgQAIfACAQCaBAAhjANAALsEACGjAyAAugQAIaQDAQCaBAAhpgMAAOUEpgMiqAMAAOYEqAMiqQMgALoEACGqAwEAmgQAIasDAQCaBAAhrAMAAMMEACCtA0AAuwQAIa4DAQCaBAAhrwMgAOcEACGwAwEAmgQAIbEDQAC7BAAhsgNAALsEACEBAAAADwAgCgMAALwEACAHAADEBAAgvgIAAOIEADC_AgAAEQAQwAIAAOIEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACHtAgEAmgQAIfACAADjBPACIgMDAACzCAAgBwAAtAgAIO0CAADwBAAgCwMAALwEACAHAADEBAAgvgIAAOIEADC_AgAAEQAQwAIAAOIEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACHtAgEAmgQAIfACAADjBPACIrMDAADhBAAgAwAAABEAIAEAABIAMAIAABMAIBMHAADEBAAgCAAAwAQAIAkAAM4EACAOAACcBAAgEAAAzwQAIL4CAADNBAAwvwIAABUAEMACAADNBAAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-QIBAJgEACH6AgEAmgQAIfsCAQCaBAAh_AIBAJoEACH9AgEAmAQAIf4CAQCaBAAh_wIBAJoEACGAA0AAuwQAIQEAAAAVACAeEQAA2QQAIBIAAMAEACATAADOBAAgFAAA2QQAIBUAANoEACAWAADbBAAgFwAA3AQAIBkAAN0EACAaAADPBAAgGwAA3gQAIBwAAN8EACAdAADgBAAgvgIAANcEADC_AgAAFwAQwAIAANcEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhAQAAABcAIBERAAC3CAAgEgAAtAgAIBMAALUIACAUAAC3CAAgFQAAuQgAIBYAAKwIACAXAAC6CAAgGQAArQgAIBoAALYIACAbAACvCAAgHAAAsAgAIB0AALEIACDqAgAA8AQAIIEDAADwBAAgggMAAPAEACCDAwAA8AQAIIwDAADwBAAgHxEAANkEACASAADABAAgEwAAzgQAIBQAANkEACAVAADaBAAgFgAA2wQAIBcAANwEACAZAADdBAAgGgAAzwQAIBsAAN4EACAcAADfBAAgHQAA4AQAIL4CAADXBAAwvwIAABcAEMACAADXBAAwwQIBAAAAAccCQACbBAAh3QJAAJsEACHqAgIAAAABgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACG3AwAA1gQAIAMAAAAXACABAAAZADACAAAaACAJCgAA0gQAIA0AANUEACC-AgAA1AQAML8CAAAcABDAAgAA1AQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfgCAQCYBAAhAgoAALcIACANAAC4CAAgCgoAANIEACANAADVBAAgvgIAANQEADC_AgAAHAAQwAIAANQEADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH4AgEAmAQAIbYDAADTBAAgAwAAABwAIAEAAB0AMAIAAB4AIAMAAAAcACABAAAdADACAAAeACABAAAAHAAgCwcAAMQEACAPAADSBAAgvgIAANAEADC_AgAAIgAQwAIAANAEADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHgAgAA0QT4AiL1AgIAuQQAIfYCAQCYBAAhAgcAALQIACAPAAC3CAAgCwcAAMQEACAPAADSBAAgvgIAANAEADC_AgAAIgAQwAIAANAEADDBAgEAAAABxwJAAJsEACHbAgEAmAQAIeACAADRBPgCIvUCAgC5BAAh9gIBAJgEACEDAAAAIgAgAQAAIwAwAgAAJAAgAQAAABcAIAEAAAAcACABAAAAIgAgAQAAABcAIAMAAAAXACABAAAZADACAAAaACABAAAAFQAgCwcAALQIACAIAAC0CAAgCQAAtQgAIA4AAMIFACAQAAC2CAAg-gIAAPAEACD7AgAA8AQAIPwCAADwBAAg_gIAAPAEACD_AgAA8AQAIIADAADwBAAgFAcAAMQEACAIAADABAAgCQAAzgQAIA4AAJwEACAQAADPBAAgvgIAAM0EADC_AgAAFQAQwAIAAM0EADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH5AgEAmAQAIfoCAQCaBAAh-wIBAJoEACH8AgEAmgQAIf0CAQCYBAAh_gIBAJoEACH_AgEAmgQAIYADQAC7BAAhtQMAAMwEACADAAAAFQAgAQAALAAwAgAALQAgAwAAABEAIAEAABIAMAIAABMAIAwHAADEBAAgvgIAAMsEADC_AgAAMAAQwAIAAMsEADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHqAgIAuQQAIesCAQCaBAAh7AIBAJoEACHtAgEAmgQAIe4CAQCaBAAhBQcAALQIACDrAgAA8AQAIOwCAADwBAAg7QIAAPAEACDuAgAA8AQAIAwHAADEBAAgvgIAAMsEADC_AgAAMAAQwAIAAMsEADDBAgEAAAABxwJAAJsEACHbAgEAmAQAIeoCAgAAAAHrAgEAmgQAIewCAQCaBAAh7QIBAJoEACHuAgEAmgQAIQMAAAAwACABAAAxADACAAAyACAKBwAAxAQAIBgAAMUEACC-AgAAyQQAML8CAAA0ABDAAgAAyQQAMMECAQCYBAAhxwJAAJsEACHbAgEAmAQAIecCAQCaBAAh6QIAAMoE6QIiAwcAALQIACAYAACzCAAg5wIAAPAEACALBwAAxAQAIBgAAMUEACC-AgAAyQQAML8CAAA0ABDAAgAAyQQAMMECAQAAAAHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiK0AwAAyAQAIAMAAAA0ACABAAA1ADACAAA2ACABAAAADwAgAwAAACIAIAEAACMAMAIAACQAIAgDAAC8BAAgBwAAxAQAIL4CAADHBAAwvwIAADoAEMACAADHBAAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAhAgMAALMIACAHAAC0CAAgCQMAALwEACAHAADEBAAgvgIAAMcEADC_AgAAOgAQwAIAAMcEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACGzAwAAxgQAIAMAAAA6ACABAAA7ADACAAA8ACARAwAAxQQAIAcAAMQEACC-AgAAwQQAML8CAAA-ABDAAgAAwQQAMMECAQCYBAAhxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEKAwAAswgAIAcAALQIACDaAgAA8AQAIN4CAADwBAAg4QIAAPAEACDiAgAA8AQAIOMCAADwBAAg5AIAAPAEACDlAgAA8AQAIOYCAADwBAAgEQMAAMUEACAHAADEBAAgvgIAAMEEADC_AgAAPgAQwAIAAMEEADDBAgEAAAABxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEDAAAAPgAgAQAAPwAwAgAAQAAgAQAAAA8AIAwDAAC8BAAgBwAAwAQAICsAAL4EACC-AgAAvwQAML8CAABDABDAAgAAvwQAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAIdsCAQCaBAAh3AICALkEACHdAkAAmwQAIQMDAACzCAAgBwAAtAgAINsCAADwBAAgDAMAALwEACAHAADABAAgKwAAvgQAIL4CAAC_BAAwvwIAAEMAEMACAAC_BAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACEDAAAAQwAgAQAARAAwAgAARQAgAQAAABcAIAEAAAAXACABAAAAFQAgAQAAABEAIAEAAAAwACABAAAANAAgAQAAACIAIAEAAAA6ACABAAAAPgAgAQAAAEMAIAMAAAA0ACABAAA1ADACAAA2ACAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAJgEACHCAgEAmAQAIcMCAQCYBAAhxAIBAJgEACHFAgEAmAQAIcYCAAC-BAAgxwJAAJsEACHIAkAAuwQAIQIgAACzCAAgyAIAAPAEACAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAAAAAcICAQCYBAAhwwIBAJgEACHEAgEAmAQAIcUCAQCYBAAhxgIAAL4EACDHAkAAmwQAIcgCQAC7BAAhAwAAAFIAIAEAAFMAMAIAAFQAIAMAAAA6ACABAAA7ADACAAA8ACADAAAAPgAgAQAAPwAwAgAAQAAgAwAAAEMAIAEAAEQAMAIAAEUAIA8DAAC8BAAgvgIAALgEADC_AgAAWQAQwAIAALgEADDBAgEAmAQAIccCQAC7BAAh2gIBAJgEACHsAgEAmgQAIY0DAQCYBAAhjgMBAJgEACGPAwIAuQQAIZADAQCYBAAhkQMgALoEACGSAwEAmgQAIZMDAQCaBAAhBQMAALMIACDHAgAA8AQAIOwCAADwBAAgkgMAAPAEACCTAwAA8AQAIA8DAAC8BAAgvgIAALgEADC_AgAAWQAQwAIAALgEADDBAgEAAAABxwJAALsEACHaAgEAmAQAIewCAQCaBAAhjQMBAJgEACGOAwEAmAQAIY8DAgC5BAAhkAMBAJgEACGRAyAAugQAIZIDAQCaBAAhkwMBAJoEACEDAAAAWQAgAQAAWgAwAgAAWwAgAQAAAAMAIAEAAAAHACABAAAACwAgAQAAABEAIAEAAAA0ACABAAAAUgAgAQAAADoAIAEAAAA-ACABAAAAQwAgAQAAAFkAIAEAAAABACAZBAAAqQgAIAUAAKoIACAGAACrCAAgHgAArAgAIB8AAK0IACAhAACuCAAgIgAArwgAICMAALAIACAkAACxCAAgJQAAsggAIOoCAADwBAAg6wIAAPAEACDsAgAA8AQAIPACAADwBAAgjAMAAPAEACCkAwAA8AQAIKoDAADwBAAgqwMAAPAEACCsAwAA8AQAIK0DAADwBAAgrgMAAPAEACCvAwAA8AQAILADAADwBAAgsQMAAPAEACCyAwAA8AQAIAMAAAAPACABAABoADACAAABACADAAAADwAgAQAAaAAwAgAAAQAgAwAAAA8AIAEAAGgAMAIAAAEAICAEAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAiAAClCAAgIwAApggAICQAAKcIACAlAACoCAAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAesCAQAAAAHsAgEAAAAB8AIBAAAAAYwDQAAAAAGjAyAAAAABpAMBAAAAAaYDAAAApgMCqAMAAACoAwKpAyAAAAABqgMBAAAAAasDAQAAAAGsA4AAAAABrQNAAAAAAa4DAQAAAAGvAyAAAAABsAMBAAAAAbEDQAAAAAGyA0AAAAABASsAAGwAIBbBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAEBKwAAbgAwASsAAG4AMCAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhAgAAAAEAICsAAHEAIBbBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACECAAAADwAgKwAAcwAgAgAAAA8AICsAAHMAIAMAAAABACAyAABsACAzAABxACABAAAAAQAgAQAAAA8AIBQMAACkBwAgOAAApQcAIDkAAKgHACA6AACnBwAgOwAApgcAIOoCAADwBAAg6wIAAPAEACDsAgAA8AQAIPACAADwBAAgjAMAAPAEACCkAwAA8AQAIKoDAADwBAAgqwMAAPAEACCsAwAA8AQAIK0DAADwBAAgrgMAAPAEACCvAwAA8AQAILADAADwBAAgsQMAAPAEACCyAwAA8AQAIBm-AgAArgQAML8CAAB6ABDAAgAArgQAMMECAQDvAwAhxwJAAPEDACHdAkAA8QMAIeoCAgCEBAAh6wIBAP0DACHsAgEA_QMAIfACAQD9AwAhjANAAPIDACGjAyAApQQAIaQDAQD9AwAhpgMAAK8EpgMiqAMAALAEqAMiqQMgAKUEACGqAwEA_QMAIasDAQD9AwAhrAMAAIYEACCtA0AA8gMAIa4DAQD9AwAhrwMgALEEACGwAwEA_QMAIbEDQADyAwAhsgNAAPIDACEDAAAADwAgAQAAeQAwNwAAegAgAwAAAA8AIAEAAGgAMAIAAAEAIAEAAAAFACABAAAABQAgAwAAAAMAIAEAAAQAMAIAAAUAIAMAAAADACABAAAEADACAAAFACADAAAAAwAgAQAABAAwAgAABQAgDgMAAKMHACDBAgEAAAABxwJAAAAAAdoCAQAAAAHdAkAAAAABmgMBAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABASsAAIIBACANwQIBAAAAAccCQAAAAAHaAgEAAAAB3QJAAAAAAZoDAQAAAAGbAwEAAAABnAMBAAAAAZ0DAQAAAAGeA0AAAAABnwNAAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAQErAACEAQAwASsAAIQBADAOAwAAogcAIMECAQD0BAAhxwJAAPUEACHaAgEA9AQAId0CQAD1BAAhmgMBAPQEACGbAwEA9AQAIZwDAQD_BAAhnQMBAP8EACGeA0AA9gQAIZ8DQAD2BAAhoAMBAP8EACGhAwEA_wQAIaIDAQD_BAAhAgAAAAUAICsAAIcBACANwQIBAPQEACHHAkAA9QQAIdoCAQD0BAAh3QJAAPUEACGaAwEA9AQAIZsDAQD0BAAhnAMBAP8EACGdAwEA_wQAIZ4DQAD2BAAhnwNAAPYEACGgAwEA_wQAIaEDAQD_BAAhogMBAP8EACECAAAAAwAgKwAAiQEAIAIAAAADACArAACJAQAgAwAAAAUAIDIAAIIBACAzAACHAQAgAQAAAAUAIAEAAAADACAKDAAAnwcAIDoAAKEHACA7AACgBwAgnAMAAPAEACCdAwAA8AQAIJ4DAADwBAAgnwMAAPAEACCgAwAA8AQAIKEDAADwBAAgogMAAPAEACAQvgIAAK0EADC_AgAAkAEAEMACAACtBAAwwQIBAO8DACHHAkAA8QMAIdoCAQDvAwAh3QJAAPEDACGaAwEA7wMAIZsDAQDvAwAhnAMBAP0DACGdAwEA_QMAIZ4DQADyAwAhnwNAAPIDACGgAwEA_QMAIaEDAQD9AwAhogMBAP0DACEDAAAAAwAgAQAAjwEAMDcAAJABACADAAAAAwAgAQAABAAwAgAABQAgAQAAAAkAIAEAAAAJACADAAAABwAgAQAACAAwAgAACQAgAwAAAAcAIAEAAAgAMAIAAAkAIAMAAAAHACABAAAIADACAAAJACAKAwAAngcAIMECAQAAAAHHAkAAAAAB2gIBAAAAAd0CQAAAAAHjAgEAAAABlgNAAAAAAZcDAQAAAAGYAwEAAAABmQMBAAAAAQErAACYAQAgCcECAQAAAAHHAkAAAAAB2gIBAAAAAd0CQAAAAAHjAgEAAAABlgNAAAAAAZcDAQAAAAGYAwEAAAABmQMBAAAAAQErAACaAQAwASsAAJoBADAKAwAAnQcAIMECAQD0BAAhxwJAAPUEACHaAgEA9AQAId0CQAD1BAAh4wIBAP8EACGWA0AA9QQAIZcDAQD0BAAhmAMBAP8EACGZAwEA_wQAIQIAAAAJACArAACdAQAgCcECAQD0BAAhxwJAAPUEACHaAgEA9AQAId0CQAD1BAAh4wIBAP8EACGWA0AA9QQAIZcDAQD0BAAhmAMBAP8EACGZAwEA_wQAIQIAAAAHACArAACfAQAgAgAAAAcAICsAAJ8BACADAAAACQAgMgAAmAEAIDMAAJ0BACABAAAACQAgAQAAAAcAIAYMAACaBwAgOgAAnAcAIDsAAJsHACDjAgAA8AQAIJgDAADwBAAgmQMAAPAEACAMvgIAAKwEADC_AgAApgEAEMACAACsBAAwwQIBAO8DACHHAkAA8QMAIdoCAQDvAwAh3QJAAPEDACHjAgEA_QMAIZYDQADxAwAhlwMBAO8DACGYAwEA_QMAIZkDAQD9AwAhAwAAAAcAIAEAAKUBADA3AACmAQAgAwAAAAcAIAEAAAgAMAIAAAkAIAEAAAANACABAAAADQAgAwAAAAsAIAEAAAwAMAIAAA0AIAMAAAALACABAAAMADACAAANACADAAAACwAgAQAADAAwAgAADQAgCAMAAJkHACDBAgEAAAABxwJAAAAAAdoCAQAAAAHdAkAAAAABlAMBAAAAAZUDAQAAAAGWA0AAAAABASsAAK4BACAHwQIBAAAAAccCQAAAAAHaAgEAAAAB3QJAAAAAAZQDAQAAAAGVAwEAAAABlgNAAAAAAQErAACwAQAwASsAALABADABAAAADwAgCAMAAJgHACDBAgEA9AQAIccCQAD2BAAh2gIBAP8EACHdAkAA9gQAIZQDAQD0BAAhlQMBAPQEACGWA0AA9QQAIQIAAAANACArAAC0AQAgB8ECAQD0BAAhxwJAAPYEACHaAgEA_wQAId0CQAD2BAAhlAMBAPQEACGVAwEA9AQAIZYDQAD1BAAhAgAAAAsAICsAALYBACACAAAACwAgKwAAtgEAIAEAAAAPACADAAAADQAgMgAArgEAIDMAALQBACABAAAADQAgAQAAAAsAIAYMAACVBwAgOgAAlwcAIDsAAJYHACDHAgAA8AQAINoCAADwBAAg3QIAAPAEACAKvgIAAKsEADC_AgAAvgEAEMACAACrBAAwwQIBAO8DACHHAkAA8gMAIdoCAQD9AwAh3QJAAPIDACGUAwEA7wMAIZUDAQDvAwAhlgNAAPEDACEDAAAACwAgAQAAvQEAMDcAAL4BACADAAAACwAgAQAADAAwAgAADQAgAQAAAFsAIAEAAABbACADAAAAWQAgAQAAWgAwAgAAWwAgAwAAAFkAIAEAAFoAMAIAAFsAIAMAAABZACABAABaADACAABbACAMAwAAlAcAIMECAQAAAAHHAkAAAAAB2gIBAAAAAewCAQAAAAGNAwEAAAABjgMBAAAAAY8DAgAAAAGQAwEAAAABkQMgAAAAAZIDAQAAAAGTAwEAAAABASsAAMYBACALwQIBAAAAAccCQAAAAAHaAgEAAAAB7AIBAAAAAY0DAQAAAAGOAwEAAAABjwMCAAAAAZADAQAAAAGRAyAAAAABkgMBAAAAAZMDAQAAAAEBKwAAyAEAMAErAADIAQAwDAMAAJMHACDBAgEA9AQAIccCQAD2BAAh2gIBAPQEACHsAgEA_wQAIY0DAQD0BAAhjgMBAPQEACGPAwIA_gQAIZADAQD0BAAhkQMgAP4FACGSAwEA_wQAIZMDAQD_BAAhAgAAAFsAICsAAMsBACALwQIBAPQEACHHAkAA9gQAIdoCAQD0BAAh7AIBAP8EACGNAwEA9AQAIY4DAQD0BAAhjwMCAP4EACGQAwEA9AQAIZEDIAD-BQAhkgMBAP8EACGTAwEA_wQAIQIAAABZACArAADNAQAgAgAAAFkAICsAAM0BACADAAAAWwAgMgAAxgEAIDMAAMsBACABAAAAWwAgAQAAAFkAIAkMAACOBwAgOAAAjwcAIDkAAJIHACA6AACRBwAgOwAAkAcAIMcCAADwBAAg7AIAAPAEACCSAwAA8AQAIJMDAADwBAAgDr4CAACqBAAwvwIAANQBABDAAgAAqgQAMMECAQDvAwAhxwJAAPIDACHaAgEA7wMAIewCAQD9AwAhjQMBAO8DACGOAwEA7wMAIY8DAgD-AwAhkAMBAO8DACGRAyAApQQAIZIDAQD9AwAhkwMBAP0DACEDAAAAWQAgAQAA0wEAMDcAANQBACADAAAAWQAgAQAAWgAwAgAAWwAgAQAAABoAIAEAAAAaACADAAAAFwAgAQAAGQAwAgAAGgAgAwAAABcAIAEAABkAMAIAABoAIAMAAAAXACABAAAZADACAAAaACAbEQAA_QYAIBIAAO4GACATAADvBgAgFAAA8AYAIBUAAPEGACAWAADyBgAgFwAA8wYAIBkAAPQGACAaAAD1BgAgGwAA9gYAIBwAAPcGACAdAAD4BgAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAYEDAgAAAAGCAwEAAAABgwMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQErAADcAQAgD8ECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAEBKwAA3gEAMAErAADeAQAwAQAAABUAIAEAAAAXACABAAAAFQAgGxEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACECAAAAGgAgKwAA5AEAIA_BAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhAgAAABcAICsAAOYBACACAAAAFwAgKwAA5gEAIAEAAAAVACABAAAAFwAgAQAAABUAIAMAAAAaACAyAADcAQAgMwAA5AEAIAEAAAAaACABAAAAFwAgCgwAAIkHACA4AACKBwAgOQAAjQcAIDoAAIwHACA7AACLBwAg6gIAAPAEACCBAwAA8AQAIIIDAADwBAAggwMAAPAEACCMAwAA8AQAIBK-AgAAowQAML8CAADwAQAQwAIAAKMEADDBAgEA7wMAIccCQADxAwAh3QJAAPEDACHqAgIAhAQAIYEDAgCEBAAhggMBAP0DACGDAwIAhAQAIYUDAACkBIUDIoYDIAClBAAhhwMgAKUEACGIAwIA_gMAIYkDAgD-AwAhigMCAP4DACGLAwIA_gMAIYwDQADyAwAhAwAAABcAIAEAAO8BADA3AADwAQAgAwAAABcAIAEAABkAMAIAABoAIAEAAAAtACABAAAALQAgAwAAABUAIAEAACwAMAIAAC0AIAMAAAAVACABAAAsADACAAAtACADAAAAFQAgAQAALAAwAgAALQAgEAcAAIgHACAIAADoBgAgCQAA6QYAIA4AAOoGACAQAADrBgAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAEBKwAA-AEAIAvHAkAAAAAB2wIBAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQErAAD6AQAwASsAAPoBADAQBwAA2QUAIAgAANoFACAJAADbBQAgDgAA3AUAIBAAAN0FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhAgAAAC0AICsAAP0BACALxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQIAAAAVACArAAD_AQAgAgAAABUAICsAAP8BACADAAAALQAgMgAA-AEAIDMAAP0BACABAAAALQAgAQAAABUAIAsMAADUBQAgOAAA1QUAIDkAANgFACA6AADXBQAgOwAA1gUAIPoCAADwBAAg-wIAAPAEACD8AgAA8AQAIP4CAADwBAAg_wIAAPAEACCAAwAA8AQAIA6-AgAAogQAML8CAACGAgAQwAIAAKIEADDHAkAA8QMAIdsCAQDvAwAh3gICAP4DACH5AgEA7wMAIfoCAQD9AwAh-wIBAP0DACH8AgEA_QMAIf0CAQDvAwAh_gIBAP0DACH_AgEA_QMAIYADQADyAwAhAwAAABUAIAEAAIUCADA3AACGAgAgAwAAABUAIAEAACwAMAIAAC0AIAEAAAAeACABAAAAHgAgAwAAABwAIAEAAB0AMAIAAB4AIAMAAAAcACABAAAdADACAAAeACADAAAAHAAgAQAAHQAwAgAAHgAgBgoAAMAFACANAADTBQAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-AIBAAAAAQErAACOAgAgBMcCQAAAAAHbAgEAAAAB3gICAAAAAfgCAQAAAAEBKwAAkAIAMAErAACQAgAwBgoAAL4FACANAADSBQAgxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-AIBAPQEACECAAAAHgAgKwAAkwIAIATHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH4AgEA9AQAIQIAAAAcACArAACVAgAgAgAAABwAICsAAJUCACADAAAAHgAgMgAAjgIAIDMAAJMCACABAAAAHgAgAQAAABwAIAUMAADNBQAgOAAAzgUAIDkAANEFACA6AADQBQAgOwAAzwUAIAe-AgAAoQQAML8CAACcAgAQwAIAAKEEADDHAkAA8QMAIdsCAQDvAwAh3gICAP4DACH4AgEA7wMAIQMAAAAcACABAACbAgAwNwAAnAIAIAMAAAAcACABAAAdADACAAAeACABAAAAJAAgAQAAACQAIAMAAAAiACABAAAjADACAAAkACADAAAAIgAgAQAAIwAwAgAAJAAgAwAAACIAIAEAACMAMAIAACQAIAgHAADLBQAgDwAAzAUAIMECAQAAAAHHAkAAAAAB2wIBAAAAAeACAAAA-AIC9QICAAAAAfYCAQAAAAEBKwAApAIAIAbBAgEAAAABxwJAAAAAAdsCAQAAAAHgAgAAAPgCAvUCAgAAAAH2AgEAAAABASsAAKYCADABKwAApgIAMAgHAADJBQAgDwAAygUAIMECAQD0BAAhxwJAAPUEACHbAgEA9AQAIeACAADIBfgCIvUCAgD-BAAh9gIBAPQEACECAAAAJAAgKwAAqQIAIAbBAgEA9AQAIccCQAD1BAAh2wIBAPQEACHgAgAAyAX4AiL1AgIA_gQAIfYCAQD0BAAhAgAAACIAICsAAKsCACACAAAAIgAgKwAAqwIAIAMAAAAkACAyAACkAgAgMwAAqQIAIAEAAAAkACABAAAAIgAgBQwAAMMFACA4AADEBQAgOQAAxwUAIDoAAMYFACA7AADFBQAgCb4CAACdBAAwvwIAALICABDAAgAAnQQAMMECAQDvAwAhxwJAAPEDACHbAgEA7wMAIeACAACeBPgCIvUCAgD-AwAh9gIBAO8DACEDAAAAIgAgAQAAsQIAMDcAALICACADAAAAIgAgAQAAIwAwAgAAJAAgCQsAAJwEACC-AgAAlwQAML8CAAC4AgAQwAIAAJcEADDBAgEAAAABxwJAAJsEACHqAgIAAAAB7AIBAAAAAfECAQCaBAAhAQAAALUCACABAAAAtQIAIAkLAACcBAAgvgIAAJcEADC_AgAAuAIAEMACAACXBAAwwQIBAJgEACHHAkAAmwQAIeoCAgCZBAAh7AIBAJgEACHxAgEAmgQAIQMLAADCBQAg6gIAAPAEACDxAgAA8AQAIAMAAAC4AgAgAQAAuQIAMAIAALUCACADAAAAuAIAIAEAALkCADACAAC1AgAgAwAAALgCACABAAC5AgAwAgAAtQIAIAYLAADBBQAgwQIBAAAAAccCQAAAAAHqAgIAAAAB7AIBAAAAAfECAQAAAAEBKwAAvQIAIAXBAgEAAAABxwJAAAAAAeoCAgAAAAHsAgEAAAAB8QIBAAAAAQErAAC_AgAwASsAAL8CADAGCwAAsgUAIMECAQD0BAAhxwJAAPUEACHqAgIAiQUAIewCAQD0BAAh8QIBAP8EACECAAAAtQIAICsAAMICACAFwQIBAPQEACHHAkAA9QQAIeoCAgCJBQAh7AIBAPQEACHxAgEA_wQAIQIAAAC4AgAgKwAAxAIAIAIAAAC4AgAgKwAAxAIAIAMAAAC1AgAgMgAAvQIAIDMAAMICACABAAAAtQIAIAEAAAC4AgAgBwwAAK0FACA4AACuBQAgOQAAsQUAIDoAALAFACA7AACvBQAg6gIAAPAEACDxAgAA8AQAIAi-AgAAlgQAML8CAADLAgAQwAIAAJYEADDBAgEA7wMAIccCQADxAwAh6gICAIQEACHsAgEA7wMAIfECAQD9AwAhAwAAALgCACABAADKAgAwNwAAywIAIAMAAAC4AgAgAQAAuQIAMAIAALUCACABAAAAEwAgAQAAABMAIAMAAAARACABAAASADACAAATACADAAAAEQAgAQAAEgAwAgAAEwAgAwAAABEAIAEAABIAMAIAABMAIAcDAACsBQAgBwAAqwUAIMcCQAAAAAHaAgEAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgErAADTAgAgBccCQAAAAAHaAgEAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgErAADVAgAwASsAANUCADAHAwAAqgUAIAcAAKkFACDHAkAA9QQAIdoCAQD0BAAh2wIBAPQEACHtAgEA_wQAIfACAACoBfACIgIAAAATACArAADYAgAgBccCQAD1BAAh2gIBAPQEACHbAgEA9AQAIe0CAQD_BAAh8AIAAKgF8AIiAgAAABEAICsAANoCACACAAAAEQAgKwAA2gIAIAMAAAATACAyAADTAgAgMwAA2AIAIAEAAAATACABAAAAEQAgBAwAAKUFACA6AACnBQAgOwAApgUAIO0CAADwBAAgCL4CAACSBAAwvwIAAOECABDAAgAAkgQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIe0CAQD9AwAh8AIAAJME8AIiAwAAABEAIAEAAOACADA3AADhAgAgAwAAABEAIAEAABIAMAIAABMAIAEAAAAyACABAAAAMgAgAwAAADAAIAEAADEAMAIAADIAIAMAAAAwACABAAAxADACAAAyACADAAAAMAAgAQAAMQAwAgAAMgAgCQcAAKQFACDBAgEAAAABxwJAAAAAAdsCAQAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHtAgEAAAAB7gIBAAAAAQErAADpAgAgCMECAQAAAAHHAkAAAAAB2wIBAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAe0CAQAAAAHuAgEAAAABASsAAOsCADABKwAA6wIAMAkHAACjBQAgwQIBAPQEACHHAkAA9QQAIdsCAQD0BAAh6gICAP4EACHrAgEA_wQAIewCAQD_BAAh7QIBAP8EACHuAgEA_wQAIQIAAAAyACArAADuAgAgCMECAQD0BAAhxwJAAPUEACHbAgEA9AQAIeoCAgD-BAAh6wIBAP8EACHsAgEA_wQAIe0CAQD_BAAh7gIBAP8EACECAAAAMAAgKwAA8AIAIAIAAAAwACArAADwAgAgAwAAADIAIDIAAOkCACAzAADuAgAgAQAAADIAIAEAAAAwACAJDAAAngUAIDgAAJ8FACA5AACiBQAgOgAAoQUAIDsAAKAFACDrAgAA8AQAIOwCAADwBAAg7QIAAPAEACDuAgAA8AQAIAu-AgAAkQQAML8CAAD3AgAQwAIAAJEEADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHqAgIA_gMAIesCAQD9AwAh7AIBAP0DACHtAgEA_QMAIe4CAQD9AwAhAwAAADAAIAEAAPYCADA3AAD3AgAgAwAAADAAIAEAADEAMAIAADIAIAEAAAA2ACABAAAANgAgAwAAADQAIAEAADUAMAIAADYAIAMAAAA0ACABAAA1ADACAAA2ACADAAAANAAgAQAANQAwAgAANgAgBwcAAJwFACAYAACdBQAgwQIBAAAAAccCQAAAAAHbAgEAAAAB5wIBAAAAAekCAAAA6QICASsAAP8CACAFwQIBAAAAAccCQAAAAAHbAgEAAAAB5wIBAAAAAekCAAAA6QICASsAAIEDADABKwAAgQMAMAEAAAAPACAHBwAAmgUAIBgAAJsFACDBAgEA9AQAIccCQAD1BAAh2wIBAPQEACHnAgEA_wQAIekCAACZBekCIgIAAAA2ACArAACFAwAgBcECAQD0BAAhxwJAAPUEACHbAgEA9AQAIecCAQD_BAAh6QIAAJkF6QIiAgAAADQAICsAAIcDACACAAAANAAgKwAAhwMAIAEAAAAPACADAAAANgAgMgAA_wIAIDMAAIUDACABAAAANgAgAQAAADQAIAQMAACWBQAgOgAAmAUAIDsAAJcFACDnAgAA8AQAIAi-AgAAjQQAML8CAACPAwAQwAIAAI0EADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHnAgEA_QMAIekCAACOBOkCIgMAAAA0ACABAACOAwAwNwAAjwMAIAMAAAA0ACABAAA1ADACAAA2ACABAAAAPAAgAQAAADwAIAMAAAA6ACABAAA7ADACAAA8ACADAAAAOgAgAQAAOwAwAgAAPAAgAwAAADoAIAEAADsAMAIAADwAIAUDAACVBQAgBwAAlAUAIMcCQAAAAAHaAgEAAAAB2wIBAAAAAQErAACXAwAgA8cCQAAAAAHaAgEAAAAB2wIBAAAAAQErAACZAwAwASsAAJkDADAFAwAAkwUAIAcAAJIFACDHAkAA9QQAIdoCAQD0BAAh2wIBAPQEACECAAAAPAAgKwAAnAMAIAPHAkAA9QQAIdoCAQD0BAAh2wIBAPQEACECAAAAOgAgKwAAngMAIAIAAAA6ACArAACeAwAgAwAAADwAIDIAAJcDACAzAACcAwAgAQAAADwAIAEAAAA6ACADDAAAjwUAIDoAAJEFACA7AACQBQAgBr4CAACMBAAwvwIAAKUDABDAAgAAjAQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIQMAAAA6ACABAACkAwAwNwAApQMAIAMAAAA6ACABAAA7ADACAAA8ACABAAAAQAAgAQAAAEAAIAMAAAA-ACABAAA_ADACAABAACADAAAAPgAgAQAAPwAwAgAAQAAgAwAAAD4AIAEAAD8AMAIAAEAAIA4DAACOBQAgBwAAjQUAIMECAQAAAAHHAkAAAAAB2gIBAAAAAdsCAQAAAAHeAgIAAAAB4AIAAADgAgLhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QKAAAAAAeYCAQAAAAEBKwAArQMAIAzBAgEAAAABxwJAAAAAAdoCAQAAAAHbAgEAAAAB3gICAAAAAeACAAAA4AIC4QIBAAAAAeICAQAAAAHjAgEAAAAB5AIBAAAAAeUCgAAAAAHmAgEAAAABASsAAK8DADABKwAArwMAMAEAAAAPACAOAwAAjAUAIAcAAIsFACDBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACECAAAAQAAgKwAAswMAIAzBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACECAAAAPgAgKwAAtQMAIAIAAAA-ACArAAC1AwAgAQAAAA8AIAMAAABAACAyAACtAwAgMwAAswMAIAEAAABAACABAAAAPgAgDQwAAIQFACA4AACFBQAgOQAAiAUAIDoAAIcFACA7AACGBQAg2gIAAPAEACDeAgAA8AQAIOECAADwBAAg4gIAAPAEACDjAgAA8AQAIOQCAADwBAAg5QIAAPAEACDmAgAA8AQAIA--AgAAgwQAML8CAAC9AwAQwAIAAIMEADDBAgEA7wMAIccCQADxAwAh2gIBAP0DACHbAgEA7wMAId4CAgCEBAAh4AIAAIUE4AIi4QIBAP0DACHiAgEA_QMAIeMCAQD9AwAh5AIBAP0DACHlAgAAhgQAIOYCAQD9AwAhAwAAAD4AIAEAALwDADA3AAC9AwAgAwAAAD4AIAEAAD8AMAIAAEAAIAEAAABFACABAAAARQAgAwAAAEMAIAEAAEQAMAIAAEUAIAMAAABDACABAABEADACAABFACADAAAAQwAgAQAARAAwAgAARQAgCQMAAIIFACAHAACDBQAgK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB2wIBAAAAAdwCAgAAAAHdAkAAAAABASsAAMUDACAHK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB2wIBAAAAAdwCAgAAAAHdAkAAAAABASsAAMcDADABKwAAxwMAMAEAAAAXACAJAwAAgAUAIAcAAIEFACArgAAAAAHBAgEA9AQAIccCQAD1BAAh2gIBAPQEACHbAgEA_wQAIdwCAgD-BAAh3QJAAPUEACECAAAARQAgKwAAywMAIAcrgAAAAAHBAgEA9AQAIccCQAD1BAAh2gIBAPQEACHbAgEA_wQAIdwCAgD-BAAh3QJAAPUEACECAAAAQwAgKwAAzQMAIAIAAABDACArAADNAwAgAQAAABcAIAMAAABFACAyAADFAwAgMwAAywMAIAEAAABFACABAAAAQwAgBgwAAPkEACA4AAD6BAAgOQAA_QQAIDoAAPwEACA7AAD7BAAg2wIAAPAEACAKKwAA8AMAIL4CAAD8AwAwvwIAANUDABDAAgAA_AMAMMECAQDvAwAhxwJAAPEDACHaAgEA7wMAIdsCAQD9AwAh3AICAP4DACHdAkAA8QMAIQMAAABDACABAADUAwAwNwAA1QMAIAMAAABDACABAABEADACAABFACABAAAAVAAgAQAAAFQAIAMAAABSACABAABTADACAABUACADAAAAUgAgAQAAUwAwAgAAVAAgAwAAAFIAIAEAAFMAMAIAAFQAIAkgAAD4BAAgwQIBAAAAAcICAQAAAAHDAgEAAAABxAIBAAAAAcUCAQAAAAHGAoAAAAABxwJAAAAAAcgCQAAAAAEBKwAA3QMAIAjBAgEAAAABwgIBAAAAAcMCAQAAAAHEAgEAAAABxQIBAAAAAcYCgAAAAAHHAkAAAAAByAJAAAAAAQErAADfAwAwASsAAN8DADAJIAAA9wQAIMECAQD0BAAhwgIBAPQEACHDAgEA9AQAIcQCAQD0BAAhxQIBAPQEACHGAoAAAAABxwJAAPUEACHIAkAA9gQAIQIAAABUACArAADiAwAgCMECAQD0BAAhwgIBAPQEACHDAgEA9AQAIcQCAQD0BAAhxQIBAPQEACHGAoAAAAABxwJAAPUEACHIAkAA9gQAIQIAAABSACArAADkAwAgAgAAAFIAICsAAOQDACADAAAAVAAgMgAA3QMAIDMAAOIDACABAAAAVAAgAQAAAFIAIAQMAADxBAAgOgAA8wQAIDsAAPIEACDIAgAA8AQAIAu-AgAA7gMAML8CAADrAwAQwAIAAO4DADDBAgEA7wMAIcICAQDvAwAhwwIBAO8DACHEAgEA7wMAIcUCAQDvAwAhxgIAAPADACDHAkAA8QMAIcgCQADyAwAhAwAAAFIAIAEAAOoDADA3AADrAwAgAwAAAFIAIAEAAFMAMAIAAFQAIAu-AgAA7gMAML8CAADrAwAQwAIAAO4DADDBAgEA7wMAIcICAQDvAwAhwwIBAO8DACHEAgEA7wMAIcUCAQDvAwAhxgIAAPADACDHAkAA8QMAIcgCQADyAwAhDgwAAPcDACA6AAD7AwAgOwAA-wMAIMkCAQAAAAHKAgEAAAAEywIBAAAABMwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEA-gMAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQ8MAAD3AwAgOgAA-QMAIDsAAPkDACDJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAELDAAA9wMAIDoAAPgDACA7AAD4AwAgyQJAAAAAAcoCQAAAAATLAkAAAAAEzAJAAAAAAc0CQAAAAAHOAkAAAAABzwJAAAAAAdACQAD2AwAhCwwAAPQDACA6AAD1AwAgOwAA9QMAIMkCQAAAAAHKAkAAAAAFywJAAAAABcwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA8wMAIQsMAAD0AwAgOgAA9QMAIDsAAPUDACDJAkAAAAABygJAAAAABcsCQAAAAAXMAkAAAAABzQJAAAAAAc4CQAAAAAHPAkAAAAAB0AJAAPMDACEIyQICAAAAAcoCAgAAAAXLAgIAAAAFzAICAAAAAc0CAgAAAAHOAgIAAAABzwICAAAAAdACAgD0AwAhCMkCQAAAAAHKAkAAAAAFywJAAAAABcwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA9QMAIQsMAAD3AwAgOgAA-AMAIDsAAPgDACDJAkAAAAABygJAAAAABMsCQAAAAATMAkAAAAABzQJAAAAAAc4CQAAAAAHPAkAAAAAB0AJAAPYDACEIyQICAAAAAcoCAgAAAATLAgIAAAAEzAICAAAAAc0CAgAAAAHOAgIAAAABzwICAAAAAdACAgD3AwAhCMkCQAAAAAHKAkAAAAAEywJAAAAABMwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA-AMAIQzJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAEODAAA9wMAIDoAAPsDACA7AAD7AwAgyQIBAAAAAcoCAQAAAATLAgEAAAAEzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQD6AwAh1wIBAAAAAdgCAQAAAAHZAgEAAAABC8kCAQAAAAHKAgEAAAAEywIBAAAABMwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEA-wMAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQorAADwAwAgvgIAAPwDADC_AgAA1QMAEMACAAD8AwAwwQIBAO8DACHHAkAA8QMAIdoCAQDvAwAh2wIBAP0DACHcAgIA_gMAId0CQADxAwAhDgwAAPQDACA6AACCBAAgOwAAggQAIMkCAQAAAAHKAgEAAAAFywIBAAAABcwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEAgQQAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQ0MAAD3AwAgOAAAgAQAIDkAAPcDACA6AAD3AwAgOwAA9wMAIMkCAgAAAAHKAgIAAAAEywICAAAABMwCAgAAAAHNAgIAAAABzgICAAAAAc8CAgAAAAHQAgIA_wMAIQ0MAAD3AwAgOAAAgAQAIDkAAPcDACA6AAD3AwAgOwAA9wMAIMkCAgAAAAHKAgIAAAAEywICAAAABMwCAgAAAAHNAgIAAAABzgICAAAAAc8CAgAAAAHQAgIA_wMAIQjJAggAAAABygIIAAAABMsCCAAAAATMAggAAAABzQIIAAAAAc4CCAAAAAHPAggAAAAB0AIIAIAEACEODAAA9AMAIDoAAIIEACA7AACCBAAgyQIBAAAAAcoCAQAAAAXLAgEAAAAFzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQCBBAAh1wIBAAAAAdgCAQAAAAHZAgEAAAABC8kCAQAAAAHKAgEAAAAFywIBAAAABcwCAQAAAAHNAgEAAAABzgIBAAAAAc8CAQAAAAHQAgEAggQAIdcCAQAAAAHYAgEAAAAB2QIBAAAAAQ--AgAAgwQAML8CAAC9AwAQwAIAAIMEADDBAgEA7wMAIccCQADxAwAh2gIBAP0DACHbAgEA7wMAId4CAgCEBAAh4AIAAIUE4AIi4QIBAP0DACHiAgEA_QMAIeMCAQD9AwAh5AIBAP0DACHlAgAAhgQAIOYCAQD9AwAhDQwAAPQDACA4AACLBAAgOQAA9AMAIDoAAPQDACA7AAD0AwAgyQICAAAAAcoCAgAAAAXLAgIAAAAFzAICAAAAAc0CAgAAAAHOAgIAAAABzwICAAAAAdACAgCKBAAhBwwAAPcDACA6AACJBAAgOwAAiQQAIMkCAAAA4AICygIAAADgAgjLAgAAAOACCNACAACIBOACIg8MAAD0AwAgOgAAhwQAIDsAAIcEACDJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAEMyQKAAAAAAcwCgAAAAAHNAoAAAAABzgKAAAAAAc8CgAAAAAHQAoAAAAAB0QIBAAAAAdICAQAAAAHTAgEAAAAB1AKAAAAAAdUCgAAAAAHWAoAAAAABBwwAAPcDACA6AACJBAAgOwAAiQQAIMkCAAAA4AICygIAAADgAgjLAgAAAOACCNACAACIBOACIgTJAgAAAOACAsoCAAAA4AIIywIAAADgAgjQAgAAiQTgAiINDAAA9AMAIDgAAIsEACA5AAD0AwAgOgAA9AMAIDsAAPQDACDJAgIAAAABygICAAAABcsCAgAAAAXMAgIAAAABzQICAAAAAc4CAgAAAAHPAgIAAAAB0AICAIoEACEIyQIIAAAAAcoCCAAAAAXLAggAAAAFzAIIAAAAAc0CCAAAAAHOAggAAAABzwIIAAAAAdACCACLBAAhBr4CAACMBAAwvwIAAKUDABDAAgAAjAQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIQi-AgAAjQQAML8CAACPAwAQwAIAAI0EADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHnAgEA_QMAIekCAACOBOkCIgcMAAD3AwAgOgAAkAQAIDsAAJAEACDJAgAAAOkCAsoCAAAA6QIIywIAAADpAgjQAgAAjwTpAiIHDAAA9wMAIDoAAJAEACA7AACQBAAgyQIAAADpAgLKAgAAAOkCCMsCAAAA6QII0AIAAI8E6QIiBMkCAAAA6QICygIAAADpAgjLAgAAAOkCCNACAACQBOkCIgu-AgAAkQQAML8CAAD3AgAQwAIAAJEEADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHqAgIA_gMAIesCAQD9AwAh7AIBAP0DACHtAgEA_QMAIe4CAQD9AwAhCL4CAACSBAAwvwIAAOECABDAAgAAkgQAMMcCQADxAwAh2gIBAO8DACHbAgEA7wMAIe0CAQD9AwAh8AIAAJME8AIiBwwAAPcDACA6AACVBAAgOwAAlQQAIMkCAAAA8AICygIAAADwAgjLAgAAAPACCNACAACUBPACIgcMAAD3AwAgOgAAlQQAIDsAAJUEACDJAgAAAPACAsoCAAAA8AIIywIAAADwAgjQAgAAlATwAiIEyQIAAADwAgLKAgAAAPACCMsCAAAA8AII0AIAAJUE8AIiCL4CAACWBAAwvwIAAMsCABDAAgAAlgQAMMECAQDvAwAhxwJAAPEDACHqAgIAhAQAIewCAQDvAwAh8QIBAP0DACEJCwAAnAQAIL4CAACXBAAwvwIAALgCABDAAgAAlwQAMMECAQCYBAAhxwJAAJsEACHqAgIAmQQAIewCAQCYBAAh8QIBAJoEACELyQIBAAAAAcoCAQAAAATLAgEAAAAEzAIBAAAAAc0CAQAAAAHOAgEAAAABzwIBAAAAAdACAQD7AwAh1wIBAAAAAdgCAQAAAAHZAgEAAAABCMkCAgAAAAHKAgIAAAAFywICAAAABcwCAgAAAAHNAgIAAAABzgICAAAAAc8CAgAAAAHQAgIA9AMAIQvJAgEAAAABygIBAAAABcsCAQAAAAXMAgEAAAABzQIBAAAAAc4CAQAAAAHPAgEAAAAB0AIBAIIEACHXAgEAAAAB2AIBAAAAAdkCAQAAAAEIyQJAAAAAAcoCQAAAAATLAkAAAAAEzAJAAAAAAc0CQAAAAAHOAkAAAAABzwJAAAAAAdACQAD4AwAhA_ICAAAcACDzAgAAHAAg9AIAABwAIAm-AgAAnQQAML8CAACyAgAQwAIAAJ0EADDBAgEA7wMAIccCQADxAwAh2wIBAO8DACHgAgAAngT4AiL1AgIA_gMAIfYCAQDvAwAhBwwAAPcDACA6AACgBAAgOwAAoAQAIMkCAAAA-AICygIAAAD4AgjLAgAAAPgCCNACAACfBPgCIgcMAAD3AwAgOgAAoAQAIDsAAKAEACDJAgAAAPgCAsoCAAAA-AIIywIAAAD4AgjQAgAAnwT4AiIEyQIAAAD4AgLKAgAAAPgCCMsCAAAA-AII0AIAAKAE-AIiB74CAAChBAAwvwIAAJwCABDAAgAAoQQAMMcCQADxAwAh2wIBAO8DACHeAgIA_gMAIfgCAQDvAwAhDr4CAACiBAAwvwIAAIYCABDAAgAAogQAMMcCQADxAwAh2wIBAO8DACHeAgIA_gMAIfkCAQDvAwAh-gIBAP0DACH7AgEA_QMAIfwCAQD9AwAh_QIBAO8DACH-AgEA_QMAIf8CAQD9AwAhgANAAPIDACESvgIAAKMEADC_AgAA8AEAEMACAACjBAAwwQIBAO8DACHHAkAA8QMAId0CQADxAwAh6gICAIQEACGBAwIAhAQAIYIDAQD9AwAhgwMCAIQEACGFAwAApASFAyKGAyAApQQAIYcDIAClBAAhiAMCAP4DACGJAwIA_gMAIYoDAgD-AwAhiwMCAP4DACGMA0AA8gMAIQcMAAD3AwAgOgAAqQQAIDsAAKkEACDJAgAAAIUDAsoCAAAAhQMIywIAAACFAwjQAgAAqASFAyIFDAAA9wMAIDoAAKcEACA7AACnBAAgyQIgAAAAAdACIACmBAAhBQwAAPcDACA6AACnBAAgOwAApwQAIMkCIAAAAAHQAiAApgQAIQLJAiAAAAAB0AIgAKcEACEHDAAA9wMAIDoAAKkEACA7AACpBAAgyQIAAACFAwLKAgAAAIUDCMsCAAAAhQMI0AIAAKgEhQMiBMkCAAAAhQMCygIAAACFAwjLAgAAAIUDCNACAACpBIUDIg6-AgAAqgQAML8CAADUAQAQwAIAAKoEADDBAgEA7wMAIccCQADyAwAh2gIBAO8DACHsAgEA_QMAIY0DAQDvAwAhjgMBAO8DACGPAwIA_gMAIZADAQDvAwAhkQMgAKUEACGSAwEA_QMAIZMDAQD9AwAhCr4CAACrBAAwvwIAAL4BABDAAgAAqwQAMMECAQDvAwAhxwJAAPIDACHaAgEA_QMAId0CQADyAwAhlAMBAO8DACGVAwEA7wMAIZYDQADxAwAhDL4CAACsBAAwvwIAAKYBABDAAgAArAQAMMECAQDvAwAhxwJAAPEDACHaAgEA7wMAId0CQADxAwAh4wIBAP0DACGWA0AA8QMAIZcDAQDvAwAhmAMBAP0DACGZAwEA_QMAIRC-AgAArQQAML8CAACQAQAQwAIAAK0EADDBAgEA7wMAIccCQADxAwAh2gIBAO8DACHdAkAA8QMAIZoDAQDvAwAhmwMBAO8DACGcAwEA_QMAIZ0DAQD9AwAhngNAAPIDACGfA0AA8gMAIaADAQD9AwAhoQMBAP0DACGiAwEA_QMAIRm-AgAArgQAML8CAAB6ABDAAgAArgQAMMECAQDvAwAhxwJAAPEDACHdAkAA8QMAIeoCAgCEBAAh6wIBAP0DACHsAgEA_QMAIfACAQD9AwAhjANAAPIDACGjAyAApQQAIaQDAQD9AwAhpgMAAK8EpgMiqAMAALAEqAMiqQMgAKUEACGqAwEA_QMAIasDAQD9AwAhrAMAAIYEACCtA0AA8gMAIa4DAQD9AwAhrwMgALEEACGwAwEA_QMAIbEDQADyAwAhsgNAAPIDACEHDAAA9wMAIDoAALcEACA7AAC3BAAgyQIAAACmAwLKAgAAAKYDCMsCAAAApgMI0AIAALYEpgMiBwwAAPcDACA6AAC1BAAgOwAAtQQAIMkCAAAAqAMCygIAAACoAwjLAgAAAKgDCNACAAC0BKgDIgUMAAD0AwAgOgAAswQAIDsAALMEACDJAiAAAAAB0AIgALIEACEFDAAA9AMAIDoAALMEACA7AACzBAAgyQIgAAAAAdACIACyBAAhAskCIAAAAAHQAiAAswQAIQcMAAD3AwAgOgAAtQQAIDsAALUEACDJAgAAAKgDAsoCAAAAqAMIywIAAACoAwjQAgAAtASoAyIEyQIAAACoAwLKAgAAAKgDCMsCAAAAqAMI0AIAALUEqAMiBwwAAPcDACA6AAC3BAAgOwAAtwQAIMkCAAAApgMCygIAAACmAwjLAgAAAKYDCNACAAC2BKYDIgTJAgAAAKYDAsoCAAAApgMIywIAAACmAwjQAgAAtwSmAyIPAwAAvAQAIL4CAAC4BAAwvwIAAFkAEMACAAC4BAAwwQIBAJgEACHHAkAAuwQAIdoCAQCYBAAh7AIBAJoEACGNAwEAmAQAIY4DAQCYBAAhjwMCALkEACGQAwEAmAQAIZEDIAC6BAAhkgMBAJoEACGTAwEAmgQAIQjJAgIAAAABygICAAAABMsCAgAAAATMAgIAAAABzQICAAAAAc4CAgAAAAHPAgIAAAAB0AICAPcDACECyQIgAAAAAdACIACnBAAhCMkCQAAAAAHKAkAAAAAFywJAAAAABcwCQAAAAAHNAkAAAAABzgJAAAAAAc8CQAAAAAHQAkAA9QMAISUEAADoBAAgBQAA6QQAIAYAAOoEACAeAADbBAAgHwAA3QQAICEAAOsEACAiAADeBAAgIwAA3wQAICQAAOAEACAlAADsBAAgvgIAAOQEADC_AgAADwAQwAIAAOQEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIesCAQCaBAAh7AIBAJoEACHwAgEAmgQAIYwDQAC7BAAhowMgALoEACGkAwEAmgQAIaYDAADlBKYDIqgDAADmBKgDIqkDIAC6BAAhqgMBAJoEACGrAwEAmgQAIawDAADDBAAgrQNAALsEACGuAwEAmgQAIa8DIADnBAAhsAMBAJoEACGxA0AAuwQAIbIDQAC7BAAhuAMAAA8AILkDAAAPACAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAJgEACHCAgEAmAQAIcMCAQCYBAAhxAIBAJgEACHFAgEAmAQAIcYCAAC-BAAgxwJAAJsEACHIAkAAuwQAIQzJAoAAAAABzAKAAAAAAc0CgAAAAAHOAoAAAAABzwKAAAAAAdACgAAAAAHRAgEAAAAB0gIBAAAAAdMCAQAAAAHUAoAAAAAB1QKAAAAAAdYCgAAAAAEMAwAAvAQAIAcAAMAEACArAAC-BAAgvgIAAL8EADC_AgAAQwAQwAIAAL8EADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACEgEQAA2QQAIBIAAMAEACATAADOBAAgFAAA2QQAIBUAANoEACAWAADbBAAgFwAA3AQAIBkAAN0EACAaAADPBAAgGwAA3gQAIBwAAN8EACAdAADgBAAgvgIAANcEADC_AgAAFwAQwAIAANcEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhuAMAABcAILkDAAAXACARAwAAxQQAIAcAAMQEACC-AgAAwQQAML8CAAA-ABDAAgAAwQQAMMECAQCYBAAhxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEEyQIAAADgAgLKAgAAAOACCMsCAAAA4AII0AIAAIkE4AIiDMkCgAAAAAHMAoAAAAABzQKAAAAAAc4CgAAAAAHPAoAAAAAB0AKAAAAAAdECAQAAAAHSAgEAAAAB0wIBAAAAAdQCgAAAAAHVAoAAAAAB1gKAAAAAASARAADZBAAgEgAAwAQAIBMAAM4EACAUAADZBAAgFQAA2gQAIBYAANsEACAXAADcBAAgGQAA3QQAIBoAAM8EACAbAADeBAAgHAAA3wQAIB0AAOAEACC-AgAA1wQAML8CAAAXABDAAgAA1wQAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAhgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACG4AwAAFwAguQMAABcAICUEAADoBAAgBQAA6QQAIAYAAOoEACAeAADbBAAgHwAA3QQAICEAAOsEACAiAADeBAAgIwAA3wQAICQAAOAEACAlAADsBAAgvgIAAOQEADC_AgAADwAQwAIAAOQEADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIesCAQCaBAAh7AIBAJoEACHwAgEAmgQAIYwDQAC7BAAhowMgALoEACGkAwEAmgQAIaYDAADlBKYDIqgDAADmBKgDIqkDIAC6BAAhqgMBAJoEACGrAwEAmgQAIawDAADDBAAgrQNAALsEACGuAwEAmgQAIa8DIADnBAAhsAMBAJoEACGxA0AAuwQAIbIDQAC7BAAhuAMAAA8AILkDAAAPACAC2gIBAAAAAdsCAQAAAAEIAwAAvAQAIAcAAMQEACC-AgAAxwQAML8CAAA6ABDAAgAAxwQAMMcCQACbBAAh2gIBAJgEACHbAgEAmAQAIQLbAgEAAAAB5wIBAAAAAQoHAADEBAAgGAAAxQQAIL4CAADJBAAwvwIAADQAEMACAADJBAAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiIEyQIAAADpAgLKAgAAAOkCCMsCAAAA6QII0AIAAJAE6QIiDAcAAMQEACC-AgAAywQAML8CAAAwABDAAgAAywQAMMECAQCYBAAhxwJAAJsEACHbAgEAmAQAIeoCAgC5BAAh6wIBAJoEACHsAgEAmgQAIe0CAQCaBAAh7gIBAJoEACEC2wIBAAAAAd4CAgAAAAETBwAAxAQAIAgAAMAEACAJAADOBAAgDgAAnAQAIBAAAM8EACC-AgAAzQQAML8CAAAVABDAAgAAzQQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACED8gIAABcAIPMCAAAXACD0AgAAFwAgA_ICAAAiACDzAgAAIgAg9AIAACIAIAsHAADEBAAgDwAA0gQAIL4CAADQBAAwvwIAACIAEMACAADQBAAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh4AIAANEE-AIi9QICALkEACH2AgEAmAQAIQTJAgAAAPgCAsoCAAAA-AIIywIAAAD4AgjQAgAAoAT4AiIVBwAAxAQAIAgAAMAEACAJAADOBAAgDgAAnAQAIBAAAM8EACC-AgAAzQQAML8CAAAVABDAAgAAzQQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACG4AwAAFQAguQMAABUAIAPbAgEAAAAB3gICAAAAAfgCAQAAAAEJCgAA0gQAIA0AANUEACC-AgAA1AQAML8CAAAcABDAAgAA1AQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfgCAQCYBAAhCwsAAJwEACC-AgAAlwQAML8CAAC4AgAQwAIAAJcEADDBAgEAmAQAIccCQACbBAAh6gICAJkEACHsAgEAmAQAIfECAQCaBAAhuAMAALgCACC5AwAAuAIAIALBAgEAAAABgQMCAAAAAR4RAADZBAAgEgAAwAQAIBMAAM4EACAUAADZBAAgFQAA2gQAIBYAANsEACAXAADcBAAgGQAA3QQAIBoAAM8EACAbAADeBAAgHAAA3wQAIB0AAOAEACC-AgAA1wQAML8CAAAXABDAAgAA1wQAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAhgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACEEyQIAAACFAwLKAgAAAIUDCMsCAAAAhQMI0AIAAKkEhQMiFQcAAMQEACAIAADABAAgCQAAzgQAIA4AAJwEACAQAADPBAAgvgIAAM0EADC_AgAAFQAQwAIAAM0EADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH5AgEAmAQAIfoCAQCaBAAh-wIBAJoEACH8AgEAmgQAIf0CAQCYBAAh_gIBAJoEACH_AgEAmgQAIYADQAC7BAAhuAMAABUAILkDAAAVACAD8gIAABUAIPMCAAAVACD0AgAAFQAgA_ICAAARACDzAgAAEQAg9AIAABEAIAPyAgAAMAAg8wIAADAAIPQCAAAwACAD8gIAADQAIPMCAAA0ACD0AgAANAAgA_ICAAA6ACDzAgAAOgAg9AIAADoAIAPyAgAAPgAg8wIAAD4AIPQCAAA-ACAD8gIAAEMAIPMCAABDACD0AgAAQwAgAtoCAQAAAAHbAgEAAAABCgMAALwEACAHAADEBAAgvgIAAOIEADC_AgAAEQAQwAIAAOIEADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACHtAgEAmgQAIfACAADjBPACIgTJAgAAAPACAsoCAAAA8AIIywIAAADwAgjQAgAAlQTwAiIjBAAA6AQAIAUAAOkEACAGAADqBAAgHgAA2wQAIB8AAN0EACAhAADrBAAgIgAA3gQAICMAAN8EACAkAADgBAAgJQAA7AQAIL4CAADkBAAwvwIAAA8AEMACAADkBAAwwQIBAJgEACHHAkAAmwQAId0CQACbBAAh6gICAJkEACHrAgEAmgQAIewCAQCaBAAh8AIBAJoEACGMA0AAuwQAIaMDIAC6BAAhpAMBAJoEACGmAwAA5QSmAyKoAwAA5gSoAyKpAyAAugQAIaoDAQCaBAAhqwMBAJoEACGsAwAAwwQAIK0DQAC7BAAhrgMBAJoEACGvAyAA5wQAIbADAQCaBAAhsQNAALsEACGyA0AAuwQAIQTJAgAAAKYDAsoCAAAApgMIywIAAACmAwjQAgAAtwSmAyIEyQIAAACoAwLKAgAAAKgDCMsCAAAAqAMI0AIAALUEqAMiAskCIAAAAAHQAiAAswQAIQPyAgAAAwAg8wIAAAMAIPQCAAADACAD8gIAAAcAIPMCAAAHACD0AgAABwAgA_ICAAALACDzAgAACwAg9AIAAAsAIAPyAgAAUgAg8wIAAFIAIPQCAABSACAD8gIAAFkAIPMCAABZACD0AgAAWQAgCwMAAMUEACC-AgAA7QQAML8CAAALABDAAgAA7QQAMMECAQCYBAAhxwJAALsEACHaAgEAmgQAId0CQAC7BAAhlAMBAJgEACGVAwEAmAQAIZYDQACbBAAhDQMAALwEACC-AgAA7gQAML8CAAAHABDAAgAA7gQAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAh4wIBAJoEACGWA0AAmwQAIZcDAQCYBAAhmAMBAJoEACGZAwEAmgQAIREDAAC8BAAgvgIAAO8EADC_AgAAAwAQwAIAAO8EADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHdAkAAmwQAIZoDAQCYBAAhmwMBAJgEACGcAwEAmgQAIZ0DAQCaBAAhngNAALsEACGfA0AAuwQAIaADAQCaBAAhoQMBAJoEACGiAwEAmgQAIQAAAAABvQMBAAAAAQG9A0AAAAABAb0DQAAAAAEFMgAAxQkAIDMAAMgJACC6AwAAxgkAILsDAADHCQAgwAMAAAEAIAMyAADFCQAgugMAAMYJACDAAwAAAQAgAAAAAAAFvQMCAAAAAcMDAgAAAAHEAwIAAAABxQMCAAAAAcYDAgAAAAEBvQMBAAAAAQUyAAC9CQAgMwAAwwkAILoDAAC-CQAguwMAAMIJACDAAwAAAQAgBzIAALsJACAzAADACQAgugMAALwJACC7AwAAvwkAIL4DAAAXACC_AwAAFwAgwAMAABoAIAMyAAC9CQAgugMAAL4JACDAAwAAAQAgAzIAALsJACC6AwAAvAkAIMADAAAaACAAAAAAAAW9AwIAAAABwwMCAAAAAcQDAgAAAAHFAwIAAAABxgMCAAAAAQG9AwAAAOACAgUyAACzCQAgMwAAuQkAILoDAAC0CQAguwMAALgJACDAAwAAGgAgBzIAALEJACAzAAC2CQAgugMAALIJACC7AwAAtQkAIL4DAAAPACC_AwAADwAgwAMAAAEAIAMyAACzCQAgugMAALQJACDAAwAAGgAgAzIAALEJACC6AwAAsgkAIMADAAABACAAAAAFMgAAqQkAIDMAAK8JACC6AwAAqgkAILsDAACuCQAgwAMAABoAIAUyAACnCQAgMwAArAkAILoDAACoCQAguwMAAKsJACDAAwAAAQAgAzIAAKkJACC6AwAAqgkAIMADAAAaACADMgAApwkAILoDAACoCQAgwAMAAAEAIAAAAAG9AwAAAOkCAgUyAACfCQAgMwAApQkAILoDAACgCQAguwMAAKQJACDAAwAAGgAgBzIAAJ0JACAzAACiCQAgugMAAJ4JACC7AwAAoQkAIL4DAAAPACC_AwAADwAgwAMAAAEAIAMyAACfCQAgugMAAKAJACDAAwAAGgAgAzIAAJ0JACC6AwAAngkAIMADAAABACAAAAAAAAUyAACYCQAgMwAAmwkAILoDAACZCQAguwMAAJoJACDAAwAAGgAgAzIAAJgJACC6AwAAmQkAIMADAAAaACAAAAABvQMAAADwAgIFMgAAkAkAIDMAAJYJACC6AwAAkQkAILsDAACVCQAgwAMAABoAIAUyAACOCQAgMwAAkwkAILoDAACPCQAguwMAAJIJACDAAwAAAQAgAzIAAJAJACC6AwAAkQkAIMADAAAaACADMgAAjgkAILoDAACPCQAgwAMAAAEAIAAAAAAACzIAALMFADAzAAC4BQAwugMAALQFADC7AwAAtQUAMLwDAAC2BQAgvQMAALcFADC-AwAAtwUAML8DAAC3BQAwwAMAALcFADDBAwAAuQUAMMIDAAC6BQAwBAoAAMAFACDHAkAAAAAB2wIBAAAAAd4CAgAAAAECAAAAHgAgMgAAvwUAIAMAAAAeACAyAAC_BQAgMwAAvQUAIAErAACNCQAwCgoAANIEACANAADVBAAgvgIAANQEADC_AgAAHAAQwAIAANQEADDHAkAAmwQAIdsCAQCYBAAh3gICALkEACH4AgEAmAQAIbYDAADTBAAgAgAAAB4AICsAAL0FACACAAAAuwUAICsAALwFACAHvgIAALoFADC_AgAAuwUAEMACAAC6BQAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-AIBAJgEACEHvgIAALoFADC_AgAAuwUAEMACAAC6BQAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-AIBAJgEACEDxwJAAPUEACHbAgEA9AQAId4CAgD-BAAhBAoAAL4FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACEFMgAAiAkAIDMAAIsJACC6AwAAiQkAILsDAACKCQAgwAMAAC0AIAQKAADABQAgxwJAAAAAAdsCAQAAAAHeAgIAAAABAzIAAIgJACC6AwAAiQkAIMADAAAtACAEMgAAswUAMLoDAAC0BQAwvAMAALYFACDAAwAAtwUAMAAAAAAAAAG9AwAAAPgCAgUyAACACQAgMwAAhgkAILoDAACBCQAguwMAAIUJACDAAwAAGgAgBTIAAP4IACAzAACDCQAgugMAAP8IACC7AwAAggkAIMADAAAtACADMgAAgAkAILoDAACBCQAgwAMAABoAIAMyAAD-CAAgugMAAP8IACDAAwAALQAgAAAAAAAFMgAA-QgAIDMAAPwIACC6AwAA-ggAILsDAAD7CAAgwAMAALUCACADMgAA-QgAILoDAAD6CAAgwAMAALUCACAAAAAAAAUyAADZCAAgMwAA9wgAILoDAADaCAAguwMAAPYIACDAAwAAGgAgBzIAAOwGACAzAACGBwAgugMAAO0GACC7AwAAhQcAIL4DAAAXACC_AwAAFwAgwAMAABoAIAsyAADzBQAwMwAA-AUAMLoDAAD0BQAwuwMAAPUFADC8AwAA9gUAIL0DAAD3BQAwvgMAAPcFADC_AwAA9wUAMMADAAD3BQAwwQMAAPkFADDCAwAA-gUAMAsyAADqBQAwMwAA7gUAMLoDAADrBQAwuwMAAOwFADC8AwAA7QUAIL0DAAC3BQAwvgMAALcFADC_AwAAtwUAMMADAAC3BQAwwQMAAO8FADDCAwAAugUAMAsyAADeBQAwMwAA4wUAMLoDAADfBQAwuwMAAOAFADC8AwAA4QUAIL0DAADiBQAwvgMAAOIFADC_AwAA4gUAMMADAADiBQAwwQMAAOQFADDCAwAA5QUAMAUHAADLBQAgwQIBAAAAAccCQAAAAAHgAgAAAPgCAvYCAQAAAAECAAAAJAAgMgAA6QUAIAMAAAAkACAyAADpBQAgMwAA6AUAIAErAAD1CAAwCwcAAMQEACAPAADSBAAgvgIAANAEADC_AgAAIgAQwAIAANAEADDBAgEAAAABxwJAAJsEACHbAgEAmAQAIeACAADRBPgCIvUCAgC5BAAh9gIBAJgEACECAAAAJAAgKwAA6AUAIAIAAADmBQAgKwAA5wUAIAm-AgAA5QUAML8CAADmBQAQwAIAAOUFADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHgAgAA0QT4AiL1AgIAuQQAIfYCAQCYBAAhCb4CAADlBQAwvwIAAOYFABDAAgAA5QUAMMECAQCYBAAhxwJAAJsEACHbAgEAmAQAIeACAADRBPgCIvUCAgC5BAAh9gIBAJgEACEEwQIBAPQEACHHAkAA9QQAIeACAADIBfgCIvYCAQD0BAAhBQcAAMkFACDBAgEA9AQAIccCQAD1BAAh4AIAAMgF-AIi9gIBAPQEACEFBwAAywUAIMECAQAAAAHHAkAAAAAB4AIAAAD4AgL2AgEAAAABAw0AANMFACDHAkAAAAAB-AIBAAAAAQIAAAAeACAyAADyBQAgAwAAAB4AIDIAAPIFACAzAADxBQAgASsAAPQIADACAAAAHgAgKwAA8QUAIAIAAAC7BQAgKwAA8AUAIALHAkAA9QQAIfgCAQD0BAAhAw0AANIFACDHAkAA9QQAIfgCAQD0BAAhAw0AANMFACDHAkAAAAAB-AIBAAAAARgRAAD9BgAgEgAA7gYAIBMAAO8GACAVAADxBgAgFgAA8gYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAIQHACADAAAAGgAgMgAAhAcAIDMAAP8FACABKwAA8wgAMB8RAADZBAAgEgAAwAQAIBMAAM4EACAUAADZBAAgFQAA2gQAIBYAANsEACAXAADcBAAgGQAA3QQAIBoAAM8EACAbAADeBAAgHAAA3wQAIB0AAOAEACC-AgAA1wQAML8CAAAXABDAAgAA1wQAMMECAQAAAAHHAkAAmwQAId0CQACbBAAh6gICAAAAAYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhtwMAANYEACACAAAAGgAgKwAA_wUAIAIAAAD7BQAgKwAA_AUAIBK-AgAA-gUAML8CAAD7BQAQwAIAAPoFADDBAgEAmAQAIccCQACbBAAh3QJAAJsEACHqAgIAmQQAIYEDAgCZBAAhggMBAJoEACGDAwIAmQQAIYUDAADYBIUDIoYDIAC6BAAhhwMgALoEACGIAwIAuQQAIYkDAgC5BAAhigMCALkEACGLAwIAuQQAIYwDQAC7BAAhEr4CAAD6BQAwvwIAAPsFABDAAgAA-gUAMMECAQCYBAAhxwJAAJsEACHdAkAAmwQAIeoCAgCZBAAhgQMCAJkEACGCAwEAmgQAIYMDAgCZBAAhhQMAANgEhQMihgMgALoEACGHAyAAugQAIYgDAgC5BAAhiQMCALkEACGKAwIAuQQAIYsDAgC5BAAhjANAALsEACENwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhAb0DAAAAhQMCAb0DIAAAAAEYEQAAgAYAIBIAAIEGACATAACCBgAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEHMgAA4AgAIDMAAPEIACC6AwAA4QgAILsDAADwCAAgvgMAABUAIL8DAAAVACDAAwAALQAgBzIAAOMIACAzAADuCAAgugMAAOQIACC7AwAA7QgAIL4DAAAXACC_AwAAFwAgwAMAABoAIAsyAAD5BgAwMwAA_wYAMLoDAAD6BgAwuwMAAP4GADC8AwAA-wYAIL0DAAD3BQAwvgMAAPcFADC_AwAA9wUAMMADAAD3BQAwwQMAAIAHADDCAwAA-gUAMAsyAADcBgAwMwAA4QYAMLoDAADdBgAwuwMAAN4GADC8AwAA3wYAIL0DAADgBgAwvgMAAOAGADC_AwAA4AYAMMADAADgBgAwwQMAAOIGADDCAwAA4wYAMAsyAADQBgAwMwAA1QYAMLoDAADRBgAwuwMAANIGADC8AwAA0wYAIL0DAADUBgAwvgMAANQGADC_AwAA1AYAMMADAADUBgAwwQMAANYGADDCAwAA1wYAMAsyAADEBgAwMwAAyQYAMLoDAADFBgAwuwMAAMYGADC8AwAAxwYAIL0DAADIBgAwvgMAAMgGADC_AwAAyAYAMMADAADIBgAwwQMAAMoGADDCAwAAywYAMAsyAAC4BgAwMwAAvQYAMLoDAAC5BgAwuwMAALoGADC8AwAAuwYAIL0DAAC8BgAwvgMAALwGADC_AwAAvAYAMMADAAC8BgAwwQMAAL4GADDCAwAAvwYAMAsyAACvBgAwMwAAswYAMLoDAACwBgAwuwMAALEGADC8AwAAsgYAIL0DAADiBQAwvgMAAOIFADC_AwAA4gUAMMADAADiBQAwwQMAALQGADDCAwAA5QUAMAsyAACjBgAwMwAAqAYAMLoDAACkBgAwuwMAAKUGADC8AwAApgYAIL0DAACnBgAwvgMAAKcGADC_AwAApwYAMMADAACnBgAwwQMAAKkGADDCAwAAqgYAMAsyAACXBgAwMwAAnAYAMLoDAACYBgAwuwMAAJkGADC8AwAAmgYAIL0DAACbBgAwvgMAAJsGADC_AwAAmwYAMMADAACbBgAwwQMAAJ0GADDCAwAAngYAMAsyAACLBgAwMwAAkAYAMLoDAACMBgAwuwMAAI0GADC8AwAAjgYAIL0DAACPBgAwvgMAAI8GADC_AwAAjwYAMMADAACPBgAwwQMAAJEGADDCAwAAkgYAMAcDAACCBQAgK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB3AICAAAAAd0CQAAAAAECAAAARQAgMgAAlgYAIAMAAABFACAyAACWBgAgMwAAlQYAIAErAADsCAAwDAMAALwEACAHAADABAAgKwAAvgQAIL4CAAC_BAAwvwIAAEMAEMACAAC_BAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACECAAAARQAgKwAAlQYAIAIAAACTBgAgKwAAlAYAIAorAAC-BAAgvgIAAJIGADC_AgAAkwYAEMACAACSBgAwwQIBAJgEACHHAkAAmwQAIdoCAQCYBAAh2wIBAJoEACHcAgIAuQQAId0CQACbBAAhCisAAL4EACC-AgAAkgYAML8CAACTBgAQwAIAAJIGADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHbAgEAmgQAIdwCAgC5BAAh3QJAAJsEACEGK4AAAAABwQIBAPQEACHHAkAA9QQAIdoCAQD0BAAh3AICAP4EACHdAkAA9QQAIQcDAACABQAgK4AAAAABwQIBAPQEACHHAkAA9QQAIdoCAQD0BAAh3AICAP4EACHdAkAA9QQAIQcDAACCBQAgK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB3AICAAAAAd0CQAAAAAEMAwAAjgUAIMECAQAAAAHHAkAAAAAB2gIBAAAAAd4CAgAAAAHgAgAAAOACAuECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAoAAAAAB5gIBAAAAAQIAAABAACAyAACiBgAgAwAAAEAAIDIAAKIGACAzAAChBgAgASsAAOsIADARAwAAxQQAIAcAAMQEACC-AgAAwQQAML8CAAA-ABDAAgAAwQQAMMECAQAAAAHHAkAAmwQAIdoCAQCaBAAh2wIBAJgEACHeAgIAmQQAIeACAADCBOACIuECAQCaBAAh4gIBAJoEACHjAgEAmgQAIeQCAQCaBAAh5QIAAMMEACDmAgEAmgQAIQIAAABAACArAAChBgAgAgAAAJ8GACArAACgBgAgD74CAACeBgAwvwIAAJ8GABDAAgAAngYAMMECAQCYBAAhxwJAAJsEACHaAgEAmgQAIdsCAQCYBAAh3gICAJkEACHgAgAAwgTgAiLhAgEAmgQAIeICAQCaBAAh4wIBAJoEACHkAgEAmgQAIeUCAADDBAAg5gIBAJoEACEPvgIAAJ4GADC_AgAAnwYAEMACAACeBgAwwQIBAJgEACHHAkAAmwQAIdoCAQCaBAAh2wIBAJgEACHeAgIAmQQAIeACAADCBOACIuECAQCaBAAh4gIBAJoEACHjAgEAmgQAIeQCAQCaBAAh5QIAAMMEACDmAgEAmgQAIQvBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHeAgIAiQUAIeACAACKBeACIuECAQD_BAAh4gIBAP8EACHjAgEA_wQAIeQCAQD_BAAh5QKAAAAAAeYCAQD_BAAhDAMAAIwFACDBAgEA9AQAIccCQAD1BAAh2gIBAP8EACHeAgIAiQUAIeACAACKBeACIuECAQD_BAAh4gIBAP8EACHjAgEA_wQAIeQCAQD_BAAh5QKAAAAAAeYCAQD_BAAhDAMAAI4FACDBAgEAAAABxwJAAAAAAdoCAQAAAAHeAgIAAAAB4AIAAADgAgLhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QKAAAAAAeYCAQAAAAEDAwAAlQUAIMcCQAAAAAHaAgEAAAABAgAAADwAIDIAAK4GACADAAAAPAAgMgAArgYAIDMAAK0GACABKwAA6ggAMAkDAAC8BAAgBwAAxAQAIL4CAADHBAAwvwIAADoAEMACAADHBAAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAhswMAAMYEACACAAAAPAAgKwAArQYAIAIAAACrBgAgKwAArAYAIAa-AgAAqgYAML8CAACrBgAQwAIAAKoGADDHAkAAmwQAIdoCAQCYBAAh2wIBAJgEACEGvgIAAKoGADC_AgAAqwYAEMACAACqBgAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAhAscCQAD1BAAh2gIBAPQEACEDAwAAkwUAIMcCQAD1BAAh2gIBAPQEACEDAwAAlQUAIMcCQAAAAAHaAgEAAAABBg8AAMwFACDBAgEAAAABxwJAAAAAAeACAAAA-AIC9QICAAAAAfYCAQAAAAECAAAAJAAgMgAAtwYAIAMAAAAkACAyAAC3BgAgMwAAtgYAIAErAADpCAAwAgAAACQAICsAALYGACACAAAA5gUAICsAALUGACAFwQIBAPQEACHHAkAA9QQAIeACAADIBfgCIvUCAgD-BAAh9gIBAPQEACEGDwAAygUAIMECAQD0BAAhxwJAAPUEACHgAgAAyAX4AiL1AgIA_gQAIfYCAQD0BAAhBg8AAMwFACDBAgEAAAABxwJAAAAAAeACAAAA-AIC9QICAAAAAfYCAQAAAAEFGAAAnQUAIMECAQAAAAHHAkAAAAAB5wIBAAAAAekCAAAA6QICAgAAADYAIDIAAMMGACADAAAANgAgMgAAwwYAIDMAAMIGACABKwAA6AgAMAsHAADEBAAgGAAAxQQAIL4CAADJBAAwvwIAADQAEMACAADJBAAwwQIBAAAAAccCQACbBAAh2wIBAJgEACHnAgEAmgQAIekCAADKBOkCIrQDAADIBAAgAgAAADYAICsAAMIGACACAAAAwAYAICsAAMEGACAIvgIAAL8GADC_AgAAwAYAEMACAAC_BgAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiIIvgIAAL8GADC_AgAAwAYAEMACAAC_BgAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh5wIBAJoEACHpAgAAygTpAiIEwQIBAPQEACHHAkAA9QQAIecCAQD_BAAh6QIAAJkF6QIiBRgAAJsFACDBAgEA9AQAIccCQAD1BAAh5wIBAP8EACHpAgAAmQXpAiIFGAAAnQUAIMECAQAAAAHHAkAAAAAB5wIBAAAAAekCAAAA6QICB8ECAQAAAAHHAkAAAAAB6gICAAAAAesCAQAAAAHsAgEAAAAB7QIBAAAAAe4CAQAAAAECAAAAMgAgMgAAzwYAIAMAAAAyACAyAADPBgAgMwAAzgYAIAErAADnCAAwDAcAAMQEACC-AgAAywQAML8CAAAwABDAAgAAywQAMMECAQAAAAHHAkAAmwQAIdsCAQCYBAAh6gICAAAAAesCAQCaBAAh7AIBAJoEACHtAgEAmgQAIe4CAQCaBAAhAgAAADIAICsAAM4GACACAAAAzAYAICsAAM0GACALvgIAAMsGADC_AgAAzAYAEMACAADLBgAwwQIBAJgEACHHAkAAmwQAIdsCAQCYBAAh6gICALkEACHrAgEAmgQAIewCAQCaBAAh7QIBAJoEACHuAgEAmgQAIQu-AgAAywYAML8CAADMBgAQwAIAAMsGADDBAgEAmAQAIccCQACbBAAh2wIBAJgEACHqAgIAuQQAIesCAQCaBAAh7AIBAJoEACHtAgEAmgQAIe4CAQCaBAAhB8ECAQD0BAAhxwJAAPUEACHqAgIA_gQAIesCAQD_BAAh7AIBAP8EACHtAgEA_wQAIe4CAQD_BAAhB8ECAQD0BAAhxwJAAPUEACHqAgIA_gQAIesCAQD_BAAh7AIBAP8EACHtAgEA_wQAIe4CAQD_BAAhB8ECAQAAAAHHAkAAAAAB6gICAAAAAesCAQAAAAHsAgEAAAAB7QIBAAAAAe4CAQAAAAEFAwAArAUAIMcCQAAAAAHaAgEAAAAB7QIBAAAAAfACAAAA8AICAgAAABMAIDIAANsGACADAAAAEwAgMgAA2wYAIDMAANoGACABKwAA5ggAMAsDAAC8BAAgBwAAxAQAIL4CAADiBAAwvwIAABEAEMACAADiBAAwxwJAAJsEACHaAgEAmAQAIdsCAQCYBAAh7QIBAJoEACHwAgAA4wTwAiKzAwAA4QQAIAIAAAATACArAADaBgAgAgAAANgGACArAADZBgAgCL4CAADXBgAwvwIAANgGABDAAgAA1wYAMMcCQACbBAAh2gIBAJgEACHbAgEAmAQAIe0CAQCaBAAh8AIAAOME8AIiCL4CAADXBgAwvwIAANgGABDAAgAA1wYAMMcCQACbBAAh2gIBAJgEACHbAgEAmAQAIe0CAQCaBAAh8AIAAOME8AIiBMcCQAD1BAAh2gIBAPQEACHtAgEA_wQAIfACAACoBfACIgUDAACqBQAgxwJAAPUEACHaAgEA9AQAIe0CAQD_BAAh8AIAAKgF8AIiBQMAAKwFACDHAkAAAAAB2gIBAAAAAe0CAQAAAAHwAgAAAPACAg4IAADoBgAgCQAA6QYAIA4AAOoGACAQAADrBgAgxwJAAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQIAAAAtACAyAADnBgAgAwAAAC0AIDIAAOcGACAzAADmBgAgASsAAOUIADAUBwAAxAQAIAgAAMAEACAJAADOBAAgDgAAnAQAIBAAAM8EACC-AgAAzQQAML8CAAAVABDAAgAAzQQAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACG1AwAAzAQAIAIAAAAtACArAADmBgAgAgAAAOQGACArAADlBgAgDr4CAADjBgAwvwIAAOQGABDAAgAA4wYAMMcCQACbBAAh2wIBAJgEACHeAgIAuQQAIfkCAQCYBAAh-gIBAJoEACH7AgEAmgQAIfwCAQCaBAAh_QIBAJgEACH-AgEAmgQAIf8CAQCaBAAhgANAALsEACEOvgIAAOMGADC_AgAA5AYAEMACAADjBgAwxwJAAJsEACHbAgEAmAQAId4CAgC5BAAh-QIBAJgEACH6AgEAmgQAIfsCAQCaBAAh_AIBAJoEACH9AgEAmAQAIf4CAQCaBAAh_wIBAJoEACGAA0AAuwQAIQrHAkAA9QQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQ4IAADaBQAgCQAA2wUAIA4AANwFACAQAADdBQAgxwJAAPUEACHeAgIA_gQAIfkCAQD0BAAh-gIBAP8EACH7AgEA_wQAIfwCAQD_BAAh_QIBAPQEACH-AgEA_wQAIf8CAQD_BAAhgANAAPYEACEOCAAA6AYAIAkAAOkGACAOAADqBgAgEAAA6wYAIMcCQAAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAEDMgAA7AYAILoDAADtBgAgwAMAABoAIAQyAADzBQAwugMAAPQFADC8AwAA9gUAIMADAAD3BQAwBDIAAOoFADC6AwAA6wUAMLwDAADtBQAgwAMAALcFADAEMgAA3gUAMLoDAADfBQAwvAMAAOEFACDAAwAA4gUAMBgSAADuBgAgEwAA7wYAIBQAAPAGACAVAADxBgAgFgAA8gYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMcCQAAAAAHdAkAAAAAB6gICAAAAAYIDAQAAAAGDAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAOwGACADMgAA4wgAILoDAADkCAAgwAMAABoAIAQyAAD5BgAwugMAAPoGADC8AwAA-wYAIMADAAD3BQAwAzIAANsIACC6AwAA3AgAIMADAAAtACAEMgAA3AYAMLoDAADdBgAwvAMAAN8GACDAAwAA4AYAMAQyAADQBgAwugMAANEGADC8AwAA0wYAIMADAADUBgAwBDIAAMQGADC6AwAAxQYAMLwDAADHBgAgwAMAAMgGADAEMgAAuAYAMLoDAAC5BgAwvAMAALsGACDAAwAAvAYAMAQyAACvBgAwugMAALAGADC8AwAAsgYAIMADAADiBQAwBDIAAKMGADC6AwAApAYAMLwDAACmBgAgwAMAAKcGADAEMgAAlwYAMLoDAACYBgAwvAMAAJoGACDAAwAAmwYAMAQyAACLBgAwugMAAIwGADC8AwAAjgYAIMADAACPBgAwGREAAP0GACATAADvBgAgFAAA8AYAIBUAAPEGACAWAADyBgAgFwAA8wYAIBkAAPQGACAaAAD1BgAgGwAA9gYAIBwAAPcGACAdAAD4BgAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAYEDAgAAAAGDAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAPwGACABKwAA4ggAMBkRAAD9BgAgEwAA7wYAIBQAAPAGACAVAADxBgAgFgAA8gYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABgwMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQMyAADgCAAgugMAAOEIACDAAwAALQAgAwAAABoAIDIAAPwGACAzAACCBwAgAgAAABoAICsAAIIHACACAAAA-wUAICsAAIEHACAOwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEZEQAAgAYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIQcyAADbCAAgMwAA3ggAILoDAADcCAAguwMAAN0IACC-AwAAFQAgvwMAABUAIMADAAAtACAYEQAA_QYAIBIAAO4GACATAADvBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHAAA9wYAIB0AAPgGACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAABgQMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQMAAAAXACAyAADsBgAgMwAAhwcAIBoAAAAXACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAIcHACDHAkAA9QQAId0CQAD1BAAh6gICAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEYEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDHAkAA9QQAId0CQAD1BAAh6gICAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEDMgAA2QgAILoDAADaCAAgwAMAABoAIAAAAAAAAAAAAAAFMgAA1AgAIDMAANcIACC6AwAA1QgAILsDAADWCAAgwAMAAAEAIAMyAADUCAAgugMAANUIACDAAwAAAQAgAAAABzIAAM8IACAzAADSCAAgugMAANAIACC7AwAA0QgAIL4DAAAPACC_AwAADwAgwAMAAAEAIAMyAADPCAAgugMAANAIACDAAwAAAQAgAAAABTIAAMoIACAzAADNCAAgugMAAMsIACC7AwAAzAgAIMADAAABACADMgAAyggAILoDAADLCAAgwAMAAAEAIAAAAAUyAADFCAAgMwAAyAgAILoDAADGCAAguwMAAMcIACDAAwAAAQAgAzIAAMUIACC6AwAAxggAIMADAAABACAAAAAAAAG9AwAAAKYDAgG9AwAAAKgDAgG9AyAAAAABCzIAAJMIADAzAACYCAAwugMAAJQIADC7AwAAlQgAMLwDAACWCAAgvQMAAJcIADC-AwAAlwgAML8DAACXCAAwwAMAAJcIADDBAwAAmQgAMMIDAACaCAAwCzIAAIcIADAzAACMCAAwugMAAIgIADC7AwAAiQgAMLwDAACKCAAgvQMAAIsIADC-AwAAiwgAML8DAACLCAAwwAMAAIsIADDBAwAAjQgAMMIDAACOCAAwCzIAAPsHADAzAACACAAwugMAAPwHADC7AwAA_QcAMLwDAAD-BwAgvQMAAP8HADC-AwAA_wcAML8DAAD_BwAwwAMAAP8HADDBAwAAgQgAMMIDAACCCAAwCzIAAPIHADAzAAD2BwAwugMAAPMHADC7AwAA9AcAMLwDAAD1BwAgvQMAANQGADC-AwAA1AYAML8DAADUBgAwwAMAANQGADDBAwAA9wcAMMIDAADXBgAwCzIAAOkHADAzAADtBwAwugMAAOoHADC7AwAA6wcAMLwDAADsBwAgvQMAALwGADC-AwAAvAYAML8DAAC8BgAwwAMAALwGADDBAwAA7gcAMMIDAAC_BgAwCzIAAN0HADAzAADiBwAwugMAAN4HADC7AwAA3wcAMLwDAADgBwAgvQMAAOEHADC-AwAA4QcAML8DAADhBwAwwAMAAOEHADDBAwAA4wcAMMIDAADkBwAwCzIAANQHADAzAADYBwAwugMAANUHADC7AwAA1gcAMLwDAADXBwAgvQMAAKcGADC-AwAApwYAML8DAACnBgAwwAMAAKcGADDBAwAA2QcAMMIDAACqBgAwCzIAAMsHADAzAADPBwAwugMAAMwHADC7AwAAzQcAMLwDAADOBwAgvQMAAJsGADC-AwAAmwYAML8DAACbBgAwwAMAAJsGADDBAwAA0AcAMMIDAACeBgAwCzIAAMIHADAzAADGBwAwugMAAMMHADC7AwAAxAcAMLwDAADFBwAgvQMAAI8GADC-AwAAjwYAML8DAACPBgAwwAMAAI8GADDBAwAAxwcAMMIDAACSBgAwCzIAALYHADAzAAC7BwAwugMAALcHADC7AwAAuAcAMLwDAAC5BwAgvQMAALoHADC-AwAAugcAML8DAAC6BwAwwAMAALoHADDBAwAAvAcAMMIDAAC9BwAwCsECAQAAAAHHAkAAAAAB7AIBAAAAAY0DAQAAAAGOAwEAAAABjwMCAAAAAZADAQAAAAGRAyAAAAABkgMBAAAAAZMDAQAAAAECAAAAWwAgMgAAwQcAIAMAAABbACAyAADBBwAgMwAAwAcAIAErAADECAAwDwMAALwEACC-AgAAuAQAML8CAABZABDAAgAAuAQAMMECAQAAAAHHAkAAuwQAIdoCAQCYBAAh7AIBAJoEACGNAwEAmAQAIY4DAQCYBAAhjwMCALkEACGQAwEAmAQAIZEDIAC6BAAhkgMBAJoEACGTAwEAmgQAIQIAAABbACArAADABwAgAgAAAL4HACArAAC_BwAgDr4CAAC9BwAwvwIAAL4HABDAAgAAvQcAMMECAQCYBAAhxwJAALsEACHaAgEAmAQAIewCAQCaBAAhjQMBAJgEACGOAwEAmAQAIY8DAgC5BAAhkAMBAJgEACGRAyAAugQAIZIDAQCaBAAhkwMBAJoEACEOvgIAAL0HADC_AgAAvgcAEMACAAC9BwAwwQIBAJgEACHHAkAAuwQAIdoCAQCYBAAh7AIBAJoEACGNAwEAmAQAIY4DAQCYBAAhjwMCALkEACGQAwEAmAQAIZEDIAC6BAAhkgMBAJoEACGTAwEAmgQAIQrBAgEA9AQAIccCQAD2BAAh7AIBAP8EACGNAwEA9AQAIY4DAQD0BAAhjwMCAP4EACGQAwEA9AQAIZEDIAD-BQAhkgMBAP8EACGTAwEA_wQAIQrBAgEA9AQAIccCQAD2BAAh7AIBAP8EACGNAwEA9AQAIY4DAQD0BAAhjwMCAP4EACGQAwEA9AQAIZEDIAD-BQAhkgMBAP8EACGTAwEA_wQAIQrBAgEAAAABxwJAAAAAAewCAQAAAAGNAwEAAAABjgMBAAAAAY8DAgAAAAGQAwEAAAABkQMgAAAAAZIDAQAAAAGTAwEAAAABBwcAAIMFACArgAAAAAHBAgEAAAABxwJAAAAAAdsCAQAAAAHcAgIAAAAB3QJAAAAAAQIAAABFACAyAADKBwAgAwAAAEUAIDIAAMoHACAzAADJBwAgASsAAMMIADACAAAARQAgKwAAyQcAIAIAAACTBgAgKwAAyAcAIAYrgAAAAAHBAgEA9AQAIccCQAD1BAAh2wIBAP8EACHcAgIA_gQAId0CQAD1BAAhBwcAAIEFACArgAAAAAHBAgEA9AQAIccCQAD1BAAh2wIBAP8EACHcAgIA_gQAId0CQAD1BAAhBwcAAIMFACArgAAAAAHBAgEAAAABxwJAAAAAAdsCAQAAAAHcAgIAAAAB3QJAAAAAAQwHAACNBQAgwQIBAAAAAccCQAAAAAHbAgEAAAAB3gICAAAAAeACAAAA4AIC4QIBAAAAAeICAQAAAAHjAgEAAAAB5AIBAAAAAeUCgAAAAAHmAgEAAAABAgAAAEAAIDIAANMHACADAAAAQAAgMgAA0wcAIDMAANIHACABKwAAwggAMAIAAABAACArAADSBwAgAgAAAJ8GACArAADRBwAgC8ECAQD0BAAhxwJAAPUEACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACEMBwAAiwUAIMECAQD0BAAhxwJAAPUEACHbAgEA9AQAId4CAgCJBQAh4AIAAIoF4AIi4QIBAP8EACHiAgEA_wQAIeMCAQD_BAAh5AIBAP8EACHlAoAAAAAB5gIBAP8EACEMBwAAjQUAIMECAQAAAAHHAkAAAAAB2wIBAAAAAd4CAgAAAAHgAgAAAOACAuECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAoAAAAAB5gIBAAAAAQMHAACUBQAgxwJAAAAAAdsCAQAAAAECAAAAPAAgMgAA3AcAIAMAAAA8ACAyAADcBwAgMwAA2wcAIAErAADBCAAwAgAAADwAICsAANsHACACAAAAqwYAICsAANoHACACxwJAAPUEACHbAgEA9AQAIQMHAACSBQAgxwJAAPUEACHbAgEA9AQAIQMHAACUBQAgxwJAAAAAAdsCAQAAAAEHwQIBAAAAAcICAQAAAAHEAgEAAAABxQIBAAAAAcYCgAAAAAHHAkAAAAAByAJAAAAAAQIAAABUACAyAADoBwAgAwAAAFQAIDIAAOgHACAzAADnBwAgASsAAMAIADAMIAAAvAQAIL4CAAC9BAAwvwIAAFIAEMACAAC9BAAwwQIBAAAAAcICAQCYBAAhwwIBAJgEACHEAgEAmAQAIcUCAQCYBAAhxgIAAL4EACDHAkAAmwQAIcgCQAC7BAAhAgAAAFQAICsAAOcHACACAAAA5QcAICsAAOYHACALvgIAAOQHADC_AgAA5QcAEMACAADkBwAwwQIBAJgEACHCAgEAmAQAIcMCAQCYBAAhxAIBAJgEACHFAgEAmAQAIcYCAAC-BAAgxwJAAJsEACHIAkAAuwQAIQu-AgAA5AcAML8CAADlBwAQwAIAAOQHADDBAgEAmAQAIcICAQCYBAAhwwIBAJgEACHEAgEAmAQAIcUCAQCYBAAhxgIAAL4EACDHAkAAmwQAIcgCQAC7BAAhB8ECAQD0BAAhwgIBAPQEACHEAgEA9AQAIcUCAQD0BAAhxgKAAAAAAccCQAD1BAAhyAJAAPYEACEHwQIBAPQEACHCAgEA9AQAIcQCAQD0BAAhxQIBAPQEACHGAoAAAAABxwJAAPUEACHIAkAA9gQAIQfBAgEAAAABwgIBAAAAAcQCAQAAAAHFAgEAAAABxgKAAAAAAccCQAAAAAHIAkAAAAABBQcAAJwFACDBAgEAAAABxwJAAAAAAdsCAQAAAAHpAgAAAOkCAgIAAAA2ACAyAADxBwAgAwAAADYAIDIAAPEHACAzAADwBwAgASsAAL8IADACAAAANgAgKwAA8AcAIAIAAADABgAgKwAA7wcAIATBAgEA9AQAIccCQAD1BAAh2wIBAPQEACHpAgAAmQXpAiIFBwAAmgUAIMECAQD0BAAhxwJAAPUEACHbAgEA9AQAIekCAACZBekCIgUHAACcBQAgwQIBAAAAAccCQAAAAAHbAgEAAAAB6QIAAADpAgIFBwAAqwUAIMcCQAAAAAHbAgEAAAAB7QIBAAAAAfACAAAA8AICAgAAABMAIDIAAPoHACADAAAAEwAgMgAA-gcAIDMAAPkHACABKwAAvggAMAIAAAATACArAAD5BwAgAgAAANgGACArAAD4BwAgBMcCQAD1BAAh2wIBAPQEACHtAgEA_wQAIfACAACoBfACIgUHAACpBQAgxwJAAPUEACHbAgEA9AQAIe0CAQD_BAAh8AIAAKgF8AIiBQcAAKsFACDHAkAAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgbBAgEAAAABxwJAAAAAAd0CQAAAAAGUAwEAAAABlQMBAAAAAZYDQAAAAAECAAAADQAgMgAAhggAIAMAAAANACAyAACGCAAgMwAAhQgAIAErAAC9CAAwCwMAAMUEACC-AgAA7QQAML8CAAALABDAAgAA7QQAMMECAQAAAAHHAkAAuwQAIdoCAQCaBAAh3QJAALsEACGUAwEAmAQAIZUDAQCYBAAhlgNAAJsEACECAAAADQAgKwAAhQgAIAIAAACDCAAgKwAAhAgAIAq-AgAAgggAML8CAACDCAAQwAIAAIIIADDBAgEAmAQAIccCQAC7BAAh2gIBAJoEACHdAkAAuwQAIZQDAQCYBAAhlQMBAJgEACGWA0AAmwQAIQq-AgAAgggAML8CAACDCAAQwAIAAIIIADDBAgEAmAQAIccCQAC7BAAh2gIBAJoEACHdAkAAuwQAIZQDAQCYBAAhlQMBAJgEACGWA0AAmwQAIQbBAgEA9AQAIccCQAD2BAAh3QJAAPYEACGUAwEA9AQAIZUDAQD0BAAhlgNAAPUEACEGwQIBAPQEACHHAkAA9gQAId0CQAD2BAAhlAMBAPQEACGVAwEA9AQAIZYDQAD1BAAhBsECAQAAAAHHAkAAAAAB3QJAAAAAAZQDAQAAAAGVAwEAAAABlgNAAAAAAQjBAgEAAAABxwJAAAAAAd0CQAAAAAHjAgEAAAABlgNAAAAAAZcDAQAAAAGYAwEAAAABmQMBAAAAAQIAAAAJACAyAACSCAAgAwAAAAkAIDIAAJIIACAzAACRCAAgASsAALwIADANAwAAvAQAIL4CAADuBAAwvwIAAAcAEMACAADuBAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHdAkAAmwQAIeMCAQCaBAAhlgNAAJsEACGXAwEAAAABmAMBAJoEACGZAwEAmgQAIQIAAAAJACArAACRCAAgAgAAAI8IACArAACQCAAgDL4CAACOCAAwvwIAAI8IABDAAgAAjggAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAh4wIBAJoEACGWA0AAmwQAIZcDAQCYBAAhmAMBAJoEACGZAwEAmgQAIQy-AgAAjggAML8CAACPCAAQwAIAAI4IADDBAgEAmAQAIccCQACbBAAh2gIBAJgEACHdAkAAmwQAIeMCAQCaBAAhlgNAAJsEACGXAwEAmAQAIZgDAQCaBAAhmQMBAJoEACEIwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh4wIBAP8EACGWA0AA9QQAIZcDAQD0BAAhmAMBAP8EACGZAwEA_wQAIQjBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHjAgEA_wQAIZYDQAD1BAAhlwMBAPQEACGYAwEA_wQAIZkDAQD_BAAhCMECAQAAAAHHAkAAAAAB3QJAAAAAAeMCAQAAAAGWA0AAAAABlwMBAAAAAZgDAQAAAAGZAwEAAAABDMECAQAAAAHHAkAAAAAB3QJAAAAAAZoDAQAAAAGbAwEAAAABnAMBAAAAAZ0DAQAAAAGeA0AAAAABnwNAAAAAAaADAQAAAAGhAwEAAAABogMBAAAAAQIAAAAFACAyAACeCAAgAwAAAAUAIDIAAJ4IACAzAACdCAAgASsAALsIADARAwAAvAQAIL4CAADvBAAwvwIAAAMAEMACAADvBAAwwQIBAAAAAccCQACbBAAh2gIBAJgEACHdAkAAmwQAIZoDAQCYBAAhmwMBAJgEACGcAwEAmgQAIZ0DAQCaBAAhngNAALsEACGfA0AAuwQAIaADAQCaBAAhoQMBAJoEACGiAwEAmgQAIQIAAAAFACArAACdCAAgAgAAAJsIACArAACcCAAgEL4CAACaCAAwvwIAAJsIABDAAgAAmggAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhEL4CAACaCAAwvwIAAJsIABDAAgAAmggAMMECAQCYBAAhxwJAAJsEACHaAgEAmAQAId0CQACbBAAhmgMBAJgEACGbAwEAmAQAIZwDAQCaBAAhnQMBAJoEACGeA0AAuwQAIZ8DQAC7BAAhoAMBAJoEACGhAwEAmgQAIaIDAQCaBAAhDMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIZoDAQD0BAAhmwMBAPQEACGcAwEA_wQAIZ0DAQD_BAAhngNAAPYEACGfA0AA9gQAIaADAQD_BAAhoQMBAP8EACGiAwEA_wQAIQzBAgEA9AQAIccCQAD1BAAh3QJAAPUEACGaAwEA9AQAIZsDAQD0BAAhnAMBAP8EACGdAwEA_wQAIZ4DQAD2BAAhnwNAAPYEACGgAwEA_wQAIaEDAQD_BAAhogMBAP8EACEMwQIBAAAAAccCQAAAAAHdAkAAAAABmgMBAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABBDIAAJMIADC6AwAAlAgAMLwDAACWCAAgwAMAAJcIADAEMgAAhwgAMLoDAACICAAwvAMAAIoIACDAAwAAiwgAMAQyAAD7BwAwugMAAPwHADC8AwAA_gcAIMADAAD_BwAwBDIAAPIHADC6AwAA8wcAMLwDAAD1BwAgwAMAANQGADAEMgAA6QcAMLoDAADqBwAwvAMAAOwHACDAAwAAvAYAMAQyAADdBwAwugMAAN4HADC8AwAA4AcAIMADAADhBwAwBDIAANQHADC6AwAA1QcAMLwDAADXBwAgwAMAAKcGADAEMgAAywcAMLoDAADMBwAwvAMAAM4HACDAAwAAmwYAMAQyAADCBwAwugMAAMMHADC8AwAAxQcAIMADAACPBgAwBDIAALYHADC6AwAAtwcAMLwDAAC5BwAgwAMAALoHADAAAAAAAAAAAAAAGQQAAKkIACAFAACqCAAgBgAAqwgAIB4AAKwIACAfAACtCAAgIQAArggAICIAAK8IACAjAACwCAAgJAAAsQgAICUAALIIACDqAgAA8AQAIOsCAADwBAAg7AIAAPAEACDwAgAA8AQAIIwDAADwBAAgpAMAAPAEACCqAwAA8AQAIKsDAADwBAAgrAMAAPAEACCtAwAA8AQAIK4DAADwBAAgrwMAAPAEACCwAwAA8AQAILEDAADwBAAgsgMAAPAEACAREQAAtwgAIBIAALQIACATAAC1CAAgFAAAtwgAIBUAALkIACAWAACsCAAgFwAAuggAIBkAAK0IACAaAAC2CAAgGwAArwgAIBwAALAIACAdAACxCAAg6gIAAPAEACCBAwAA8AQAIIIDAADwBAAggwMAAPAEACCMAwAA8AQAIAAACwcAALQIACAIAAC0CAAgCQAAtQgAIA4AAMIFACAQAAC2CAAg-gIAAPAEACD7AgAA8AQAIPwCAADwBAAg_gIAAPAEACD_AgAA8AQAIIADAADwBAAgAwsAAMIFACDqAgAA8AQAIPECAADwBAAgAAAMwQIBAAAAAccCQAAAAAHdAkAAAAABmgMBAAAAAZsDAQAAAAGcAwEAAAABnQMBAAAAAZ4DQAAAAAGfA0AAAAABoAMBAAAAAaEDAQAAAAGiAwEAAAABCMECAQAAAAHHAkAAAAAB3QJAAAAAAeMCAQAAAAGWA0AAAAABlwMBAAAAAZgDAQAAAAGZAwEAAAABBsECAQAAAAHHAkAAAAAB3QJAAAAAAZQDAQAAAAGVAwEAAAABlgNAAAAAAQTHAkAAAAAB2wIBAAAAAe0CAQAAAAHwAgAAAPACAgTBAgEAAAABxwJAAAAAAdsCAQAAAAHpAgAAAOkCAgfBAgEAAAABwgIBAAAAAcQCAQAAAAHFAgEAAAABxgKAAAAAAccCQAAAAAHIAkAAAAABAscCQAAAAAHbAgEAAAABC8ECAQAAAAHHAkAAAAAB2wIBAAAAAd4CAgAAAAHgAgAAAOACAuECAQAAAAHiAgEAAAAB4wIBAAAAAeQCAQAAAAHlAoAAAAAB5gIBAAAAAQYrgAAAAAHBAgEAAAABxwJAAAAAAdsCAQAAAAHcAgIAAAAB3QJAAAAAAQrBAgEAAAABxwJAAAAAAewCAQAAAAGNAwEAAAABjgMBAAAAAY8DAgAAAAGQAwEAAAABkQMgAAAAAZIDAQAAAAGTAwEAAAABHwUAAKAIACAGAAChCAAgHgAAoggAIB8AAKMIACAhAACkCAAgIgAApQgAICMAAKYIACAkAACnCAAgJQAAqAgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADFCAAgAwAAAA8AIDIAAMUIACAzAADJCAAgIQAAAA8AIAUAAK0HACAGAACuBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAICsAAMkIACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAJ8IACAGAAChCAAgHgAAoggAIB8AAKMIACAhAACkCAAgIgAApQgAICMAAKYIACAkAACnCAAgJQAAqAgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADKCAAgAwAAAA8AIDIAAMoIACAzAADOCAAgIQAAAA8AIAQAAKwHACAGAACuBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAICsAAM4IACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBAAArAcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAJ8IACAFAACgCAAgHgAAoggAIB8AAKMIACAhAACkCAAgIgAApQgAICMAAKYIACAkAACnCAAgJQAAqAgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADPCAAgAwAAAA8AIDIAAM8IACAzAADTCAAgIQAAAA8AIAQAAKwHACAFAACtBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAICsAANMIACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBAAArAcAIAUAAK0HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICQAALQHACAlAAC1BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAJ8IACAFAACgCAAgBgAAoQgAIB4AAKIIACAfAACjCAAgIQAApAgAICIAAKUIACAjAACmCAAgJAAApwgAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAfACAQAAAAGMA0AAAAABowMgAAAAAaQDAQAAAAGmAwAAAKYDAqgDAAAAqAMCqQMgAAAAAaoDAQAAAAGrAwEAAAABrAOAAAAAAa0DQAAAAAGuAwEAAAABrwMgAAAAAbADAQAAAAGxA0AAAAABsgNAAAAAAQIAAAABACAyAADUCAAgAwAAAA8AIDIAANQIACAzAADYCAAgIQAAAA8AIAQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICIAALIHACAjAACzBwAgJAAAtAcAICsAANgIACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIesCAQD_BAAh7AIBAP8EACHwAgEA_wQAIYwDQAD2BAAhowMgAP4FACGkAwEA_wQAIaYDAACpB6YDIqgDAACqB6gDIqkDIAD-BQAhqgMBAP8EACGrAwEA_wQAIawDgAAAAAGtA0AA9gQAIa4DAQD_BAAhrwMgAKsHACGwAwEA_wQAIbEDQAD2BAAhsgNAAPYEACEfBAAArAcAIAUAAK0HACAGAACuBwAgHgAArwcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhGhEAAP0GACASAADuBgAgEwAA7wYAIBQAAPAGACAWAADyBgAgFwAA8wYAIBkAAPQGACAaAAD1BgAgGwAA9gYAIBwAAPcGACAdAAD4BgAgwQIBAAAAAccCQAAAAAHdAkAAAAAB6gICAAAAAYEDAgAAAAGCAwEAAAABgwMCAAAAAYUDAAAAhQMChgMgAAAAAYcDIAAAAAGIAwIAAAABiQMCAAAAAYoDAgAAAAGLAwIAAAABjANAAAAAAQIAAAAaACAyAADZCAAgDwcAAIgHACAIAADoBgAgDgAA6gYAIBAAAOsGACDHAkAAAAAB2wIBAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQIAAAAtACAyAADbCAAgAwAAABUAIDIAANsIACAzAADfCAAgEQAAABUAIAcAANkFACAIAADaBQAgDgAA3AUAIBAAAN0FACArAADfCAAgxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQ8HAADZBQAgCAAA2gUAIA4AANwFACAQAADdBQAgxwJAAPUEACHbAgEA9AQAId4CAgD-BAAh-QIBAPQEACH6AgEA_wQAIfsCAQD_BAAh_AIBAP8EACH9AgEA9AQAIf4CAQD_BAAh_wIBAP8EACGAA0AA9gQAIQ8HAACIBwAgCQAA6QYAIA4AAOoGACAQAADrBgAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAECAAAALQAgMgAA4AgAIA7BAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAABgQMCAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAEaEQAA_QYAIBIAAO4GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHAAA9wYAIB0AAPgGACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAABgQMCAAAAAYIDAQAAAAGDAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAgAAABoAIDIAAOMIACAKxwJAAAAAAd4CAgAAAAH5AgEAAAAB-gIBAAAAAfsCAQAAAAH8AgEAAAAB_QIBAAAAAf4CAQAAAAH_AgEAAAABgANAAAAAAQTHAkAAAAAB2gIBAAAAAe0CAQAAAAHwAgAAAPACAgfBAgEAAAABxwJAAAAAAeoCAgAAAAHrAgEAAAAB7AIBAAAAAe0CAQAAAAHuAgEAAAABBMECAQAAAAHHAkAAAAAB5wIBAAAAAekCAAAA6QICBcECAQAAAAHHAkAAAAAB4AIAAAD4AgL1AgIAAAAB9gIBAAAAAQLHAkAAAAAB2gIBAAAAAQvBAgEAAAABxwJAAAAAAdoCAQAAAAHeAgIAAAAB4AIAAADgAgLhAgEAAAAB4gIBAAAAAeMCAQAAAAHkAgEAAAAB5QKAAAAAAeYCAQAAAAEGK4AAAAABwQIBAAAAAccCQAAAAAHaAgEAAAAB3AICAAAAAd0CQAAAAAEDAAAAFwAgMgAA4wgAIDMAAO8IACAcAAAAFwAgEQAAgAYAIBIAAIEGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACArAADvCAAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAACABgAgEgAAgQYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEDAAAAFQAgMgAA4AgAIDMAAPIIACARAAAAFQAgBwAA2QUAIAkAANsFACAOAADcBQAgEAAA3QUAICsAAPIIACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhDwcAANkFACAJAADbBQAgDgAA3AUAIBAAAN0FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhDcECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABhQMAAACFAwKGAyAAAAABhwMgAAAAAYgDAgAAAAGJAwIAAAABigMCAAAAAYsDAgAAAAGMA0AAAAABAscCQAAAAAH4AgEAAAABBMECAQAAAAHHAkAAAAAB4AIAAAD4AgL2AgEAAAABAwAAABcAIDIAANkIACAzAAD4CAAgHAAAABcAIBEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAWAACEBgAgFwAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgKwAA-AgAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEaEQAAgAYAIBIAAIEGACATAACCBgAgFAAAgwcAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAIB0AAIoGACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhBcECAQAAAAHHAkAAAAAB6gICAAAAAewCAQAAAAHxAgEAAAABAgAAALUCACAyAAD5CAAgAwAAALgCACAyAAD5CAAgMwAA_QgAIAcAAAC4AgAgKwAA_QgAIMECAQD0BAAhxwJAAPUEACHqAgIAiQUAIewCAQD0BAAh8QIBAP8EACEFwQIBAPQEACHHAkAA9QQAIeoCAgCJBQAh7AIBAPQEACHxAgEA_wQAIQ8HAACIBwAgCAAA6AYAIAkAAOkGACAOAADqBgAgxwJAAAAAAdsCAQAAAAHeAgIAAAAB-QIBAAAAAfoCAQAAAAH7AgEAAAAB_AIBAAAAAf0CAQAAAAH-AgEAAAAB_wIBAAAAAYADQAAAAAECAAAALQAgMgAA_ggAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAgAkAIAMAAAAVACAyAAD-CAAgMwAAhAkAIBEAAAAVACAHAADZBQAgCAAA2gUAIAkAANsFACAOAADcBQAgKwAAhAkAIMcCQAD1BAAh2wIBAPQEACHeAgIA_gQAIfkCAQD0BAAh-gIBAP8EACH7AgEA_wQAIfwCAQD_BAAh_QIBAPQEACH-AgEA_wQAIf8CAQD_BAAhgANAAPYEACEPBwAA2QUAIAgAANoFACAJAADbBQAgDgAA3AUAIMcCQAD1BAAh2wIBAPQEACHeAgIA_gQAIfkCAQD0BAAh-gIBAP8EACH7AgEA_wQAIfwCAQD_BAAh_QIBAPQEACH-AgEA_wQAIf8CAQD_BAAhgANAAPYEACEDAAAAFwAgMgAAgAkAIDMAAIcJACAcAAAAFwAgEQAAgAYAIBIAAIEGACATAACCBgAgFAAAgwcAIBUAAIMGACAWAACEBgAgFwAAhQYAIBkAAIYGACAbAACIBgAgHAAAiQYAIB0AAIoGACArAACHCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBsAAIgGACAcAACJBgAgHQAAigYAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAhgQMCAIkFACGCAwEA_wQAIYMDAgCJBQAhhQMAAP0FhQMihgMgAP4FACGHAyAA_gUAIYgDAgD-BAAhiQMCAP4EACGKAwIA_gQAIYsDAgD-BAAhjANAAPYEACEPBwAAiAcAIAgAAOgGACAJAADpBgAgEAAA6wYAIMcCQAAAAAHbAgEAAAAB3gICAAAAAfkCAQAAAAH6AgEAAAAB-wIBAAAAAfwCAQAAAAH9AgEAAAAB_gIBAAAAAf8CAQAAAAGAA0AAAAABAgAAAC0AIDIAAIgJACADAAAAFQAgMgAAiAkAIDMAAIwJACARAAAAFQAgBwAA2QUAIAgAANoFACAJAADbBQAgEAAA3QUAICsAAIwJACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhDwcAANkFACAIAADaBQAgCQAA2wUAIBAAAN0FACDHAkAA9QQAIdsCAQD0BAAh3gICAP4EACH5AgEA9AQAIfoCAQD_BAAh-wIBAP8EACH8AgEA_wQAIf0CAQD0BAAh_gIBAP8EACH_AgEA_wQAIYADQAD2BAAhA8cCQAAAAAHbAgEAAAAB3gICAAAAAR8EAACfCAAgBQAAoAgAIAYAAKEIACAfAACjCAAgIQAApAgAICIAAKUIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAjgkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBcAAPMGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAkAkAIAMAAAAPACAyAACOCQAgMwAAlAkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAfAACwBwAgIQAAsQcAICIAALIHACAjAACzBwAgJAAAtAcAICUAALUHACArAACUCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB8AALAHACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACQCQAgMwAAlwkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAJcJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFwAAhQYAIBkAAIYGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAZAAD0BgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAmAkAIAMAAAAXACAyAACYCQAgMwAAnAkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAJwJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBkAAIYGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgIQAApAgAICIAAKUIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAnQkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGgAA9QYAIBsAAPYGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAnwkAIAMAAAAPACAyAACdCQAgMwAAowkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgIQAAsQcAICIAALIHACAjAACzBwAgJAAAtAcAICUAALUHACArAACjCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAhAACxBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACfCQAgMwAApgkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgHQAAigYAICsAAKYJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAaAACHBgAgGwAAiAYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAApwkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAcAAD3BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAqQkAIAMAAAAPACAyAACnCQAgMwAArQkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAjAACzBwAgJAAAtAcAICUAALUHACArAACtCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACpCQAgMwAAsAkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAcAACJBgAgHQAAigYAICsAALAJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBwAAIkGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAiAAClCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAsQkAIBoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHQAA-AYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAswkAIAMAAAAPACAyAACxCQAgMwAAtwkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgJAAAtAcAICUAALUHACArAAC3CQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICIAALIHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQMAAAAXACAyAACzCQAgMwAAugkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHQAAigYAICsAALoJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAdAACKBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIRoRAAD9BgAgEgAA7gYAIBMAAO8GACAUAADwBgAgFQAA8QYAIBYAAPIGACAXAADzBgAgGQAA9AYAIBoAAPUGACAbAAD2BgAgHAAA9wYAIMECAQAAAAHHAkAAAAAB3QJAAAAAAeoCAgAAAAGBAwIAAAABggMBAAAAAYMDAgAAAAGFAwAAAIUDAoYDIAAAAAGHAyAAAAABiAMCAAAAAYkDAgAAAAGKAwIAAAABiwMCAAAAAYwDQAAAAAECAAAAGgAgMgAAuwkAIB8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICEAAKQIACAiAAClCAAgIwAApggAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAvQkAIAMAAAAXACAyAAC7CQAgMwAAwQkAIBwAAAAXACARAACABgAgEgAAgQYAIBMAAIIGACAUAACDBwAgFQAAgwYAIBYAAIQGACAXAACFBgAgGQAAhgYAIBoAAIcGACAbAACIBgAgHAAAiQYAICsAAMEJACDBAgEA9AQAIccCQAD1BAAh3QJAAPUEACHqAgIAiQUAIYEDAgCJBQAhggMBAP8EACGDAwIAiQUAIYUDAAD9BYUDIoYDIAD-BQAhhwMgAP4FACGIAwIA_gQAIYkDAgD-BAAhigMCAP4EACGLAwIA_gQAIYwDQAD2BAAhGhEAAIAGACASAACBBgAgEwAAggYAIBQAAIMHACAVAACDBgAgFgAAhAYAIBcAAIUGACAZAACGBgAgGgAAhwYAIBsAAIgGACAcAACJBgAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACGBAwIAiQUAIYIDAQD_BAAhgwMCAIkFACGFAwAA_QWFAyKGAyAA_gUAIYcDIAD-BQAhiAMCAP4EACGJAwIA_gQAIYoDAgD-BAAhiwMCAP4EACGMA0AA9gQAIQMAAAAPACAyAAC9CQAgMwAAxAkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICEAALEHACAiAACyBwAgIwAAswcAICUAALUHACArAADECQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIQAAsQcAICIAALIHACAjAACzBwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIR8EAACfCAAgBQAAoAgAIAYAAKEIACAeAACiCAAgHwAAowgAICIAAKUIACAjAACmCAAgJAAApwgAICUAAKgIACDBAgEAAAABxwJAAAAAAd0CQAAAAAHqAgIAAAAB6wIBAAAAAewCAQAAAAHwAgEAAAABjANAAAAAAaMDIAAAAAGkAwEAAAABpgMAAACmAwKoAwAAAKgDAqkDIAAAAAGqAwEAAAABqwMBAAAAAawDgAAAAAGtA0AAAAABrgMBAAAAAa8DIAAAAAGwAwEAAAABsQNAAAAAAbIDQAAAAAECAAAAAQAgMgAAxQkAIAMAAAAPACAyAADFCQAgMwAAyQkAICEAAAAPACAEAACsBwAgBQAArQcAIAYAAK4HACAeAACvBwAgHwAAsAcAICIAALIHACAjAACzBwAgJAAAtAcAICUAALUHACArAADJCQAgwQIBAPQEACHHAkAA9QQAId0CQAD1BAAh6gICAIkFACHrAgEA_wQAIewCAQD_BAAh8AIBAP8EACGMA0AA9gQAIaMDIAD-BQAhpAMBAP8EACGmAwAAqQemAyKoAwAAqgeoAyKpAyAA_gUAIaoDAQD_BAAhqwMBAP8EACGsA4AAAAABrQNAAPYEACGuAwEA_wQAIa8DIACrBwAhsAMBAP8EACGxA0AA9gQAIbIDQAD2BAAhHwQAAKwHACAFAACtBwAgBgAArgcAIB4AAK8HACAfAACwBwAgIgAAsgcAICMAALMHACAkAAC0BwAgJQAAtQcAIMECAQD0BAAhxwJAAPUEACHdAkAA9QQAIeoCAgCJBQAh6wIBAP8EACHsAgEA_wQAIfACAQD_BAAhjANAAPYEACGjAyAA_gUAIaQDAQD_BAAhpgMAAKkHpgMiqAMAAKoHqAMiqQMgAP4FACGqAwEA_wQAIasDAQD_BAAhrAOAAAAAAa0DQAD2BAAhrgMBAP8EACGvAyAAqwcAIbADAQD_BAAhsQNAAPYEACGyA0AA9gQAIQsEBgIFCgMGDgQMABUeFAUfUQ4hVRMiVg8jVxAkWBElXBQBAwABAQMAAQEDEAECAwABBwAGDQwAEhEWBxIpBhMqBhQrBxUuBxYvBRczDRk3Dho5Cxs9DxxBEB1GEQYHAAYIGAYJGwYMAAwOHwgQJQsCCgAHDQAJAgsgCAwACgELIQACBwAGDwAHAwkmAA4nABAoAAEHAAYCBwAGGDgBAgMAAQcABgIDQgEHAAYCAwABB0cGCRNIABVJABZKABdLABlMABpNABtOABxPAB1QAAEgAAEBAwABCgRdAAVeAAZfAB5gAB9hACFiACJjACNkACRlACVmAAAAAAUMABo4ABs5ABw6AB07AB4AAAAAAAUMABo4ABs5ABw6AB07AB4BAwABAQMAAQMMACM6ACQ7ACUAAAADDAAjOgAkOwAlAQMAAQEDAAEDDAAqOgArOwAsAAAAAwwAKjoAKzsALAEDswEBAQO5AQEDDAAxOgAyOwAzAAAAAwwAMToAMjsAMwEDAAEBAwABBQwAODgAOTkAOjoAOzsAPAAAAAAABQwAODgAOTkAOjoAOzsAPAMR4QEHEuIBBhTjAQcDEekBBxLqAQYU6wEHBQwAQTgAQjkAQzoARDsARQAAAAAABQwAQTgAQjkAQzoARDsARQEHAAYBBwAGBQwASjgASzkATDoATTsATgAAAAAABQwASjgASzkATDoATTsATgIKAAcNAAkCCgAHDQAJBQwAUzgAVDkAVToAVjsAVwAAAAAABQwAUzgAVDkAVToAVjsAVwIHAAYPAAcCBwAGDwAHBQwAXDgAXTkAXjoAXzsAYAAAAAAABQwAXDgAXTkAXjoAXzsAYAAABQwAZTgAZjkAZzoAaDsAaQAAAAAABQwAZTgAZjkAZzoAaDsAaQIDAAEHAAYCAwABBwAGAwwAbjoAbzsAcAAAAAMMAG46AG87AHABBwAGAQcABgUMAHU4AHY5AHc6AHg7AHkAAAAAAAUMAHU4AHY5AHc6AHg7AHkCBwAGGIQDAQIHAAYYigMBAwwAfjoAfzsAgAEAAAADDAB-OgB_OwCAAQIDAAEHAAYCAwABBwAGAwwAhQE6AIYBOwCHAQAAAAMMAIUBOgCGATsAhwECA7IDAQcABgIDuAMBBwAGBQwAjAE4AI0BOQCOAToAjwE7AJABAAAAAAAFDACMATgAjQE5AI4BOgCPATsAkAECAwABB8oDBgIDAAEH0AMGBQwAlQE4AJYBOQCXAToAmAE7AJkBAAAAAAAFDACVATgAlgE5AJcBOgCYATsAmQEBIAABASAAAQMMAJ4BOgCfATsAoAEAAAADDACeAToAnwE7AKABJgIBJ2cBKGkBKWoBKmsBLG0BLW8WLnAXL3IBMHQWMXUYNHYBNXcBNngWPHsZPXwfPn0CP34CQH8CQYABAkKBAQJDgwECRIUBFkWGASBGiAECR4oBFkiLASFJjAECSo0BAkuOARZMkQEiTZIBJk6TAQNPlAEDUJUBA1GWAQNSlwEDU5kBA1SbARZVnAEnVp4BA1egARZYoQEoWaIBA1qjAQNbpAEWXKcBKV2oAS1eqQEEX6oBBGCrAQRhrAEEYq0BBGOvAQRksQEWZbIBLma1AQRntwEWaLgBL2m6AQRquwEEa7wBFmy_ATBtwAE0bsEBFG_CARRwwwEUccQBFHLFARRzxwEUdMkBFnXKATV2zAEUd84BFnjPATZ50AEUetEBFHvSARZ81QE3fdYBPX7XAQZ_2AEGgAHZAQaBAdoBBoIB2wEGgwHdAQaEAd8BFoUB4AE-hgHlAQaHAecBFogB6AE_iQHsAQaKAe0BBosB7gEWjAHxAUCNAfIBRo4B8wEHjwH0AQeQAfUBB5EB9gEHkgH3AQeTAfkBB5QB-wEWlQH8AUeWAf4BB5cBgAIWmAGBAkiZAYICB5oBgwIHmwGEAhacAYcCSZ0BiAJPngGJAgifAYoCCKABiwIIoQGMAgiiAY0CCKMBjwIIpAGRAhalAZICUKYBlAIIpwGWAhaoAZcCUakBmAIIqgGZAgirAZoCFqwBnQJSrQGeAliuAZ8CC68BoAILsAGhAguxAaICC7IBowILswGlAgu0AacCFrUBqAJZtgGqAgu3AawCFrgBrQJauQGuAgu6Aa8CC7sBsAIWvAGzAlu9AbQCYb4BtgIJvwG3AgnAAboCCcEBuwIJwgG8AgnDAb4CCcQBwAIWxQHBAmLGAcMCCccBxQIWyAHGAmPJAccCCcoByAIJywHJAhbMAcwCZM0BzQJqzgHOAgXPAc8CBdAB0AIF0QHRAgXSAdICBdMB1AIF1AHWAhbVAdcCa9YB2QIF1wHbAhbYAdwCbNkB3QIF2gHeAgXbAd8CFtwB4gJt3QHjAnHeAeQCDd8B5QIN4AHmAg3hAecCDeIB6AIN4wHqAg3kAewCFuUB7QJy5gHvAg3nAfECFugB8gJz6QHzAg3qAfQCDesB9QIW7AH4AnTtAfkCeu4B-gIO7wH7Ag7wAfwCDvEB_QIO8gH-Ag7zAYADDvQBggMW9QGDA3v2AYYDDvcBiAMW-AGJA3z5AYsDDvoBjAMO-wGNAxb8AZADff0BkQOBAf4BkgMP_wGTAw-AApQDD4EClQMPggKWAw-DApgDD4QCmgMWhQKbA4IBhgKdAw-HAp8DFogCoAODAYkCoQMPigKiAw-LAqMDFowCpgOEAY0CpwOIAY4CqAMQjwKpAxCQAqoDEJECqwMQkgKsAxCTAq4DEJQCsAMWlQKxA4kBlgK0AxCXArYDFpgCtwOKAZkCuQMQmgK6AxCbArsDFpwCvgOLAZ0CvwORAZ4CwAMRnwLBAxGgAsIDEaECwwMRogLEAxGjAsYDEaQCyAMWpQLJA5IBpgLMAxGnAs4DFqgCzwOTAakC0QMRqgLSAxGrAtMDFqwC1gOUAa0C1wOaAa4C2AMTrwLZAxOwAtoDE7EC2wMTsgLcAxOzAt4DE7QC4AMWtQLhA5sBtgLjAxO3AuUDFrgC5gOcAbkC5wMTugLoAxO7AukDFrwC7AOdAb0C7QOhAQ" } config.compilerWasm = { getRuntime: async () => require('./query_compiler_fast_bg.js'), diff --git a/apps/modeling-commons-backend/generated/prisma/package.json b/apps/modeling-commons-backend/generated/prisma/package.json index 10a469b5..60dc004a 100644 --- a/apps/modeling-commons-backend/generated/prisma/package.json +++ b/apps/modeling-commons-backend/generated/prisma/package.json @@ -1,5 +1,5 @@ { - "name": "prisma-client-fcaac490b84f33f683f0601ea8fa99fcb04047fea616e2c73bc77a003e98770f", + "name": "prisma-client-af8d9cd952af75c255e648d4376319ab8c412ef134d4d3c4cb42d336ce682951", "main": "index.js", "types": "index.d.ts", "browser": "default.js", diff --git a/apps/modeling-commons-backend/generated/prisma/schema.prisma b/apps/modeling-commons-backend/generated/prisma/schema.prisma index 492dcbd1..6315ce73 100644 --- a/apps/modeling-commons-backend/generated/prisma/schema.prisma +++ b/apps/modeling-commons-backend/generated/prisma/schema.prisma @@ -194,13 +194,14 @@ model Model { childModels Model[] @relation("ModelParent") parentVersion ModelVersion? @relation("ParentVersion", fields: [parentModelId, parentVersionNumber], references: [modelId, versionNumber]) - versions ModelVersion[] @relation("ModelVersions") - authors ModelAuthor[] - permissions ModelPermission[] - additionalFiles ModelAdditionalFile[] - likes ModelLike[] - interactions ModelInteraction[] - drafts ModelDraft[] + versions ModelVersion[] @relation("ModelVersions") + authors ModelAuthor[] + nonMemberContributors NonMemberContributor[] + permissions ModelPermission[] + additionalFiles ModelAdditionalFile[] + likes ModelLike[] + interactions ModelInteraction[] + drafts ModelDraft[] @@unique([id, latestVersionNumber]) @@index([parentModelId]) @@ -275,10 +276,12 @@ model Tag { } model ModelAuthor { - modelId String - userId String - role AuthorRole - createdAt DateTime @default(now()) + modelId String + userId String + role AuthorRole + // Legacy collaborator_types.name, kept for provenance. Nothing reads it. + collaboratorType String? + createdAt DateTime @default(now()) model Model @relation(fields: [modelId], references: [id], onDelete: Cascade) user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@ -287,6 +290,25 @@ model ModelAuthor { @@index([userId]) } +// Legacy non_member_collaborators joined onto non_member_collaborations: people +// credited on a model who never held an account. Archival only, no business logic +// reads this table. +model NonMemberContributor { + id String @id @default(uuid()) + legacyId Int @unique + modelId String + email String? + name String? + collaboratorType String? + addedByUserId String? + createdAt DateTime @default(now()) + + model Model @relation(fields: [modelId], references: [id], onDelete: Cascade) + + @@index([modelId]) + @@index([email]) +} + model ModelPermission { id String @id @default(uuid()) modelId String diff --git a/apps/modeling-commons-backend/package.json b/apps/modeling-commons-backend/package.json index fa9cd2be..697a3a7a 100644 --- a/apps/modeling-commons-backend/package.json +++ b/apps/modeling-commons-backend/package.json @@ -37,7 +37,9 @@ "db:migrate": "prisma migrate deploy", "db:migrate:dev": "prisma migrate dev", "db:seed": "prisma db seed", - "db:seed:archive": "sh -c 'PRISMA_SEED_FILE=archive.ts yarn run db:seed'", + "db:legacy:import": "sh -c 'PRISMA_SEED_FILE=legacy-migration/initial-import.ts yarn run db:seed'", + "db:legacy:patch": "tsx prisma/legacy-migration/apply-diff.ts", + "db:legacy:collaborators": "tsx prisma/legacy-migration/backfill-collaborators.ts", "db:reset": "prisma migrate reset --force", "deps:validate": "depcruise src --config .dependency-cruiser.cjs --output-type err-long", "deps:graph": "depcruise src --include-only \"^src\" --config --output-type dot | dot -T svg > doc/dependency-graph.svg" diff --git a/apps/modeling-commons-backend/prisma/recompute-interaction-counts.ts b/apps/modeling-commons-backend/prisma/actions/recompute-interaction-counts.ts similarity index 93% rename from apps/modeling-commons-backend/prisma/recompute-interaction-counts.ts rename to apps/modeling-commons-backend/prisma/actions/recompute-interaction-counts.ts index ee7701b9..e2498026 100644 --- a/apps/modeling-commons-backend/prisma/recompute-interaction-counts.ts +++ b/apps/modeling-commons-backend/prisma/actions/recompute-interaction-counts.ts @@ -4,12 +4,12 @@ * write path ever fails to bump a counter (the log stays the source of truth). * * Usage: - * DATABASE_URL= tsx ./prisma/recompute-interaction-counts.ts + * DATABASE_URL= tsx ./prisma/actions/recompute-interaction-counts.ts */ import 'dotenv/config'; import { PrismaPg } from '@prisma/adapter-pg'; -import { PrismaClient } from '../generated/prisma/client.js'; +import { PrismaClient } from '#prisma/index'; const adapter = new PrismaPg({ connectionString: process.env['DATABASE_URL']! }); const prisma = new PrismaClient({ adapter }); diff --git a/apps/modeling-commons-backend/prisma/archive-auto-convert.ts b/apps/modeling-commons-backend/prisma/archive-auto-convert.ts deleted file mode 100644 index f3e9a919..00000000 --- a/apps/modeling-commons-backend/prisma/archive-auto-convert.ts +++ /dev/null @@ -1,232 +0,0 @@ -import 'dotenv/config'; - -import path from 'node:path'; -import fs from 'fs/promises'; - -import { parseNlogo, parseNlogox } from './netlogo-utils.ts'; -import { mkdir, writeFile } from 'node:fs/promises'; -import { Dirent } from 'node:fs'; - -const seedFilesPath = path.join(import.meta.dirname, 'archive-output', 'files'); -const outputPath = path.join(import.meta.dirname, 'archive-converted'); - -// upload each file in seedFilesPath to the S3 bucket, key relative to seedFilesPath -const report = { - files: { converted: 0, skipped: 0, failed: 0 }, - versions: {} as Record, - errors: [] as { - file: string; - netlogoVersion?: string | null; - error: string; - stackTrace?: string; - }[], -}; - -const MAX_FILES = parseInt(process.env['MAX_FILES'] || '1000000', 10); -const OFFSET_INDEX = parseInt(process.env['OFFSET_INDEX'] || '0', 10); -const BATCH_SIZE = parseInt(process.env['BATCH_SIZE'] || '1', 10); - -async function $fetch(...args: Parameters): Promise { - const maxRetries = 5; - let attempt = 0; - let delay = 1000; - - while (attempt < maxRetries) { - try { - const response = await fetch(...args); - if (response.status === 503) { - throw new Error(`Service unavailable (503)`); - } - return response; - } catch (error) { - attempt++; - if (attempt >= maxRetries) { - throw new Error( - `Failed after ${maxRetries} attempts: ${error instanceof Error ? error.message : String(error)}`, - ); - } - console.warn( - `Attempt ${attempt} failed: ${error instanceof Error ? error.message : String(error)}. Retrying in ${delay}ms...`, - ); - await new Promise((resolve) => setTimeout(resolve, delay)); - delay *= 2; - } - } - throw new Error('Unexpected error in $fetch'); -} - -async function convertModel(file: Dirent) { - if (file.isFile()) { - const filePath = path.join(file.parentPath, file.name); - - const extName = path.extname(file.name).toLowerCase(); - if (['.nlogo', '.nlogo3d', '.nlogox', '.nlogox3d'].includes(extName)) { - const fileContent = await fs.readFile(filePath); - const { netlogoVersion = 'unknown' } = ['.nlogo', '.nlogo3d'].includes(extName) - ? parseNlogo(fileContent.toString()) - : parseNlogox(fileContent.toString()); - - console.info(`Processing file: ${file.name} (NetLogo version: ${netlogoVersion})`); - - try { - const formData = new FormData(); - formData.append('model', new Blob([fileContent]), file.name); - - const response = await $fetch('https://convert.netlogo.org/convert', { - method: 'POST', - body: formData, - // retry with exponential backoff on 503 or network errors, up to 5 attempts - }); - - if (!response.ok) { - const errorText = - (await response.text()) ?? - (await response - .json() - .then((json) => JSON.stringify(json)) - .catch(() => null)) ?? - 'No error details'; - handleStatus( - 'failed', - filePath, - netlogoVersion, - new Error(`Conversion failed with status ${response.status}: ${errorText}`), - { - statusCode: response.status, - responseText: errorText, - responseHeaders: Object.fromEntries(response.headers.entries()), - }, - ); - return; - } else { - const convertedContent = await readResponseStream(response); - const convertedFilename = file.name.replace(/\.nlogo(3d)?$/, '.nlogox$1'); - const relKey = path.relative( - seedFilesPath, - path.join(file.parentPath, convertedFilename), - ); - await writeLocalFile(relKey, convertedContent); - } - } catch (error) { - handleStatus( - 'failed', - filePath, - netlogoVersion, - error instanceof Error ? error : new Error(String(error)), - ); - return; - } - - handleStatus('converted', filePath, netlogoVersion); - } else { - handleStatus('skipped', filePath, 'N/A'); - return; - } - } -} - -async function convertModels() { - const allEntries = await fs.readdir(seedFilesPath, { withFileTypes: true, recursive: true }); - - const convertibleExts = ['.nlogo', '.nlogo3d', '.nlogox', '.nlogox3d']; - const files = allEntries.filter( - (f) => f.isFile() && convertibleExts.includes(path.extname(f.name).toLowerCase()), - ); - - const skippedCount = allEntries.length - files.length; - console.log( - `Found ${allEntries.length} entries, ${files.length} convertible, ${skippedCount} skipped. Starting conversion...`, - ); - report.files.skipped += skippedCount; - - function cursor() { - let lastProcessedIndex = OFFSET_INDEX - 1; - return function getNext() { - lastProcessedIndex++; - if (lastProcessedIndex >= files.length || lastProcessedIndex >= OFFSET_INDEX + MAX_FILES) { - return null; - } - return files[lastProcessedIndex]; - }; - } - - const getNext = cursor(); - - function processOne(file: Dirent | null, slot: number): Promise { - if (file === null) return Promise.resolve(); - if (!file) return Promise.resolve(); - - return convertModel(file) - .then(() => writeLocalFile(`report.json`, Buffer.from(JSON.stringify(report, null, 2)))) - .then(() => processOne(getNext(), slot)) - .catch((error) => { - console.error(`Error processing file ${file.name}:`, error); - return processOne(getNext(), slot); - }); - } - - const slots = Array.from({ length: BATCH_SIZE }, (_, i) => processOne(getNext(), i)); - await Promise.all(slots); -} - -function handleStatus( - status: 'converted' | 'skipped' | 'failed', - filePath: string, - netlogoVersion?: string | null, - error?: Error, - metadata?: Record, -): void { - if (status === 'failed' && error) { - report.errors.push({ - file: filePath, - netlogoVersion, - error: error instanceof Error ? error.message : String(error), - stackTrace: error instanceof Error ? error.stack : undefined, - ...metadata, - }); - } - report.files[status]++; - - const versionKey = netlogoVersion || 'unknown'; - report.versions[versionKey] ??= { converted: 0, skipped: 0, failed: 0 }; - report.versions[versionKey][status]++; -} - -async function writeGitIgnore() { - const gitIgnore = ` - * - !.gitignore - `; - await mkdir(outputPath, { recursive: true }); - await writeFile(path.join(outputPath, '.gitignore'), gitIgnore); -} - -async function writeLocalFile(relKey: string, contents: Buffer) { - const full = path.join(outputPath, relKey); - await mkdir(path.dirname(full), { recursive: true }); - await writeFile(full, contents); -} - -async function readResponseStream(response: Response): Promise { - const reader = response.body?.getReader(); - if (!reader) throw new Error('No response body'); - - const chunks: Uint8Array[] = []; - let done = false; - - while (!done) { - const { value, done: doneReading } = await reader.read(); - if (value) chunks.push(value); - done = doneReading; - } - - return Buffer.concat(chunks); -} - -async function runHeadless() {} - -writeGitIgnore() - .then(() => convertModels()) - .then(() => writeLocalFile('report.json', Buffer.from(JSON.stringify(report, null, 2)))) - .then(() => console.log('Conversion complete. Report written to archive-converted/report.json')) - .catch((error) => console.error('Error during conversion:', error)); diff --git a/apps/modeling-commons-backend/prisma/archive.ts b/apps/modeling-commons-backend/prisma/archive.ts deleted file mode 100644 index e742bf31..00000000 --- a/apps/modeling-commons-backend/prisma/archive.ts +++ /dev/null @@ -1,849 +0,0 @@ -/** - * NetLogo Commons → new schema migration. - * - * Source: nlcommons_production (Rails app, integer ids, tables: people, nodes, - * versions, tags, tagged_nodes, attachments, spam_warnings, - * permission_settings). - * Target: new Prisma schema (UUIDs, Model/ModelVersion split, Better Auth users, - * file storage by key). - * - * Idempotent via legacyId columns on User/Model/Tag. Re-running skips already- - * migrated rows. File extraction goes to local disk; an external uploader pushes - * to S3 later. - * - * Usage: - * DATABASE_URL= yarn run db:migrate:dev - * DATABASE_URL= PRISMA_SEED_FILE=archive.ts yarn run db:seed - */ - -import { PrismaPg } from '@prisma/adapter-pg'; -import { exec } from 'child_process'; -import { createHash, randomUUID } from 'node:crypto'; -import { mkdir, rm, writeFile } from 'node:fs/promises'; -import path from 'node:path'; -import process from 'node:process'; -import pg from 'pg'; -import Cursor from 'pg-cursor'; -import { Prisma, PrismaClient } from '../generated/prisma/client.js'; - -const OLD_URL = 'postgresql://admin:test@127.0.0.1:5432/nlcommons_production'; -const NEW_URL = required('DATABASE_URL'); -const AVATARS_DIR = path.join('.', 'prisma', 'avatars'); -const OUTPUT_DIR = process.env.OUTPUT_DIR ?? './prisma/archive-output'; -const FILES_DIR = path.join(OUTPUT_DIR, 'files'); -const BATCH = parseInt(process.env.BATCH_SIZE ?? '500', 10); -const WIPE_TARGET = process.env.WIPE_TARGET === 'true'; -const IP_HASH_SALT = required('IP_HASH_SALT'); - -// Type mappings - -type OldPerson = { - id: number; - email_address: string | null; - first_name: string | null; - last_name: string | null; - administrator: boolean | null; - birthdate: Date | null; - country_name: string | null; - url: string | null; - avatar_file_name: string | null; - avatar_updated_at: Date | null; - biography: string | null; - created_at: Date | null; - updated_at: Date | null; -}; - -type OldNode = { - id: number; - name: string; - created_at: Date | null; - updated_at: Date | null; - visibility_id: number; -}; - -type OldVersion = { - id: number; - node_id: number; - person_id: number; - description: string; - contents: string; // the .nlogo file body, stored as text - created_at: Date | null; - updated_at: Date | null; -}; - -type OldTag = { - id: number; - name: string | null; - created_at: Date | null; -}; - -type OldTaggedNode = { - node_id: number; - tag_id: number; -}; - -type OldAttachment = { - id: number; - node_id: number; - person_id: number; - filename: string; - content_type: string; - contents: Buffer; // bytea - created_at: Date | null; -}; - -type OldEvent = { - logged_at: Date | null; - ip_address: string | null; - node_id: number | null; - person_id: number | null; -}; - -// Migration -const oldPool = new pg.Pool({ connectionString: OLD_URL, max: 4 }); - -const adapter = new PrismaPg({ connectionString: NEW_URL, max: 4 }); -const prisma = new PrismaClient({ adapter }); - -const report = { - users: { migrated: 0, skipped_existing: 0, deduped_email: 0, null_email: 0 }, - tags: { migrated: 0, skipped_existing: 0 }, - models: { migrated: 0, skipped_spam: 0, skipped_existing: 0, skipped_no_versions: 0 }, - versions: { migrated: 0 }, - authors: { owners: 0, contributors: 0 }, - attachments: { migrated: 0, skipped_orphan: 0, previews_attached: 0 }, - taggings: { migrated: 0, skipped_orphan: 0 }, - interactions: { views: 0, runs: 0, downloads: 0 }, - errors: [] as string[], -}; - -async function main() { - console.log('→ Output dir:', path.resolve(OUTPUT_DIR)); - await mkdir(FILES_DIR, { recursive: true }); - - if (WIPE_TARGET) { - console.log('→ WIPE_TARGET=true: truncating target tables'); - await wipeTarget(); - } - - console.log('→ Loading spam-warned node ids (>=2 warnings)'); - const spamNodeIds = await loadSpamNodeIds(); - console.log(` ${spamNodeIds.size} nodes excluded as spam`); - - console.log('→ Migrating people → User'); - const userIdMap = await migrateUsers(); - - console.log('→ Migrating tags → Tag'); - const tagIdMap = await migrateTags(); - - console.log('→ Migrating nodes → Model (+ versions, authors, attachments, taggings)'); - const { modelIdMap } = await migrateNodes(spamNodeIds, userIdMap, tagIdMap); - - console.log('→ Migrating model_views/runs/downloads → ModelInteraction'); - await migrateInteractions(modelIdMap, userIdMap); - - console.log('→ Writing manifest + report'); - await writeFile(path.join(OUTPUT_DIR, 'report.json'), JSON.stringify(report, null, 2)); - - console.log('\n=== DONE ==='); - console.log(JSON.stringify(report, null, 2)); - - await oldPool.end(); - await prisma.$disconnect(); -} - -// Clear target tables - -async function wipeTarget() { - // Order matters: leaf tables first, but TRUNCATE CASCADE handles it. - await prisma.$executeRawUnsafe(` - TRUNCATE TABLE - "ModelVersionTag", - "ModelAdditionalFile", - "ModelVersion", - "ModelAuthor", - "ModelPermission", - "ModelLike", - "ModelInteraction", - "ModelDraft", - "Event", - "Model", - "Tag", - "Verification", - "Session", - "Account", - "Passkey", - "User" - RESTART IDENTITY CASCADE; - `); - - await rm(FILES_DIR, { recursive: true }); -} - -async function loadSpamNodeIds(): Promise> { - const { rows } = await oldPool.query<{ node_id: number }>(` - SELECT node_id - FROM spam_warnings - WHERE node_id IS NOT NULL - GROUP BY node_id - HAVING COUNT(*) >= 2 - `); - return new Set(rows.map((r) => r.node_id)); -} - -async function migrateUsers(): Promise> { - const map = new Map(); - - // Build email dedupe map: lowest id wins per non-null lowercased email. - const { rows: emailRows } = await oldPool.query<{ - id: number; - email_address: string | null; - }>(`SELECT id, email_address FROM people ORDER BY id ASC`); - - const emailWinner = new Map(); - for (const r of emailRows) { - const e = (r.email_address ?? '').trim().toLowerCase(); - if (!e) continue; - if (!emailWinner.has(e)) emailWinner.set(e, r.id); - } - - // Existing legacyIds in target (for idempotency) - const existing = await prisma.user.findMany({ - where: { legacyId: { not: null } }, - select: { id: true, legacyId: true }, - }); - for (const u of existing) { - if (u.legacyId !== null) map.set(u.legacyId, u.id); - } - - await streamRows( - `SELECT id, email_address, first_name, last_name, administrator, - avatar_file_name, avatar_updated_at, - birthdate, country_name, url, biography, - created_at, updated_at - FROM people - ORDER BY id ASC`, - async (batch) => { - const toCreate: Prisma.UserCreateManyInput[] = []; - for (const p of batch) { - if (map.has(p.id)) { - report.users.skipped_existing++; - continue; - } - - const id = randomUUID(); - const rawEmail = (p.email_address ?? '').trim().toLowerCase(); - let email: string | null = null; - if (rawEmail) { - if (emailWinner.get(rawEmail) === p.id) { - email = rawEmail; - } else { - report.users.deduped_email++; - } - } else { - report.users.null_email++; - } - - const name = - [p.first_name, p.last_name] - .map((s) => (s ?? '').trim()) - .filter(Boolean) - .join(' ') || null; - - let imageUrl: string | null = null; - if (p.avatar_file_name) { - const avatarUuid = randomUUID(); - const avatarKey = buildAvatarFileKey( - id, - p.avatar_updated_at ?? new Date(), - avatarUuid, - 'avatar', - ); - imageUrl = `cdn.modelingcommons.org/modeling-commons/${avatarKey}`; - - const fsAvatarPath = path.join(AVATARS_DIR, `${p.id}`, 'original', p.avatar_file_name); - try { - await copyFile(fsAvatarPath, path.join(FILES_DIR, avatarKey)); - } catch (err) { - report.errors.push( - `Failed to copy avatar for person id ${p.id} from ${fsAvatarPath}: ${(err as Error).message}`, - ); - imageUrl = null; - } - } - - toCreate.push({ - id, - legacyId: p.id, - email, - name, - emailVerified: false, - bio: p.biography?.trim() || null, - dob: p.birthdate ?? null, - image: p.avatar_file_name ? imageUrl : null, - socialLinks: [{ type: 'other', rawValue: p.url?.trim() || null }], - systemRole: 'user', // all users → user, per spec - userKind: 'other', - createdAt: p.created_at ?? new Date(), - updatedAt: p.updated_at ?? p.created_at ?? new Date(), - }); - map.set(p.id, id); - report.users.migrated++; - } - if (toCreate.length > 0) { - await prisma.user.createMany({ data: toCreate, skipDuplicates: true }); - } - }, - ); - - return map; -} - -async function migrateTags(): Promise> { - const map = new Map(); - - const existing = await prisma.tag.findMany({ - where: { legacyId: { not: null } }, - select: { id: true, legacyId: true }, - }); - for (const t of existing) { - if (t.legacyId !== null) map.set(t.legacyId, t.id); - } - - // Old tag names are nullable + non-unique; new is unique. Dedupe by lowercased name. - const { rows } = await oldPool.query( - `SELECT id, name, created_at FROM tags ORDER BY id ASC`, - ); - - const nameWinner = new Map(); - for (const t of rows) { - const n = (t.name ?? '').trim().toLowerCase(); - if (!n) continue; - if (!nameWinner.has(n)) nameWinner.set(n, t); - } - - const toCreate: Prisma.TagCreateManyInput[] = []; - for (const t of rows) { - if (map.has(t.id)) { - report.tags.skipped_existing++; - continue; - } - const n = (t.name ?? '').trim().toLowerCase(); - if (!n) continue; - const winner = nameWinner.get(n)!; - if (winner.id !== t.id) { - // Alias old id to the winning tag's new uuid (set after first pass) - // We resolve this in a second pass below. - continue; - } - const id = randomUUID(); - toCreate.push({ - id, - legacyId: t.id, - name: n, - displayName: (t.name ?? '').trim() || null, - createdAt: t.created_at ?? new Date(), - }); - map.set(t.id, id); - report.tags.migrated++; - } - if (toCreate.length > 0) { - await prisma.tag.createMany({ data: toCreate, skipDuplicates: true }); - } - - // Second pass: alias the duplicate-name old tag ids to the winning uuid - for (const t of rows) { - if (map.has(t.id)) continue; - const n = (t.name ?? '').trim().toLowerCase(); - if (!n) continue; - const winner = nameWinner.get(n); - if (!winner) continue; - const winnerUuid = map.get(winner.id); - if (winnerUuid) map.set(t.id, winnerUuid); - } - - return map; -} - -async function migrateNodes( - spamNodeIds: Set, - userIdMap: Map, - tagIdMap: Map, -) { - // Existing legacyIds (idempotency) - const existingModels = await prisma.model.findMany({ - where: { legacyId: { not: null } }, - select: { id: true, legacyId: true }, - }); - const modelIdMap = new Map(); - for (const m of existingModels) { - if (m.legacyId !== null) modelIdMap.set(m.legacyId, m.id); - } - - // Visibility lookup - const visibilityMap: Record = { - 1: 'public', - 2: 'private', - 3: 'private', - }; - - // Process node-by-node. We can't batch the whole pipeline cleanly because - // each node spawns versions, authors, attachments, taggings — all interrelated. - await streamRows( - `SELECT id, name, created_at, updated_at, visibility_id - FROM nodes - ORDER BY id ASC`, - async (batch) => { - for (const node of batch) { - if (spamNodeIds.has(node.id)) { - report.models.skipped_spam++; - continue; - } - if (modelIdMap.has(node.id)) { - report.models.skipped_existing++; - continue; - } - - const versions = await fetchVersionsForNode(node.id); - if (versions.length === 0) { - report.models.skipped_no_versions++; - continue; - } - - const modelUuid = randomUUID(); - modelIdMap.set(node.id, modelUuid); - - const visibility = visibilityMap[node.visibility_id] ?? 'public'; - - // One transaction per node so partial failure rolls back cleanly. - await prisma.$transaction( - async (tx) => { - // 1. Create Model with no latestVersionNumber yet (it points at a version row that doesn't exist) - await tx.model.create({ - data: { - id: modelUuid, - legacyId: node.id, - visibility, - isEndorsed: false, - createdAt: node.created_at ?? new Date(), - updatedAt: node.updated_at ?? node.created_at ?? new Date(), - }, - }); - - // 2. Versions — assign versionNumbers 1..N by created_at ascending - let versionNumber = 0; - let latestVersionNumber = 0; - let latestInfoTab: string | null = null; - for (const v of versions) { - versionNumber++; - const versionFileUuid = randomUUID(); - const dateForPath = v.created_at ?? node.created_at ?? new Date(); - const format = getNlogoFileExtension(v.contents); - const relKey = buildVersionFileKey( - modelUuid, - dateForPath, - versionFileUuid, - `${node.name}.${format}`, - ); - - await writeLocalFile(relKey, Buffer.from(v.contents, 'utf8')); - - const { netlogoVersion, infoTab } = format.startsWith('nlogox') - ? parseNlogox(v.contents) - : parseNlogo(v.contents); - - await tx.modelVersion.create({ - data: { - modelId: modelUuid, - versionNumber, - title: node.name, - description: v.description || null, - netlogoFileKey: relKey, - netlogoVersion, - infoTab, - createdAt: v.created_at ?? new Date(), - finalizedAt: v.created_at ?? null, - }, - }); - - latestVersionNumber = versionNumber; - latestInfoTab = infoTab; - report.versions.migrated++; - } - - // 3. Update model with latestVersionNumber - await tx.model.update({ - where: { id: modelUuid }, - data: { latestVersionNumber }, - }); - - // 4. Authors: first version's person = owner; later distinct persons = contributors - const seenAuthors = new Set(); - const ownerLegacyId = versions[0].person_id; - const ownerUuid = userIdMap.get(ownerLegacyId); - if (ownerUuid) { - await tx.modelAuthor.create({ - data: { - modelId: modelUuid, - userId: ownerUuid, - role: 'owner', - createdAt: versions[0].created_at ?? new Date(), - }, - }); - seenAuthors.add(ownerUuid); - report.authors.owners++; - } - for (let i = 1; i < versions.length; i++) { - const v = versions[i]; - const uuid = userIdMap.get(v.person_id); - if (!uuid || seenAuthors.has(uuid)) continue; - await tx.modelAuthor.create({ - data: { - modelId: modelUuid, - userId: uuid, - role: 'contributor', - createdAt: v.created_at ?? new Date(), - }, - }); - seenAuthors.add(uuid); - report.authors.contributors++; - } - - // 5. Attachments — tagged to the LATEST version - const attachments = await fetchAttachmentsForNode(node.id); - - for (const a of attachments) { - const fileUuid = randomUUID(); - const dateForPath = a.created_at ?? node.created_at ?? new Date(); - - if (a.content_type === 'preview') { - // Last preview wins (matches Rails behavior — latest upload). - const relKey = buildPreviewFileKey(modelUuid, dateForPath, fileUuid, a.filename); - await writeLocalFile(relKey, a.contents); - - await tx.modelVersion.update({ - where: { - modelId_versionNumber: { - modelId: modelUuid, - versionNumber: latestVersionNumber, - }, - }, - data: { previewImageFileKey: relKey }, - }); - report.attachments.previews_attached = - (report.attachments.previews_attached ?? 0) + 1; - continue; - } - - const relKey = buildAttachmentFileKey(modelUuid, dateForPath, fileUuid, a.filename); - await writeLocalFile(relKey, a.contents); - - const metadataRelKey = relKey + '.metadata.json'; - const metadata = JSON.stringify({ - contentType: a.content_type, - originalFilename: a.filename, - userId: a.person_id ? (userIdMap.get(a.person_id) ?? null) : null, - createdAt: a.created_at?.toISOString() ?? new Date().toISOString(), - }); - - await writeLocalFile(metadataRelKey, Buffer.from(metadata, 'utf8')); - - await tx.modelAdditionalFile.create({ - data: { - id: fileUuid, - modelId: modelUuid, - taggedVersionNumber: latestVersionNumber, - fileKey: relKey, - createdAt: a.created_at ?? new Date(), - }, - }); - report.attachments.migrated++; - } - - // 6. Tags — attached to the LATEST version - const taggings = await fetchTaggingsForNode(node.id); - const seenTags = new Set(); - for (const tg of taggings) { - const tagUuid = tagIdMap.get(tg.tag_id); - if (!tagUuid) { - report.taggings.skipped_orphan++; - continue; - } - if (seenTags.has(tagUuid)) continue; - seenTags.add(tagUuid); - - await tx.modelVersionTag.create({ - data: { - modelId: modelUuid, - versionNumber: latestVersionNumber, - tagId: tagUuid, - createdAt: tg.created_at ?? new Date(), - }, - }); - report.taggings.migrated++; - } - }, - { timeout: 60_000 }, - ); - - report.models.migrated++; - if (report.models.migrated % 50 === 0) { - console.log(` ...migrated ${report.models.migrated} models`); - } - } - }, - ); - - return { modelIdMap }; -} - -async function migrateInteractions( - modelIdMap: Map, - userIdMap: Map, -) { - const sources: Array<{ table: string; kind: 'view' | 'run' | 'download' }> = [ - { table: 'model_views', kind: 'view' }, - { table: 'model_runs', kind: 'run' }, - { table: 'model_downloads', kind: 'download' }, - ]; - - for (const { table, kind } of sources) { - let count = 0; - await streamRows( - `SELECT logged_at, ip_address, node_id, person_id FROM ${table}`, - async (batch) => { - const rows: Prisma.ModelInteractionCreateManyInput[] = []; - for (const e of batch) { - if (!e.node_id) continue; - const modelUuid = modelIdMap.get(e.node_id); - if (!modelUuid) continue; // node was spam-skipped or dropped - const userUuid = e.person_id ? (userIdMap.get(e.person_id) ?? null) : null; - rows.push({ - id: randomUUID(), - modelId: modelUuid, - kind, - userId: userUuid, - ipHash: hashIp(e.ip_address, IP_HASH_SALT), - createdAt: e.logged_at ?? new Date(), - }); - } - if (rows.length > 0) { - await prisma.modelInteraction.createMany({ data: rows, skipDuplicates: true }); - count += rows.length; - } - }, - ); - console.log(` ${table}: ${count} rows`); - } -} - -async function fetchVersionsForNode(nodeId: number): Promise { - const { rows } = await oldPool.query( - `SELECT id, node_id, person_id, description, contents, created_at, updated_at - FROM versions - WHERE node_id = $1 - ORDER BY created_at ASC NULLS LAST, id ASC`, - [nodeId], - ); - return rows; -} - -async function fetchAttachmentsForNode(nodeId: number): Promise { - const { rows } = await oldPool.query( - `SELECT id, node_id, person_id, filename, content_type, contents, created_at - FROM attachments - WHERE node_id = $1 - ORDER BY id ASC`, - [nodeId], - ); - return rows; -} - -async function fetchTaggingsForNode( - nodeId: number, -): Promise> { - const { rows } = await oldPool.query( - `SELECT node_id, tag_id, created_at - FROM tagged_nodes - WHERE node_id = $1 - ORDER BY id ASC`, - [nodeId], - ); - return rows; -} - -function dateParts(d: Date) { - const y = d.getUTCFullYear().toString(); - const m = (d.getUTCMonth() + 1).toString().padStart(2, '0'); - const day = d.getUTCDate().toString().padStart(2, '0'); - return { y, m, day }; -} - -function sanitizeFilename(name: string): string { - // Strip path separators and control chars; collapse whitespace. - const cleaned = name - .replace(/[\x00-\x1f\x7f]/g, '') - .replace(/[\/\\]/g, '_') - .trim(); - return cleaned || 'file'; -} - -function getAccessPrefix(access: 'public-read' | 'private'): string { - return access === 'public-read' ? 'files/public/uploads' : 'uploads'; -} - -function buildVersionFileKey( - modelUuid: string, - d: Date, - fileUuid: string, - _filename: string = 'file', - accessPolicy: 'public-read' | 'private' = 'private', -): string { - const { y, m, day } = dateParts(d); - const filename = sanitizeFilename(_filename); - return `${getAccessPrefix(accessPolicy)}/models/${modelUuid}/versions/${y}/${m}/${day}/${fileUuid}/${filename}`; -} - -function buildPreviewFileKey( - modelUuid: string, - d: Date, - fileUuid: string, - _filename: string = 'file', -): string { - const { y, m, day } = dateParts(d); - const filename = sanitizeFilename(_filename); - return `${getAccessPrefix('public-read')}/models/${modelUuid}/preview-images/${y}/${m}/${day}/${fileUuid}/${filename}`; -} - -function buildAttachmentFileKey( - modelUuid: string, - d: Date, - fileUuid: string, - _filename: string = 'file', -): string { - const { y, m, day } = dateParts(d); - const filename = sanitizeFilename(_filename); - return `${getAccessPrefix('private')}/models/${modelUuid}/additionalFiles/${y}/${m}/${day}/${fileUuid}/${filename}`; -} - -function buildAvatarFileKey( - userUuid: string, - d: Date, - fileUuid: string, - _filename: string = 'file', -): string { - const { y, m, day } = dateParts(d); - const filename = sanitizeFilename(_filename); - return `${getAccessPrefix('public-read')}/avatars/${userUuid}/${y}/${m}/${day}/${fileUuid}/${filename}`; -} - -async function copyFile(src: string, dest: string) { - await mkdir(path.dirname(dest), { recursive: true }); - await new Promise((resolve, reject) => { - const cp = process.platform === 'win32' ? 'copy' : 'cp'; - const cmd = `${cp} "${src}" "${dest}"`; - exec(cmd, (err: Error | null) => (err ? reject(err) : resolve())); - }); -} - -async function writeLocalFile(relKey: string, contents: Buffer) { - const full = path.join(FILES_DIR, relKey); - await mkdir(path.dirname(full), { recursive: true }); - await writeFile(full, contents); -} - -/** - * NetLogo .nlogo files are sectioned by `@#$#@#$#@` separators. The sections, - * in order: code, interface, info, turtle shapes, version, preview commands, - * system dynamics, behavior space, hub net client, link shapes, model settings, - * delta tick. - * - * We extract: - * - infoTab → section index 2 (the "Info" tab markdown) - * - netlogoVersion → section index 4 (e.g. "NetLogo 5.0.4") - * - * If parsing fails, both return null. Worth noting: not all old models follow - * the modern format, so silent fallback is fine. - */ -function parseNlogo(contents: string): { - netlogoVersion: string | null; - infoTab: string | null; -} { - const SEP = '@#$#@#$#@'; - const parts = contents.split(SEP); - if (parts.length < 5) return { netlogoVersion: null, infoTab: null }; - const infoTab = parts[2]?.trim() || null; - const versionRaw = parts[4]?.trim() || null; - const netlogoVersion = versionRaw && versionRaw.length < 100 ? versionRaw : null; - return { netlogoVersion, infoTab }; -} - -function parseNlogox(contents: string): { - netlogoVersion: string | null; - infoTab: string | null; -} { - try { - const parser = new DOMParser(); - const doc = parser.parseFromString(contents, 'application/xml'); - const modelEl = doc.querySelector('model'); - if (!modelEl) return { netlogoVersion: null, infoTab: null }; - const versionRaw = modelEl.getAttribute('version') ?? null; - const netlogoVersion = versionRaw - ? versionRaw.trim().replace(/^NetLogo\s*(3D)?\s*/i, '') - : null; - const infoTabEl = doc.querySelector('info'); - const infoTab = infoTabEl ? infoTabEl.textContent?.trim() || null : null; - return { netlogoVersion, infoTab }; - } catch { - return { netlogoVersion: null, infoTab: null }; - } -} - -function getNlogoFileExtension(contents: string): string { - if (contents.includes('@#$#@#$#@')) return 'nlogo'; - if (contents.includes(' 0) { + console.error( + '\nRefusing to continue — the diff contains changes this script will not guess at:', + ); + for (const b of plan.blockers) console.error(` ✗ ${b}`); + process.exitCode = 1; + return; + } + + if (!APPLY) { + console.log('\nDry run. Re-run with --apply to stage files and write these changes.'); + return; + } + + const expectations = buildExpectations(plan); + await stageFiles(plan); + await applyPlan(plan); + await mkdir(OUTPUT_DIR, { recursive: true }); + await writeFile( + MANIFEST_PATH, + JSON.stringify( + { + generatedAt: new Date().toISOString(), + legacySchema: LEGACY_SCHEMA, + expectations, + } satisfies Manifest, + null, + 2, + ), + ); + console.log(` manifest written to ${MANIFEST_PATH}`); + await verify(expectations); +} + +// --diff intake + +async function loadDiffs(): Promise> { + const files = (await readdir(DIFF_DIR)).filter((f) => f.endsWith('.csv')).sort(); + const diffs = new Map(); + const ignored: string[] = []; + + for (const file of files) { + const table = file.replace(/\.csv$/, ''); + const diff = parseTableDiff(table, await readFile(path.join(DIFF_DIR, file), 'utf8')); + + if (!isPatchableTable(table)) { + ignored.push(`${table} (${diff.rows.length} rows)`); + continue; + } + if (diff.problems.length > 0) { + throw new Error(`Unusable diff for ${table}:\n ${diff.problems.join('\n ')}`); + } + diffs.set(table, diff); + } + + if (ignored.length > 0) { + console.log( + '→ Ignored, because initial-import.ts never mapped these tables into the new schema:', + ); + console.log(` ${ignored.join(', ')}\n`); + } + return diffs; +} + +function rows(diffs: Map, table: PatchableTable, side: DiffRow['side']) { + const diff = diffs.get(table); + return diff ? rowsBySide(diff, side) : []; +} + +// planning + +type PlanContext = { + legacy: LegacyDatabase; + userIdByLegacyId: Map; + tagIdByLegacyId: Map; + tagIdByName: Map; + modelIdByLegacyId: Map; + createdNodeIds: Set; +}; + +async function buildPlan( + diffs: Map, + legacy: LegacyDatabase, +): Promise { + const plan: Plan = { + tags: { create: [], alias: [], update: [], remove: [] }, + users: { create: [], update: [], softDelete: [] }, + models: { create: [], update: [], softDelete: [] }, + versions: { append: [], update: [] }, + additionalFiles: { add: [], remove: [] }, + previews: [], + taggings: { add: [], remove: [] }, + files: [], + notes: [], + blockers: [], + }; + + const [targetUsers, targetTags, targetModels] = await Promise.all([ + prisma.user.findMany({ + where: { legacyId: { not: null } }, + select: { id: true, legacyId: true }, + }), + prisma.tag.findMany({ select: { id: true, legacyId: true, name: true } }), + prisma.model.findMany({ + where: { legacyId: { not: null } }, + select: { id: true, legacyId: true }, + }), + ]); + + const ctx: PlanContext = { + legacy, + userIdByLegacyId: indexByLegacyId(targetUsers), + tagIdByLegacyId: indexByLegacyId(targetTags), + tagIdByName: new Map(targetTags.map((t) => [t.name, t.id] as const)), + modelIdByLegacyId: indexByLegacyId(targetModels), + createdNodeIds: new Set(), + }; + + await planTags(diffs, plan, ctx); + await planUsers(diffs, plan, ctx); + await planNewModels(diffs, plan, ctx); + await planVersions(diffs, plan, ctx); + await planAdditionalFilesAndPreviews(diffs, plan, ctx); + await planTaggings(diffs, plan, ctx); + await planModelUpdates(diffs, plan, ctx); + await planDeletions(diffs, plan, ctx); + + return plan; +} + +async function planTags(diffs: Map, plan: Plan, ctx: PlanContext) { + const newTags = await ctx.legacy.tagsByIds(rows(diffs, 'tags', 'new').map((r) => r.id)); + const modifiedTags = await ctx.legacy.tagsByIds(rows(diffs, 'tags', 'modified').map((r) => r.id)); + + for (const t of newTags) { + if (ctx.tagIdByLegacyId.has(t.id)) { + plan.notes.push(`tag ${t.id} already present in target; nothing to do`); + continue; + } + const name = normalizeTagName(t.name); + if (!name) { + plan.notes.push(`tag ${t.id} has a blank name; skipped, as initial-import.ts does`); + continue; + } + const existingId = ctx.tagIdByName.get(name); + if (existingId) { + // Tag.name and Tag.legacyId are both unique, so the newcomer cannot claim + // a second legacyId on that row. Point its taggings at the incumbent. + plan.tags.alias.push({ legacyId: t.id, name, tagId: existingId }); + plan.notes.push( + `tag ${t.id} "${name}" resolves to the existing tag that already owns that name`, + ); + ctx.tagIdByLegacyId.set(t.id, existingId); + continue; + } + const id = randomUUID(); + plan.tags.create.push({ + id, + legacyId: t.id, + name, + displayName: (t.name ?? '').trim() || null, + createdAt: t.created_at ?? new Date(), + }); + ctx.tagIdByLegacyId.set(t.id, id); + ctx.tagIdByName.set(name, id); + } + + for (const t of modifiedTags) { + const tagId = ctx.tagIdByLegacyId.get(t.id); + if (!tagId) { + plan.notes.push(`tag ${t.id} was modified but is not in the target; skipped`); + continue; + } + const name = normalizeTagName(t.name); + if (!name) { + plan.notes.push(`tag ${t.id} was renamed to a blank name; left unchanged`); + continue; + } + const holder = ctx.tagIdByName.get(name); + if (holder && holder !== tagId) { + plan.notes.push( + `tag ${t.id} was renamed to "${name}", which another tag owns; left unchanged`, + ); + continue; + } + const current = await prisma.tag.findUnique({ + where: { id: tagId }, + select: { name: true, displayName: true }, + }); + const data = changedFields(current ?? {}, { + name, + displayName: (t.name ?? '').trim() || null, + }); + if (Object.keys(data).length > 0) plan.tags.update.push({ tagId, legacyId: t.id, data }); + } + + for (const row of rows(diffs, 'tags', 'deleted')) { + const tagId = ctx.tagIdByLegacyId.get(row.id); + if (!tagId) continue; + plan.tags.remove.push({ + tagId, + legacyId: row.id, + name: optionalString(row.deletedRow ?? {}, 'name') ?? '?', + }); + // Stop it resolving, or a tagging in the same diff would be created and then + // cascade-deleted, and verification would report a misleading failure. + ctx.tagIdByLegacyId.delete(row.id); + } +} + +async function planUsers(diffs: Map, plan: Plan, ctx: PlanContext) { + const newPeople = await ctx.legacy.peopleByIds(rows(diffs, 'people', 'new').map((r) => r.id)); + const modifiedPeople = await ctx.legacy.peopleByIds( + rows(diffs, 'people', 'modified').map((r) => r.id), + ); + + // Within the diff itself the lowest legacy id still claims a shared email. + const emailWinner = pickLowestIdWinners(newPeople, (p) => normalizeEmail(p.email_address)); + + for (const p of newPeople) { + if (ctx.userIdByLegacyId.has(p.id)) { + plan.notes.push(`person ${p.id} already present in target; nothing to do`); + continue; + } + const id = randomUUID(); + plan.users.create.push({ + id, + legacyId: p.id, + email: await claimEmail(p, emailWinner, plan), + name: buildFullName(p.first_name, p.last_name), + emailVerified: false, + bio: p.biography?.trim() || null, + dob: toUtcDateOnly(p.birthdate), + image: await stageAvatar(p, id, plan), + socialLinks: [{ type: 'other', rawValue: p.url?.trim() || null }], + systemRole: 'user', + userKind: 'other', + createdAt: p.created_at ?? new Date(), + updatedAt: p.updated_at ?? p.created_at ?? new Date(), + }); + ctx.userIdByLegacyId.set(p.id, id); + } + + let avatarsSkipped = 0; + for (const p of modifiedPeople) { + const userId = ctx.userIdByLegacyId.get(p.id); + if (!userId) { + plan.notes.push(`person ${p.id} was modified but is not in the target; skipped`); + continue; + } + if (p.avatar_file_name) avatarsSkipped++; + + const current = await prisma.user.findUnique({ + where: { id: userId }, + select: { + email: true, + name: true, + bio: true, + dob: true, + socialLinks: true, + createdAt: true, + }, + }); + if (!current) continue; + + const desired: Record = { + name: buildFullName(p.first_name, p.last_name), + bio: p.biography?.trim() || null, + dob: toUtcDateOnly(p.birthdate), + socialLinks: [{ type: 'other', rawValue: p.url?.trim() || null }], + createdAt: p.created_at ?? current.createdAt, + }; + + const email = normalizeEmail(p.email_address); + if (email && email !== current.email) { + const holder = await prisma.user.findUnique({ where: { email }, select: { id: true } }); + if (holder && holder.id !== userId) { + plan.notes.push(`person ${p.id} now uses an email another user owns; email left unchanged`); + } else { + desired['email'] = email; + } + } + + const data = changedFields(current, desired); + if (Object.keys(data).length > 0) plan.users.update.push({ legacyId: p.id, userId, data }); + } + + if (avatarsSkipped > 0) { + plan.notes.push( + `${avatarsSkipped} modified people have avatars; avatar images are a filesystem snapshot rather than ` + + `part of the diff, so User.image was left unchanged`, + ); + } +} + +async function claimEmail( + p: LegacyPerson, + emailWinner: Map, + plan: Plan, +): Promise { + const email = normalizeEmail(p.email_address); + if (!email) return null; + if (emailWinner.get(email)?.id !== p.id) { + plan.notes.push( + `person ${p.id} shares an email with a lower legacy id in this diff; email dropped`, + ); + return null; + } + const holder = await prisma.user.findUnique({ where: { email }, select: { legacyId: true } }); + if (holder) { + plan.notes.push( + `person ${p.id} reuses the email of migrated person ${holder.legacyId}; email dropped`, + ); + return null; + } + return email; +} + +async function stageAvatar(p: LegacyPerson, userId: string, plan: Plan): Promise { + if (!p.avatar_file_name) return null; + const key = buildAvatarFileKey(userId, p.avatar_updated_at ?? new Date(), randomUUID(), 'avatar'); + const source = path.join(AVATARS_DIR, `${p.id}`, 'original', p.avatar_file_name); + try { + plan.files.push({ key, body: await readFile(source) }); + return `cdn.modelingcommons.org/modeling-commons/${key}`; + } catch { + plan.notes.push(`person ${p.id} has an avatar but ${source} is missing; image left null`); + return null; + } +} + +async function planNewModels(diffs: Map, plan: Plan, ctx: PlanContext) { + const newNodes = await ctx.legacy.nodesByIds(rows(diffs, 'nodes', 'new').map((r) => r.id)); + if (newNodes.length === 0) return; + + const spamNodeIds = await ctx.legacy.spamNodeIds(); + + for (const node of newNodes) { + if (ctx.modelIdByLegacyId.has(node.id)) { + plan.notes.push(`node ${node.id} already present in target; nothing to do`); + continue; + } + if (spamNodeIds.has(node.id)) { + plan.notes.push(`node ${node.id} has >=2 spam warnings; skipped, as initial-import.ts does`); + continue; + } + + const [versions, attachments, taggings] = await Promise.all([ + ctx.legacy.versionsForNode(node.id), + ctx.legacy.attachmentsForNode(node.id), + ctx.legacy.taggingsForNode(node.id), + ]); + if (versions.length === 0) { + plan.notes.push(`node ${node.id} has no versions; skipped, as initial-import.ts does`); + continue; + } + + const modelId = randomUUID(); + const tree: NodeTree = { node, versions, attachments, taggings }; + const ops: RecordedOp[] = []; + + // Run the real archive routine now so the plan holds every write and every + // file. Applying just replays these ops inside the transaction. + await createModelFromNode(recordingWriter(ops), modelId, tree, { + writeFile: async (key, body) => { + plan.files.push({ key, body }); + }, + newUuid: randomUUID, + now: () => new Date(), + userIdByLegacyId: ctx.userIdByLegacyId, + tagIdByLegacyId: ctx.tagIdByLegacyId, + }); + + plan.models.create.push({ modelId, node, versionCount: versions.length, ops }); + ctx.modelIdByLegacyId.set(node.id, modelId); + ctx.createdNodeIds.add(node.id); + } +} + +function recordingWriter(ops: RecordedOp[]): ModelWriter { + const record = + (model: keyof ModelWriter, op: 'create' | 'update') => + (args: unknown): Promise => { + ops.push({ model, op, args }); + return Promise.resolve({}); + }; + return { + model: { create: record('model', 'create'), update: record('model', 'update') }, + modelVersion: { + create: record('modelVersion', 'create'), + update: record('modelVersion', 'update'), + }, + modelAuthor: { create: record('modelAuthor', 'create') }, + modelAdditionalFile: { create: record('modelAdditionalFile', 'create') }, + modelVersionTag: { create: record('modelVersionTag', 'create') }, + }; +} + +async function planVersions(diffs: Map, plan: Plan, ctx: PlanContext) { + for (const row of rows(diffs, 'versions', 'deleted')) { + const nodeId = requireNumber(row.deletedRow ?? {}, 'node_id'); + if (rows(diffs, 'nodes', 'deleted').some((n) => n.id === nodeId)) { + plan.notes.push( + `version ${row.id} went with its deleted node ${nodeId}; covered by the model soft delete`, + ); + continue; + } + if (!ctx.modelIdByLegacyId.has(nodeId)) continue; + plan.blockers.push( + `version ${row.id} was deleted from surviving node ${nodeId}. versionNumber is a positional counter ` + + `referenced by Model.latestVersionNumber, Model.parentVersionNumber, ModelVersionTag and ` + + `ModelAdditionalFile, so removing one mid-sequence needs a hand-written renumbering.`, + ); + } + + const newVersions = await ctx.legacy.versionsByIds( + rows(diffs, 'versions', 'new').map((r) => r.id), + ); + const byNode = new Map(); + for (const v of newVersions) { + if (ctx.createdNodeIds.has(v.node_id)) continue; // written by createModelFromNode + byNode.set(v.node_id, [...(byNode.get(v.node_id) ?? []), v]); + } + + for (const [nodeId, appended] of byNode) { + const modelId = ctx.modelIdByLegacyId.get(nodeId); + if (!modelId) { + plan.notes.push( + `${appended.length} new version(s) belong to node ${nodeId}, not in the target; skipped`, + ); + continue; + } + + const legacyOrder = await ctx.legacy.versionsForNode(nodeId); + const existing = await prisma.modelVersion.findMany({ + where: { modelId }, + orderBy: { versionNumber: 'asc' }, + select: { versionNumber: true, previewImageFileKey: true }, + }); + + const appendedIds = new Set(appended.map((v) => v.id)); + const missing = legacyOrder.length - existing.length; + + if (missing === 0) { + plan.notes.push( + `node ${nodeId}: version(s) ${[...appendedIds].join(', ')} are already in the target; nothing to append`, + ); + continue; + } + + const tail = missing > 0 ? legacyOrder.slice(legacyOrder.length - missing) : []; + if (missing < 0 || !tail.every((v) => appendedIds.has(v.id))) { + plan.blockers.push( + `node ${nodeId}: cannot append version(s) ${[...appendedIds].join(', ')}. The target holds ` + + `${existing.length} version(s) against ${legacyOrder.length} in the legacy snapshot, and the ` + + `${missing} missing one(s) are not exactly the chronologically newest. Appending would break the ` + + `created_at ordering that versionNumber encodes.`, + ); + continue; + } + + const node = (await ctx.legacy.nodesByIds([nodeId]))[0]; + if (!node) continue; + + const previousLatest = existing.at(-1); + const carryTagIds = previousLatest + ? ( + await prisma.modelVersionTag.findMany({ + where: { modelId, versionNumber: previousLatest.versionNumber }, + select: { tagId: true }, + }) + ).map((t) => t.tagId) + : []; + + let versionNumber = previousLatest?.versionNumber ?? 0; + for (const [index, v] of tail.entries()) { + versionNumber++; + const isLast = index === tail.length - 1; + plan.versions.append.push({ + nodeLegacyId: nodeId, + modelId, + versionNumber, + legacyVersionId: v.id, + data: stageVersion(plan, buildVersionCreate(modelId, node, v, versionNumber), v), + contributorUserId: ctx.userIdByLegacyId.get(v.person_id) ?? null, + // initial-import.ts keeps a node's tags and preview on its latest version + // only, and the app reads them from there. Move them onto the new + // latest so the result matches a fresh archive of the same snapshot. + carryTagIds: isLast ? carryTagIds : [], + carryPreviewImageFileKey: isLast ? (previousLatest?.previewImageFileKey ?? null) : null, + vacatedVersionNumber: isLast ? (previousLatest?.versionNumber ?? null) : null, + }); + } + } + + const changedVersions = await ctx.legacy.versionsByIds( + rows(diffs, 'versions', 'modified').map((r) => r.id), + ); + for (const v of changedVersions) { + if (ctx.createdNodeIds.has(v.node_id)) continue; + const modelId = ctx.modelIdByLegacyId.get(v.node_id); + if (!modelId) continue; + + const legacyOrder = await ctx.legacy.versionsForNode(v.node_id); + const count = await prisma.modelVersion.count({ where: { modelId } }); + const position = legacyOrder.findIndex((x) => x.id === v.id); + + if (count !== legacyOrder.length || position < 0) { + plan.blockers.push( + `version ${v.id} on node ${v.node_id} was modified, but the target holds ${count} version(s) against ` + + `${legacyOrder.length} in the legacy snapshot, so its versionNumber cannot be derived.`, + ); + continue; + } + + const node = (await ctx.legacy.nodesByIds([v.node_id]))[0]; + if (!node) continue; + const versionNumber = position + 1; + const created = buildVersionCreate(modelId, node, v, versionNumber); + + const current = await prisma.modelVersion.findUnique({ + where: { modelId_versionNumber: { modelId, versionNumber } }, + select: { description: true, netlogoFileKey: true, netlogoVersion: true, infoTab: true }, + }); + const data = changedFields(current ?? {}, { + description: created.description, + netlogoFileKey: created.netlogoFileKey, + netlogoVersion: created.netlogoVersion, + infoTab: created.infoTab, + }); + + if (Object.keys(data).length === 0) { + plan.notes.push(`version ${v.id} is already up to date in the target; nothing to do`); + continue; + } + + stageVersion(plan, created, v); + plan.versions.update.push({ legacyVersionId: v.id, modelId, versionNumber, data }); + } +} + +/** + * Derives the object key from the legacy version id rather than a fresh random + * one, so re-running lands on the same object instead of uploading a duplicate + * and repointing the row at it. + */ +function buildVersionCreate( + modelId: string, + node: LegacyNode, + v: LegacyVersion, + versionNumber: number, +): Prisma.ModelVersionUncheckedCreateInput { + const format = getNlogoFileExtension(v.contents); + const key = buildVersionFileKey( + modelId, + v.created_at ?? node.created_at ?? new Date(), + derivedUuid('version', v.id), + `${node.name}.${format}`, + ); + + const { netlogoVersion, infoTab } = parseNetlogoContents(v.contents, format); + return { + modelId, + versionNumber, + title: node.name, + description: v.description || null, + netlogoFileKey: key, + netlogoVersion, + infoTab, + createdAt: v.created_at ?? new Date(), + finalizedAt: v.created_at ?? null, + }; +} + +function stageVersion( + plan: Plan, + data: Prisma.ModelVersionUncheckedCreateInput, + v: LegacyVersion, +): Prisma.ModelVersionUncheckedCreateInput { + plan.files.push({ key: data.netlogoFileKey, body: Buffer.from(v.contents, 'utf8') }); + return data; +} + +async function planAdditionalFilesAndPreviews( + diffs: Map, + plan: Plan, + ctx: PlanContext, +) { + const added = await ctx.legacy.attachmentsByIds( + rows(diffs, 'attachments', 'new').map((r) => r.id), + ); + const changed = await ctx.legacy.attachmentsByIds( + rows(diffs, 'attachments', 'modified').map((r) => r.id), + ); + const removed = rows(diffs, 'attachments', 'deleted'); + const changedIds = new Set(changed.map((a) => a.id)); + + const previewNodeIds = new Set(); + const seenNodeIds = new Set(); + + const touch = (nodeId: number, isPreview: boolean) => { + if (ctx.createdNodeIds.has(nodeId)) return; + if (!ctx.modelIdByLegacyId.has(nodeId)) { + if (!seenNodeIds.has(nodeId)) { + plan.notes.push(`attachment changes reference node ${nodeId}, not in the target; skipped`); + } + seenNodeIds.add(nodeId); + return; + } + seenNodeIds.add(nodeId); + if (isPreview) previewNodeIds.add(nodeId); + }; + + for (const a of added) touch(a.node_id, a.content_type === 'preview'); + for (const a of changed) touch(a.node_id, a.content_type === 'preview'); + for (const row of removed) { + const deleted = row.deletedRow ?? {}; + touch(requireNumber(deleted, 'node_id'), optionalString(deleted, 'content_type') === 'preview'); + } + + // A non-preview attachment whose bytes or filename changed maps onto a + // ModelAdditionalFile row that carries no legacy id, so there is no reliable + // way to tell which row to rewrite. Stop rather than guess. + const changedFiles = changed.filter((a) => a.content_type !== 'preview'); + if (changedFiles.length > 0) { + plan.blockers.push( + `attachment(s) ${changedFiles.map((a) => a.id).join(', ')} were modified in place. ` + + `ModelAdditionalFile carries no legacyId, so the matching row cannot be identified with ` + + `confidence. Handle these by hand, or re-upload them in the legacy app so they arrive as new rows.`, + ); + } + + for (const a of added) { + if (a.content_type === 'preview') continue; // the resync below owns previews + if (ctx.createdNodeIds.has(a.node_id)) continue; + const modelId = ctx.modelIdByLegacyId.get(a.node_id); + if (!modelId) continue; + + const existing = await findAdditionalFile(modelId, a.filename, a.created_at); + if (existing === 'ambiguous') { + plan.notes.push( + `attachment ${a.id} (${a.filename}) matches more than one existing row; assuming already present`, + ); + continue; + } + if (existing) { + plan.notes.push(`attachment ${a.id} already present as ${existing.id}; nothing to do`); + continue; + } + + const fileUuid = randomUUID(); + const key = buildAttachmentFileKey(modelId, a.created_at ?? new Date(), fileUuid, a.filename); + plan.files.push({ key, body: a.contents }); + plan.files.push({ + key: `${key}.metadata.json`, + body: buildAttachmentMetadata(a, ctx.userIdByLegacyId, new Date()), + }); + + plan.additionalFiles.add.push({ + legacyAttachmentId: a.id, + nodeLegacyId: a.node_id, + data: { + id: fileUuid, + modelId, + taggedVersionNumber: await latestVersionNumberAfterAppends(plan, modelId), + fileKey: key, + kind: 'additional', + createdAt: a.created_at ?? new Date(), + }, + }); + } + + for (const row of removed) { + const deleted = row.deletedRow ?? {}; + if (optionalString(deleted, 'content_type') === 'preview') continue; + const nodeId = requireNumber(deleted, 'node_id'); + if (ctx.createdNodeIds.has(nodeId)) continue; + const modelId = ctx.modelIdByLegacyId.get(nodeId); + if (!modelId) continue; + + const filename = optionalString(deleted, 'filename'); + if (!filename) { + plan.notes.push( + `deleted attachment ${row.id} has no filename in the diff; cannot locate its row`, + ); + continue; + } + const match = await findAdditionalFile(modelId, filename, optionalDate(deleted, 'created_at')); + if (match === 'ambiguous') { + plan.blockers.push( + `deleted attachment ${row.id} (${filename}) on node ${nodeId} matches more than one ` + + `ModelAdditionalFile row. That table carries no legacyId, so deleting one would be a guess.`, + ); + continue; + } + if (!match) { + plan.notes.push( + `deleted attachment ${row.id} (${filename}) has no row in the target; already gone`, + ); + continue; + } + plan.additionalFiles.remove.push({ + legacyAttachmentId: row.id, + modelId, + additionalFileId: match.id, + }); + } + + // A preview is a single column on the latest version, and the highest legacy + // attachment id wins it. Individual adds/removes cannot be applied to that; + // recompute it from the whole attachment set instead. + for (const nodeId of previewNodeIds) { + const modelId = ctx.modelIdByLegacyId.get(nodeId); + if (!modelId) continue; + + const previews = (await ctx.legacy.attachmentsForNode(nodeId)).filter( + (a) => a.content_type === 'preview', + ); + const winner = previews.at(-1) ?? null; + const versionNumber = await latestVersionNumberAfterAppends(plan, modelId); + + // Derive the object key from the legacy attachment id so re-running lands on + // the same object instead of uploading a fresh copy every time. + const key = winner + ? buildPreviewFileKey( + modelId, + winner.created_at ?? new Date(), + derivedUuid('preview', winner.id), + winner.filename, + ) + : null; + + // When a version is being appended, the version this resync targets does not + // exist in the database yet; what it will hold is whatever the append + // carries forward. Comparing against the database would read null and wrongly + // conclude a cleared preview is already applied. + const append = plan.versions.append.filter((a) => a.modelId === modelId).at(-1); + const currentKey = append + ? append.carryPreviewImageFileKey + : (( + await prisma.modelVersion.findUnique({ + where: { modelId_versionNumber: { modelId, versionNumber } }, + select: { previewImageFileKey: true }, + }) + )?.previewImageFileKey ?? null); + const alreadyPointsThere = samePreviewObject(currentKey, key); + + if (alreadyPointsThere && !(winner && changedIds.has(winner.id))) { + plan.notes.push( + `preview for node ${nodeId} already points at ` + + `${winner ? `attachment ${winner.id}` : 'nothing'}; nothing to do`, + ); + continue; + } + + if (winner && key) plan.files.push({ key, body: winner.contents }); + if (alreadyPointsThere) continue; // bytes restaged, but the row is already right + + if (append) append.carryPreviewImageFileKey = null; // this resync supersedes it + plan.previews.push({ + nodeLegacyId: nodeId, + modelId, + versionNumber, + previewImageFileKey: key, + sourceAttachmentId: winner?.id ?? null, + }); + } +} + +/** + * The uuid segment of a file key is a nonce; what identifies a preview object is + * its model, date partition and filename. createModelFromNode mints a random + * nonce while the resync derives one from the legacy attachment id, so compare + * the two without it. + */ +function samePreviewObject(a: string | null, b: string | null): boolean { + if (a === null || b === null) return a === b; + const strip = (key: string) => key.replace(/\/[0-9a-f-]{36}\//gi, '/'); + return strip(a) === strip(b); +} + +/** + * ModelAdditionalFile carries no legacy id, so a row is located by its filename + * and creation time. Returns 'ambiguous' rather than picking one when that pair + * does not single a row out — deleting the wrong attachment is unrecoverable. + */ +async function findAdditionalFile( + modelId: string, + filename: string, + createdAt: Date | null, +): Promise<{ id: string; fileKey: string } | 'ambiguous' | null> { + const candidates = await prisma.modelAdditionalFile.findMany({ + where: { modelId }, + select: { id: true, fileKey: true, createdAt: true }, + }); + const suffix = `/${sanitizeFilename(filename)}`; + const matches = candidates.filter( + (c) => + c.fileKey.endsWith(suffix) && + (createdAt === null || c.createdAt.getTime() === createdAt.getTime()), + ); + if (matches.length === 0) return null; + if (matches.length > 1) return 'ambiguous'; + return matches[0]!; +} + +async function latestVersionNumberAfterAppends(plan: Plan, modelId: string): Promise { + const appended = plan.versions.append.filter((a) => a.modelId === modelId).at(-1); + if (appended) return appended.versionNumber; + const latest = await prisma.modelVersion.findFirst({ + where: { modelId }, + orderBy: { versionNumber: 'desc' }, + select: { versionNumber: true }, + }); + return latest?.versionNumber ?? 1; +} + +async function planTaggings(diffs: Map, plan: Plan, ctx: PlanContext) { + const added = await ctx.legacy.taggingsByIds(rows(diffs, 'tagged_nodes', 'new').map((r) => r.id)); + + for (const tg of added) { + if (ctx.createdNodeIds.has(tg.node_id)) continue; + const modelId = ctx.modelIdByLegacyId.get(tg.node_id); + const tagId = ctx.tagIdByLegacyId.get(tg.tag_id); + if (!modelId) { + plan.notes.push(`tagging ${tg.id} references node ${tg.node_id}, not in the target; skipped`); + continue; + } + if (!tagId) { + plan.notes.push(`tagging ${tg.id} references tag ${tg.tag_id}, not in the target; skipped`); + continue; + } + + const versionNumber = await latestVersionNumberAfterAppends(plan, modelId); + const already = await prisma.modelVersionTag.findFirst({ + where: { modelId, versionNumber, tagId }, + }); + if (already) { + plan.notes.push( + `tagging ${tg.id} already present on version ${versionNumber}; nothing to do`, + ); + continue; + } + if (plan.taggings.add.some((t) => t.data.modelId === modelId && t.data.tagId === tagId)) + continue; + + plan.taggings.add.push({ + nodeLegacyId: tg.node_id, + tagLegacyId: tg.tag_id, + data: { modelId, versionNumber, tagId, createdAt: tg.created_at ?? new Date() }, + }); + } + + for (const row of rows(diffs, 'tagged_nodes', 'deleted')) { + const deleted = row.deletedRow ?? {}; + const nodeId = requireNumber(deleted, 'node_id'); + const tagLegacyId = requireNumber(deleted, 'tag_id'); + if (ctx.createdNodeIds.has(nodeId)) continue; + + const modelId = ctx.modelIdByLegacyId.get(nodeId); + const tagId = ctx.tagIdByLegacyId.get(tagLegacyId); + if (!modelId || !tagId) continue; + plan.taggings.remove.push({ nodeLegacyId: nodeId, modelId, tagId, tagLegacyId }); + } +} + +/** + * `updatedAt` is carried by Prisma's @updatedAt, which overrides any value + * supplied on create — so initial-import.ts stamped every migrated row with the + * migration time and legacy `updated_at` was never preserved. Writing it here + * would leave a handful of rows inconsistent with the rest, so it is left alone. + */ +async function planModelUpdates( + diffs: Map, + plan: Plan, + ctx: PlanContext, +) { + const changed = await ctx.legacy.nodesByIds(rows(diffs, 'nodes', 'modified').map((r) => r.id)); + + for (const node of changed) { + const modelId = ctx.modelIdByLegacyId.get(node.id); + if (!modelId) { + plan.notes.push(`node ${node.id} was modified but is not in the target; skipped`); + continue; + } + const current = await prisma.model.findUnique({ + where: { id: modelId }, + select: { visibility: true, createdAt: true }, + }); + if (!current) continue; + + const data = changedFields(current, { + visibility: mapVisibility(node.visibility_id), + createdAt: node.created_at ?? current.createdAt, + }); + + // initial-import.ts titles every version with the node name, so a rename fans out. + const staleTitles = await prisma.modelVersion.count({ + where: { modelId, title: { not: node.name } }, + }); + const retitleVersionsTo = staleTitles > 0 ? node.name : null; + + if (Object.keys(data).length > 0 || retitleVersionsTo) { + plan.models.update.push({ legacyId: node.id, modelId, data, retitleVersionsTo }); + } + } +} + +async function planDeletions(diffs: Map, plan: Plan, ctx: PlanContext) { + for (const row of rows(diffs, 'nodes', 'deleted')) { + const modelId = ctx.modelIdByLegacyId.get(row.id); + if (!modelId) { + plan.notes.push(`node ${row.id} was deleted but is not in the target; nothing to do`); + continue; + } + const current = await prisma.model.findUnique({ + where: { id: modelId }, + select: { deletedAt: true }, + }); + if (current?.deletedAt) continue; + plan.models.softDelete.push({ legacyId: row.id, modelId }); + } + + for (const row of rows(diffs, 'people', 'deleted')) { + const userId = ctx.userIdByLegacyId.get(row.id); + if (!userId) continue; + const current = await prisma.user.findUnique({ + where: { id: userId }, + select: { deletedAt: true }, + }); + if (current?.deletedAt) continue; + plan.users.softDelete.push({ legacyId: row.id, userId }); + } +} + +// -output + +function printPlan(plan: Plan) { + const counts: Array<[number, string]> = [ + [plan.tags.create.length, 'Tag rows created'], + [plan.tags.update.length, 'Tag rows renamed'], + [plan.tags.remove.length, 'Tag rows deleted (cascades to ModelVersionTag)'], + [plan.users.create.length, 'User rows created'], + [plan.users.update.length, 'User rows updated'], + [plan.users.softDelete.length, 'User rows soft deleted'], + [plan.models.create.length, 'Models created with their full version/author/file/tag tree'], + [plan.models.update.length, 'Models updated'], + [plan.models.softDelete.length, 'Models soft deleted'], + [plan.versions.append.length, 'ModelVersion rows appended to existing models'], + [plan.versions.update.length, 'ModelVersion rows updated in place'], + [plan.additionalFiles.add.length, 'ModelAdditionalFile rows added'], + [plan.additionalFiles.remove.length, 'ModelAdditionalFile rows removed'], + [plan.previews.length, 'preview images recomputed from the full attachment set'], + [plan.taggings.add.length, 'ModelVersionTag rows added'], + [plan.taggings.remove.length, 'ModelVersionTag rows removed'], + [plan.files.length, 'files staged for object storage'], + ]; + + console.log('=== PLAN ==='); + const lines = counts + .filter(([n]) => n > 0) + .map(([n, what]) => ` ${String(n).padStart(4)} ${what}`); + console.log(lines.length > 0 ? lines.join('\n') : ' (nothing to do)'); + + console.log(''); + for (const m of plan.models.create) { + console.log(` + model legacyId=${m.node.id} "${m.node.name}" (${m.versionCount} versions)`); + } + for (const t of plan.tags.create) console.log(` + tag legacyId=${t.legacyId} "${t.name}"`); + for (const u of plan.users.create) + console.log(` + user legacyId=${u.legacyId} "${u.name ?? ''}"`); + for (const u of plan.users.update) + console.log(` ~ user legacyId=${u.legacyId} ${fieldList(u.data)}`); + for (const u of plan.models.update) { + console.log( + ` ~ model legacyId=${u.legacyId} ${fieldList(u.data)}${u.retitleVersionsTo ? ' +retitle versions' : ''}`, + ); + } + for (const d of plan.models.softDelete) + console.log(` - model legacyId=${d.legacyId} soft deleted`); + for (const d of plan.users.softDelete) + console.log(` - user legacyId=${d.legacyId} soft deleted`); + for (const a of plan.versions.append) { + console.log( + ` + version #${a.versionNumber} on node ${a.nodeLegacyId} from legacy version ${a.legacyVersionId}`, + ); + } + for (const u of plan.versions.update) { + console.log(` ~ version #${u.versionNumber} from legacy version ${u.legacyVersionId}`); + } + for (const a of plan.additionalFiles.add) { + console.log( + ` + additional file on node ${a.nodeLegacyId} from attachment ${a.legacyAttachmentId}`, + ); + } + for (const r of plan.additionalFiles.remove) { + console.log(` - additional file from attachment ${r.legacyAttachmentId}`); + } + for (const p of plan.previews) { + console.log( + ` ~ preview node=${p.nodeLegacyId} version ${p.versionNumber} → ` + + `${p.sourceAttachmentId ? `attachment ${p.sourceAttachmentId}` : 'none (cleared)'}`, + ); + } + for (const t of plan.taggings.add) + console.log(` + tagging node=${t.nodeLegacyId} tag=${t.tagLegacyId}`); + for (const t of plan.taggings.remove) + console.log(` - tagging node=${t.nodeLegacyId} tag=${t.tagLegacyId}`); + + if (plan.notes.length > 0) { + console.log('\n--- notes ---'); + for (const n of plan.notes) console.log(` · ${n}`); + } +} + +function fieldList(data: Record): string { + return `[${Object.keys(data).join(', ')}]`; +} + +// --files + +async function stageFiles(plan: Plan) { + if (plan.files.length === 0) return; + console.log(`\n→ Staging ${plan.files.length} files under ${path.resolve(FILES_DIR)}`); + + for (const file of plan.files) { + const full = path.join(FILES_DIR, file.key); + await mkdir(path.dirname(full), { recursive: true }); + await writeFile(full, file.body); + } + + if (SKIP_UPLOAD) { + console.log(' --skip-upload: nothing sent to object storage'); + return; + } + + const storage = createStorage(); + for (const file of plan.files) { + await storage.client.send( + new PutObjectCommand({ + Bucket: storage.bucket, + Key: file.key, + Body: file.body, + ACL: 'public-read', + }), + ); + } + console.log(` uploaded ${plan.files.length} objects to ${storage.bucket}`); +} + +function createStorage() { + return { + client: new S3Client({ + region: process.env['STORE_REGION'], + credentials: { + accessKeyId: required('STORE_ACCESS_KEY'), + secretAccessKey: required('STORE_SECRET_KEY'), + }, + endpoint: process.env['STORE_ENDPOINT'], + forcePathStyle: true, + }), + bucket: required('STORE_BUCKET'), + }; +} + +// --apply + +async function applyPlan(plan: Plan) { + console.log('\n→ Applying (one transaction; rolls back entirely on error)'); + + await prisma.$transaction( + async (tx) => { + for (const data of plan.tags.create) await tx.tag.create({ data }); + for (const u of plan.tags.update) + await tx.tag.update({ where: { id: u.tagId }, data: u.data }); + + for (const data of plan.users.create) await tx.user.create({ data }); + for (const u of plan.users.update) { + await tx.user.update({ where: { id: u.userId }, data: u.data }); + } + + for (const m of plan.models.create) await replay(tx, m.ops); + + for (const a of plan.versions.append) { + if (a.vacatedVersionNumber !== null) { + await tx.modelVersionTag.deleteMany({ + where: { modelId: a.modelId, versionNumber: a.vacatedVersionNumber }, + }); + await tx.modelVersion.update({ + where: { + modelId_versionNumber: { modelId: a.modelId, versionNumber: a.vacatedVersionNumber }, + }, + data: { previewImageFileKey: null }, + }); + } + await tx.modelVersion.create({ data: a.data }); + await tx.model.update({ + where: { id: a.modelId }, + data: { latestVersionNumber: a.versionNumber }, + }); + if (a.carryPreviewImageFileKey) { + await tx.modelVersion.update({ + where: { + modelId_versionNumber: { modelId: a.modelId, versionNumber: a.versionNumber }, + }, + data: { previewImageFileKey: a.carryPreviewImageFileKey }, + }); + } + for (const tagId of a.carryTagIds) { + await tx.modelVersionTag.create({ + data: { modelId: a.modelId, versionNumber: a.versionNumber, tagId }, + }); + } + await tx.modelAdditionalFile.updateMany({ + where: { modelId: a.modelId }, + data: { taggedVersionNumber: a.versionNumber }, + }); + if (a.contributorUserId) { + await tx.modelAuthor.upsert({ + where: { modelId_userId: { modelId: a.modelId, userId: a.contributorUserId } }, + update: {}, + create: { modelId: a.modelId, userId: a.contributorUserId, role: 'contributor' }, + }); + } + } + + for (const u of plan.versions.update) { + await tx.modelVersion.update({ + where: { modelId_versionNumber: { modelId: u.modelId, versionNumber: u.versionNumber } }, + data: u.data, + }); + } + + for (const a of plan.additionalFiles.add) + await tx.modelAdditionalFile.create({ data: a.data }); + for (const r of plan.additionalFiles.remove) { + await tx.modelAdditionalFile.delete({ where: { id: r.additionalFileId } }); + } + + for (const p of plan.previews) { + await tx.modelVersion.update({ + where: { modelId_versionNumber: { modelId: p.modelId, versionNumber: p.versionNumber } }, + data: { previewImageFileKey: p.previewImageFileKey }, + }); + } + + for (const t of plan.taggings.add) await tx.modelVersionTag.create({ data: t.data }); + for (const t of plan.taggings.remove) { + await tx.modelVersionTag.deleteMany({ where: { modelId: t.modelId, tagId: t.tagId } }); + } + + for (const u of plan.models.update) { + if (Object.keys(u.data).length > 0) { + await tx.model.update({ where: { id: u.modelId }, data: u.data }); + } + if (u.retitleVersionsTo) { + await tx.modelVersion.updateMany({ + where: { modelId: u.modelId }, + data: { title: u.retitleVersionsTo }, + }); + } + } + + const now = new Date(); + for (const d of plan.models.softDelete) { + await tx.model.update({ where: { id: d.modelId }, data: { deletedAt: now } }); + } + for (const d of plan.users.softDelete) { + await tx.user.update({ where: { id: d.userId }, data: { deletedAt: now } }); + } + for (const r of plan.tags.remove) await tx.tag.delete({ where: { id: r.tagId } }); + }, + { timeout: TXN_TIMEOUT_MS, maxWait: 30_000 }, + ); + + console.log(' committed'); +} + +async function replay(tx: Prisma.TransactionClient, ops: readonly RecordedOp[]) { + for (const { model, op, args } of ops) { + const delegate = tx[model] as unknown as Record Promise>; + await delegate[op]!(args); + } +} + +// expectations + +function buildExpectations(plan: Plan): Expectation[] { + const out: Expectation[] = []; + + for (const t of plan.tags.create) out.push({ kind: 'tag', legacyId: t.legacyId!, name: t.name }); + for (const u of plan.users.create) out.push({ kind: 'user', legacyId: u.legacyId! }); + for (const u of plan.users.update) { + out.push({ + kind: 'fields', + entity: 'user', + id: u.userId, + legacyId: u.legacyId, + fields: jsonSafe(u.data), + }); + } + + for (const m of plan.models.create) { + out.push({ + kind: 'model', + legacyId: m.node.id, + versionCount: m.versionCount, + title: m.node.name, + }); + out.push({ kind: 'latestIsMax', modelId: m.modelId }); + } + for (const u of plan.models.update) { + if (Object.keys(u.data).length > 0) { + out.push({ + kind: 'fields', + entity: 'model', + id: u.modelId, + legacyId: u.legacyId, + fields: jsonSafe(u.data), + }); + } + if (u.retitleVersionsTo) { + out.push({ + kind: 'versionTitles', + modelId: u.modelId, + legacyId: u.legacyId, + title: u.retitleVersionsTo, + }); + } + } + for (const d of plan.models.softDelete) { + out.push({ kind: 'softDeleted', entity: 'model', id: d.modelId, legacyId: d.legacyId }); + } + for (const d of plan.users.softDelete) { + out.push({ kind: 'softDeleted', entity: 'user', id: d.userId, legacyId: d.legacyId }); + } + + for (const a of plan.versions.append) { + out.push({ + kind: 'version', + modelId: a.modelId, + versionNumber: a.versionNumber, + netlogoFileKey: a.data.netlogoFileKey, + }); + out.push({ kind: 'latestIsMax', modelId: a.modelId }); + if (a.vacatedVersionNumber !== null) { + out.push({ + kind: 'preview', + modelId: a.modelId, + versionNumber: a.vacatedVersionNumber, + key: null, + nodeLegacyId: a.nodeLegacyId, + }); + out.push({ + kind: 'noTaggings', + modelId: a.modelId, + versionNumber: a.vacatedVersionNumber, + nodeLegacyId: a.nodeLegacyId, + }); + } + for (const tagId of a.carryTagIds) { + out.push({ + kind: 'tagging', + modelId: a.modelId, + versionNumber: a.versionNumber, + tagId, + nodeLegacyId: a.nodeLegacyId, + }); + } + // Only assert the carried preview when no resync supersedes it, or the two + // expectations would contradict each other. + if ( + !plan.previews.some((p) => p.modelId === a.modelId && p.versionNumber === a.versionNumber) + ) { + out.push({ + kind: 'preview', + modelId: a.modelId, + versionNumber: a.versionNumber, + key: a.carryPreviewImageFileKey, + nodeLegacyId: a.nodeLegacyId, + }); + } + } + for (const u of plan.versions.update) { + out.push({ + kind: 'version', + modelId: u.modelId, + versionNumber: u.versionNumber, + netlogoFileKey: u.data.netlogoFileKey as string, + }); + } + + for (const a of plan.additionalFiles.add) { + out.push({ kind: 'additionalFile', id: a.data.id!, fileKey: a.data.fileKey }); + } + for (const r of plan.additionalFiles.remove) { + out.push({ + kind: 'absentAdditionalFile', + id: r.additionalFileId, + legacyAttachmentId: r.legacyAttachmentId, + }); + } + for (const p of plan.previews) { + out.push({ + kind: 'preview', + modelId: p.modelId, + versionNumber: p.versionNumber, + key: p.previewImageFileKey, + nodeLegacyId: p.nodeLegacyId, + }); + } + for (const t of plan.taggings.add) { + out.push({ + kind: 'tagging', + modelId: t.data.modelId, + versionNumber: t.data.versionNumber, + tagId: t.data.tagId, + nodeLegacyId: t.nodeLegacyId, + }); + } + for (const t of plan.taggings.remove) { + out.push({ + kind: 'absentTagging', + modelId: t.modelId, + tagId: t.tagId, + nodeLegacyId: t.nodeLegacyId, + }); + } + for (const f of plan.files) out.push({ kind: 'object', key: f.key, bytes: f.body.byteLength }); + + return out; +} + +// verify + +async function verify(expectations: readonly Expectation[]) { + console.log('\n→ Verifying'); + const failures: string[] = []; + const storage = SKIP_UPLOAD ? null : createStorage(); + + for (const e of expectations) { + const failure = await checkExpectation(e, storage); + if (failure) failures.push(failure); + } + + const total = expectations.length; + console.log(` ${total - failures.length}/${total} checks passed`); + if (failures.length > 0) { + console.error('\nVERIFICATION FAILED:'); + for (const f of failures) console.error(` ✗ ${f}`); + process.exitCode = 1; + return; + } + console.log(' ✓ patch verified'); +} + +async function checkExpectation( + e: Expectation, + storage: ReturnType | null, +): Promise { + switch (e.kind) { + case 'tag': { + const tag = await prisma.tag.findUnique({ where: { legacyId: e.legacyId } }); + return tag?.name === e.name ? null : `tag legacyId=${e.legacyId} is missing or misnamed`; + } + case 'user': { + const user = await prisma.user.findUnique({ where: { legacyId: e.legacyId } }); + return user ? null : `user legacyId=${e.legacyId} was not created`; + } + case 'fields': { + const record = + e.entity === 'user' + ? await prisma.user.findUnique({ where: { id: e.id } }) + : await prisma.model.findUnique({ where: { id: e.id } }); + if (!record) return `${e.entity} legacyId=${e.legacyId} disappeared`; + const actual = jsonSafe(record as unknown as Record); + const stale = Object.keys(e.fields).filter( + (k) => JSON.stringify(actual[k] ?? null) !== JSON.stringify(e.fields[k] ?? null), + ); + return stale.length === 0 + ? null + : `${e.entity} legacyId=${e.legacyId} did not take field(s) ${stale.join(', ')}`; + } + case 'model': { + const model = await prisma.model.findUnique({ + where: { legacyId: e.legacyId }, + include: { versions: { select: { title: true } } }, + }); + if (!model) return `model legacyId=${e.legacyId} was not created`; + if (model.versions.length !== e.versionCount) { + return `model legacyId=${e.legacyId} has ${model.versions.length} versions, expected ${e.versionCount}`; + } + return model.versions.every((v) => v.title === e.title) + ? null + : `model legacyId=${e.legacyId} has versions titled differently from its node name`; + } + case 'versionTitles': { + const stale = await prisma.modelVersion.count({ + where: { modelId: e.modelId, title: { not: e.title } }, + }); + return stale === 0 + ? null + : `model legacyId=${e.legacyId} still has ${stale} stale version title(s)`; + } + case 'softDeleted': { + const record = + e.entity === 'user' + ? await prisma.user.findUnique({ where: { id: e.id }, select: { deletedAt: true } }) + : await prisma.model.findUnique({ where: { id: e.id }, select: { deletedAt: true } }); + return record?.deletedAt ? null : `${e.entity} legacyId=${e.legacyId} is not soft deleted`; + } + case 'version': { + const version = await prisma.modelVersion.findUnique({ + where: { modelId_versionNumber: { modelId: e.modelId, versionNumber: e.versionNumber } }, + select: { netlogoFileKey: true }, + }); + return version?.netlogoFileKey === e.netlogoFileKey + ? null + : `version ${e.modelId}#${e.versionNumber} is missing or points at the wrong file`; + } + case 'latestIsMax': { + const [model, max] = await Promise.all([ + prisma.model.findUnique({ + where: { id: e.modelId }, + select: { latestVersionNumber: true }, + }), + prisma.modelVersion.aggregate({ + where: { modelId: e.modelId }, + _max: { versionNumber: true }, + }), + ]); + return model?.latestVersionNumber === max._max.versionNumber + ? null + : `model ${e.modelId} latestVersionNumber=${model?.latestVersionNumber} is not the highest version (${max._max.versionNumber})`; + } + case 'preview': { + const version = await prisma.modelVersion.findUnique({ + where: { modelId_versionNumber: { modelId: e.modelId, versionNumber: e.versionNumber } }, + select: { previewImageFileKey: true }, + }); + return (version?.previewImageFileKey ?? null) === e.key + ? null + : `preview for node ${e.nodeLegacyId} is ${version?.previewImageFileKey ?? 'null'}, expected ${e.key ?? 'null'}`; + } + case 'additionalFile': { + const file = await prisma.modelAdditionalFile.findUnique({ where: { id: e.id } }); + return file?.fileKey === e.fileKey ? null : `additional file ${e.id} is missing`; + } + case 'absentAdditionalFile': { + const file = await prisma.modelAdditionalFile.findUnique({ where: { id: e.id } }); + return file === null + ? null + : `additional file from attachment ${e.legacyAttachmentId} is still present`; + } + case 'tagging': { + const tag = await prisma.modelVersionTag.findFirst({ + where: { modelId: e.modelId, versionNumber: e.versionNumber, tagId: e.tagId }, + }); + return tag ? null : `tagging on node ${e.nodeLegacyId} is missing`; + } + case 'absentTagging': { + const tag = await prisma.modelVersionTag.findFirst({ + where: { modelId: e.modelId, tagId: e.tagId }, + }); + return tag === null ? null : `tagging on node ${e.nodeLegacyId} is still present`; + } + case 'noTaggings': { + const count = await prisma.modelVersionTag.count({ + where: { modelId: e.modelId, versionNumber: e.versionNumber }, + }); + return count === 0 + ? null + : `version ${e.versionNumber} of node ${e.nodeLegacyId} still carries ${count} tag(s) after being superseded`; + } + case 'object': { + if (!storage) return null; + try { + const head = await storage.client.send( + new HeadObjectCommand({ Bucket: storage.bucket, Key: e.key }), + ); + return head.ContentLength === e.bytes + ? null + : `object ${e.key} is ${head.ContentLength} bytes, expected ${e.bytes}`; + } catch { + return `object ${e.key} is not in the bucket`; + } + } + } +} + +// shared + +function indexByLegacyId( + records: readonly T[], +): Map { + const map = new Map(); + for (const r of records) { + if (r.legacyId !== null) map.set(r.legacyId, r.id); + } + return map; +} + +function changedFields( + current: Record, + desired: Record, +): Record { + const changed: Record = {}; + for (const [key, value] of Object.entries(desired)) { + if (!sameValue(current[key], value)) changed[key] = value; + } + return changed; +} + +function sameValue(a: unknown, b: unknown): boolean { + if (a instanceof Date || b instanceof Date) { + return a instanceof Date && b instanceof Date && a.getTime() === b.getTime(); + } + if (typeof a === 'object' || typeof b === 'object') { + return JSON.stringify(a ?? null) === JSON.stringify(b ?? null); + } + return a === b; +} + +function jsonSafe(data: Record): Record { + return Object.fromEntries( + Object.entries(data).map(([k, v]) => [k, v instanceof Date ? v.toISOString() : v]), + ); +} + +function required(name: string): string { + const v = process.env[name]; + if (!v) throw new Error(`Missing required env: ${name}`); + return v; +} + +main() + .catch((err) => { + console.error('FATAL:', err); + process.exitCode = 1; + }) + .finally(async () => { + await prisma.$disconnect(); + }); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/backfill-collaborators.ts b/apps/modeling-commons-backend/prisma/legacy-migration/backfill-collaborators.ts new file mode 100644 index 00000000..d421cb3d --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/backfill-collaborators.ts @@ -0,0 +1,207 @@ +/** + * Members fold into ModelAuthor as role=contributor, which grants write access + * because canWrite treats any contributor as a writer. Non-members are archival. + */ + +import 'dotenv/config'; +import { PrismaPg } from '@prisma/adapter-pg'; +import process from 'node:process'; +import { PrismaClient } from '../../generated/prisma/client.js'; +import { + authorKey, + buildTypeNameById, + planCollaborators, + type CollaboratorPlan, + type ExistingAuthor, +} from './lib/collaborators.ts'; +import { LegacyDatabase } from './lib/legacy.ts'; + +const APPLY = process.argv.includes('--apply'); +const LEGACY_SCHEMA = process.env['LEGACY_SCHEMA'] ?? 'public'; +const TXN_TIMEOUT_MS = parseInt(process.env['BACKFILL_TXN_TIMEOUT_MS'] ?? '300000', 10); + +const legacy = new LegacyDatabase( + process.env['LEGACY_DATABASE_URL'] ?? + 'postgresql://admin:test@127.0.0.1:5432/nlcommons_production', + LEGACY_SCHEMA, +); +const prisma = new PrismaClient({ + adapter: new PrismaPg({ connectionString: required('DATABASE_URL'), max: 4 }), +}); + +async function main() { + console.log(`→ Mode: ${APPLY ? 'APPLY' : 'dry run (pass --apply to write)'}`); + + const [types, collaborations, nonMembers] = await Promise.all([ + legacy.allCollaboratorTypes(), + legacy.allCollaborations(), + legacy.allNonMemberCollaborations(), + ]); + console.log( + `→ Legacy: ${collaborations.length} collaborations, ${nonMembers.length} non-member collaborations`, + ); + + const plan = planCollaborators(collaborations, nonMembers, { + userIdByLegacyId: await legacyIdMap('user'), + modelIdByLegacyId: await legacyIdMap('model'), + typeNameById: buildTypeNameById(types), + existingAuthors: await loadExistingAuthors(), + existingNonMemberLegacyIds: await loadExistingNonMemberIds(), + }); + + print(plan); + + const writes = + plan.authorInserts.length + plan.authorTypeUpdates.length + plan.nonMemberInserts.length; + if (writes === 0) { + console.log('\n(nothing to do)'); + return; + } + if (!APPLY) { + console.log('\nDry run: nothing written. Re-run with --apply.'); + return; + } + + await prisma.$transaction( + async (tx) => { + if (plan.authorInserts.length > 0) { + await tx.modelAuthor.createMany({ + data: plan.authorInserts.map((a) => ({ + modelId: a.modelId, + userId: a.userId, + role: a.role, + collaboratorType: a.collaboratorType, + ...(a.createdAt ? { createdAt: a.createdAt } : {}), + })), + skipDuplicates: true, + }); + } + for (const u of plan.authorTypeUpdates) { + await tx.modelAuthor.update({ + where: { modelId_userId: { modelId: u.modelId, userId: u.userId } }, + data: { collaboratorType: u.collaboratorType }, + }); + } + if (plan.nonMemberInserts.length > 0) { + await tx.nonMemberContributor.createMany({ + data: plan.nonMemberInserts.map((n) => ({ + legacyId: n.legacyId, + modelId: n.modelId, + email: n.email, + name: n.name, + collaboratorType: n.collaboratorType, + addedByUserId: n.addedByUserId, + ...(n.createdAt ? { createdAt: n.createdAt } : {}), + })), + skipDuplicates: true, + }); + } + }, + { timeout: TXN_TIMEOUT_MS }, + ); + + console.log(`\n✓ Applied ${writes} write(s)`); + await verify(plan); +} + +function print(plan: CollaboratorPlan) { + console.log('\n=== PLAN ==='); + console.log(` ModelAuthor inserts (role=contributor, gains write access): ${plan.authorInserts.length}`); + console.log(` ModelAuthor collaboratorType backfills: ${plan.authorTypeUpdates.length}`); + console.log(` NonMemberContributor inserts: ${plan.nonMemberInserts.length}`); + console.log(' Skipped:'); + console.log(` node not in target (spam/versionless/deleted): ${plan.skipped.orphanModel}`); + console.log(` person not in target (email dedupe): ${plan.skipped.orphanUser}`); + console.log(` author row already typed: ${plan.skipped.alreadyTyped}`); + console.log(` non-member already backfilled: ${plan.skipped.alreadyPresent}`); + console.log(` duplicate (model, person) pair: ${plan.skipped.duplicatePair}`); + + const byType = new Map(); + for (const a of [...plan.authorInserts, ...plan.authorTypeUpdates]) { + const t = a.collaboratorType ?? '(none)'; + byType.set(t, (byType.get(t) ?? 0) + 1); + } + if (byType.size > 0) { + console.log(' Member collaborator types:'); + for (const [name, count] of [...byType].sort((a, b) => b[1] - a[1])) { + console.log(` ${name}: ${count}`); + } + } +} + +async function verify(plan: CollaboratorPlan) { + const nonMemberCount = await prisma.nonMemberContributor.count({ + where: { legacyId: { in: plan.nonMemberInserts.map((n) => n.legacyId) } }, + }); + const missingNonMembers = plan.nonMemberInserts.length - nonMemberCount; + + let missingAuthors = 0; + for (const a of [...plan.authorInserts, ...plan.authorTypeUpdates]) { + const row = await prisma.modelAuthor.findUnique({ + where: { modelId_userId: { modelId: a.modelId, userId: a.userId } }, + select: { collaboratorType: true }, + }); + if (!row) missingAuthors++; + } + + if (missingAuthors > 0 || missingNonMembers > 0) { + throw new Error( + `Verification failed: ${missingAuthors} author row(s) and ${missingNonMembers} non-member row(s) missing`, + ); + } + console.log('✓ Verified every planned row is present'); +} + +async function legacyIdMap(model: 'user' | 'model'): Promise> { + const rows = + model === 'user' + ? await prisma.user.findMany({ + where: { legacyId: { not: null } }, + select: { id: true, legacyId: true }, + }) + : await prisma.model.findMany({ + where: { legacyId: { not: null } }, + select: { id: true, legacyId: true }, + }); + + const map = new Map(); + for (const r of rows) { + if (r.legacyId !== null) map.set(r.legacyId, r.id); + } + return map; +} + +async function loadExistingAuthors(): Promise> { + const rows = await prisma.modelAuthor.findMany({ + select: { modelId: true, userId: true, role: true, collaboratorType: true }, + }); + const map = new Map(); + for (const r of rows) { + map.set(authorKey(r.modelId, r.userId), { + role: r.role, + collaboratorType: r.collaboratorType, + }); + } + return map; +} + +async function loadExistingNonMemberIds(): Promise> { + const rows = await prisma.nonMemberContributor.findMany({ select: { legacyId: true } }); + return new Set(rows.map((r) => r.legacyId)); +} + +function required(name: string): string { + const v = process.env[name]; + if (!v) throw new Error(`Missing required env: ${name}`); + return v; +} + +main() + .catch((err) => { + console.error('FATAL:', err); + process.exitCode = 1; + }) + .finally(async () => { + await legacy.end(); + await prisma.$disconnect(); + }); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/diffdb.sh b/apps/modeling-commons-backend/prisma/legacy-migration/diffdb.sh new file mode 100755 index 00000000..339dad97 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/diffdb.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# Diffs the migrated snapshot (`public`) against a fresh dump (`incoming`), one CSV +# per changed table as `side,id,detail`. versions/attachments `contents` are md5'd +# to keep it small, so apply-diff.ts re-reads the real bytes. SKIP drops tables no +# patch can act on; small unpatchable ones stay in and get listed as ignored. +# +# Connection comes from the standard PG* env vars. +# Usage: LEGACY_DB=nlcommons_current DIFF_DIR=~/dbdiff ./prisma/legacy-migration/diffdb.sh +set -euo pipefail + +DB="${LEGACY_DB:-nlcommons_current}" +OUT="${DIFF_DIR:-$HOME/dbdiff}" +SKIP="logged_actions model_views model_view_counts model_downloads sessions ip_locations" +mkdir -p "$OUT" + +hash_cols_for() { + case "$1" in + versions|attachments) echo "'contents'" ;; + *) echo "''" ;; + esac +} +in_list() { for x in $2; do [ "$x" = "$1" ] && return 0; done; return 1; } + +tables=$(psql -d "$DB" -Atc " + SELECT c.relname FROM pg_class c JOIN pg_namespace n ON n.oid=c.relnamespace + WHERE n.nspname='public' AND c.relkind='r' + AND EXISTS (SELECT 1 FROM pg_class c2 JOIN pg_namespace n2 ON n2.oid=c2.relnamespace + WHERE n2.nspname='incoming' AND c2.relname=c.relname) + ORDER BY 1") + +for t in $tables; do + in_list "$t" "$SKIP" && { echo "SKIP $t"; continue; } + f="$OUT/$t.csv"; e="$OUT/$t.err" + hc=$(hash_cols_for "$t") + + proj=$(psql -d "$DB" -Atc " + SELECT string_agg( + CASE WHEN column_name = ANY(ARRAY[$hc]) + THEN format('md5(%I::text) AS %I', column_name, column_name) + ELSE format('%I', column_name) END, + ', ' ORDER BY ordinal_position) + FROM information_schema.columns + WHERE table_schema='public' AND table_name='$t'") + + has_id=$(psql -d "$DB" -Atc " + SELECT count(*) FROM information_schema.columns + WHERE table_schema='public' AND table_name='$t' AND column_name='id'") + + if [ "$has_id" = "1" ]; then + q=" + WITH a AS (SELECT $proj FROM public.\"$t\"), + b AS (SELECT $proj FROM incoming.\"$t\"), + oc AS (SELECT * FROM a EXCEPT ALL SELECT * FROM b), + oi AS (SELECT * FROM b EXCEPT ALL SELECT * FROM a), + m AS ( + SELECT oc.id, + string_agg(ka.key || ': [' || coalesce(ka.value,'NULL') || + '] -> [' || coalesce(kb.value,'NULL') || ']', + ' | ' ORDER BY ka.key) AS detail + FROM oc JOIN oi ON oi.id = oc.id, + LATERAL json_each_text(row_to_json(oc)) ka, + LATERAL json_each_text(row_to_json(oi)) kb + WHERE kb.key = ka.key AND ka.value IS DISTINCT FROM kb.value + GROUP BY oc.id) + SELECT 'deleted' AS side, oc.id, row_to_json(oc)::text AS detail + FROM oc WHERE NOT EXISTS (SELECT 1 FROM m WHERE m.id = oc.id) + UNION ALL + SELECT 'new', oi.id, row_to_json(oi)::text + FROM oi WHERE NOT EXISTS (SELECT 1 FROM m WHERE m.id = oi.id) + UNION ALL + SELECT 'modified', m.id, m.detail FROM m + ORDER BY 2" + else + q=" + WITH a AS (SELECT $proj FROM public.\"$t\"), + b AS (SELECT $proj FROM incoming.\"$t\") + SELECT 'deleted' AS side, row_to_json(x)::text AS detail + FROM (SELECT * FROM a EXCEPT ALL SELECT * FROM b) x + UNION ALL + SELECT 'new', row_to_json(y)::text + FROM (SELECT * FROM b EXCEPT ALL SELECT * FROM a) y" + fi + + psql -d "$DB" --csv -o "$f" -c "$q" 2>"$e" || { echo "FAIL $t -> $e"; continue; } + + if [ "$(wc -l < "$f")" -le 1 ]; then rm -f "$f" "$e" + else rm -f "$e"; echo "DIFF $t ($(( $(wc -l < "$f") - 1 )) rows)"; fi +done diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/initial-import.ts b/apps/modeling-commons-backend/prisma/legacy-migration/initial-import.ts new file mode 100644 index 00000000..f0467818 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/initial-import.ts @@ -0,0 +1,447 @@ +/** + * NetLogo Commons → new schema migration. + * + * Source: nlcommons_production (Rails app, integer ids, tables: people, nodes, + * versions, tags, tagged_nodes, attachments, spam_warnings, + * permission_settings). + * Target: new Prisma schema (UUIDs, Model/ModelVersion split, Better Auth users, + * file storage by key). + * + * Idempotent via legacyId columns on User/Model/Tag — with one exception: + * migrateInteractions has no dedupe key (ModelInteraction carries no legacyId + * and no unique constraint), so re-running it duplicates every row. It is the + * last phase; re-running the script after it has produced rows needs a manual + * DELETE first. + * + * Re-running skips already-migrated rows but does NOT pick up changes to them, + * nor new versions/attachments/tags on an already-migrated node. Use + * apply-diff.ts for that. + * + * File extraction goes to local disk; an external uploader pushes to S3 later. + * + * Usage: + * DATABASE_URL= yarn run db:migrate:dev + * DATABASE_URL= yarn run db:legacy:import + * DATABASE_URL= yarn run db:legacy:patch + */ + +import { PrismaPg } from '@prisma/adapter-pg'; +import { randomUUID } from 'node:crypto'; +import { copyFile as fsCopyFile, mkdir, rm, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import process from 'node:process'; +import { Prisma, PrismaClient } from '../../generated/prisma/client.js'; +import { buildAvatarFileKey } from './lib/file-keys.ts'; +import { + LegacyDatabase, + NODE_COLUMNS, + PERSON_COLUMNS, + type LegacyNode, + type LegacyPerson, + type LegacyTag, +} from './lib/legacy.ts'; +import { createModelFromNode } from './lib/node-migration.ts'; +import { + buildFullName, + hashIp, + normalizeEmail, + normalizeTagName, + pickLowestIdWinners, + toUtcDateOnly, +} from './lib/normalize.ts'; + +const OLD_URL = + process.env['LEGACY_DATABASE_URL'] ?? + 'postgresql://admin:test@127.0.0.1:5432/nlcommons_production'; +const OLD_SCHEMA = process.env['LEGACY_SCHEMA'] ?? 'public'; +const NEW_URL = required('DATABASE_URL'); +const AVATARS_DIR = path.join('.', 'prisma', 'legacy-migration', 'avatars'); +const OUTPUT_DIR = process.env['OUTPUT_DIR'] ?? './prisma/legacy-migration/output/archive'; +const FILES_DIR = path.join(OUTPUT_DIR, 'files'); +const BATCH = parseInt(process.env['BATCH_SIZE'] ?? '500', 10); +const WIPE_TARGET = process.env['WIPE_TARGET'] === 'true'; +const IP_HASH_SALT = required('IP_HASH_SALT'); + +type OldEvent = { + logged_at: Date | null; + ip_address: string | null; + node_id: number | null; + person_id: number | null; +}; + +const legacy = new LegacyDatabase(OLD_URL, OLD_SCHEMA); + +const adapter = new PrismaPg({ connectionString: NEW_URL, max: 4 }); +const prisma = new PrismaClient({ adapter }); + +const report = { + users: { migrated: 0, skipped_existing: 0, deduped_email: 0, null_email: 0 }, + tags: { migrated: 0, skipped_existing: 0 }, + models: { migrated: 0, skipped_spam: 0, skipped_existing: 0, skipped_no_versions: 0 }, + versions: { migrated: 0 }, + authors: { owners: 0, contributors: 0 }, + attachments: { migrated: 0, skipped_orphan: 0, previews_attached: 0 }, + taggings: { migrated: 0, skipped_orphan: 0 }, + interactions: { views: 0, runs: 0, downloads: 0 }, + errors: [] as string[], +}; + +async function main() { + console.log('→ Output dir:', path.resolve(OUTPUT_DIR)); + await mkdir(FILES_DIR, { recursive: true }); + + if (WIPE_TARGET) { + console.log('→ WIPE_TARGET=true: truncating target tables'); + await wipeTarget(); + } + + console.log('→ Loading spam-warned node ids (>=2 warnings)'); + const spamNodeIds = await legacy.spamNodeIds(); + console.log(` ${spamNodeIds.size} nodes excluded as spam`); + + console.log('→ Migrating people → User'); + const userIdMap = await migrateUsers(); + + console.log('→ Migrating tags → Tag'); + const tagIdMap = await migrateTags(); + + console.log('→ Migrating nodes → Model (+ versions, authors, attachments, taggings)'); + const { modelIdMap } = await migrateNodes(spamNodeIds, userIdMap, tagIdMap); + + console.log('→ Migrating model_views/runs/downloads → ModelInteraction'); + await migrateInteractions(modelIdMap, userIdMap); + + console.log('→ Writing manifest + report'); + await writeFile(path.join(OUTPUT_DIR, 'report.json'), JSON.stringify(report, null, 2)); + + console.log('\n=== DONE ==='); + console.log(JSON.stringify(report, null, 2)); + + await legacy.end(); + await prisma.$disconnect(); +} + +async function wipeTarget() { + await prisma.$executeRawUnsafe(` + TRUNCATE TABLE + "ModelVersionTag", + "ModelAdditionalFile", + "ModelVersion", + "ModelAuthor", + "ModelPermission", + "ModelLike", + "ModelInteraction", + "ModelDraft", + "Event", + "Model", + "Tag", + "Verification", + "Session", + "Account", + "Passkey", + "User" + RESTART IDENTITY CASCADE; + `); + + await rm(FILES_DIR, { recursive: true }); +} + +async function migrateUsers(): Promise> { + const map = new Map(); + + const emailWinner = pickLowestIdWinners(await legacy.allPeopleEmails(), (r) => + normalizeEmail(r.email_address), + ); + + const existing = await prisma.user.findMany({ + where: { legacyId: { not: null } }, + select: { id: true, legacyId: true }, + }); + for (const u of existing) { + if (u.legacyId !== null) map.set(u.legacyId, u.id); + } + + await legacy.streamRows( + `SELECT ${PERSON_COLUMNS} FROM ${legacy.table('people')} ORDER BY id ASC`, + BATCH, + async (batch) => { + const toCreate: Prisma.UserCreateManyInput[] = []; + for (const p of batch) { + if (map.has(p.id)) { + report.users.skipped_existing++; + continue; + } + + const id = randomUUID(); + const rawEmail = normalizeEmail(p.email_address); + let email: string | null = null; + if (rawEmail) { + if (emailWinner.get(rawEmail)?.id === p.id) { + email = rawEmail; + } else { + report.users.deduped_email++; + } + } else { + report.users.null_email++; + } + + let imageUrl: string | null = null; + if (p.avatar_file_name) { + const avatarKey = buildAvatarFileKey( + id, + p.avatar_updated_at ?? new Date(), + randomUUID(), + 'avatar', + ); + imageUrl = `cdn.modelingcommons.org/modeling-commons/${avatarKey}`; + + const fsAvatarPath = path.join(AVATARS_DIR, `${p.id}`, 'original', p.avatar_file_name); + try { + await copyFile(fsAvatarPath, path.join(FILES_DIR, avatarKey)); + } catch (err) { + report.errors.push( + `Failed to copy avatar for person id ${p.id} from ${fsAvatarPath}: ${(err as Error).message}`, + ); + imageUrl = null; + } + } + + toCreate.push({ + id, + legacyId: p.id, + email, + name: buildFullName(p.first_name, p.last_name), + emailVerified: false, + bio: p.biography?.trim() || null, + dob: toUtcDateOnly(p.birthdate), + image: imageUrl, + socialLinks: [{ type: 'other', rawValue: p.url?.trim() || null }], + systemRole: 'user', // all users → user, per spec + userKind: 'other', + createdAt: p.created_at ?? new Date(), + updatedAt: p.updated_at ?? p.created_at ?? new Date(), + }); + map.set(p.id, id); + report.users.migrated++; + } + if (toCreate.length > 0) { + await prisma.user.createMany({ data: toCreate, skipDuplicates: true }); + } + }, + ); + + return map; +} + +async function migrateTags(): Promise> { + const map = new Map(); + + const existing = await prisma.tag.findMany({ + where: { legacyId: { not: null } }, + select: { id: true, legacyId: true }, + }); + for (const t of existing) { + if (t.legacyId !== null) map.set(t.legacyId, t.id); + } + + // Old tag names are nullable + non-unique; new is unique. Dedupe by lowercased name. + const rows = await legacy.allTags(); + const nameWinner = pickLowestIdWinners(rows, (t) => normalizeTagName(t.name)); + + const toCreate: Prisma.TagCreateManyInput[] = []; + for (const t of rows) { + if (map.has(t.id)) { + report.tags.skipped_existing++; + continue; + } + const n = normalizeTagName(t.name); + if (!n) continue; + if (nameWinner.get(n)?.id !== t.id) continue; + + const id = randomUUID(); + toCreate.push({ + id, + legacyId: t.id, + name: n, + displayName: (t.name ?? '').trim() || null, + createdAt: t.created_at ?? new Date(), + }); + map.set(t.id, id); + report.tags.migrated++; + } + if (toCreate.length > 0) { + await prisma.tag.createMany({ data: toCreate, skipDuplicates: true }); + } + + aliasDuplicateTagNames(rows, nameWinner, map); + + return map; +} + +function aliasDuplicateTagNames( + rows: readonly LegacyTag[], + nameWinner: ReadonlyMap, + map: Map, +) { + for (const t of rows) { + if (map.has(t.id)) continue; + const n = normalizeTagName(t.name); + if (!n) continue; + const winnerUuid = map.get(nameWinner.get(n)?.id ?? -1); + if (winnerUuid) map.set(t.id, winnerUuid); + } +} + +async function migrateNodes( + spamNodeIds: Set, + userIdMap: Map, + tagIdMap: Map, +) { + const existingModels = await prisma.model.findMany({ + where: { legacyId: { not: null } }, + select: { id: true, legacyId: true }, + }); + const modelIdMap = new Map(); + for (const m of existingModels) { + if (m.legacyId !== null) modelIdMap.set(m.legacyId, m.id); + } + + // Node-by-node: each node spawns versions, authors, attachments and taggings + // that all reference one another, so the whole tree shares one transaction. + await legacy.streamRows( + `SELECT ${NODE_COLUMNS} FROM ${legacy.table('nodes')} ORDER BY id ASC`, + BATCH, + async (batch) => { + for (const node of batch) { + if (spamNodeIds.has(node.id)) { + report.models.skipped_spam++; + continue; + } + if (modelIdMap.has(node.id)) { + report.models.skipped_existing++; + continue; + } + + const versions = await legacy.versionsForNode(node.id); + if (versions.length === 0) { + report.models.skipped_no_versions++; + continue; + } + + const [attachments, taggings] = await Promise.all([ + legacy.attachmentsForNode(node.id), + legacy.taggingsForNode(node.id), + ]); + + const modelUuid = randomUUID(); + modelIdMap.set(node.id, modelUuid); + + await prisma.$transaction( + async (tx) => { + const counts = await createModelFromNode( + tx, + modelUuid, + { node, versions, attachments, taggings }, + { + writeFile: writeLocalFile, + newUuid: randomUUID, + now: () => new Date(), + userIdByLegacyId: userIdMap, + tagIdByLegacyId: tagIdMap, + }, + ); + + report.versions.migrated += counts.versions; + report.authors.owners += counts.owners; + report.authors.contributors += counts.contributors; + report.attachments.migrated += counts.attachments; + report.attachments.previews_attached += counts.previewsAttached; + report.taggings.migrated += counts.taggings; + report.taggings.skipped_orphan += counts.skippedOrphanTaggings; + }, + { timeout: 60_000 }, + ); + + report.models.migrated++; + if (report.models.migrated % 50 === 0) { + console.log(` ...migrated ${report.models.migrated} models`); + } + } + }, + ); + + return { modelIdMap }; +} + +/** + * NOT idempotent: ModelInteraction has no legacyId and no unique constraint, so + * skipDuplicates cannot help and a second run duplicates every row. + */ +async function migrateInteractions( + modelIdMap: Map, + userIdMap: Map, +) { + const sources: Array<{ + table: string; + kind: 'view' | 'run' | 'download'; + counter: keyof typeof report.interactions; + }> = [ + { table: 'model_views', kind: 'view', counter: 'views' }, + { table: 'model_runs', kind: 'run', counter: 'runs' }, + { table: 'model_downloads', kind: 'download', counter: 'downloads' }, + ]; + + for (const { table, kind, counter } of sources) { + let count = 0; + await legacy.streamRows( + `SELECT logged_at, ip_address, node_id, person_id FROM ${legacy.table(table)}`, + BATCH, + async (batch) => { + const rows: Prisma.ModelInteractionCreateManyInput[] = []; + for (const e of batch) { + if (!e.node_id) continue; + const modelUuid = modelIdMap.get(e.node_id); + if (!modelUuid) continue; // node was spam-skipped or dropped + rows.push({ + id: randomUUID(), + modelId: modelUuid, + kind, + userId: e.person_id ? (userIdMap.get(e.person_id) ?? null) : null, + ipHash: hashIp(e.ip_address, IP_HASH_SALT), + createdAt: e.logged_at ?? new Date(), + }); + } + if (rows.length > 0) { + await prisma.modelInteraction.createMany({ data: rows, skipDuplicates: true }); + count += rows.length; + } + }, + ); + report.interactions[counter] = count; + console.log(` ${table}: ${count} rows`); + } +} + +async function copyFile(src: string, dest: string) { + await mkdir(path.dirname(dest), { recursive: true }); + await fsCopyFile(src, dest); +} + +async function writeLocalFile(relKey: string, contents: Buffer) { + const full = path.join(FILES_DIR, relKey); + await mkdir(path.dirname(full), { recursive: true }); + await writeFile(full, contents); +} + +function required(name: string): string { + const v = process.env[name]; + if (!v) throw new Error(`Missing required env: ${name}`); + return v; +} + +main().catch((err) => { + console.error('FATAL:', err); + process.exit(1); +}); + +export default main; diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/collaborators.spec.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/collaborators.spec.ts new file mode 100644 index 00000000..d47dd5d4 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/collaborators.spec.ts @@ -0,0 +1,187 @@ +import { describe, expect, test } from 'vitest'; +import { + authorKey, + buildTypeNameById, + planCollaborators, + type CollaboratorContext, + type ExistingAuthor, +} from './collaborators.ts'; +import type { LegacyCollaboration, LegacyNonMemberCollaboration } from './legacy.ts'; + +const MODEL = 'model-uuid-1'; +const USER = 'user-uuid-1'; +const CREATED = new Date('2013-05-01T00:00:00Z'); + +const TYPES = buildTypeNameById([ + { id: 1, name: 'Author' }, + { id: 2, name: 'Domain expert' }, + { id: 5, name: ' Editor ' }, + { id: 9, name: ' ' }, +]); + +function ctx(overrides: Partial = {}): CollaboratorContext { + return { + userIdByLegacyId: new Map([[10, USER]]), + modelIdByLegacyId: new Map([[20, MODEL]]), + typeNameById: TYPES, + existingAuthors: new Map(), + existingNonMemberLegacyIds: new Set(), + ...overrides, + }; +} + +function collab(overrides: Partial = {}): LegacyCollaboration { + return { + id: 1, + person_id: 10, + node_id: 20, + collaborator_type_id: 2, + created_at: CREATED, + ...overrides, + }; +} + +function nonMember( + overrides: Partial = {}, +): LegacyNonMemberCollaboration { + return { + id: 100, + non_member_collaborator_id: 7, + node_id: 20, + collaborator_type_id: 1, + person_id: 10, + email: 'ada@example.com', + name: 'Ada', + created_at: CREATED, + ...overrides, + }; +} + +describe('buildTypeNameById', () => { + test('trims names and drops blank ones', () => { + expect(TYPES.get(5)).toBe('Editor'); + expect(TYPES.has(9)).toBe(false); + }); +}); + +describe('planCollaborators - members', () => { + test('a collaborator with no ModelAuthor row becomes a typed contributor', () => { + const plan = planCollaborators([collab()], [], ctx()); + + expect(plan.authorInserts).toEqual([ + { + legacyCollaborationId: 1, + modelId: MODEL, + userId: USER, + role: 'contributor', + collaboratorType: 'Domain expert', + createdAt: CREATED, + }, + ]); + expect(plan.authorTypeUpdates).toEqual([]); + }); + + test('an existing author keeps its role and only gains the type', () => { + const existingAuthors = new Map([ + [authorKey(MODEL, USER), { role: 'owner', collaboratorType: null }], + ]); + const plan = planCollaborators([collab()], [], ctx({ existingAuthors })); + + expect(plan.authorInserts).toEqual([]); + expect(plan.authorTypeUpdates).toEqual([ + { legacyCollaborationId: 1, modelId: MODEL, userId: USER, collaboratorType: 'Domain expert' }, + ]); + }); + + test('an author that already carries a type is left alone, so re-runs are no-ops', () => { + const existingAuthors = new Map([ + [authorKey(MODEL, USER), { role: 'contributor', collaboratorType: 'Author' }], + ]); + const plan = planCollaborators([collab()], [], ctx({ existingAuthors })); + + expect(plan.authorInserts).toEqual([]); + expect(plan.authorTypeUpdates).toEqual([]); + expect(plan.skipped.alreadyTyped).toBe(1); + }); + + test('an untyped collaboration does not overwrite an untyped existing author', () => { + const existingAuthors = new Map([ + [authorKey(MODEL, USER), { role: 'owner', collaboratorType: null }], + ]); + const plan = planCollaborators( + [collab({ collaborator_type_id: null })], + [], + ctx({ existingAuthors }), + ); + + expect(plan.authorTypeUpdates).toEqual([]); + expect(plan.skipped.alreadyTyped).toBe(1); + }); + + test('an unknown type id lands as a null type rather than failing', () => { + const plan = planCollaborators([collab({ collaborator_type_id: 404 })], [], ctx()); + expect(plan.authorInserts[0]?.collaboratorType).toBeNull(); + }); + + test('a second row for the same pair is dropped, since ModelAuthor is keyed on it', () => { + const plan = planCollaborators([collab({ id: 1 }), collab({ id: 2 })], [], ctx()); + + expect(plan.authorInserts).toHaveLength(1); + expect(plan.authorInserts[0]?.legacyCollaborationId).toBe(1); + expect(plan.skipped.duplicatePair).toBe(1); + }); + + test('rows pointing at a missing model or user are counted, not written', () => { + const plan = planCollaborators( + [collab({ id: 1, node_id: 999 }), collab({ id: 2, person_id: 999 }), collab({ id: 3, node_id: null })], + [], + ctx(), + ); + + expect(plan.authorInserts).toEqual([]); + expect(plan.skipped.orphanModel).toBe(2); + expect(plan.skipped.orphanUser).toBe(1); + }); +}); + +describe('planCollaborators - non-members', () => { + test('carries identity, type and the member who added them', () => { + const plan = planCollaborators([], [nonMember()], ctx()); + + expect(plan.nonMemberInserts).toEqual([ + { + legacyId: 100, + modelId: MODEL, + email: 'ada@example.com', + name: 'Ada', + collaboratorType: 'Author', + addedByUserId: USER, + createdAt: CREATED, + }, + ]); + }); + + test('a legacyId already in the target is skipped, so re-runs are no-ops', () => { + const plan = planCollaborators([], [nonMember()], ctx({ existingNonMemberLegacyIds: new Set([100]) })); + + expect(plan.nonMemberInserts).toEqual([]); + expect(plan.skipped.alreadyPresent).toBe(1); + }); + + test('a dangling collaborator join keeps the row with null identity', () => { + const plan = planCollaborators( + [], + [nonMember({ non_member_collaborator_id: null, email: null, name: ' ' })], + ctx(), + ); + + expect(plan.nonMemberInserts[0]).toMatchObject({ email: null, name: null }); + }); + + test('an unmigrated adder is recorded as null rather than dropping the row', () => { + const plan = planCollaborators([], [nonMember({ person_id: 999 })], ctx()); + + expect(plan.nonMemberInserts).toHaveLength(1); + expect(plan.nonMemberInserts[0]?.addedByUserId).toBeNull(); + }); +}); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/collaborators.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/collaborators.ts new file mode 100644 index 00000000..36f6c36b --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/collaborators.ts @@ -0,0 +1,168 @@ +import type { + LegacyCollaboration, + LegacyCollaboratorType, + LegacyNonMemberCollaboration, +} from './legacy.ts'; + +export type ExistingAuthor = { role: 'owner' | 'contributor'; collaboratorType: string | null }; + +export type CollaboratorContext = { + userIdByLegacyId: ReadonlyMap; + modelIdByLegacyId: ReadonlyMap; + typeNameById: ReadonlyMap; + /** Keyed `${modelUuid}\0${userUuid}` — the ModelAuthor rows already in the target. */ + existingAuthors: ReadonlyMap; + existingNonMemberLegacyIds: ReadonlySet; +}; + +export type AuthorInsert = { + legacyCollaborationId: number; + modelId: string; + userId: string; + role: 'contributor'; + collaboratorType: string | null; + createdAt: Date | null; +}; + +export type AuthorTypeUpdate = { + legacyCollaborationId: number; + modelId: string; + userId: string; + collaboratorType: string; +}; + +export type NonMemberInsert = { + legacyId: number; + modelId: string; + email: string | null; + name: string | null; + collaboratorType: string | null; + addedByUserId: string | null; + createdAt: Date | null; +}; + +export type CollaboratorPlan = { + authorInserts: AuthorInsert[]; + authorTypeUpdates: AuthorTypeUpdate[]; + nonMemberInserts: NonMemberInsert[]; + skipped: { + orphanUser: number; + orphanModel: number; + alreadyTyped: number; + alreadyPresent: number; + duplicatePair: number; + }; +}; + +export function authorKey(modelId: string, userId: string): string { + return `${modelId}\0${userId}`; +} + +export function buildTypeNameById(types: readonly LegacyCollaboratorType[]): Map { + const map = new Map(); + for (const t of types) { + const name = t.name?.trim(); + if (name) map.set(t.id, name); + } + return map; +} + +/** + * Rows whose node or person is missing from the target drop out as orphans rather + * than failing the run, and an unknown type id lands as a null collaboratorType. + */ +export function planCollaborators( + collaborations: readonly LegacyCollaboration[], + nonMembers: readonly LegacyNonMemberCollaboration[], + ctx: CollaboratorContext, +): CollaboratorPlan { + const plan: CollaboratorPlan = { + authorInserts: [], + authorTypeUpdates: [], + nonMemberInserts: [], + skipped: { + orphanUser: 0, + orphanModel: 0, + alreadyTyped: 0, + alreadyPresent: 0, + duplicatePair: 0, + }, + }; + + const claimed = new Set(); + + for (const c of collaborations) { + const modelId = c.node_id === null ? undefined : ctx.modelIdByLegacyId.get(c.node_id); + if (!modelId) { + plan.skipped.orphanModel++; + continue; + } + const userId = c.person_id === null ? undefined : ctx.userIdByLegacyId.get(c.person_id); + if (!userId) { + plan.skipped.orphanUser++; + continue; + } + + const key = authorKey(modelId, userId); + if (claimed.has(key)) { + plan.skipped.duplicatePair++; + continue; + } + + const type = + c.collaborator_type_id === null ? null : (ctx.typeNameById.get(c.collaborator_type_id) ?? null); + const existing = ctx.existingAuthors.get(key); + + if (existing) { + if (existing.collaboratorType !== null || type === null) { + plan.skipped.alreadyTyped++; + continue; + } + claimed.add(key); + plan.authorTypeUpdates.push({ + legacyCollaborationId: c.id, + modelId, + userId, + collaboratorType: type, + }); + continue; + } + + claimed.add(key); + plan.authorInserts.push({ + legacyCollaborationId: c.id, + modelId, + userId, + role: 'contributor', + collaboratorType: type, + createdAt: c.created_at, + }); + } + + for (const n of nonMembers) { + if (ctx.existingNonMemberLegacyIds.has(n.id)) { + plan.skipped.alreadyPresent++; + continue; + } + const modelId = n.node_id === null ? undefined : ctx.modelIdByLegacyId.get(n.node_id); + if (!modelId) { + plan.skipped.orphanModel++; + continue; + } + + plan.nonMemberInserts.push({ + legacyId: n.id, + modelId, + email: n.email?.trim() || null, + name: n.name?.trim() || null, + collaboratorType: + n.collaborator_type_id === null + ? null + : (ctx.typeNameById.get(n.collaborator_type_id) ?? null), + addedByUserId: ctx.userIdByLegacyId.get(n.person_id) ?? null, + createdAt: n.created_at, + }); + } + + return plan; +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/csv.spec.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/csv.spec.ts new file mode 100644 index 00000000..5e52202c --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/csv.spec.ts @@ -0,0 +1,59 @@ +import { describe, expect, test } from 'vitest'; +import { parseCsv } from './csv.ts'; + +describe('parseCsv', () => { + test('parses a plain record', () => { + expect(parseCsv('side,id,detail\nnew,7921,hello\n')).toEqual([ + ['side', 'id', 'detail'], + ['new', '7921', 'hello'], + ]); + }); + + test('parses a final record with no trailing newline', () => { + expect(parseCsv('new,1,a')).toEqual([['new', '1', 'a']]); + }); + + test('keeps commas inside quoted fields', () => { + expect(parseCsv('new,1,"a,b,c"')).toEqual([['new', '1', 'a,b,c']]); + }); + + test('unescapes doubled quotes', () => { + expect(parseCsv('new,1,"{""id"":1}"')).toEqual([['new', '1', '{"id":1}']]); + }); + + test('keeps newlines inside quoted fields as one record', () => { + const input = 'side,id,detail\nmodified,5674,"line one\n\nline two"\nnew,8545,x\n'; + expect(parseCsv(input)).toEqual([ + ['side', 'id', 'detail'], + ['modified', '5674', 'line one\n\nline two'], + ['new', '8545', 'x'], + ]); + }); + + test('does not split on a newline-looking prefix inside quotes', () => { + expect(parseCsv('modified,1,"a\nnew,2,b"')).toEqual([['modified', '1', 'a\nnew,2,b']]); + }); + + test('preserves empty fields', () => { + expect(parseCsv('a,,c\n')).toEqual([['a', '', 'c']]); + }); + + test('preserves a trailing empty field', () => { + expect(parseCsv('a,b,\n')).toEqual([['a', 'b', '']]); + }); + + test('strips carriage returns', () => { + expect(parseCsv('a,b\r\nc,d\r\n')).toEqual([ + ['a', 'b'], + ['c', 'd'], + ]); + }); + + test('returns no rows for empty input', () => { + expect(parseCsv('')).toEqual([]); + }); + + test('ignores a trailing blank line', () => { + expect(parseCsv('a,b\n\n')).toEqual([['a', 'b']]); + }); +}); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/csv.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/csv.ts new file mode 100644 index 00000000..6b1ed761 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/csv.ts @@ -0,0 +1,50 @@ +export function parseCsv(input: string): string[][] { + const rows: string[][] = []; + let row: string[] = []; + let field = ''; + let quoted = false; + let started = false; + + for (let i = 0; i < input.length; i++) { + const c = input[i]; + + if (quoted) { + if (c !== '"') { + field += c; + } else if (input[i + 1] === '"') { + field += '"'; + i++; + } else { + quoted = false; + } + continue; + } + + if (c === '"') { + quoted = true; + started = true; + } else if (c === ',') { + row.push(field); + field = ''; + started = true; + } else if (c === '\n') { + if (started) { + row.push(field); + rows.push(row); + row = []; + field = ''; + started = false; + } + } else if (c !== '\r') { + field += c; + started = true; + } + } + + if (started) { + row.push(field); + rows.push(row); + } + + return rows; +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/diff.spec.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/diff.spec.ts new file mode 100644 index 00000000..b86014a7 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/diff.spec.ts @@ -0,0 +1,119 @@ +import { describe, expect, test } from 'vitest'; +import { + idsBySide, + isPatchableTable, + optionalDate, + optionalString, + parseTableDiff, + requireNumber, +} from './diff.ts'; + +const HEADER = 'side,id,detail\n'; + +describe('isPatchableTable', () => { + test('accepts the six tables initial-import.ts migrates', () => { + for (const t of ['people', 'nodes', 'versions', 'tags', 'tagged_nodes', 'attachments']) { + expect(isPatchableTable(t)).toBe(true); + } + }); + + test('rejects tables the archive never mapped', () => { + for (const t of ['collaborations', 'groups', 'memberships', 'recommendations', 'model_views']) { + expect(isPatchableTable(t)).toBe(false); + } + }); +}); + +describe('parseTableDiff', () => { + test('reads side and id for each row', () => { + const diff = parseTableDiff('nodes', `${HEADER}modified,7852,updated_at: [a] -> [b]\n`); + expect(diff.problems).toEqual([]); + expect(diff.rows).toEqual([{ side: 'modified', id: 7852, deletedRow: null }]); + }); + + test('keeps the json of deleted rows, since the snapshot no longer has them', () => { + const detail = '{""id"":7691,""node_id"":7691,""filename"":""a.png""}'; + const diff = parseTableDiff('attachments', `${HEADER}deleted,7691,"${detail}"\n`); + expect(diff.problems).toEqual([]); + expect(diff.rows[0]!.deletedRow).toEqual({ id: 7691, node_id: 7691, filename: 'a.png' }); + }); + + test('does not try to interpret the detail of modified rows', () => { + const diff = parseTableDiff( + 'people', + `${HEADER}modified,5674,"bio: [a] -> [b] | sex: [m] -> [?]"\n`, + ); + expect(diff.rows[0]!.deletedRow).toBeNull(); + }); + + test('survives a detail field containing newlines and delimiters', () => { + const diff = parseTableDiff( + 'people', + `${HEADER}modified,5674,"biography: [one\n\ntwo] -> [three]"\nnew,8545,"{}"\n`, + ); + expect(diff.problems).toEqual([]); + expect(idsBySide(diff, 'modified')).toEqual([5674]); + expect(idsBySide(diff, 'new')).toEqual([8545]); + }); + + test('rejects a diff whose table has no id column', () => { + const diff = parseTableDiff('model_view_counts', 'side,detail\nnew,"{}"\n'); + expect(diff.rows).toEqual([]); + expect(diff.problems[0]).toMatch(/expected \[side,id,detail\]/); + }); + + test('reports unusable rows instead of dropping them silently', () => { + const diff = parseTableDiff('nodes', `${HEADER}sideways,1,x\nnew,abc,y\ndeleted,3,not-json\n`); + expect(diff.rows).toEqual([]); + expect(diff.problems).toHaveLength(3); + expect(diff.problems[0]).toMatch(/unknown side/); + expect(diff.problems[1]).toMatch(/unusable id/); + expect(diff.problems[2]).toMatch(/unreadable json/); + }); + + test('reports an empty file', () => { + expect(parseTableDiff('tags', '').problems).toEqual(['tags.csv is empty']); + }); + + test('handles a header-only file as no changes', () => { + const diff = parseTableDiff('tags', HEADER); + expect(diff.rows).toEqual([]); + expect(diff.problems).toEqual([]); + }); +}); + +describe('deleted-row field readers', () => { + const row = { + id: 4986, + node_id: 7910, + filename: 'Evolved foraging behaviors.png', + content_type: 'preview', + created_at: '2026-05-28T19:02:09.298417', + missing: null, + }; + + test('requireNumber returns the value', () => { + expect(requireNumber(row, 'node_id')).toBe(7910); + }); + + test('requireNumber throws rather than guessing', () => { + expect(() => requireNumber(row, 'missing')).toThrow(/numeric missing/); + expect(() => requireNumber(row, 'filename')).toThrow(); + }); + + test('optionalString returns null for non-strings', () => { + expect(optionalString(row, 'filename')).toBe('Evolved foraging behaviors.png'); + expect(optionalString(row, 'missing')).toBeNull(); + expect(optionalString(row, 'id')).toBeNull(); + }); + + test('optionalDate parses postgres timestamps as local time, truncated to ms', () => { + const parsed = optionalDate(row, 'created_at')!; + expect(parsed).toEqual(new Date(2026, 4, 28, 19, 2, 9, 298)); + }); + + test('optionalDate returns null for missing or unparseable values', () => { + expect(optionalDate(row, 'missing')).toBeNull(); + expect(optionalDate({ x: 'not a date' }, 'x')).toBeNull(); + }); +}); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/diff.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/diff.ts new file mode 100644 index 00000000..94f1557d --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/diff.ts @@ -0,0 +1,133 @@ +import { parseCsv } from './csv.ts'; + +/** + * Reads the CSVs produced by prisma/legacy-migration/diffdb.sh. Each file is `side,id,detail` + * where `detail` is row_to_json for new/deleted rows and a human-readable + * `col: [old] -> [new]` summary for modified rows. + * + * Only `side` and `id` are trusted for new/modified rows — the authoritative + * values are re-read from the legacy snapshot, because diffdb.sh replaces the + * `contents` columns with an md5 digest. Deleted rows are the exception: the + * row is gone from the snapshot, so its json is the only remaining copy. + */ + +export const PATCHABLE_TABLES = [ + 'people', + 'nodes', + 'versions', + 'tags', + 'tagged_nodes', + 'attachments', +] as const; + +export type PatchableTable = (typeof PATCHABLE_TABLES)[number]; + +export const DIFF_SIDES = ['new', 'modified', 'deleted'] as const; +export type DiffSide = (typeof DIFF_SIDES)[number]; + +export type DiffRow = { + side: DiffSide; + id: number; + /** row_to_json of the deleted row; null for new/modified rows. */ + deletedRow: Record | null; +}; + +export type TableDiff = { + table: string; + rows: DiffRow[]; + problems: string[]; +}; + +export function isPatchableTable(table: string): table is PatchableTable { + return (PATCHABLE_TABLES as readonly string[]).includes(table); +} + +export function parseTableDiff(table: string, contents: string): TableDiff { + const records = parseCsv(contents); + const problems: string[] = []; + const rows: DiffRow[] = []; + + const [header, ...body] = records; + if (!header) return { table, rows, problems: [`${table}.csv is empty`] }; + if (header.join(',') !== 'side,id,detail') { + return { + table, + rows, + problems: [ + `${table}.csv has header [${header.join(',')}], expected [side,id,detail]. ` + + `Tables without an id column cannot be patched.`, + ], + }; + } + + for (const [index, record] of body.entries()) { + const line = index + 2; + const [side, rawId, detail] = record; + + if (!side || !isDiffSide(side)) { + problems.push(`${table}.csv:${line}: unknown side ${JSON.stringify(side ?? '')}`); + continue; + } + if (!rawId || !/^\d+$/.test(rawId)) { + problems.push(`${table}.csv:${line}: unusable id ${JSON.stringify(rawId ?? '')}`); + continue; + } + + let deletedRow: Record | null = null; + if (side === 'deleted') { + try { + const parsed: unknown = JSON.parse(detail ?? ''); + if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { + throw new Error('not a json object'); + } + deletedRow = parsed as Record; + } catch (err) { + problems.push( + `${table}.csv:${line}: deleted row ${rawId} has unreadable json (${(err as Error).message})`, + ); + continue; + } + } + + rows.push({ side, id: Number(rawId), deletedRow }); + } + + return { table, rows, problems }; +} + +export function rowsBySide(diff: TableDiff, side: DiffSide): DiffRow[] { + return diff.rows.filter((r) => r.side === side); +} + +export function idsBySide(diff: TableDiff, side: DiffSide): number[] { + return rowsBySide(diff, side).map((r) => r.id); +} + +export function requireNumber(row: Record, key: string): number { + const value = row[key]; + if (typeof value !== 'number') { + throw new Error(`Deleted row is missing a numeric ${key}`); + } + return value; +} + +export function optionalString(row: Record, key: string): string | null { + const value = row[key]; + return typeof value === 'string' ? value : null; +} + +/** + * Legacy timestamps are `timestamp without time zone`, which node-postgres reads + * as local time. Parse json copies the same way, or deleted rows would land in a + * different instant than the rows initial-import.ts wrote from the same source. + */ +export function optionalDate(row: Record, key: string): Date | null { + const value = row[key]; + if (typeof value !== 'string') return null; + const parsed = new Date(value.replace(/(\.\d{3})\d+$/, '$1')); + return Number.isNaN(parsed.getTime()) ? null : parsed; +} + +function isDiffSide(value: string): value is DiffSide { + return (DIFF_SIDES as readonly string[]).includes(value); +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/file-keys.spec.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/file-keys.spec.ts new file mode 100644 index 00000000..84109e16 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/file-keys.spec.ts @@ -0,0 +1,116 @@ +import { describe, expect, test } from 'vitest'; +import { + buildAttachmentFileKey, + derivedUuid, + buildAvatarFileKey, + buildPreviewFileKey, + buildVersionFileKey, + getAccessPrefix, + sanitizeFilename, +} from './file-keys.ts'; + +const MODEL = '11111111-1111-4111-8111-111111111111'; +const FILE = '22222222-2222-4222-8222-222222222222'; +const DATE = new Date('2011-02-18T23:30:00.000Z'); + +describe('sanitizeFilename', () => { + test.each(['file.txt', 'my model.nlogo', 'Coffee Farm Model.png'])('preserves %j', (input) => { + expect(sanitizeFilename(input)).toBe(input); + }); + + test('replaces path separators so a filename cannot escape its prefix', () => { + expect(sanitizeFilename('../../etc/passwd')).toBe('.._.._etc_passwd'); + expect(sanitizeFilename('a\\b')).toBe('a_b'); + }); + + test('strips control characters', () => { + const control = [0x00, 0x1f, 0x7f].map((c) => String.fromCharCode(c)); + expect(sanitizeFilename(`a${control[0]}b${control[1]}c${control[2]}`)).toBe('abc'); + }); + + test('trims surrounding whitespace', () => { + expect(sanitizeFilename(' model.nlogo ')).toBe('model.nlogo'); + }); + + test('falls back to "file" when nothing survives', () => { + expect(sanitizeFilename(' ')).toBe('file'); + expect(sanitizeFilename('')).toBe('file'); + }); +}); + +describe('derivedUuid', () => { + test('is stable for the same namespace and id', () => { + expect(derivedUuid('preview', 4986)).toBe(derivedUuid('preview', 4986)); + }); + + test('differs by id and by namespace', () => { + expect(derivedUuid('preview', 4986)).not.toBe(derivedUuid('preview', 4987)); + expect(derivedUuid('preview', 4986)).not.toBe(derivedUuid('attachment', 4986)); + }); + + test('is a well-formed v4-shaped uuid', () => { + expect(derivedUuid('preview', 1)).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, + ); + }); + + test('holds the shape across many ids', () => { + for (let i = 0; i < 200; i++) { + expect(derivedUuid('preview', i)).toMatch( + /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/, + ); + } + }); +}); + +describe('getAccessPrefix', () => { + test('public-read is served from the public prefix', () => { + expect(getAccessPrefix('public-read')).toBe('files/public/uploads'); + }); + + test('private uses the bare uploads prefix', () => { + expect(getAccessPrefix('private')).toBe('uploads'); + }); +}); + +describe('key builders', () => { + test('version keys are private by default and date-partitioned in UTC', () => { + expect(buildVersionFileKey(MODEL, DATE, FILE, 'wolf sheep.nlogo')).toBe( + `uploads/models/${MODEL}/versions/2011/02/18/${FILE}/wolf sheep.nlogo`, + ); + }); + + test('version keys honour an explicit access policy', () => { + expect(buildVersionFileKey(MODEL, DATE, FILE, 'a.nlogo', 'public-read')).toBe( + `files/public/uploads/models/${MODEL}/versions/2011/02/18/${FILE}/a.nlogo`, + ); + }); + + test('preview keys are public-read', () => { + expect(buildPreviewFileKey(MODEL, DATE, FILE, 'p.png')).toBe( + `files/public/uploads/models/${MODEL}/preview-images/2011/02/18/${FILE}/p.png`, + ); + }); + + test('attachment keys are private', () => { + expect(buildAttachmentFileKey(MODEL, DATE, FILE, 'CTRNN.nls')).toBe( + `uploads/models/${MODEL}/additionalFiles/2011/02/18/${FILE}/CTRNN.nls`, + ); + }); + + test('avatar keys are public-read and keyed by user uuid', () => { + expect(buildAvatarFileKey(MODEL, DATE, FILE, 'avatar')).toBe( + `files/public/uploads/avatars/${MODEL}/2011/02/18/${FILE}/avatar`, + ); + }); + + test('all builders default the filename and sanitize it', () => { + expect(buildVersionFileKey(MODEL, DATE, FILE)).toMatch(/\/file$/); + expect(buildAttachmentFileKey(MODEL, DATE, FILE, 'a/b')).toMatch(/\/a_b$/); + }); + + test('partitions by UTC, not local time', () => { + const newYearUtc = new Date('2020-01-01T00:30:00.000Z'); + expect(buildVersionFileKey(MODEL, newYearUtc, FILE)).toContain('/2020/01/01/'); + }); +}); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/file-keys.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/file-keys.ts new file mode 100644 index 00000000..3f9c9e4f --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/file-keys.ts @@ -0,0 +1,75 @@ +import { createHash } from 'node:crypto'; + +export type AccessPolicy = 'public-read' | 'private'; + +/** + * A stable stand-in for randomUUID, so re-deriving a key for the same legacy row + * yields the same object rather than a fresh copy on every run. + */ +export function derivedUuid(namespace: string, id: number | string): string { + const hex = createHash('sha256').update(`${namespace}:${id}`).digest('hex'); + const version = `4${hex.slice(13, 16)}`; + const variant = ((parseInt(hex.slice(16, 17), 16) & 0x3) | 0x8).toString(16) + hex.slice(17, 20); + return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${version}-${variant}-${hex.slice(20, 32)}`; +} + +function dateParts(d: Date) { + const y = d.getUTCFullYear().toString(); + const m = (d.getUTCMonth() + 1).toString().padStart(2, '0'); + const day = d.getUTCDate().toString().padStart(2, '0'); + return { y, m, day }; +} + +export function sanitizeFilename(name: string): string { + const cleaned = name + // eslint-disable-next-line no-control-regex + .replace(/[\x00-\x1f\x7f]/g, '') + .replace(/[/\\]/g, '_') + .trim(); + return cleaned || 'file'; +} + +export function getAccessPrefix(access: AccessPolicy): string { + return access === 'public-read' ? 'files/public/uploads' : 'uploads'; +} + +export function buildVersionFileKey( + modelUuid: string, + d: Date, + fileUuid: string, + filename: string = 'file', + accessPolicy: AccessPolicy = 'private', +): string { + const { y, m, day } = dateParts(d); + return `${getAccessPrefix(accessPolicy)}/models/${modelUuid}/versions/${y}/${m}/${day}/${fileUuid}/${sanitizeFilename(filename)}`; +} + +export function buildPreviewFileKey( + modelUuid: string, + d: Date, + fileUuid: string, + filename: string = 'file', +): string { + const { y, m, day } = dateParts(d); + return `${getAccessPrefix('public-read')}/models/${modelUuid}/preview-images/${y}/${m}/${day}/${fileUuid}/${sanitizeFilename(filename)}`; +} + +export function buildAttachmentFileKey( + modelUuid: string, + d: Date, + fileUuid: string, + filename: string = 'file', +): string { + const { y, m, day } = dateParts(d); + return `${getAccessPrefix('private')}/models/${modelUuid}/additionalFiles/${y}/${m}/${day}/${fileUuid}/${sanitizeFilename(filename)}`; +} + +export function buildAvatarFileKey( + userUuid: string, + d: Date, + fileUuid: string, + filename: string = 'file', +): string { + const { y, m, day } = dateParts(d); + return `${getAccessPrefix('public-read')}/avatars/${userUuid}/${y}/${m}/${day}/${fileUuid}/${sanitizeFilename(filename)}`; +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/legacy.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/legacy.ts new file mode 100644 index 00000000..336f8471 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/legacy.ts @@ -0,0 +1,267 @@ +import pg from 'pg'; +import Cursor from 'pg-cursor'; + +export type LegacyPerson = { + id: number; + email_address: string | null; + first_name: string | null; + last_name: string | null; + administrator: boolean | null; + birthdate: Date | null; + country_name: string | null; + url: string | null; + avatar_file_name: string | null; + avatar_updated_at: Date | null; + biography: string | null; + created_at: Date | null; + updated_at: Date | null; +}; + +export type LegacyNode = { + id: number; + name: string; + created_at: Date | null; + updated_at: Date | null; + visibility_id: number; +}; + +export type LegacyVersion = { + id: number; + node_id: number; + person_id: number; + description: string; + contents: string; + created_at: Date | null; + updated_at: Date | null; +}; + +export type LegacyTag = { + id: number; + name: string | null; + created_at: Date | null; +}; + +export type LegacyTagging = { + id: number; + node_id: number; + tag_id: number; + created_at: Date | null; +}; + +export type LegacyAttachment = { + id: number; + node_id: number; + person_id: number; + filename: string; + content_type: string; + contents: Buffer; + created_at: Date | null; +}; + +export type LegacyCollaboration = { + id: number; + person_id: number | null; + node_id: number | null; + collaborator_type_id: number | null; + created_at: Date | null; +}; + +export type LegacyNonMemberCollaboration = { + id: number; + non_member_collaborator_id: number | null; + node_id: number | null; + collaborator_type_id: number | null; + person_id: number; + email: string | null; + name: string | null; + created_at: Date | null; +}; + +export type LegacyCollaboratorType = { + id: number; + name: string | null; +}; + +export const PERSON_COLUMNS = `id, email_address, first_name, last_name, administrator, + avatar_file_name, avatar_updated_at, birthdate, country_name, url, biography, + created_at, updated_at`; +export const NODE_COLUMNS = `id, name, created_at, updated_at, visibility_id`; +export const VERSION_COLUMNS = `id, node_id, person_id, description, contents, created_at, updated_at`; +export const TAG_COLUMNS = `id, name, created_at`; +export const TAGGING_COLUMNS = `id, node_id, tag_id, created_at`; +export const ATTACHMENT_COLUMNS = `id, node_id, person_id, filename, content_type, contents, created_at`; + +export function assertSchemaName(schema: string): string { + if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(schema)) { + throw new Error(`Invalid legacy schema name: ${JSON.stringify(schema)}`); + } + return schema; +} + +export class LegacyDatabase { + private readonly pool: pg.Pool; + readonly schema: string; + + constructor(connectionString: string, schema: string, max = 4) { + this.pool = new pg.Pool({ connectionString, max }); + this.schema = assertSchemaName(schema); + } + + table(name: string): string { + return `${this.schema}.${name}`; + } + + async allPeopleEmails(): Promise> { + const { rows } = await this.pool.query<{ id: number; email_address: string | null }>( + `SELECT id, email_address FROM ${this.table('people')} ORDER BY id ASC`, + ); + return rows; + } + + async peopleByIds(ids: readonly number[]): Promise { + return this.byIds('people', PERSON_COLUMNS, ids); + } + + async nodesByIds(ids: readonly number[]): Promise { + return this.byIds('nodes', NODE_COLUMNS, ids); + } + + async versionsByIds(ids: readonly number[]): Promise { + return this.byIds('versions', VERSION_COLUMNS, ids); + } + + async tagsByIds(ids: readonly number[]): Promise { + return this.byIds('tags', TAG_COLUMNS, ids); + } + + async taggingsByIds(ids: readonly number[]): Promise { + return this.byIds('tagged_nodes', TAGGING_COLUMNS, ids); + } + + async attachmentsByIds(ids: readonly number[]): Promise { + return this.byIds('attachments', ATTACHMENT_COLUMNS, ids); + } + + async allTags(): Promise { + const { rows } = await this.pool.query( + `SELECT ${TAG_COLUMNS} FROM ${this.table('tags')} ORDER BY id ASC`, + ); + return rows; + } + + async allCollaboratorTypes(): Promise { + const { rows } = await this.pool.query( + `SELECT id, name FROM ${this.table('collaborator_types')} ORDER BY id ASC`, + ); + return rows; + } + + async allCollaborations(): Promise { + const { rows } = await this.pool.query( + `SELECT id, person_id, node_id, collaborator_type_id, created_at + FROM ${this.table('collaborations')} + ORDER BY id ASC`, + ); + return rows; + } + + /** Joined so a contributor's identity travels with the row that credits it. */ + async allNonMemberCollaborations(): Promise { + const { rows } = await this.pool.query( + `SELECT c.id, c.non_member_collaborator_id, c.node_id, c.collaborator_type_id, + c.person_id, c.created_at, p.email, p.name + FROM ${this.table('non_member_collaborations')} c + LEFT JOIN ${this.table('non_member_collaborators')} p + ON p.id = c.non_member_collaborator_id + ORDER BY c.id ASC`, + ); + return rows; + } + + async versionsForNode(nodeId: number): Promise { + const { rows } = await this.pool.query( + `SELECT ${VERSION_COLUMNS} FROM ${this.table('versions')} + WHERE node_id = $1 + ORDER BY created_at ASC NULLS LAST, id ASC`, + [nodeId], + ); + return rows; + } + + async attachmentsForNode(nodeId: number): Promise { + const { rows } = await this.pool.query( + `SELECT ${ATTACHMENT_COLUMNS} FROM ${this.table('attachments')} + WHERE node_id = $1 + ORDER BY id ASC`, + [nodeId], + ); + return rows; + } + + async taggingsForNode(nodeId: number): Promise { + const { rows } = await this.pool.query( + `SELECT ${TAGGING_COLUMNS} FROM ${this.table('tagged_nodes')} + WHERE node_id = $1 + ORDER BY id ASC`, + [nodeId], + ); + return rows; + } + + async spamNodeIds(): Promise> { + const { rows } = await this.pool.query<{ node_id: number }>( + `SELECT node_id FROM ${this.table('spam_warnings')} + WHERE node_id IS NOT NULL + GROUP BY node_id + HAVING COUNT(*) >= 2`, + ); + return new Set(rows.map((r) => r.node_id)); + } + + async existingIds(table: string, ids: readonly number[]): Promise> { + if (ids.length === 0) return new Set(); + const { rows } = await this.pool.query<{ id: number }>( + `SELECT id FROM ${this.table(table)} WHERE id = ANY($1::int[])`, + [[...ids]], + ); + return new Set(rows.map((r) => r.id)); + } + + async streamRows( + sql: string, + batchSize: number, + onBatch: (rows: T[]) => Promise, + ): Promise { + const client = await this.pool.connect(); + try { + const cursor = client.query(new Cursor(sql)); + for (;;) { + const rows: T[] = await new Promise((resolve, reject) => + cursor.read(batchSize, (err, r) => (err ? reject(err) : resolve(r as T[]))), + ); + if (rows.length === 0) break; + await onBatch(rows); + } + await new Promise((resolve) => cursor.close(() => resolve())); + } finally { + client.release(); + } + } + + async end(): Promise { + await this.pool.end(); + } + + private async byIds( + table: string, + columns: string, + ids: readonly number[], + ): Promise { + if (ids.length === 0) return []; + const { rows } = await this.pool.query( + `SELECT ${columns} FROM ${this.table(table)} WHERE id = ANY($1::int[]) ORDER BY id ASC`, + [[...ids]], + ); + return rows; + } +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/nlogo.spec.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/nlogo.spec.ts new file mode 100644 index 00000000..70cdbed0 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/nlogo.spec.ts @@ -0,0 +1,132 @@ +import { describe, expect, test } from 'vitest'; +import { getNlogoFileExtension, parseNetlogoContents, parseNlogo, parseNlogox } from './nlogo.ts'; + +const SEP = '@#$#@#$#@'; + +function nlogo(sections: string[]): string { + return sections.join(SEP); +} + +describe('getNlogoFileExtension', () => { + test('detects the sectioned legacy format', () => { + expect(getNlogoFileExtension(`code${SEP}ui`)).toBe('nlogo'); + }); + + test('detects 3D xml before plain xml', () => { + expect(getNlogoFileExtension('')).toBe( + 'nlogox3d', + ); + }); + + test('detects plain xml', () => { + expect(getNlogoFileExtension('')).toBe( + 'nlogox', + ); + }); + + test('falls back to nlogo3d on the setxyz heuristic', () => { + expect(getNlogoFileExtension('to setup setxyz 1 2 3 end')).toBe('nlogo3d'); + }); + + test('returns unknown when nothing matches', () => { + expect(getNlogoFileExtension('just some text')).toBe('unknown'); + }); +}); + +describe('parseNlogo', () => { + test('reads the info tab from section 2 and the version from section 4', () => { + const contents = nlogo([ + 'code', + 'interface', + ' ## WHAT IS IT? ', + 'shapes', + 'NetLogo 5.0.4', + 'rest', + ]); + expect(parseNlogo(contents)).toEqual({ + netlogoVersion: 'NetLogo 5.0.4', + infoTab: '## WHAT IS IT?', + }); + }); + + test('returns nulls when there are too few sections', () => { + expect(parseNlogo(nlogo(['code', 'interface', 'info']))).toEqual({ + netlogoVersion: null, + infoTab: null, + }); + }); + + test('treats empty sections as null', () => { + expect(parseNlogo(nlogo(['code', 'ui', ' ', 'shapes', ' ']))).toEqual({ + netlogoVersion: null, + infoTab: null, + }); + }); + + test('rejects an implausibly long version section', () => { + const contents = nlogo(['code', 'ui', 'info', 'shapes', 'x'.repeat(100)]); + expect(parseNlogo(contents).netlogoVersion).toBeNull(); + }); +}); + +describe('parseNlogox', () => { + test('reads the version attribute and strips the NetLogo prefix', () => { + const xml = + 'hi'; + expect(parseNlogox(xml)).toEqual({ netlogoVersion: '6.4.0', infoTab: 'hi' }); + }); + + test('strips the 3D prefix too', () => { + const xml = 'x'; + expect(parseNlogox(xml).netlogoVersion).toBe('6.2.2'); + }); + + test('unwraps CDATA in the info tab', () => { + const xml = + ''; + expect(parseNlogox(xml).infoTab).toBe('## WHAT IS IT?\n\nA model.'); + }); + + test('decodes xml entities in the info tab', () => { + const xml = + 'a <b> &amp; "c"'; + expect(parseNlogox(xml).infoTab).toBe('a & "c"'); + }); + + test('handles attributes declared before version', () => { + const xml = 'i'; + expect(parseNlogox(xml).netlogoVersion).toBe('6.3'); + }); + + test('returns nulls when the model element or info tab is missing', () => { + expect(parseNlogox('')).toEqual({ netlogoVersion: null, infoTab: null }); + expect(parseNlogox('').infoTab).toBeNull(); + }); + + test('treats a blank info tab as null', () => { + expect(parseNlogox(' ').infoTab).toBeNull(); + }); + + test('does not throw on malformed xml', () => { + expect(() => parseNlogox('unclosed')).not.toThrow(); + expect(parseNlogox('unclosed').infoTab).toBeNull(); + }); +}); + +describe('parseNetlogoContents', () => { + test('routes nlogox and nlogox3d to the xml parser', () => { + const xml = 'i'; + expect(parseNetlogoContents(xml, 'nlogox')).toEqual({ netlogoVersion: '6.4', infoTab: 'i' }); + expect(parseNetlogoContents(xml, 'nlogox3d')).toEqual({ netlogoVersion: '6.4', infoTab: 'i' }); + }); + + test('routes every other format to the sectioned parser', () => { + const contents = nlogo(['code', 'ui', 'info', 'shapes', 'NetLogo 5.0.4']); + for (const format of ['nlogo', 'nlogo3d', 'unknown']) { + expect(parseNetlogoContents(contents, format)).toEqual({ + netlogoVersion: 'NetLogo 5.0.4', + infoTab: 'info', + }); + } + }); +}); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/nlogo.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/nlogo.ts new file mode 100644 index 00000000..d2a45f64 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/nlogo.ts @@ -0,0 +1,55 @@ +export type NlogoMetadata = { + netlogoVersion: string | null; + infoTab: string | null; +}; + +const NLOGO_SECTION_SEPARATOR = '@#$#@#$#@'; + +export function getNlogoFileExtension(contents: string): string { + if (contents.includes(NLOGO_SECTION_SEPARATOR)) return 'nlogo'; + if (contents.includes(']*>([\s\S]*?)<\/info>/.exec(contents)?.[1] ?? null; + const infoTab = infoRaw ? decodeXmlText(infoRaw).trim() || null : null; + + return { netlogoVersion, infoTab }; +} + +export function parseNetlogoContents(contents: string, format: string): NlogoMetadata { + return format.startsWith('nlogox') ? parseNlogox(contents) : parseNlogo(contents); +} + +function decodeXmlText(raw: string): string { + const cdata = /^\s*\s*$/.exec(raw); + return (cdata?.[1] ?? raw) + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, "'") + .replace(/&#(\d+);/g, (_, code: string) => String.fromCodePoint(Number(code))) + .replace(/&/g, '&'); +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/node-migration.spec.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/node-migration.spec.ts new file mode 100644 index 00000000..be35372f --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/node-migration.spec.ts @@ -0,0 +1,351 @@ +import { describe, expect, test } from 'vitest'; +import { + createModelFromNode, + mapVisibility, + type ModelWriter, + type NodeTree, +} from './node-migration.ts'; +import type { LegacyAttachment, LegacyNode, LegacyTagging, LegacyVersion } from './legacy.ts'; + +const MODEL_UUID = '00000000-0000-4000-8000-000000000000'; +const NOW = new Date('2030-01-01T00:00:00.000Z'); +const SEP = '@#$#@#$#@'; + +function nlogo(version = 'NetLogo 5.0.4', info = 'the info tab'): string { + return ['code', 'ui', info, 'shapes', version].join(SEP); +} + +type Call = { method: string; args: unknown }; + +function recordingWriter() { + const calls: Call[] = []; + const record = (method: string) => (args: unknown) => { + calls.push({ method, args }); + return Promise.resolve({}); + }; + const tx: ModelWriter = { + model: { create: record('model.create'), update: record('model.update') }, + modelVersion: { create: record('modelVersion.create'), update: record('modelVersion.update') }, + modelAuthor: { create: record('modelAuthor.create') }, + modelAdditionalFile: { create: record('modelAdditionalFile.create') }, + modelVersionTag: { create: record('modelVersionTag.create') }, + }; + const dataFor = (method: string) => + calls.filter((c) => c.method === method).map((c) => (c.args as { data: unknown }).data); + return { tx, calls, dataFor }; +} + +function deps(overrides: Partial[3]> = {}) { + const written = new Map(); + let counter = 0; + return { + written, + value: { + writeFile: async (relKey: string, contents: Buffer) => { + written.set(relKey, contents); + }, + newUuid: () => `uuid-${++counter}`, + now: () => NOW, + userIdByLegacyId: new Map([ + [10, 'user-10'], + [11, 'user-11'], + ]), + tagIdByLegacyId: new Map([ + [100, 'tag-100'], + [101, 'tag-101'], + ]), + ...overrides, + }, + }; +} + +const node: LegacyNode = { + id: 7921, + name: 'Wolf Sheep', + created_at: new Date('2020-05-04T10:00:00.000Z'), + updated_at: new Date('2021-06-05T11:00:00.000Z'), + visibility_id: 1, +}; + +function version(over: Partial = {}): LegacyVersion { + return { + id: 1, + node_id: node.id, + person_id: 10, + description: 'Initial upload', + contents: nlogo(), + created_at: new Date('2020-05-04T10:00:00.000Z'), + updated_at: null, + ...over, + }; +} + +function attachment(over: Partial = {}): LegacyAttachment { + return { + id: 1, + node_id: node.id, + person_id: 10, + filename: 'notes.txt', + content_type: 'data', + contents: Buffer.from('hello'), + created_at: new Date('2020-07-01T00:00:00.000Z'), + ...over, + }; +} + +function tagging(over: Partial = {}): LegacyTagging { + return { + id: 1, + node_id: node.id, + tag_id: 100, + created_at: new Date('2020-08-01T00:00:00.000Z'), + ...over, + }; +} + +function tree(over: Partial = {}): NodeTree { + return { node, versions: [version()], attachments: [], taggings: [], ...over }; +} + +describe('mapVisibility', () => { + test('1 is public, 2 and 3 are private', () => { + expect(mapVisibility(1)).toBe('public'); + expect(mapVisibility(2)).toBe('private'); + expect(mapVisibility(3)).toBe('private'); + }); + + test('unknown legacy visibility falls back to public', () => { + expect(mapVisibility(99)).toBe('public'); + }); +}); + +describe('createModelFromNode', () => { + test('refuses a node with no versions', async () => { + const { tx } = recordingWriter(); + await expect( + createModelFromNode(tx, MODEL_UUID, tree({ versions: [] }), deps().value), + ).rejects.toThrow(/no versions/i); + }); + + test('creates the model keyed on the legacy node id, never touching the uuid of anything else', async () => { + const { tx, dataFor } = recordingWriter(); + await createModelFromNode(tx, MODEL_UUID, tree(), deps().value); + + expect(dataFor('model.create')[0]).toEqual({ + id: MODEL_UUID, + legacyId: 7921, + visibility: 'public', + isEndorsed: false, + createdAt: node.created_at, + updatedAt: node.updated_at, + }); + }); + + test('falls back through created_at then now for missing timestamps', async () => { + const { tx, dataFor } = recordingWriter(); + const bare = { ...node, created_at: null, updated_at: null }; + await createModelFromNode(tx, MODEL_UUID, tree({ node: bare }), deps().value); + + expect(dataFor('model.create')[0]).toMatchObject({ createdAt: NOW, updatedAt: NOW }); + }); + + test('numbers versions 1..N in the order supplied and points latestVersionNumber at the last', async () => { + const { tx, dataFor } = recordingWriter(); + const versions = [ + version({ id: 1, created_at: new Date('2020-01-01T00:00:00.000Z') }), + version({ id: 2, created_at: new Date('2021-01-01T00:00:00.000Z') }), + version({ id: 3, created_at: new Date('2022-01-01T00:00:00.000Z') }), + ]; + const result = await createModelFromNode(tx, MODEL_UUID, tree({ versions }), deps().value); + + expect( + dataFor('modelVersion.create').map((d) => (d as { versionNumber: number }).versionNumber), + ).toEqual([1, 2, 3]); + expect(dataFor('model.update')[0]).toEqual({ latestVersionNumber: 3 }); + expect(result.latestVersionNumber).toBe(3); + expect(result.versions).toBe(3); + }); + + test('titles every version with the node name and parses metadata out of the contents', async () => { + const { tx, dataFor } = recordingWriter(); + await createModelFromNode(tx, MODEL_UUID, tree(), deps().value); + + expect(dataFor('modelVersion.create')[0]).toMatchObject({ + modelId: MODEL_UUID, + versionNumber: 1, + title: 'Wolf Sheep', + description: 'Initial upload', + netlogoVersion: 'NetLogo 5.0.4', + infoTab: 'the info tab', + finalizedAt: version().created_at, + }); + }); + + test('an empty version description becomes null', async () => { + const { tx, dataFor } = recordingWriter(); + await createModelFromNode( + tx, + MODEL_UUID, + tree({ versions: [version({ description: '' })] }), + deps().value, + ); + + expect(dataFor('modelVersion.create')[0]).toMatchObject({ description: null }); + }); + + test('writes the version file under a key derived from the node name and detected format', async () => { + const { tx, dataFor } = recordingWriter(); + const d = deps(); + await createModelFromNode(tx, MODEL_UUID, tree(), d.value); + + const key = (dataFor('modelVersion.create')[0] as { netlogoFileKey: string }).netlogoFileKey; + expect(key).toBe(`uploads/models/${MODEL_UUID}/versions/2020/05/04/uuid-1/Wolf Sheep.nlogo`); + expect(d.written.get(key)?.toString('utf8')).toBe(nlogo()); + }); + + test('the first version author is the owner and later distinct authors are contributors', async () => { + const { tx, dataFor } = recordingWriter(); + const versions = [ + version({ id: 1, person_id: 10 }), + version({ id: 2, person_id: 11 }), + version({ id: 3, person_id: 10 }), + ]; + const result = await createModelFromNode(tx, MODEL_UUID, tree({ versions }), deps().value); + + expect(dataFor('modelAuthor.create')).toEqual([ + { modelId: MODEL_UUID, userId: 'user-10', role: 'owner', createdAt: versions[0]!.created_at }, + { + modelId: MODEL_UUID, + userId: 'user-11', + role: 'contributor', + createdAt: versions[1]!.created_at, + }, + ]); + expect(result.owners).toBe(1); + expect(result.contributors).toBe(1); + }); + + test('an unmapped author is dropped rather than failing the node', async () => { + const { tx, dataFor } = recordingWriter(); + const versions = [version({ id: 1, person_id: 999 }), version({ id: 2, person_id: 11 })]; + const result = await createModelFromNode(tx, MODEL_UUID, tree({ versions }), deps().value); + + expect(result.owners).toBe(0); + expect(dataFor('modelAuthor.create')).toEqual([ + { + modelId: MODEL_UUID, + userId: 'user-11', + role: 'contributor', + createdAt: versions[1]!.created_at, + }, + ]); + }); + + test('preview attachments land on the latest version and the last one by id wins', async () => { + const { tx, calls, dataFor } = recordingWriter(); + const versions = [ + version({ id: 1 }), + version({ id: 2, created_at: new Date('2021-01-01T00:00:00.000Z') }), + ]; + const attachments = [ + attachment({ id: 5, content_type: 'preview', filename: 'first.png' }), + attachment({ id: 6, content_type: 'preview', filename: 'second.png' }), + ]; + const result = await createModelFromNode( + tx, + MODEL_UUID, + tree({ versions, attachments }), + deps().value, + ); + + const updates = calls.filter((c) => c.method === 'modelVersion.update'); + expect(updates).toHaveLength(2); + expect(updates.at(-1)!.args).toMatchObject({ + where: { modelId_versionNumber: { modelId: MODEL_UUID, versionNumber: 2 } }, + }); + expect( + (updates.at(-1)!.args as { data: { previewImageFileKey: string } }).data.previewImageFileKey, + ).toContain('/second.png'); + expect(result.previewsAttached).toBe(2); + expect(dataFor('modelAdditionalFile.create')).toEqual([]); + }); + + test('preview keys are public-read', async () => { + const { tx, calls } = recordingWriter(); + const attachments = [attachment({ id: 5, content_type: 'preview', filename: 'p.png' })]; + await createModelFromNode(tx, MODEL_UUID, tree({ attachments }), deps().value); + + const update = calls.find((c) => c.method === 'modelVersion.update')!; + expect( + (update.args as { data: { previewImageFileKey: string } }).data.previewImageFileKey, + ).toBe(`files/public/uploads/models/${MODEL_UUID}/preview-images/2020/07/01/uuid-2/p.png`); + }); + + test('non-preview attachments become additional files tagged to the latest version, with a metadata sidecar', async () => { + const { tx, dataFor } = recordingWriter(); + const d = deps(); + const attachments = [attachment({ id: 5, filename: 'CTRNN.nls', content_type: 'extension' })]; + const result = await createModelFromNode(tx, MODEL_UUID, tree({ attachments }), d.value); + + const file = dataFor('modelAdditionalFile.create')[0] as { + id: string; + fileKey: string; + taggedVersionNumber: number; + }; + expect(file).toMatchObject({ + id: 'uuid-2', + modelId: MODEL_UUID, + taggedVersionNumber: 1, + kind: 'additional', + createdAt: attachments[0]!.created_at, + }); + expect(file.fileKey).toBe( + `uploads/models/${MODEL_UUID}/additionalFiles/2020/07/01/uuid-2/CTRNN.nls`, + ); + expect(d.written.get(file.fileKey)?.toString()).toBe('hello'); + expect(JSON.parse(d.written.get(`${file.fileKey}.metadata.json`)!.toString())).toEqual({ + contentType: 'extension', + originalFilename: 'CTRNN.nls', + userId: 'user-10', + createdAt: attachments[0]!.created_at!.toISOString(), + }); + expect(result.attachments).toBe(1); + }); + + test('taggings land on the latest version, deduped, with unmapped tags skipped', async () => { + const { tx, dataFor } = recordingWriter(); + const versions = [ + version({ id: 1 }), + version({ id: 2, created_at: new Date('2021-01-01T00:00:00.000Z') }), + ]; + const taggings = [ + tagging({ id: 1, tag_id: 100 }), + tagging({ id: 2, tag_id: 100 }), + tagging({ id: 3, tag_id: 101 }), + tagging({ id: 4, tag_id: 999 }), + ]; + const result = await createModelFromNode( + tx, + MODEL_UUID, + tree({ versions, taggings }), + deps().value, + ); + + expect(dataFor('modelVersionTag.create')).toEqual([ + { + modelId: MODEL_UUID, + versionNumber: 2, + tagId: 'tag-100', + createdAt: taggings[0]!.created_at, + }, + { + modelId: MODEL_UUID, + versionNumber: 2, + tagId: 'tag-101', + createdAt: taggings[2]!.created_at, + }, + ]); + expect(result.taggings).toBe(2); + expect(result.skippedOrphanTaggings).toBe(1); + }); +}); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/node-migration.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/node-migration.ts new file mode 100644 index 00000000..18284379 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/node-migration.ts @@ -0,0 +1,258 @@ +import type { Prisma } from '../../../generated/prisma/client.js'; +import { buildAttachmentFileKey, buildPreviewFileKey, buildVersionFileKey } from './file-keys.ts'; +import type { LegacyAttachment, LegacyNode, LegacyTagging, LegacyVersion } from './legacy.ts'; +import { getNlogoFileExtension, parseNetlogoContents } from './nlogo.ts'; + +export type ModelVisibility = 'public' | 'private'; + +export type ModelWriter = { + model: { + create(args: { data: Prisma.ModelUncheckedCreateInput }): Promise; + update(args: { + where: { id: string }; + data: { latestVersionNumber: number }; + }): Promise; + }; + modelVersion: { + create(args: { data: Prisma.ModelVersionUncheckedCreateInput }): Promise; + update(args: { + where: { modelId_versionNumber: { modelId: string; versionNumber: number } }; + data: { previewImageFileKey: string }; + }): Promise; + }; + modelAuthor: { create(args: { data: Prisma.ModelAuthorUncheckedCreateInput }): Promise }; + modelAdditionalFile: { + create(args: { data: Prisma.ModelAdditionalFileUncheckedCreateInput }): Promise; + }; + modelVersionTag: { + create(args: { data: Prisma.ModelVersionTagUncheckedCreateInput }): Promise; + }; +}; + +export type NodeTree = { + node: LegacyNode; + /** Ordered created_at ASC NULLS LAST, id ASC — this order defines versionNumber. */ + versions: LegacyVersion[]; + /** Ordered id ASC — this order decides which preview wins. */ + attachments: LegacyAttachment[]; + taggings: LegacyTagging[]; +}; + +export type NodeMigrationDeps = { + writeFile: (relKey: string, contents: Buffer) => Promise; + newUuid: () => string; + now: () => Date; + userIdByLegacyId: ReadonlyMap; + tagIdByLegacyId: ReadonlyMap; +}; + +export type NodeMigrationResult = { + latestVersionNumber: number; + versions: number; + owners: number; + contributors: number; + attachments: number; + previewsAttached: number; + taggings: number; + skippedOrphanTaggings: number; +}; + +const VISIBILITY_BY_LEGACY_ID: Record = { + 1: 'public', + 2: 'private', + 3: 'private', +}; + +export function mapVisibility(visibilityId: number): ModelVisibility { + return VISIBILITY_BY_LEGACY_ID[visibilityId] ?? 'public'; +} + +export function buildVersionFilename(nodeName: string, contents: string): string { + return `${nodeName}.${getNlogoFileExtension(contents)}`; +} + +export function buildAttachmentMetadata( + attachment: LegacyAttachment, + userIdByLegacyId: ReadonlyMap, + now: Date, +): Buffer { + return Buffer.from( + JSON.stringify({ + contentType: attachment.content_type, + originalFilename: attachment.filename, + userId: attachment.person_id ? (userIdByLegacyId.get(attachment.person_id) ?? null) : null, + createdAt: attachment.created_at?.toISOString() ?? now.toISOString(), + }), + 'utf8', + ); +} + +export async function createModelFromNode( + tx: ModelWriter, + modelUuid: string, + tree: NodeTree, + deps: NodeMigrationDeps, +): Promise { + const { node, versions, attachments, taggings } = tree; + const [firstVersion] = versions; + if (!firstVersion) { + throw new Error(`Legacy node ${node.id} has no versions and cannot become a Model`); + } + + const result: NodeMigrationResult = { + latestVersionNumber: 0, + versions: 0, + owners: 0, + contributors: 0, + attachments: 0, + previewsAttached: 0, + taggings: 0, + skippedOrphanTaggings: 0, + }; + + await tx.model.create({ + data: { + id: modelUuid, + legacyId: node.id, + visibility: mapVisibility(node.visibility_id), + isEndorsed: false, + createdAt: node.created_at ?? deps.now(), + updatedAt: node.updated_at ?? node.created_at ?? deps.now(), + }, + }); + + let versionNumber = 0; + for (const v of versions) { + versionNumber++; + await writeVersion(tx, modelUuid, node, v, versionNumber, deps); + result.versions++; + } + const latestVersionNumber = versionNumber; + result.latestVersionNumber = latestVersionNumber; + + await tx.model.update({ where: { id: modelUuid }, data: { latestVersionNumber } }); + + const seenAuthors = new Set(); + const ownerUuid = deps.userIdByLegacyId.get(firstVersion.person_id); + if (ownerUuid) { + await tx.modelAuthor.create({ + data: { + modelId: modelUuid, + userId: ownerUuid, + role: 'owner', + createdAt: firstVersion.created_at ?? deps.now(), + }, + }); + seenAuthors.add(ownerUuid); + result.owners++; + } + for (const v of versions.slice(1)) { + const uuid = deps.userIdByLegacyId.get(v.person_id); + if (!uuid || seenAuthors.has(uuid)) continue; + await tx.modelAuthor.create({ + data: { + modelId: modelUuid, + userId: uuid, + role: 'contributor', + createdAt: v.created_at ?? deps.now(), + }, + }); + seenAuthors.add(uuid); + result.contributors++; + } + + for (const a of attachments) { + const fileUuid = deps.newUuid(); + const dateForPath = a.created_at ?? node.created_at ?? deps.now(); + + if (a.content_type === 'preview') { + const relKey = buildPreviewFileKey(modelUuid, dateForPath, fileUuid, a.filename); + await deps.writeFile(relKey, a.contents); + await tx.modelVersion.update({ + where: { + modelId_versionNumber: { modelId: modelUuid, versionNumber: latestVersionNumber }, + }, + data: { previewImageFileKey: relKey }, + }); + result.previewsAttached++; + continue; + } + + const relKey = buildAttachmentFileKey(modelUuid, dateForPath, fileUuid, a.filename); + await deps.writeFile(relKey, a.contents); + await deps.writeFile( + `${relKey}.metadata.json`, + buildAttachmentMetadata(a, deps.userIdByLegacyId, deps.now()), + ); + await tx.modelAdditionalFile.create({ + data: { + id: fileUuid, + modelId: modelUuid, + taggedVersionNumber: latestVersionNumber, + fileKey: relKey, + kind: 'additional', + createdAt: a.created_at ?? deps.now(), + }, + }); + result.attachments++; + } + + const seenTags = new Set(); + for (const tg of taggings) { + const tagUuid = deps.tagIdByLegacyId.get(tg.tag_id); + if (!tagUuid) { + result.skippedOrphanTaggings++; + continue; + } + if (seenTags.has(tagUuid)) continue; + seenTags.add(tagUuid); + + await tx.modelVersionTag.create({ + data: { + modelId: modelUuid, + versionNumber: latestVersionNumber, + tagId: tagUuid, + createdAt: tg.created_at ?? deps.now(), + }, + }); + result.taggings++; + } + + return result; +} + +async function writeVersion( + tx: ModelWriter, + modelUuid: string, + node: LegacyNode, + v: LegacyVersion, + versionNumber: number, + deps: NodeMigrationDeps, +): Promise { + const dateForPath = v.created_at ?? node.created_at ?? deps.now(); + const format = getNlogoFileExtension(v.contents); + const relKey = buildVersionFileKey( + modelUuid, + dateForPath, + deps.newUuid(), + `${node.name}.${format}`, + ); + + await deps.writeFile(relKey, Buffer.from(v.contents, 'utf8')); + + const { netlogoVersion, infoTab } = parseNetlogoContents(v.contents, format); + + await tx.modelVersion.create({ + data: { + modelId: modelUuid, + versionNumber, + title: node.name, + description: v.description || null, + netlogoFileKey: relKey, + netlogoVersion, + infoTab, + createdAt: v.created_at ?? deps.now(), + finalizedAt: v.created_at ?? null, + }, + }); +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/normalize.spec.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/normalize.spec.ts new file mode 100644 index 00000000..6efec677 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/normalize.spec.ts @@ -0,0 +1,127 @@ +import { describe, expect, test } from 'vitest'; +import { + buildFullName, + hashIp, + normalizeEmail, + normalizeTagName, + pickLowestIdWinners, + toUtcDateOnly, +} from './normalize.ts'; + +describe('normalizeEmail', () => { + test('trims and lowercases', () => { + expect(normalizeEmail(' Foo@Example.COM ')).toBe('foo@example.com'); + }); + + test('maps blank and nullish input to the empty string', () => { + expect(normalizeEmail(null)).toBe(''); + expect(normalizeEmail(undefined)).toBe(''); + expect(normalizeEmail(' ')).toBe(''); + }); +}); + +describe('normalizeTagName', () => { + test('trims and lowercases', () => { + expect(normalizeTagName(' Sexual Reproduction ')).toBe('sexual reproduction'); + }); + + test('maps blank and nullish input to the empty string', () => { + expect(normalizeTagName(null)).toBe(''); + expect(normalizeTagName(' ')).toBe(''); + }); +}); + +describe('buildFullName', () => { + test('joins both parts with a single space', () => { + expect(buildFullName('Ada', 'Lovelace')).toBe('Ada Lovelace'); + }); + + test('tolerates a missing part', () => { + expect(buildFullName('Ada', null)).toBe('Ada'); + expect(buildFullName(null, 'Lovelace')).toBe('Lovelace'); + }); + + test('trims each part', () => { + expect(buildFullName(' Ada ', ' Lovelace ')).toBe('Ada Lovelace'); + }); + + test('returns null when nothing is left', () => { + expect(buildFullName(null, null)).toBeNull(); + expect(buildFullName(' ', '')).toBeNull(); + }); +}); + +describe('toUtcDateOnly', () => { + test('pins a local-midnight date to UTC midnight of the same calendar day', () => { + const local = new Date(1815, 11, 10); // what pg returns for a `date` column + expect(toUtcDateOnly(local)?.toISOString()).toBe('1815-12-10T00:00:00.000Z'); + }); + + test('keeps the calendar day whatever the local time of day', () => { + expect(toUtcDateOnly(new Date(2020, 0, 1, 23, 59, 59))?.toISOString()).toBe( + '2020-01-01T00:00:00.000Z', + ); + expect(toUtcDateOnly(new Date(2020, 0, 1, 0, 0, 1))?.toISOString()).toBe( + '2020-01-01T00:00:00.000Z', + ); + }); + + test('is stable across timezones for the same calendar day', () => { + expect(toUtcDateOnly(new Date(1990, 5, 15))?.toISOString()).toBe('1990-06-15T00:00:00.000Z'); + }); + + test('passes through missing values', () => { + expect(toUtcDateOnly(null)).toBeNull(); + expect(toUtcDateOnly(undefined)).toBeNull(); + }); +}); + +describe('hashIp', () => { + test('returns null for a missing ip', () => { + expect(hashIp(null, 'salt')).toBeNull(); + expect(hashIp('', 'salt')).toBeNull(); + }); + + test('is a stable 32-char hex digest', () => { + const hash = hashIp('203.0.113.7', 'salt'); + expect(hash).toMatch(/^[0-9a-f]{32}$/); + expect(hashIp('203.0.113.7', 'salt')).toBe(hash); + }); + + test('changes with the salt, so the raw ip is not recoverable across rotations', () => { + expect(hashIp('203.0.113.7', 'a')).not.toBe(hashIp('203.0.113.7', 'b')); + }); +}); + +describe('pickLowestIdWinners', () => { + const rows = [ + { id: 3, name: 'Alpha' }, + { id: 1, name: 'alpha' }, + { id: 2, name: 'beta' }, + { id: 4, name: '' }, + ]; + + test('the lowest id claims each key', () => { + const winners = pickLowestIdWinners(rows, (r) => r.name.toLowerCase()); + expect(winners.get('alpha')?.id).toBe(1); + expect(winners.get('beta')?.id).toBe(2); + }); + + test('rows with an empty key are excluded', () => { + const winners = pickLowestIdWinners(rows, (r) => r.name.toLowerCase()); + expect(winners.has('')).toBe(false); + expect(winners.size).toBe(2); + }); + + test('does not depend on input ordering', () => { + const ascending = pickLowestIdWinners( + [...rows].sort((a, b) => a.id - b.id), + (r) => r.name.toLowerCase(), + ); + const descending = pickLowestIdWinners( + [...rows].sort((a, b) => b.id - a.id), + (r) => r.name.toLowerCase(), + ); + expect(ascending.get('alpha')?.id).toBe(descending.get('alpha')?.id); + }); +}); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/lib/normalize.ts b/apps/modeling-commons-backend/prisma/legacy-migration/lib/normalize.ts new file mode 100644 index 00000000..e860935d --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/lib/normalize.ts @@ -0,0 +1,58 @@ +import { createHash } from 'node:crypto'; + +export function normalizeEmail(raw: string | null | undefined): string { + return (raw ?? '').trim().toLowerCase(); +} + +export function normalizeTagName(raw: string | null | undefined): string { + return (raw ?? '').trim().toLowerCase(); +} + +export function buildFullName( + first: string | null | undefined, + last: string | null | undefined, +): string | null { + return ( + [first, last] + .map((s) => (s ?? '').trim()) + .filter(Boolean) + .join(' ') || null + ); +} + +/** + * node-postgres reads a `date` column as local midnight, while Prisma stores a + * `@db.Date` field from the Date's UTC calendar day. Left alone, the same + * birthdate round-trips to a different instant on every read and shifts by a + * day in positive UTC offsets. Pin it to UTC midnight of the same calendar day. + */ +export function toUtcDateOnly(d: Date | null | undefined): Date | null { + if (!d) return null; + return new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate())); +} + +export function hashIp(ip: string | null, salt: string): string | null { + if (!ip) return null; + return createHash('sha256') + .update(salt + ':' + ip) + .digest('hex') + .slice(0, 32); +} + +/** + * Lowest legacy id claims a value that is unique in the target schema + * (User.email, Tag.name). Losers are dropped rather than renamed. + */ +export function pickLowestIdWinners( + rows: readonly T[], + keyOf: (row: T) => string, +): Map { + const winners = new Map(); + for (const row of rows) { + const key = keyOf(row); + if (!key) continue; + const current = winners.get(key); + if (!current || row.id < current.id) winners.set(key, row); + } + return winners; +} diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/.gitignore b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/.gitignore new file mode 100644 index 00000000..3c1b3b23 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/.gitignore @@ -0,0 +1 @@ +.work/ diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/01-baseline.sql b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/01-baseline.sql new file mode 100644 index 00000000..5a0659c2 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/01-baseline.sql @@ -0,0 +1,92 @@ +-- Legacy Rails schema subset (the tables initial-import.ts reads), seeded with the +-- "already migrated" snapshot. +DROP SCHEMA IF EXISTS public CASCADE; +CREATE SCHEMA public; +SET search_path TO public; + +CREATE TABLE people ( + id integer PRIMARY KEY, + email_address varchar(255), first_name varchar(255), last_name varchar(255), + password varchar(255), administrator boolean, + created_at timestamp, updated_at timestamp, + avatar_file_name text, avatar_content_type varchar(255), + avatar_file_size integer, avatar_updated_at timestamp, + salt varchar(255), registration_consent boolean DEFAULT false, + sex varchar(255), birthdate date, country_name varchar(255), + send_site_updates boolean DEFAULT true, send_model_updates boolean DEFAULT true, + send_tag_updates boolean DEFAULT true, + url varchar(255), biography text, show_email_address boolean DEFAULT false +); + +CREATE TABLE nodes ( + id integer PRIMARY KEY, parent_id integer, name text NOT NULL, + created_at timestamp, updated_at timestamp, + visibility_id integer DEFAULT 1 NOT NULL, changeability_id integer DEFAULT 1 NOT NULL, + group_id integer, wants_help boolean DEFAULT false NOT NULL +); + +CREATE TABLE versions ( + id integer PRIMARY KEY, node_id integer NOT NULL, person_id integer NOT NULL, + description text NOT NULL, contents text NOT NULL, + created_at timestamp, updated_at timestamp +); + +CREATE TABLE tags ( + id integer PRIMARY KEY, name varchar(255), person_id integer, + created_at timestamp, updated_at timestamp +); + +CREATE TABLE tagged_nodes ( + id integer PRIMARY KEY, node_id integer, tag_id integer, + created_at timestamp, updated_at timestamp, person_id integer, comment text +); + +CREATE TABLE attachments ( + id integer PRIMARY KEY, node_id integer NOT NULL, person_id integer NOT NULL, + description varchar(255) NOT NULL, contents bytea NOT NULL, + filename varchar(255) NOT NULL, content_type varchar(255) NOT NULL, + created_at timestamp, updated_at timestamp +); + +CREATE TABLE spam_warnings ( + id integer PRIMARY KEY, person_id integer, node_id integer, + created_at timestamp, updated_at timestamp +); + +-- initial-import.ts reads these in its last phase; empty is enough. +CREATE TABLE model_views (logged_at timestamp, ip_address text, node_id integer, person_id integer); +CREATE TABLE model_runs (logged_at timestamp, ip_address text, node_id integer, person_id integer); +CREATE TABLE model_downloads (logged_at timestamp, ip_address text, node_id integer, person_id integer); + +INSERT INTO people (id, email_address, first_name, last_name, biography, url, birthdate, created_at, updated_at) VALUES + (1, 'ada@example.com', 'Ada', 'Lovelace', 'Original bio.', 'https://ada.example', '1815-12-10', '2020-01-01 10:00:00', '2020-01-01 10:00:00'), + (2, 'grace@example.com', 'Grace', 'Hopper', NULL, NULL, NULL, '2020-01-02 10:00:00', '2020-01-02 10:00:00'), + (3, 'alan@example.com', 'Alan', 'Turing', NULL, NULL, NULL, '2020-01-03 10:00:00', '2020-01-03 10:00:00'), + (4, 'spam@example.com', 'Spam', 'Bot', NULL, NULL, NULL, '2020-01-04 10:00:00', '2020-01-04 10:00:00'); + +INSERT INTO nodes (id, name, created_at, updated_at, visibility_id) VALUES + (10, 'Wolf Sheep Predation', '2020-02-01 10:00:00', '2020-02-01 10:00:00', 1), + (11, 'Ant Colony', '2020-02-02 10:00:00', '2020-02-02 10:00:00', 1), + (12, 'Segregation', '2020-02-03 10:00:00', '2020-02-03 10:00:00', 1), + (13, 'Doomed Model', '2020-02-04 10:00:00', '2020-02-04 10:00:00', 1); + +INSERT INTO versions (id, node_id, person_id, description, contents, created_at, updated_at) VALUES + (100, 10, 1, 'Initial upload', 'code@#$#@#$#@ui@#$#@#$#@wolf info@#$#@#$#@shapes@#$#@#$#@NetLogo 5.0.4', '2020-02-01 10:00:00', '2020-02-01 10:00:00'), + (101, 11, 2, 'Initial upload', 'code@#$#@#$#@ui@#$#@#$#@ant info@#$#@#$#@shapes@#$#@#$#@NetLogo 6.1.0', '2020-02-02 10:00:00', '2020-02-02 10:00:00'), + (102, 12, 3, 'Initial upload', 'seg info', '2020-02-03 10:00:00', '2020-02-03 10:00:00'), + (103, 13, 1, 'Initial upload', 'code@#$#@#$#@ui@#$#@#$#@doomed@#$#@#$#@shapes@#$#@#$#@NetLogo 5.0.4', '2020-02-04 10:00:00', '2020-02-04 10:00:00'); + +INSERT INTO tags (id, name, person_id, created_at, updated_at) VALUES + (200, 'biology', 1, '2020-03-01 10:00:00', '2020-03-01 10:00:00'), + (201, 'emergent', 1, '2020-03-02 10:00:00', '2020-03-02 10:00:00'); + +INSERT INTO tagged_nodes (id, node_id, tag_id, person_id, comment, created_at, updated_at) VALUES + (300, 10, 200, 1, '', '2020-03-03 10:00:00', '2020-03-03 10:00:00'), + (301, 11, 201, 2, '', '2020-03-04 10:00:00', '2020-03-04 10:00:00'); + +INSERT INTO attachments (id, node_id, person_id, description, contents, filename, content_type, created_at, updated_at) VALUES + (400, 10, 1, 'Preview', '\x89504e470d0a1a0a01', 'wolf-old.png', 'preview', '2020-04-01 10:00:00', '2020-04-01 10:00:00'), + (401, 10, 1, 'Preview v2','\x89504e470d0a1a0a02', 'wolf-new.png', 'preview', '2020-04-02 10:00:00', '2020-04-02 10:00:00'), + (402, 10, 1, 'Helper', '\x6e6c73206f6c64', 'helper.nls', 'extension', '2020-04-03 10:00:00', '2020-04-03 10:00:00'), + (403, 11, 2, 'Data', '\x646174612d6f6c64', 'runs.csv', 'data', '2020-04-04 10:00:00', '2020-04-04 10:00:00'), + (404, 11, 2, 'Preview', '\x89504e470d0a1a0a03', 'ant.png', 'preview', '2020-04-05 10:00:00', '2020-04-05 10:00:00'); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/02-incoming.sql b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/02-incoming.sql new file mode 100644 index 00000000..5313d383 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/02-incoming.sql @@ -0,0 +1,103 @@ +-- `incoming` is a byte-for-byte copy of the migrated snapshot, then a changelog +-- of everything that happened in the legacy app since the migration. +DROP SCHEMA IF EXISTS incoming CASCADE; +CREATE SCHEMA incoming; + +CREATE TABLE incoming.people (LIKE public.people INCLUDING ALL); +CREATE TABLE incoming.nodes (LIKE public.nodes INCLUDING ALL); +CREATE TABLE incoming.versions (LIKE public.versions INCLUDING ALL); +CREATE TABLE incoming.tags (LIKE public.tags INCLUDING ALL); +CREATE TABLE incoming.tagged_nodes (LIKE public.tagged_nodes INCLUDING ALL); +CREATE TABLE incoming.attachments (LIKE public.attachments INCLUDING ALL); +CREATE TABLE incoming.spam_warnings (LIKE public.spam_warnings INCLUDING ALL); +CREATE TABLE incoming.model_views (LIKE public.model_views INCLUDING ALL); +CREATE TABLE incoming.model_runs (LIKE public.model_runs INCLUDING ALL); +CREATE TABLE incoming.model_downloads (LIKE public.model_downloads INCLUDING ALL); + +INSERT INTO incoming.people SELECT * FROM public.people; +INSERT INTO incoming.nodes SELECT * FROM public.nodes; +INSERT INTO incoming.versions SELECT * FROM public.versions; +INSERT INTO incoming.tags SELECT * FROM public.tags; +INSERT INTO incoming.tagged_nodes SELECT * FROM public.tagged_nodes; +INSERT INTO incoming.attachments SELECT * FROM public.attachments; +INSERT INTO incoming.spam_warnings SELECT * FROM public.spam_warnings; + +SET search_path TO incoming; + +-- 1. a brand new person +INSERT INTO people (id, email_address, first_name, last_name, created_at, updated_at) VALUES + (5, 'katherine@example.com', 'Katherine', 'Johnson', '2026-01-01 10:00:00', '2026-01-01 10:00:00'); + +-- 2. a new person reusing an already-migrated email; the newcomer must lose it +INSERT INTO people (id, email_address, first_name, last_name, created_at, updated_at) VALUES + (6, 'ada@example.com', 'Ada', 'Impostor', '2026-01-02 10:00:00', '2026-01-02 10:00:00'); + +-- 3. a profile edit that maps onto User columns +UPDATE people SET biography = 'Rewritten bio.', url = 'https://ada.example/new', + updated_at = '2026-01-03 10:00:00' WHERE id = 1; + +-- 4. a password reset: nothing initial-import.ts maps, so only updated_at moves +UPDATE people SET password = 'new-digest', updated_at = '2026-01-04 10:00:00' WHERE id = 2; + +-- 5. a new model with a version, a preview and a tag +INSERT INTO nodes (id, name, created_at, updated_at, visibility_id) VALUES + (14, 'Flocking', '2026-02-01 10:00:00', '2026-02-01 10:00:00', 1); +INSERT INTO versions (id, node_id, person_id, description, contents, created_at, updated_at) VALUES + (104, 14, 5, 'Initial upload', 'code@#$#@#$#@ui@#$#@#$#@flock info@#$#@#$#@shapes@#$#@#$#@NetLogo 6.4.0', '2026-02-01 10:00:00', '2026-02-01 10:00:00'); +INSERT INTO attachments (id, node_id, person_id, description, contents, filename, content_type, created_at, updated_at) VALUES + (405, 14, 5, 'Preview', '\x89504e470d0a1a0a04', 'flocking.png', 'preview', '2026-02-01 10:00:00', '2026-02-01 10:00:00'); + +-- 6. a node with no versions: initial-import.ts skips these, so the patch must too +INSERT INTO nodes (id, name, created_at, updated_at, visibility_id) VALUES + (15, 'Empty Draft', '2026-02-02 10:00:00', '2026-02-02 10:00:00', 1); + +-- 7. a node with two spam warnings: excluded, as initial-import.ts excludes it +INSERT INTO nodes (id, name, created_at, updated_at, visibility_id) VALUES + (16, 'Buy Cheap Pills', '2026-02-03 10:00:00', '2026-02-03 10:00:00', 1); +INSERT INTO versions (id, node_id, person_id, description, contents, created_at, updated_at) VALUES + (105, 16, 4, 'Initial upload', 'code@#$#@#$#@ui@#$#@#$#@spam@#$#@#$#@shapes@#$#@#$#@NetLogo 5.0.4', '2026-02-03 10:00:00', '2026-02-03 10:00:00'); +INSERT INTO spam_warnings (id, person_id, node_id, created_at, updated_at) VALUES + (500, 1, 16, '2026-02-04 10:00:00', '2026-02-04 10:00:00'), + (501, 2, 16, '2026-02-05 10:00:00', '2026-02-05 10:00:00'); + +-- 8. a new version on an already-migrated node, by a different author, whose +-- only preview is deleted in the same batch: the appended version must not +-- inherit a preview that no longer exists +DELETE FROM attachments WHERE id = 404; +-- 8. a new version on an already-migrated node, by a different author +INSERT INTO versions (id, node_id, person_id, description, contents, created_at, updated_at) VALUES + (106, 11, 3, 'Tuned parameters', 'code@#$#@#$#@ui@#$#@#$#@ant info v2@#$#@#$#@shapes@#$#@#$#@NetLogo 6.2.0', '2026-03-01 10:00:00', '2026-03-01 10:00:00'); +UPDATE nodes SET updated_at = '2026-03-01 10:00:00' WHERE id = 11; + +-- 9 + 10 + 11. on node 10: one attachment added, one removed, and the winning +-- preview removed so the preview falls back to the older one +INSERT INTO attachments (id, node_id, person_id, description, contents, filename, content_type, created_at, updated_at) VALUES + (406, 10, 1, 'Extra', '\x6e6c73206e6577', 'extra.nls', 'extension', '2026-03-02 10:00:00', '2026-03-02 10:00:00'); +DELETE FROM attachments WHERE id IN (401, 402); + +-- 12 + 13. node 12 renamed, made private, and given a tag +UPDATE nodes SET name = 'Schelling Segregation', visibility_id = 2, + updated_at = '2026-03-03 10:00:00' WHERE id = 12; +INSERT INTO tagged_nodes (id, node_id, tag_id, person_id, comment, created_at, updated_at) VALUES + (302, 12, 200, 3, '', '2026-03-03 10:00:00', '2026-03-03 10:00:00'); + +-- 14. a node deleted outright, versions and all +DELETE FROM versions WHERE node_id = 13; +DELETE FROM nodes WHERE id = 13; + +-- 15. a new tag whose name collides with an existing one once normalised +INSERT INTO tags (id, name, person_id, created_at, updated_at) VALUES + (202, 'BIOLOGY', 3, '2026-03-04 10:00:00', '2026-03-04 10:00:00'); +INSERT INTO tagged_nodes (id, node_id, tag_id, person_id, comment, created_at, updated_at) VALUES + (303, 11, 202, 3, '', '2026-03-04 10:00:00', '2026-03-04 10:00:00'); + +-- 16. a genuinely new tag, used by the new model +INSERT INTO tags (id, name, person_id, created_at, updated_at) VALUES + (203, 'chemistry', 5, '2026-03-05 10:00:00', '2026-03-05 10:00:00'); +INSERT INTO tagged_nodes (id, node_id, tag_id, person_id, comment, created_at, updated_at) VALUES + (304, 14, 203, 5, '', '2026-03-05 10:00:00', '2026-03-05 10:00:00'); + +-- 17. an existing version edited in place +UPDATE versions SET description = 'Corrected upload', + contents = 'code@#$#@#$#@ui@#$#@#$#@wolf info v2@#$#@#$#@shapes@#$#@#$#@NetLogo 5.0.5' + WHERE id = 100; diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/dump.ts b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/dump.ts new file mode 100644 index 00000000..bcb8270d --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/dump.ts @@ -0,0 +1,93 @@ +/** Canonical, uuid-free dump of a target DB so two of them can be compared. */ +import { PrismaPg } from '@prisma/adapter-pg'; +import { PrismaClient } from '../../../generated/prisma/client.js'; + +const prisma = new PrismaClient({ + adapter: new PrismaPg({ connectionString: process.env['DATABASE_URL']! }), +}); + +const UUID = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi; +const norm = (key: string | null) => (key === null ? null : key.replace(UUID, '')); +// A version file keeps the node name it was uploaded under; renaming a node in +// the legacy app does not move objects in storage, so the trailing filename can +// legitimately differ from a from-scratch archive. Compare the path only. +const normVersionKey = (key: string | null) => + key === null ? null : norm(key)!.replace(/\/[^/]*$/, '/'); +const iso = (d: Date | null) => (d === null ? null : d.toISOString()); + +async function main() { + const users = await prisma.user.findMany({ + where: { legacyId: { not: null } }, + orderBy: { legacyId: 'asc' }, + }); + + const models = await prisma.model.findMany({ + where: { legacyId: { not: null } }, + orderBy: { legacyId: 'asc' }, + include: { + versions: { + orderBy: { versionNumber: 'asc' }, + include: { tags: { include: { tag: true } } }, + }, + authors: { include: { user: true } }, + additionalFiles: true, + }, + }); + + const tags = await prisma.tag.findMany({ orderBy: { name: 'asc' } }); + + console.log( + JSON.stringify( + { + users: users.map((u) => ({ + legacyId: u.legacyId, + email: u.email, + name: u.name, + bio: u.bio, + dob: iso(u.dob), + image: norm(u.image), + socialLinks: u.socialLinks, + createdAt: iso(u.createdAt), + softDeleted: u.deletedAt !== null, + })), + tags: tags.map((t) => ({ legacyId: t.legacyId, name: t.name, displayName: t.displayName })), + softDeletedModels: models.filter((m) => m.deletedAt).map((m) => m.legacyId), + models: models + .filter((m) => !m.deletedAt) + .map((m) => ({ + legacyId: m.legacyId, + visibility: m.visibility, + isEndorsed: m.isEndorsed, + createdAt: iso(m.createdAt), + latestVersionNumber: m.latestVersionNumber, + authors: m.authors + .map((a) => ({ userLegacyId: a.user.legacyId, role: a.role })) + .sort((a, b) => (a.userLegacyId ?? 0) - (b.userLegacyId ?? 0)), + versions: m.versions.map((v) => ({ + versionNumber: v.versionNumber, + title: v.title, + description: v.description, + netlogoFileKey: normVersionKey(v.netlogoFileKey), + netlogoVersion: v.netlogoVersion, + infoTab: v.infoTab, + previewImageFileKey: norm(v.previewImageFileKey), + createdAt: iso(v.createdAt), + finalizedAt: iso(v.finalizedAt), + tags: v.tags.map((t) => t.tag.name).sort(), + })), + additionalFiles: m.additionalFiles + .map((f) => ({ + fileKey: norm(f.fileKey), + taggedVersionNumber: f.taggedVersionNumber, + createdAt: iso(f.createdAt), + })) + .sort((a, b) => (a.fileKey! < b.fileKey! ? -1 : 1)), + })), + }, + null, + 2, + ), + ); +} + +main().finally(() => prisma.$disconnect()); diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/run.sh b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/run.sh new file mode 100755 index 00000000..c2066dbb --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/rehearsal/run.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# Full rehearsal: +# archive(baseline) + patch(diff) must equal archive(incoming) +set -euo pipefail + +HERE="$(cd "$(dirname "$0")" && pwd)" +APP="$(cd "$HERE/../.." && pwd)" +cd "$APP" + +export PGHOST=127.0.0.1 PGPORT=5432 PGUSER=admin PGPASSWORD=test +export IP_HASH_SALT=rehearsal-salt +BASE="postgresql://admin:test@127.0.0.1:5432" +LEGACY_DB=rehearsal_legacy +PATCHED_DB=rehearsal_patched +FRESH_DB=rehearsal_fresh +DIFF_DIR="${DIFF_DIR:-$HERE/.work/diff}" +WORK="$HERE/.work" +mkdir -p "$WORK" + +step() { printf '\n\033[1m== %s ==\033[0m\n' "$1"; } + +step "1. legacy database: baseline (public) + fresh dump (incoming)" +psql -d postgres -qc "DROP DATABASE IF EXISTS $LEGACY_DB" >/dev/null +psql -d postgres -qc "CREATE DATABASE $LEGACY_DB" >/dev/null +psql -d "$LEGACY_DB" -q -v ON_ERROR_STOP=1 -f "$HERE/01-baseline.sql" +psql -d "$LEGACY_DB" -q -v ON_ERROR_STOP=1 -f "$HERE/02-incoming.sql" + +step "2. two empty target databases on the current schema" +for db in "$PATCHED_DB" "$FRESH_DB"; do + psql -d postgres -qc "DROP DATABASE IF EXISTS $db" >/dev/null + psql -d postgres -qc "CREATE DATABASE $db" >/dev/null + DATABASE_URL="$BASE/$db" npx prisma migrate deploy >/dev/null +done + +step "3. archive the baseline into the patch target (what production looks like today)" +rm -rf "$WORK/out-archive" +DATABASE_URL="$BASE/$PATCHED_DB" LEGACY_DATABASE_URL="$BASE/$LEGACY_DB" LEGACY_SCHEMA=public \ + OUTPUT_DIR="$WORK/out-archive" npx tsx prisma/legacy-migration/initial-import.ts | tail -3 + +step "4. diff baseline against the fresh dump" +rm -rf "$DIFF_DIR" +LEGACY_DB="$LEGACY_DB" DIFF_DIR="$DIFF_DIR" ./prisma/legacy-migration/diffdb.sh + +step "5. dry run" +DATABASE_URL="$BASE/$PATCHED_DB" LEGACY_DATABASE_URL="$BASE/$LEGACY_DB" LEGACY_SCHEMA=incoming \ + DIFF_DIR="$DIFF_DIR" OUTPUT_DIR="$WORK/out-patch" npx tsx prisma/legacy-migration/apply-diff.ts + +step "6. apply" +DATABASE_URL="$BASE/$PATCHED_DB" LEGACY_DATABASE_URL="$BASE/$LEGACY_DB" LEGACY_SCHEMA=incoming \ + DIFF_DIR="$DIFF_DIR" OUTPUT_DIR="$WORK/out-patch" npx tsx prisma/legacy-migration/apply-diff.ts --apply --skip-upload + +step "7. archive the fresh dump into a second target, from scratch" +rm -rf "$WORK/out-fresh" +DATABASE_URL="$BASE/$FRESH_DB" LEGACY_DATABASE_URL="$BASE/$LEGACY_DB" LEGACY_SCHEMA=incoming \ + OUTPUT_DIR="$WORK/out-fresh" npx tsx prisma/legacy-migration/initial-import.ts | tail -3 + +step "8. compare" +DATABASE_URL="$BASE/$PATCHED_DB" npx tsx prisma/legacy-migration/rehearsal/dump.ts > "$WORK/patched.json" +DATABASE_URL="$BASE/$FRESH_DB" npx tsx prisma/legacy-migration/rehearsal/dump.ts > "$WORK/fresh.json" + +# A soft-deleted model is by design absent from an archive of the new snapshot, +# so assert it separately and compare everything else. +soft=$(node -e "console.log(JSON.stringify(require('$WORK/patched.json').softDeletedModels))") +if [ "$soft" != "[13]" ]; then + printf '\n\033[31mFAIL\033[0m expected model 13 soft deleted, got %s\n' "$soft" + exit 1 +fi +printf 'soft-deleted models: %s (node 13 was deleted in the legacy app)\n' "$soft" + +for f in fresh patched; do + node -e "const d=require('$WORK/$f.json'); delete d.softDeletedModels; console.log(JSON.stringify(d,null,2))" \ + > "$WORK/$f.cmp.json" +done + +if diff -u "$WORK/fresh.cmp.json" "$WORK/patched.cmp.json"; then + printf '\n\033[32mPASS\033[0m patched target is identical to a from-scratch archive of the new snapshot\n' +else + printf '\n\033[31mFAIL\033[0m see the diff above (- fresh archive, + patched)\n' + exit 1 +fi diff --git a/apps/modeling-commons-backend/prisma/legacy-migration/schema.sql b/apps/modeling-commons-backend/prisma/legacy-migration/schema.sql new file mode 100644 index 00000000..e2c2628e --- /dev/null +++ b/apps/modeling-commons-backend/prisma/legacy-migration/schema.sql @@ -0,0 +1,2327 @@ +-- +-- PostgreSQL database dump +-- + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET client_min_messages = warning; + +-- +-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; + + +-- +-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: - +-- + +COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language'; + + +-- +-- Name: statinfo; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.statinfo AS ( + word text, + ndoc integer, + nentry integer +); + + +-- +-- Name: tokenout; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.tokenout AS ( + tokid integer, + token text +); + + +-- +-- Name: tokentype; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.tokentype AS ( + tokid integer, + alias text, + descr text +); + + +-- +-- Name: tsdebug; Type: TYPE; Schema: public; Owner: - +-- + +CREATE TYPE public.tsdebug AS ( + ts_name text, + tok_type text, + description text, + token text, + dict_name text[] +); + + +-- +-- Name: _get_parser_from_curcfg(); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public._get_parser_from_curcfg() RETURNS text + LANGUAGE sql IMMUTABLE STRICT + AS $$ select prs_name from pg_ts_cfg where oid = show_curcfg() $$; + + +-- +-- Name: get_password_from_email(character varying); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.get_password_from_email(email character varying) RETURNS TABLE(id integer, first_name character varying, last_name character varying, password character varying, salt character varying) + LANGUAGE plpgsql + AS $$ +BEGIN + RETURN QUERY +SELECT + id, first_name, last_name, password, salt + FROM + people + WHERE + email_address = email; +END; $$; + + +-- +-- Name: ts_debug(text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.ts_debug(text) RETURNS SETOF public.tsdebug + LANGUAGE sql STRICT + AS $_$ +select + m.ts_name, + t.alias as tok_type, + t.descr as description, + p.token, + m.dict_name, + strip(to_tsvector(p.token)) as tsvector +from + parse( _get_parser_from_curcfg(), $1 ) as p, + token_type() as t, + pg_ts_cfgmap as m, + pg_ts_cfg as c +where + t.tokid=p.tokid and + t.alias = m.tok_alias and + m.ts_name=c.ts_name and + c.oid=show_curcfg() +$_$; + + +-- +-- Name: wow(text); Type: FUNCTION; Schema: public; Owner: - +-- + +CREATE FUNCTION public.wow(text) RETURNS text + LANGUAGE sql + AS $_$select $1 || ' copyright'; $_$; + + +SET default_tablespace = ''; + +SET default_with_oids = false; + +-- +-- Name: attachments; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.attachments ( + id integer NOT NULL, + node_id integer NOT NULL, + person_id integer NOT NULL, + description character varying(255) NOT NULL, + contents bytea NOT NULL, + filename character varying(255) NOT NULL, + content_type character varying(255) NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: attachments_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.attachments_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: attachments_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.attachments_id_seq OWNED BY public.attachments.id; + + +-- +-- Name: nodes; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.nodes ( + id integer NOT NULL, + parent_id integer, + name text NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone, + visibility_id integer DEFAULT 1 NOT NULL, + changeability_id integer DEFAULT 1 NOT NULL, + group_id integer, + wants_help boolean DEFAULT false NOT NULL +); + + +-- +-- Name: ccl_model_creations_per_month; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.ccl_model_creations_per_month AS + SELECT to_char(nodes.created_at, 'YY MM'::text) AS yearmonth, + count(*) AS count + FROM public.nodes + WHERE (nodes.group_id = 2) + GROUP BY to_char(nodes.created_at, 'YY MM'::text) + ORDER BY to_char(nodes.created_at, 'YY MM'::text); + + +-- +-- Name: collaborations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.collaborations ( + id integer NOT NULL, + person_id integer, + node_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone, + collaborator_type_id integer +); + + +-- +-- Name: collaborations_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.collaborations_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: collaborations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.collaborations_id_seq OWNED BY public.collaborations.id; + + +-- +-- Name: collaborator_types; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.collaborator_types ( + id integer NOT NULL, + name character varying(255), + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: collaborator_types_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.collaborator_types_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: collaborator_types_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.collaborator_types_id_seq OWNED BY public.collaborator_types.id; + + +-- +-- Name: logged_actions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.logged_actions ( + id integer NOT NULL, + person_id integer, + logged_at timestamp without time zone, + message text, + ip_address character varying(255), + browser_info text, + url text, + params text NOT NULL, + session text, + cookies text, + flash text, + referrer text, + node_id integer, + controller text, + action text, + is_searchbot boolean DEFAULT false NOT NULL +); + + +-- +-- Name: people; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.people ( + id integer NOT NULL, + email_address character varying(255), + first_name character varying(255), + last_name character varying(255), + password character varying(255), + administrator boolean, + created_at timestamp without time zone, + updated_at timestamp without time zone, + avatar_file_name text, + avatar_content_type character varying(255), + avatar_file_size integer, + avatar_updated_at timestamp without time zone, + salt character varying(255), + registration_consent boolean DEFAULT false, + sex character varying(255), + birthdate date, + country_name character varying(255), + send_site_updates boolean DEFAULT true, + send_model_updates boolean DEFAULT true, + send_tag_updates boolean DEFAULT true, + url character varying(255), + biography text, + show_email_address boolean DEFAULT false +); + + +-- +-- Name: versions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.versions ( + id integer NOT NULL, + node_id integer NOT NULL, + person_id integer NOT NULL, + description text NOT NULL, + contents text NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: create_view_models_view; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.create_view_models_view AS + SELECT p.id, + ( SELECT min(v.created_at) AS min + FROM public.versions v + WHERE (v.person_id = p.id)) AS earliest_version_creation, + ( SELECT min(l.logged_at) AS min + FROM public.logged_actions l + WHERE (((p.id = l.person_id) AND (l.controller = 'browse'::text)) AND (l.action = 'one_model'::text))) AS earliest_view_model + FROM public.people p + ORDER BY p.id; + + +-- +-- Name: email_recommendations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.email_recommendations ( + id integer NOT NULL, + person_id integer, + recipient_email_address character varying(255), + node_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: email_recommendations_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.email_recommendations_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: email_recommendations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.email_recommendations_id_seq OWNED BY public.email_recommendations.id; + + +-- +-- Name: foobar; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.foobar ( + id integer NOT NULL, + ip_address text, + new_inet inet +); + + +-- +-- Name: foobar_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.foobar_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: foobar_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.foobar_id_seq OWNED BY public.foobar.id; + + +-- +-- Name: groups; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.groups ( + id integer NOT NULL, + name character varying(255), + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: groups_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.groups_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: groups_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.groups_id_seq OWNED BY public.groups.id; + + +-- +-- Name: hits_and_days_view; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.hits_and_days_view AS + SELECT count(*) AS count, + (logged_actions.logged_at)::date AS logged_at, + date_part('dow'::text, (logged_actions.logged_at)::date) AS date_part + FROM public.logged_actions + WHERE (logged_actions.is_searchbot = false) + GROUP BY (logged_actions.logged_at)::date + ORDER BY (logged_actions.logged_at)::date; + + +-- +-- Name: hits_and_months_view; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.hits_and_months_view AS + SELECT count(*) AS count, + ((date_part('year'::text, (logged_actions.logged_at)::date) || '-'::text) || date_part('month'::text, (logged_actions.logged_at)::date)) + FROM public.logged_actions + WHERE (logged_actions.is_searchbot = false) + GROUP BY ((date_part('year'::text, (logged_actions.logged_at)::date) || '-'::text) || date_part('month'::text, (logged_actions.logged_at)::date)) + ORDER BY ((date_part('year'::text, (logged_actions.logged_at)::date) || '-'::text) || date_part('month'::text, (logged_actions.logged_at)::date)); + + +-- +-- Name: ip_locations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.ip_locations ( + id integer NOT NULL, + ip_address character varying(255), + location text, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL +); + + +-- +-- Name: ip_locations_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.ip_locations_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: ip_locations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.ip_locations_id_seq OWNED BY public.ip_locations.id; + + +-- +-- Name: logged_actions_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.logged_actions_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: logged_actions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.logged_actions_id_seq OWNED BY public.logged_actions.id; + + +-- +-- Name: memberships; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.memberships ( + id integer NOT NULL, + person_id integer, + group_id integer, + is_administrator boolean DEFAULT false, + created_at timestamp without time zone, + updated_at timestamp without time zone, + status text DEFAULT 'pending'::text NOT NULL +); + + +-- +-- Name: memberships_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.memberships_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: memberships_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.memberships_id_seq OWNED BY public.memberships.id; + + +-- +-- Name: model_collaborator_countries; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.model_collaborator_countries ( + id integer, + countries text[] +); + + +-- +-- Name: model_downloads; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.model_downloads ( + logged_at timestamp without time zone, + ip_address text, + node_id integer, + person_id integer +); + + +-- +-- Name: model_runs; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.model_runs ( + logged_at timestamp without time zone, + ip_address text, + node_id integer, + person_id integer +); + + +-- +-- Name: model_view_counts; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.model_view_counts ( + count bigint, + node_id integer +); + + +-- +-- Name: model_view_download_countries; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.model_view_download_countries ( + node_id integer, + country_codes text[] +); + + +-- +-- Name: model_views; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.model_views ( + logged_at timestamp without time zone, + ip_address text, + node_id integer, + person_id integer +); + + +-- +-- Name: month_year_referrers; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.month_year_referrers ( + to_char text, + referrer text, + controller text, + action text +); + + +-- +-- Name: news_items; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.news_items ( + id integer NOT NULL, + title character varying(255), + body text, + person_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: news_items_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.news_items_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: news_items_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.news_items_id_seq OWNED BY public.news_items.id; + + +-- +-- Name: node_projects; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.node_projects ( + id integer NOT NULL, + project_id integer, + node_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: node_projects_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.node_projects_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: node_projects_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.node_projects_id_seq OWNED BY public.node_projects.id; + + +-- +-- Name: nodes_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.nodes_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: nodes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.nodes_id_seq OWNED BY public.nodes.id; + + +-- +-- Name: non_ccl_model_creations_per_month; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.non_ccl_model_creations_per_month AS + SELECT to_char(nodes.created_at, 'YY MM'::text) AS yearmonth, + count(*) AS count + FROM public.nodes + WHERE (nodes.group_id <> 2) + GROUP BY to_char(nodes.created_at, 'YY MM'::text) + ORDER BY to_char(nodes.created_at, 'YY MM'::text); + + +-- +-- Name: non_member_collaborations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.non_member_collaborations ( + id integer NOT NULL, + non_member_collaborator_id integer, + node_id integer, + collaborator_type_id integer, + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL, + person_id integer NOT NULL +); + + +-- +-- Name: non_member_collaborations_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.non_member_collaborations_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: non_member_collaborations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.non_member_collaborations_id_seq OWNED BY public.non_member_collaborations.id; + + +-- +-- Name: non_member_collaborators; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.non_member_collaborators ( + id integer NOT NULL, + email character varying(255), + name character varying(255), + created_at timestamp without time zone NOT NULL, + updated_at timestamp without time zone NOT NULL +); + + +-- +-- Name: non_member_collaborators_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.non_member_collaborators_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: non_member_collaborators_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.non_member_collaborators_id_seq OWNED BY public.non_member_collaborators.id; + + +-- +-- Name: people_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.people_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: people_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.people_id_seq OWNED BY public.people.id; + + +-- +-- Name: permission_settings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.permission_settings ( + id integer NOT NULL, + name character varying(255) NOT NULL, + created_at timestamp without time zone, + updated_at timestamp without time zone, + short_form character varying(255) +); + + +-- +-- Name: permission_settings_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.permission_settings_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: permission_settings_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.permission_settings_id_seq OWNED BY public.permission_settings.id; + + +-- +-- Name: permissions_changed_log_view; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.permissions_changed_log_view ( + count bigint, + id text +); + + +SET default_with_oids = true; + +-- +-- Name: pg_ts_cfg; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.pg_ts_cfg ( + ts_name text NOT NULL, + prs_name text NOT NULL, + locale text +); + + +-- +-- Name: pg_ts_cfgmap; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.pg_ts_cfgmap ( + ts_name text NOT NULL, + tok_alias text NOT NULL, + dict_name text[] +); + + +-- +-- Name: pg_ts_dict; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.pg_ts_dict ( + dict_name text NOT NULL, + dict_init regprocedure, + dict_initoption text, + dict_lexize regprocedure NOT NULL, + dict_comment text +); + + +-- +-- Name: pg_ts_parser; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.pg_ts_parser ( + prs_name text NOT NULL, + prs_start regprocedure NOT NULL, + prs_nexttoken regprocedure NOT NULL, + prs_end regprocedure NOT NULL, + prs_headline regprocedure NOT NULL, + prs_lextype regprocedure NOT NULL, + prs_comment text +); + + +-- +-- Name: popular_pages_view; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.popular_pages_view AS + SELECT count(*) AS count, + logged_actions.controller, + logged_actions.action + FROM public.logged_actions + WHERE (logged_actions.is_searchbot = false) + GROUP BY logged_actions.controller, logged_actions.action + ORDER BY count(*) DESC; + + +SET default_with_oids = false; + +-- +-- Name: postings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.postings ( + id integer NOT NULL, + person_id integer, + node_id integer, + title character varying(255), + body text, + created_at timestamp without time zone, + updated_at timestamp without time zone, + parent_id integer, + is_question boolean DEFAULT false NOT NULL, + deleted_at timestamp without time zone, + answered_at timestamp without time zone +); + + +-- +-- Name: posting_count_view; Type: VIEW; Schema: public; Owner: - +-- + +CREATE VIEW public.posting_count_view AS + SELECT count(*) AS count, + postings.node_id + FROM public.postings + WHERE (postings.deleted_at IS NULL) + GROUP BY postings.node_id + HAVING (count(*) > 2) + ORDER BY count(*) DESC; + + +-- +-- Name: postings_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.postings_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: postings_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.postings_id_seq OWNED BY public.postings.id; + + +-- +-- Name: projects; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.projects ( + id integer NOT NULL, + name character varying(255), + created_at timestamp without time zone, + updated_at timestamp without time zone, + person_id integer, + group_id integer, + visibility_id integer, + changeability_id integer +); + + +-- +-- Name: projects_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.projects_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: projects_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.projects_id_seq OWNED BY public.projects.id; + + +-- +-- Name: recommendations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.recommendations ( + id integer NOT NULL, + node_id integer, + person_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: recommendations_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.recommendations_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: recommendations_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.recommendations_id_seq OWNED BY public.recommendations.id; + + +-- +-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.schema_migrations ( + version character varying(255) NOT NULL +); + + +-- +-- Name: sessions; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.sessions ( + id integer NOT NULL, + session_id text NOT NULL, + data text, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: sessions_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.sessions_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: sessions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.sessions_id_seq OWNED BY public.sessions.id; + + +-- +-- Name: spam_warnings; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.spam_warnings ( + id integer NOT NULL, + person_id integer, + node_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: spam_warnings_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.spam_warnings_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: spam_warnings_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.spam_warnings_id_seq OWNED BY public.spam_warnings.id; + + +-- +-- Name: tagged_nodes; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.tagged_nodes ( + id integer NOT NULL, + node_id integer, + tag_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone, + person_id integer, + comment text +); + + +-- +-- Name: tagged_models_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.tagged_models_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: tagged_models_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.tagged_models_id_seq OWNED BY public.tagged_nodes.id; + + +-- +-- Name: tags; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.tags ( + id integer NOT NULL, + name character varying(255), + person_id integer, + created_at timestamp without time zone, + updated_at timestamp without time zone +); + + +-- +-- Name: tags_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.tags_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: tags_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.tags_id_seq OWNED BY public.tags.id; + + +-- +-- Name: test_tsquery; Type: TABLE; Schema: public; Owner: -; Tablespace: +-- + +CREATE TABLE public.test_tsquery ( + txtkeyword text, + txtsample text +); + + +-- +-- Name: versions_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.versions_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: versions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.versions_id_seq OWNED BY public.versions.id; + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.attachments ALTER COLUMN id SET DEFAULT nextval('public.attachments_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.collaborations ALTER COLUMN id SET DEFAULT nextval('public.collaborations_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.collaborator_types ALTER COLUMN id SET DEFAULT nextval('public.collaborator_types_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.email_recommendations ALTER COLUMN id SET DEFAULT nextval('public.email_recommendations_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.foobar ALTER COLUMN id SET DEFAULT nextval('public.foobar_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.groups ALTER COLUMN id SET DEFAULT nextval('public.groups_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.ip_locations ALTER COLUMN id SET DEFAULT nextval('public.ip_locations_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.logged_actions ALTER COLUMN id SET DEFAULT nextval('public.logged_actions_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.memberships ALTER COLUMN id SET DEFAULT nextval('public.memberships_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.news_items ALTER COLUMN id SET DEFAULT nextval('public.news_items_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.node_projects ALTER COLUMN id SET DEFAULT nextval('public.node_projects_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.nodes ALTER COLUMN id SET DEFAULT nextval('public.nodes_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.non_member_collaborations ALTER COLUMN id SET DEFAULT nextval('public.non_member_collaborations_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.non_member_collaborators ALTER COLUMN id SET DEFAULT nextval('public.non_member_collaborators_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.people ALTER COLUMN id SET DEFAULT nextval('public.people_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.permission_settings ALTER COLUMN id SET DEFAULT nextval('public.permission_settings_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.postings ALTER COLUMN id SET DEFAULT nextval('public.postings_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.projects ALTER COLUMN id SET DEFAULT nextval('public.projects_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.recommendations ALTER COLUMN id SET DEFAULT nextval('public.recommendations_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.sessions ALTER COLUMN id SET DEFAULT nextval('public.sessions_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.spam_warnings ALTER COLUMN id SET DEFAULT nextval('public.spam_warnings_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.tagged_nodes ALTER COLUMN id SET DEFAULT nextval('public.tagged_models_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.tags ALTER COLUMN id SET DEFAULT nextval('public.tags_id_seq'::regclass); + + +-- +-- Name: id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.versions ALTER COLUMN id SET DEFAULT nextval('public.versions_id_seq'::regclass); + + +-- +-- Name: attachments_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.attachments + ADD CONSTRAINT attachments_pkey PRIMARY KEY (id); + + +-- +-- Name: collaborations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.collaborations + ADD CONSTRAINT collaborations_pkey PRIMARY KEY (id); + + +-- +-- Name: collaborator_types_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.collaborator_types + ADD CONSTRAINT collaborator_types_pkey PRIMARY KEY (id); + + +-- +-- Name: email_recommendations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.email_recommendations + ADD CONSTRAINT email_recommendations_pkey PRIMARY KEY (id); + + +-- +-- Name: groups_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.groups + ADD CONSTRAINT groups_pkey PRIMARY KEY (id); + + +-- +-- Name: ip_locations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.ip_locations + ADD CONSTRAINT ip_locations_pkey PRIMARY KEY (id); + + +-- +-- Name: logged_actions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.logged_actions + ADD CONSTRAINT logged_actions_pkey PRIMARY KEY (id); + + +-- +-- Name: memberships_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.memberships + ADD CONSTRAINT memberships_pkey PRIMARY KEY (id); + + +-- +-- Name: news_items_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.news_items + ADD CONSTRAINT news_items_pkey PRIMARY KEY (id); + + +-- +-- Name: node_projects_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.node_projects + ADD CONSTRAINT node_projects_pkey PRIMARY KEY (id); + + +-- +-- Name: nodes_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.nodes + ADD CONSTRAINT nodes_pkey PRIMARY KEY (id); + + +-- +-- Name: non_member_collaborations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.non_member_collaborations + ADD CONSTRAINT non_member_collaborations_pkey PRIMARY KEY (id); + + +-- +-- Name: non_member_collaborators_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.non_member_collaborators + ADD CONSTRAINT non_member_collaborators_pkey PRIMARY KEY (id); + + +-- +-- Name: people_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.people + ADD CONSTRAINT people_pkey PRIMARY KEY (id); + + +-- +-- Name: permission_settings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.permission_settings + ADD CONSTRAINT permission_settings_pkey PRIMARY KEY (id); + + +-- +-- Name: pg_ts_cfg_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.pg_ts_cfg + ADD CONSTRAINT pg_ts_cfg_pkey PRIMARY KEY (ts_name); + + +-- +-- Name: pg_ts_cfgmap_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.pg_ts_cfgmap + ADD CONSTRAINT pg_ts_cfgmap_pkey PRIMARY KEY (ts_name, tok_alias); + + +-- +-- Name: pg_ts_dict_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.pg_ts_dict + ADD CONSTRAINT pg_ts_dict_pkey PRIMARY KEY (dict_name); + + +-- +-- Name: pg_ts_parser_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.pg_ts_parser + ADD CONSTRAINT pg_ts_parser_pkey PRIMARY KEY (prs_name); + + +-- +-- Name: postings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.postings + ADD CONSTRAINT postings_pkey PRIMARY KEY (id); + + +-- +-- Name: projects_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.projects + ADD CONSTRAINT projects_pkey PRIMARY KEY (id); + + +-- +-- Name: recommendations_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.recommendations + ADD CONSTRAINT recommendations_pkey PRIMARY KEY (id); + + +-- +-- Name: sessions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.sessions + ADD CONSTRAINT sessions_pkey PRIMARY KEY (id); + + +-- +-- Name: spam_warnings_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.spam_warnings + ADD CONSTRAINT spam_warnings_pkey PRIMARY KEY (id); + + +-- +-- Name: tagged_models_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.tagged_nodes + ADD CONSTRAINT tagged_models_pkey PRIMARY KEY (id); + + +-- +-- Name: tags_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.tags + ADD CONSTRAINT tags_pkey PRIMARY KEY (id); + + +-- +-- Name: versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: +-- + +ALTER TABLE ONLY public.versions + ADD CONSTRAINT versions_pkey PRIMARY KEY (id); + + +-- +-- Name: index_attachments_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_attachments_on_node_id ON public.attachments USING btree (node_id); + + +-- +-- Name: index_attachments_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_attachments_on_person_id ON public.attachments USING btree (person_id); + + +-- +-- Name: index_attachments_on_type; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_attachments_on_type ON public.attachments USING btree (content_type); + + +-- +-- Name: index_email_recommendations_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_email_recommendations_on_node_id ON public.email_recommendations USING btree (node_id); + + +-- +-- Name: index_email_recommendations_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_email_recommendations_on_person_id ON public.email_recommendations USING btree (person_id); + + +-- +-- Name: index_ip_locations_on_ip_address; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX index_ip_locations_on_ip_address ON public.ip_locations USING btree (ip_address); + + +-- +-- Name: index_logged_actions_on_action; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_action ON public.logged_actions USING btree (action); + + +-- +-- Name: index_logged_actions_on_controller; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_controller ON public.logged_actions USING btree (controller); + + +-- +-- Name: index_logged_actions_on_ip_address; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_ip_address ON public.logged_actions USING btree (ip_address); + + +-- +-- Name: index_logged_actions_on_is_searchbot; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_is_searchbot ON public.logged_actions USING btree (is_searchbot); + + +-- +-- Name: index_logged_actions_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_node_id ON public.logged_actions USING btree (node_id); + + +-- +-- Name: index_logged_actions_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_person_id ON public.logged_actions USING btree (person_id); + + +-- +-- Name: index_logged_actions_on_referrer; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_referrer ON public.logged_actions USING btree (referrer); + + +-- +-- Name: index_logged_actions_on_url; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_logged_actions_on_url ON public.logged_actions USING btree (url); + + +-- +-- Name: index_memberships_on_group_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_memberships_on_group_id ON public.memberships USING btree (group_id); + + +-- +-- Name: index_memberships_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_memberships_on_person_id ON public.memberships USING btree (person_id); + + +-- +-- Name: index_memberships_on_person_id_and_group_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX index_memberships_on_person_id_and_group_id ON public.memberships USING btree (person_id, group_id); + + +-- +-- Name: index_news_items_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_news_items_on_created_at ON public.news_items USING btree (created_at); + + +-- +-- Name: index_news_items_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_news_items_on_person_id ON public.news_items USING btree (person_id); + + +-- +-- Name: index_news_items_on_title; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_news_items_on_title ON public.news_items USING btree (title); + + +-- +-- Name: index_node_projects_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_node_projects_on_node_id ON public.node_projects USING btree (node_id); + + +-- +-- Name: index_node_projects_on_project_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_node_projects_on_project_id ON public.node_projects USING btree (project_id); + + +-- +-- Name: index_nodes_on_changeability_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_nodes_on_changeability_id ON public.nodes USING btree (changeability_id); + + +-- +-- Name: index_nodes_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_nodes_on_created_at ON public.nodes USING btree (created_at); + + +-- +-- Name: index_nodes_on_group_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_nodes_on_group_id ON public.nodes USING btree (group_id); + + +-- +-- Name: index_nodes_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_nodes_on_name ON public.nodes USING btree (name); + + +-- +-- Name: index_nodes_on_parent_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_nodes_on_parent_id ON public.nodes USING btree (parent_id); + + +-- +-- Name: index_nodes_on_visibility_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_nodes_on_visibility_id ON public.nodes USING btree (visibility_id); + + +-- +-- Name: index_nodes_on_wants_help; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_nodes_on_wants_help ON public.nodes USING btree (wants_help); + + +-- +-- Name: index_non_member_collaborations_on_collaborator_type_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_non_member_collaborations_on_collaborator_type_id ON public.non_member_collaborations USING btree (collaborator_type_id); + + +-- +-- Name: index_non_member_collaborations_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_non_member_collaborations_on_node_id ON public.non_member_collaborations USING btree (node_id); + + +-- +-- Name: index_non_member_collaborations_on_non_member_collaborator_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_non_member_collaborations_on_non_member_collaborator_id ON public.non_member_collaborations USING btree (non_member_collaborator_id); + + +-- +-- Name: index_non_member_collaborators_on_email; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX index_non_member_collaborators_on_email ON public.non_member_collaborators USING btree (email); + + +-- +-- Name: index_non_member_collaborators_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_non_member_collaborators_on_name ON public.non_member_collaborators USING btree (name); + + +-- +-- Name: index_people_on_email_address; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_people_on_email_address ON public.people USING btree (email_address); + + +-- +-- Name: index_people_on_first_name; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_people_on_first_name ON public.people USING btree (first_name); + + +-- +-- Name: index_people_on_last_name; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_people_on_last_name ON public.people USING btree (last_name); + + +-- +-- Name: index_people_on_registration_consent; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_people_on_registration_consent ON public.people USING btree (registration_consent); + + +-- +-- Name: index_permission_settings_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_permission_settings_on_name ON public.permission_settings USING btree (name); + + +-- +-- Name: index_postings_on_body; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_postings_on_body ON public.postings USING btree (body); + + +-- +-- Name: index_postings_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_postings_on_created_at ON public.postings USING btree (created_at); + + +-- +-- Name: index_postings_on_nlmodel_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_postings_on_nlmodel_id ON public.postings USING btree (node_id); + + +-- +-- Name: index_postings_on_parent_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_postings_on_parent_id ON public.postings USING btree (parent_id); + + +-- +-- Name: index_postings_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_postings_on_person_id ON public.postings USING btree (person_id); + + +-- +-- Name: index_postings_on_title; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_postings_on_title ON public.postings USING btree (title); + + +-- +-- Name: index_postings_on_updated_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_postings_on_updated_at ON public.postings USING btree (updated_at); + + +-- +-- Name: index_projects_on_changeability_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_projects_on_changeability_id ON public.projects USING btree (changeability_id); + + +-- +-- Name: index_projects_on_group_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_projects_on_group_id ON public.projects USING btree (group_id); + + +-- +-- Name: index_projects_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_projects_on_person_id ON public.projects USING btree (person_id); + + +-- +-- Name: index_projects_on_visibility_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_projects_on_visibility_id ON public.projects USING btree (visibility_id); + + +-- +-- Name: index_recommendations_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_recommendations_on_node_id ON public.recommendations USING btree (node_id); + + +-- +-- Name: index_recommendations_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_recommendations_on_person_id ON public.recommendations USING btree (person_id); + + +-- +-- Name: index_sessions_on_session_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_sessions_on_session_id ON public.sessions USING btree (session_id); + + +-- +-- Name: index_sessions_on_updated_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_sessions_on_updated_at ON public.sessions USING btree (updated_at); + + +-- +-- Name: index_spam_warnings_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_spam_warnings_on_node_id ON public.spam_warnings USING btree (node_id); + + +-- +-- Name: index_spam_warnings_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_spam_warnings_on_person_id ON public.spam_warnings USING btree (person_id); + + +-- +-- Name: index_tagged_nodes_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tagged_nodes_on_created_at ON public.tagged_nodes USING btree (created_at); + + +-- +-- Name: index_tagged_nodes_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tagged_nodes_on_node_id ON public.tagged_nodes USING btree (node_id); + + +-- +-- Name: index_tagged_nodes_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tagged_nodes_on_person_id ON public.tagged_nodes USING btree (person_id); + + +-- +-- Name: index_tagged_nodes_on_tag_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tagged_nodes_on_tag_id ON public.tagged_nodes USING btree (tag_id); + + +-- +-- Name: index_tagged_nodes_on_updated_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tagged_nodes_on_updated_at ON public.tagged_nodes USING btree (updated_at); + + +-- +-- Name: index_tags_on_created_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tags_on_created_at ON public.tags USING btree (created_at); + + +-- +-- Name: index_tags_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tags_on_name ON public.tags USING btree (name); + + +-- +-- Name: index_tags_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tags_on_person_id ON public.tags USING btree (person_id); + + +-- +-- Name: index_tags_on_updated_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_tags_on_updated_at ON public.tags USING btree (updated_at); + + +-- +-- Name: index_versions_on_node_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_versions_on_node_id ON public.versions USING btree (node_id); + + +-- +-- Name: index_versions_on_person_id; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX index_versions_on_person_id ON public.versions USING btree (person_id); + + +-- +-- Name: logged_actions_logged_at; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX logged_actions_logged_at ON public.logged_actions USING btree (logged_at); + + +-- +-- Name: logged_actions_not_null_node_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX logged_actions_not_null_node_id_idx ON public.logged_actions USING btree (node_id) WHERE (node_id IS NOT NULL); + + +-- +-- Name: logged_actions_null_node_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX logged_actions_null_node_id_idx ON public.logged_actions USING btree (node_id) WHERE (node_id IS NULL); + + +-- +-- Name: model_downloads_ip_address_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_downloads_ip_address_idx ON public.model_downloads USING btree (ip_address); + + +-- +-- Name: model_downloads_logged_at_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_downloads_logged_at_idx ON public.model_downloads USING btree (logged_at); + + +-- +-- Name: model_downloads_node_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_downloads_node_id_idx ON public.model_downloads USING btree (node_id); + + +-- +-- Name: model_downloads_person_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_downloads_person_id_idx ON public.model_downloads USING btree (person_id); + + +-- +-- Name: model_runs_ip_address_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_runs_ip_address_idx ON public.model_runs USING btree (ip_address); + + +-- +-- Name: model_runs_logged_at_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_runs_logged_at_idx ON public.model_runs USING btree (logged_at); + + +-- +-- Name: model_runs_node_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_runs_node_id_idx ON public.model_runs USING btree (node_id); + + +-- +-- Name: model_runs_person_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_runs_person_id_idx ON public.model_runs USING btree (person_id); + + +-- +-- Name: model_views_ip_address_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_views_ip_address_idx ON public.model_views USING btree (ip_address); + + +-- +-- Name: model_views_logged_at_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_views_logged_at_idx ON public.model_views USING btree (logged_at); + + +-- +-- Name: model_views_node_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_views_node_id_idx ON public.model_views USING btree (node_id); + + +-- +-- Name: model_views_person_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX model_views_person_id_idx ON public.model_views USING btree (person_id); + + +-- +-- Name: new_model_view_counts_count_idx1; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX new_model_view_counts_count_idx1 ON public.model_view_counts USING btree (count); + + +-- +-- Name: new_model_view_counts_node_id_idx1; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX new_model_view_counts_node_id_idx1 ON public.model_view_counts USING btree (node_id); + + +-- +-- Name: node_id_not_null; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX node_id_not_null ON public.logged_actions USING btree (node_id) WHERE (node_id IS NOT NULL); + + +-- +-- Name: tagged_nodes_node_id_tag_id_person_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX tagged_nodes_node_id_tag_id_person_id_idx ON public.tagged_nodes USING btree (node_id, tag_id, person_id); + + +-- +-- Name: tags_lower_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX tags_lower_idx ON public.tags USING btree (lower((name)::text)); + + +-- +-- Name: unique_schema_migrations; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE UNIQUE INDEX unique_schema_migrations ON public.schema_migrations USING btree (version); + + +-- +-- Name: version_contents_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX version_contents_idx ON public.versions USING gin (to_tsvector('english'::regconfig, contents)) WITH (fastupdate=off); + + +-- +-- Name: version_description_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: +-- + +CREATE INDEX version_description_idx ON public.versions USING gin (to_tsvector('english'::regconfig, description)); + + +-- +-- Name: permissions_changed_log_view _RETURN; Type: RULE; Schema: public; Owner: - +-- + +CREATE RULE "_RETURN" AS + ON SELECT TO public.permissions_changed_log_view DO INSTEAD SELECT count(*) AS count, + "substring"(logged_actions.params, 'id"?:\s*"(\d+)'::text) AS id + FROM public.logged_actions + WHERE ((logged_actions.action = 'set_permissions'::text) AND (logged_actions.person_id <> 1)) + GROUP BY logged_actions.id + ORDER BY "substring"(logged_actions.params, 'id"?:\s*"(\d+)'::text) DESC; + + +-- +-- Name: node_changeability_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.nodes + ADD CONSTRAINT node_changeability_fkey FOREIGN KEY (changeability_id) REFERENCES public.permission_settings(id); + + +-- +-- Name: node_parent_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.nodes + ADD CONSTRAINT node_parent_fkey FOREIGN KEY (parent_id) REFERENCES public.nodes(id); + + +-- +-- Name: node_visibility_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.nodes + ADD CONSTRAINT node_visibility_fkey FOREIGN KEY (visibility_id) REFERENCES public.permission_settings(id); + + +-- +-- Name: posting_node_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.postings + ADD CONSTRAINT posting_node_fkey FOREIGN KEY (node_id) REFERENCES public.nodes(id); + + +-- +-- Name: posting_parent_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.postings + ADD CONSTRAINT posting_parent_fkey FOREIGN KEY (parent_id) REFERENCES public.nodes(id); + + +-- +-- Name: posting_versions_person_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.postings + ADD CONSTRAINT posting_versions_person_fkey FOREIGN KEY (person_id) REFERENCES public.people(id); + + +-- +-- Name: tag_creator_person_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.tags + ADD CONSTRAINT tag_creator_person_fkey FOREIGN KEY (person_id) REFERENCES public.people(id); + + +-- +-- Name: tag_node_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.tagged_nodes + ADD CONSTRAINT tag_node_fkey FOREIGN KEY (node_id) REFERENCES public.nodes(id); + + +-- +-- Name: tag_person_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.tagged_nodes + ADD CONSTRAINT tag_person_fkey FOREIGN KEY (person_id) REFERENCES public.people(id); + + +-- +-- Name: tag_tag_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.tagged_nodes + ADD CONSTRAINT tag_tag_fkey FOREIGN KEY (tag_id) REFERENCES public.tags(id); + + +-- +-- PostgreSQL database dump complete +-- diff --git a/apps/modeling-commons-backend/prisma/archive-upload.ts b/apps/modeling-commons-backend/prisma/legacy-migration/upload-files.ts similarity index 94% rename from apps/modeling-commons-backend/prisma/archive-upload.ts rename to apps/modeling-commons-backend/prisma/legacy-migration/upload-files.ts index 5000fd72..356dbb64 100644 --- a/apps/modeling-commons-backend/prisma/archive-upload.ts +++ b/apps/modeling-commons-backend/prisma/legacy-migration/upload-files.ts @@ -16,7 +16,7 @@ const storage = new S3Client({ forcePathStyle: true, }); const bucket = { Name: process.env['STORE_BUCKET']! }; -const seedFilesPath = path.join(import.meta.dirname, 'archive-output', 'files'); +const seedFilesPath = path.join(import.meta.dirname, 'output', 'archive', 'files'); // upload each file in seedFilesPath to the S3 bucket, key relative to seedFilesPath const report = { diff --git a/apps/modeling-commons-backend/prisma/migrations/20260810201942_collaborators/migration.sql b/apps/modeling-commons-backend/prisma/migrations/20260810201942_collaborators/migration.sql new file mode 100644 index 00000000..dbd1b850 --- /dev/null +++ b/apps/modeling-commons-backend/prisma/migrations/20260810201942_collaborators/migration.sql @@ -0,0 +1,28 @@ +-- AlterTable +ALTER TABLE "ModelAuthor" ADD COLUMN "collaboratorType" TEXT; + +-- CreateTable +CREATE TABLE "NonMemberContributor" ( + "id" TEXT NOT NULL, + "legacyId" INTEGER NOT NULL, + "modelId" TEXT NOT NULL, + "email" TEXT, + "name" TEXT, + "collaboratorType" TEXT, + "addedByUserId" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "NonMemberContributor_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "NonMemberContributor_legacyId_key" ON "NonMemberContributor"("legacyId"); + +-- CreateIndex +CREATE INDEX "NonMemberContributor_modelId_idx" ON "NonMemberContributor"("modelId"); + +-- CreateIndex +CREATE INDEX "NonMemberContributor_email_idx" ON "NonMemberContributor"("email"); + +-- AddForeignKey +ALTER TABLE "NonMemberContributor" ADD CONSTRAINT "NonMemberContributor_modelId_fkey" FOREIGN KEY ("modelId") REFERENCES "Model"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/apps/modeling-commons-backend/prisma/netlogo-utils.ts b/apps/modeling-commons-backend/prisma/netlogo-utils.ts deleted file mode 100644 index e228c1b8..00000000 --- a/apps/modeling-commons-backend/prisma/netlogo-utils.ts +++ /dev/null @@ -1,43 +0,0 @@ -function parseNlogo(contents: string): { - netlogoVersion: string | null; - infoTab: string | null; -} { - const SEP = '@#$#@#$#@'; - const parts = contents.split(SEP); - if (parts.length < 5) return { netlogoVersion: null, infoTab: null }; - const infoTab = parts[2]?.trim() || null; - const versionRaw = parts[4]?.trim() || null; - const netlogoVersion = versionRaw && versionRaw.length < 100 ? versionRaw : null; - return { netlogoVersion, infoTab }; -} - -function parseNlogox(contents: string): { - netlogoVersion: string | null; - infoTab: string | null; -} { - try { - const parser = new DOMParser(); - const doc = parser.parseFromString(contents, 'application/xml'); - const modelEl = doc.querySelector('model'); - if (!modelEl) return { netlogoVersion: null, infoTab: null }; - const versionRaw = modelEl.getAttribute('version') ?? null; - const netlogoVersion = versionRaw - ? versionRaw.trim().replace(/^NetLogo\s*(3D)?\s*/i, '') - : null; - const infoTabEl = doc.querySelector('info'); - const infoTab = infoTabEl ? infoTabEl.textContent?.trim() || null : null; - return { netlogoVersion, infoTab }; - } catch { - return { netlogoVersion: null, infoTab: null }; - } -} - -function getNlogoFileExtension(contents: string): string { - if (contents.includes('@#$#@#$#@')) return 'nlogo'; - if (contents.includes(' = { '.png': 'image/png', @@ -60,7 +60,7 @@ function loadPreview(previewFilename: string): PreviewAsset { }; } -/** Load a real `.nlogox` file shipped in `seed-files/`, with its Info tab + optional preview. */ +/** Load a real `.nlogox` file shipped in `seed/files/`, with its Info tab + optional preview. */ export function loadNlogox(filename: string, previewFilename?: string): NlogoxAsset { const filepath = path.join(seedFilesPath, filename); const content = fs.readFileSync(filepath, 'utf-8'); diff --git a/apps/modeling-commons-backend/prisma/seed-files/ants-preview.png b/apps/modeling-commons-backend/prisma/seed/files/ants-preview.png similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/ants-preview.png rename to apps/modeling-commons-backend/prisma/seed/files/ants-preview.png diff --git a/apps/modeling-commons-backend/prisma/seed-files/ants.nlogox b/apps/modeling-commons-backend/prisma/seed/files/ants.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/ants.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/ants.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/download.png b/apps/modeling-commons-backend/prisma/seed/files/download.png similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/download.png rename to apps/modeling-commons-backend/prisma/seed/files/download.png diff --git a/apps/modeling-commons-backend/prisma/seed-files/fire-preview.png b/apps/modeling-commons-backend/prisma/seed/files/fire-preview.png similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/fire-preview.png rename to apps/modeling-commons-backend/prisma/seed/files/fire-preview.png diff --git a/apps/modeling-commons-backend/prisma/seed-files/fire.nlogox b/apps/modeling-commons-backend/prisma/seed/files/fire.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/fire.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/fire.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/traffic-2-lanes-preview.png b/apps/modeling-commons-backend/prisma/seed/files/traffic-2-lanes-preview.png similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/traffic-2-lanes-preview.png rename to apps/modeling-commons-backend/prisma/seed/files/traffic-2-lanes-preview.png diff --git a/apps/modeling-commons-backend/prisma/seed-files/traffic-2-lanes.nlogox b/apps/modeling-commons-backend/prisma/seed/files/traffic-2-lanes.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/traffic-2-lanes.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/traffic-2-lanes.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/traffic-basic-preview.png b/apps/modeling-commons-backend/prisma/seed/files/traffic-basic-preview.png similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/traffic-basic-preview.png rename to apps/modeling-commons-backend/prisma/seed/files/traffic-basic-preview.png diff --git a/apps/modeling-commons-backend/prisma/seed-files/traffic-basic.nlogox b/apps/modeling-commons-backend/prisma/seed/files/traffic-basic.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/traffic-basic.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/traffic-basic.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/traffic-grid-preview.png b/apps/modeling-commons-backend/prisma/seed/files/traffic-grid-preview.png similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/traffic-grid-preview.png rename to apps/modeling-commons-backend/prisma/seed/files/traffic-grid-preview.png diff --git a/apps/modeling-commons-backend/prisma/seed-files/traffic-grid.nlogox b/apps/modeling-commons-backend/prisma/seed/files/traffic-grid.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/traffic-grid.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/traffic-grid.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-predation-fork.nlogox b/apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-predation-fork.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-predation-fork.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-predation-fork.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-predation-v2.nlogox b/apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-predation-v2.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-predation-v2.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-predation-v2.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-predation.nlogox b/apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-predation.nlogox similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-predation.nlogox rename to apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-predation.nlogox diff --git a/apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-preview.png b/apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-preview.png similarity index 100% rename from apps/modeling-commons-backend/prisma/seed-files/wolf-sheep-preview.png rename to apps/modeling-commons-backend/prisma/seed/files/wolf-sheep-preview.png diff --git a/apps/modeling-commons-backend/prisma/seed/manifest/types.ts b/apps/modeling-commons-backend/prisma/seed/manifest/types.ts index 6e8e279d..0513b8d7 100644 --- a/apps/modeling-commons-backend/prisma/seed/manifest/types.ts +++ b/apps/modeling-commons-backend/prisma/seed/manifest/types.ts @@ -36,7 +36,7 @@ export interface TagSeed { legacyId?: number; } -/** A model file backed by a real `.nlogox` shipped in `seed-files/`. */ +/** A model file backed by a real `.nlogox` shipped in `seed/files/`. */ export interface RealFileSeed { file: string; preview?: string; diff --git a/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.spec.ts b/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.spec.ts index aa178740..41bb5e9e 100644 --- a/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.spec.ts +++ b/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.spec.ts @@ -21,7 +21,7 @@ describe('modelAuthorDomain', () => { describe('assertIsOwner', () => { it('passes for owner', () => { expect(() => - domain.assertIsOwner({ modelId: 'm1', userId: 'u1', role: 'owner', createdAt: new Date() }), + domain.assertIsOwner({ modelId: 'm1', userId: 'u1', role: 'owner', collaboratorType: null, createdAt: new Date() }), ).not.toThrow(); }); @@ -31,6 +31,7 @@ describe('modelAuthorDomain', () => { modelId: 'm1', userId: 'u1', role: 'contributor', + collaboratorType: null, createdAt: new Date(), }), ).toThrow(NotOwnerError); @@ -44,6 +45,7 @@ describe('modelAuthorDomain', () => { modelId: 'm1', userId: 'u1', role: 'contributor', + collaboratorType: null, createdAt: new Date(), }), ).not.toThrow(); @@ -55,6 +57,7 @@ describe('modelAuthorDomain', () => { modelId: 'm1', userId: 'u1', role: 'owner', + collaboratorType: null, createdAt: new Date(), }), ).toThrow(CannotRemoveOwnerError); diff --git a/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.ts b/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.ts index a37b184d..b052f68d 100644 --- a/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.ts +++ b/apps/modeling-commons-backend/src/modules/model-author/domain/model-author.domain.ts @@ -14,6 +14,7 @@ export default function modelAuthorDomain() { modelId, userId, role, + collaboratorType: null, createdAt: new Date(), }; }, diff --git a/apps/modeling-commons-backend/tsconfig.json b/apps/modeling-commons-backend/tsconfig.json index 3bb50a44..c1a4038d 100644 --- a/apps/modeling-commons-backend/tsconfig.json +++ b/apps/modeling-commons-backend/tsconfig.json @@ -8,6 +8,6 @@ "#prisma/*": ["./generated/prisma/*"] } }, - "include": ["src", "tests"], + "include": ["src", "tests", "prisma"], "exclude": ["**/*.k6.ts"] }