Skip to content

Commit

Permalink
#11 - Use king streak data to display notice
Browse files Browse the repository at this point in the history
  • Loading branch information
Fezzzi committed Jul 9, 2020
1 parent f3004f4 commit 337d389
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 30 deletions.
9 changes: 6 additions & 3 deletions frontend/src/app/components/Leaderboard/Leaderboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@ import { connect } from 'react-redux'
import { ListCon } from '../../../styles/blocks'
import { LeaderboardRow } from './LeaderboardRow'
import { LeaderboardFilters } from './LeaderboardFilters'
import { getTopPlayers } from '../../modules/players/players-selectors'
import { getKing } from '../../modules/matches/matches-selectors'
import { LeaderboardActions } from '../../modules/leaderboard/leaderboard-actions'
import * as Filters from '../../const/leaderboard-filters'

const LeaderboardComponent = (
{ topPlayers, filters, maxItems, showFilters, updateCriteria, updateOrder, updateTimespan },
{ topPlayers, king, filters, maxItems, showFilters, updateCriteria, updateOrder, updateTimespan },
) => (
<>
{showFilters
? <LeaderboardFilters filters={filters} updateCriteria={updateCriteria}
updateOrder={updateOrder} updateTimespan={updateTimespan}/>
: ''}

<ListCon className="topPlayers" ascending={filters.order === Filters.orderTypes.ASC}>
{topPlayers.slice(0, maxItems).map((player, index) =>
<LeaderboardRow key={player.id} player={player}
<LeaderboardRow key={player.id} player={player} king={king}
position={
filters.order === Filters.orderTypes.ASC ? topPlayers.length - index : index + 1
}
Expand All @@ -29,6 +30,8 @@ const LeaderboardComponent = (
)

const mapStateToProps = state => ({
topPlayers: getTopPlayers(state),
king: getKing(state),
filters: state.filters,
})

Expand Down
8 changes: 6 additions & 2 deletions frontend/src/app/components/Leaderboard/LeaderboardRow.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import React from 'react'
import { TextSpan, TextDiv, ListItem, StyledLink } from '../../../styles/blocks'
import { TextSpan, KingSpan, TextDiv, ListItem, StyledLink } from '../../../styles/blocks'
import { createProfilePath } from '../../const/routes'

const trophies = [
require('../../../media/trophy-1.svg'),
require('../../../media/trophy-2.svg'),
require('../../../media/trophy-3.svg'),
]

export const LeaderboardRow = ({ player, position, points }) => (
export const LeaderboardRow = ({ player, king, position, points }) => (
<ListItem>
<TextSpan align="left">{
position > 3 ? (position + '.') : <img src={trophies[position - 1]} alt={`cup${position}`} />
}</TextSpan>
{king && king.id === player.id
? <KingSpan>King of The Hill<br/>since {king.since.toLocaleDateString()}</KingSpan>
: ''}
<TextDiv>
<StyledLink to={player.link}>{player.name} ({points})</StyledLink>
</TextDiv>
Expand Down
42 changes: 21 additions & 21 deletions frontend/src/app/modules/matches/matches-computations.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,46 +69,46 @@ export const computeWinRatio = (playerId, playerMatches) => {
return (playerMatches.length > 0) ? (wonMatchesCount / playerMatches.length) : 0
}

export const computeKingStreakDuration = (userId, users, matches) => {
// todo: remove usersLast and matchesLast when it is not needed after merging leaderboards branch
const usersLast = users.sort((user1, user2) => user2.rating - user1.rating)
const matchesLast = matches.sort((match1, match2) => match2.date - match1.date)
if (!usersLast.length || !matchesLast.length || usersLast[0].id !== userId) {
return false
export const computeKingStreakDuration = (matchesLast, usersLast) => {
if (usersLast.length < 1) {
return null
}

const usersMap = usersLast.reduce((map, user) => {
map[user.id] = user.rating
return map
})
}, new Map())

let kingRating = usersLast[0].rating
for (let i = 0; i < matchesLast.length; ++i) {
const players = [...matchesLast[i].team1, ...matchesLast[i].team2]
const kingId = usersLast[0].id
let matchFound = false;
for (let match of matchesLast) {
const players = [...match.team1, ...match.team2]

// #1 recomptute king's rating before in case he played the match
const kingPlayer = players.find(player => player.id === userId)
const kingPlayer = players.find(player => player.id === kingId)
const kingWon = false;
if (kingPlayer) {
kingWon = kingRating > kingPlayer.matchRating
kingRating = kingPlayer.matchRating
kingWon = usersMap[kingId] > kingPlayer.matchRating
usersMap[kingId] = kingPlayer.matchRating
}

// #2 check whether none of the other players beat the king
for (let player of players) {
usersMap[player.id] = player.matchRating
if (player.id !== userId && player.matchRating > kingRating) {
return matchesLast[i]
}
matchFound |= (player.id !== kingId && player.matchRating > usersMap[kingId])
}

// todo: remove `key < 180` when it is not needed after merging leaderboards branch
// #3 check if king was first before winning
if (kingPlayer && kingWon) {
if (kingPlayer && kingWon && !matchFound) {
for (let key in usersMap) {
if (key < 180 && usersMap[key] > kingRating) {
return matchesLast[i]
}
matchFound |= (usersMap[key] > usersMap[kingId])
}
}

if (matchFound) {
return {
id: kingId,
since: match.date,
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/app/modules/matches/matches-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import {
computeWinRatio,
generateMatchRatingChanges,
plotRatingHistory,
computeKingStreakDuration,
} from './matches-computations'
import { getPlayer } from '../players/players-selectors'
import { getPlayer, getTopRatedPlayers } from '../players/players-selectors'

const fillPlayers = (team, state) => team.map(emptyPlayer => {
const player = state.players.find(player => player.id === emptyPlayer.id)
Expand Down Expand Up @@ -44,6 +45,12 @@ const generateStatisticsForPlayer = (playerId, playerMatches) => ({
totalMatches: playerMatches.length,
})

export const getKing = createSelector(
getLastMatches,
getTopRatedPlayers,
(userMatches, users) => computeKingStreakDuration(userMatches, users)
)

export const getStatisticsForPlayer = createSelector(
getLastMatchesForPlayer,
(state, playerId) => playerId,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/styles/blocks/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
Title, Subtitle, TextSpan, TextDiv, WinnerSpan, BattleLabel,
Title, Subtitle, TextSpan, KingSpan, TextDiv, WinnerSpan, BattleLabel,
FiltersBlock, FiltersSpan, StyledHyperLink,
} from './typo'
import { Nav, Container, GridContainer, Box, ProfileDetail } from './layout'
Expand All @@ -10,7 +10,7 @@ import { SelectBox, Label, Input } from './inputs'
import { Logo } from './logo'

export {
Title, Subtitle, TextSpan, TextDiv, WinnerSpan, BattleLabel,
Title, Subtitle, TextSpan, KingSpan, TextDiv, WinnerSpan, BattleLabel,
FiltersBlock, FiltersSpan, StyledHyperLink,
Nav, Container, GridContainer, Box, ProfileDetail,
ListCon, ListItem,
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/styles/blocks/typo.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ const TextSpan = styled.span`
padding: 0 5px;
`

const KingSpan = styled.span`
font-size: 14px;
font-style: italic;
float: right;
color: var(--cFont);
padding: 0 5px;
`

const TextDiv = styled.div`
text-align: ${props => props.textAlign};
float: ${props => props.align || 'none'};
Expand Down Expand Up @@ -71,6 +79,6 @@ const StyledHyperLink = styled.a`
`

export {
Title, Subtitle, TextSpan, TextDiv, WinnerSpan, BattleLabel,
Title, Subtitle, TextSpan, KingSpan, TextDiv, WinnerSpan, BattleLabel,
FiltersBlock, FiltersSpan, StyledHyperLink,
}

0 comments on commit 337d389

Please sign in to comment.