-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
309 additions
and
22 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { readonlyRecord as RR, readonlyArray as RA, } from "fp-ts" | ||
import { ContractBid, eqContractBid, levels, strains } from "../../model/bridge" | ||
import StrainTableView, { StrainSpan } from "./StrainTableView" | ||
import { pipe } from "fp-ts/lib/function" | ||
import { Button } from '@fluentui/react-components'; | ||
|
||
interface BidSelectorButtonProps { | ||
selected: boolean, | ||
children: JSX.Element | ||
setSelected: (selected: boolean) => void | ||
} | ||
const BidSelectorButton = ({ children, selected, setSelected }: BidSelectorButtonProps) => | ||
<Button style={{minWidth: "50px", width: "50px"}} onClick={() => setSelected(!selected)} appearance={selected ? "primary" : "secondary"}>{children}</Button> | ||
|
||
interface BidSelectorProps { | ||
bids: ReadonlyArray<ContractBid>, | ||
setSelectedBid: (bid: ContractBid, selected: boolean) => void | ||
} | ||
export const BidSelector = ({ bids, setSelectedBid }: BidSelectorProps) => { | ||
const contractBidsEnabledByLevel = | ||
pipe(levels, | ||
RA.map(level => pipe(strains, | ||
RA.map(strain => ({ level, strain }) as ContractBid), | ||
RA.map(bid => [bid.strain, pipe(bids, RA.exists(selectedBid => eqContractBid.equals(bid, selectedBid)))] as const), | ||
RR.fromEntries))) | ||
return (<StrainTableView | ||
table={{rows: contractBidsEnabledByLevel}} | ||
renderColHeader={() => undefined} | ||
renderRowHeader={() => undefined} | ||
renderCell={(selected, s, i) => | ||
<BidSelectorButton selected={selected} setSelected={selected => setSelectedBid({ level: i + 1, strain: s}, selected)}> | ||
<>{i + 1}<StrainSpan className={s} /></> | ||
</BidSelectorButton>} | ||
/>) | ||
} | ||
|
||
export default BidSelector |
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,48 @@ | ||
import styled from 'styled-components'; | ||
import { readonlyRecord as RR } from 'fp-ts'; | ||
import { Strain, strains } from '../../model/bridge'; | ||
|
||
const suitBase = ` | ||
&.S::before { content: "♠"; color: #0000FF } | ||
&.H::before { content: "♥"; color: #FF0000 } | ||
&.D::before { content: "♦"; color: #FFA500 } | ||
&.C::before { content: "♣"; color: #32CD32 } | ||
` | ||
|
||
export const StrainSpan = styled.span ` | ||
${suitBase} | ||
&.N::before { content: "NT"; color: #000000; font-size: 12px; } | ||
` | ||
|
||
type StrainRow<T> = RR.ReadonlyRecord<Strain, T> | ||
export interface StrainTable<T> { | ||
rows: ReadonlyArray<StrainRow<T>> | ||
} | ||
|
||
interface StrainTableProps<T> { | ||
table: StrainTable<T> | ||
renderColHeader: ((strain: Strain, index: number) => JSX.Element | undefined) | ||
renderRowHeader: (row: StrainRow<T>, index: number) => JSX.Element | undefined | ||
renderCell: (value: T, strain: Strain, rowIndex: number) => JSX.Element | undefined | ||
} | ||
|
||
export const StrainTableView = <T extends any>({ table, renderColHeader, renderRowHeader, renderCell }: StrainTableProps<T>) => { | ||
return ( | ||
<table> | ||
<thead> | ||
<tr> | ||
<th></th> | ||
{strains.map((s, i) => renderColHeader ? renderColHeader(s, i) : <th style={{fontWeight: "normal", verticalAlign: "middle"}} key={i}><StrainSpan className={s} /></th>)} | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{table.rows.map((r, i) => <tr key={i}> | ||
<td>{renderRowHeader(r, i)}</td> | ||
{strains.map((s, j) => <td key={j}>{renderCell(r[s], s, i)}</td>)} | ||
</tr>)} | ||
</tbody> | ||
</table> | ||
) | ||
} | ||
|
||
export default StrainTableView |
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,57 @@ | ||
import { ContractBid, Direction, eqContractBid, ordContractBid } from "../../model/bridge"; | ||
import { readonlyArray as RA, readonlyNonEmptyArray as RNEA } from "fp-ts"; | ||
import { Scores, compareScores } from "../../model/stats" | ||
import Percentage from "../core/Percentage"; | ||
import BidSelector from "../core/BidSelector"; | ||
import { useCallback, useMemo, useState } from "react"; | ||
import { pipe } from "fp-ts/lib/function"; | ||
import styled from "styled-components"; | ||
import { BidView } from "../core/BidPath"; | ||
import { serializedBidL } from "../../model/serialization"; | ||
|
||
interface ScoreComparisonProps { | ||
contractBid: ContractBid | ||
scores: Scores | ||
} | ||
const defaultDir : Direction = "N" | ||
|
||
export const Columns = styled.div ` | ||
display: flex; | ||
flex-direction: row; | ||
` | ||
|
||
export const Column = styled.div ` | ||
width: 35%; | ||
` | ||
|
||
export const ScoreList = styled.ul ` | ||
list-style-type: none; | ||
` | ||
|
||
const ScoreComparison = ({ contractBid, scores }: ScoreComparisonProps) => { | ||
const [bids, setBids] = useState<RNEA.ReadonlyNonEmptyArray<ContractBid>>([contractBid]) | ||
const setSelectedBid = useCallback((bid: ContractBid, selected: boolean) => | ||
setBids(pipe( | ||
bids, | ||
selected ? RA.union(eqContractBid)([bid]) : RA.filter(b => !eqContractBid.equals(bid, b)), | ||
RA.append(contractBid), | ||
RNEA.uniq(eqContractBid), | ||
RNEA.sort(ordContractBid))) | ||
, [bids, contractBid]) | ||
const comparison = useMemo(() => compareScores(scores)(pipe(bids, RNEA.map(b => ([defaultDir, b])))), [bids, scores]) | ||
const length = scores.length | ||
return (<section> | ||
<h4>Compare Contracts</h4> | ||
<Columns> | ||
<BidSelector bids={bids} setSelectedBid={setSelectedBid} /> | ||
<ScoreList>{length && Object.entries(comparison).map(([contract, count], i) => | ||
<li key={i}> | ||
{contract === "tie" ? "(ties)" : <BidView bid={serializedBidL.reverseGet(contract)} />} | ||
: {count} (<Percentage numerator={count} denominator={length} />) | ||
</li>)} | ||
</ScoreList> | ||
</Columns> | ||
</section>) | ||
} | ||
|
||
export default ScoreComparison |
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
Oops, something went wrong.