sendou.ink/graphql-schemas/tournament.js
2020-03-07 17:37:12 +02:00

249 lines
6.3 KiB
JavaScript

const { UserInputError, gql } = require("apollo-server-express")
const Tournament = require("../mongoose-models/tournament")
const Round = require("../mongoose-models/round")
const typeDef = gql`
extend type Query {
searchForTournamentById(id: String!): Tournament
searchForTournaments(
tournament_name: String
region: Region
player_name: String
unique_id: String
team_name: String
comp: [String]
stage: String
mode: Mode
page: Int
): TournamentCollection!
}
type Tournament {
id: ID!
name: String!
bracket: String
"True if the tournament was a Japanese one"
jpn: Boolean!
"Link to the Google Sheet containing ganbawoomy's data"
google_sheet_url: String
date: String!
"Top 5 of the most played weapons in the rounds recorded"
popular_weapons: [String!]!
winning_team_name: String!
winning_team_players: [String!]!
winning_team_unique_ids: [String]
rounds: [Round!]!
}
type TournamentCollection {
tournaments: [Tournament]!
pageCount: Int!
}
type Round {
tournament_id: Tournament!
stage: String!
"SZ/TC/RM/CB/TW"
mode: Mode!
"E.g. Quarter-Finals"
round_name: String!
"Order of the round. Smaller number means the round took place before."
round_number: Int!
"Order the match in the round. Smaller number means the match took place before."
game_number: Int!
winning_team_name: String!
winning_team_players: [String!]!
winning_team_unique_ids: [String]!
winning_team_weapons: [String!]!
winning_team_main_abilities: [[Ability]!]!
winning_team_sub_abilities: [[Ability]!]!
losing_team_name: String!
losing_team_players: [String!]!
losing_team_unique_ids: [String]!
losing_team_weapons: [String!]!
losing_team_main_abilities: [[Ability]!]!
losing_team_sub_abilities: [[Ability]!]!
}
enum Mode {
SZ
TC
RM
CB
TW
}
enum Region {
all
western
jpn
}
`
const resolvers = {
Query: {
searchForTournamentById: async (root, args) => {
if (!args.id.match(/^[0-9a-fA-F]{24}$/)) return null
const rounds = await Round.find({ tournament_id: args.id })
.sort({ round_number: "asc", game_number: "asc" })
.catch(e => {
throw new UserInputError(e.message, {
invalidArgs: args,
})
})
const tournament = await Tournament.findById(args.id).catch(e => {
throw new UserInputError(e.message, {
invalidArgs: args,
})
})
if (!tournament) return null
tournament.rounds = rounds
return tournament
},
searchForTournaments: async (root, args) => {
Object.keys(args).forEach(
key => (args[key] == null || args[key].length === 0) && delete args[key]
)
const tournamentsPerPage = 18
const currentPage = args.page ? args.page - 1 : 0
const roundSearchCriteria = {
$or: [],
}
if (args.team_name) {
roundSearchCriteria.$or.push({
winning_team_name: {
$regex: args.team_name,
$options: "i",
},
})
roundSearchCriteria.$or.push({
losing_team_name: {
$regex: args.team_name,
$options: "i",
},
})
}
if (args.player_name) {
roundSearchCriteria.$or.push({
winning_team_players: {
$regex: args.player_name,
$options: "i",
},
})
roundSearchCriteria.$or.push({
losing_team_players: {
$regex: args.player_name,
$options: "i",
},
})
}
if (args.unique_id) {
roundSearchCriteria.$or.push({
winning_team_unique_ids: {
$regex: args.unique_id,
$options: "i",
},
})
roundSearchCriteria.$or.push({
losing_team_unique_ids: {
$regex: args.unique_id,
$options: "i",
},
})
}
if (args.comp) {
roundSearchCriteria.$or.push({
winning_team_weapons: {
$all: args.comp,
},
})
roundSearchCriteria.$or.push({
losing_team_weapons: {
$all: args.comp,
},
})
}
if (args.mode) {
roundSearchCriteria.mode = args.mode
}
if (args.stage) {
roundSearchCriteria.stage = args.stage
}
// if criteria were presented that we have to search
// from the Round collection
let tournament_ids = null
const tournamentSearchCriteria = {}
if (args.region && args.region === "western")
tournamentSearchCriteria.jpn = false
if (args.region && args.region === "jpn")
tournamentSearchCriteria.jpn = true
if (roundSearchCriteria.$or.length === 0) {
delete roundSearchCriteria.$or
}
if (
roundSearchCriteria.$or ||
roundSearchCriteria.stage ||
roundSearchCriteria.mode
) {
tournament_ids = await Round.find(roundSearchCriteria).distinct(
"tournament_id"
)
tournamentSearchCriteria._id = {
$in: tournament_ids,
}
}
if (args.tournament_name)
tournamentSearchCriteria.name = {
$regex: args.tournament_name,
$options: "i",
}
const tournamentCount = await Tournament.countDocuments(
tournamentSearchCriteria
).catch(e => {
throw new UserInputError(e.message, {
invalidArgs: args,
})
})
const pageCount = Math.ceil(tournamentCount / tournamentsPerPage)
// if 0 documents we don't care if the page is wrong
if (tournamentCount !== 0) {
if (args.page > pageCount)
throw new UserInputError("too big page number given", {
invalidArgs: args,
})
}
const tournaments = await Tournament.find(tournamentSearchCriteria)
.skip(tournamentsPerPage * currentPage)
.limit(tournamentsPerPage)
.sort({ date: "desc" })
.catch(e => {
throw new UserInputError(e.message, {
invalidArgs: args,
})
})
return { tournaments, pageCount }
},
},
}
module.exports = {
Tournament: typeDef,
tournamentResolvers: resolvers,
}