From 0501c11c490d7e98e238c7d5d803ef0474c01b91 Mon Sep 17 00:00:00 2001 From: schreifuchs Date: Fri, 7 Feb 2025 13:33:43 +0100 Subject: [PATCH] before svelte upgrade --- app.go | 32 ++++-- frontend/src/App.svelte | 12 ++- frontend/src/routes/Home.svelte | 70 ++++++------ frontend/src/routes/TourCreator.svelte | 44 ++++++++ frontend/src/routes/Tournament.svelte | 28 +++++ frontend/wailsjs/go/main/App.d.ts | 9 +- frontend/wailsjs/go/main/App.js | 16 ++- frontend/wailsjs/go/models.ts | 135 +++++++++++++++++++++++- frontend/wailsjs/go/things/Service.d.ts | 9 -- frontend/wailsjs/go/things/Service.js | 15 --- go.mod | 13 ++- go.sum | 14 ++- main.go | 7 +- model/init.go | 36 +++++++ model/model.go | 44 ++++++++ things.db | 0 tournament.db | Bin 0 -> 49152 bytes 17 files changed, 396 insertions(+), 88 deletions(-) create mode 100644 frontend/src/routes/TourCreator.svelte create mode 100644 frontend/src/routes/Tournament.svelte delete mode 100755 frontend/wailsjs/go/things/Service.d.ts delete mode 100755 frontend/wailsjs/go/things/Service.js create mode 100644 model/init.go create mode 100644 model/model.go create mode 100644 things.db create mode 100644 tournament.db diff --git a/app.go b/app.go index af53038..04779b4 100644 --- a/app.go +++ b/app.go @@ -2,17 +2,22 @@ package main import ( "context" - "fmt" + "gegio-ue1/model" + + "gorm.io/gorm" ) // App struct type App struct { ctx context.Context + db *gorm.DB } // NewApp creates a new App application struct -func NewApp() *App { - return &App{} +func NewApp(db *gorm.DB) *App { + return &App{ + db: db, + } } // startup is called when the app starts. The context is saved @@ -21,7 +26,22 @@ func (a *App) startup(ctx context.Context) { a.ctx = ctx } -// Greet returns a greeting for the given name -func (a *App) Greet(name string) string { - return fmt.Sprintf("Hello %s, It's show time!", name) +func (a *App) GetGames() (gs []model.Game, err error) { + err = a.db.Find(&gs).Error + return + +} + +func (a *App) GetTournaments() (ts []model.Tournament, err error) { + err = a.db.Preload("Game").Find(&ts).Error + return +} + +func (a *App) GetTournament(id int) (t model.Tournament, err error) { + err = a.db.Preload("Game").First(&t, id).Error + return +} +func (a *App) SaveTournament(t model.Tournament) error { + err := a.db.Save(&t).Error + return err } diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index f0af3f7..f1d466e 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -1,22 +1,26 @@
- - Wails + navigate("", { replace: true })}> + Tournamenter - +
+
diff --git a/frontend/src/routes/Home.svelte b/frontend/src/routes/Home.svelte index 1fb6462..d8a1dd0 100644 --- a/frontend/src/routes/Home.svelte +++ b/frontend/src/routes/Home.svelte @@ -1,14 +1,8 @@ -
-
- - -
-
- -
-
- ID - Name - - Delete + Title + Game + Winner {#each thingsList as t} - {t.ID} + {t.Title} + + + {t.Game.Name} + + + {t.WinnierParticipant.Name} - {t.Name} - - - + Edit {/each} +
+ + +
+ + { + update(); + newThing = false; + }} + /> +
diff --git a/frontend/src/routes/TourCreator.svelte b/frontend/src/routes/TourCreator.svelte new file mode 100644 index 0000000..9e1b5c5 --- /dev/null +++ b/frontend/src/routes/TourCreator.svelte @@ -0,0 +1,44 @@ + + +
+
+ + +
+
+ e + + +
+ +
diff --git a/frontend/src/routes/Tournament.svelte b/frontend/src/routes/Tournament.svelte new file mode 100644 index 0000000..9785a83 --- /dev/null +++ b/frontend/src/routes/Tournament.svelte @@ -0,0 +1,28 @@ + + +
+ Home +
+{#if tournament} + {tournament.Title} +{/if} diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 02a3bb9..4d3489f 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -1,4 +1,11 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +import {model} from '../models'; -export function Greet(arg1:string):Promise; +export function GetGames():Promise>; + +export function GetTournament(arg1:number):Promise; + +export function GetTournaments():Promise>; + +export function SaveTournament(arg1:model.Tournament):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index c71ae77..04be6e3 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -2,6 +2,18 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -export function Greet(arg1) { - return window['go']['main']['App']['Greet'](arg1); +export function GetGames() { + return window['go']['main']['App']['GetGames'](); +} + +export function GetTournament(arg1) { + return window['go']['main']['App']['GetTournament'](arg1); +} + +export function GetTournaments() { + return window['go']['main']['App']['GetTournaments'](); +} + +export function SaveTournament(arg1) { + return window['go']['main']['App']['SaveTournament'](arg1); } diff --git a/frontend/wailsjs/go/models.ts b/frontend/wailsjs/go/models.ts index e590fe2..a526dbe 100755 --- a/frontend/wailsjs/go/models.ts +++ b/frontend/wailsjs/go/models.ts @@ -1,18 +1,147 @@ -export namespace things { +export namespace model { - export class Thing { + export class Game { ID: number; + // Go type: time + CreatedAt: any; + // Go type: time + UpdatedAt: any; + // Go type: gorm + DeletedAt: any; Name: string; static createFrom(source: any = {}) { - return new Thing(source); + return new Game(source); } constructor(source: any = {}) { if ('string' === typeof source) source = JSON.parse(source); this.ID = source["ID"]; + this.CreatedAt = this.convertValues(source["CreatedAt"], null); + this.UpdatedAt = this.convertValues(source["UpdatedAt"], null); + this.DeletedAt = this.convertValues(source["DeletedAt"], null); this.Name = source["Name"]; } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + export class Tournament { + ID: number; + // Go type: time + CreatedAt: any; + // Go type: time + UpdatedAt: any; + // Go type: gorm + DeletedAt: any; + Title: string; + GameID: number; + Game: Game; + Size?: number; + TournamentState: number; + WinnierParticipantID: number; + WinnierParticipant: Participant; + Participants: Participant[]; + + static createFrom(source: any = {}) { + return new Tournament(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.ID = source["ID"]; + this.CreatedAt = this.convertValues(source["CreatedAt"], null); + this.UpdatedAt = this.convertValues(source["UpdatedAt"], null); + this.DeletedAt = this.convertValues(source["DeletedAt"], null); + this.Title = source["Title"]; + this.GameID = source["GameID"]; + this.Game = this.convertValues(source["Game"], Game); + this.Size = source["Size"]; + this.TournamentState = source["TournamentState"]; + this.WinnierParticipantID = source["WinnierParticipantID"]; + this.WinnierParticipant = this.convertValues(source["WinnierParticipant"], Participant); + this.Participants = this.convertValues(source["Participants"], Participant); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + export class Participant { + ID: number; + // Go type: time + CreatedAt: any; + // Go type: time + UpdatedAt: any; + // Go type: gorm + DeletedAt: any; + Name: string; + IsTemporary: boolean; + IsTeam: boolean; + Tournaments: Tournament[]; + + static createFrom(source: any = {}) { + return new Participant(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.ID = source["ID"]; + this.CreatedAt = this.convertValues(source["CreatedAt"], null); + this.UpdatedAt = this.convertValues(source["UpdatedAt"], null); + this.DeletedAt = this.convertValues(source["DeletedAt"], null); + this.Name = source["Name"]; + this.IsTemporary = source["IsTemporary"]; + this.IsTeam = source["IsTeam"]; + this.Tournaments = this.convertValues(source["Tournaments"], Tournament); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } } } diff --git a/frontend/wailsjs/go/things/Service.d.ts b/frontend/wailsjs/go/things/Service.d.ts deleted file mode 100755 index 0f9aab6..0000000 --- a/frontend/wailsjs/go/things/Service.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -import {things} from '../models'; - -export function DeleteThing(arg1:number):Promise; - -export function GetThings():Promise>; - -export function NewThing(arg1:string):Promise; diff --git a/frontend/wailsjs/go/things/Service.js b/frontend/wailsjs/go/things/Service.js deleted file mode 100755 index 1d5ee94..0000000 --- a/frontend/wailsjs/go/things/Service.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export function DeleteThing(arg1) { - return window['go']['things']['Service']['DeleteThing'](arg1); -} - -export function GetThings() { - return window['go']['things']['Service']['GetThings'](); -} - -export function NewThing(arg1) { - return window['go']['things']['Service']['NewThing'](arg1); -} diff --git a/go.mod b/go.mod index 291463c..8fd51c1 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,12 @@ -module wails-svelte-tailwind-ts +module gegio-ue1 go 1.23 -require github.com/wailsapp/wails/v2 v2.9.2 +require ( + github.com/wailsapp/wails/v2 v2.9.2 + gorm.io/driver/sqlite v1.5.7 + gorm.io/gorm v1.25.12 +) require ( github.com/bep/debounce v1.2.1 // indirect @@ -10,6 +14,8 @@ require ( github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect github.com/labstack/echo/v4 v4.10.2 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/leaanthony/go-ansi-parser v1.6.0 // indirect @@ -18,6 +24,7 @@ require ( github.com/leaanthony/u v1.1.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.4.4 // indirect @@ -31,7 +38,7 @@ require ( golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/net v0.25.0 // indirect golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/text v0.22.0 // indirect ) // replace github.com/wailsapp/wails/v2 v2.9.2 => /Users/u80864958/go/pkg/mod diff --git a/go.sum b/go.sum index 6ed0576..2c3ec92 100644 --- a/go.sum +++ b/go.sum @@ -11,6 +11,10 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= @@ -35,6 +39,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -84,11 +90,15 @@ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I= +gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= diff --git a/main.go b/main.go index b744f26..5dce711 100644 --- a/main.go +++ b/main.go @@ -2,7 +2,7 @@ package main import ( "embed" - "wails-svelte-tailwind-ts/things" + "gegio-ue1/model" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/options" @@ -14,8 +14,8 @@ var assets embed.FS func main() { // Create an instance of the app structure - app := NewApp() - things := things.NewThingsService() + db := model.InitDB() + app := NewApp(db) // Create application with options err := wails.Run(&options.App{ @@ -29,7 +29,6 @@ func main() { OnStartup: app.startup, Bind: []interface{}{ app, - things, }, }) diff --git a/model/init.go b/model/init.go new file mode 100644 index 0000000..efba913 --- /dev/null +++ b/model/init.go @@ -0,0 +1,36 @@ +package model + +import ( + "log" + + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +func InitDB() *gorm.DB { + db, err := gorm.Open(sqlite.Open("tournament.db")) + if err != nil { + log.Panic(err) + } + db.AutoMigrate(&Game{}, &Participant{}, &Tournament{}, &Match{}) + db.Save(&Game{ + Model: gorm.Model{ + ID: 1, + }, + Name: "CS:GO", + }) + db.Save(&Game{ + Model: gorm.Model{ + ID: 2, + }, + Name: "Overwatch", + }) + db.Save(&Game{ + Model: gorm.Model{ + ID: 3, + }, + Name: "Minecraft", + }) + + return db +} diff --git a/model/model.go b/model/model.go new file mode 100644 index 0000000..6d87935 --- /dev/null +++ b/model/model.go @@ -0,0 +1,44 @@ +package model + +import ( + "gorm.io/gorm" +) + +type Game struct { + gorm.Model + Name string +} + +type Participant struct { + gorm.Model + Name string + IsTemporary bool // only for one tournament + IsTeam bool + Tournaments []*Tournament `gorm:"many2many:partcipant_tournaments;"` +} + +type Tournament struct { + gorm.Model + Title string + GameID int + Game Game `gorm:"foreignKey:GameID"` + Size int `json:"Size,string,omitempty"` // number of prarticipants + TournamentState int + + WinnierParticipantID int + WinnierParticipant Participant `gorm:"foreignKey:WinnierParticipantID"` + Participants []*Participant `gorm:"many2many:partcipant_tournaments;"` +} + +type Match struct { + gorm.Model + TournamentID int + Stage int + Order int + Participant1ID int + Participant1 Participant `gorm:"foreignKey:Participant1ID"` + Participant2ID int + Participant2 Participant `gorm:"foreignKey:Participant2ID"` + WinnierParticipantID int + WinnierParticipant Participant `gorm:"foreignKey:WinnierParticipantID"` +} diff --git a/things.db b/things.db new file mode 100644 index 0000000..e69de29 diff --git a/tournament.db b/tournament.db new file mode 100644 index 0000000000000000000000000000000000000000..8e0276ff9f20b4864d6cc8e5bdc5095bc6a6e4dd GIT binary patch literal 49152 zcmeI)+i%-c90zcpxXrCi!= z0x1+W?U}y;@h9-kzra7h3leWgNQjp`aO~WUodjB`-9q)X(!@FE_*_2c=aW=UQn`Ou zH#PCFZ8TL=OmJ^;gm52-BFAyN^ly>=4YmN?nHxNzkA&Huw!6!1K6x1m{>m+Q-{!&( z!hxk9LO+LYFVus-`~L`j?|n{_u|WU=5P-l;2|QZx3E5@R4e71AcB$H`&{eD zb*-V9T3uGne#+ujxsb0G#GT@Yg-=Cga#=+z6-A|ggtDfLYEdHJ9tM5F@-lh3VyX`t zTE9^LVWD4pHGlhVVN`>-MjKK@y=7`gnjzjR@9gKx2jX7gK+Jz!E$tNPVf%$*HLBDM zP3`qp5$kl%)SFsVIXSlWtx>S4Os|--X8XiwsZFhA%1oP4rDLi`+OQ8%rESzTgL!_e z8m3;;kJXkLa~{d$#GN@$^;S#Q44En6D6my3R;uOvPO&N~hhGdQWx`>Kc&Ah@>}(fp zlr?2S5v%5iST5WtlnceJLPb=VW;=A2to-PdCYho!cUx@UWi=B2mqu*F{~Sr=?1rC4 zb(VbhnH^|WFMHD?kEXaYIW^!6!^wpd8kM7(9P`G?Ix^VEbsrsdA2l`^ll#F8$BpLf zo|9~pH*M~xG-oCE1Kr&olXb2@i0lQtf}ACsz3y}#H|YCQSv@h^_H+BR7@smZHo0R# zx}^H8W%ZfQC*)U1_ub)Y#*CF&(U?^K_^QU_GRO2*HYU%tx}81n`h=Ag^8711=$L}c zuFn}>OpX;(%&K$6E1hmO=!#})r)E?+qD!75RF#hYj9u?Wy_D%vXtG&T7MsC(?Oszx zHFadGS$7l-y5fviD|K3=vNcZVjJtseMa~zlU(fr5tyR*!F^nuG;@KBVHrYEKTWt1N zaIu-L=;|tSK4Ep0obkgYt$!xk3)x_Q-Wgwx3SVb{Sudl5_|iMFsWp$=hH8ANh^>>R zX6Uu3VkfK3VM^p7?-P;&>CO*{?TKfU?B{disP1yTQ*{tF%!_^Gp2sV!uag5CvA^nc zw8tk}tERc0@(xN@=9)FYC_OULeV_OQK_K7s-qhHQ+IJqu@%CBPd95e;XbvKw@H-s8 z^kRPLm++&d7c=z+6rF(p1Rwwb2tWV=5P$##AOL~uC$P(Vxm)+S_asS*ZP+(al5+NK z-M)`Y@#KaS-;mN`ES8HUa`DWjl**)2@kC}_iqWF`dP}Pr>Y=$!Xk8UfxL93@L|l^6 z>3(HfmE3kI{1dl#t8}4Gr8d)vcrq;|Tzxt;%{`CZtqTq@8Ovrf>1?W3U+IZvJhiUE z&