From ce0fc2f4894656d18393bb4bd53e93beccade50c Mon Sep 17 00:00:00 2001 From: Sendou <38327916+Sendouc@users.noreply.github.com> Date: Sun, 14 Jun 2020 12:51:38 +0300 Subject: [PATCH] create team backend --- frontend-react/package-lock.json | 6 +- frontend-react/package.json | 2 +- graphql-schemas/team.js | 151 ++++++++++++++++--------------- graphql-schemas/user.js | 21 +---- index.js | 30 +----- mongoose-models/team.js | 38 ++++---- package.json | 1 + utils/mocks.js | 21 +++++ 8 files changed, 131 insertions(+), 139 deletions(-) create mode 100644 utils/mocks.js diff --git a/frontend-react/package-lock.json b/frontend-react/package-lock.json index 87c5da676..45321158b 100644 --- a/frontend-react/package-lock.json +++ b/frontend-react/package-lock.json @@ -2304,9 +2304,9 @@ } }, "@types/jest": { - "version": "25.2.3", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-25.2.3.tgz", - "integrity": "sha512-JXc1nK/tXHiDhV55dvfzqtmP4S3sy3T3ouV2tkViZgxY/zeUkcpQcQPGRlgF4KmWzWW5oiWYSZwtCB+2RsE4Fw==", + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.0.tgz", + "integrity": "sha512-/yeMsH9HQ1RLORlXAwoLXe8S98xxvhNtUz3yrgrwbaxYjT+6SFPZZRksmRKRA6L5vsUtSHeN71viDOTTyYAD+g==", "requires": { "jest-diff": "^25.2.1", "pretty-format": "^25.2.1" diff --git a/frontend-react/package.json b/frontend-react/package.json index afb5ea0af..e51da2a94 100644 --- a/frontend-react/package.json +++ b/frontend-react/package.json @@ -13,7 +13,7 @@ "@testing-library/jest-dom": "^5.10.0", "@testing-library/react": "^10.2.1", "@testing-library/user-event": "^11.4.2", - "@types/jest": "^25.2.3", + "@types/jest": "^26.0.0", "@types/reach__router": "^1.3.5", "@types/react": "^16.9.36", "@types/react-color": "^3.0.2", diff --git a/graphql-schemas/team.js b/graphql-schemas/team.js index cb1a997cd..f9e52f9fb 100644 --- a/graphql-schemas/team.js +++ b/graphql-schemas/team.js @@ -1,6 +1,9 @@ const { UserInputError, gql } = require("apollo-server-express") +const { v4: uuidv4 } = require("uuid") const Team = require("../mongoose-models/team") const User = require("../mongoose-models/user") +const Placement = require("../mongoose-models/placement") +const Player = require("../mongoose-models/player") const typeDef = gql` extend type Query { @@ -9,54 +12,80 @@ const typeDef = gql` } extend type Mutation { - addTeam(name: String!): Team! - addResult( - date: String! - tweet_id: String - tournament_name: String! - placement: Int! - ): Boolean! + addTeam(name: String!): Boolean! } extend type User { team: Team } - type Result { - date: String! - tweet_id: String - tournament_name: String! - placement: Int! - } - type Founded { month: Int! year: Int! } + type Member { + discordId: String! + captain: Boolean + role: String + } + + type TeamMemberPlacement { + discordId: String! + mode: Int! + weapon: String! + month: Int! + year: Int! + xPower: Float! + } + type Team { name: String! - twitter_name: String - challonge_name: String - discord_url: String + disbanded: Boolean founded: Founded - captain_discord_id: String! - member_discord_ids: [String!]! - member_users: [User!]! - countries: [String!]! + members: [Member!] + pastMembersDiscordIds: [String] tag: String - lf_post: String - tournament_results: [Result!]! + # inviteCode: String + lfPost: String + xpPlacements: [TeamMemberPlacement!] + teamXp: Float } ` + +const getUsersBestPlacement = async (twitter, discordId) => { + if (!twitter) return null + + const player = await Player.findOne({ twitter }) + if (!player) return null + + const placements = await Placement.find({ unique_id: player.unique_id }) + if (!placements.length) return null + + const best = placements.reduce((best, placement) => { + if (placement.x_power > best.x_power) return placement + + return best + }) + + return { + discordId, + mode: best.mode, + weapon: best.weapon, + month: best.month, + year: best.year, + xPower: best.x_power, + } +} + const resolvers = { Query: { - teams: (root, args) => Team.find({}), - searchForTeam: (root, { name }) => { - const name_regex = `^${name.replace("-", " ")}$` + teams: () => Team.find({}), + searchForTeam: (_root, args) => { + const name_regex = `^${args.name.replace("-", " ")}$` return Team.findOne({ name: { $regex: new RegExp(name_regex, "i") }, - }).populate("member_users") + }).populate("memberUsers") }, }, Mutation: { @@ -78,59 +107,37 @@ const resolvers = { const name_regex = `^${name}$` const existing_team = await Team.findOne({ name: { $regex: new RegExp(name_regex, "i") }, + disbanded: { $ne: true }, }) - if (existing_team) + if (existing_team) { throw new UserInputError("Team with this name already exists") + } + + const bestPlacement = await getUsersBestPlacement( + user.twitter_name, + user.discord_id + ) + const teamXp = bestPlacement + ? (bestPlacement.xPower + 2000 * 3) / 4 + : undefined + const xpPlacements = bestPlacement ? [bestPlacement] : undefined const team = new Team({ name, - captain_discord_id: user.discord_id, - member_discord_ids: [user.discord_id], + members: [ + { + discordId: user.discord_id, + captain: true, + }, + ], + inviteCode: uuidv4(), + teamXp, + xpPlacements, }) + await User.findByIdAndUpdate(user._id, { $set: { team: team._id } }) - return team.save() - }, - addResult: async (root, args, { user }) => { - if (!user) { - throw new UserInputError("Must be logged in") - } - - const team = await Team.findById(user.team) - - if (!team) throw new UserInputError("Not a team captain") - - if (team.tournament_results.length > 100) { - throw new UserInputError("Can't have more than 100 tournament results") - } - - if (Date.parse(args.date) === NaN) { - throw new UserInputError("Invalid date") - } - - if (args.tweet_id && isNaN(args.tweet_id)) { - throw new UserInputError("Tweet ID can only contain numbers") - } - - if ( - args.tournament_name.length < 2 || - args.tournament_name.length > 100 - ) { - throw new UserInputError( - "Tournament name has to be between 2 and 100 characters long" - ) - } - - if (args.placement < 1 || args.placement > 500) { - throw new UserInputError("Placement has to be between 1 and 500") - } - - team.tournament_results.push({ - date: args.date, - tournament_name: args.tournament_name, - placement: args.placement, - tweet_id: args.tweet_id, - }) await team.save() + return true }, }, diff --git a/graphql-schemas/user.js b/graphql-schemas/user.js index b8bc0604d..79a0a9b06 100644 --- a/graphql-schemas/user.js +++ b/graphql-schemas/user.js @@ -3,6 +3,7 @@ const User = require("../mongoose-models/user") const Player = require("../mongoose-models/player") const countries = require("../utils/countries") const weapons = require("../utils/weapons") +const mockUser = require("../utils/mocks") require("dotenv").config() const typeDef = gql` @@ -90,25 +91,7 @@ const resolvers = { Query: { user: (root, args, ctx) => { if (process.env.LOGGED_IN) { - return { - id: "5cee8f73d1120d4315c55011", - team: "5e3ecc0ea7dd3830303eaaa7", - discord_id: "79237403620945920", - __v: 0, - avatar: "a22c9557975494f859242aaf9b317058", - discriminator: "0043", - twitch_name: "sendou", - twitter_name: "sendouc", - username: "Sendou", - top500: true, - custom_url: "sendou", - plus: { - membership_status: "ONE", - vouch_status: null, - plus_region: "EU", - can_vouch: "ONE", - }, - } + return { user: mockUser } } return ctx.user }, diff --git a/index.js b/index.js index 5414e9dec..5a2e67c9e 100644 --- a/index.js +++ b/index.js @@ -13,6 +13,7 @@ const User = require("./mongoose-models/user") const Player = require("./mongoose-models/player") const path = require("path") const schema = require("./schema") +const mockUser = require("./utils/mocks") mongoose.set("useFindAndModify", false) mongoose.set("useCreateIndex", true) @@ -98,34 +99,7 @@ const server = new ApolloServer({ schema, context: ({ req }) => { if (process.env.LOGGED_IN) { - return { - user: { - _id: "5cee8f73d1120d4315c55011", - team: "5e3ecc0ea7dd3830303eaaa7", - discord_id: "79237403620945920", - __v: 0, - avatar: "2e292c1b5d1366c24a9e4b6c1cffc700", - discriminator: "0043", - twitch_name: "sendou", - twitter_name: "sendouc", - username: "Sendou", - custom_url: "sendou", - weapons: [ - "Tenta Brella", - "Range Blaster", - "Kensa Sloshing Machine", - "Custom Blaster", - ], - country: "fi", - top500: true, - plus: { - membership_status: "ONE", - vouch_status: null, - plus_region: "EU", - can_vouch: "ONE", - }, - }, - } + return { user: mockUser } } return { user: req.user } }, diff --git a/mongoose-models/team.js b/mongoose-models/team.js index 5bee0f403..f63b03a2b 100644 --- a/mongoose-models/team.js +++ b/mongoose-models/team.js @@ -2,32 +2,38 @@ const mongoose = require("mongoose") const teamSchema = new mongoose.Schema({ name: String, - twitter_name: String, - challonge_name: String, - discord_url: String, + disbanded: Boolean, founded: { month: Number, year: Number, }, - captain_discord_id: String, - member_discord_ids: [String], - countries: [String], - tag: String, - invite_code: String, - lf_post: String, - tournament_results: [ + members: [ { - date: Date, - tweet_id: String, - tournament_name: String, - placement: Number, + discordId: String, + captain: Boolean, + role: String, }, ], + pastMembersDiscordIds: [String], + tag: String, + inviteCode: String, + lfPost: String, + xpPlacements: [ + { + discordId: String, + mode: Number, + weapon: String, + month: Number, + year: Number, + xPower: Number, + }, + ], + teamXp: Number, }) -teamSchema.virtual("member_users", { +teamSchema.virtual("memberUsers", { ref: "User", - localField: "member_discord_ids", + localField: "members.discordId", foreignField: "discord_id", }) diff --git a/package.json b/package.json index 136946e20..07d8cea3d 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "node-fetch": "^2.6.0", "passport": "^0.4.1", "passport-discord": "^0.1.4", + "uuid": "^8.1.0", "webhook-discord": "^3.7.3" }, "devDependencies": { diff --git a/utils/mocks.js b/utils/mocks.js new file mode 100644 index 000000000..17ad154bc --- /dev/null +++ b/utils/mocks.js @@ -0,0 +1,21 @@ +const mockUser = { + id: "5cee8f73d1120d4315c55011", + //team: "5e3ecc0ea7dd3830303eaaa7", + discord_id: "79237403620945920", + __v: 0, + avatar: "a22c9557975494f859242aaf9b317058", + discriminator: "0043", + twitch_name: "sendou", + twitter_name: "sendouc", + username: "Sendou", + top500: true, + custom_url: "sendou", + plus: { + membership_status: "ONE", + vouch_status: null, + plus_region: "EU", + can_vouch: "ONE", + }, +} + +module.exports = mockUser