From 90a167cfb42a91e6906fb7baa0b0f40c60b31025 Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Wed, 24 Oct 2018 15:30:54 -0400 Subject: [PATCH 01/11] Playlist on player compare graphs --- .../service_layers/player/play_style.py | 5 ++- backend/blueprints/spa_api/spa_api.py | 3 +- .../PlayerComparePlayStyleCharts.tsx | 41 +++++++++++++++++-- .../Player/Compare/PlayerCompareContent.tsx | 10 ++++- 4 files changed, 51 insertions(+), 8 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/player/play_style.py b/backend/blueprints/spa_api/service_layers/player/play_style.py index b3849490c..7717fd2cc 100644 --- a/backend/blueprints/spa_api/service_layers/player/play_style.py +++ b/backend/blueprints/spa_api/service_layers/player/play_style.py @@ -50,7 +50,7 @@ def create_from_id(cls, id_: str, raw=False, rank=None, replay_ids=None, playlis ) @staticmethod - def create_all_stats_from_id(id_: str, rank=None, replay_ids=None) -> PlayerDataPoint: + def create_all_stats_from_id(id_: str, rank=None, replay_ids=None, playlist=None, win=None) -> PlayerDataPoint: session = current_app.config['db']() game_count = player_wrapper.get_total_games(session, id_) if game_count == 0: @@ -59,7 +59,8 @@ def create_all_stats_from_id(id_: str, rank=None, replay_ids=None) -> PlayerData rank = get_rank(id_) averaged_stats, global_stats = player_stat_wrapper.get_averaged_stats(session, id_, redis=current_app.config['r'], raw=True, - rank=rank, replay_ids=replay_ids) + rank=rank, replay_ids=replay_ids, + playlist=playlist, win=win) playstyle_data_raw: PlayerDataPoint = PlayerDataPoint(name=id_, data_points=[ DataPoint(k, averaged_stats[k]) diff --git a/backend/blueprints/spa_api/spa_api.py b/backend/blueprints/spa_api/spa_api.py index e51717d15..449d96e99 100644 --- a/backend/blueprints/spa_api/spa_api.py +++ b/backend/blueprints/spa_api/spa_api.py @@ -142,7 +142,8 @@ def api_get_player_play_style(id_): def api_get_player_play_style_all(id_): accepted_query_params = [ QueryParam(name='rank', optional=True, type_=int), - QueryParam(name='replay_ids', optional=True) + QueryParam(name='replay_ids', optional=True), + QueryParam(name='playlist', optional=True, type_=int), ] query_params = get_query_params(accepted_query_params, request) diff --git a/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx b/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx index 46079cc84..e77ef1465 100644 --- a/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx +++ b/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx @@ -2,12 +2,15 @@ import { FormControlLabel, Grid, Switch, Typography } from "@material-ui/core" import * as React from "react" import { PlayStyleRawResponse, PlayStyleResponse } from "src/Models" import { getPlayStyle, getPlayStyleRaw } from "../../../../Requests/Player/getPlayStyle" +import { PlaylistSelect } from "../../../Shared/Selects/PlaylistSelect" import { RankSelect } from "../../../Shared/Selects/RankSelect" import { PlayerPlayStyleChart } from "../../Overview/PlayStyle/PlayerPlayStyleChart" import { PlayerCompareTable } from "./PlayerCompareTable" interface Props { players: Player[] + playlist: number + handlePlaylistChange?: (playlist: number) => void } interface State { @@ -15,12 +18,19 @@ interface State { playerPlayStylesRaw: PlayStyleRawResponse[] rank: number heatmapMode: boolean + playlist: number } export class PlayerComparePlayStyleCharts extends React.PureComponent { constructor(props: Props) { super(props) - this.state = {playerPlayStyles: [], playerPlayStylesRaw: [], rank: -1, heatmapMode: false} + this.state = { + playerPlayStyles: [], + playerPlayStylesRaw: [], + rank: -1, + heatmapMode: false, + playlist: props.playlist + } } public componentDidMount() { @@ -46,6 +56,9 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent ) + + const dropDown = ( + + ) return ( <> @@ -75,6 +99,9 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent + + {dropDown} + {chartTitles.map((chartTitle, i) => { return ( { const rank = this.state.rank === -1 ? undefined : this.state.rank - Promise.all(players.map((player) => getPlayStyle(player.id, rank))) + Promise.all(players.map((player) => getPlayStyle(player.id, rank, this.state.playlist))) .then((playerPlayStyles) => { if (reload) { this.setState({playerPlayStyles}) @@ -113,7 +140,7 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent getPlayStyleRaw(player.id))) + Promise.all(players.map((player) => getPlayStyleRaw(player.id, this.state.playlist))) .then((playerPlayStylesRaw) => { if (reload) { this.setState({playerPlayStylesRaw}) @@ -142,4 +169,12 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent { this.setState({heatmapMode}) } + + private readonly handlePlaylistsChange: React.ChangeEventHandler = (event) => { + const selectedPlaylist = event.target.value as any as number + this.setState({playlist: selectedPlaylist}) + if (this.props.handlePlaylistChange) { + this.props.handlePlaylistChange(selectedPlaylist) + } + } } diff --git a/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx b/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx index c8e33535d..17144e7c1 100644 --- a/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx +++ b/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx @@ -11,12 +11,13 @@ type PlayerCompareTab = "Current" | "Progression" interface State { selectedTab: PlayerCompareTab + playlist: number } export class PlayerCompareContent extends React.PureComponent { constructor(props: Props) { super(props) - this.state = {selectedTab: "Current"} + this.state = {selectedTab: "Current", playlist: 13} } public render() { @@ -33,7 +34,8 @@ export class PlayerCompareContent extends React.PureComponent { {this.state.selectedTab === "Current" ?
- +
: @@ -50,4 +52,8 @@ export class PlayerCompareContent extends React.PureComponent { private readonly handleSelectTab = (event: React.ChangeEvent, selectedTab: PlayerCompareTab) => { this.setState({selectedTab}) } + + private readonly handlePlaylistChange = (playlist: number) => { + this.setState({playlist}) + } } From 1f914ede7ac12bbb5c2a106d87991bc48f530050 Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Wed, 24 Oct 2018 15:41:42 -0400 Subject: [PATCH 02/11] Playlist on progression page --- .../player/play_style_progression.py | 5 +-- backend/blueprints/spa_api/spa_api.py | 1 + .../wrapper/stats/player_stat_wrapper.py | 6 +++- .../Player/Compare/PlayerCompareContent.tsx | 3 +- .../Progression/PlayerProgressionCharts.tsx | 36 ++++++++++++++++--- webapp/src/Requests/Player/getProgression.ts | 4 ++- 6 files changed, 45 insertions(+), 10 deletions(-) diff --git a/backend/blueprints/spa_api/service_layers/player/play_style_progression.py b/backend/blueprints/spa_api/service_layers/player/play_style_progression.py index 18ebfdb06..ab92b9e23 100644 --- a/backend/blueprints/spa_api/service_layers/player/play_style_progression.py +++ b/backend/blueprints/spa_api/service_layers/player/play_style_progression.py @@ -18,13 +18,14 @@ class PlayStyleProgression: def create_progression(id_: str, time_unit: TimeUnit = None, start_date: datetime.datetime = None, - end_date: datetime.datetime = None) -> List['PlayStyleProgressionDataPoint']: + end_date: datetime.datetime = None, + playlist: int = None) -> List['PlayStyleProgressionDataPoint']: session = current_app.config['db']() game_count = player_wrapper.get_total_games(session, id_) if game_count == 0: raise UserHasNoReplays() data = player_stat_wrapper.get_progression_stats(session, id_, time_unit=time_unit, start_date=start_date, - end_date=end_date) + end_date=end_date, playlist=playlist) session.close() return [ diff --git a/backend/blueprints/spa_api/spa_api.py b/backend/blueprints/spa_api/spa_api.py index 449d96e99..dd5f8b2df 100644 --- a/backend/blueprints/spa_api/spa_api.py +++ b/backend/blueprints/spa_api/spa_api.py @@ -157,6 +157,7 @@ def api_get_player_play_style_progress(id_): QueryParam(name='time_unit', optional=True, type_=convert_to_enum(TimeUnit)), QueryParam(name='start_date', optional=True, type_=convert_to_datetime), QueryParam(name='end_date', optional=True, type_=convert_to_datetime), + QueryParam(name='playlist', optional=True, type_=int), ] query_params = get_query_params(accepted_query_params, request) diff --git a/backend/database/wrapper/stats/player_stat_wrapper.py b/backend/database/wrapper/stats/player_stat_wrapper.py index e71802b85..f8b9cc0a0 100644 --- a/backend/database/wrapper/stats/player_stat_wrapper.py +++ b/backend/database/wrapper/stats/player_stat_wrapper.py @@ -89,7 +89,8 @@ def get_averaged_stats(self, session, id_: str, rank: int = None, redis=None, ra def get_progression_stats(self, session, id_, time_unit: 'TimeUnit' = TimeUnit.MONTH, start_date: datetime.datetime = None, - end_date: datetime.datetime = None): + end_date: datetime.datetime = None, + playlist: int = 13): if time_unit == TimeUnit.MONTH: date = func.to_char(Game.match_date, 'YY-MM') @@ -128,6 +129,9 @@ def get_progression_stats(self, session, id_, if end_date is not None: mean_query = mean_query.filter(Game.match_date < end_date) std_query = std_query.filter(Game.match_date < end_date) + if playlist is not None: + mean_query = mean_query.filter(Game.playlist == playlist) + std_query = std_query.filter(Game.playlist == playlist) mean_query = mean_query.all() std_query = std_query.all() diff --git a/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx b/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx index 17144e7c1..1e15f806b 100644 --- a/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx +++ b/webapp/src/Components/Player/Compare/PlayerCompareContent.tsx @@ -41,7 +41,8 @@ export class PlayerCompareContent extends React.PureComponent { :
- +
} diff --git a/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx b/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx index 71cfb52a7..5bebb4ce8 100644 --- a/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx +++ b/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx @@ -8,9 +8,12 @@ import { convertSnakeAndCamelCaseToReadable } from "../../../../Utils/String" import { ClearableDatePicker } from "../../../Shared/ClearableDatePicker" import { FieldSelect } from "./FieldSelect" import { ProgressionChart } from "./ProgressionChart" +import { PlaylistSelect } from "../../../Shared/Selects/PlaylistSelect" interface Props { players: Player[] + playlist: number + handlePlaylistChange?: (playlist: number) => void } export type TimeUnit = "day" | "month" | "quarter" | "year" @@ -23,6 +26,7 @@ interface State { startDate: moment.Moment | null endDate: moment.Moment | null timeUnit: "day" | "month" | "quarter" | "year" + playlist: number | null } export class PlayerProgressionCharts extends React.PureComponent { @@ -34,7 +38,8 @@ export class PlayerProgressionCharts extends React.PureComponent { selectedFields: [], startDate: null, endDate: null, - timeUnit: "month" + timeUnit: "month", + playlist: this.props.playlist } } @@ -65,7 +70,8 @@ export class PlayerProgressionCharts extends React.PureComponent { if ((this.state.timeUnit !== prevState.timeUnit) || (this.state.startDate !== prevState.startDate) - || (this.state.endDate !== prevState.endDate)) { + || (this.state.endDate !== prevState.endDate) + || (this.state.playlist !== prevState.playlist)) { this.refreshAllData() .then(this.updateFields) } @@ -82,10 +88,19 @@ export class PlayerProgressionCharts extends React.PureComponent { player: players[i], playStyleProgressionPoints })) - + const dropDown = ( + + ) return ( <> - + { label="End date"/> + + {dropDown} + {this.state.selectedFields.map((field) => { return ( { return getProgression(playerId, { timeUnit: this.state.timeUnit === null ? undefined : this.state.timeUnit, startDate: this.state.startDate === null ? undefined : this.state.startDate, - endDate: this.state.endDate === null ? undefined : this.state.endDate + endDate: this.state.endDate === null ? undefined : this.state.endDate, + playlist: this.state.playlist === null ? undefined : this.state.playlist }) } @@ -201,4 +220,11 @@ export class PlayerProgressionCharts extends React.PureComponent { private readonly handleTimeUnitChange: React.ChangeEventHandler = (event) => { this.setState({timeUnit: event.target.value as TimeUnit}) } + private readonly handlePlaylistsChange: React.ChangeEventHandler = (event) => { + const selectedPlaylist = event.target.value as any as number + this.setState({playlist: selectedPlaylist}) + if (this.props.handlePlaylistChange) { + this.props.handlePlaylistChange(selectedPlaylist) + } + } } diff --git a/webapp/src/Requests/Player/getProgression.ts b/webapp/src/Requests/Player/getProgression.ts index 472fb300a..aa821a5c8 100644 --- a/webapp/src/Requests/Player/getProgression.ts +++ b/webapp/src/Requests/Player/getProgression.ts @@ -8,12 +8,14 @@ interface ProgressionQueryParams { timeUnit?: TimeUnit startDate?: moment.Moment endDate?: moment.Moment + playlist?: number } const progressionQueryParamMetadatas: QueryParamMetadata[] = [ {name: "timeUnit", optional: true}, {name: "startDate", isDate: true, optional: true}, - {name: "endDate", isDate: true, optional: true} + {name: "endDate", isDate: true, optional: true}, + {name: "playlist", optional: true} ] export const getProgression = (id: string, queryParams: ProgressionQueryParams): Promise => { From 541593ee162db9cd1b851cba53fd33b5fc91ea0e Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Wed, 24 Oct 2018 15:42:29 -0400 Subject: [PATCH 03/11] Fix order --- .../Player/Compare/Progression/PlayerProgressionCharts.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx b/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx index 5bebb4ce8..187a1e952 100644 --- a/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx +++ b/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx @@ -6,9 +6,9 @@ import { PlayStyleProgressionPoint } from "src/Models" import { getProgression } from "../../../../Requests/Player/getProgression" import { convertSnakeAndCamelCaseToReadable } from "../../../../Utils/String" import { ClearableDatePicker } from "../../../Shared/ClearableDatePicker" +import { PlaylistSelect } from "../../../Shared/Selects/PlaylistSelect" import { FieldSelect } from "./FieldSelect" import { ProgressionChart } from "./ProgressionChart" -import { PlaylistSelect } from "../../../Shared/Selects/PlaylistSelect" interface Props { players: Player[] From c9b28de9d1c7d8373369fa19b30641b7af0de6cd Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Wed, 24 Oct 2018 15:59:07 -0400 Subject: [PATCH 04/11] Win Loss Frontend --- .../Overview/PlayStyle/PlayStyleActions.tsx | 32 +++++++++++++++++-- .../Overview/PlayStyle/PlayerPlayStyle.tsx | 3 +- .../src/Components/Player/PlayerOverview.tsx | 10 ++++-- webapp/src/Requests/Player/getPlayStyle.ts | 4 +-- 4 files changed, 42 insertions(+), 7 deletions(-) diff --git a/webapp/src/Components/Player/Overview/PlayStyle/PlayStyleActions.tsx b/webapp/src/Components/Player/Overview/PlayStyle/PlayStyleActions.tsx index bc59abfaf..38a29c2e5 100644 --- a/webapp/src/Components/Player/Overview/PlayStyle/PlayStyleActions.tsx +++ b/webapp/src/Components/Player/Overview/PlayStyle/PlayStyleActions.tsx @@ -1,4 +1,13 @@ -import { Button, Dialog, DialogContent, DialogTitle, Grid, IconButton, Tooltip } from "@material-ui/core" +import { + Button, + Dialog, + DialogContent, + DialogTitle, + FormControlLabel, + Grid, + IconButton, Switch, + Tooltip +} from "@material-ui/core" import CompareArrows from "@material-ui/icons/CompareArrows" import * as React from "react" import { Link } from "react-router-dom" @@ -11,6 +20,7 @@ interface OwnProps { player: Player useFullSizeCompareButton?: boolean handlePlaylistChange?: (playlist: number) => void + handleWinsLossesChange?: (winLossMode: boolean) => void } type Props = OwnProps @@ -18,12 +28,13 @@ type Props = OwnProps interface State { dialogOpen: boolean playlist: number + winLossMode: boolean } export class PlayStyleActions extends React.PureComponent { constructor(props: Props) { super(props) - this.state = {dialogOpen: false, playlist: 13} + this.state = {dialogOpen: false, playlist: 13, winLossMode: false} } public render() { @@ -52,8 +63,18 @@ export class PlayStyleActions extends React.PureComponent { multiple={false}/> ) + const toggleWinsLosses = ( + } + label="Wins/Losses mode" + /> + ) + return ( + + {toggleWinsLosses} + {dropDown} @@ -97,4 +118,11 @@ export class PlayStyleActions extends React.PureComponent { this.props.handlePlaylistChange(selectedPlaylist) } } + + private readonly handleWinsLossesChange = (event: React.ChangeEvent, winLossMode: boolean) => { + this.setState({winLossMode}) + if (this.props.handleWinsLossesChange) { + this.props.handleWinsLossesChange(winLossMode) + } + } } diff --git a/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx b/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx index 5ceadac9e..b13f689ca 100644 --- a/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx +++ b/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx @@ -9,6 +9,7 @@ import { PlayerPlayStyleChart } from "./PlayerPlayStyleChart" interface OwnProps { player: Player playlist?: number + winLossMode?: boolean } type Props = OwnProps @@ -77,7 +78,7 @@ class PlayerPlayStyleComponent extends React.PureComponent { } private readonly getPlayStyles = (): Promise => { - return getPlayStyle(this.props.player.id, undefined, this.props.playlist) + return getPlayStyle(this.props.player.id, undefined, this.props.playlist, this.props.winLossMode) .then((data) => this.setState({data})) } diff --git a/webapp/src/Components/Player/PlayerOverview.tsx b/webapp/src/Components/Player/PlayerOverview.tsx index c673d1b16..ca2f82f09 100644 --- a/webapp/src/Components/Player/PlayerOverview.tsx +++ b/webapp/src/Components/Player/PlayerOverview.tsx @@ -23,12 +23,13 @@ const playerViewTabs = ["Profile", "Playstyle", "Match History"] interface State { selectedMobileTab?: PlayerViewTab playlist?: number + winLossMode: boolean } class PlayerOverviewComponent extends React.PureComponent { constructor(props: Props) { super(props) - this.state = {selectedMobileTab: "Profile", playlist: 13} + this.state = {selectedMobileTab: "Profile", playlist: 13, winLossMode: false} } public render() { @@ -39,7 +40,7 @@ class PlayerOverviewComponent extends React.PureComponent { } const playerSideBar = - const playerPlayStyle = + const playerPlayStyle = const playerMatchHistory = ( { <> {playerPlayStyle} @@ -111,6 +113,10 @@ class PlayerOverviewComponent extends React.PureComponent { private readonly handlePlaylistChange = (playlist: number) => { this.setState({playlist}) } + + private readonly handleWinsLossesChange = (winLossMode: boolean) => { + this.setState({winLossMode}) + } } export const PlayerOverview = withWidth()(PlayerOverviewComponent) diff --git a/webapp/src/Requests/Player/getPlayStyle.ts b/webapp/src/Requests/Player/getPlayStyle.ts index aa83949ed..9279ea042 100644 --- a/webapp/src/Requests/Player/getPlayStyle.ts +++ b/webapp/src/Requests/Player/getPlayStyle.ts @@ -4,11 +4,11 @@ import { doGet } from "../../apiHandler/apiHandler" import { useMockData } from "../Config" import { MOCK_PLAY_STYLE, MOCK_PLAY_STYLE_RAW } from "../Mock" -export const getPlayStyle = (id: string, rank?: number, playlist?: number): Promise => { +export const getPlayStyle = (id: string, rank?: number, playlist?: number, winLoss?: boolean): Promise => { if (useMockData) { return Promise.resolve(MOCK_PLAY_STYLE) } - const url = qs.stringify({rank, playlist}, {addQueryPrefix: true, indices: false}) + const url = qs.stringify({rank, playlist, win: winLoss ? 1 : 0}, {addQueryPrefix: true, indices: false}) return doGet(`/player/${id}/play_style` + url) } From b18f1e1656ede082f13467a6c49af6bead4981f4 Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Wed, 24 Oct 2018 16:21:46 -0400 Subject: [PATCH 05/11] Win Loss --- .../Overview/PlayStyle/PlayerPlayStyle.tsx | 54 ++++++++++++++----- .../PlayStyle/PlayerPlayStyleCard.tsx | 5 +- .../src/Components/Player/PlayerOverview.tsx | 7 ++- webapp/src/Requests/Player/getPlayStyle.ts | 11 +++- 4 files changed, 58 insertions(+), 19 deletions(-) diff --git a/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx b/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx index b13f689ca..6731f3674 100644 --- a/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx +++ b/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyle.tsx @@ -17,6 +17,7 @@ type Props = OwnProps interface State { data?: PlayStyleResponse + winLossData?: PlayStyleResponse[] reloadSignal: boolean } @@ -33,6 +34,9 @@ class PlayerPlayStyleComponent extends React.PureComponent { if (prevProps.playlist !== this.props.playlist) { this.triggerReload() } + if (prevProps.winLossMode !== this.props.winLossMode) { + this.triggerReload() + } } public render() { @@ -42,7 +46,8 @@ class PlayerPlayStyleComponent extends React.PureComponent { "Upload more replays to get more accurate stats." return ( - + {this.state.data && <> {this.state.data.showWarning && @@ -58,18 +63,33 @@ class PlayerPlayStyleComponent extends React.PureComponent { } - {this.state.data.chartDatas.map((chartDataResponse) => { - return ( - - - {chartDataResponse.title} - - - - ) - })} - + {(this.props.winLossMode && this.state.winLossData) ? + this.state.winLossData[0].chartDatas.map((chartDataResponse, i) => { + return ( + + + {chartDataResponse.title} + + {this.state.winLossData && + + data.chartDatas[i])}/>} + + ) + }) + : + this.state.data.chartDatas.map((chartDataResponse) => { + return ( + + + {chartDataResponse.title} + + + + ) + })} } @@ -78,10 +98,16 @@ class PlayerPlayStyleComponent extends React.PureComponent { } private readonly getPlayStyles = (): Promise => { - return getPlayStyle(this.props.player.id, undefined, this.props.playlist, this.props.winLossMode) + return getPlayStyle(this.props.player.id, undefined, this.props.playlist) .then((data) => this.setState({data})) } + private readonly getPlayStylesWinLoss = (): Promise => { + const win = getPlayStyle(this.props.player.id, undefined, this.props.playlist, true) + const loss = getPlayStyle(this.props.player.id, undefined, this.props.playlist, false) + return Promise.all([win, loss]).then((winLossData) => this.setState({winLossData})) + } + private readonly triggerReload = () => { this.setState({reloadSignal: !this.state.reloadSignal}) } diff --git a/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyleCard.tsx b/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyleCard.tsx index c507e00d5..f74b5aa26 100644 --- a/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyleCard.tsx +++ b/webapp/src/Components/Player/Overview/PlayStyle/PlayerPlayStyleCard.tsx @@ -6,6 +6,7 @@ import { PlayStyleActions } from "./PlayStyleActions" interface Props { player: Player handlePlaylistChange?: (playlist: number) => void + handleWinsLossesChange?: (winLossMode: boolean) => void } export class PlayerPlayStyleCard extends React.PureComponent { @@ -25,7 +26,9 @@ export class PlayerPlayStyleCard extends React.PureComponent { action={ + handlePlaylistChange={this.props.handlePlaylistChange} + handleWinsLossesChange={this.props.handleWinsLossesChange} + /> }/> {this.props.children} diff --git a/webapp/src/Components/Player/PlayerOverview.tsx b/webapp/src/Components/Player/PlayerOverview.tsx index ca2f82f09..d97ed0702 100644 --- a/webapp/src/Components/Player/PlayerOverview.tsx +++ b/webapp/src/Components/Player/PlayerOverview.tsx @@ -40,7 +40,8 @@ class PlayerOverviewComponent extends React.PureComponent { } const playerSideBar = - const playerPlayStyle = + const playerPlayStyle = const playerMatchHistory = ( { + handlePlaylistChange={this.handlePlaylistChange} + handleWinsLossesChange={this.handleWinsLossesChange} + > {playerPlayStyle} diff --git a/webapp/src/Requests/Player/getPlayStyle.ts b/webapp/src/Requests/Player/getPlayStyle.ts index 9279ea042..277f9d3dc 100644 --- a/webapp/src/Requests/Player/getPlayStyle.ts +++ b/webapp/src/Requests/Player/getPlayStyle.ts @@ -4,11 +4,18 @@ import { doGet } from "../../apiHandler/apiHandler" import { useMockData } from "../Config" import { MOCK_PLAY_STYLE, MOCK_PLAY_STYLE_RAW } from "../Mock" -export const getPlayStyle = (id: string, rank?: number, playlist?: number, winLoss?: boolean): Promise => { +export const getPlayStyle = (id: string, rank?: number, playlist?: number, + win?: boolean): Promise => { if (useMockData) { return Promise.resolve(MOCK_PLAY_STYLE) } - const url = qs.stringify({rank, playlist, win: winLoss ? 1 : 0}, {addQueryPrefix: true, indices: false}) + let params = {} + if (win === undefined) { + params = {rank, playlist} + } else { + params = {rank, playlist, win: win ? 1 : 0} + } + const url = qs.stringify(params, {addQueryPrefix: true, indices: false}) return doGet(`/player/${id}/play_style` + url) } From 3a76d2fa4349a1b62980dc2fcc9cf1de4bb57902 Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Wed, 24 Oct 2018 16:23:09 -0400 Subject: [PATCH 06/11] Change colors so it makes more sense --- webapp/src/Utils/Color.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapp/src/Utils/Color.ts b/webapp/src/Utils/Color.ts index 60a23718b..b8cbb4ff2 100644 --- a/webapp/src/Utils/Color.ts +++ b/webapp/src/Utils/Color.ts @@ -83,7 +83,7 @@ const chartColors: ChartColors = { })) } -export const colorsForPlaylists = ["#F9A782", "#71EFAF", "#88C6F9", "#E888F7"] +export const colorsForPlaylists = ["#71EFAF", "#F9A782", "#88C6F9", "#E888F7"] export const primaryColours = [ "#33B8A5", From ad77547f1493dd12718a5f2be0685d36e663b5b3 Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Wed, 24 Oct 2018 16:36:26 -0400 Subject: [PATCH 07/11] Formatting changes --- .../PlayStyle/PlayerComparePlayStyleCharts.tsx | 11 ++++------- .../Compare/Progression/PlayerProgressionCharts.tsx | 1 + webapp/src/Components/Player/PlayerOverview.tsx | 6 ++++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx b/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx index e77ef1465..4c603a7d6 100644 --- a/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx +++ b/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx @@ -18,7 +18,6 @@ interface State { playerPlayStylesRaw: PlayStyleRawResponse[] rank: number heatmapMode: boolean - playlist: number } export class PlayerComparePlayStyleCharts extends React.PureComponent { @@ -28,8 +27,7 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent { const rank = this.state.rank === -1 ? undefined : this.state.rank - Promise.all(players.map((player) => getPlayStyle(player.id, rank, this.state.playlist))) + Promise.all(players.map((player) => getPlayStyle(player.id, rank, this.props.playlist))) .then((playerPlayStyles) => { if (reload) { this.setState({playerPlayStyles}) @@ -140,7 +138,7 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent getPlayStyleRaw(player.id, this.state.playlist))) + Promise.all(players.map((player) => getPlayStyleRaw(player.id, this.props.playlist))) .then((playerPlayStylesRaw) => { if (reload) { this.setState({playerPlayStylesRaw}) @@ -172,7 +170,6 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent = (event) => { const selectedPlaylist = event.target.value as any as number - this.setState({playlist: selectedPlaylist}) if (this.props.handlePlaylistChange) { this.props.handlePlaylistChange(selectedPlaylist) } diff --git a/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx b/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx index 187a1e952..ca442c475 100644 --- a/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx +++ b/webapp/src/Components/Player/Compare/Progression/PlayerProgressionCharts.tsx @@ -220,6 +220,7 @@ export class PlayerProgressionCharts extends React.PureComponent { private readonly handleTimeUnitChange: React.ChangeEventHandler = (event) => { this.setState({timeUnit: event.target.value as TimeUnit}) } + private readonly handlePlaylistsChange: React.ChangeEventHandler = (event) => { const selectedPlaylist = event.target.value as any as number this.setState({playlist: selectedPlaylist}) diff --git a/webapp/src/Components/Player/PlayerOverview.tsx b/webapp/src/Components/Player/PlayerOverview.tsx index d97ed0702..04dc1f7f9 100644 --- a/webapp/src/Components/Player/PlayerOverview.tsx +++ b/webapp/src/Components/Player/PlayerOverview.tsx @@ -40,8 +40,10 @@ class PlayerOverviewComponent extends React.PureComponent { } const playerSideBar = - const playerPlayStyle = + const playerPlayStyle = ( + + ) const playerMatchHistory = ( Date: Wed, 24 Oct 2018 16:38:04 -0400 Subject: [PATCH 08/11] Type --- backend/blueprints/spa_api/service_layers/player/play_style.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/blueprints/spa_api/service_layers/player/play_style.py b/backend/blueprints/spa_api/service_layers/player/play_style.py index 7717fd2cc..e7c8cf16b 100644 --- a/backend/blueprints/spa_api/service_layers/player/play_style.py +++ b/backend/blueprints/spa_api/service_layers/player/play_style.py @@ -50,7 +50,8 @@ def create_from_id(cls, id_: str, raw=False, rank=None, replay_ids=None, playlis ) @staticmethod - def create_all_stats_from_id(id_: str, rank=None, replay_ids=None, playlist=None, win=None) -> PlayerDataPoint: + def create_all_stats_from_id(id_: str, rank: int = None, replay_ids: List[str] = None, playlist: int = None, + win: bool = None) -> PlayerDataPoint: session = current_app.config['db']() game_count = player_wrapper.get_total_games(session, id_) if game_count == 0: From 2d7c525551e9f78ea6c03754af0777b1933c63cc Mon Sep 17 00:00:00 2001 From: Matthew Mage Date: Thu, 25 Oct 2018 11:49:50 -0400 Subject: [PATCH 09/11] Props fix --- .../PlayerComparePlayStyleCharts.tsx | 2 +- .../Progression/PlayerProgressionCharts.tsx | 2 +- .../Overview/PlayStyle/PlayStyleActions.tsx | 2 +- .../Shared/Selects/PlaylistSelect.tsx | 28 +++++++++++++------ 4 files changed, 22 insertions(+), 12 deletions(-) diff --git a/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx b/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx index 4c603a7d6..2525873b2 100644 --- a/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx +++ b/webapp/src/Components/Player/Compare/PlayStyle/PlayerComparePlayStyleCharts.tsx @@ -80,7 +80,7 @@ export class PlayerComparePlayStyleCharts extends React.PureComponent { })) const dropDown = ( { ) const dropDown = ( helperText: string inputLabel: string dropdownOnly?: boolean currentPlaylistsOnly?: boolean - multiple: boolean } -type Props = OwnProps +interface MultiplePlaylistProps { + multiple: true + selectedPlaylists: number[] + handleChange: React.ChangeEventHandler +} + +interface SinglePlaylistProps { + multiple: false + selectedPlaylist: number + handleChange: React.ChangeEventHandler +} + +type Props = (SinglePlaylistProps | MultiplePlaylistProps) & OwnProps & WithStyles interface State { @@ -224,29 +233,30 @@ class PlaylistSelectComponent extends React.PureComponent { || (this.state.filterStandardMode !== prevState.filterStandardMode) || (this.state.filterCurrent !== prevState.filterCurrent)) { const filteredPlaylists = this.getFilteredPlaylists().map((playlist) => playlist.value) - const filteredSelectedPlaylists = _.intersection(this.props.selectedPlaylists, filteredPlaylists) - if (!_.isEqual(this.props.selectedPlaylists, filteredSelectedPlaylists)) { + const selectedPlaylists = this.props.multiple ? this.props.selectedPlaylists : [this.props.selectedPlaylist] + const filteredSelectedPlaylists = _.intersection(selectedPlaylists, filteredPlaylists) + if (!_.isEqual(selectedPlaylists, filteredSelectedPlaylists)) { this.setSelectedPlaylists(filteredSelectedPlaylists) } } } public render() { - const {classes, selectedPlaylists, handleChange, inputLabel, helperText} = this.props + const {classes, handleChange, inputLabel, helperText} = this.props const playlistsMultiSelect = ( {inputLabel}