-
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.
* format score comparison files with Prettier * added score comparison
- Loading branch information
Showing
9 changed files
with
1,378 additions
and
568 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,66 @@ | ||
import { option as O, readonlyRecord as RR } from 'fp-ts'; | ||
import { flow, pipe } from 'fp-ts/lib/function'; | ||
import { get } from '../../lib/object'; | ||
import { | ||
option as O, | ||
readonlyRecord as RR, | ||
readonlyNonEmptyArray as RNEA, | ||
} from "fp-ts"; | ||
import { flow, pipe } from "fp-ts/lib/function"; | ||
import { get } from "../../lib/object"; | ||
import { Generation } from "../../model/job"; | ||
import { SerializedBidPath } from "../../model/serialization"; | ||
import { | ||
SerializedBidPath, | ||
serializedBidPathL, | ||
} from "../../model/serialization"; | ||
import SolutionStats from "./SolutionStats"; | ||
import ScoreComparison from "./ScoreComparison"; | ||
import { ContractBid } from "../../model/bridge"; | ||
import styled from "styled-components"; | ||
|
||
export const Columns = styled.div` | ||
display: flex; | ||
flex-direction: row; | ||
`; | ||
|
||
export const Column = styled.div` | ||
width: 35%; | ||
`; | ||
|
||
interface StatsDetailsProps { | ||
path: SerializedBidPath | ||
generation: Generation | ||
onClose: () => void | ||
path: SerializedBidPath; | ||
generation: Generation; | ||
onClose: () => void; | ||
} | ||
const StatsDetails = ({ path, generation, onClose }: StatsDetailsProps) => { | ||
const stats = pipe( | ||
generation, | ||
O.fromNullable, | ||
O.chain(flow( | ||
get('solutionStats'), | ||
RR.lookup(path))), | ||
O.toNullable) | ||
O.chain(flow(get("solutionStats"), RR.lookup(path))), | ||
O.toNullable | ||
); | ||
const solveCount = pipe( | ||
stats, | ||
O.fromNullable, | ||
O.map(get('count')), | ||
O.chain(O.fromPredicate(len => len > 0)), | ||
O.toNullable) | ||
return (<div> | ||
{solveCount && <h3>{solveCount} solutions found</h3>} | ||
{stats && <SolutionStats stats={stats} />} | ||
</div>) | ||
} | ||
O.map(get("count")), | ||
O.chain(O.fromPredicate((len) => len > 0)), | ||
O.toNullable | ||
); | ||
const contractBid = pipe( | ||
path, | ||
serializedBidPathL.reverseGet, | ||
RNEA.last | ||
) as ContractBid; | ||
return ( | ||
<div> | ||
{solveCount && <h3>{solveCount} solutions found</h3>} | ||
<Columns> | ||
<Column>{stats && <SolutionStats stats={stats} />}</Column> | ||
<div> | ||
{stats?.scores && ( | ||
<ScoreComparison contractBid={contractBid} scores={stats.scores} /> | ||
)} | ||
</div> | ||
</Columns> | ||
</div> | ||
); | ||
}; | ||
|
||
export default StatsDetails | ||
export default StatsDetails; |
Oops, something went wrong.