package web import ( "log" "git.kapelle.org/niklas/beerpong-elo/internal/model" "git.kapelle.org/niklas/beerpong-elo/internal/repo" "github.com/graphql-go/graphql" ) func createShema(repo repo.Repo) graphql.Schema { player := graphql.NewObject(graphql.ObjectConfig{ Name: "Player", Description: "A player. Can also be authors of games", Fields: graphql.Fields{ "ID": &graphql.Field{ Type: graphql.NewNonNull(graphql.ID), }, "name": &graphql.Field{ Type: graphql.NewNonNull(graphql.String), }, "elo": &graphql.Field{ Type: graphql.NewNonNull(graphql.Int), }, // Field "games" added below // Field "history" added below }, }) game := graphql.NewObject(graphql.ObjectConfig{ Name: "Game", Description: "A game played", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.NewNonNull(graphql.ID), }, "added": &graphql.Field{ Type: graphql.NewNonNull(graphql.DateTime), }, "overtime": &graphql.Field{ Type: graphql.NewNonNull(graphql.Boolean), }, "score": &graphql.Field{ Type: graphql.NewNonNull(graphql.Int), }, "author": &graphql.Field{ Type: graphql.NewNonNull(player), Resolve: func(p graphql.ResolveParams) (interface{}, error) { game, ok := p.Source.(*model.Game) if !ok { log.Printf("Can't get source for field 'author' on 'Game' is %v", p.Source) return nil, nil } player, err := repo.GetPlayer(game.Author) if err != nil { return nil, err } return player, nil }, }, "team0player0": &graphql.Field{ Type: graphql.NewNonNull(player), Resolve: func(p graphql.ResolveParams) (interface{}, error) { game, ok := p.Source.(*model.Game) if !ok { log.Printf("Can't get source for field 'team0player0' on 'Game' is %v", p.Source) return nil, nil } player, err := repo.GetPlayer(game.Team0Player0) if err != nil { return nil, err } return player, nil }, }, "team0player1": &graphql.Field{ Type: graphql.NewNonNull(player), Resolve: func(p graphql.ResolveParams) (interface{}, error) { game, ok := p.Source.(*model.Game) if !ok { log.Printf("Can't get source for field 'team0player1' on 'Game' is %v", p.Source) return nil, nil } player, err := repo.GetPlayer(game.Team0Player1) if err != nil { return nil, err } return player, nil }, }, "team1player0": &graphql.Field{ Type: graphql.NewNonNull(player), Resolve: func(p graphql.ResolveParams) (interface{}, error) { game, ok := p.Source.(*model.Game) if !ok { log.Printf("Can't get source for field 'team1player0' on 'Game' is %v", p.Source) return nil, nil } player, err := repo.GetPlayer(game.Team1Player0) if err != nil { return nil, err } return player, nil }, }, "team1player1": &graphql.Field{ Type: graphql.NewNonNull(player), Resolve: func(p graphql.ResolveParams) (interface{}, error) { game, ok := p.Source.(*model.Game) if !ok { log.Printf("Can't get source for field 'team1player1' on 'Game' is %v", p.Source) return nil, nil } player, err := repo.GetPlayer(game.Team1Player1) if err != nil { return nil, err } return player, nil }, }, }, }) player.AddFieldConfig("games", &graphql.Field{ Type: graphql.NewNonNull(graphql.NewList(game)), Resolve: func(p graphql.ResolveParams) (interface{}, error) { player, ok := p.Source.(*model.Player) if !ok { log.Printf("Can't get source for field 'games' on 'Player' is %v", p.Source) return nil, nil } games, err := repo.GetGamesForPlayer(player.ID) if err != nil { return nil, err } return games, nil }, }) gameResult := graphql.NewObject(graphql.ObjectConfig{ Name: "GameResult", Description: "The ELO change for a player in a game", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.NewNonNull(graphql.ID), }, "player": &graphql.Field{ Type: player, Resolve: func(p graphql.ResolveParams) (interface{}, error) { gameResult, ok := p.Source.(*model.GameResult) if !ok { log.Printf("Can't get source for field 'player' on 'GameResult' is %v", p.Source) return nil, nil } player, err := repo.GetPlayer(gameResult.Player) if err != nil { return nil, err } return player, nil }, }, "game": &graphql.Field{ Type: graphql.NewNonNull(game), Resolve: func(p graphql.ResolveParams) (interface{}, error) { gameResult, ok := p.Source.(*model.GameResult) if !ok { log.Printf("Can't get source for field 'game' on 'GameResult' is %v", p.Source) return nil, nil } game, err := repo.GetGame(gameResult.Game) if err != nil { return nil, err } return game, nil }, }, "startElo": &graphql.Field{ Type: graphql.NewNonNull(graphql.Int), }, "endElo": &graphql.Field{ Type: graphql.NewNonNull(graphql.Int), }, "delta": &graphql.Field{ Type: graphql.NewNonNull(graphql.Int), Resolve: func(p graphql.ResolveParams) (interface{}, error) { gameResult, ok := p.Source.(*model.GameResult) if !ok { log.Printf("Can't get source for field 'delta' on 'GameResult' is %v", p.Source) return nil, nil } delta := gameResult.EndElo - gameResult.StartElo return delta, nil }, }, }, }) player.AddFieldConfig("history", &graphql.Field{ Type: graphql.NewNonNull(graphql.NewList(gameResult)), Args: graphql.FieldConfigArgument{ "game": &graphql.ArgumentConfig{ Type: graphql.ID, Description: "Filter by Game ID", }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { player, ok := p.Source.(*model.Player) if !ok { log.Printf("Can't get source from field 'history' on 'player' is %v", p.Source) return nil, nil } if p.Args["game"] != nil { // Find result for single game gameID, ok := p.Args["game"].(string) if !ok { log.Printf("Failed to parse 'game' at field 'history' on 'player' is %v", p.Args["game"]) return nil, nil } gameResult, err := repo.GetGameResultForPlayerAndGame(model.GameID(gameID), player.ID) if err != nil { return nil, err } return []*model.GameResult{gameResult}, nil } // Find all gameResults for a player gameResults, err := repo.GetGameResultsForPlayer(player.ID) if err != nil { return nil, err } return gameResults, nil }, }) queryFields := graphql.Fields{ "player": &graphql.Field{ Type: player, Description: "Get player by ID", Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.ID), }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { id, ok := p.Args["id"].(string) if !ok { log.Printf("Failed to parse ID at player: %v", p.Args["id"]) return nil, nil } player, err := repo.GetPlayer(model.PlayerID(id)) if err != nil { return nil, err } return player, nil }, }, "game": &graphql.Field{ Type: game, Description: "Get game by ID", Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.ID), }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { id, ok := p.Args["id"].(string) if !ok { log.Printf("Failed to parse ID at game: %v", p.Args["id"]) return nil, nil } game, err := repo.GetGame(model.GameID(id)) if err != nil { return nil, err } return game, nil }, }, "gameResult": &graphql.Field{ Type: gameResult, Description: "Result of a game on a players ELO", Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.ID), }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { id, ok := p.Args["id"].(string) if !ok { log.Printf("Failed to parse ID at gameResult: %v", p.Args["id"]) return nil, nil } gameResult, err := repo.GetGameResult(model.GameResultID(id)) if err != nil { return nil, err } return gameResult, nil }, }, "players": &graphql.Field{ Type: graphql.NewNonNull(graphql.NewList(player)), Description: "Get all players", Resolve: func(p graphql.ResolveParams) (interface{}, error) { players, err := repo.GetPlayers() if err != nil { return nil, err } return players, nil }, }, "games": &graphql.Field{ Type: graphql.NewNonNull(graphql.NewList(game)), Description: "Get all games", Resolve: func(p graphql.ResolveParams) (interface{}, error) { games, err := repo.GetGames() if err != nil { return nil, err } return games, nil }, }, } querySchema := graphql.ObjectConfig{ Name: "Query", Fields: queryFields, } schemaConfig := graphql.SchemaConfig{Query: graphql.NewObject(querySchema)} schema, err := graphql.NewSchema(schemaConfig) if err != nil { log.Fatalf("failed to create new schema, error: %v", err) } return schema }