HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Tally Calculator for Baloot in F#

Submitted by: @import:stackexchange-codereview··
0
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).

// 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 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 card


Instead 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) 4

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)
    ...

Code Snippets

let trumpTrickPts card trump = 
    match (card.Rank, card.Suit = trump) with
    | (Jack, true) -> 20
    | (Nine, true) -> 14
    | _ -> sunTrickPts card
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) ]
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.