Compare commits

...

4 Commits

Author SHA1 Message Date
8b5bb78764 start on matches 2025-02-10 09:51:43 +01:00
6cfea2e8dc status after 3h & 30min 2025-02-07 17:14:01 +01:00
5f8842b140 update to svelte 5 2025-02-07 13:41:17 +01:00
0501c11c49 before svelte upgrade 2025-02-07 13:33:43 +01:00
27 changed files with 1478 additions and 682 deletions

114
app.go
View File

@ -3,16 +3,25 @@ package main
import (
"context"
"fmt"
"gegio-ue1/model"
"os"
"slices"
"github.com/wailsapp/wails/v2/pkg/runtime"
"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 +30,102 @@ 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").Preload("Participants").Preload("Matches").First(&t, id).Error
return
}
func (a *App) SaveTournament(t model.Tournament) error {
err := a.db.Save(&t).Error
return err
}
func (a *App) FillRandom(t model.Tournament) {
for range t.Size - len(t.Participants) {
t.Participants = append(t.Participants, &model.Participant{
Name: model.RandomName(),
IsTemporary: true,
IsTeam: true,
})
}
a.db.Save(&t.Participants)
a.db.Save(&t)
}
func (a *App) StartTournament(t model.Tournament) {
t.TournamentState = 1
a.SaveTournament(t)
t, _ = a.GetTournament(int(t.ID))
matches := make([]model.Match, 0, len(t.Participants)/2)
for i := range len(t.Participants) / 2 {
matches = append(matches, model.Match{
TournamentID: t.ID,
Stage: 1,
Order: i,
Participant1ID: t.Participants[i].ID,
Participant2ID: t.Participants[i+len(t.Participants)/2].ID,
})
}
if len(t.Participants)%2 != 0 {
matches = append(matches, model.Match{
TournamentID: t.ID,
Stage: 1,
Order: len(t.Participants)/2 + 1,
Participant1ID: t.Participants[len(t.Participants)-1].ID,
Participant2ID: t.Participants[len(t.Participants)-1].ID,
})
}
a.db.Save(matches)
}
func (a *App) ExportTournament(t model.Tournament) {
dirname, _ := os.UserHomeDir()
str, err := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{DefaultDirectory: dirname, DefaultFilename: "tournament.csv"})
if err != nil {
fmt.Println(err)
}
println(str)
}
func (a *App) GetParticipants() (ps []model.Participant, err error) {
err = a.db.Find(&ps).Error
return
}
func (a *App) SaveParticipant(p model.Participant) error {
return a.db.Save(&p).Error
}
func (a *App) DeleteParticipat(p model.Participant) {
a.db.Delete(&p)
}
func (a *App) RemoveParticipantFromTournament(p model.Participant, t model.Tournament) {
if p.IsTemporary {
a.db.Delete(&p)
return
}
a.db.Model(&t).Association("Participants").Delete(&p)
}
func (a *App) GetMatches(tID uint) [][]model.Match {
matches := make([][]model.Match, 0)
for {
ms := make([]model.Match, 0)
if err := a.db.Where("tournament_id = ? AND stage = ?", tID, len(matches)).Find(&ms).Error; err != nil || len(ms) == 0 {
fmt.Println(ms)
fmt.Println(err)
return matches
}
slices.SortFunc(ms, func(a, b model.Match) int { return a.Order - b.Order })
matches = append(matches, ms)
}
}

View File

@ -10,19 +10,19 @@
"check": "svelte-check --tsconfig ./tsconfig.json"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tsconfig/svelte": "^3.0.0",
"autoprefixer": "^10.4.20",
"flowbite": "^3.1.1",
"flowbite-svelte": "^0.47.4",
"flowbite-svelte-icons": "^2.0.2",
"svelte": "^3.49.0",
"svelte-check": "^2.8.0",
"svelte-preprocess": "^4.10.7",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"svelte-preprocess": "^6.0.0",
"svelte-routing": "^2.13.0",
"tailwindcss": "^3.4.9",
"tslib": "^2.4.0",
"typescript": "^4.6.4",
"vite": "^3.0.7"
"typescript": "^5.5.0",
"vite": "^5.4.4"
}
}

View File

@ -1 +1 @@
a5a8c3695f34d6c9bafb2ee7f70bf99a
6f760b83cd6ae4745bc9e5ebf4de97b2

1148
frontend/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,26 @@
<script lang="ts">
import "./app.css";
import { Navbar, NavBrand, DarkMode } from "flowbite-svelte";
import { Router, Route } from "svelte-routing";
import { Navbar, NavBrand, DarkMode, Button } from "flowbite-svelte";
import { Router, Route, Link } from "svelte-routing";
import Home from "./routes/Home.svelte";
import "./app.css";
import Tournament from "./routes/Tournament.svelte";
export let url = "";
</script>
<main class="flex-col h-screen items-center bg-gray-50 dark:bg-gray-800">
<Navbar>
<NavBrand>
<span>Wails</span>
</NavBrand>
<DarkMode />
</Navbar>
<Router {url}>
<Router bind:url>
<Navbar>
<NavBrand>
<Link to="/">Tournaments</Link>
</NavBrand>
<DarkMode />
</Navbar>
<div>
<Route path="/"><Home /></Route>
<Route path="/tournament/:id" let:params>
<Tournament id={parseInt(params.id)} />
</Route>
</div>
</Router>
</main>

View File

@ -1,7 +1,8 @@
import './style.css'
import App from './App.svelte'
import { mount } from "svelte";
const app = new App({
const app = mount(App, {
target: document.getElementById('app')
})

View File

@ -1,14 +1,8 @@
<script lang="ts">
import { onMount } from "svelte";
import { GetTournaments } from "../../wailsjs/go/main/App";
import { model } from "../../wailsjs/go/models";
import {
GetThings,
DeleteThing,
NewThing,
} from "../../wailsjs/go/things/Service";
import { things } from "../../wailsjs/go/models";
import {
Label,
Input,
Button,
Table,
TableHead,
@ -16,60 +10,61 @@
TableBody,
TableBodyRow,
TableBodyCell,
Modal,
} from "flowbite-svelte";
import TourCreator from "./TourCreator.svelte";
import { Link } from "svelte-routing";
let name: string;
let thingsList: things.Thing[] = [];
let thingsList: model.Tournament[] = $state([]);
let newThing: boolean = $state(false);
function update() {
GetThings().then((ts) => {
GetTournaments().then((ts) => {
thingsList = ts;
});
}
function submit(e: Event) {
e.preventDefault();
NewThing(name).then(update);
name = "";
}
function deleteEvent(id: number) {
DeleteThing(id).then(update);
}
onMount(update);
</script>
<form class="max-w-96 m-5 grid-cols-1 gap-10" on:submit={submit}>
<div class="m-5">
<Label for="first_name" class="mb-2">First name</Label>
<Input type="text" placeholder="John" bind:value={name} required />
</div>
<div class="m-5">
<Button type="submit">Submit</Button>
</div>
</form>
<Table>
<TableHead>
<TableHeadCell>ID</TableHeadCell>
<TableHeadCell>Name</TableHeadCell>
<TableHeadCell>Delete</TableHeadCell>
<TableHeadCell>Title</TableHeadCell>
<TableHeadCell>Game</TableHeadCell>
<TableHeadCell>Winner</TableHeadCell>
<TableHeadCell></TableHeadCell>
</TableHead>
<TableBody>
{#each thingsList as t}
<TableBodyRow>
<TableBodyCell>
{t.ID}
{t.Title}
</TableBodyCell>
<TableBodyCell>
{t.Game.Name}
</TableBodyCell>
<TableBodyCell>
{t.WinnierParticipant.Name}
</TableBodyCell>
<TableBodyCell>
{t.Name}
</TableBodyCell>
<TableBodyCell>
<Button on:click={(_) => deleteEvent(t.ID)}>Delete</Button>
<Link class="text-primary-500 underline" to={`/tournament/${t.ID}`}
>Edit</Link
>
</TableBodyCell>
</TableBodyRow>
{/each}
</TableBody>
<div class="flex-row justify-evenly p-5">
<Button>View</Button>
<Button on:click={(_) => (newThing = true)}>New Tournament</Button>
</div>
<Modal bind:open={newThing}>
<TourCreator
onCreated={() => {
update();
newThing = false;
}}
/>
</Modal>
</Table>

View File

@ -0,0 +1,39 @@
<script lang="ts">
import { onMount } from "svelte";
import {
GetMatches,
GetTournament,
StartTournament,
} from "../../wailsjs/go/main/App";
import { model } from "../../wailsjs/go/models";
import { Button, TabItem, Tabs } from "flowbite-svelte";
let { tournamentID }: { tournamentID: number } = $props();
let tournament: model.Tournament = $state(new model.Tournament());
let matches: model.Match[][] = $state([]);
function update() {
GetTournament(tournamentID).then((t) => {
console.log(t);
tournament = t;
});
GetMatches(tournamentID).then((ms) => (matches = ms));
}
$effect(update);
onMount(update);
</script>
{#if tournament.TournamentState == 0}
<Button
onclick={() => {
StartTournament(tournament).then(update);
}}>Start</Button
>
{:else}
<Tabs>
{#each matches as ms, i}
<TabItem title={`Stage: ${i}`}></TabItem>
{/each}
</Tabs>
{/if}

View File

@ -0,0 +1,131 @@
<script lang="ts">
import {
Button,
Checkbox,
Heading,
Input,
Label,
Modal,
Radio,
Table,
TableBody,
TableBodyCell,
TableBodyRow,
TableHead,
TableHeadCell,
} from "flowbite-svelte";
import { model } from "../../wailsjs/go/models";
import {
GetParticipants,
GetTournament,
RemoveParticipantFromTournament,
SaveParticipant,
DeleteParticipat,
SaveTournament,
FillRandom,
} from "../../wailsjs/go/main/App";
import { onMount } from "svelte";
let { tournamentID }: { tournamentID: number } = $props();
let participants: model.Participant[] = $state([]);
let newOpen: boolean = $state(false);
let participant: model.Participant = $state(
new model.Participant({ IsTeam: false }),
);
let tournament: model.Tournament = $state();
function update() {
GetParticipants().then((ps) => (participants = ps));
if (tournamentID) {
GetTournament(tournamentID).then((t) => {
console.log(t);
tournament = t;
});
}
}
function saveNewPart(e: Event) {
e.preventDefault();
SaveParticipant(participant).then(update);
newOpen = false;
}
$effect(update);
onMount(() => setTimeout(update, 0));
</script>
{#if tournament}
<section class="grid grid-cols-2 gap-5 p-5 text-center text-2xl text-white">
<p>{tournament.Participants.length}</p>
<p>{tournament.Size}</p>
<p>Participants</p>
<p>Max Participants</p>
</section>
{/if}
<Table>
<TableHead>
<TableHeadCell>Name</TableHeadCell>
<TableHeadCell />
<TableHeadCell />
<TableHeadCell />
</TableHead>
<TableBody>
{#each participants as p}
<TableBodyRow>
<TableBodyCell>
{p.Name}
</TableBodyCell>
<TableBodyCell>
{#if tournament.Participants.find((pa) => pa.ID == p.ID)}
<Button
onclick={() => {
RemoveParticipantFromTournament(p, tournament).then(update);
}}>Remove</Button
>
{:else}
<Button
disabled={tournament.Participants.length >= tournament.Size}
onclick={() => {
tournament.Participants.push(p);
SaveTournament(tournament).then(update);
}}>Add</Button
>
{/if}
</TableBodyCell>
<TableBodyCell>
<Button onclick={() => DeleteParticipat(p).then(update)}
>Delete</Button
>
</TableBodyCell>
</TableBodyRow>
{/each}
</TableBody>
</Table>
<div class="grid p-5 gap-5 grid-cols-2">
<Button onclick={() => (newOpen = true)}>+ Participant</Button>
<Button onclick={() => FillRandom(tournament).then(update)}
>Fill Random</Button
>
</div>
<Modal bind:open={newOpen}>
<form onsubmit={saveNewPart}>
<Heading tag="h3">New Participant</Heading>
<div class="m-5">
<Label>Name</Label>
<Input type="text" required bind:value={participant.Name} />
</div>
<div class="m-5 grid grid-cols-3">
<Label>Type:</Label>
<Radio required value={false} bind:group={participant.IsTeam}
>Single Player</Radio
>
<Radio required value={true} bind:group={participant.IsTeam}>Team</Radio>
</div>
<div class=" m-5 grid grid-cols-3">
<Label>Teporary:</Label>
<Checkbox bind:value={participant.IsTemporary} />
</div>
<Button class="m-5" type="submit">Save</Button>
</form>
</Modal>

View File

@ -0,0 +1,48 @@
<script lang="ts">
import { Button, Input, Label, Select } from "flowbite-svelte";
import { model } from "../../wailsjs/go/models";
import { GetGames, SaveTournament } from "../../wailsjs/go/main/App";
import { onMount } from "svelte";
let tournament = $state(new model.Tournament());
let games: model.Game[] = $state([]);
interface Props {
onCreated?: (t: model.Tournament) => void;
}
let { onCreated = (_) => {} }: Props = $props();
function submit(e: Event) {
e.preventDefault();
SaveTournament(tournament).then(() => {
onCreated(tournament);
});
}
onMount(() => {
GetGames().then((gs) => {
games = gs;
});
});
</script>
<form onsubmit={submit}>
<div>
<Label>Title</Label>
<Input type="text" bind:value={tournament.Title} />
</div>
<div>
e
<Label>Game</Label>
<Select
items={games.map((g) => {
return { value: g.ID, name: g.Name };
})}
bind:value={tournament.GameID}
/>
</div>
<div>
<Label>Size</Label>
<Input type="number" step="1" min="1" bind:value={tournament.Size} />
</div>
<Button type="submit">Save</Button>
</form>

View File

@ -0,0 +1,41 @@
<script lang="ts">
import { Link, navigate } from "svelte-routing";
import { GetTournament, ExportTournament } from "../../wailsjs/go/main/App";
import { model } from "../../wailsjs/go/models";
import { onMount } from "svelte";
import { Button, Heading, TabItem, Tabs } from "flowbite-svelte";
import Participants from "./Participants.svelte";
import Matches from "./Matches.svelte";
interface Props {
id?: number | null;
}
let { id = $bindable(null) }: Props = $props();
let tournament: model.Tournament = $state();
function update() {
GetTournament(id).then((t) => {
console.log(t);
tournament = t;
});
}
$effect(update);
onMount(update);
</script>
<div></div>
{#if tournament}
<section class="grid grid-cols-2 p-5">
<Heading>{tournament.Title}</Heading>
<Button on:click={() => ExportTournament(tournament)}>Export</Button>
</section>
<Tabs>
<TabItem open title="Participants">
<Participants tournamentID={tournament.ID} />
</TabItem>
<TabItem title="Matches">
<Matches tournamentID={tournament.ID} />
</TabItem>
</Tabs>
{/if}

View File

@ -1,7 +1,5 @@
import sveltePreprocess from 'svelte-preprocess'
export default {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: sveltePreprocess()
}

View File

@ -12,6 +12,7 @@
* Note that setting allowJs false does not prevent the use
* of JS in `.svelte` files.
*/
"verbatimModuleSyntax": true,
"allowJs": true,
"checkJs": true,
"isolatedModules": true

View File

@ -0,0 +1,10 @@
// vite.config.ts
import { defineConfig } from "file:///home/schreifuchs/go/src/git.schreifuchs.ch/schreifuchs/regio-ue1/frontend/node_modules/.pnpm/vite@5.4.14_sass@1.83.4/node_modules/vite/dist/node/index.js";
import { svelte } from "file:///home/schreifuchs/go/src/git.schreifuchs.ch/schreifuchs/regio-ue1/frontend/node_modules/.pnpm/@sveltejs+vite-plugin-svelte@4.0.4_svelte@5.19.9_vite@5.4.14_sass@1.83.4_/node_modules/@sveltejs/vite-plugin-svelte/src/index.js";
var vite_config_default = defineConfig({
plugins: [svelte()]
});
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCIvaG9tZS9zY2hyZWlmdWNocy9nby9zcmMvZ2l0LnNjaHJlaWZ1Y2hzLmNoL3NjaHJlaWZ1Y2hzL3JlZ2lvLXVlMS9mcm9udGVuZFwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL2hvbWUvc2NocmVpZnVjaHMvZ28vc3JjL2dpdC5zY2hyZWlmdWNocy5jaC9zY2hyZWlmdWNocy9yZWdpby11ZTEvZnJvbnRlbmQvdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL2hvbWUvc2NocmVpZnVjaHMvZ28vc3JjL2dpdC5zY2hyZWlmdWNocy5jaC9zY2hyZWlmdWNocy9yZWdpby11ZTEvZnJvbnRlbmQvdml0ZS5jb25maWcudHNcIjtpbXBvcnQge2RlZmluZUNvbmZpZ30gZnJvbSAndml0ZSdcbmltcG9ydCB7c3ZlbHRlfSBmcm9tICdAc3ZlbHRlanMvdml0ZS1wbHVnaW4tc3ZlbHRlJ1xuXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xuZXhwb3J0IGRlZmF1bHQgZGVmaW5lQ29uZmlnKHtcbiAgcGx1Z2luczogW3N2ZWx0ZSgpXVxufSlcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFBZ1osU0FBUSxvQkFBbUI7QUFDM2EsU0FBUSxjQUFhO0FBR3JCLElBQU8sc0JBQVEsYUFBYTtBQUFBLEVBQzFCLFNBQVMsQ0FBQyxPQUFPLENBQUM7QUFDcEIsQ0FBQzsiLAogICJuYW1lcyI6IFtdCn0K

View File

@ -1,4 +1,27 @@
// 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<string>;
export function DeleteParticipat(arg1:model.Participant):Promise<void>;
export function ExportTournament(arg1:model.Tournament):Promise<void>;
export function FillRandom(arg1:model.Tournament):Promise<void>;
export function GetGames():Promise<Array<model.Game>>;
export function GetMatches(arg1:number):Promise<Array<any>>;
export function GetParticipants():Promise<Array<model.Participant>>;
export function GetTournament(arg1:number):Promise<model.Tournament>;
export function GetTournaments():Promise<Array<model.Tournament>>;
export function RemoveParticipantFromTournament(arg1:model.Participant,arg2:model.Tournament):Promise<void>;
export function SaveParticipant(arg1:model.Participant):Promise<void>;
export function SaveTournament(arg1:model.Tournament):Promise<void>;
export function StartTournament(arg1:model.Tournament):Promise<void>;

View File

@ -2,6 +2,50 @@
// 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 DeleteParticipat(arg1) {
return window['go']['main']['App']['DeleteParticipat'](arg1);
}
export function ExportTournament(arg1) {
return window['go']['main']['App']['ExportTournament'](arg1);
}
export function FillRandom(arg1) {
return window['go']['main']['App']['FillRandom'](arg1);
}
export function GetGames() {
return window['go']['main']['App']['GetGames']();
}
export function GetMatches(arg1) {
return window['go']['main']['App']['GetMatches'](arg1);
}
export function GetParticipants() {
return window['go']['main']['App']['GetParticipants']();
}
export function GetTournament(arg1) {
return window['go']['main']['App']['GetTournament'](arg1);
}
export function GetTournaments() {
return window['go']['main']['App']['GetTournaments']();
}
export function RemoveParticipantFromTournament(arg1, arg2) {
return window['go']['main']['App']['RemoveParticipantFromTournament'](arg1, arg2);
}
export function SaveParticipant(arg1) {
return window['go']['main']['App']['SaveParticipant'](arg1);
}
export function SaveTournament(arg1) {
return window['go']['main']['App']['SaveTournament'](arg1);
}
export function StartTournament(arg1) {
return window['go']['main']['App']['StartTournament'](arg1);
}

View File

@ -1,19 +1,208 @@
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[];
Matches: Match[];
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);
this.Matches = this.convertValues(source["Matches"], Match);
}
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;
Size?: 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.Size = source["Size"];
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;
}
}
export class Match {
ID: number;
// Go type: time
CreatedAt: any;
// Go type: time
UpdatedAt: any;
// Go type: gorm
DeletedAt: any;
TournamentID: number;
Stage: number;
Order: number;
Participant1ID: number;
Participant1: Participant;
Participant2ID: number;
Participant2: Participant;
WinnierParticipantID: number;
WinnierParticipant: Participant;
static createFrom(source: any = {}) {
return new Match(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.TournamentID = source["TournamentID"];
this.Stage = source["Stage"];
this.Order = source["Order"];
this.Participant1ID = source["Participant1ID"];
this.Participant1 = this.convertValues(source["Participant1"], Participant);
this.Participant2ID = source["Participant2ID"];
this.Participant2 = this.convertValues(source["Participant2"], Participant);
this.WinnierParticipantID = source["WinnierParticipantID"];
this.WinnierParticipant = this.convertValues(source["WinnierParticipant"], 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;
}
}
}

View File

@ -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<void>;
export function GetThings():Promise<Array<things.Thing>>;
export function NewThing(arg1:string):Promise<void>;

View File

@ -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);
}

13
go.mod
View File

@ -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

14
go.sum
View File

@ -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=

View File

@ -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,
},
})

36
model/init.go Normal file
View File

@ -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
}

44
model/model.go Normal file
View File

@ -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 `json:"Size,string,omitempty"` // 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 // number of prarticipants
TournamentState int
WinnierParticipantID int
WinnierParticipant Participant `gorm:"foreignKey:WinnierParticipantID"`
Participants []*Participant `gorm:"many2many:partcipant_tournaments;"`
Matches []Match
}
type Match struct {
gorm.Model
TournamentID uint
Stage int
Order int
Participant1ID uint
Participant1 Participant `gorm:"foreignKey:Participant1ID"`
Participant2ID uint
Participant2 Participant `gorm:"foreignKey:Participant2ID"`
WinnierParticipantID uint
WinnierParticipant Participant `gorm:"foreignKey:WinnierParticipantID"`
}

65
model/names.go Normal file
View File

@ -0,0 +1,65 @@
package model
import (
"crypto/rand"
"math/big"
)
var funnyNames = []string{
"Captain Quirk",
"Giggle Muffin",
"Bubbles McFarty",
"Dapper Dingle",
"Wacky McWiggles",
"Sir Laughs-a-Lot",
"Chuckles the Chipmunk",
"Fuzzy Pickles",
"Snickerdoodle Sprout",
"Zany Zucchini",
"Professor Pudding",
"Bumbling Bumblebee",
"Cheeky Monkey",
"Silly Sausage",
"Wobble Bottom",
"Grinning Goblin",
"Fluffy Fiasco",
"Tickle Tortilla",
"Jolly Jester",
"Merry Marmalade",
"Wacky Wonka",
"Noodle Nugget",
"Bubblegum Bandit",
"Funky Ferret",
"Giggle Gopher",
"Happy Hiccup",
"Nifty Noodle",
"Dizzy Donut",
"Bouncy Biscuit",
"Frolic Fox",
"Whimsical Wombat",
"Peppy Pumpernickel",
"Loco Lobster",
"Sassy Sasquatch",
"Rambunctious Radish",
"Prankster Panda",
"Zippy Zebra",
"Giggling Giraffe",
"Funky Flamingo",
"Silly Sphinx",
"Guffawing Gopher",
"Cheerful Cucumber",
"Hapless Hedgehog",
"Jovial Jalapeño",
"Bubbly Banana",
"Quirky Quokka",
"Dandy Dodo",
"Laughing Llama",
"Zany Zephyr",
}
func RandomName() string {
x := big.NewInt(int64(len(funnyNames) - 1))
i, _ := rand.Int(rand.Reader, x)
return funnyNames[i.Int64()]
}

View File

@ -1,43 +0,0 @@
package things
import "slices"
type Thing struct {
ID int
Name string
}
type Service struct {
things map[int]Thing
maxID int
}
func NewThingsService() *Service {
return &Service{
things: make(map[int]Thing),
}
}
func (s *Service) NewThing(name string) {
s.maxID++
s.things[s.maxID] = Thing{
Name: name,
ID: s.maxID,
}
print(name)
}
func (s *Service) GetThings() []Thing {
things := make([]Thing, 0, len(s.things))
for _, t := range s.things {
things = append(things, t)
}
slices.SortFunc(things, func(a, b Thing) int { return a.ID - b.ID })
return things
}
func (s *Service) DeleteThing(id int) {
delete(s.things, id)
}

BIN
tournament.db Normal file

Binary file not shown.