Created
November 6, 2017 19:22
-
-
Save grtjn/f24a747b823fc3f28e806d911242eb88 to your computer and use it in GitHub Desktop.
Saint Nicolas Lottery
This file contains hidden or 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
xquery version "1.0-ml"; | |
declare function local:draw-one($remaining-map, $member) { | |
let $household-name := name($member/..) | |
let $household-map := map:get($remaining-map, $household-name) | |
let $household-count := count(map:keys($household-map)) | |
let $household-key := $household-name || "/" || head(map:keys($household-map)) | |
let $remaining-members := | |
for $h-name in map:keys($remaining-map) | |
for $m-name in map:keys(map:get($remaining-map, $h-name)) | |
return $h-name || "/" || $m-name | |
let $household-position := | |
for $key at $x in $remaining-members | |
where $key eq $household-key | |
return $x | |
let $remaining-count := count($remaining-members) - $household-count | |
let $random := xdmp:random($remaining-count - 1) + 1 | |
let $target-key := | |
if ($random lt $household-position) then | |
for $m at $x in $remaining-members | |
where $x eq $random | |
return $m | |
else | |
for $m at $x in $remaining-members | |
where $x eq ($random + $household-count) | |
return $m | |
let $target-household-name := substring-before($target-key, "/") | |
let $target-member-name := substring-after($target-key, "/") | |
let $_ := map:delete(map:get($remaining-map, $target-household-name), $target-member-name) | |
return $target-key | |
}; | |
declare function local:draw-all($family) { | |
try { | |
let $members := $family//text() | |
let $remaining-map := xdmp:from-json($family) | |
let $result := map:map() | |
let $_ := | |
for $member in $members | |
let $member-key := name($member/..) || "/" || name($member) | |
let $target-key := local:draw-one($remaining-map, $member) | |
return | |
if ($target-key eq $member-key) then | |
error(xs:QName("FAIL"), $member-key || " picked him/herself!") | |
else if (substring-before($target-key, "/") eq substring-before($member-key, "/")) then | |
error(xs:QName("FAIL"), $member-key || " picked " || $target-key || "!") | |
else | |
map:put($result, $member-key, $target-key) | |
return $result | |
} catch ($ignore) { | |
local:draw-all($family) | |
} | |
}; | |
declare function local:send-mail( | |
$recipient-name as xs:string, | |
$recipient-email as xs:string, | |
$subject as xs:string, | |
$message as item() | |
) as empty-sequence() { | |
xdmp:email( | |
<em:Message | |
xmlns:em="URN:ietf:params:email-xml:" | |
xmlns:rf="URN:ietf:params:rfc822:"> | |
<rf:subject>{$subject}</rf:subject> | |
<rf:from> | |
<em:Address> | |
<em:name>Saint Nicolas Lottery</em:name> | |
<em:adrs>[email protected]</em:adrs> | |
</em:Address> | |
</rf:from> | |
<rf:to> | |
<em:Address> | |
<em:name>{$recipient-name}</em:name> | |
<em:adrs>{$recipient-email}</em:adrs> | |
</em:Address> | |
</rf:to> | |
<em:content> | |
<html xmlns="http://www.w3.org/1999/xhtml"> | |
<head> | |
<title>{$subject}</title> | |
</head> | |
<body>{$message}</body> | |
</html> | |
</em:content> | |
</em:Message> | |
) | |
}; | |
let $family := xdmp:unquote(' | |
{ | |
Household1: { | |
Grandpa: "[email protected]", | |
Grandma: "[email protected]" | |
}, | |
Household2: { | |
Son1: "[email protected]", | |
Wife1: "[email protected]", | |
Grandchild1: "[email protected]" | |
}, | |
Household3: { | |
Daughter2: "[email protected]", | |
Husband2: "[email protected]", | |
Grandchild2: "[email protected]", | |
Grandchild3: "[email protected]" | |
} | |
} | |
') | |
let $result := local:draw-all($family) | |
let $_ := xdmp:save("/tmp/drawing.json", xdmp:to-json($result)) | |
for $draw in map:keys($result) | |
let $household-name := substring-before($draw, "/") | |
let $member-name := substring-after($draw, "/") | |
let $member-email := map:get(map:get(xdmp:from-json($family), $household-name), $member-name) | |
let $target-name := substring-after(map:get($result, $draw), "/") | |
return local:send-mail( | |
$member-name, | |
$member-email, | |
"Saint Nicolas lottery for 5 December", | |
"Dear " || $member-name || ", you have drawn " || $target-name || "." | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Input is a JSON family tree, output as email. Runs on MarkLogic. Note that it draws names from other households only.