From 4d7ca7fb7fa84b1ed22a389c2012f14575100603 Mon Sep 17 00:00:00 2001 From: Sendou Date: Sun, 15 Mar 2020 03:50:13 +0200 Subject: [PATCH] map list ballot vote generation backend code --- .../src/components/builds/BuildCard.tsx | 2 +- .../src/components/plus/MapVoting.tsx | 4 +- graphql-schemas/fapost.js | 36 ++++ graphql-schemas/maps.js | 168 +++++++++++++++++- 4 files changed, 202 insertions(+), 8 deletions(-) diff --git a/frontend-react/src/components/builds/BuildCard.tsx b/frontend-react/src/components/builds/BuildCard.tsx index 30be68e8e..dee9ab59b 100644 --- a/frontend-react/src/components/builds/BuildCard.tsx +++ b/frontend-react/src/components/builds/BuildCard.tsx @@ -78,7 +78,7 @@ const BuildCard: React.FC = ({ ml="8px" mt="1em" > - {new Date(parseInt(build.updatedAt)).toLocaleString()} + {new Date(parseInt(build.updatedAt)).toLocaleDateString()} {build.title && ( diff --git a/frontend-react/src/components/plus/MapVoting.tsx b/frontend-react/src/components/plus/MapVoting.tsx index aec1f8580..be344fc7e 100644 --- a/frontend-react/src/components/plus/MapVoting.tsx +++ b/frontend-react/src/components/plus/MapVoting.tsx @@ -7,7 +7,7 @@ import Loading from "../common/Loading" import { Helmet } from "react-helmet-async" import PageHeader from "../common/PageHeader" import MapVoteGrid from "./MapVoteGrid" -import { Box, useToast } from "@chakra-ui/core" +import { useToast } from "@chakra-ui/core" import Button from "../elements/Button" import { FaEnvelope, FaLongArrowAltLeft } from "react-icons/fa" import { @@ -17,7 +17,7 @@ import { import Alert from "../elements/Alert" import { USER } from "../../graphql/queries/user" -const MapVoting: React.FC = ({}) => { +const MapVoting: React.FC = () => { const { data, error, loading } = useQuery(MAP_VOTES) const { data: userData, diff --git a/graphql-schemas/fapost.js b/graphql-schemas/fapost.js index bfcd8dee0..ab767ac63 100644 --- a/graphql-schemas/fapost.js +++ b/graphql-schemas/fapost.js @@ -13,6 +13,7 @@ const playstyleValues = ["FRONTLINE", "MIDLINE", "BACKLINE"] const typeDef = gql` extend type Query { freeAgentPosts: [FAPost!]! + freeAgentMatches: FAMatches! } extend type Mutation { @@ -50,6 +51,11 @@ const typeDef = gql` BACKLINE } + type FAMatches { + matched_discord_ids: [String!]! + number_of_likes_received: Int! + } + "Represents a free agent post of a player looking for a team" type FAPost { id: ID! @@ -113,6 +119,36 @@ const resolvers = { }) }) }, + freeAgentMatches: async (root, args, ctx) => { + if (!ctx.user) throw new AuthenticationError("Not logged in.") + + const post = await FAPost.findOne({ discord_id: ctx.user.discord_id }) + + if (!post) { + throw new UserInputError("Not a free agent") + } + + const likesGiven = await FALike.find({ + liker_discord_id: ctx.user.discord_id, + }) + + const likesReceived = await FALike.find({ + liked_discord_id: ctx.user.discord_id, + }) + + const number_of_likes_received = likesReceived.length + const likerDiscordIds = likesReceived.map( + FALike => FALike.liker_discord_id + ) + + const matched_discord_ids = likesGiven.reduce((acc, cur) => { + if (likerDiscordIds.indexOf(cur.liked_discord_id) === -1) return acc + + return [...acc, cur.liked_discord_id] + }, []) + + return { matched_discord_ids, number_of_likes_received } + }, }, Mutation: { addFreeAgentPost: async (root, args, ctx) => { diff --git a/graphql-schemas/maps.js b/graphql-schemas/maps.js index 7f7b9031a..57bf635ba 100644 --- a/graphql-schemas/maps.js +++ b/graphql-schemas/maps.js @@ -23,6 +23,22 @@ const typeDef = gql` extend type Mutation { addMapVotes(votes: [MapVoteInput!]!): Boolean + generateMaplistFromVotes: Boolean + } + + type MapVoteCount { + name: String! + sz: [Int!]! + tc: [Int!]! + rm: [Int!]! + cb: [Int!]! + } + + type PlusMaplistInfo { + month: Int! + year: Int! + voter_count: Int! + vote_counts: [MapVoteCount!]! } type Maplist { @@ -31,6 +47,7 @@ const typeDef = gql` tc: [String!]! rm: [String!]! cb: [String!]! + plus: PlusMaplistInfo } type MapVote { @@ -40,11 +57,6 @@ const typeDef = gql` rm: Int! cb: Int! } - - # type MapBallot { - # discord_id: String! - # maps: [MapVote!]! - # } ` const resolvers = { @@ -115,6 +127,152 @@ const resolvers = { return true }, + generateMaplistFromVotes: async (root, args, ctx) => { + if (!ctx.user) throw new AuthenticationError("Not logged in") + if (ctx.user.discord_id !== process.env.ADMIN_ID) + throw new AuthenticationError("Not admin") + + const ballots = await MapBallot.find({}).populate("discord_user") + + const validBallots = ballots.filter( + ballot => !!ballot.discord_user.plus.membership_status + ) + + /*type MapVoteCount { + name: String! + sz: [Int!]! + tc: [Int!]! + rm: [Int!]! + cb: [Int!]! + }*/ + const voter_count = validBallots.length + const vote_counts = maps.map(stage => ({ + name: stage, + sz: [0, 0, 0], + tc: [0, 0, 0], + rm: [0, 0, 0], + cb: [0, 0, 0], + })) + + validBallots.forEach(ballot => + ballot.maps.forEach((stage, index) => { + const { sz, tc, rm, cb } = stage + // one is added to the index so -1 vote goes to 0 index, 0 to 1 and 1 to 2 + vote_counts[index].sz[sz + 1] = vote_counts[index].sz[sz + 1] + 1 + vote_counts[index].tc[tc + 1] = vote_counts[index].tc[tc + 1] + 1 + vote_counts[index].rm[rm + 1] = vote_counts[index].rm[rm + 1] + 1 + vote_counts[index].cb[cb + 1] = vote_counts[index].cb[cb + 1] + 1 + }) + ) + + let szMaps = [] + let tcMaps = [] + let rmMaps = [] + let cbMaps = [] + vote_counts.forEach(count => { + szMaps.push({ + name: count.name, + score: +((count.sz[0] * -1 + count.sz[2]) / voter_count).toFixed(2), + }) + tcMaps.push({ + name: count.name, + score: +((count.tc[0] * -1 + count.tc[2]) / voter_count).toFixed(2), + }) + rmMaps.push({ + name: count.name, + score: +((count.rm[0] * -1 + count.rm[2]) / voter_count).toFixed(2), + }) + cbMaps.push({ + name: count.name, + score: +((count.cb[0] * -1 + count.cb[2]) / voter_count).toFixed(2), + }) + }) + + szMaps = szMaps.sort((a, b) => b.score - a.score) + tcMaps = tcMaps.sort((a, b) => b.score - a.score) + rmMaps = rmMaps.sort((a, b) => b.score - a.score) + cbMaps = cbMaps.sort((a, b) => b.score - a.score) + + szMapPool = [] + tcMapPool = [] + rmMapPool = [] + cbMapPool = [] + + for (const stageObj of szMaps) { + if (szMapPool.length >= 8 && stageObj.score <= 0) { + break + } + + szMapPool.push(stageObj.name) + } + + for (const stageObj of tcMaps) { + if (tcMapPool.length >= 8 && stageObj.score <= 0) { + break + } + + tcMapPool.push(stageObj.name) + } + + for (const stageObj of rmMaps) { + if (rmMapPool.length >= 8 && stageObj.score <= 0) { + break + } + + rmMapPool.push(stageObj.name) + } + + for (const stageObj of cbMaps) { + console.log("cbMapPool.length", cbMapPool.length) + if (cbMapPool.length >= 8 && stageObj.score <= 0) { + break + } + + cbMapPool.push(stageObj.name) + } + + szMapPool.sort((a, b) => maps.indexOf(a) - maps.indexOf(b)) + tcMapPool.sort((a, b) => maps.indexOf(a) - maps.indexOf(b)) + rmMapPool.sort((a, b) => maps.indexOf(a) - maps.indexOf(b)) + cbMapPool.sort((a, b) => maps.indexOf(a) - maps.indexOf(b)) + + console.log("szMapPool", szMapPool) + console.log("tcMapPool", tcMapPool) + console.log("rmMapPool", rmMapPool) + console.log("cbMapPool", cbMapPool) + + /*type PlusMaplistInfo { + month: Int! + year: Int! + voter_count: Int! + vote_counts: [MapVoteCount!]! + } + + type Maplist { + name: String! + sz: [String!]! + tc: [String!]! + rm: [String!]! + cb: [String!]! + plus: PlusMaplistInfo + }*/ + + const maplist = { + name: `Plus Server getmonth getyear`, + sz: szMapPool, + tc: tcMapPool, + rm: rmMapPool, + cb: cbMapPool, + plus: { + month: 1, + year: 1999, + voter_count, + vote_counts, + }, + } + + console.log("maplist", maplist) + }, }, }