-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add simulations for pot balancing for missed attendances.
- Loading branch information
Showing
10 changed files
with
190 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import React, {ReactElement} from 'react'; | ||
import {asLink} from '../../AsLink'; | ||
import {useRouteMatch} from 'react-router-dom'; | ||
import FullPot from '../pot/FullPot'; | ||
import {Divider} from 'semantic-ui-react'; | ||
import {useGroup} from '../../store/Groups'; | ||
|
||
export default function Pot(): ReactElement | null { | ||
const group = useGroup(); | ||
const {url} = useRouteMatch(); | ||
if (!group?.settings.eurosPerPointDiffToTopPlayer) { | ||
return null; | ||
} | ||
return <> | ||
<FullPot as={asLink(`${url}/pot`)}/> | ||
<Divider/> | ||
</>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import React, {ReactElement, useMemo} from 'react'; | ||
import {useSortedGroupMembers} from '../../store/GroupMembers'; | ||
import {Icon, Label} from 'semantic-ui-react'; | ||
|
||
export default function FullPot({as}: { as?: any }): ReactElement { | ||
const groupMembers = useSortedGroupMembers(); | ||
const fullPot = useMemo(() => groupMembers.reduce((acc, {euroBalance}) => acc + (euroBalance || 0), 0), | ||
[groupMembers]); | ||
return <section> | ||
<div className="memberDetail"> | ||
<Label as={as} color={'purple'}> | ||
Gesamter Pott | ||
<Label.Detail> | ||
{fullPot} <Icon name={'euro'}/> | ||
</Label.Detail> | ||
</Label> | ||
</div> | ||
</section>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import React, {Fragment, ReactElement} from 'react'; | ||
import {useSortedGroupMembers} from '../../store/GroupMembers'; | ||
import {Header, Icon, Message} from 'semantic-ui-react'; | ||
import {useSortedRounds} from '../../store/Rounds'; | ||
import classNames from 'classnames'; | ||
import {useGroup} from '../../store/Groups'; | ||
|
||
export default function SplitPotAttendance(): ReactElement { | ||
const {completedRoundsCount} = useGroup()!; | ||
const groupMembers = useSortedGroupMembers(); | ||
let fullPot = 0; | ||
let attendances = 0; | ||
groupMembers.forEach(({euroBalance, roundsCount}) => { | ||
fullPot += euroBalance || 0; | ||
attendances += roundsCount || 0; | ||
}); | ||
|
||
const mapped = groupMembers.map(({id, name, euroBalance, roundsCount}) => { | ||
const euros = euroBalance || 0; | ||
const attendance = roundsCount / attendances; | ||
const partial = fullPot * attendance; | ||
const balance = partial - euros; | ||
const row = <Fragment key={id}> | ||
<div className={'name'}>{name}</div> | ||
<div className={'value'}>{euros.toFixed(2)} €</div> | ||
<div className={'value'}>{roundsCount} / {partial.toFixed(2)} €</div> | ||
<div className={classNames('value', {pos: balance >= 0, neg: balance < 0})}>{balance.toFixed(2)} €</div> | ||
</Fragment>; | ||
return {id, row, balance}; | ||
}); | ||
mapped.sort((a, b) => b.balance - a.balance); | ||
|
||
return <section> | ||
<Header>#1 Split-Pott nach Teilnahmen</Header> | ||
<Message> | ||
<Message.Content> | ||
<p>Jeder Spieler hat durch seine Teilnahmen zum Pott beigetragen.</p> | ||
<p>Der Pott wird anteilig angerechnet.</p> | ||
<p>Es gibt insgesamt {completedRoundsCount} beendete Runden, mit {attendances} Teilnahmen.</p> | ||
</Message.Content> | ||
</Message> | ||
|
||
<div className={'potGrid splitPotAttendance'}> | ||
<div className={'name'}/> | ||
<div className={'value'}>Beitrag</div> | ||
<div className={'value'}>Anteil</div> | ||
<div className={'value'}><Icon name={'balance scale'}/></div> | ||
{mapped.map(({row}) => row)} | ||
</div> | ||
</section>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import React, {Fragment, ReactElement} from 'react'; | ||
import {useSortedGroupMembers} from '../../store/GroupMembers'; | ||
import {Header, Message} from 'semantic-ui-react'; | ||
import {useGroup} from '../../store/Groups'; | ||
|
||
export default function TopUpByAverage(): ReactElement { | ||
const {completedRoundsCount} = useGroup()!; | ||
const groupMembers = useSortedGroupMembers(); | ||
let realPot = 0; | ||
let topUpPot = 0; | ||
|
||
const mapped = groupMembers.map(({id, name, euroBalance, roundsCount}) => { | ||
const euros = euroBalance || 0; | ||
const missedRounds = completedRoundsCount - roundsCount; | ||
const averageBalance = euros / roundsCount; | ||
realPot += euros; | ||
const topUp = missedRounds * averageBalance; | ||
topUpPot += topUp; | ||
const total = euros + topUp; | ||
const row = <Fragment key={id}> | ||
<div className={'name'}>{name}</div> | ||
<div className={'value'}>{euros.toFixed(2)} €</div> | ||
<div className={'value'}>{missedRounds} x {averageBalance.toFixed(2)} €</div> | ||
<div className={'value'}>{total.toFixed(2)} €</div> | ||
</Fragment>; | ||
return {id, row, total}; | ||
}); | ||
mapped.sort((a, b) => a.total - b.total); | ||
|
||
const toppedUpPot = realPot + topUpPot; | ||
|
||
return <section> | ||
<Header>#2 Pott-Auffüllung via Durchschnitt</Header> | ||
<Message> | ||
<Message.Content> | ||
<p>Der Pott wird mit dem durchschnittlichen Geldbetrag pro Runde eines jeden Spielers aufgestockt.</p> | ||
<p>Es wird so die 100% Teilnahme jedes Spielers simuliert.</p> | ||
<p>Der Pott erhöht sich von {realPot.toFixed(2)} € auf {toppedUpPot.toFixed(2)} €.</p> | ||
</Message.Content> | ||
</Message> | ||
|
||
<div className={'potGrid topUpByAverage'}> | ||
<div className={'name'}/> | ||
<div className={'value'}>Beitrag</div> | ||
<div className={'value'}>Ausgleich</div> | ||
<div className={'value'}>Total</div> | ||
{mapped.map(({row}) => row)} | ||
</div> | ||
</section>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React, {ReactElement} from 'react'; | ||
import {Divider} from 'semantic-ui-react'; | ||
import FullPot from './FullPot'; | ||
import SplitPotAttendance from './SplitPotAttendance'; | ||
import TopUpByAverage from './TopUpByAverage'; | ||
|
||
export default function PotIndex(): ReactElement | null { | ||
return <section> | ||
<FullPot/> | ||
<Divider section/> | ||
<SplitPotAttendance/> | ||
<Divider section/> | ||
<TopUpByAverage/> | ||
</section>; | ||
} |