Ok so here's my attempt at doing this with just RDF and SPARQL.
Here's my sample data:
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
@prefix : <http://example.org/poker/>.
:Ace a :Card .
:King a :Card ;
:beatenBy :Ace .
:Queen a :Card ;
:beatenBy :King .
:Jack a :Card ;
:beatenBy :Queen .
:Ten a :Card ;
:beatenBy :Jack .
:Nine a :Card ;
:beatenBy :Ten .
:Eight a :Card ;
:beatenBy :Nine .
:Seven a :Card ;
:beatenBy :Eight .
:Six a :Card ;
:beatenBy :Seven .
:Five a :Card ;
:beatenBy :Six .
:Four a :Card ;
:beatenBy :Five .
:Three a :Card ;
:beatenBy :Four .
:Two a :Card ;
:beatenBy :Three .
:me :hasPokerHand [ :containsCard [ :value :King ; :suit :Hearts ] ,
[ :value :King ; :suit :Spades ] ,
[ :value :King ; :suit :Clubs ],
[ :value :Three ; :suit :Diamonds ],
[ :value :Seven ; :suit :Hearts ] ] .
:opponent :hasPokerHand [ :containsCard [ :value :Ace ; :suit :Diamonds ],
[ :value :Four ; :suit :Clubs ],
[ :value :Ace ; :suit :Spades ],
[ :value :Ace ; :suit :Hearts ],
[ :value :Nine ; :suit :Clubs ] ] .
:opponent2 :hasPokerHand [ :containsCard [ :value :Seven ; :suit :Clubs ],
[ :value :Eight ; :suit :Clubs ],
[ :value :Two ; :suit :Clubs ],
[ :value :Jack ; :suit :Clubs ],
[ :value :Ace ; :suit :Clubs ] ] .
:opponent3 :hasPokerHand [ :containsCard [ :value :Three ; :suit :Spades ],
[ :value :Four ; :suit :Spades ],
[ :value :Five ; :suit :Spades ],
[ :value :Six ; :suit :Spades ],
[ :value :Seven ; :suit :Spades ] ] .
Firstly checking we have a valid hand:
PREFIX : <http://example.org/poker/>
SELECT
?player
(COUNT(?card) AS ?cards)
(IF(?cards = 5, true, false) AS ?ValidHand)
WHERE
{
?player :hasPokerHand ?hand .
?hand :containsCard ?card .
} GROUP BY ?player
We can use SELECT queries to determine what hand you have e.g. pairs, three of a kind or four of a kind
PREFIX : <http://example.org/poker/>
SELECT
?player
?value
(COUNT(?value) AS ?count)
(IF(?count = 2, true, false) AS ?Pair)
(IF(?count = 3, true, false) AS ?ThreeOfAKind)
(IF(?count = 4, true, false) AS ?FourOfAKind)
WHERE
{
?player :hasPokerHand ?hand .
?hand :containsCard ?card .
?card :value ?value
} GROUP BY ?player ?value HAVING (COUNT(?value) > 1)
Full house starts to get a bit more complicated since we're looking for a pair and a 3 of a kind. We can do this by using the previous query as a subquery and then using an IF
to determine if this is present:
PREFIX : <http://example.org/poker/>
SELECT
?player
IF (?ThreeOfAKind && ?Pair, true, false) AS ?FullHouse)
WHERE
{
{
SELECT
?player
?value
(COUNT(?value) AS ?count)
(IF(?count = 2, true, false) AS ?Pair)
(IF(?count = 3, true, false) AS ?ThreeOfAKind)
(IF(?count = 4, true, false) AS ?FourOfAKind)
{
?player :hasPokerHand ?hand .
?hand :containsCard ?card .
?card :value ?value
} GROUP BY ?player ?value HAVING (COUNT(?value) > 1)
}
}
Flushes are relatively simple:
PREFIX : <http://example.org/poker/>
SELECT
?player
?suit
(true AS ?Flush)
WHERE
{
?player :hasPokerHand ?hand .
?hand :containsCard ?card .
?card :value ?value ;
:suit ?suit .
} GROUP BY ?player ?suit HAVING (COUNT(?value) = 5)
Straights are again a bit harder, note that the desired count is 4 and not 5 since the highest card in the straight will not have a card above it in the hand:
PREFIX : <http://example.org/poker>
SELECT
?player
(true AS ?Straight)
WHERE
{
?player :hasPokerHand ?hand .
?hand :containsCard ?card .
?card :value ?value .
BIND(EXISTS {
?value :beatenBy ?higherValue .
?hand :containsCard ?higherCard .
?higherCard :value ?higherValue
} AS ?StraightMember)
FILTER(?StraightMember)
} GROUP BY ?player HAVING (COUNT(?StraightMember) = 4)
From this you could work up to queries that determine whose hand is better though I don't have time to do this right now, may add more later when I have more time...