patternMinor
Tally Calculator for Baloot in F#
Viewed 0 times
balootcalculatortallyfor
Problem
This is a tally calculator for the Saudi card game Baloot. As in, they're a set of functions so that the user would provide their winnings at the end of a round (card captured, projects declared, etc) and the functions would give them the score for themselves and their opponent.
Domain Model
(I listed most of these types in one line for vertical brevity).
Point Tally functions
```
// Trick Total Point Calculations
let sunTrickPts card =
match card.Rank with
| Ace -> 11
| Ten -> 10
| King -> 4
| Queen -> 3
| Jack -> 2
| _ -> 0
let trumpTrickPts card trump =
match (card.Rank, card.Suit) with
| (Jack, s) when s = trump -> 20
| (Nine, s) when s = trump -> 14
| _ -> sunTrickPts card
let capturedTrickPts hand =
match hand.Mode with
| Sun ->
hand.Captured
|> List.fold (fun acc card -> acc + (sunTrickPts card)) 0
| Trump(suit) ->
hand.Captured
|> List.fold (fun acc card -> acc + (trumpTrickPts card suit)) 0
+ if hand.Ground then 10
else 0
// Captured Cards Point Calculations
let sunHandPts pts =
match pts % 10 with
| 5 -> pts
| n when n pts - n
| n -> pts - n + 10
/ 5
let trumpHandPts pts =
match pts % 10 with
| n when n pts - n
| n -> pts - n + 10
/ 10
let capturedHandPts hand =
let pts = capturedTrickPts hand
match hand.Mode with
| Sun -> sunHandPts pts
| Trump(_) ->
match pts % 10, hand.Bettor with
| 6, t when t = hand.Owner -> (trumpHandPts p
Domain Model
(I listed most of these types in one line for vertical brevity).
// Types
type Team = Us | Them
type Suit = Hearts | Diamonds | Clubs | Spades
type Rank = Ace | King | Queen | Jack | Ten | Nine | Eight | Seven
type Card =
{ Rank : Rank
Suit : Suit }
type Mode = Sun | Trump of Suit
type Project = Sira | Fifty | Hundred | FourHundred | Baloot
type Hand =
{ Mode : Mode
Captured : Card list
Projects : Project list
Ground : bool
Bettor : Team
Owner : Team }Point Tally functions
```
// Trick Total Point Calculations
let sunTrickPts card =
match card.Rank with
| Ace -> 11
| Ten -> 10
| King -> 4
| Queen -> 3
| Jack -> 2
| _ -> 0
let trumpTrickPts card trump =
match (card.Rank, card.Suit) with
| (Jack, s) when s = trump -> 20
| (Nine, s) when s = trump -> 14
| _ -> sunTrickPts card
let capturedTrickPts hand =
match hand.Mode with
| Sun ->
hand.Captured
|> List.fold (fun acc card -> acc + (sunTrickPts card)) 0
| Trump(suit) ->
hand.Captured
|> List.fold (fun acc card -> acc + (trumpTrickPts card suit)) 0
+ if hand.Ground then 10
else 0
// Captured Cards Point Calculations
let sunHandPts pts =
match pts % 10 with
| 5 -> pts
| n when n pts - n
| n -> pts - n + 10
/ 5
let trumpHandPts pts =
match pts % 10 with
| n when n pts - n
| n -> pts - n + 10
/ 10
let capturedHandPts hand =
let pts = capturedTrickPts hand
match hand.Mode with
| Sun -> sunHandPts pts
| Trump(_) ->
match pts % 10, hand.Bettor with
| 6, t when t = hand.Owner -> (trumpHandPts p
Solution
In my opinion, the code is pretty good. The only thing:
In function
So, you can write:
Instead of reflection, you can enumerate all the options in the list:
In the function
Example
Since you are using Random in several function, then better to "take away" it.
Instead of
In function
trumpTrickPts all versions share the same "guarding rules".So, you can write:
let trumpTrickPts card trump =
match (card.Rank, card.Suit = trump) with
| (Jack, true) -> 20
| (Nine, true) -> 14
| _ -> sunTrickPts cardInstead of reflection, you can enumerate all the options in the list:
let fullDeck =
let suits =
[Hearts; Diamonds; Clubs; Spades]
let ranks =
[Ace ; King ; Queen ; Jack ; Ten ; Nine ; Eight ; Seven]
[for s in suits do
for r in ranks ->
newCard (r, s) ]In the function
shuffleDeck you creating a new Random inside the function. By default, Random "starts" with the current system clock. So, if you quickly run two stirring new deck, you'll get same results:Example
Since you are using Random in several function, then better to "take away" it.
Instead of
rand.Next(0, 7) 4 you can use rand.Next(7) 4let rand = System.Random()
let shuffleDeck deck =
deck |> List.sortBy (fun _ -> rand.Next())
let cutDeck deck =
let rInt = rand.Next(7) * 4
deck |> splitAt rInt
// Randomized Hand Creation for testing
let createTestHands (mode) =
let rInt = rand.Next(100)
...Code Snippets
let trumpTrickPts card trump =
match (card.Rank, card.Suit = trump) with
| (Jack, true) -> 20
| (Nine, true) -> 14
| _ -> sunTrickPts cardlet fullDeck =
let suits =
[Hearts; Diamonds; Clubs; Spades]
let ranks =
[Ace ; King ; Queen ; Jack ; Ten ; Nine ; Eight ; Seven]
[for s in suits do
for r in ranks ->
newCard (r, s) ]let rand = System.Random()
let shuffleDeck deck =
deck |> List.sortBy (fun _ -> rand.Next())
let cutDeck deck =
let rInt = rand.Next(7) * 4
deck |> splitAt rInt
// Randomized Hand Creation for testing
let createTestHands (mode) =
let rInt = rand.Next(100)
...Context
StackExchange Code Review Q#134085, answer score: 3
Revisions (0)
No revisions yet.