From c9bf7595e624279f929068f20969c9bfa1e4f79a Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 5 Apr 2024 22:27:28 +0100 Subject: [PATCH 01/20] Remove / comment out explicit Glicko2 stuff --- src/lib/glicko2.hoon | 62 ------------------------------------- src/lib/telos.hoon | 54 ++++++++++++++++----------------- src/sur/glicko2.hoon | 52 ------------------------------- src/sur/telos.hoon | 4 +-- src/tests/glicko2.hoon | 69 ------------------------------------------ 5 files changed, 29 insertions(+), 212 deletions(-) delete mode 100644 src/lib/glicko2.hoon delete mode 100644 src/sur/glicko2.hoon delete mode 100644 src/tests/glicko2.hoon diff --git a/src/lib/glicko2.hoon b/src/lib/glicko2.hoon deleted file mode 100644 index 74025b5..0000000 --- a/src/lib/glicko2.hoon +++ /dev/null @@ -1,62 +0,0 @@ -/- *glicko2 -|% -++ delta - |= [[(list r) (list rd) (list outcome)] @rs] - :: XX where possible, these `@rs`s should be /sur types - ^- @rs - .20211718190.033577 -:: -++ eee - |= [@ @] - ^- @rs - .0.0004206362164754052 -:: -++ gee - |= rd - ^- @rs - .0.0051822143113334366 -:: -++ get-rating - |= =player-data - ^+ r.player-data - .~1.500 -:: -++ get-rd - |= =player-data - ^+ rd.player-data - .~350.0 -:: -++ new-vol - |= [[(list r) (list rd) (list outcome)] @rs] - ^- @rd - .~0.06000004916805347 -:: -++ pre-rating-rd - |= =rd - ^+ rd - .~2.015655080250959 -:: -++ scale-rat - |= =r - ^+ r - .~0 -:: -++ scale-rd - |= =rd - ^+ rd - .~2.014761872416068 -:: -++ update-player - |= [=player-data matches=(list (pair player-data outcome))] - ^+ player-data - :* .~1300 :: dummy r - .~300 :: dummy rd - .~0.03 :: dummy vol - == -:: -++ vee - |= [(list r) (list rd)] - ^- @rs - .795778282.6043352 -:: --- diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 7ef0ef7..955fd06 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -1,5 +1,4 @@ /- *telos -/+ glicko2 |% :: +| %poke-helpers @@ -195,30 +194,31 @@ ++ update-ratings |= [players=(map player player-data) =winner =loser draw=?] ^+ players - :: - :: add default player-data for new players - =/ winner-data - %+ fall - (~(get by players) winner) - *player-data - =/ loser-data - %+ fall - (~(get by players) loser) - *player-data - :: - :: get new data for both players - =+ - ^= [new-winner-data new-loser-data] - ?. draw - :- (update-player:glicko2 winner-data [[loser-data %win] ~]) - (update-player:glicko2 loser-data [[winner-data %loss] ~]) - :- (update-player:glicko2 winner-data [[loser-data %draw] ~]) - (update-player:glicko2 loser-data [[winner-data %draw] ~]) - :: - :: add new data to players - %+ %~ put - by - (~(put by players) winner new-winner-data) - loser - new-loser-data + (my [[winner [.~1500 .~250 .~0.05]] [loser [.~1500 .~250 .~0.05]] ~]) + :: :: + :: :: add default player-data for new players + :: =/ winner-data + :: %+ fall + :: (~(get by players) winner) + :: *player-data + :: =/ loser-data + :: %+ fall + :: (~(get by players) loser) + :: *player-data + :: :: + :: :: get new data for both players + :: =+ + :: ^= [new-winner-data new-loser-data] + :: ?. draw + :: :- (update-player:glicko2 winner-data [[loser-data %win] ~]) + :: (update-player:glicko2 loser-data [[winner-data %loss] ~]) + :: :- (update-player:glicko2 winner-data [[loser-data %draw] ~]) + :: (update-player:glicko2 loser-data [[winner-data %draw] ~]) + :: :: + :: :: add new data to players + :: %+ %~ put + :: by + :: (~(put by players) winner new-winner-data) + :: loser + :: new-loser-data -- diff --git a/src/sur/glicko2.hoon b/src/sur/glicko2.hoon deleted file mode 100644 index d713537..0000000 --- a/src/sur/glicko2.hoon +++ /dev/null @@ -1,52 +0,0 @@ -|% -:: -:: define constants as in step 1 of the glicko-2 system -:: -:: τ, the change in player's volatility over time -:: XX settle on a strategy behind the default value of tau and rd -:: ideally, a player's rating should jump around a -:: lot in their first ~10 matches so they hit -:: an accurate estimate of their skill quickly. -:: this might require a %server-action poke -:: to adjust tau manually -+$ tau - $~ .~0.5 - @rd -:: -:: other constants -:: -:: epsilon -+$ eps - $~ .~0.0000001 - @rd -:: -:: player's rating -+$ r - $~ .~1500 - @rd -:: -:: player's rating deviation -+$ rd - $~ .~250 - @rd -:: -:: player's rating volatility -+$ vol - $~ .~0.05 - @rd -:: -:: structures -+$ player-data - $: =r - =rd - =vol - == -:: -:: outcome -+$ outcome - $? %win - %loss - %draw - == -:: --- diff --git a/src/sur/telos.hoon b/src/sur/telos.hoon index 780d50f..c7b5fcc 100644 --- a/src/sur/telos.hoon +++ b/src/sur/telos.hoon @@ -1,4 +1,3 @@ -/- *glicko2 |% +$ payload * :: arbitrary data on any match +$ source @p :: our source for a match record @@ -8,9 +7,10 @@ +$ id @uvF :: unique id for a match and its payload +$ loser player +$ winner player ++$ player-data [r=@rd rd=@rd vol=@rd] :: placeholder :: +$ match - :: + :: $: =id =date =winner diff --git a/src/tests/glicko2.hoon b/src/tests/glicko2.hoon deleted file mode 100644 index e427bb3..0000000 --- a/src/tests/glicko2.hoon +++ /dev/null @@ -1,69 +0,0 @@ -/+ *test, *glicko2 -|% -++ test-delta - %+ expect-eq - !> .20211718190.033577 - !> %- delta - :- :- ~[1.400 1.500 1.700] - :- ~[.30.0 .100.0 .300.0] - ~[[%win .1.00] [%loss .0.00] [%loss .0.00]] - .795778282.6043352 -:: -++ test-eee - %+ expect-eq - !> .0.0004206362164754052 - !> %- eee - :- 1.500 - .350.0 -:: -++ test-gee - %+ expect-eq - !> .0.0051822143113334366 - !> %- gee .350.0 -:: -++ test-get-rating - %+ expect-eq - !> 1.500 - !> %- get-rating [1.500 .350.0 .0.06] -:: -++ test-get-dev - %+ expect-eq - !> .350.0 - !> %- get-dev [1.500 .350.0 .0.06] -:: -++ test-new-vol - %+ expect-eq - !> .0.06000004916805347 - !> %- new-vol - :- :- ~[1.400 1.500 1.700] - :- ~[.30.0 .100.0 .300.0] - ~[[%win .1.00] [%loss .0.00] [%loss .0.00]] - .795778282.6043352 -:: -++ test-pre-rating-dev - %+ expect-eq - !> .2.015655080250959 - !> %- pre-rating-dev .350.0 -:: -++ test-scale-rat - %+ expect-eq - !> 0 - !> %- scale-rat 1.500 -:: -++ test-scale-dev - %+ expect-eq - !> .2.014761872416068 - !> %- scale-dev .350.0 -:: -++ test-update-player - %+ expect-eq - !> [1.441 .193.0 .0.06] - !> %- update-player - :- [1.500 .350.0 .0.06] - ~[[%win .1.00] [%loss .0.00] [%loss .0.00]] -:: -++ test-vee - %+ expect-eq - !> .795778282.6043352 - !> %+ vee ~[1.400 1.500 1.700] ~[.30.0 .100.0 .300.0] --- From 9594cf8c9ba33bbaf20bec618720916e9b772d54 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 5 Apr 2024 22:27:43 +0100 Subject: [PATCH 02/20] Update for 411k --- src/lib/telos.hoon | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 955fd06..318ebe9 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -40,7 +40,7 @@ ++ delete-player-from-ratings |= [=game =player =ratings] ^+ ratings - %- ~(rut by ratings) + %- ~(urn by ratings) |= [=^game players=(map ^player player-data)] ^+ players ?. =(game ^game) @@ -140,7 +140,7 @@ %- zing %+ turn %~ tap by - %- ~(rut by ratings) + %- ~(urn by ratings) |= [=game players=(map player player-data)] ^- (list player) %+ skim From 9eb886d06048c460c55eb6c93f875425c3732e07 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 5 Apr 2024 22:31:39 +0100 Subject: [PATCH 03/20] Remove rd and vol --- src/lib/telos.hoon | 2 +- src/sur/telos.hoon | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 318ebe9..c06983d 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -194,7 +194,7 @@ ++ update-ratings |= [players=(map player player-data) =winner =loser draw=?] ^+ players - (my [[winner [.~1500 .~250 .~0.05]] [loser [.~1500 .~250 .~0.05]] ~]) + (my [[winner .~1500] [loser .~1500] ~]) :: :: :: :: add default player-data for new players :: =/ winner-data diff --git a/src/sur/telos.hoon b/src/sur/telos.hoon index c7b5fcc..8e9ae6b 100644 --- a/src/sur/telos.hoon +++ b/src/sur/telos.hoon @@ -7,7 +7,7 @@ +$ id @uvF :: unique id for a match and its payload +$ loser player +$ winner player -+$ player-data [r=@rd rd=@rd vol=@rd] :: placeholder ++$ player-data r=@rd :: placeholder :: +$ match :: From 13b584532062f5f85718c94d9d596cc9a51ecd86 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 5 Apr 2024 22:37:59 +0100 Subject: [PATCH 04/20] CTRL+F player-data into a @rd rating --- src/app/telos.hoon | 80 ++++++++++++++--------------- src/lib/telos.hoon | 26 +++++----- src/mar/telos/data/game.hoon | 4 +- src/mar/telos/data/player-game.hoon | 4 +- src/mar/telos/data/player.hoon | 4 +- src/sur/telos.hoon | 5 +- testing/pyglicko2/glicko2.py | 58 ++++++++++----------- 7 files changed, 91 insertions(+), 90 deletions(-) diff --git a/src/app/telos.hoon b/src/app/telos.hoon index aef500b..169f651 100644 --- a/src/app/telos.hoon +++ b/src/app/telos.hoon @@ -247,7 +247,7 @@ ~(tap by ratings) has-player-in-ratings player.action - |= [=game (map player player-data)] + |= [=game (map player rating)] ^- card :* %pass ~ %agent [our.bowl dap.bowl] %poke %delete-player-from-game !>([game player.action]) @@ -337,34 +337,34 @@ :: update subscribers to this game %+ turn new-ratings-list - |= [=player =player-data] + |= [=player =rating] ^- card :* %give %fact ~[/ratings/(scot %tas game.action)] - %telos-player-rating !>([player r.player-data]) + %telos-player-rating !>([player rating]) == :: :: update subscribers to one player in any game %+ turn new-ratings-list - |= [=player =player-data] + |= [=player =rating] ^- card :* %give %fact ~[/ratings/(scot %p player)] - %telos-game-rating !>([game.action r.player-data]) + %telos-game-rating !>([game.action rating]) == :: :: update subscibers to one player in this game %+ turn new-ratings-list - |= [=player =player-data] + |= [=player =rating] ^- card :* %give %fact ~[/ratings/game/(scot %p player)] - %telos-rating !>(r.player-data) + %telos-rating !>(rating) == == :: end of list of lists of cards == :: end of server actions == :: end of mark branches :: -++ on-watch +++ on-watch |= =path ^- (quip card _this) ?+ path (on-watch:def path) @@ -379,13 +379,13 @@ %+ fall %+ bind (~(get by ratings) game) - |= ratings=(map player player-data) + |= ratings=(map player rating) ~(tap by ratings) ~ - |= [=player =player-data] + |= [=player =rating] ^- card :* %give %fact ~ - %telos-player-rating !>([player r.player-data]) + %telos-player-rating !>([player rating]) == :: :: ratings updates for a player @@ -397,10 +397,10 @@ ~(tap by ratings) has-player-in-ratings player - |= [=game players=(map ^player player-data)] + |= [=game players=(map ^player rating)] ^- card :* %give %fact ~ - %telos-game-rating !>([game r:(~(got by players) player)]) + %telos-game-rating !>([game (~(got by players) player)]) == :: :: ratings updates for a player in one game @@ -411,11 +411,11 @@ ?> (~(has by ratings) game) :_ this %+ turn - ^- (list player-data) + ^- (list rating) (drop (~(get by (~(got by ratings) game)) player)) - |= =player-data + |= =rating :* %give %fact ~ - %telos-rating !>(r.player-data) + %telos-rating !>(rating) == == :: end of path branches :: @@ -456,8 +456,8 @@ ~(tap by ratings) has-player-in-ratings player - |= [=game players=(map ^player player-data)] - ^- [^game (pair player-data (list match))] + |= [=game players=(map ^player rating)] + ^- [^game (pair rating (list match))] :- game :- (~(got by players) player) (skim (~(got by archive) game) (curr has-player-in-match player)) @@ -476,8 +476,8 @@ ~ %+ bind (~(get by (~(got by ratings) game)) player) - |= =player-data - :- r.player-data + |= =rating + :- rating %+ skim (~(got by archive) game) (curr has-player-in-match player) @@ -513,8 +513,8 @@ ?~ players=(~(get by ratings) game) ~ %- ~(run by u.players) - |= =player-data - r.player-data + |= =rating + rating :: :: return all ratings for a player :: .^(noun %gx /=telos=/ratings/~sampel-palnet/noun) @@ -530,9 +530,9 @@ ~(tap by ratings) has-player-in-ratings player - |= [=game ratings=(map ^player player-data)] + |= [=game ratings=(map ^player rating)] ^- [^game @rd] - [game r:(~(got by ratings) player)] + [game (~(got by ratings) player)] :: :: return rating for one player in one game :: .^(noun %gx /=telos=/ratings/chess/~sampel-palnet/noun) @@ -547,8 +547,8 @@ ~ %+ bind (~(get by (~(got by ratings) game)) player) - |= =player-data - r.player-data + |= =rating + rating :: :: return ratings within a range for one game :: .^(noun %gx /=telos=/ratings/chess/.~1250/.~1750/25/0/noun) @@ -571,12 +571,12 @@ %+ skim %+ skim ~(tap by (~(got by ratings) game)) - |= [player =player-data] - (lth r.player-data hi) - |= [player =player-data] - (gth r.player-data lo) - |= [=player =player-data] - [player r.player-data] + |= [player =rating] + (lth rating hi) + |= [player =rating] + (gth rating lo) + |= [=player =rating] + [player rating] == :: end of scries :: ++ on-agent @@ -617,29 +617,29 @@ :: confirm results :- :~ :: update players with their new ratings :* %pass ~ %agent [winner game] - %poke %win !>([id loser r.winner-new-data]) + %poke %win !>([id loser winner-new-data]) == :* %pass ~ %agent [loser game] - %poke %loss !>([id winner r.loser-new-data]) + %poke %loss !>([id winner loser-new-data]) == :: update other subscribers :* %give %fact ~[/ratings/(scot %tas game)] - %telos-player-rating !>([winner r.winner-new-data]) + %telos-player-rating !>([winner winner-new-data]) == :* %give %fact ~[/ratings/(scot %tas game)] - %telos-player-rating !>([loser r.loser-new-data]) + %telos-player-rating !>([loser loser-new-data]) == :* %give %fact ~[/ratings/(scot %p winner)] - %telos-game-rating !>([game r.winner-new-data]) + %telos-game-rating !>([game winner-new-data]) == :* %give %fact ~[/ratings/(scot %p loser)] - %telos-game-rating !>([game r.loser-new-data]) + %telos-game-rating !>([game loser-new-data]) == :* %give %fact ~[/ratings/game/(scot %p winner)] - %telos-rating !>(r.winner-new-data) + %telos-rating !>(winner-new-data) == :* %give %fact ~[/ratings/game/(scot %p loser)] - %telos-rating !>(r.loser-new-data) + %telos-rating !>(loser-new-data) == == %= this diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index c06983d..6edda18 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -41,7 +41,7 @@ |= [=game =player =ratings] ^+ ratings %- ~(urn by ratings) - |= [=^game players=(map ^player player-data)] + |= [=^game players=(map ^player rating)] ^+ players ?. =(game ^game) players @@ -95,19 +95,19 @@ |= [=rank:title =ratings] ^+ ratings %- ~(run by ratings) - |= players=(map player player-data) + |= players=(map player rating) ^+ players %- malt %+ skip ~(tap by players) - |= [=player player-data] + |= [=player rating] ^- ? =(rank (clan:title player)) :: ++ compute-ratings-game |= matches=(list match) - ^- (map player player-data) - =/ player-ratings `(map player player-data)`~ + ^- (map player rating) + =/ player-ratings `(map player rating)`~ |- ?~ matches player-ratings @@ -141,7 +141,7 @@ %+ turn %~ tap by %- ~(urn by ratings) - |= [=game players=(map player player-data)] + |= [=game players=(map player rating)] ^- (list player) %+ skim ~(tap in ~(key by players)) @@ -173,9 +173,9 @@ :: :: general-purpose filters ++ filter-ratings - |= [games=(list [game (map player player-data)]) filter=$-([[game (map player player-data)] @] ?) term=@] + |= [games=(list [game (map player rating)]) filter=$-([[game (map player rating)] @] ?) term=@] ^+ games - (skim games |=(x=[game (map player player-data)] (filter x term))) + (skim games |=(x=[game (map player rating)] (filter x term))) :: ++ has-player-in-match |= [=match =player] @@ -185,26 +185,26 @@ == :: ++ has-player-in-ratings - |= [[game ratings=(map player player-data)] player=@] + |= [[game ratings=(map player rating)] player=@] ^- ? (~(has by ratings) player) :: +| %ratings-helper :: ++ update-ratings - |= [players=(map player player-data) =winner =loser draw=?] + |= [players=(map player rating) =winner =loser draw=?] ^+ players (my [[winner .~1500] [loser .~1500] ~]) :: :: - :: :: add default player-data for new players + :: :: add default rating for new players :: =/ winner-data :: %+ fall :: (~(get by players) winner) - :: *player-data + :: *rating :: =/ loser-data :: %+ fall :: (~(get by players) loser) - :: *player-data + :: *rating :: :: :: :: get new data for both players :: =+ diff --git a/src/mar/telos/data/game.hoon b/src/mar/telos/data/game.hoon index 304df68..5036854 100644 --- a/src/mar/telos/data/game.hoon +++ b/src/mar/telos/data/game.hoon @@ -1,8 +1,8 @@ /- *telos -|_ data=(pair (map player player-data) (list match)) +|_ data=(pair (map player rating) (list match)) ++ grab |% - ++ noun (pair (map player player-data) (list match)) + ++ noun (pair (map player rating) (list match)) -- ++ grow |% diff --git a/src/mar/telos/data/player-game.hoon b/src/mar/telos/data/player-game.hoon index ea0de99..2c6125a 100644 --- a/src/mar/telos/data/player-game.hoon +++ b/src/mar/telos/data/player-game.hoon @@ -1,8 +1,8 @@ /- *telos -|_ data=(unit (pair player-data (list match))) +|_ data=(unit (pair rating (list match))) ++ grab |% - ++ noun (unit (pair player-data (list match))) + ++ noun (unit (pair rating (list match))) -- ++ grow |% diff --git a/src/mar/telos/data/player.hoon b/src/mar/telos/data/player.hoon index 0b4c6a2..d3580af 100644 --- a/src/mar/telos/data/player.hoon +++ b/src/mar/telos/data/player.hoon @@ -1,8 +1,8 @@ /- *telos -|_ data=(map game (pair player-data (list match))) +|_ data=(map game (pair rating (list match))) ++ grab |% - ++ noun (map game (pair player-data (list match))) + ++ noun (map game (pair rating (list match))) -- ++ grow |% diff --git a/src/sur/telos.hoon b/src/sur/telos.hoon index 8e9ae6b..804d18a 100644 --- a/src/sur/telos.hoon +++ b/src/sur/telos.hoon @@ -3,11 +3,12 @@ +$ source @p :: our source for a match record +$ player @p +$ date @da +:: XX change to @ud ++$ rating @rd :: player's rating +$ game @tas +$ id @uvF :: unique id for a match and its payload +$ loser player +$ winner player -+$ player-data r=@rd :: placeholder :: +$ match :: @@ -30,7 +31,7 @@ :: +$ payloads (map id payload) +$ archive (map game (list match)) -+$ ratings (map game (map player player-data)) ++$ ratings (map game (map player rating)) :: +$ client-action $% [%cede-match [=game =winner =payload]] diff --git a/testing/pyglicko2/glicko2.py b/testing/pyglicko2/glicko2.py index a2ffd46..fa9f5b5 100644 --- a/testing/pyglicko2/glicko2.py +++ b/testing/pyglicko2/glicko2.py @@ -29,7 +29,7 @@ class Player: # Class attribute # The system constant, which constrains # the change in volatility over time. - # + # # underscore = "weak internal use"; do not export _tau = 0.5 @@ -37,7 +37,7 @@ def getRating(self): # __double_leading_underscore # inside class FooBar, __boo becomes _FooBar__boo # "self.rating" becomes Ryan.rating in tests.py - # + # # 'self' is a specific instance of parent class # (add (add rating.player 173.7178) 1500) # print(f"getRating: {(self.__rating * 173.7178) + 1500}") @@ -64,7 +64,7 @@ def setRd(self, rd): self.__rd = rd / 173.7178 rd = property(getRd, setRd) - + # __double_leading_and_trailing_underscore__ # "magic" objects or attribs that live in user-controlled namespaces # bascially, reserved for Python itself @@ -74,23 +74,23 @@ def __init__(self, rating = 1500, rd = 350, vol = 0.06): self.setRating(rating) self.setRd(rd) self.vol = vol - + def _preRatingRD(self): """ Calculates and updates the player's rating deviation for the beginning of a rating period. - + preRatingRD() -> None - + """ # (sqrt (add (pow rd.player 2) (pow vol.player 2))) # print(f"preRatingRD: {math.sqrt(math.pow(self.__rd, 2) + math.pow(self.vol, 2))}") self.__rd = math.sqrt(math.pow(self.__rd, 2) + math.pow(self.vol, 2)) - + def update_player(self, rating_list, RD_list, outcome_list): """ Calculates the new rating and rating deviation of the player. - + update_player(list[int], list[int], list[bool]) -> None - + """ # Convert the rating and rating deviation values for internal use. # (div (sub x 1500) 173.7178) @@ -103,21 +103,21 @@ def update_player(self, rating_list, RD_list, outcome_list): self._preRatingRD() # (div 1 (sqrt (add (pow rd.player 2) (div 1 v)))) self.__rd = 1 / math.sqrt((1 / math.pow(self.__rd, 2)) + (1 / v)) - + tempSum = 0 for i in range(len(rating_list)): # (add tempSum (mul g.player (sub outcome_list[i] self._E(rating_list[i], RD_list[i]))) tempSum += self._g(RD_list[i]) * (outcome_list[i] - self._E(rating_list[i], RD_list[i])) - # (add player.rating (mul (pow rd.player 2) tempSum)) + # (add playerating (mul (pow rd.player 2) tempSum)) self.__rating += math.pow(self.__rd, 2) * tempSum # print(f"{math.pow(self.__rd, 2) * tempSum}") - - + + def _newVol(self, rating_list, RD_list, outcome_list, v): """ Calculating the new volatility as per the Glicko2 system. - + _newVol(list, list, list) -> float - + """ # Step 5 of the Glicko-2 algorithm # Step 5.1 @@ -184,12 +184,12 @@ def f(x): / (2 * math.pow(math.pow(self.__rd, 2) + v + math.exp(x), 2)) - (x - A) / math.pow(self._tau, 2) # print(f"f: {math.exp(x) * (math.pow(delta, 2) - math.pow(self.__rd, 2) - v - math.exp(x)) / (2 * math.pow(math.pow(self.__rd, 2) + v + math.exp(x), 2)) - (x - A) / math.pow(self._tau, 2)}") return f - + def _delta(self, rating_list, RD_list, outcome_list, v): """ The delta function of the Glicko2 system. - + _delta(list, list, list) -> float - + """ tempSum = 0 for i in range(len(rating_list)): @@ -197,12 +197,12 @@ def _delta(self, rating_list, RD_list, outcome_list, v): tempSum += self._g(RD_list[i]) * (outcome_list[i] - self._E(rating_list[i], RD_list[i])) # print(f"delta: {v * tempSum}") return v * tempSum - + def _v(self, rating_list, RD_list): """ The v function of the Glicko2 system. - + _v(list[int], list[int]) -> float - + """ tempSum = 0 for i in range(len(rating_list)): @@ -212,33 +212,33 @@ def _v(self, rating_list, RD_list): # (div 1 tempSum) # print(f"v: {1 / tempSum}") return 1 / tempSum - + def _E(self, p2rating, p2RD): """ The Glicko E function. - + _E(int) -> float - + """ # (div 1 (add 1 (exp ;(mul -1 self._g(p2RD) (sub rating.player p2rating))))) # print(f"E: {1 / (1 + math.exp(-1 * self._g(p2RD) * (self.__rating - p2rating)))}") return 1 / (1 + math.exp(-1 * self._g(p2RD) * (self.__rating - p2rating))) - + def _g(self, RD): """ The Glicko2 g(RD) function. - + _g() -> float - + """ # (div 1 (sqrt (add 1 (mul 3 (div (pow RD 2) (pow pi 2)))))) # print(f"g: {1 / math.sqrt(1 + 3 * math.pow(RD, 2) / math.pow(math.pi, 2))}") return 1 / math.sqrt(1 + 3 * math.pow(RD, 2) / math.pow(math.pi, 2)) - + def did_not_compete(self): """ Applies Step 6 of the algorithm. Use this for players who did not compete in the rating period. did_not_compete() -> None - + """ # print(f"did_not_compete: {self._preRatingRD()}") self._preRatingRD() From 81a2a92951a56aa3db4cfe4c64c3c660d2d0e60d Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Fri, 5 Apr 2024 22:42:11 +0100 Subject: [PATCH 05/20] CTRL+F @rd rating to a @ud --- src/app/telos.hoon | 2 +- src/lib/telos.hoon | 2 +- src/mar/telos/game-rating.hoon | 4 ++-- src/mar/telos/player-rating.hoon | 4 ++-- src/mar/telos/rating.hoon | 4 ++-- src/mar/telos/ratings/game.hoon | 4 ++-- src/mar/telos/ratings/player-game.hoon | 4 ++-- src/mar/telos/ratings/player.hoon | 4 ++-- src/sur/telos.hoon | 3 +-- 9 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/app/telos.hoon b/src/app/telos.hoon index 169f651..57ff14f 100644 --- a/src/app/telos.hoon +++ b/src/app/telos.hoon @@ -531,7 +531,7 @@ has-player-in-ratings player |= [=game ratings=(map ^player rating)] - ^- [^game @rd] + ^- [^game @ud] [game (~(got by ratings) player)] :: :: return rating for one player in one game diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 6edda18..8701375 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -194,7 +194,7 @@ ++ update-ratings |= [players=(map player rating) =winner =loser draw=?] ^+ players - (my [[winner .~1500] [loser .~1500] ~]) + (my [[winner 1.500] [loser 1.500] ~]) :: :: :: :: add default rating for new players :: =/ winner-data diff --git a/src/mar/telos/game-rating.hoon b/src/mar/telos/game-rating.hoon index 0b8c181..0bb1c92 100644 --- a/src/mar/telos/game-rating.hoon +++ b/src/mar/telos/game-rating.hoon @@ -1,8 +1,8 @@ /- *telos -|_ game-rating=(pair game @rd) +|_ game-rating=(pair game @ud) ++ grab |% - ++ noun (pair game @rd) + ++ noun (pair game @ud) -- ++ grow |% diff --git a/src/mar/telos/player-rating.hoon b/src/mar/telos/player-rating.hoon index 921e0d3..bd6d382 100644 --- a/src/mar/telos/player-rating.hoon +++ b/src/mar/telos/player-rating.hoon @@ -1,8 +1,8 @@ /- *telos -|_ player-rating=(pair player @rd) +|_ player-rating=(pair player @ud) ++ grab |% - ++ noun (pair player @rd) + ++ noun (pair player @ud) -- ++ grow |% diff --git a/src/mar/telos/rating.hoon b/src/mar/telos/rating.hoon index 5d171b4..09e15eb 100644 --- a/src/mar/telos/rating.hoon +++ b/src/mar/telos/rating.hoon @@ -1,8 +1,8 @@ /- *telos -|_ rating=@rd +|_ rating=@ud ++ grab |% - ++ noun @rd + ++ noun @ud -- ++ grow |% diff --git a/src/mar/telos/ratings/game.hoon b/src/mar/telos/ratings/game.hoon index f6d5f95..0946dfe 100644 --- a/src/mar/telos/ratings/game.hoon +++ b/src/mar/telos/ratings/game.hoon @@ -1,8 +1,8 @@ /- *telos -|_ ratings=(map player @rd) +|_ ratings=(map player @ud) ++ grab |% - ++ noun (map player @rd) + ++ noun (map player @ud) -- ++ grow |% diff --git a/src/mar/telos/ratings/player-game.hoon b/src/mar/telos/ratings/player-game.hoon index 13f6729..241fce7 100644 --- a/src/mar/telos/ratings/player-game.hoon +++ b/src/mar/telos/ratings/player-game.hoon @@ -1,8 +1,8 @@ /- *telos -|_ rating=(unit @rd) +|_ rating=(unit @ud) ++ grab |% - ++ noun (unit @rd) + ++ noun (unit @ud) -- ++ grow |% diff --git a/src/mar/telos/ratings/player.hoon b/src/mar/telos/ratings/player.hoon index f445a74..263be6c 100644 --- a/src/mar/telos/ratings/player.hoon +++ b/src/mar/telos/ratings/player.hoon @@ -1,8 +1,8 @@ /- *telos -|_ ratings=(map game @rd) +|_ ratings=(map game @ud) ++ grab |% - ++ noun (map game @rd) + ++ noun (map game @ud) -- ++ grow |% diff --git a/src/sur/telos.hoon b/src/sur/telos.hoon index 804d18a..07979eb 100644 --- a/src/sur/telos.hoon +++ b/src/sur/telos.hoon @@ -3,8 +3,7 @@ +$ source @p :: our source for a match record +$ player @p +$ date @da -:: XX change to @ud -+$ rating @rd :: player's rating ++$ rating @ud :: player's rating +$ game @tas +$ id @uvF :: unique id for a match and its payload +$ loser player From d130db607bd43cb0f2e28683f30a2b7c42d62575 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 6 Apr 2024 15:01:15 +0100 Subject: [PATCH 06/20] wip: draft most elo logic --- src/lib/elo.hoon | 93 ++++++++++++++++++++++++++++++++++++++ src/lib/telos.hoon | 110 ++++++++++++++++++++++++++++++++------------- 2 files changed, 173 insertions(+), 30 deletions(-) create mode 100644 src/lib/elo.hoon diff --git a/src/lib/elo.hoon b/src/lib/elo.hoon new file mode 100644 index 0000000..cfd2b35 --- /dev/null +++ b/src/lib/elo.hoon @@ -0,0 +1,93 @@ +/- *telos +|% +++ round + |= rd=@rd + ^- @ud + (abs:si (need (toi:rd rd))) +:: +:: define expected score for a player in this match +:: Ea = expected score for player A +:: Ra = Elo rating of player A +:: Rb = Elo rating of player B +:: Ea = 1 / (1 + 2^((Rb - Ra) / 125)) +++ expected-score + |= [our=rating opp=rating] + ^- @rd + %+ div:rd + .~1 + %+ add:rd + ~.1 + :: XX need our own pow:rd + %+ pow:rd + .~2 + %+ div:rd + %+ sub:rd + (sun:rd opp) + (sun:rd our) + ~.125 +:: +:: calculate K +:: K = 16 over 100 games played +:: K = 24 between 60 and 100 games played +:: K = 32 between 30 and 60 games played +:: K = 40 between 10 and 30 games played +:: K = 64 less than 10 games played +++ scaling-factor + |= matches=@ud + ^- @ud + :: ?: (lth matches 10) + :: 64 + ?: (lth matches 30) + 40 + ?: (lth matches 60) + 32 + ?: (lth matches 100) + 24 + 16 +:: +:: bootstrap a new rating in the first 10 games +:: P = performance rating +:: Σ = sum of opponents' ratings +:: N = number of games played +:: w = number of wins +:: l = number of losses +:: P = (Σ + (400 * (w - l))) / N +++ new-performance-rating + |= [sum=@ud matches=@ud wins=@ud losses=@ud] + ^- rating + %+ div + %+ add + sum + %+ mul + 400 + %+ sub + wins + losses + matches +:: +:: calculate new rating +:: Rn = new rating +:: Ro = old rating +:: Ee = expected score +:: Ea = actual score +:: K = scaling factor +:: Rn = Ro + (K * (Ea - Ee)) +++ new-rating + |= [our=rating our-ex=@rd our-scale=@ud opp=rating out=?(%win %loss %draw)] + ^- rating + =/ our-actual + ?: =(out %win) + our-ex + ?. =(out %draw) + (sub:rd .~1 our-ex) + :: XX what's our actual score if it's a draw? + !! + %- round + %+ add:rd + (sun:rd our) + %+ mul:rd + (sun:rd our-scale) + %+ sub:rd + our-actual + our-ex +-- diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 8701375..717e9bb 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -1,4 +1,5 @@ /- *telos +/+ elo |% :: +| %poke-helpers @@ -184,41 +185,90 @@ =(player loser.match) == :: +++ has-winner-in-match + |= [=match =player] + ^- ? + =(player winner.match) +:: +++ has-loser-in-match + |= [=match =player] + ^- ? + =(player loser.match) +:: ++ has-player-in-ratings |= [[game ratings=(map player rating)] player=@] ^- ? (~(has by ratings) player) :: -+| %ratings-helper ++| %ratings :: -++ update-ratings - |= [players=(map player rating) =winner =loser draw=?] +++ update-elo-ratings + :: XX matches should include the match just played + |= [players=(map player rating) matches=(list match) =winner =loser draw=?] ^+ players - (my [[winner 1.500] [loser 1.500] ~]) - :: :: - :: :: add default rating for new players - :: =/ winner-data - :: %+ fall - :: (~(get by players) winner) - :: *rating - :: =/ loser-data - :: %+ fall - :: (~(get by players) loser) - :: *rating - :: :: - :: :: get new data for both players - :: =+ - :: ^= [new-winner-data new-loser-data] - :: ?. draw - :: :- (update-player:glicko2 winner-data [[loser-data %win] ~]) - :: (update-player:glicko2 loser-data [[winner-data %loss] ~]) - :: :- (update-player:glicko2 winner-data [[loser-data %draw] ~]) - :: (update-player:glicko2 loser-data [[winner-data %draw] ~]) - :: :: - :: :: add new data to players - :: %+ %~ put - :: by - :: (~(put by players) winner new-winner-data) - :: loser - :: new-loser-data + =/ new-winner-elo=rating + =/ our-rating + (~(gut by ratings) winner 1.500) + =/ opp-rating + (~(gut by ratings) loser 1.500) + =/ our-matches + (skim matches |=(=match (has-player-in-match match winner))) + =/ our-outcome + :: XX assuming (head matches) is most recent match + ?. draw:(head matches) + %win + %draw + :: + ?: (lth our-matches 10) + %: new-performance-rating:elo + :: XX sum up opps' ratings from previous games + :: would need to know what the opponents' + :: ratings were at the time of the match. + :: could change id.match to @da and scry + :: for the rating at that case. + (~(gut by ratings) loser 1.500) + (lent our-matches) + (skim our-matches |=(=match (has-winner-in-match match winner))) + (skim our-matches |=(=match (has-loser-in-match match winner))) + == + %: new-rating:elo + our-rating + (expected-score:elo our-rating opp-rating) + (scaling-factor:elo (lent our-matches)) + opp-rating + our-outcome + == + =/ new-loser-elo=rating + =/ our-rating + (~(gut by ratings) loser 1.500) + =/ opp-rating + (~(gut by ratings) winner 1.500) + =/ our-matches + (skim matches |=(=match (has-player-in-match match loser))) + =/ our-outcome + :: XX assuming (head matches) is most recent match + ?. draw:(head matches) + %loss + %draw + :: + ?: (lth our-matches 10) + %: new-performance-rating:elo + :: XX sum up opps' ratings from previous games + (~(gut by ratings) loser 1.500) + (lent our-matches) + (skim our-matches |=(=match (has-winner-in-match match loser))) + (skim our-matches |=(=match (has-loser-in-match match loser))) + == + %: new-rating:elo + our-rating + (expected-score:elo our-rating opp-rating) + (scaling-factor:elo (lent our-matches)) + opp-rating + our-outcome + == + %- %~ put by + %- %~ put by + players + [loser new-loser-elo] + [winner new-winner-elo] -- From a5844cabc6a2b045c5f24a3a2360a131020bd6cf Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 6 Apr 2024 18:20:33 +0100 Subject: [PATCH 07/20] wip: saloon --- src/lib/elo.hoon | 70 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib/telos.hoon | 2 +- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/lib/elo.hoon b/src/lib/elo.hoon index cfd2b35..8d41e52 100644 --- a/src/lib/elo.hoon +++ b/src/lib/elo.hoon @@ -1,4 +1,74 @@ /- *telos +=> +|% +:: +:: helper core +:: adapted from /lib/saloon +:: by ~lagrev-nocfep and ~mopfel-winrux +:: +++ neg |=(x=@rd (sub:rd .~0 x)) +:: accounted for +++ abs + |= x=@rd ^- @rd + ?: (^sig x) + x + (neg x) +:: +++ exp + |= x=@rd ^- @rd + =/ p .~1 + =/ po .~-1 + =/ i .~1 + |- ^- @rd + ?: (lth:rd (abs (sub:rd po p)) .~1e-5) + p + $(i (add:rd i .~1), p (add:rd p (div:rd (pow-n x i) (factorial i))), po p) +:: +++ factorial + |= x=@rd ^- @rd + =/ t=@rd .~1 + ?: (isclose x .~0) + t + |- ^- @rd + ?: (isclose x .~1) + t + $(x (sub:rd x .~1), t (mul:rd t x)) +:: +++ isclose + |= [p=@rd r=@rd] + (lth:rd (abs (sub:rd p r)) .~1e-5) +:: +++ log + |= z=@rd ^- @rd + =/ p .~0 + =/ po .~-1 + =/ i .~0 + |- ^- @rd + ?: (lth:rd (abs (sub:rd po p)) .~1e-5) + (mul:rd (div:rd (mul:rd .~2 (sub:rd z .~1)) (add:rd z .~1)) p) + =/ term1 (div:rd .~1 (add:rd .~1 (mul:rd .~2 i))) + =/ term2 (mul:rd (sub:rd z .~1) (sub:rd z .~1)) + =/ term3 (mul:rd (add:rd z .~1) (add:rd z .~1)) + =/ term (mul:rd term1 (pow-n (div:rd term2 term3) i)) + $(i (add:rd i .~1), p (add:rd p term), po p) +:: +++ rd + |% + ++ pow + |= [x=@rd n=@rd] ^- @rd + (exp (mul:rd n (log x))) + -- +:: +++ pow-n + |= [x=@rd n=@rd] ^- @rd + ?: =(n .~0) .~1 + =/ p x + |- ^- @rd + ?: (lth:rd n .~2) + p + $(n (sub:rd n .~1), p (mul:rd p x)) +-- +:: |% ++ round |= rd=@rd diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 717e9bb..483b639 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -267,7 +267,7 @@ our-outcome == %- %~ put by - %- %~ put by + %- %~ put by players [loser new-loser-elo] [winner new-winner-elo] From b1513b83ca23c67db076d8e8bf8b1452b6fd8bfb Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 6 Apr 2024 18:44:16 +0100 Subject: [PATCH 08/20] Integrate draft elo ratings --- src/app/telos.hoon | 2 +- src/lib/elo.hoon | 153 +++++++++++++++++++++++---------------------- src/lib/telos.hoon | 27 ++++---- 3 files changed, 92 insertions(+), 90 deletions(-) diff --git a/src/app/telos.hoon b/src/app/telos.hoon index 57ff14f..903ea13 100644 --- a/src/app/telos.hoon +++ b/src/app/telos.hoon @@ -606,7 +606,7 @@ == :: =/ new-ratings - (update-ratings (~(got by ratings) game) winner loser draw) + (update-elo-ratings (~(got by ratings) game) (~(got by archive) game) winner loser draw) :: =/ winner-new-data (~(got by new-ratings) winner) diff --git a/src/lib/elo.hoon b/src/lib/elo.hoon index 8d41e52..af6879d 100644 --- a/src/lib/elo.hoon +++ b/src/lib/elo.hoon @@ -1,79 +1,10 @@ /- *telos -=> -|% -:: -:: helper core -:: adapted from /lib/saloon -:: by ~lagrev-nocfep and ~mopfel-winrux -:: -++ neg |=(x=@rd (sub:rd .~0 x)) -:: accounted for -++ abs - |= x=@rd ^- @rd - ?: (^sig x) - x - (neg x) -:: -++ exp - |= x=@rd ^- @rd - =/ p .~1 - =/ po .~-1 - =/ i .~1 - |- ^- @rd - ?: (lth:rd (abs (sub:rd po p)) .~1e-5) - p - $(i (add:rd i .~1), p (add:rd p (div:rd (pow-n x i) (factorial i))), po p) -:: -++ factorial - |= x=@rd ^- @rd - =/ t=@rd .~1 - ?: (isclose x .~0) - t - |- ^- @rd - ?: (isclose x .~1) - t - $(x (sub:rd x .~1), t (mul:rd t x)) -:: -++ isclose - |= [p=@rd r=@rd] - (lth:rd (abs (sub:rd p r)) .~1e-5) -:: -++ log - |= z=@rd ^- @rd - =/ p .~0 - =/ po .~-1 - =/ i .~0 - |- ^- @rd - ?: (lth:rd (abs (sub:rd po p)) .~1e-5) - (mul:rd (div:rd (mul:rd .~2 (sub:rd z .~1)) (add:rd z .~1)) p) - =/ term1 (div:rd .~1 (add:rd .~1 (mul:rd .~2 i))) - =/ term2 (mul:rd (sub:rd z .~1) (sub:rd z .~1)) - =/ term3 (mul:rd (add:rd z .~1) (add:rd z .~1)) - =/ term (mul:rd term1 (pow-n (div:rd term2 term3) i)) - $(i (add:rd i .~1), p (add:rd p term), po p) -:: -++ rd - |% - ++ pow - |= [x=@rd n=@rd] ^- @rd - (exp (mul:rd n (log x))) - -- -:: -++ pow-n - |= [x=@rd n=@rd] ^- @rd - ?: =(n .~0) .~1 - =/ p x - |- ^- @rd - ?: (lth:rd n .~2) - p - $(n (sub:rd n .~1), p (mul:rd p x)) --- -:: +=< |% ++ round - |= rd=@rd + |= num=@rd ^- @ud - (abs:si (need (toi:rd rd))) + (abs:si (need (toi:rd num))) :: :: define expected score for a player in this match :: Ea = expected score for player A @@ -86,15 +17,14 @@ %+ div:rd .~1 %+ add:rd - ~.1 - :: XX need our own pow:rd - %+ pow:rd + .~1 + %+ pow-rd .~2 %+ div:rd %+ sub:rd (sun:rd opp) (sun:rd our) - ~.125 + .~125 :: :: calculate K :: K = 16 over 100 games played @@ -161,3 +91,74 @@ our-actual our-ex -- +:: +|% +:: +:: helper core +:: adapted from /lib/saloon +:: by ~lagrev-nocfep and ~mopfel-winrux +:: +++ sgn + |= x=@rd ^- ? + =(0 (rsh [0 31] x)) +:: +++ neg + |=(x=@rd (sub:rd .~0 x)) +:: +++ abs + |= x=@rd ^- @rd + ?: (sgn x) + x + (neg x) +:: +++ exp + |= x=@rd ^- @rd + =/ p .~1 + =/ po .~-1 + =/ i .~1 + |- ^- @rd + ?: (lth:rd (abs (sub:rd po p)) .~1e-5) + p + $(i (add:rd i .~1), p (add:rd p (div:rd (pow-n x i) (factorial i))), po p) +:: +++ factorial + |= x=@rd ^- @rd + =/ t=@rd .~1 + ?: (isclose x .~0) + t + |- ^- @rd + ?: (isclose x .~1) + t + $(x (sub:rd x .~1), t (mul:rd t x)) +:: +++ isclose + |= [p=@rd r=@rd] + (lth:rd (abs (sub:rd p r)) .~1e-5) +:: +++ log + |= z=@rd ^- @rd + =/ p .~0 + =/ po .~-1 + =/ i .~0 + |- ^- @rd + ?: (lth:rd (abs (sub:rd po p)) .~1e-5) + (mul:rd (div:rd (mul:rd .~2 (sub:rd z .~1)) (add:rd z .~1)) p) + =/ term1 (div:rd .~1 (add:rd .~1 (mul:rd .~2 i))) + =/ term2 (mul:rd (sub:rd z .~1) (sub:rd z .~1)) + =/ term3 (mul:rd (add:rd z .~1) (add:rd z .~1)) + =/ term (mul:rd term1 (pow-n (div:rd term2 term3) i)) + $(i (add:rd i .~1), p (add:rd p term), po p) +:: +++ pow-rd + |= [x=@rd n=@rd] ^- @rd + (exp (mul:rd n (log x))) +:: +++ pow-n + |= [x=@rd n=@rd] ^- @rd + ?: =(n .~0) .~1 + =/ p x + |- ^- @rd + ?: (lth:rd n .~2) + p + $(n (sub:rd n .~1), p (mul:rd p x)) +-- diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 483b639..0ebf4e6 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -114,8 +114,9 @@ player-ratings %= $ matches (tail matches) - player-ratings %: update-ratings + player-ratings %: update-elo-ratings player-ratings + matches winner:(head matches) loser:(head matches) draw:(head matches) @@ -208,9 +209,9 @@ ^+ players =/ new-winner-elo=rating =/ our-rating - (~(gut by ratings) winner 1.500) + (~(gut by players) winner 1.500) =/ opp-rating - (~(gut by ratings) loser 1.500) + (~(gut by players) loser 1.500) =/ our-matches (skim matches |=(=match (has-player-in-match match winner))) =/ our-outcome @@ -219,17 +220,17 @@ %win %draw :: - ?: (lth our-matches 10) + ?: (lth (lent our-matches) 10) %: new-performance-rating:elo :: XX sum up opps' ratings from previous games :: would need to know what the opponents' :: ratings were at the time of the match. :: could change id.match to @da and scry :: for the rating at that case. - (~(gut by ratings) loser 1.500) + (~(gut by players) loser 1.500) (lent our-matches) - (skim our-matches |=(=match (has-winner-in-match match winner))) - (skim our-matches |=(=match (has-loser-in-match match winner))) + (lent (skim our-matches |=(=match (has-winner-in-match match winner)))) + (lent (skim our-matches |=(=match (has-loser-in-match match winner)))) == %: new-rating:elo our-rating @@ -240,9 +241,9 @@ == =/ new-loser-elo=rating =/ our-rating - (~(gut by ratings) loser 1.500) + (~(gut by players) loser 1.500) =/ opp-rating - (~(gut by ratings) winner 1.500) + (~(gut by players) winner 1.500) =/ our-matches (skim matches |=(=match (has-player-in-match match loser))) =/ our-outcome @@ -251,13 +252,13 @@ %loss %draw :: - ?: (lth our-matches 10) + ?: (lth (lent our-matches) 10) %: new-performance-rating:elo :: XX sum up opps' ratings from previous games - (~(gut by ratings) loser 1.500) + (~(gut by players) loser 1.500) (lent our-matches) - (skim our-matches |=(=match (has-winner-in-match match loser))) - (skim our-matches |=(=match (has-loser-in-match match loser))) + (lent (skim our-matches |=(=match (has-winner-in-match match loser)))) + (lent (skim our-matches |=(=match (has-loser-in-match match loser)))) == %: new-rating:elo our-rating From b62cf9132d0fe7020596755e2737e54b0d4d7e7b Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 6 Apr 2024 18:45:05 +0100 Subject: [PATCH 09/20] Remove Glicko2 testing --- .gitignore | 2 - TESTING.md | 76 --- testing/glicko2js/.travis.yml | 3 - testing/glicko2js/LICENSE.md | 21 - testing/glicko2js/Makefile | 19 - testing/glicko2js/README.md | 156 ------ testing/glicko2js/READMEnpm.md | 117 ----- testing/glicko2js/bower.json | 26 - testing/glicko2js/example/index.html | 90 ---- testing/glicko2js/glicko2.js | 587 ----------------------- testing/glicko2js/package.json | 23 - testing/glicko2js/test/glicko2.js | 230 --------- testing/glicko2js/yarn.lock | 683 --------------------------- testing/pyglicko2/glicko2.py | 244 ---------- testing/pyglicko2/glicko2_tests.py | 59 --- 15 files changed, 2336 deletions(-) delete mode 100644 .gitignore delete mode 100644 TESTING.md delete mode 100644 testing/glicko2js/.travis.yml delete mode 100644 testing/glicko2js/LICENSE.md delete mode 100644 testing/glicko2js/Makefile delete mode 100644 testing/glicko2js/README.md delete mode 100644 testing/glicko2js/READMEnpm.md delete mode 100644 testing/glicko2js/bower.json delete mode 100644 testing/glicko2js/example/index.html delete mode 100644 testing/glicko2js/glicko2.js delete mode 100644 testing/glicko2js/package.json delete mode 100644 testing/glicko2js/test/glicko2.js delete mode 100644 testing/glicko2js/yarn.lock delete mode 100644 testing/pyglicko2/glicko2.py delete mode 100644 testing/pyglicko2/glicko2_tests.py diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 05d2208..0000000 --- a/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -__pycache__ -test_results.txt diff --git a/TESTING.md b/TESTING.md deleted file mode 100644 index 8d733e5..0000000 --- a/TESTING.md +++ /dev/null @@ -1,76 +0,0 @@ -# JS and Python tests - -## Initial test (player RD: 200) - -[Original Glicko paper](http://www.glicko.net/glicko/glicko.pdf) -[Example of the Glicko-2 system](http://www.glicko.net/glicko/glicko2.pdf) - -These initial tests demonstrated that the JS version was a correct implementation of -Glicko-2, up-to-date with the system's Feb. 2022 update. The Python version has been -amended to agree with the JS version, in lines 116 to 187. - -### Glickman’s paper -#### Initial ranks and RDs -* Player = rating 1500, RD 200 -* Opp1 = rating 1400, RD 30 -* Opp2 = rating 1550, RD 100 -* Opp3 = rating 1700, RD 300 - -Outcome of games: 1, 0, and 0. - -#### Player’s ranking after games -* Player = rating 1464.06, RD 151.52 - -### JavaScript - -#### Inital rankings -* Player: 1500.000000000000000000 (rd: 200.000000000000000000) (vol: 0.059999999999999998) -* Opp1: 1400.000000000000000000 (rd: 30.000000000000003553) (vol: 0.059999999999999998) -* Opp2: 1550.000000000000000000 (rd: 100.000000000000000000) (vol: 0.059999999999999998) -* Opp3: 1700.000000000000000000 (rd: 300.000000000000000000) (vol: 0.059999999999999998) - -#### Rankings after games -* Player: 1464.050670539301336248 (rd: 151.516524123857266204) (vol: 0.059995984286488495) -* Opp1: 1398.143558233733756424 (rd: 31.670215281150621678) (vol: 0.059999123728885308) -* Opp2: 1570.394740240853934665 (rd: 97.709168522003068347) (vol: 0.059999419471993810) -* Opp3: 1784.421790132087380698 (rd: 251.565564532247350371) (vol: 0.059999011763670944) - -### Python - -#### Initial rankings -* Player: 1500.000000000000000000 (rd: 200.000000000000000000) - -#### Rankings after games -* Player: 1464.050670539301336248 (rd: 151.516524123857266204) (vol: 0.059995984286488495) - -*** - -## Amended test (player RD: 350) - -The JS and Python versions have since been updated so that the player's initial RD is -350 rather than 200. 350 is the system default in %telos, since Glickman assigns this RD -to unrated players. - -### JavaScript -#### Initial Rankings -* Player: 1500.000000000000000000 (rd: 350.000000000000000000) (vol: 0.059999999999999998) -* Opp1: 1400.000000000000000000 (rd: 30.000000000000003553) (vol: 0.059999999999999998) -* Opp2: 1550.000000000000000000 (rd: 100.000000000000000000) (vol: 0.059999999999999998) -* Opp3: 1700.000000000000000000 (rd: 300.000000000000000000) (vol: 0.059999999999999998) - -#### Rankings after games -* Player: 1441.532789209275733811 (rd: 193.228325244026990504) (vol: 0.059997781896653730) -* Opp1: 1398.432771279122562191 (rd: 31.701978358302014271) (vol: 0.059999532672676020) -* Opp2: 1566.967754234200356223 (rd: 98.725018110245727598) (vol: 0.059999704551092846) -* Opp3: 1785.184258294325218230 (rd: 264.385389300972235560) (vol: 0.059999350112324330) - -### Python -#### Initial rankings -* Old Rating: 1500.000000000000000000 -* Old Rating Deviation: 350.000000000000000000 -* Old Volatility: 0.059999999999999998 - -#### Rankings after games -* New Rating: 1441.532789209275733811 -* New Rating Deviation: 193.228325244026990504 -* New Volatility: 0.059997781896653730 \ No newline at end of file diff --git a/testing/glicko2js/.travis.yml b/testing/glicko2js/.travis.yml deleted file mode 100644 index c7b016c..0000000 --- a/testing/glicko2js/.travis.yml +++ /dev/null @@ -1,3 +0,0 @@ -language: node_js -node_js: - - 12 diff --git a/testing/glicko2js/LICENSE.md b/testing/glicko2js/LICENSE.md deleted file mode 100644 index 242132d..0000000 --- a/testing/glicko2js/LICENSE.md +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/testing/glicko2js/Makefile b/testing/glicko2js/Makefile deleted file mode 100644 index b90b80d..0000000 --- a/testing/glicko2js/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -DIRNPM=toNPM - -test: - npm test - -build: - rm -rf $(DIRNPM) - mkdir $(DIRNPM) - cp glicko2.js $(DIRNPM) - cp package.json $(DIRNPM) - cp READMEnpm.md $(DIRNPM)/README.md - cp -R test $(DIRNPM) - -publish: build - cd $(DIRNPM) - npm publish . - cd .. - -.PHONY: test diff --git a/testing/glicko2js/README.md b/testing/glicko2js/README.md deleted file mode 100644 index ad3ec99..0000000 --- a/testing/glicko2js/README.md +++ /dev/null @@ -1,156 +0,0 @@ -# Glicko 2 javascript implementation - -[![Build Status](https://travis-ci.org/mmai/glicko2js.png)](https://travis-ci.org/mmai/glicko2js) - - -The Glicko-2 rating system is a method for assessing a player's strength in games of skill, such as chess and go. -The algorithm is explained by its author, Mark E. Glickman, on http://glicko.net/glicko.html. - -Each player begins with a rating, a rating deviation (accuracy of the rating) and a volatility (speed of rating evolution). These values will evolve according to the outcomes of matches with other players. - -## Usage - -In the browser, you need to include the glicko2.js file : - -``` html - -``` - -In node.js, just require the module : - -``` javascript -var glicko2 = require('glicko2'); -``` - -First we initiate a ranking manager and create players with initial ratings, rating deviations and volatilities. - -``` javascript -var settings = { - // tau : "Reasonable choices are between 0.3 and 1.2, though the system should - // be tested to decide which value results in greatest predictive accuracy." - tau : 0.5, - // rating : default rating - rating : 1500, - //rd : Default rating deviation - // small number = good confidence on the rating accuracy - rd : 200, - //vol : Default volatility (expected fluctation on the player rating) - vol : 0.06 -}; -var ranking = new glicko2.Glicko2(settings); - -// Create players -var Ryan = ranking.makePlayer(); -var Bob = ranking.makePlayer(1400, 30, 0.06); -var John = ranking.makePlayer(1550, 100, 0.06); -var Mary = ranking.makePlayer(1700, 300, 0.06); -``` - -We can then enter results, calculate the new ratings... - -``` javascript -var matches = []; -matches.push([Ryan, Bob, 1]); //Ryan won over Bob -matches.push([Ryan, John, 0]); //Ryan lost against John -matches.push([Ryan, Mary, 0.5]); //A draw between Ryan and Mary -ranking.updateRatings(matches); -``` - -... and get these new ratings. - -``` javascript -console.log("Ryan new rating: " + Ryan.getRating()); -console.log("Ryan new rating deviation: " + Ryan.getRd()); -console.log("Ryan new volatility: " + Ryan.getVol()); -``` - -Get players list - -``` javascript -var players = ranking.getPlayers(); -``` - -## When to update rankings - -You should not update the ranking after each match. -The typical use of glicko is to calculate the ratings after each tournament (ie collection of matches in a period of time). -A player rating will evolve after a tournament has finished, but not during the tournament. - -Here is what says Mark E. Glickman about the number of matches in a tournament or rating period (cf. http://www.glicko.net/glicko/glicko2.pdf ) : -> The Glicko-2 system works best when the number of games in a rating period is moderate to large, say an average of at least 10-15 games per player in a rating period. - -### Support for multiple competitors matches (experimental) - -**Note: the glicko2 algorithm was not designed for multiple competitors matches, this is a naive workaround whose results should be taken whith caution.** - -You can enter results from games where multiple competitors play against each other at the same time (ie swimming, racing...). - -First make "Race" objects by entering the results in an array of "positions", where each position is an array of players at this position : - -```javascript -var race1 = glicko.makeRace( - [ - [Ryan], //Ryan won the race - [Bob, John], //Bob and John ended ex aequo at the 2nd position - [Mary] // Mary 4th position - ] -); - -var race2 = glicko.makeRace( - [ - [Mary], // won - [Bob], // 2nd - [John], // 3rd - [Ryan], // 4th - ] -); - -``` - -Then convert the races to the equivalent matches : -```javascript - -var matches1 = race1.getMatches(); -var matches2 = race2.getMatches(); - -var allMatches = matches1.concat(matches2) - -ranking.updateRatings(allMatches); -``` - -You can also update ratings for one race without converting to matches : - -```javascript -ranking.updateRatings(race1); -``` - -## Installation - -### In the browser - -You just need to include the glicko2.js script. -See index.html in the example folder. - -``` html - -``` - -### With [bower](http://bower.io/) - -``` shell -$ bower install glicko2 -``` -``` html - -``` - -### As a node.js module - -glicko2.js is available as a npm module. - -Install with: - -``` shell -$ npm install glicko2 -``` - diff --git a/testing/glicko2js/READMEnpm.md b/testing/glicko2js/READMEnpm.md deleted file mode 100644 index ff91e61..0000000 --- a/testing/glicko2js/READMEnpm.md +++ /dev/null @@ -1,117 +0,0 @@ -# Glicko 2 javascript implementation - -[![Build Status](https://travis-ci.org/mmai/glicko2js.png)](https://travis-ci.org/mmai/glicko2js) - - -The Glicko-2 rating system is a method for assessing a player's strength in games of skill, such as chess and go. -The algorithm is explained by its author, Mark E. Glickman, on http://glicko.net/glicko.html. - -Each player begins with a rating, a rating deviation (accuracy of the rating) and a volatility (speed of rating evolution). These values will evolve according to the outcomes of matches with other players. - -## Usage - -First we initiate a ranking manager and create players with initial ratings, rating deviations and volatilities. - -``` javascript -var glicko2 = require('glicko2'); -var settings = { - // tau : "Reasonable choices are between 0.3 and 1.2, though the system should - // be tested to decide which value results in greatest predictive accuracy." - tau : 0.5, - // rating : default rating - rating : 1500, - //rd : Default rating deviation - // small number = good confidence on the rating accuracy - rd : 200, - //vol : Default volatility (expected fluctation on the player rating) - vol : 0.06 -}; -var ranking = new glicko2.Glicko2(settings); - -// Create players -var Ryan = ranking.makePlayer(); -var Bob = ranking.makePlayer(1400, 30, 0.06); -var John = ranking.makePlayer(1550, 100, 0.06); -var Mary = ranking.makePlayer(1700, 300, 0.06); -``` - -We can then enter results, calculate the new ratings... - -``` javascript -var matches = []; -matches.push([Ryan, Bob, 1]); //Ryan won over Bob -matches.push([Ryan, John, 0]); //Ryan lost against John -matches.push([Ryan, Mary, 0.5]); //A draw between Ryan and Mary -ranking.updateRatings(matches); -``` - -... and get these new ratings. - -``` javascript -console.log("Ryan new rating: " + Ryan.getRating()); -console.log("Ryan new rating deviation: " + Ryan.getRd()); -console.log("Ryan new volatility: " + Ryan.getVol()); -``` - -Get players list - -``` javascript -var players = ranking.getPlayers(); -``` - -## When to update rankings - -You should not update the ranking after each match. -The typical use of glicko is to calculate the ratings after each tournament (ie collection of matches in a period of time). -A player rating will evolve after a tournament has finished, but not during the tournament. - -You can see a client side javascript example using tournaments here : https://github.com/mmai/glicko2js/blob/master/example/index.html - -Here is what says Mark E. Glickman about the number of matches in a tournament or rating period (cf. http://www.glicko.net/glicko/glicko2.pdf ) : -> The Glicko-2 system works best when the number of games in a rating period is moderate to large, say an average of at least 10-15 games per player in a rating period. - -### Support for multiple competitors matches (experimental) - -**Note: the glicko2 algorithm was not designed for multiple competitors matches, this is a naive workaround whose results should be taken whith caution.** - -You can enter results from games where multiple competitors play against each other at the same time (ie swimming, racing...). - -First make "Race" objects by entering the results in an array of "positions", where each position is an array of players at this position : - -```javascript -var race1 = glicko.makeRace( - [ - [Ryan], //Ryan won the race - [Bob, John], //Bob and John ended ex aequo at the 2nd position - [Mary] // Mary 4th position - ] -); - -var race2 = glicko.makeRace( - [ - [Mary], // won - [Bob], // 2nd - [John], // 3rd - [Ryan], // 4th - ] -); - -``` - -Then convert the races to the equivalent matches : -```javascript - -var matches1 = race1.getMatches(); -var matches2 = race2.getMatches(); - -var allMatches = matches1.concat(matches2) - -ranking.updateRatings(allMatches); -``` - -You can also update ratings for one race without converting to matches : - -```javascript -ranking.updateRatings(race1); -``` - diff --git a/testing/glicko2js/bower.json b/testing/glicko2js/bower.json deleted file mode 100644 index f047663..0000000 --- a/testing/glicko2js/bower.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "glicko2", - "version": "0.8.7", - "homepage": "https://github.com/mmai/glicko2js", - "authors": [ - "Henri Bourcereau " - ], - "description": "glicko2 ranking system", - "main": "./glicko2.js", - "keywords": [ - "glicko", - "utilities", - "ranking" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "example", - "node_modules", - "test", - "toNPM", - "Makefile", - "package.json", - "READMEnpm.md" - ] -} diff --git a/testing/glicko2js/example/index.html b/testing/glicko2js/example/index.html deleted file mode 100644 index 134abf7..0000000 --- a/testing/glicko2js/example/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - -

Initial rankings

- - -

Rankings after tournament 1

- - - - - - - - diff --git a/testing/glicko2js/glicko2.js b/testing/glicko2js/glicko2.js deleted file mode 100644 index e43a33b..0000000 --- a/testing/glicko2js/glicko2.js +++ /dev/null @@ -1,587 +0,0 @@ -// everything is in one function -(function(exports){ - // set scalingFactor to 173.7178 - var scalingFactor = 173.7178; - // create Race function - function Race(results){ - this.matches = this.computeMatches(results); - } - // add getMatches to Race - Race.prototype.getMatches = function(){ - return this.matches; - }; - // add computeMatches to Race - Race.prototype.computeMatches = function(results){ - var players = []; - var position = 0; - - results.forEach(function (rank) { - position += 1; - rank.forEach(function (player) { - players.push({"player": player, "position": position}); - }) - }) - - function computeMatches(players){ - if (players.length === 0) return []; - - var player1 = players.shift() - var player1_results = players.map(function(player2){ - return [player1.player, player2.player, (player1.position < player2.position) ? 1 : 0.5]; - }); - - return player1_results.concat(computeMatches(players)); - } - - return computeMatches(players) - } - // create Player function - function Player(rating, rd, vol, tau, default_rating, volatility_algorithm, id) { - // Step 1 - this._tau = tau; - this.defaultRating = default_rating; - this.volatility_algorithm = volatility_algorithm; - - this.setRating(rating); - this.setRd(rd); - this.setVol(vol); - - this.id = id - this.adv_ranks = []; - this.adv_rds = []; - this.outcomes = []; - } - // add getRating to Player - Player.prototype.getRating = function (){ - // (mul rating.player (add scalingFactor default-rating.player)) - return this.__rating * scalingFactor + this.defaultRating; - }; - // add setRating to Player - Player.prototype.setRating = function (rating){ - // Step 2.1 - this.__rating = (rating - this.defaultRating) / scalingFactor; - }; - // addd getRd to Player - Player.prototype.getRd = function(){ - // (mul rd.player scaling-factor) - return this.__rd * scalingFactor; - }; - // add setRd to Player - Player.prototype.setRd = function(rd){ - // Step 2.2 - this.__rd = rd / scalingFactor; - }; - // add getVol to Player - Player.prototype.getVol = function(){ - return this.__vol; - }; - // add setVol to Player - Player.prototype.setVol = function(vol){ - this.__vol = vol; - }; - // add addResult to Player - Player.prototype.addResult = function(opponent, outcome){ - // add opponent's rating to adv_ranks array - this.adv_ranks.push(opponent.__rating); - // add opponent's RD to adv_rds array - // (i think adv is "adversary"?) - this.adv_rds.push(opponent.__rd); - // add outcome to outcomes array - this.outcomes.push(outcome); - }; - // adds update_rank to Player - // Calculates the new rating and rating deviation of the player. - // Follows the steps of the algorithm described at http://www.glicko.net/glicko/glicko2.pdf - Player.prototype.update_rank = function(){ - // if player has not competed in this series of matches... - if (!this.hasPlayed()){ - // Applies only the Step 6 of the algorithm - this._preRatingRD(); - return; - } - - //Step 1 : done by Player initialization - //Step 2 : done by setRating and setRd - - //Step 3 - // set v to this Player's variance - var v = this._variance(); - - //Step 4 - // set delta to this Player's delta - var delta = this._delta(v); - - //Step 5 - // set this Player's volatility - this.__vol = this.volatility_algorithm(v, delta); - - //Step 6 - // init this Player's pre-rating period RD - this._preRatingRD(); - - //Step 7 - // set this Player's new RD - // (div 1 (sqrt (add (div 1 (pow RD 2)) (div 1 v)))) - this.__rd = 1 / Math.sqrt((1 / Math.pow(this.__rd, 2)) + (1 / v)); - - var tempSum = 0; - for (var i=0,len = this.adv_ranks.length;i< len;i++){ - // $(tempSum (add tempSum (mul _g(this.adv_rds[i] (sub this.outcomes[i] _E(this.adv_ranks[i] this.adv_rds[i])))))) - tempSum += this._g(this.adv_rds[i]) * (this.outcomes[i] - this._E(this.adv_ranks[i], this.adv_rds[i])); - } - // $(this.__rating (add this.__rating (mul (pow this.__rd 2) tempSum))) - this.__rating += Math.pow(this.__rd, 2) * tempSum; - - //Step 8 : done by getRating and getRd - }; - // add hasPlayed to Player - Player.prototype.hasPlayed = function(){ - // determine whether or not player has played in this rating period - return this.outcomes.length > 0; - }; - - // Calculates and updates the player's rating deviation for the beginning of a rating period. - // preRatingRD() -> None - Player.prototype._preRatingRD = function(){ - // (sqrt (add (pow RD 2) (pow vol 2))) - this.__rd = Math.sqrt(Math.pow(this.__rd, 2) + Math.pow(this.__vol, 2)); - }; - - // Calculation of the estimated variance of the player's rating based on game outcomes - Player.prototype._variance = function (){ - var tempSum = 0; - for (var i = 0, len = this.adv_ranks.length;i 0 ){ - result = upper; - } else { - x1 = 0; - x2 = x1; - y2 = y1; - x1 = x1 - 1; - y1 = equation(phi, v, x1, a, tau, delta); - while (y1 < 0){ - x2 = x1; - y2 = y1; - x1 = x1 - 1; - y1 = equation(phi, v, x1, a, tau, delta); - } - for (var i = 0; i<21; i++){ - x3 = y1 * (x1 - x2) / (y2 - y1) + x1; - y3 = equation(phi, v, x3, a, tau, delta); - if (y3 > 0 ){ - x1 = x3; - y1 = y3; - } else { - x2 = x3; - y2 = y3; - } - } - if (Math.exp((y1 * (x1 - x2) / (y2 - y1) + x1) / 2) > upper ){ - result = upper; - } else { - result = Math.exp((y1 * (x1 - x2) / (y2 - y1) + x1) / 2); - } - } - return result; - - function new_sigma(sigma , phi , v , delta , tau ) { - var a = Math.log(Math.pow(sigma, 2)); - var x = a; - var old_x = 0; - while (x != old_x){ - old_x = x; - var d = Math.pow(phi, 2) + v + Math.exp(old_x); - var h1 = -(old_x - a) / Math.pow(tau, 2) - 0.5 * Math.exp(old_x) / d + 0.5 * Math.exp(old_x) * Math.pow((delta / d), 2); - var h2 = -1 / Math.pow(tau, 2) - 0.5 * Math.exp(old_x) * (Math.pow(phi, 2) + v) / Math.pow(d, 2) + 0.5 * Math.pow(delta, 2) * Math.exp(old_x) * (Math.pow(phi, 2) + v - Math.exp(old_x)) / Math.pow(d, 3); - x = old_x - h1 / h2; - } - return Math.exp(x / 2); - } - - function equation(phi , v , x , a , tau , delta) { - var d = Math.pow(phi, 2) + v + Math.exp(x); - return -(x - a) / Math.pow(tau, 2) - 0.5 * Math.exp(x) / d + 0.5 * Math.exp(x) * Math.pow((delta / d), 2); - } - - function new_sigma_bisection(sigma , phi , v , delta , tau ) { - var a, x1, x2, x3; - a = Math.log(Math.pow(sigma, 2)); - if (equation(phi, v, 0, a, tau, delta) < 0 ){ - x1 = -1; - while (equation(phi, v, x1, a, tau, delta) < 0){ - x1 = x1 - 1; - } - x2 = x1 + 1; - } else { - x2 = 1; - while (equation(phi, v, x2, a, tau, delta) > 0){ - x2 = x2 + 1; - } - x1 = x2 - 1; - } - - for (var i = 0; i < 27; i++) { - x3 = (x1 + x2) / 2; - if (equation(phi, v, x3, a, tau, delta) > 0 ){ - x1 = x3; - } else { - x2 = x3; - } - } - return Math.exp((x1 + x2)/ 4); - } - - function Dequation(phi , v , x , tau , delta) { - d = Math.pow(phi, 2) + v + Math.exp(x); - return -1 / Math.pow(tau, 2) - 0.5 * Math.exp(x) / d + 0.5 * Math.exp(x) * (Math.exp(x) + Math.pow(delta, 2)) / Math.pow(d, 2) - Math.pow(Math.exp(x), 2) * Math.pow(delta, 2) / Math.pow(d, 3); - } - - function find_upper_falsep(phi , v , delta , tau) { - var x1, x2, x3, y1, y2, y3; - y1 = Dequation(phi, v, 0, tau, delta); - if (y1 < 0 ){ - return 1; - } else { - x1 = 0; - x2 = x1; - y2 = y1; - x1 = x1 - 1; - y1 = Dequation(phi, v, x1, tau, delta); - while (y1 > 0){ - x2 = x1; - y2 = y1; - x1 = x1 - 1; - y1 = Dequation(phi, v, x1, tau, delta); - } - for (var i = 0; i < 21 ; i++){ - x3 = y1 * (x1 - x2) / (y2 - y1) + x1; - y3 = Dequation(phi, v, x3, tau, delta); - if (y3 > 0 ){ - x1 = x3; - y1 = y3; - } else { - x2 = x3; - y2 = y3; - } - } - return Math.exp((y1 * (x1 - x2) / (y2 - y1) + x1) / 2); - } - } - }, - newprocedure: function(v, delta){ - //Step 5.1 - // A = (log (pow vol 2)) - var A = Math.log(Math.pow(this.__vol, 2)); - // define f(x) 'function' - var f = this._makef(delta, v, A); - // ε = 0.000001 - var epsilon = 0.0000001; - - //Step 5.2 - // we've set A already - // init var B and k - var B, k; - // if ∆2 > φ2 + v - // (gth (pow delta 2) (add (pow phi 2) v)) - if (Math.pow(delta, 2) > Math.pow(this.__rd, 2) + v){ - // set B = ln(∆2 − φ2 − v) - // (log ;(sub (pow delta 2) (pow phi 2) v)) - B = Math.log(Math.pow(delta, 2) - Math.pow(this.__rd, 2) - v); - } else { - // If ∆2 ≤ φ2 + v, then perform the following iteration: - // (lte (pow delta 2) (add (pow phi 2) v)) - // let k = 1 - k = 1; - // If f(a−kτ) < 0,then - // (lth (f (sub a (mul k tau))) 0) - while (f(A - k * this._tau) < 0){ - // Set k ← k + 1 - k = k + 1; - } - // set B = a − kτ - // (sub a (mul k tau)) - B = A - k * this._tau; - } - - //Step 5.3 - // Let fA = f(A) - var fA = f(A); - // Let fB = f(B) - var fB = f(B); - - //Step 5.4 - // init var C and fC - var C, fC; - // absolute value: distance from 0 (always a positive number, @ud) - // While |B − A| > ε, carry out the following steps - while (Math.abs(B - A) > epsilon){ - // Let C = A + (A−B)fA/(fB −fA) - // (add A (mul (sub A B) (div fA (sub fB fA)))) - C = A + (A - B) * fA /(fB - fA ); - // Let fC =f(C) - fC = f(C); - // If fCfB ≤ 0 - // (lte (mul fC fB) 0) - if (fC * fB < 0){ - // set A ← B - A = B; - // set fA ← fB - fA = fB; - } else { - // otherwise, just set fA ← fA/2 - fA = fA / 2; - } - // set B ← C - B = C; - // fB ← fC - fB = fC; - } - //Step 5.5 - // Once |B − A| ≤ ε, set σ′ ← eA/2 - // e = euler's number ; ~2.718 - // .exp(x) is euler's number raised to the power of x - // (pow e x) - return Math.exp(A/2); - }, - newprocedure_mod: function(v, delta){ - //Step 5.1 - var A = Math.log(Math.pow(this.__vol, 2)); - var f = this._makef(delta, v, A); - var epsilon = 0.0000001; - - //Step 5.2 - var B, k; - //XXX mod - if (delta > Math.pow(this.__rd, 2) + v){ - //XXX mod - B = Math.log(delta - Math.pow(this.__rd, 2) - v); - } else { - k = 1; - while (f(A - k * this._tau) < 0){ - k = k + 1; - } - B = A - k * this._tau; - } - - //Step 5.3 - var fA = f(A); - var fB = f(B); - - //Step 5.4 - var C, fC; - while (Math.abs(B - A) > epsilon){ - C = A + (A - B) * fA /(fB - fA ); - fC = f(C); - if (fC * fB < 0){ - A = B; - fA = fB; - } else { - fA = fA / 2; - } - B = C; - fB = fC; - } - //Step 5.5 - return Math.exp(A/2); - }, - oldprocedure_simple: function(v, delta){ - var i = 0; - var a = Math.log(Math.pow(this.__vol, 2)); - var tau = this._tau; - var x0 = a; - var x1 = 0; - var d,h1,h2; - - while (Math.abs(x0 - x1) > 0.00000001){ - // New iteration, so x(i) becomes x(i-1) - x0 = x1; - d = Math.pow(this.__rating, 2) + v + Math.exp(x0); - h1 = -(x0 - a) / Math.pow(tau, 2) - 0.5 * Math.exp(x0) / d + 0.5 * Math.exp(x0) * Math.pow(delta / d, 2); - h2 = -1 / Math.pow(tau, 2) - 0.5 * Math.exp(x0) * (Math.pow(this.__rating, 2) + v) / Math.pow(d, 2) + 0.5 * Math.pow(delta, 2) * Math.exp(x0) * (Math.pow(this.__rating, 2) + v - Math.exp(x0)) / Math.pow(d, 3); - x1 = x0 - (h1 / h2); - } - - return Math.exp(x1 / 2); - } - }; - //==== End of volatility algorithms - - exports.Glicko2 = Glicko2; - - })(typeof exports === 'undefined'? this['glicko2']={}: exports); diff --git a/testing/glicko2js/package.json b/testing/glicko2js/package.json deleted file mode 100644 index eb20a40..0000000 --- a/testing/glicko2js/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "glicko2", - "description": "glicko2 ranking system", - "version": "0.8.7", - "author": "Henri Bourcereau", - "keywords": [ - "glicko", - "utilities", - "ranking" - ], - "repository": { - "type": "git", - "url": "git://github.com/mmai/glicko2js.git" - }, - "main": "./glicko2.js", - "devDependencies": { - "mocha": "8.2.x", - "should": "13.2.x" - }, - "scripts": { - "test": "mocha --require should --reporter list" - } -} diff --git a/testing/glicko2js/test/glicko2.js b/testing/glicko2js/test/glicko2.js deleted file mode 100644 index 82f58e9..0000000 --- a/testing/glicko2js/test/glicko2.js +++ /dev/null @@ -1,230 +0,0 @@ -var glicko2 = require('../glicko2'); - -describe('Glicko2', function(){ - describe('makePlayer()', function(){ - it('should make a default player when passed no settings', function(){ - var glicko = new glicko2.Glicko2(); - var player = glicko.makePlayer(); - player.getRating().should.equal(1500); - player.getRd().should.equal(350); - player.getVol().should.equal(0.06); - }); - it('should support setting individual settings', function(){ - var glicko = new glicko2.Glicko2({ - rating: 1600 - }); - var player = glicko.makePlayer(); - player.getRating().should.equal(1600); - player.getRd().should.equal(350); - player.getVol().should.equal(0.06); - }); - it('should not be affected by newer instances of Glicko2', function(){ - var glicko = new glicko2.Glicko2({ - rating: 1400 - }); - var player = glicko.makePlayer(); - - var newerGlicko = new glicko2.Glicko2({ - rating: 1600 - }); - - player.getRating().should.equal(1400); - }); - }); - describe('getPlayers()', function(){ - it('should retrieve all players with ids', function(){ - var settings = { - tau : 0.5, - rpd : 604800, - rating : 1500, - rd : 200, - vol : 0.06 - }; - var glicko = new glicko2.Glicko2(settings); - var player = glicko.makePlayer(); - var pl1 = glicko.makePlayer(1400, 30, 0.06); - var pl3 = glicko.makePlayer(1550, 100, 0.06); - var players = glicko.getPlayers(); - players.length.should.equal(3); - players[1].id.should.equal(1); - players[1].getRating().should.equal(1400); - }); - }); - describe('updateRatings()', function(){ - it('should calculate new ratings', function(){ - // Following the example at: - // http://math.bu.edu/people/mg/glicko/glicko2.doc/example.html - // Pretend Ryan (of rating 1500 and rating deviation 350) plays players of ratings 1400, 1550 and 1700 - // and rating deviations 30, 100 and 300 respectively with outcomes 1, 0 and 0. - var settings = { - tau : 0.5, - rpd : 604800, - rating : 1500, - rd : 200, - vol : 0.06 - }; - var glicko = new glicko2.Glicko2(settings); - var Ryan = glicko.makePlayer(); - var Bob = glicko.makePlayer(1400, 30, 0.06); - var John = glicko.makePlayer(1550, 100, 0.06); - var Mary = glicko.makePlayer(1700, 300, 0.06); - - var matches = []; - matches.push([Ryan, Bob, 1]); //Ryan won over Bob - matches.push([Ryan, John, 0]); //Ryan lost against John - matches.push([Ryan, Mary, 0]); //Ryan lost against Mary - - /*Perfs testing - var players = [Bob, John, Mary]; - - var ind = 0; - while (ind++ < 50){ - players.push(glicko.makePlayer()); - } - - var nbpl = players.length; - var pl1, pl2; - for (var i=0; i<1000;i++){ - pl1 = players[Math.floor(Math.random() * nbpl)]; - pl2 = players[Math.floor(Math.random() * nbpl)]; - matches.push([pl1, pl2, Math.floor(Math.random() * 3) / 2]); - } - //End perfs - */ - - glicko.updateRatings(matches); - - (Math.abs(Ryan.getRating() - 1464) < 0.1).should.be.true; - (Math.abs(Ryan.getRd() - 151.52) < 0.01).should.be.true; - (Math.abs(Ryan.getVol() - 0.05999) < 0.00001).should.be.true; - }); - it('should allow to be called multiple times', function(){ - var settings = { - tau : 0.5, - rpd : 604800, - rating : 1500, - rd : 200, - vol : 0.06 - }; - var glicko = new glicko2.Glicko2(settings); - var Ryan = glicko.makePlayer(); - var Bob = glicko.makePlayer(1400, 30, 0.06); - var John = glicko.makePlayer(1550, 100, 0.06); - var Mary = glicko.makePlayer(1700, 300, 0.06); - - var matches = []; - matches.push([Ryan, Bob, 1]); //Ryan won over Bob - matches.push([Ryan, John, 0]); //Ryan lost against John - matches.push([Ryan, Mary, 0]); //Ryan lost against Mary - glicko.updateRatings(matches); - - - //We initiate a new ranking instance with the actual values of the first one - var glicko_new = new glicko2.Glicko2(settings); - var Ryan_new = glicko_new.makePlayer(Ryan.getRating(), Ryan.getRd(), Ryan.getVol()); - var Bob_new = glicko_new.makePlayer(Bob.getRating(), Bob.getRd(), Bob.getVol()); - var John_new = glicko_new.makePlayer(John.getRating(), John.getRd(), John.getVol()); - var Mary_new = glicko_new.makePlayer(Mary.getRating(), Mary.getRd(), Mary.getVol()); - - //Second tournament for the first ranking instance - matches = []; - matches.push([Ryan, Bob, 0]); - matches.push([Ryan, John, 1]); - matches.push([Mary, Bob, 1]); - glicko.updateRatings(matches); - //console.log('nb players: ' + glicko.getPlayers().length); - - //Fist tournament for the second ranking instance, with the same matches - var matches_new = []; - matches_new.push([Ryan_new, Bob_new, 0]); - matches_new.push([Ryan_new, John_new, 1]); - matches_new.push([Mary_new, Bob_new, 1]); - glicko_new.updateRatings(matches_new); - - //The ratings in both systems should be the same - (Math.abs(Ryan.getRating() - Ryan_new.getRating()) < 0.1).should.be.true; - (Math.abs(Ryan.getRd() - Ryan_new.getRd()) < 0.1).should.be.true; - (Math.abs(Ryan.getVol() - Ryan_new.getVol()) < 0.00001).should.be.true; - }); - it('should be able to update ratings when a player did not play', function(){ - var settings = { - tau : 0.5, - rpd : 604800, - rating : 1500, - rd : 200, - vol : 0.06 - }; - var glicko = new glicko2.Glicko2(settings); - var Ryan = glicko.makePlayer(); - var matches = []; - glicko.updateRatings(matches); - }); - it('should accept Race objects', function(){ - var settings = { - tau : 0.5, - rpd : 604800, - rating : 1500, - rd : 200, - vol : 0.06 - }; - var glicko = new glicko2.Glicko2(settings); - var Ryan = glicko.makePlayer(); - var Bob = glicko.makePlayer(1400, 30, 0.06); - var John = glicko.makePlayer(1550, 100, 0.06); - var Mary = glicko.makePlayer(1700, 300, 0.06); - - var race = glicko.makeRace( - [ - [Ryan], //Ryan won the race - [Bob, John], //Bob and John 2nd position ex-aequo - [Mary] // Mary 4th position - ] - ); - - glicko.updateRatings(race); - - (Math.abs(Ryan.getRating() - 1685.7) < 0.1).should.be.true; - (Math.abs(Ryan.getRd() - 151.52) < 0.01).should.be.true; - (Math.abs(Ryan.getVol() - 0.06000) < 0.00001).should.be.true; - }); - }); - }); - -describe("Race", function(){ - describe("getMatches", function(){ - it("Should convert a race to a list of matches", function(){ - var settings = { - tau : 0.5, - rpd : 604800, - rating : 1500, - rd : 200, - vol : 0.06 - }; - var glicko = new glicko2.Glicko2(settings); - var Ryan = glicko.makePlayer(); - var Bob = glicko.makePlayer(1400, 30, 0.06); - var John = glicko.makePlayer(1550, 100, 0.06); - var Mary = glicko.makePlayer(1700, 300, 0.06); - - var race = glicko.makeRace( - [ - [Ryan], //Ryan won the race - [Bob, John], //Bob and John 2nd position ex-aequo - [Mary] // Mary 4th position - ] - ); - - var matches = race.getMatches(); - matches.should.eql([ - [Ryan, Bob, 1], - [Ryan, John, 1], - [Ryan, Mary, 1], - [Bob, John, 0.5], - [Bob, Mary, 1], - [John, Mary, 1] - ]); - }) - }) - -}) - diff --git a/testing/glicko2js/yarn.lock b/testing/glicko2js/yarn.lock deleted file mode 100644 index b3a081c..0000000 --- a/testing/glicko2js/yarn.lock +++ /dev/null @@ -1,683 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ungap/promise-all-settled@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" - integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-styles@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" - integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== - dependencies: - color-convert "^2.0.1" - -anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -camelcase@^6.0.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== - -chalk@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -chokidar@3.4.3: - version "3.4.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" - integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.1.2" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -debug@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== - dependencies: - ms "2.1.2" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - -diff@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -escape-string-regexp@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -glob-parent@~5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -js-yaml@3.14.0: - version "3.14.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" - integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" - integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== - dependencies: - p-locate "^5.0.0" - -log-symbols@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" - integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== - dependencies: - chalk "^4.0.0" - -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -mocha@8.2.x: - version "8.2.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.2.1.tgz#f2fa68817ed0e53343d989df65ccd358bc3a4b39" - integrity sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w== - dependencies: - "@ungap/promise-all-settled" "1.1.2" - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.4.3" - debug "4.2.0" - diff "4.0.2" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "7.1.6" - growl "1.10.5" - he "1.2.0" - js-yaml "3.14.0" - log-symbols "4.0.0" - minimatch "3.0.4" - ms "2.1.2" - nanoid "3.1.12" - serialize-javascript "5.0.1" - strip-json-comments "3.1.1" - supports-color "7.2.0" - which "2.0.2" - wide-align "1.1.3" - workerpool "6.0.2" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "2.0.0" - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -nanoid@3.1.12: - version "3.1.12" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" - integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A== - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -p-limit@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-limit@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" - integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== - dependencies: - yocto-queue "^0.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" - integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== - dependencies: - p-limit "^3.0.2" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -picomatch@^2.0.4, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -readdirp@~3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" - integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== - dependencies: - picomatch "^2.2.1" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -serialize-javascript@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" - integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== - dependencies: - randombytes "^2.1.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -should-equal@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/should-equal/-/should-equal-2.0.0.tgz#6072cf83047360867e68e98b09d71143d04ee0c3" - integrity sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA== - dependencies: - should-type "^1.4.0" - -should-format@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/should-format/-/should-format-3.0.3.tgz#9bfc8f74fa39205c53d38c34d717303e277124f1" - integrity sha1-m/yPdPo5IFxT04w01xcwPidxJPE= - dependencies: - should-type "^1.3.0" - should-type-adaptors "^1.0.1" - -should-type-adaptors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz#401e7f33b5533033944d5cd8bf2b65027792e27a" - integrity sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA== - dependencies: - should-type "^1.3.0" - should-util "^1.0.0" - -should-type@^1.3.0, should-type@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/should-type/-/should-type-1.4.0.tgz#0756d8ce846dfd09843a6947719dfa0d4cff5cf3" - integrity sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM= - -should-util@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/should-util/-/should-util-1.0.1.tgz#fb0d71338f532a3a149213639e2d32cbea8bcb28" - integrity sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g== - -should@13.2.x: - version "13.2.3" - resolved "https://registry.yarnpkg.com/should/-/should-13.2.3.tgz#96d8e5acf3e97b49d89b51feaa5ae8d07ef58f10" - integrity sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ== - dependencies: - should-equal "^2.0.0" - should-format "^3.0.3" - should-type "^1.4.0" - should-type-adaptors "^1.0.1" - should-util "^1.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-json-comments@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - -supports-color@7.2.0, supports-color@^7.1.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" - integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== - dependencies: - has-flag "^4.0.0" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wide-align@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -workerpool@6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.2.tgz#e241b43d8d033f1beb52c7851069456039d1d438" - integrity sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q== - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -y18n@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" - integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== - -yargs-parser@13.1.2, yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yocto-queue@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" - integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/testing/pyglicko2/glicko2.py b/testing/pyglicko2/glicko2.py deleted file mode 100644 index fa9f5b5..0000000 --- a/testing/pyglicko2/glicko2.py +++ /dev/null @@ -1,244 +0,0 @@ -""" -Copyright (c) 2009 Ryan Kirkman - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -""" - -import math - -class Player: - # Class attribute - # The system constant, which constrains - # the change in volatility over time. - # - # underscore = "weak internal use"; do not export - _tau = 0.5 - - def getRating(self): - # __double_leading_underscore - # inside class FooBar, __boo becomes _FooBar__boo - # "self.rating" becomes Ryan.rating in tests.py - # - # 'self' is a specific instance of parent class - # (add (add rating.player 173.7178) 1500) - # print(f"getRating: {(self.__rating * 173.7178) + 1500}") - return (self.__rating * 173.7178) + 1500 - - def setRating(self, rating): - # (div (sub rating 1500) 173.7178) - # print(f"setRating: {(rating - 1500) / 173.7178}") - self.__rating = (rating - 1500) / 173.7178 - - # property(fget, fset) turns class attributes into properties - # fget: function that returns the value of the managed attribute - # fset: function that allows you to set the value of the managed attribute - rating = property(getRating, setRating) - - def getRd(self): - # (mul rd.player 173.7178) - # print(f"getRd: {self.__rd * 173.7178}") - return self.__rd * 173.7178 - - def setRd(self, rd): - # (div rd.player 173.7178) - # print(f"setRd: {rd / 173.7178}") - self.__rd = rd / 173.7178 - - rd = property(getRd, setRd) - - # __double_leading_and_trailing_underscore__ - # "magic" objects or attribs that live in user-controlled namespaces - # bascially, reserved for Python itself - def __init__(self, rating = 1500, rd = 350, vol = 0.06): - # For testing purposes, preload the values - # assigned to an unrated player. - self.setRating(rating) - self.setRd(rd) - self.vol = vol - - def _preRatingRD(self): - """ Calculates and updates the player's rating deviation for the - beginning of a rating period. - - preRatingRD() -> None - - """ - # (sqrt (add (pow rd.player 2) (pow vol.player 2))) - # print(f"preRatingRD: {math.sqrt(math.pow(self.__rd, 2) + math.pow(self.vol, 2))}") - self.__rd = math.sqrt(math.pow(self.__rd, 2) + math.pow(self.vol, 2)) - - def update_player(self, rating_list, RD_list, outcome_list): - """ Calculates the new rating and rating deviation of the player. - - update_player(list[int], list[int], list[bool]) -> None - - """ - # Convert the rating and rating deviation values for internal use. - # (div (sub x 1500) 173.7178) - rating_list = [(x - 1500) / 173.7178 for x in rating_list] - # (div x 173.7178) - RD_list = [x / 173.7178 for x in RD_list] - - v = self._v(rating_list, RD_list) - self.vol = self._newVol(rating_list, RD_list, outcome_list, v) - self._preRatingRD() - # (div 1 (sqrt (add (pow rd.player 2) (div 1 v)))) - self.__rd = 1 / math.sqrt((1 / math.pow(self.__rd, 2)) + (1 / v)) - - tempSum = 0 - for i in range(len(rating_list)): - # (add tempSum (mul g.player (sub outcome_list[i] self._E(rating_list[i], RD_list[i]))) - tempSum += self._g(RD_list[i]) * (outcome_list[i] - self._E(rating_list[i], RD_list[i])) - # (add playerating (mul (pow rd.player 2) tempSum)) - self.__rating += math.pow(self.__rd, 2) * tempSum - # print(f"{math.pow(self.__rd, 2) * tempSum}") - - - def _newVol(self, rating_list, RD_list, outcome_list, v): - """ Calculating the new volatility as per the Glicko2 system. - - _newVol(list, list, list) -> float - - """ - # Step 5 of the Glicko-2 algorithm - # Step 5.1 - A = math.log(math.pow(self.vol, 2)) - eps = 0.0000001 - tau = self._tau - delta = self._delta(rating_list, RD_list, outcome_list, v) - f = self._makef(delta, v, A) - - # Step 5.2 - # init var B and k - B = None - k = None - # if ∆2 > φ2 + v - if math.pow(delta, 2) > math.pow(self.__rd, 2) + v: - # set B = ln(∆2 − φ2 − v) - B = math.log(math.pow(delta, 2) - math.pow(self.__rd, 2) - v) - else: - # if ∆2 ≤ φ2 + v - k = 1 - # if f(a−kτ) < 0 - while f(A - k * tau) < 0: - k += 1 - # set B = a − kτ - B = A - k * tau - - # Step 5.3 - # let fA = f(A) - fA = f(A) - # let fB = f(B) - fB = f(B) - - # Step 5.4 - C = None - fC = None - # while |B − A| > ε - while abs(B - A) > eps: - # let C = A + (A−B)fA/(fB −fA) - C = A + (A - B) * fA / (fB - fA) - # let fC =f(C) - fC = f(C) - # if fCfB ≤ 0 - if fC * fB < 0: - # set A ← B - A = B - # set fA ← fB - fA = fB - else: - # set fA ← fA/2 - fA = fA / 2 - # set B ← C - B = C - # set fB ← fC - fB = fC - - # Step 5.5 - # print(f"newVol: {math.exp(A / 2)}") - return math.exp(A / 2) - - # there are other ways to do this, don't get caught up in how JS did it - def _makef(self, delta, v, A): - def f(x): - return math.exp(x) * (math.pow(delta, 2) - math.pow(self.__rd, 2) - v - math.exp(x)) \ - / (2 * math.pow(math.pow(self.__rd, 2) + v + math.exp(x), 2)) - (x - A) / math.pow(self._tau, 2) - # print(f"f: {math.exp(x) * (math.pow(delta, 2) - math.pow(self.__rd, 2) - v - math.exp(x)) / (2 * math.pow(math.pow(self.__rd, 2) + v + math.exp(x), 2)) - (x - A) / math.pow(self._tau, 2)}") - return f - - def _delta(self, rating_list, RD_list, outcome_list, v): - """ The delta function of the Glicko2 system. - - _delta(list, list, list) -> float - - """ - tempSum = 0 - for i in range(len(rating_list)): - # (mul RD_list[i] (sub outcome_list[i] self._E(rating_list[i], RD_list[i]))) - tempSum += self._g(RD_list[i]) * (outcome_list[i] - self._E(rating_list[i], RD_list[i])) - # print(f"delta: {v * tempSum}") - return v * tempSum - - def _v(self, rating_list, RD_list): - """ The v function of the Glicko2 system. - - _v(list[int], list[int]) -> float - - """ - tempSum = 0 - for i in range(len(rating_list)): - tempE = self._E(rating_list[i], RD_list[i]) - # ;(mul (pow _g(RD_list[i]) 2) tempE (sub 1 tempE)) - tempSum += math.pow(self._g(RD_list[i]), 2) * tempE * (1 - tempE) - # (div 1 tempSum) - # print(f"v: {1 / tempSum}") - return 1 / tempSum - - def _E(self, p2rating, p2RD): - """ The Glicko E function. - - _E(int) -> float - - """ - # (div 1 (add 1 (exp ;(mul -1 self._g(p2RD) (sub rating.player p2rating))))) - # print(f"E: {1 / (1 + math.exp(-1 * self._g(p2RD) * (self.__rating - p2rating)))}") - return 1 / (1 + math.exp(-1 * self._g(p2RD) * (self.__rating - p2rating))) - - def _g(self, RD): - """ The Glicko2 g(RD) function. - - _g() -> float - - """ - # (div 1 (sqrt (add 1 (mul 3 (div (pow RD 2) (pow pi 2)))))) - # print(f"g: {1 / math.sqrt(1 + 3 * math.pow(RD, 2) / math.pow(math.pi, 2))}") - return 1 / math.sqrt(1 + 3 * math.pow(RD, 2) / math.pow(math.pi, 2)) - - def did_not_compete(self): - """ Applies Step 6 of the algorithm. Use this for - players who did not compete in the rating period. - - did_not_compete() -> None - - """ - # print(f"did_not_compete: {self._preRatingRD()}") - self._preRatingRD() diff --git a/testing/pyglicko2/glicko2_tests.py b/testing/pyglicko2/glicko2_tests.py deleted file mode 100644 index 324de5b..0000000 --- a/testing/pyglicko2/glicko2_tests.py +++ /dev/null @@ -1,59 +0,0 @@ -""" -Copyright (c) 2009 Ryan Kirkman - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. -""" - -import glicko2 -import timeit - -def exampleCase(): - # Create a player called Ryan - Ryan = glicko2.Player() - # Following the example at: - # http://math.bu.edu/people/mg/glicko/glicko2.doc/example.html - # Pretend Ryan (of rating 1500 and rating deviation 350) - # plays players of ratings 1400, 1550 and 1700 - # and rating deviations 30, 100 and 300 respectively - # with outcomes 1, 0 and 0. - print("Old Rating: %.18f" % Ryan.rating) - print("Old Rating Deviation: %.18f" % Ryan.rd) - print("Old Volatility: %.18f" % Ryan.vol) - Ryan.update_player([x for x in [1400, 1550, 1700]], - [x for x in [30, 100, 300]], [1, 0, 0]) - print("New Rating: %.18f" % Ryan.rating) - print("New Rating Deviation: %.18f" % Ryan.rd) - print("New Volatility: %.18f" % Ryan.vol) - -def timingExample(runs = 10000): - print("\nThe time taken to perform " + str(runs)) - print("separate calculations (in seconds) was:") - timeTaken = timeit.Timer("Ryan = glicko2.Player(); \ - Ryan.update_player([x \ - for x in [1400, 1550, 1700]], \ - [x for x in [30, 100, 300]], [1, 0, 0])", \ - "import glicko2").repeat(1, 10000) - print(round(timeTaken[0], 4)) - -if __name__ == "__main__": - exampleCase() - timingExample() From be7fd82726fc2c8b7dfe1ed1894c4464946fd024 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 6 Apr 2024 21:01:31 +0100 Subject: [PATCH 10/20] Get Elo unit tests working --- src/lib/elo.hoon | 21 +++++++-------- src/lib/telos.hoon | 18 ++++++------- src/tests/elo.hoon | 64 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 src/tests/elo.hoon diff --git a/src/lib/elo.hoon b/src/lib/elo.hoon index af6879d..eb1063b 100644 --- a/src/lib/elo.hoon +++ b/src/lib/elo.hoon @@ -55,15 +55,16 @@ ++ new-performance-rating |= [sum=@ud matches=@ud wins=@ud losses=@ud] ^- rating - %+ div - %+ add - sum - %+ mul - 400 - %+ sub - wins - losses - matches + %- round + %+ div:rd + %+ add:rd + (sun:rd sum) + %+ mul:rd + .~400 + %+ sub:rd + (sun:rd wins) + (sun:rd losses) + (sun:rd matches) :: :: calculate new rating :: Rn = new rating @@ -73,7 +74,7 @@ :: K = scaling factor :: Rn = Ro + (K * (Ea - Ee)) ++ new-rating - |= [our=rating our-ex=@rd our-scale=@ud opp=rating out=?(%win %loss %draw)] + |= [our=rating our-ex=@rd our-scale=@ud out=?(%win %loss %draw)] ^- rating =/ our-actual ?: =(out %win) diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 0ebf4e6..4881990 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -233,11 +233,10 @@ (lent (skim our-matches |=(=match (has-loser-in-match match winner)))) == %: new-rating:elo - our-rating - (expected-score:elo our-rating opp-rating) - (scaling-factor:elo (lent our-matches)) - opp-rating - our-outcome + our-rating + (expected-score:elo our-rating opp-rating) + (scaling-factor:elo (lent our-matches)) + our-outcome == =/ new-loser-elo=rating =/ our-rating @@ -261,11 +260,10 @@ (lent (skim our-matches |=(=match (has-loser-in-match match loser)))) == %: new-rating:elo - our-rating - (expected-score:elo our-rating opp-rating) - (scaling-factor:elo (lent our-matches)) - opp-rating - our-outcome + our-rating + (expected-score:elo our-rating opp-rating) + (scaling-factor:elo (lent our-matches)) + our-outcome == %- %~ put by %- %~ put by diff --git a/src/tests/elo.hoon b/src/tests/elo.hoon new file mode 100644 index 0000000..77773da --- /dev/null +++ b/src/tests/elo.hoon @@ -0,0 +1,64 @@ +/+ *test, *elo +|% +++ test-expected-score + ;: weld + %+ expect-eq + !> .~0.500 + !> (expected-score 1.200 1.200) + :: + %+ expect-eq + !> .~0.752 + !> (expected-score 1.400 1.200) + :: + %+ expect-eq + !> .~0.902 + !> (expected-score 1.600 1.200) + :: + %+ expect-eq + !> .~0.965 + !> (expected-score 1.800 1.200) + == +:: +++ test-scaling-factor + ;: weld + %+ expect-eq + !> 40 + !> (scaling-factor 20) + %+ expect-eq + !> 32 + !> (scaling-factor 40) + %+ expect-eq + !> 24 + !> (scaling-factor 75) + == +:: +++ test-new-performance-rating + ;: weld + %+ expect-eq + !> 1.580 + !> (new-performance-rating 7.500 5 3 2) + :: + %+ expect-eq + !> 1.580 + !> (new-performance-rating 15.000 10 5 5) + :: + %+ expect-eq + !> 1.329 + !> (new-performance-rating 10.500 7 2 5) + == +:: +++ test-new-rating + ;: weld + %+ expect-eq + !> 1.515 + !> (new-rating 1.500 .~0.50 30 %win) + :: + %+ expect-eq + !> 1.578 + !> (new-rating 1.600 .~0.75 30 %loss) + :: + :: %+ expect-eq + :: !> 1.456 + :: !> (new-rating 1.450 .~0.30 30 %draw) + == +-- From 2a99bd2bf6b9018a2fa4da7ba04299590ec89c64 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 6 Apr 2024 21:28:39 +0100 Subject: [PATCH 11/20] Remove saloon --- src/lib/elo.hoon | 82 ++++------------------------------------------ src/tests/elo.hoon | 13 ++++++++ 2 files changed, 19 insertions(+), 76 deletions(-) diff --git a/src/lib/elo.hoon b/src/lib/elo.hoon index eb1063b..1b297cb 100644 --- a/src/lib/elo.hoon +++ b/src/lib/elo.hoon @@ -1,5 +1,4 @@ /- *telos -=< |% ++ round |= num=@rd @@ -16,10 +15,12 @@ ^- @rd %+ div:rd .~1 - %+ add:rd - .~1 - %+ pow-rd - .~2 + %- sun:rd + %+ add + 1 + %+ pow + 2 + %- round %+ div:rd %+ sub:rd (sun:rd opp) @@ -92,74 +93,3 @@ our-actual our-ex -- -:: -|% -:: -:: helper core -:: adapted from /lib/saloon -:: by ~lagrev-nocfep and ~mopfel-winrux -:: -++ sgn - |= x=@rd ^- ? - =(0 (rsh [0 31] x)) -:: -++ neg - |=(x=@rd (sub:rd .~0 x)) -:: -++ abs - |= x=@rd ^- @rd - ?: (sgn x) - x - (neg x) -:: -++ exp - |= x=@rd ^- @rd - =/ p .~1 - =/ po .~-1 - =/ i .~1 - |- ^- @rd - ?: (lth:rd (abs (sub:rd po p)) .~1e-5) - p - $(i (add:rd i .~1), p (add:rd p (div:rd (pow-n x i) (factorial i))), po p) -:: -++ factorial - |= x=@rd ^- @rd - =/ t=@rd .~1 - ?: (isclose x .~0) - t - |- ^- @rd - ?: (isclose x .~1) - t - $(x (sub:rd x .~1), t (mul:rd t x)) -:: -++ isclose - |= [p=@rd r=@rd] - (lth:rd (abs (sub:rd p r)) .~1e-5) -:: -++ log - |= z=@rd ^- @rd - =/ p .~0 - =/ po .~-1 - =/ i .~0 - |- ^- @rd - ?: (lth:rd (abs (sub:rd po p)) .~1e-5) - (mul:rd (div:rd (mul:rd .~2 (sub:rd z .~1)) (add:rd z .~1)) p) - =/ term1 (div:rd .~1 (add:rd .~1 (mul:rd .~2 i))) - =/ term2 (mul:rd (sub:rd z .~1) (sub:rd z .~1)) - =/ term3 (mul:rd (add:rd z .~1) (add:rd z .~1)) - =/ term (mul:rd term1 (pow-n (div:rd term2 term3) i)) - $(i (add:rd i .~1), p (add:rd p term), po p) -:: -++ pow-rd - |= [x=@rd n=@rd] ^- @rd - (exp (mul:rd n (log x))) -:: -++ pow-n - |= [x=@rd n=@rd] ^- @rd - ?: =(n .~0) .~1 - =/ p x - |- ^- @rd - ?: (lth:rd n .~2) - p - $(n (sub:rd n .~1), p (mul:rd p x)) --- diff --git a/src/tests/elo.hoon b/src/tests/elo.hoon index 77773da..4aab8c8 100644 --- a/src/tests/elo.hoon +++ b/src/tests/elo.hoon @@ -17,6 +17,19 @@ %+ expect-eq !> .~0.965 !> (expected-score 1.800 1.200) + :: + :: XX hangs + :: %+ expect-eq + :: !> .~0.248 + :: !> (expected-score 1.200 1.400) + :: + %+ expect-eq + !> .~0.098 + !> (expected-score 1.200 1.600) + :: + %+ expect-eq + !> .~0.035 + !> (expected-score 1.200 1.800) == :: ++ test-scaling-factor From 81eb57c01d0ba316f41a757615ce803cc74ae222 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sat, 6 Apr 2024 21:29:19 +0100 Subject: [PATCH 12/20] Uncomment test that crashed with saloon --- src/tests/elo.hoon | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/tests/elo.hoon b/src/tests/elo.hoon index 4aab8c8..b0e0c05 100644 --- a/src/tests/elo.hoon +++ b/src/tests/elo.hoon @@ -18,10 +18,9 @@ !> .~0.965 !> (expected-score 1.800 1.200) :: - :: XX hangs - :: %+ expect-eq - :: !> .~0.248 - :: !> (expected-score 1.200 1.400) + %+ expect-eq + !> .~0.248 + !> (expected-score 1.200 1.400) :: %+ expect-eq !> .~0.098 From c1921a072f3e62831ac3ab6b60372c513ee98218 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 00:13:31 +0100 Subject: [PATCH 13/20] Stub out +expected-score, don't allow negative ratings --- src/lib/elo.hoon | 69 +++++++++++++++++++++------------------------- src/tests/elo.hoon | 6 ++-- 2 files changed, 35 insertions(+), 40 deletions(-) diff --git a/src/lib/elo.hoon b/src/lib/elo.hoon index 1b297cb..eb04473 100644 --- a/src/lib/elo.hoon +++ b/src/lib/elo.hoon @@ -2,8 +2,8 @@ |% ++ round |= num=@rd - ^- @ud - (abs:si (need (toi:rd num))) + ^- @sd + (need (toi:rd num)) :: :: define expected score for a player in this match :: Ea = expected score for player A @@ -13,19 +13,7 @@ ++ expected-score |= [our=rating opp=rating] ^- @rd - %+ div:rd - .~1 - %- sun:rd - %+ add - 1 - %+ pow - 2 - %- round - %+ div:rd - %+ sub:rd - (sun:rd opp) - (sun:rd our) - .~125 + !! :: :: calculate K :: K = 16 over 100 games played @@ -56,16 +44,20 @@ ++ new-performance-rating |= [sum=@ud matches=@ud wins=@ud losses=@ud] ^- rating - %- round - %+ div:rd - %+ add:rd - (sun:rd sum) - %+ mul:rd - .~400 - %+ sub:rd - (sun:rd wins) - (sun:rd losses) - (sun:rd matches) + =/ signed-rating + %- round + %+ div:rd + %+ add:rd + (sun:rd sum) + %+ mul:rd + .~400 + %+ sub:rd + (sun:rd wins) + (sun:rd losses) + (sun:rd matches) + ?. (syn:si signed-rating) + 0 + (abs:si signed-rating) :: :: calculate new rating :: Rn = new rating @@ -79,17 +71,20 @@ ^- rating =/ our-actual ?: =(out %win) - our-ex + .~1 ?. =(out %draw) - (sub:rd .~1 our-ex) - :: XX what's our actual score if it's a draw? - !! - %- round - %+ add:rd - (sun:rd our) - %+ mul:rd - (sun:rd our-scale) - %+ sub:rd - our-actual - our-ex + .~0 + .~0.50 + =/ signed-rating + %- round + %+ add:rd + (sun:rd our) + %+ mul:rd + (sun:rd our-scale) + %+ sub:rd + our-actual + our-ex + ?. (syn:si signed-rating) + 0 + (abs:si signed-rating) -- diff --git a/src/tests/elo.hoon b/src/tests/elo.hoon index b0e0c05..368da0a 100644 --- a/src/tests/elo.hoon +++ b/src/tests/elo.hoon @@ -69,8 +69,8 @@ !> 1.578 !> (new-rating 1.600 .~0.75 30 %loss) :: - :: %+ expect-eq - :: !> 1.456 - :: !> (new-rating 1.450 .~0.30 30 %draw) + %+ expect-eq + !> 1.456 + !> (new-rating 1.450 .~0.30 30 %draw) == -- From 94b562bc97acee1c25dfb5d0b5e54d61b63acd55 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 11:15:03 +0100 Subject: [PATCH 14/20] Integrate /lib/math --- src/lib/elo.hoon | 79 +- src/lib/math.hoon | 2966 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2997 insertions(+), 48 deletions(-) create mode 100644 src/lib/math.hoon diff --git a/src/lib/elo.hoon b/src/lib/elo.hoon index eb04473..40059be 100644 --- a/src/lib/elo.hoon +++ b/src/lib/elo.hoon @@ -1,26 +1,23 @@ /- *telos +/+ math |% -++ round - |= num=@rd - ^- @sd - (need (toi:rd num)) -:: -:: define expected score for a player in this match -:: Ea = expected score for player A -:: Ra = Elo rating of player A -:: Rb = Elo rating of player B -:: Ea = 1 / (1 + 2^((Rb - Ra) / 125)) ++ expected-score |= [our=rating opp=rating] ^- @rd - !! + %+ div:rd:math + .~1 + %+ add:rd:math + .~1 + %- exp:rd:math + %+ mul:rd:math + %- log:rd:math + .~2 + %+ div:rd:math + %+ sub:rd:math + (sun:rd opp) + (sun:rd our) + .~125 :: -:: calculate K -:: K = 16 over 100 games played -:: K = 24 between 60 and 100 games played -:: K = 32 between 30 and 60 games played -:: K = 40 between 10 and 30 games played -:: K = 64 less than 10 games played ++ scaling-factor |= matches=@ud ^- @ud @@ -34,38 +31,24 @@ 24 16 :: -:: bootstrap a new rating in the first 10 games -:: P = performance rating -:: Σ = sum of opponents' ratings -:: N = number of games played -:: w = number of wins -:: l = number of losses -:: P = (Σ + (400 * (w - l))) / N ++ new-performance-rating |= [sum=@ud matches=@ud wins=@ud losses=@ud] ^- rating - =/ signed-rating - %- round - %+ div:rd - %+ add:rd + %- abs:si + %- need + %- toi:rd:math + %+ round-places:rd:math + %+ div:rd:math + %+ add:rd:math (sun:rd sum) - %+ mul:rd + %+ mul:rd:math .~400 - %+ sub:rd + %+ sub:rd:math (sun:rd wins) (sun:rd losses) (sun:rd matches) - ?. (syn:si signed-rating) - 0 - (abs:si signed-rating) + 0 :: -:: calculate new rating -:: Rn = new rating -:: Ro = old rating -:: Ee = expected score -:: Ea = actual score -:: K = scaling factor -:: Rn = Ro + (K * (Ea - Ee)) ++ new-rating |= [our=rating our-ex=@rd our-scale=@ud out=?(%win %loss %draw)] ^- rating @@ -75,16 +58,16 @@ ?. =(out %draw) .~0 .~0.50 - =/ signed-rating - %- round - %+ add:rd + %- abs:si + %- need + %- toi:rd:math + %+ round-places:rd:math + %+ add:rd:math (sun:rd our) - %+ mul:rd + %+ mul:rd:math (sun:rd our-scale) - %+ sub:rd + %+ sub:rd:math our-actual our-ex - ?. (syn:si signed-rating) - 0 - (abs:si signed-rating) + 0 -- diff --git a/src/lib/math.hoon b/src/lib/math.hoon new file mode 100644 index 0000000..ff13f9f --- /dev/null +++ b/src/lib/math.hoon @@ -0,0 +1,2966 @@ + :: +:::: Mathematical library +:: +:: Pure Hoon implementations are naive formally correct algorithms, +:: awaiting efficient jetting with GNU Scientific Library. +:: +|% +++ rs + ^| + |_ $: r=$?(%n %u %d %z) :: round nearest, up, down, to zero + rtol=_.1e-5 :: relative tolerance for precision of operations + == + :: mathematics constants to single precision + :: +tau: @rs + :: + :: Returns the value 2*pi (OEIS A019692). + :: Examples + :: > tau + :: .6.2831855 + :: Source + ++ tau .6.2831855 + :: +pi: @rs + :: + :: Returns the value pi (OEIS A000796). + :: Examples + :: > pi + :: .3.1415927 + :: Source + ++ pi .3.1415927 + :: +e: @rs + :: + :: Returns the value e (Euler's constant) (OEIS A001113). + :: Examples + :: > e + :: .2.7182817 + :: Source + ++ e .2.7182817 + :: +phi: @rs + :: + :: Returns the value phi (golden ratio) (OEIS A001622). + :: Examples + :: > phi + :: .1.618034 + :: Source + ++ phi .1.618034 + :: +sqt2: @rs + :: + :: Returns the value sqrt(2) (OEIS A002193). + :: Examples + :: > sqt2 + :: .1.4142135 + :: Source + ++ sqt2 .1.4142135 + :: +invsqt2: @rs + :: + :: Returns the value 1/sqrt(2) (OEIS A010503). + :: Examples + :: > invsqt2 + :: .70710677 + :: Source + ++ invsqt2 .70710677 + :: +log2: @rs + :: + :: Returns the value log(2) (OEIS A002162). + :: Examples + :: > log2 + :: .6931472 + :: Source + ++ log2 .0.6931472 + :: +invlog2: @rs + :: + :: Returns the value 1/log(2). + :: Examples + :: > invlog2 + :: 1.442695 + :: Source + ++ invlog2 .1.442695 + :: +log10: @rs + :: + :: Returns the value log(10) (OEIS A002392). + :: Examples + :: > log10 + :: .2.3025851 + :: Source + ++ log10 .2.3025851 + :: +huge: @rs + :: + :: Returns the value of the largest representable number. + :: Examples + :: > huge + :: .3.4028235e+38 + :: Source + ++ huge `@rs`0x7f80.0000 :: 3.40282346638528859812e+38 + :: +tiny: @rs + :: + :: Returns the value of the smallest representable normal number. + :: Examples + :: > tiny + :: .1.1754944e-38 + :: Source + ++ tiny `@rs`0x1 :: 1.40129846432481707092e-45 + :: + :: Operations + :: + :: +sea: @rs -> fn + :: + :: Returns the +$fn representation of a floating-point atom. + :: Examples + :: > (sea .1) + :: [%f s=%.y e=-23 a=8.388.608] + :: > (sea .1.1) + :: [%f s=%.y e=-23 a=9.227.469] + :: Source + ++ sea sea:^rs + :: +bit: fn -> @rs + :: + :: Returns the floating-point atom of a +$fn representation. + :: Examples + :: > (bit [%f s=%.y e=-23 a=8.388.608]) + :: .1 + :: > (bit [%f s=%.y e=-23 a=9.227.469]) + :: .1.1 + :: Source + ++ bit bit:^rs + :: +sun: @ud -> @rs + :: + :: Returns the floating-point atom of an unsigned integer atom. + :: Examples + :: > (sun 1) + :: .1 + :: > (sun 1.000) + :: .1e3 + :: Source + ++ sun sun:^rs + :: +san: @sd -> @rs + :: + :: Returns the floating-point atom of a signed integer atom. + :: Examples + :: > (san --1) + :: .1 + :: > (san -1) + :: .-1 + :: Source + ++ san san:^rs + ::++ exp exp:^rs :: no pass-through because of exp function + :: +toi: @rs -> @sd + :: + :: Returns the unitized signed integer atom of a rounded floating-point atom. + :: Examples + :: > (toi .1) + :: [~ --1] + :: > (toi .1.1) + :: [~ --1] + :: Source + ++ toi toi:^rs + :: +drg: @rs -> dn + :: + :: Returns the decimal form of a floating-point atom using the Dragon4 + :: algorithm. + :: Examples + :: > (drg .1) + :: [%d s=%.y e=--0 a=1] + :: > (drg .1.1) + :: [%d s=%.y e=-1 a=11] + :: Source + ++ drg drg:^rs + :: +grd: dn -> @rs + :: + :: Returns the floating-point atom of a decimal form. + :: Examples + :: > (grd [%d s=%.y e=--0 a=1]) + :: .1 + :: > (grd [%d s=%.y e=-1 a=11]) + :: .1.1 + :: Source + ++ grd grd:^rs + :: + :: Comparison + :: + :: +lth: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than. + :: Examples + :: > (lth .1 .2) + :: %.y + :: > (lth .2 .1) + :: %.n + :: > (lth .1 .1) + :: %.n + :: Source + ++ lth lth:^rs + :: +lte: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Examples + :: > (lte .1 .2) + :: %.y + :: > (lte .2 .1) + :: %.n + :: > (lte .1 .1) + :: %.y + :: Source + ++ lte lte:^rs + :: +leq: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Alias for +lte. + :: Examples + :: > (leq .1 .2) + :: %.y + :: > (leq .2 .1) + :: %.n + :: > (leq .1 .1) + :: %.y + :: Source + ++ leq lte:^rs + :: +equ: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, equal to. + :: Examples + :: > (equ .1 .2) + :: %.n + :: > (equ .2 .1) + :: %.n + :: > (equ .1 .1) + :: %.y + :: Source + ++ equ equ:^rs + :: +gth: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than. + :: Examples + :: > (gth .1 .2) + :: %.n + :: > (gth .2 .1) + :: %.y + :: > (gth .1 .1) + :: %.n + :: Source + ++ gth gth:^rs + :: +gte: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Examples + :: > (gte .1 .2) + :: %.n + :: > (gte .2 .1) + :: %.y + :: > (gte .1 .1) + :: %.y + :: Source + ++ gte gte:^rs + :: +geq: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Alias for +gte. + :: Examples + :: > (geq .1 .2) + :: %.n + :: > (geq .2 .1) + :: %.y + :: > (geq .1 .1) + :: %.y + :: Source + ++ geq gte:^rs + :: +neq: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, not equal to. + :: Examples + :: > (neq .1 .2) + :: %.y + :: > (neq .2 .1) + :: %.y + :: > (neq .1 .1) + :: %.n + :: Source + ++ neq |=([a=@rs b=@rs] ^-(? !(equ:^rs a b))) + :: +isclose: [@rs @rs] -> ? + :: + :: Returns the comparison of two floating-point atoms, within a relative + :: tolerance (provided by the +rs door). + :: Examples + :: > (isclose .1 .2) + :: %.n + :: > (isclose .1 .1000001) + :: %.y + :: > (~(isclose rs [%z .1e-8]) .1 .1000001) + :: %.n + :: Source + ++ isclose + |= [p=@rs r=@rs] + (lth (abs (sub p r)) rtol) + :: +allclose: [@rs (list @rs)] -> ? + :: + :: Returns the comparison of a floating-point atom to a list of floating- + :: point atoms, within a relative tolerance (provided by the +rs door). + :: Examples + :: > (allclose .1 ~[.1 .2]) + :: %.n + :: > (allclose .1 ~[.1 .1.000001]) + :: %.y + :: > (~(allclose rs [%z .1e-8]) .1 ~[.1 .1000001]) + :: %.n + :: Source + ++ allclose + |= [p=@rs q=(list @rs)] + =/ i 0 + =/ n (lent q) + |- ^- ? + ?: =(n i) + %.y + ?. (isclose p (snag i q)) + %.n + $(i +(i)) + :: +isint: @rs -> ? + :: + :: Returns whether a floating-point value is an integer (no fractional part). + :: Examples + :: > (isint .1) + :: %.y + :: > (isint .1.1) + :: %.n + :: Source + ++ isint + |= x=@rs ^- ? + (equ x (san (need (toi x)))) + :: + :: Algebraic + :: + :: +add: [@rs @rs] -> @rs + :: + :: Returns the sum of two floating-point atoms. + :: Examples + :: > (add .1 .2) + :: .3 + :: Source + ++ add add:^rs + :: +sub: [@rs @rs] -> @rs + :: + :: Returns the difference of two floating-point atoms. + :: Examples + :: > (sub .1 .2) + :: .-1 + :: Source + ++ sub sub:^rs + :: +mul: [@rs @rs] -> @rs + :: + :: Returns the product of two floating-point atoms. + :: Examples + :: > (mul .1 .2) + :: .2 + :: > (mul .2 .3) + :: .6 + :: Source + ++ mul mul:^rs + :: +div: [@rs @rs] -> @rs + :: + :: Returns the quotient of two floating-point atoms. + :: Examples + :: > (div .1 .2) + :: .0.5 + :: Source + ++ div div:^rs + :: +mod: [@rs @rs] -> @rs + :: + :: Returns the modulus of two floating-point atoms. + :: Examples + :: > (mod .1 .2) + :: .1 + :: > (mod .100 .8) + :: .4 + :: Source + ++ mod + |= [a=@rs b=@rs] ^- @rs + ?: (lth a .0) + (sub b (mod (neg a) b)) + (sub a (mul b (san (need (toi (div a b)))))) :: a - b * floor(a / b) + :: +fma: [@rs @rs @rs] -> @rs + :: + :: Returns the fused multiply-add of three floating-point atoms. + :: Examples + :: > (fma .1 .2 .3) + :: .5 + :: > (fma .2 .3 .4) + :: .10 + :: Source + ++ fma fma:^rs + :: +sig: @rs -> ? + :: + :: Returns the sign of a floating-point atom. + :: Examples + :: > (sig .1) + :: %.y + :: > (sig .-1) + :: %.n + :: Source + ++ sig |=(x=@rs =(0 (rsh [0 31] x))) + :: +sgn: @rs -> ? + :: + :: Returns the sign of a floating-point atom. + :: Alias for +sig. + :: Examples + :: > (sgn .1) + :: %.y + :: > (sgn .-1) + :: %.n + :: Source + ++ sgn sig + :: +neg: @rs -> @rs + :: + :: Returns the negation of a floating-point atom. + :: Examples + :: > (neg .1) + :: .-1 + :: > (neg .-1) + :: .1 + :: Source + ++ neg |=(x=@rs (sub .0 x)) + :: +factorial: @rs -> @rs + :: + :: Returns the factorial of a floating-point atom. Assumes integer input. + :: Examples + :: > (factorial .1) + :: .1 + :: > (factorial .2) + :: .2 + :: > (factorial .3) + :: .6 + :: Source + ++ factorial + |= x=@rs ^- @rs + ?> (gte x .0) + =/ t=@rs .1 + ?: (isclose x .0) + t + |- ^- @rs + ?: (isclose x .1) + t + $(x (sub x .1), t (mul t x)) + :: +abs: @rs -> @rs + :: + :: Returns the absolute value of a floating-point atom. + :: Examples + :: > (abs .1) + :: .1 + :: > (abs .-1) + :: .1 + :: Source + ++ abs + |= x=@rs ^- @rs + ?:((sgn x) x (neg x)) + :: +exp: @rs -> @rs + :: + :: Returns the exponential of a floating-point atom. + :: Examples + :: > (exp .1) + :: .2.7182808 + :: > (exp .2) + :: .7.389052 + :: > (~(exp rs [%z .1e-8]) .2) + :: .7.389053 + :: > (exp .inf) + :: .inf + :: Source + ++ exp + |= x=@rs ^- @rs + :: filter out non-finite arguments + ?: =(x 0x0) .1 + :: check infinities + ?: =(x 0x7f80.0000) `@rs`0x7f80.0000 :: exp(+inf) -> inf + ?: =(x 0xff80.0000) .0.0 :: exp(-inf) -> 0 + :: check NaN + ?. (^gte (dis 0x7fc0.0000 x) 0) `@rs`0x7fc0.0000 :: exp(NaN) -> NaN + :: check overflow to infinity + =/ o-threshold `@rs`0x42b0.c0a8 :: 88.72283905206835, value above which exp(x) overflows + ?: (gth x o-threshold) (mul huge huge) + :: check underflow to zero + =/ u-threshold `@rs`0xc2b0.c0a8 :: -88.72283905206835, value below which exp(x) underflows + ?: (lth x u-threshold) (mul tiny tiny) + :: otherwise, use Taylor series + =/ p .1 + =/ po .-1 + =/ i .1 + |- ^- @rs + ?: (lth (abs (sub po p)) rtol) + p + $(i (add i .1), p (add p (div (pow-n x i) (factorial i))), po p) + :: +sin: @rs -> @rs + :: + :: Returns the sine of a floating-point atom. + :: Examples + :: > (sin .1) + :: .0.84147096 + :: > (sin .2) + :: .0.9092974 + :: > (sin pi) + :: .3.1609193e-7 + :: Source + ++ sin + |= x=@rs ^- @rs + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7f80.0000) `@rs`0x7fc0.0000 :: sin(+inf) -> NaN + ?: =(x 0xff80.0000) `@rs`0x7fc0.0000 :: sin(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7fc0.0000 x) 0) `@rs`0x7fc0.0000 :: sin(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p x + =/ po .-2 + =/ i 1 + =/ term x + |- ^- @rs + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (add i2 .1)))) + $(i +(i), p (add p term), po p) + :: +cos: @rs -> @rs + :: + :: Returns the cosine of a floating-point atom. + :: Examples + :: > (cos .1) + :: .0.5403022 + :: > (cos .2) + :: .-0.41614664 + :: > (cos pi) + :: .-0.9999998 + :: Source + ++ cos + |= x=@rs ^- @rs + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7f80.0000) `@rs`0x7fc0.0000 :: sin(+inf) -> NaN + ?: =(x 0xff80.0000) `@rs`0x7fc0.0000 :: sin(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7fc0.0000 x) 0) `@rs`0x7fc0.0000 :: sin(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p .1 + =/ po .-2 + =/ i 1 + =/ term .1 + |- ^- @rs + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (sub i2 .1)))) + $(i +(i), p (add p term), po p) + :: +tan: @rs -> @rs + :: + :: Returns the tangent of a floating-point atom. + :: Examples + :: > (tan .1) + :: .1.5574079 + :: > (tan .2) + :: .-2.1850407 + :: > (tan pi) + :: .-7.0094916e-7 + :: Source + ++ tan + |= x=@rs ^- @rs + (div (sin x) (cos x)) + :: +pow-n: [@rs @rs] -> @rs + :: + :: Returns the power of a floating-point atom to an integer exponent. + :: Examples + :: > (pow-n .1 .2) + :: .1 + :: > (pow-n .2 .2) + :: .4 + :: > (pow-n .2 .3) + :: .8 + :: Source + ++ pow-n + |= [x=@rs n=@rs] ^- @rs + ?: =(n .0) .1 + ?> &((gth n .0) (isint n)) + =/ p x + |- ^- @rs + ?: (lth n .2) + p + $(n (sub n .1), p (mul p x)) + :: +log: @rs -> @rs + :: + :: Returns the natural logarithm of a floating-point atom. + :: Examples + :: > (log .1) + :: .0 + :: > (log .2) + :: .0.69314677 + :: > (~(log rs [%z .1e-8]) .2) + :: .0.6931469 + :: > (log .inf) + :: .inf + :: > (log:rs:math e:rs:math) + :: .0.999998 + :: > (~(log rs:math [%z .1e-8]) e:rs:math) + :: .0.9999994 + :: Source + ++ log + |= z=@rs ^- @rs + :: filter out non-finite arguments + :: check infinities + ?: =(z 0x7f80.0000) `@rs`0x7f80.0000 :: log(+inf) -> inf + ?: =(z 0xff80.0000) `@rs`0x7fc0.0000 :: log(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7fc0.0000 z) 0) `@rs`0x7fc0.0000 :: exp(NaN) -> NaN + :: otherwise, use Taylor series + =/ p .0 + =/ po .-1 + =/ i .0 + |- ^- @rs + ?: (lth (abs (sub po p)) rtol) + (mul (div (mul .2 (sub z .1)) (add z .1)) p) + =/ term1 (div .1 (add .1 (mul .2 i))) + =/ term2 (mul (sub z .1) (sub z .1)) + =/ term3 (mul (add z .1) (add z .1)) + =/ term (mul term1 (pow-n (div term2 term3) i)) + $(i (add i .1), p (add p term), po p) + :: +log-10: @rs -> @rs + :: + :: Returns the base-10 logarithm of a floating-point atom. + :: Examples + :: > (log-10 .0.1) + :: .-0.999989 + :: > (log-10 .2) + :: .0.30102932 + :: > (~(log-10 rs [%z .1e-8]) .2) + :: .0.3010301 + :: > (log-10 .inf) + :: .inf + :: Source + ++ log-10 + |= z=@rs ^- @rs + (div (log z) log10) + :: +log-2: @rs -> @rs + :: + :: Returns the base-2 logarithm of a floating-point atom. + :: Examples + :: > (log-2 .0.1) + :: .-3.321928 + :: > (log-2 .2) + :: .1.5849625 + :: > (~(log-2 rs [%z .1e-8]) .2) + :: .1.5849633 + :: Source + ++ log-2 + |= z=@rs ^- @rs + (div (log z) log2) + :: +pow: [@rs @rs] -> @rs + :: + :: Returns the power of a floating-point atom to a floating-point exponent. + :: Examples + :: > (pow .1 .2) + :: .1 + :: > (pow .2 .2) + :: .4 + :: > (pow .2 .3.5) + :: .11.313682 + :: > (~(pow rs:math [%z .1e-8]) .2 .3.5) + :: .11.313687 + :: Source + ++ pow + |= [x=@rs n=@rs] ^- @rs + :: fall through on integers (faster) + ?: =(n (san (need (toi n)))) (pow-n x (san (need (toi n)))) + (exp (mul n (log x))) + :: +sqrt: @rs -> @rs + :: + :: Returns the square root of a floating-point atom. + :: Alias for +sqt. + :: Examples + :: > (sqrt .1) + :: .1 + :: > (sqrt .2) + :: .1.4142128 + :: > (~(sqrt rs [%z .1e-8]) .2) + :: .1.414213 + :: Source + ++ sqrt sqt + :: +sqt: @rs -> @rs + :: + :: Returns the square root of a floating-point atom. + :: Examples + :: > (sqt .1) + :: .1 + :: > (sqt .2) + :: .1.4142128 + :: > (~(sqt rs [%z .1e-8]) .2) + :: .1.414213 + :: Source + ++ sqt + |= x=@rs ^- @rs + ?> (sgn x) + (pow x .0.5) + :: +cbrt: @rs -> @rs + :: + :: Returns the cube root of a floating-point atom. + :: Alias for +cbt. + :: Examples + :: > (cbrt .1) + :: .1 + :: > (cbrt .2) + :: .1.2599205 + :: > (~(cbrt rs [%z .1e-8]) .2) + :: .1.2599207 + :: Source + ++ cbrt cbt + :: +cbt: @rs -> @rs + :: + :: Returns the cube root of a floating-point atom. + :: Examples + :: > (cbt .1) + :: .1 + :: > (cbt .2) + :: .1.2599205 + :: > (~(cbt rs [%z .1e-8]) .2) + :: .1.2599207 + :: Source + ++ cbt + |= x=@rs ^- @rs + ?> (sgn x) + (pow x .0.33333333) + :: +arg: @rs -> @rs + :: + :: Returns the argument of a floating-point atom (real argument = absolute + :: value). + :: Examples + :: > (arg .1) + :: .1 + :: > (arg .-1) + :: .1 + :: Source + ++ arg abs + :: +round: [@rs @ud] -> @rs + :: + :: Returns the floating-point atom rounded to a given number of decimal + :: places. + :: Examples + :: > (round .1 0) + :: .1 + :: > (round .1.11 1) + :: .1.1 + :: > (round .1.11 2) + :: .1.11 + :: > (round .1.11 3) + :: .1.11 + :: Source + ++ round + |= [x=@rs n=@ud] ^- @rs + ?: =(.0 x) .0 + :: Calculate the order of magnitude. + =/ oom (san (need (toi (log-10 (abs x))))) + :: Calculate the scaling factor. + =/ scaling (pow .10 :(sub (sun n) oom .1)) + :: Round the mantissa to desired significant digits. + =/ rnd-mantissa (round-bankers (mul x scaling)) + :: Convert back to the original scale. + (div rnd-mantissa scaling) + :: +round-places: [@rs @ud] -> @rs + :: + :: Returns the floating-point atom rounded to a given number of decimal + :: places. This is exceptionally sensitive to off-by-one FP rounding error. + :: Examples + :: > (round-places .1 0) + :: .1 + :: > (round-places .1.11 1) + :: .1.1 + :: > (round-places .1.285 2) + :: .1.28 + :: > (round-places .4.12345 3) + :: .4.1229997 + :: Source + ++ round-places + |= [x=@rs n=@ud] ^- @rs + :: Calculate the scaling factor. + =/ scaling (pow .10 (sun n)) + :: Scale the number. + =/ scaled (mul x scaling) + :: Round the mantissa to desired significant digits. + =/ rnd-mantissa (round-bankers scaled) + :: Convert back to the original scale. + (div rnd-mantissa scaling) + :: +round-bankers: @rs -> @rs + :: + :: Returns the floating-point atom rounded to the nearest integer, with + :: ties rounded to the nearest even integer. + :: Examples + :: > (round-bankers .1) + :: .1 + :: > (round-bankers .1.5) + :: .2 + :: > (round-bankers .1.49) + :: .1 + :: Source + ++ round-bankers + |= x=@rs ^- @rs + =/ int (san (need (toi x))) + =/ dcm (sub x int) + ?: (lth dcm .0.5) + int + (add int .1) + -- +:: double precision +++ rd + ^| + |_ $: r=$?(%n %u %d %z) :: round nearest, up, down, to zero + rtol=_.~1e-10 :: relative tolerance for precision of operations + == + :: mathematics constants to single precision + :: +tau: @rd + :: + :: Returns the value 2*pi (OEIS A019692). + :: Examples + :: > tau + :: .~6.283185307179586 + :: Source + ++ tau .~6.283185307179586 + :: +pi: @rd + :: + :: Returns the value pi (OEIS A000796). + :: Examples + :: > pi + :: .~3.141592653589793 + :: Source + ++ pi .~3.141592653589793 + :: +e: @rd + :: + :: Returns the value e (Euler's constant) (OEIS A001113). + :: Examples + :: > e + :: .~2.718281828459045 + :: Source + ++ e .~2.718281828459045 + :: +phi: @rd + :: + :: Returns the value phi (golden ratio) (OEIS A001622). + :: Examples + :: > phi + :: .~1.618033988749895 + :: Source + ++ phi .~1.618033988749895 + :: +sqt2: @rd + :: + :: Returns the value sqrt(2) (OEIS A002193). + :: Examples + :: > sqt2 + :: .~1.414213562373095 + :: Source + ++ sqt2 .~1.4142135623730951 + :: +invsqt2: @rd + :: + :: Returns the value 1/sqrt(2) (OEIS A010503). + :: Examples + :: > invsqt2 + :: .~0.7071067811865476 + :: Source + ++ invsqt2 .~0.7071067811865476 + :: +log2: @rd + :: + :: Returns the value log(2) (OEIS A002162). + :: Examples + :: > log2 + :: .~0.6931471805599453 + :: Source + ++ log2 .~0.6931471805599453 + :: +invlog2: @rd + :: + :: Returns the value 1/log(2). + :: Examples + :: > invlog2 + :: .~1.4426950408889634 + :: Source + ++ invlog2 .~1.4426950408889634 + :: +log10: @rd + :: + :: Returns the value log(10) (OEIS A002392). + :: Examples + :: > log10 + :: .~2.302585092994046 + :: Source + ++ log10 .~2.302585092994046 + :: + :: +huge: @rd + :: + :: Returns the value of the largest representable number. + :: Examples + :: > huge + :: .~1.7976931348623157e+308 + :: Source + ++ huge `@rd`0x7fef.ffff.ffff.ffff :: 1.79769313486231570815e+308 + :: +tiny: @rd + :: + :: Returns the value of the smallest representable normal number. + :: Examples + :: > tiny + :: .~2.2250738585072014e-308 + :: Source + ++ tiny `@rd`0x10.0000.0000.0000 :: 2.22507385850720138309e-308 + :: + :: Operations + :: + :: +sea: @rd -> fn + :: + :: Returns the +$fn representation of a floating-point atom. + :: Examples + :: > (sea .~1) + :: [%f s=%.y e=-52 a=4.503.599.627.370.496] + :: > (sea .~1.1) + :: [%f s=%.y e=-52 a=4.953.959.590.107.546] + :: Source + ++ sea sea:^rd + :: +bit: fn -> @rd + :: + :: Returns the floating-point atom of a +$fn representation. + :: Examples + :: > (bit [%f s=%.y e=-52 a=4.503.599.627.370.496]) + :: .~1 + :: > (bit [%f s=%.y e=-52 a=4.953.959.590.107.546]) + :: .~1.1 + :: Source + ++ bit bit:^rd + :: +sun: @ud -> @rd + :: + :: Returns the floating-point atom of an unsigned integer atom. + :: Examples + :: > (sun 1) + :: .~1 + :: > (sun 1.000) + :: .~1e3 + :: Source + ++ sun sun:^rd + :: +san: @sd -> @rd + :: + :: Returns the floating-point atom of a signed integer atom. + :: Examples + :: > (san --1) + :: .~1 + :: > (san -1) + :: .~-1 + :: Source + ++ san san:^rd + ::++ exp exp:^rd :: no pass-through because of exp function + :: +toi: @rd -> @sd + :: + :: Returns the unitized signed integer atom of a rounded floating-point atom. + :: Examples + :: > (toi .~1) + :: [~ --1] + :: > (toi .~1.1) + :: [~ --1] + :: Source + ++ toi toi:^rd + :: +drg: @rd -> dn + :: + :: Returns the decimal form of a floating-point atom using the Dragon4 + :: algorithm. + :: Examples + :: > (drg .~1) + :: [%d s=%.y e=--0 a=1] + :: > (drg .~1.1) + :: [%d s=%.y e=-1 a=11] + :: Source + ++ drg drg:^rd + :: +grd: dn -> @rd + :: + :: Returns the floating-point atom of a decimal form. + :: Examples + :: > (grd [%d s=%.y e=--0 a=1]) + :: .~1 + :: > (grd [%d s=%.y e=-1 a=11]) + :: .~1.1 + :: Source + ++ grd grd:^rd + :: + :: Comparison + :: + :: +lth: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than. + :: Examples + :: > (lth .~1 .~2) + :: %.y + :: > (lth .~2 .~1) + :: %.n + :: > (lth .~1 .~1) + :: %.n + :: Source + ++ lth lth:^rd + :: +lte: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Examples + :: > (lte .~1 .~2) + :: %.y + :: > (lte .~2 .~1) + :: %.n + :: > (lte .~1 .~1) + :: %.y + :: Source + ++ lte lte:^rd + :: +leq: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Alias for +lte. + :: Examples + :: > (leq .~1 .~2) + :: %.y + :: > (leq .~2 .~1) + :: %.n + :: > (leq .~1 .~1) + :: %.y + :: Source + ++ leq lte:^rd + :: +equ: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, equal to. + :: Examples + :: > (equ .~1 .~2) + :: %.n + :: > (equ .~2 .~1) + :: %.n + :: > (equ .~1 .~1) + :: %.y + :: Source + ++ equ equ:^rd + :: +gth: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than. + :: Examples + :: > (gth .~1 .~2) + :: %.n + :: > (gth .~2 .~1) + :: %.y + :: > (gth .~1 .~1) + :: %.n + :: Source + ++ gth gth:^rd + :: +gte: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Examples + :: > (gte .~1 .~2) + :: %.n + :: > (gte .~2 .~1) + :: %.y + :: > (gte .~1 .~1) + :: %.y + :: Source + ++ gte gte:^rd + :: +geq: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Alias for +gte. + :: Examples + :: > (geq .~1 .~2) + :: %.n + :: > (geq .~2 .~1) + :: %.y + :: > (geq .~1 .~1) + :: %.y + :: Source + ++ geq gte:^rd + :: +neq: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, not equal to. + :: Examples + :: > (neq .~1 .~2) + :: %.y + :: > (neq .~2 .~1) + :: %.y + :: > (neq .~1 .~1) + :: %.n + :: Source + ++ neq |=([a=@rd b=@rd] ^-(? !(equ:^rd a b))) + :: +isclose: [@rd @rd] -> ? + :: + :: Returns the comparison of two floating-point atoms, within a relative + :: tolerance (provided by the +rd door). + :: Examples + :: > (isclose .~1 .~2) + :: %.n + :: > (isclose .~1 .~1.0000001) + :: %.n + :: > (~(isclose rd [%z .~1e-3]) .~1 .~1.0000001) + :: %.y + :: Source + ++ isclose + |= [p=@rd r=@rd] + (lth (abs (sub p r)) rtol) + :: +allclose: [@rd (list @rd)] -> ? + :: + :: Returns the comparison of a floating-point atom to a list of floating- + :: point atoms, within a relative tolerance (provided by the +rd door). + :: Examples + :: > (allclose .~1 ~[.~1 .~2]) + :: %.n + :: > (allclose .~1 ~[.~1 .~1.0000001]) + :: %.n + :: > (~(allclose rd [%z .~1e-3]) .~1 ~[.~1 .~1.0000001]) + :: %.y + :: Source + ++ allclose + |= [p=@rd q=(list @rd)] + =/ i 0 + =/ n (lent q) + |- ^- ? + ?: =(n i) + %.y + ?. (isclose p (snag i q)) + %.n + $(i +(i)) + :: +isint: @rd -> ? + :: + :: Returns whether a floating-point value is an integer (no fractional part). + :: Examples + :: > (isint .~1) + :: %.y + :: > (isint .~1.1) + :: %.n + :: Source + ++ isint + |= x=@rd ^- ? + (equ x (san (need (toi x)))) + :: + :: Algebraic + :: + :: +add: [@rd @rd] -> @rd + :: + :: Returns the sum of two floating-point atoms. + :: Examples + :: > (add .~1 .~2) + :: .~3 + :: Source + ++ add add:^rd + :: +sub: [@rd @rd] -> @rd + :: + :: Returns the difference of two floating-point atoms. + :: Examples + :: > (sub .~1 .~2) + :: .~-1 + :: Source + ++ sub sub:^rd + :: +mul: [@rd @rd] -> @rd + :: + :: Returns the product of two floating-point atoms. + :: Examples + :: > (mul .~1 .~2) + :: .~2 + :: > (mul .~2 .~3) + :: .~6 + :: Source + ++ mul mul:^rd + :: +div: [@rd @rd] -> @rd + :: + :: Returns the quotient of two floating-point atoms. + :: Examples + :: > (div .~1 .~2) + :: .~0.5 + :: Source + ++ div div:^rd + :: +fma: [@rd @rd @rd] -> @rd + :: + :: Returns the fused multiply-add of three floating-point atoms. + :: Examples + :: > (fma .~1 .~2 .~3) + :: .~5 + :: > (fma .~2 .~3 .~4) + :: .~10 + :: Source + ++ fma fma:^rd + :: +sig: @rd -> ? + :: + :: Returns the sign of a floating-point atom. + :: Examples + :: > (sig .~1) + :: %.y + :: > (sig .~-1) + :: %.n + :: Source + ++ sig |=(x=@rd =(0 (rsh [0 63] x))) + :: +sgn: @rd -> ? + :: + :: Returns the sign of a floating-point atom. + :: Alias for +sig. + :: Examples + :: > (sgn .~1) + :: %.y + :: > (sgn .~-1) + :: %.n + :: Source + ++ sgn sig + :: +neg: @rd -> @rd + :: + :: Returns the negation of a floating-point atom. + :: Examples + :: > (neg .~1) + :: .~-1 + :: > (neg .~-1) + :: .~1 + :: Source + ++ neg |=(x=@rd (sub .~0 x)) + :: +factorial: @rd -> @rd + :: + :: Returns the factorial of a floating-point atom. Assumes integer input. + :: Examples + :: > (factorial .~1) + :: .~1 + :: > (factorial .~2) + :: .~2 + :: > (factorial .~3) + :: .~6 + :: Source + ++ factorial + |= x=@rd ^- @rd + ?> (gte x .~0) + =/ t=@rd .~1 + ?: (isclose x .~0) + t + |- ^- @rd + ?: (isclose x .~1) + t + $(x (sub x .~1), t (mul t x)) + :: +abs: @rd -> @rd + :: + :: Returns the absolute value of a floating-point atom. + :: Examples + :: > (abs .~1) + :: .~1 + :: > (abs .~-1) + :: .~1 + :: Source + ++ abs + |= x=@rd ^- @rd + ?:((sgn x) x (neg x)) + :: +exp: @rd -> @rd + :: + :: Returns the exponential of a floating-point atom. + :: Examples + :: > (exp .~1) + :: .~2.7182818284582266 + :: > (exp .~2) + :: .~7.389056098925858 + :: > (~(exp rd [%z .~1e-15]) .~2) + :: .~7.389056098930642 + :: > (exp .~inf) + :: .inf + :: Source + ++ exp + |= x=@rd ^- @rd + :: filter out non-finite arguments + ?: =(x 0x0) .~1 + :: check infinities + ?: =(x 0x7ff0.0000.0000.0000) `@rd`0x7ff0.0000.0000.0000 :: exp(+inf) -> inf + ?: =(x 0xfff0.0000.0000.0000) .~0.0 :: exp(-inf) -> 0 + :: check NaN + ?. (^gte (dis 0x7ff8.0000.0000.0000 x) 0) `@rd`0x7ff8.0000.0000.0000 :: exp(NaN) -> NaN + :: check overflow to infinity + =/ o-threshold `@rd`0x4086.2e42.fefa.39ef :: 709.782712893384, value above which exp(x) overflows + ?: (gth x o-threshold) (mul huge huge) + :: check underflow to zero + =/ u-threshold `@rd`0xc086.2e42.fefa.39ef :: -709.782712893384, value below which exp(x) underflows + ?: (lth x u-threshold) (mul tiny tiny) + :: otherwise, use Taylor series + =/ p .~1 + =/ po .~-1 + =/ i .~1 + |- ^- @rd + ?: (lth (abs (sub po p)) rtol) + p + $(i (add i .~1), p (add p (div (pow-n x i) (factorial i))), po p) + :: +sin: @rd -> @rd + :: + :: Returns the sine of a floating-point atom. + :: Examples + :: > (sin .~1) + :: .~0.8414709848078934 + :: > (sin .~2) + :: .~0.9092974268256406 + :: > (sin pi) + :: .~-1.698287706085482e-13 + :: Source + ++ sin + |= x=@rd ^- @rd + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7ff0.0000.0000.0000) `@rd`0x7ff8.0000.0000.0000 :: sin(+inf) -> NaN + ?: =(x 0xfff0.0000.0000.0000) `@rd`0x7ff8.0000.0000.0000 :: sin(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7ff8.0000.0000.0000 x) 0) `@rd`0x7ff8.0000.0000.0000 :: sin(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p x + =/ po .~-2 + =/ i 1 + =/ term x + |- ^- @rd + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (add i2 .~1)))) + $(i +(i), p (add p term), po p) + :: +cos: @rd -> @rd + :: + :: Returns the cosine of a floating-point atom. + :: Examples + :: > (cos .~1) + :: .~0.5403023058680917 + :: > (cos .~2) + :: .~-0.41614683654756957 + :: > (cos pi) + :: .~-1.0000000000013558 + :: Source + ++ cos + |= x=@rd ^- @rd + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7ff0.0000.0000.0000) `@rd`0x7ff8.0000.0000.0000 :: cos(+inf) -> NaN + ?: =(x 0xfff0.0000.0000.0000) `@rd`0x7ff8.0000.0000.0000 :: cos(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7ff8.0000.0000.0000 x) 0) `@rd`0x7ff8.0000.0000.0000 :: exp(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p .~1 + =/ po .~-2 + =/ i 1 + =/ term .~1 + |- ^- @rd + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (sub i2 .~1)))) + $(i +(i), p (add p term), po p) + :: +tan: @rd -> @rd + :: + :: Returns the tangent of a floating-point atom. + :: Examples + :: > (tan .~1) + :: .~1.5574077246550349 + :: > (tan .~2) + :: .~-2.185039863259177 + :: > (tan pi) + :: .~-2.6535896228476087e-6 + :: Source + ++ tan + |= x=@rd ^- @rd + (div (sin x) (cos x)) + :: +pow-n: [@rd @rd] -> @rd + :: + :: Returns the power of a floating-point atom to an integer exponent. + :: Examples + :: > (pow-n .1 .2) + :: .1 + :: > (pow-n .2 .2) + :: .4 + :: > (pow-n .2 .3) + :: .8 + :: Source + ++ pow-n + |= [x=@rd n=@rd] ^- @rd + ?: =(n .~0) .~1 + ?> &((gth n .~0) (isint n)) + =/ p x + |- ^- @rd + ?: (lth n .~2) + p + $(n (sub n .~1), p (mul p x)) + :: +log: @rd -> @rd + :: + :: Returns the natural logarithm of a floating-point atom. + :: Examples + :: > (log .~1) + :: .~0 + :: > (log .~2) + :: .~0.6931471805589156 + :: > (~(log rd [%z .~1e-15]) .~2) + :: .~0.693147180559944 + :: > (log .~inf) + :: .~inf + :: Source + ++ log + |= z=@rd ^- @rd + :: filter out non-finite arguments + :: check infinities + ?: =(z 0x7ff0.0000.0000.0000) `@rd`0x7ff0.0000.0000.0000 :: exp(+inf) -> inf + ?: =(z 0xfff0.0000.0000.0000) .~0.0 :: exp(-inf) -> 0 + :: check NaN + ?. (^gte (dis 0x7ff8.0000.0000.0000 z) 0) `@rd`0x7ff8.0000.0000.0000 :: exp(NaN) -> NaN + :: otherwise, use Taylor series + =/ p .~0 + =/ po .~-1 + =/ i .~0 + |- ^- @rd + ?: (lth (abs (sub po p)) rtol) + (mul (div (mul .~2 (sub z .~1)) (add z .~1)) p) + =/ term1 (div .~1 (add .~1 (mul .~2 i))) + =/ term2 (mul (sub z .~1) (sub z .~1)) + =/ term3 (mul (add z .~1) (add z .~1)) + =/ term (mul term1 (pow-n (div term2 term3) i)) + $(i (add i .~1), p (add p term), po p) + :: +log-10: @rd -> @rd + :: + :: Returns the base-10 logarithm of a floating-point atom. + :: Examples + :: > (log-10 .~0.1) + :: .~-0.9999999999082912 + :: > (log-10 .~2) + :: .~0.30102999566353394 + :: > (~(log-10 rd [%z .~1e-8]) .~2) + :: .~0.30102999562024696 + :: Source + ++ log-10 + |= z=@rd ^- @rd + (div (log z) log10) + :: +log-2: @rd -> @rd + :: + :: Returns the base-2 logarithm of a floating-point atom. + :: Examples + :: > (log-2 .0.1) + :: .~-3.321928094582713 + :: > (log-2 .2) + :: .~0.9999999999985144 + :: > (~(log-2 rs [%z .1e-8]) .2) + :: .~0.9999999998547181 + :: Source + ++ log-2 + |= z=@rd ^- @rd + (div (log z) log2) + :: +pow: [@rd @rd] -> @rd + :: + :: Returns the power of a floating-point atom to a floating-point exponent. + :: Examples + :: > (pow .~1 .~2) + :: .~1 + :: > (pow .~2 .~2) + :: .~4 + :: > (pow .~2 .~3.5) + :: .~11.313708498941306 + :: > (~(pow rd [%z .~1e-15]) .~2 .~3.5) + :: .~11.313708498984685 + :: Source + ++ pow + |= [x=@rd n=@rd] ^- @rd + :: fall through on integers (faster) + ?: =(n (san (need (toi n)))) (pow-n x (san (need (toi n)))) + (exp (mul n (log x))) + :: +sqrt: @rd -> @rd + :: + :: Returns the square root of a floating-point atom. + :: Alias for +sqt. + :: Examples + :: > (sqrt .~1) + :: .~1 + :: > (sqrt .~2) + :: .~1.4142135623721421 + :: > (~(sqrt rd [%z .~1e-15]) .~2) + :: .~1.4142135623730923 + :: Source + ++ sqrt sqt + :: +sqt: @rd -> @rd + :: + :: Returns the square root of a floating-point atom. + :: Examples + :: > (sqt .~1) + :: .~1 + :: > (sqt .~2) + :: .~1.4142135623721421 + :: > (~(sqt rd [%z .~1e-15]) .~2) + :: .~1.4142135623730923 + :: Source + ++ sqt + |= x=@rd ^- @rd + ?> (sgn x) + (pow x .~0.5) + :: +cbrt: @rd -> @rd + :: + :: Returns the cube root of a floating-point atom. + :: Alias for +cbt. + :: Examples + :: > (cbrt .~1) + :: .~1 + :: > (cbrt .~2) + :: .~1.2599210498943176 + :: > (~(cbrt rd [%z .~1e-15]) .~2) + :: .~1.2599210498948716 + :: Source + ++ cbrt cbt + :: +cbt: @rd -> @rd + :: + :: Returns the cube root of a floating-point atom. + :: Examples + :: > (cbt .~1) + :: .~1 + :: > (cbt .~2) + :: .~1.2599210498943176 + :: > (~(cbt rd [%z .~1e-15]) .~2) + :: .~1.2599210498948716 + :: Source + ++ cbt + |= x=@rd ^- @rd + ?> (sgn x) + (pow x .~0.3333333333333333) + :: +arg: @rd -> @rd + :: + :: Returns the argument of a floating-point atom (real argument = absolute + :: value). + :: Examples + :: > (arg .~1) + :: .~1 + :: > (arg .~-1) + :: .~1 + :: Source + ++ arg abs + :: +round: [@rs @ud] -> @rs + :: + :: Returns the floating-point atom rounded to a given number of decimal + :: places. + :: Examples + :: > (round .1 0) + :: .1 + :: > (round .1.11 1) + :: .1.1 + :: > (round .1.11 2) + :: .1.11 + :: > (round .1.11 3) + :: .1.11 + :: Source + ++ round + |= [x=@rd n=@ud] ^- @rd + ?: =(.~0 x) .~0 + :: Calculate the order of magnitude. + =/ oom (san (need (toi (log-10 (abs x))))) + :: Calculate the scaling factor. + =/ scaling (pow .~10 :(sub (sun n) oom .~1)) + :: Round the mantissa to desired significant digits. + =/ rnd-mantissa (round-bankers (mul x scaling)) + :: Convert back to the original scale. + (div rnd-mantissa scaling) + :: +round-places: [@rs @ud] -> @rs + :: + :: Returns the floating-point atom rounded to a given number of decimal + :: places. This is exceptionally sensitive to off-by-one FP rounding error. + :: Examples + :: > (round-places .1 0) + :: .1 + :: > (round-places .1.11 1) + :: .1.1 + :: > (round-places .1.285 2) + :: .1.28 + :: > (round-places .4.12345 3) + :: .4.1229997 + :: Source + ++ round-places + |= [x=@rd n=@ud] ^- @rd + :: Calculate the scaling factor. + =/ scaling (pow .~10 (sun n)) + :: Scale the number. + =/ scaled (mul x scaling) + :: Round the mantissa to desired significant digits. + =/ rnd-mantissa (round-bankers scaled) + :: Convert back to the original scale. + (div rnd-mantissa scaling) + :: +round-bankers: @rs -> @rs + :: + :: Returns the floating-point atom rounded to the nearest integer, with + :: ties rounded to the nearest even integer. + :: Examples + :: > (round-bankers .1) + :: .1 + :: > (round-bankers .1.5) + :: .2 + :: > (round-bankers .1.49) + :: .1 + :: Source + ++ round-bankers + |= x=@rd ^- @rd + =/ int (san (need (toi x))) + =/ dcm (sub x int) + ?: (lth dcm .~0.5) + int + (add int .~1) + -- +:: half precision +++ rh + ^| + |_ $: r=$?(%n %u %d %z) :: round nearest, up, down, to zero + rtol=_.~~1e-2 :: relative tolerance for precision of operations + == + :: mathematics constants to half precision + :: +tau: @rh + :: + :: Returns the value 2*pi (OEIS A019692). + :: Examples + :: > tau + :: .~~6.28 + :: Source + ++ tau .~~6.28 + :: +pi: @rh + :: + :: Returns the value pi (OEIS A000796). + :: Examples + :: > pi + :: .~~3.14 + :: Source + ++ pi .~~3.14 + :: +e: @rh + :: + :: Returns the value e (Euler's constant) (OEIS A001113). + :: Examples + :: > e + :: .~~2.72 + :: Source + ++ e .~~2.719 + :: +phi: @rh + :: + :: Returns the value phi (golden ratio) (OEIS A001622). + :: Examples + :: > phi + :: .~~1.62 + :: Source + ++ phi .~~1.618 + :: +sqt2: @rh + :: + :: Returns the value sqrt(2) (OEIS A002193). + :: Examples + :: > sqt2 + :: .~~1.414 + :: Source + ++ sqt2 .~~1.414 + :: +invsqt2: @rh + :: + :: Returns the value 1/sqrt(2) (OEIS A010503). + :: Examples + :: > invsqt2 + :: .~~0.707 + :: Source + ++ invsqt2 .~~0.707 + :: +log2: @rh + :: + :: Returns the value log(2) (OEIS A002162). + :: Examples + :: > log2 + :: .~~0.693 + :: Source + ++ log2 .~~0.6934 + :: +invlog2: @rh + :: + :: Returns the value 1/log(2). + :: Examples + :: > invlog2 + :: .~~1.443 + :: Source + ++ invlog2 .~~1.443 + :: +log10: @rh + :: + :: Returns the value log(10) (OEIS A002392). + :: Examples + :: > log10 + :: .~~2.303 + :: Source + ++ log10 .~~2.303 + :: +huge: @rh + :: + :: Returns the value of the largest representable number. + :: Examples + :: > huge + :: .~~6.55e+04 + :: Source + ++ huge `@rh`0x7bff :: 6.55e+04 + :: +tiny: @rh + :: + :: Returns the value of the smallest representable normal number. + :: Examples + :: > tiny + :: .~~6.10e-05 + :: Source + ++ tiny `@rh`0x1 :: 6e-08 + :: + :: Operations + :: + :: +sea: @rh -> fn + :: + :: Returns the +$fn representation of a floating-point atom. + :: Examples + :: > (sea .~~1) + :: [%f s=%.y e=-10 a=1.024] + :: > (sea .~~1.1) + :: [%f s=%.y e=-10 a=1.126] + :: Source + ++ sea sea:^rh + :: +bit: fn -> @rh + :: + :: Returns the floating-point atom of a +$fn representation. + :: Examples + :: > (bit [%f s=%.y e=-10 a=1.024]) + :: .~~1 + :: > (bit [%f s=%.y e=-10 a=1.126]) + :: .~~1.1 + :: Source + ++ bit bit:^rh + :: +sun: @ud -> @rh + :: + :: Returns the floating-point atom of an unsigned integer atom. + :: Examples + :: > (sun 1) + :: .~~1 + :: > (sun 1.000) + :: .~~1e3 + :: Source + ++ sun sun:^rh + :: +san: @sd -> @rh + :: + :: Returns the floating-point atom of a signed integer atom. + :: Examples + :: > (san --1) + :: .~~1 + :: > (san -1) + :: .~-1 + :: Source + ++ san san:^rh + ::++ exp exp:^rh :: no pass-through because of exp function + :: +toi: @rh -> @sd + :: + :: Returns the unitized signed integer atom of a rounded floating-point atom. + :: Examples + :: > (toi .~~1) + :: [~ --1] + :: > (toi .~~1.1) + :: [~ --1] + :: Source + ++ toi toi:^rh + :: +drg: @rh -> dn + :: + :: Returns the decimal form of a floating-point atom using the Dragon4 + :: algorithm. + :: Examples + :: > (drg .~~1) + :: [%d s=%.y e=--0 a=1] + :: > (drg .~~1.1) + :: [%d s=%.y e=-1 a=11] + :: Source + ++ drg drg:^rh + :: +grd: dn -> @rh + :: + :: Returns the floating-point atom of a decimal form. + :: Examples + :: > (grd [%d s=%.y e=--0 a=1]) + :: .~~1 + :: > (grd [%d s=%.y e=-1 a=11]) + :: .~~1.1 + :: Source + ++ grd grd:^rh + :: + :: Comparison + :: + :: +lth: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than. + :: Examples + :: > (lth .~~1 .~~2) + :: %.y + :: > (lth .~~2 .~~1) + :: %.n + :: > (lth .~~1 .~~1) + :: %.n + :: Source + ++ lth lth:^rh + :: +lte: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Examples + :: > (lte .~~1 .~~2) + :: %.y + :: > (lte .~~2 .~~1) + :: %.n + :: > (lte .~~1 .~~1) + :: %.y + :: Source + ++ lte lte:^rh + :: +leq: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Alias for +lte. + :: Examples + :: > (leq .~~1 .~~2) + :: %.y + :: > (leq .~~2 .~~1) + :: %.n + :: > (leq .~~1 .~~1) + :: %.y + :: Source + ++ leq lte:^rh + :: +equ: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, equal to. + :: Examples + :: > (equ .~~1 .~~2) + :: %.n + :: > (equ .~~2 .~~1) + :: %.n + :: > (equ .~~1 .~~1) + :: %.y + :: Source + ++ equ equ:^rh + :: +gth: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than. + :: Examples + :: > (gth .~~1 .~~2) + :: %.n + :: > (gth .~~2 .~~1) + :: %.y + :: > (gth .~~1 .~~1) + :: %.n + :: Source + ++ gth gth:^rh + :: +gte: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Examples + :: > (gte .~~1 .~~2) + :: %.n + :: > (gte .~~2 .~~1) + :: %.y + :: > (gte .~~1 .~~1) + :: %.y + :: Source + ++ gte gte:^rh + :: +geq: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Alias for +gte. + :: Examples + :: > (geq .~~1 .~~2) + :: %.n + :: > (geq .~~2 .~~1) + :: %.y + :: > (geq .~~1 .~~1) + :: %.y + :: Source + ++ geq gte:^rh + :: +neq: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, not equal to. + :: Examples + :: > (neq .~~1 .~~2) + :: %.y + :: > (neq .~~2 .~~1) + :: %.y + :: > (neq .~~1 .~~1) + :: %.n + :: Source + ++ neq |=([a=@rh b=@rh] ^-(? !(equ:^rh a b))) + :: +isclose: [@rh @rh] -> ? + :: + :: Returns the comparison of two floating-point atoms, within a relative + :: tolerance (provided by the +rh door). + :: Examples + :: > (isclose .~~1 .~~2) + :: %.n + :: > (isclose .~~1 .~~1.0000001) + :: %.n + :: > (~(isclose rh [%z .~~1e-3]) .~~1 .~~1.0001) + :: %.y + :: Source + ++ isclose + |= [p=@rh r=@rh] + (lth (abs (sub p r)) rtol) + :: +allclose: [@rh (list @rh)] -> ? + :: + :: Returns the comparison of a floating-point atom to a list of floating- + :: point atoms, within a relative tolerance (provided by the +rh door). + :: Examples + :: > (allclose .~~1 ~[.~~1 .~~2]) + :: %.n + :: > (allclose .~~1 ~[.~~1 .~~1.0000001]) + :: %.n + :: > (~(allclose rh [%z .~~1e-3]) .~~1 ~[.~~1 .~~1.0001]) + :: %.y + :: Source + ++ allclose + |= [p=@rh q=(list @rh)] + =/ i 0 + =/ n (lent q) + |- ^- ? + ?: =(n i) + %.y + ?. (isclose p (snag i q)) + %.n + $(i +(i)) + :: +isint: @rh -> ? + :: + :: Returns whether a floating-point value is an integer (no fractional part). + :: Examples + :: > (isint .~~1) + :: %.y + :: > (isint .~~1.1) + :: %.n + :: Source + ++ isint + |= x=@rh ^- ? + (equ x (san (need (toi x)))) + :: + :: Algebraic + :: + :: +add: [@rh @rh] -> @rh + :: + :: Returns the sum of two floating-point atoms. + :: Examples + :: > (add .~~1 .~~2) + :: .~~3 + :: Source + ++ add add:^rh + :: +sub: [@rh @rh] -> @rh + :: + :: Returns the difference of two floating-point atoms. + :: Examples + :: > (sub .~~1 .~~2) + :: .~~-1 + :: Source + ++ sub sub:^rh + :: +mul: [@rh @rh] -> @rh + :: + :: Returns the product of two floating-point atoms. + :: Examples + :: > (mul .~~1 .~~2) + :: .~~2 + :: Source + ++ mul mul:^rh + :: +div: [@rh @rh] -> @rh + :: + :: Returns the quotient of two floating-point atoms. + :: Examples + :: > (div .~~1 .~~2) + :: .~~0.5 + :: Source + ++ div div:^rh + :: +fma: [@rh @rh @rh] -> @rh + :: + :: Returns the fused multiply-add of three floating-point atoms. + :: Examples + :: > (fma .~~1 .~~2 .~~3) + :: .~~5 + :: > (fma .~~2 .~~3 .~~4) + :: .~~10 + :: Source + ++ fma fma:^rh + :: +sig: @rh -> ? + :: + :: Returns the sign of a floating-point atom. + :: Examples + :: > (sig .~~1) + :: %.y + :: > (sig .~~-1) + :: %.n + :: Source + ++ sig |=(x=@rh =(0 (rsh [0 15] x))) + :: +sgn: @rh -> ? + :: + :: Returns the sign of a floating-point atom. + :: Alias for +sig. + :: Examples + :: > (sgn .~~1) + :: %.y + :: > (sgn .~~-1) + :: %.n + :: Source + ++ sgn sig + :: +neg: @rh -> @rh + :: + :: Returns the negation of a floating-point atom. + :: Examples + :: > (neg .~~1) + :: .~~-1 + :: > (neg .~~-1) + :: .~~1 + :: Source + ++ neg |=(x=@rh (sub .~~0 x)) + :: +factorial: @rh -> @rh + :: + :: Returns the factorial of a floating-point atom. Assumes integer input. + :: Examples + :: > (factorial .~~1) + :: .~~1 + :: > (factorial .~~2) + :: .~~2 + :: > (factorial .~~3) + :: .~~6 + :: Source + ++ factorial + |= x=@rh ^- @rh + ?> (gte x .~~0) + =/ t=@rh .~~1 + ?: (isclose x .~~0) + t + |- ^- @rh + ?: (isclose x .~~1) + t + $(x (sub x .~~1), t (mul t x)) + :: +abs: @rh -> @rh + :: + :: Returns the absolute value of a floating-point atom. + :: Examples + :: > (abs .~~1) + :: .~~1 + :: > (abs .~~-1) + :: .~~1 + :: Source + ++ abs + |= x=@rh ^- @rh + ?:((sgn x) x (neg x)) + :: +exp: @rh -> @rh + :: + :: Returns the exponential of a floating-point atom. + :: Examples + :: > (exp .~~1) + :: .~~2.715 + :: > (exp .~~2) + :: .~~7.375 + :: > (~(exp rh [%z .~~1e-1]) .~~2) + :: .~~7.348 + :: > (exp .~~inf) + :: .inf + :: Source + ++ exp + |= x=@rh ^- @rh + :: filter out non-finite arguments + ?: =(x 0x0) .~~1 + :: check infinities + ?: =(x 0x7c00) `@rh`0x7c00 :: exp(+inf) -> inf + ?: =(x 0xfc00) .~~0.0 :: exp(-inf) -> 0 + :: check NaN + ?. (^gte (dis 0x7e00 x) 0) `@rh`0x7e00 :: exp(NaN) -> NaN + :: check overflow to infinity + =/ o-threshold `@rh`0x498c :: 11.091265424003277, value above which exp(x) overflows + ?: (gth x o-threshold) (mul huge huge) + :: check underflow to zero + =/ u-threshold `@rh`0xc98c :: -11.091265424003277, value below which exp(x) underflows + ?: (lth x u-threshold) (mul tiny tiny) + :: otherwise, use Taylor series + =/ p .~~1 + =/ po .~~-1 + =/ i .~~1 + |- ^- @rh + ?: (lth (abs (sub po p)) rtol) + p + $(i (add i .~~1), p (add p (div (pow-n x i) (factorial i))), po p) + :: +sin: @rh -> @rh + :: + :: Returns the sine of a floating-point atom. + :: Examples + :: > (sin .~~1) + :: .~~0.8413 + :: > (sin .~~2) + :: .~~0.9087 + :: > (sin pi) + :: .~~3.437e-3 + :: Source + ++ sin + |= x=@rh ^- @rh + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7c00) `@rh`0x7e00 :: sin(+inf) -> NaN + ?: =(x 0xfc00) `@rh`0x7e00 :: sin(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7e00 x) 0) `@rh`0x7e00 :: sin(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p x + =/ po .~~-2 + =/ i 1 + =/ term x + |- ^- @rh + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (add i2 .~~1)))) + $(i +(i), p (add p term), po p) + :: +cos: @rh -> @rh + :: + :: Returns the cosine of a floating-point atom. + :: Examples + :: > (cos .~~1) + :: .~~0.54 + :: > (cos .~~2) + :: .~~-0.4158 + :: > (cos pi) + :: .~~-1.001 + :: Source + ++ cos + |= x=@rh ^- @rh + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7c00) `@rh`0x7e00 :: cos(+inf) -> NaN + ?: =(x 0xfc00) `@rh`0x7e00 :: cos(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7e00 x) 0) `@rh`0x7e00 :: cos(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p .~~1 + =/ po .~~-2 + =/ i 1 + =/ term .~~1 + |- ^- @rh + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (sub i2 .~~1)))) + $(i +(i), p (add p term), po p) + :: +tan: @rh -> @rh + :: + :: Returns the tangent of a floating-point atom. + :: Examples + :: > (tan .~~1) + :: .~~1.558 + :: > (tan .~~2) + :: .~~-2.186 + :: > (tan pi) + :: .~~-3.433e-3 + :: Source + ++ tan + |= x=@rh ^- @rh + (div (sin x) (cos x)) + :: +pow-n: [@rh @rh] -> @rh + :: + :: Returns the power of a floating-point atom to an integer exponent. + :: Examples + :: > (pow-n .~~1 .~~2) + :: .~~1 + :: > (pow-n .~~2 .~~2) + :: .~~4 + :: > (pow-n .~~2 .~~3) + :: .~~8 + :: Source + ++ pow-n + |= [x=@rh n=@rh] ^- @rh + ?: =(n .~~0) .~~1 + ?> &((gth n .~~0) (isint n)) + =/ p x + |- ^- @rh + ?: (lth n .~~2) + p + $(n (sub n .~~1), p (mul p x)) + :: +log: @rh -> @rh + :: + :: Returns the natural logarithm of a floating-point atom. + :: Examples + :: > (log .~~1) + :: .~~0 + :: > (log .~~2) + :: .~~0.6914 + :: > (~(log rh [%z .~~1e-1]) .~~2) + :: .~~0.6904 + ++ log + |= z=@rh ^- @rh + :: filter out non-finite arguments + :: check infinities + ?: =(z 0x7c00) `@rh`0x7c00 :: exp(+inf) -> inf + ?: =(z 0xfc00) .~~0.0 :: exp(-inf) -> 0 + :: check NaN + ?. (^gte (dis 0x7e00 z) 0) `@rh`0x7e00 :: exp(NaN) -> NaN + :: otherwise, use Taylor series + =/ p .~~0 + =/ po .~~-1 + =/ i .~~0 + |- ^- @rh + ?: (lth (abs (sub po p)) rtol) + (mul (div (mul .~~2 (sub z .~~1)) (add z .~~1)) p) + =/ term1 (div .~~1 (add .~~1 (mul .~~2 i))) + =/ term2 (mul (sub z .~~1) (sub z .~~1)) + =/ term3 (mul (add z .~~1) (add z .~~1)) + =/ term (mul term1 (pow-n (div term2 term3) i)) + $(i (add i .~~1), p (add p term), po p) + :: +pow: [@rh @rh] -> @rh + :: + :: Returns the power of a floating-point atom to a floating-point exponent. + :: Examples + :: > (pow .~~1 .~~2) + :: .~~1 + :: > (pow .~~2 .~~2) + :: .~~4 + :: > (~(pow rh:math [%z .~~1e-1]) .~~2 .~~3.5) + :: .~~11.14 + :: Source + ++ pow + |= [x=@rh n=@rh] ^- @rh + :: fall through on integers (faster) + ?: =(n (san (need (toi n)))) (pow-n x (san (need (toi n)))) + (exp (mul n (log x))) + :: +sqrt: @rh -> @rh + :: + :: Returns the square root of a floating-point atom. + :: Alias for +sqt. + :: Examples + :: > (sqrt .~~1) + :: .~~1 + :: > (sqrt .~~2) + :: .~~1.412 + :: > (~(sqrt rh [%z .~~1e-1]) .~~2) + :: .~~1.404 + :: Source + ++ sqrt sqt + :: +sqt: @rh -> @rh + :: + :: Returns the square root of a floating-point atom. + :: Examples + :: > (sqt .~~1) + :: .~~1 + :: > (sqt .~~2) + :: .~~1.412 + :: > (~(sqt rh [%z .~~1e-1]) .~~2) + :: .~~1.404 + :: Source + ++ sqt + |= x=@rh ^- @rh + ?> (sgn x) + (pow x .~~0.5) + :: +cbrt: @rh -> @rh + :: + :: Returns the cube root of a floating-point atom. + :: Alias for +cbt. + :: Examples + :: > (cbrt .~~1) + :: .~~1 + :: > (cbrt .~~2) + :: .~~1.258 + :: > (~(cbrt rh [%z .~~1e-1]) .~~2) + :: .~~1.256 + :: Source + ++ cbrt cbt + :: +cbt: @rh -> @rh + :: + :: Returns the cube root of a floating-point atom. + :: Examples + :: > (cbt .~~1) + :: .~~1 + :: > (cbt .~~2) + :: .~~1.258 + :: > (~(cbt rh [%z .~~1e-1]) .~~2) + :: .~~1.256 + :: Source + ++ cbt + |= x=@rh ^- @rh + ?> (sgn x) + (pow x .~~0.3333) + :: +arg: @rh -> @rh + :: + :: Returns the argument of a floating-point atom (real argument = absolute + :: value). + :: Examples + :: > (arg .~~1) + :: .~~1 + :: > (arg .~-1) + :: .~~1 + :: Source + ++ arg abs + -- +:: quad precision +++ rq + ^| + |_ $: r=$?(%n %u %d %z) :: round nearest, up, down, to zero + rtol=_.~~~1e-20 :: relative tolerance for precision of operations + == + :: mathematics constants to quad precision + :: +tau: @rq + :: + :: Returns the value 2*pi (OEIS A019692). + :: Examples + :: > tau + :: .~~~6.2831853071795864769252867665590056 + :: Source + ++ tau .~~~6.2831853071795864769252867665590056 + :: +pi: @rq + :: + :: Returns the value pi (OEIS A000796). + :: Examples + :: > pi + :: .~~~3.1415926535897932384626433832795028 + :: Source + ++ pi .~~~3.1415926535897932384626433832795028 + :: +e: @rq + :: + :: Returns the value e (Euler's constant) (OEIS A001113). + :: Examples + :: > e + :: .~~~2.7182818284590452353602874713526623 + :: Source + ++ e .~~~2.7182818284590452353602874713526623 + :: +phi: @rq + :: + :: Returns the value phi (golden ratio) (OEIS A001622). + :: Examples + :: > phi + :: .~~~1.6180339887498948482045868343656382 + :: Source + ++ phi .~~~1.6180339887498948482045868343656382 + :: +sqt2: @rq + :: + :: Returns the value sqrt(2) (OEIS A002193). + :: Examples + :: > sqt2 + :: .~~~1.414213562373095048801688724209698 + :: Source + ++ sqt2 .~~~1.414213562373095048801688724209698 + :: +invsqt2: @rq + :: + :: Returns the value 1/sqrt(2) (OEIS A010503). + :: Examples + :: > invsqt2 + :: .~~~0.707106781186547524400844362104849 + :: Source + ++ invsqt2 .~~~0.707106781186547524400844362104849 + :: +log2: @rq + :: + :: Returns the value log(2) (OEIS A002162). + :: Examples + :: > log2 + :: .~~~0.6931471805599453094172321214581766 + :: Source + ++ log2 .~~~0.6931471805599453094172321214581766 + :: +invlog2: @rq + :: + :: Returns the value 1/log(2). + :: Examples + :: > invlog2 + :: .~~~1.442695040888963387004650940070860 + :: Source + ++ invlog2 .~~~1.442695040888963387004650940070860 :: TODO check + :: +log10: @rq + :: + :: Returns the value log(10) (OEIS A002392). + :: Examples + :: > log10 + :: .~~~2.302585092994045684017991454684364 + :: Source + ++ log10 .~~~2.302585092994045684017991454684364 + :: +huge: @rq + :: + :: Returns the value of the largest representable number. + :: Examples + :: > huge + :: .~~~1.189731495357231765085759326628007e4932 + :: Source + ++ huge `@rq`0x7ffe.ffff.ffff.ffff.ffff.ffff.ffff.ffff.ffff :: 1.18973149535723176508575932662800702e4932 + :: +tiny: @rq + :: + :: Returns the value of the smallest representable normal number. + :: Examples + :: > tiny + :: .~~~3.3621031431120935062626778173217526e-4932 + :: Source + ++ tiny `@rq`0x1.0000.0000.0000.0000.0000.0000.0000.0000 :: 3.36210314311209350626267781732175260e-4932 + :: + :: Operations + :: + :: +sea: @rq -> fn + :: + :: Returns the +$fn representation of a floating-point atom. + :: Examples + :: > (sea .~~~1) + :: [%f s=%.y e=-112 a=5.192.296.858.534.827.628.530.496.329.220.096] + :: > (sea .~~~1.1) + :: [%f s=%.y e=-112 a=5.711.526.544.388.310.391.383.545.962.142.106] + :: Source + ++ sea sea:^rq + :: +bit: fn -> @rq + :: + :: Returns the floating-point atom of a +$fn representation. + :: Examples + :: > (bit [%f s=%.y e=-112 a=5.192.296.858.534.827.628.530.496.329.220.096]) + :: .~~~1 + :: > (bit [%f s=%.y e=-112 a=5.711.526.544.388.310.391.383.545.962.142.106]) + :: .~~~1.1 + :: Source + ++ bit bit:^rq + :: +sun: @ud -> @rq + :: + :: Returns the floating-point atom of an unsigned integer atom. + :: Examples + :: > (sun 1) + :: .~~~1 + :: > (sun 1.000) + :: .~~~1e3 + :: Source + ++ sun sun:^rq + :: +san: @sd -> @rq + :: + :: Returns the floating-point atom of a signed integer atom. + :: Examples + :: > (san --1) + :: .~~~1 + :: > (san -1) + :: .~~~-1 + :: Source + ++ san san:^rq + ::++ exp exp:^rq :: no pass-through because of exp function + :: +toi: @rq -> @sd + :: + :: Returns the unitized signed integer atom of a rounded floating-point atom. + :: Examples + :: > (toi .~~~1) + :: [~ --1] + :: > (toi .~~~1.1) + :: [~ --1] + :: Source + ++ toi toi:^rq + :: +drg: @rq -> dn + :: + :: Returns the decimal form of a floating-point atom using the Dragon4 + :: algorithm. + :: Examples + :: > (drg .~~~1) + :: [%d s=%.y e=--0 a=1] + :: > (drg .~~~1.1) + :: [%d s=%.y e=-1 a=11] + :: Source + ++ drg drg:^rq + :: +grd: dn -> @rq + :: + :: Returns the floating-point atom of a decimal form. + :: Examples + :: > (grd [%d s=%.y e=--0 a=1]) + :: .~~~1 + :: > (grd [%d s=%.y e=-1 a=11]) + :: .~~~1.1 + :: Source + ++ grd grd:^rq + :: + :: Comparison + :: + :: +lth: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than. + :: Examples + :: > (lth .~~~1 .~~~2) + :: %.y + :: > (lth .~~~2 .~~~1) + :: %.n + :: > (lth .~~~1 .~~~1) + :: %.n + :: Source + ++ lth lth:^rq + :: +lte: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Examples + :: > (lte .~~~1 .~~~2) + :: %.y + :: > (lte .~~~2 .~~~1) + :: %.n + :: > (lte .~~~1 .~~~1) + :: %.y + :: Source + ++ lte lte:^rq + :: +leq: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, less than or equal to. + :: Alias for +lte. + :: Examples + :: > (leq .~~~1 .~~~2) + :: %.y + :: > (leq .~~~2 .~~~1) + :: %.n + :: > (leq .~~~1 .~~~1) + :: %.y + :: Source + ++ leq lte:^rq + :: +equ: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, equal to. + :: Examples + :: > (equ .~~~1 .~~~2) + :: %.n + :: > (equ .~~~2 .~~~1) + :: %.n + :: > (equ .~~~1 .~~~1) + :: %.y + :: Source + ++ equ equ:^rq + :: +gth: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than. + :: Examples + :: > (gth .~~~1 .~~~2) + :: %.n + :: > (gth .~~~2 .~~~1) + :: %.y + :: > (gth .~~~1 .~~~1) + :: %.n + :: Source + ++ gth gth:^rq + :: +gte: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Examples + :: > (gte .~~~1 .~~~2) + :: %.n + :: > (gte .~~~2 .~~~1) + :: %.y + :: > (gte .~~~1 .~~~1) + :: %.y + :: Source + ++ gte gte:^rq + :: +geq: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, greater than or equal to. + :: Alias for +gte. + :: Examples + :: > (geq .~~~1 .~~~2) + :: %.n + :: > (geq .~~~2 .~~~1) + :: %.y + :: > (geq .~~~1 .~~~1) + :: %.y + :: Source + ++ geq gte:^rq + :: +neq: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, not equal to. + :: Examples + :: > (neq .~~~1 .~~~2) + :: %.y + :: > (neq .~~~2 .~~~1) + :: %.y + :: > (neq .~~~1 .~~~1) + :: %.n + :: Source + ++ neq |=([a=@rq b=@rq] ^-(? !(equ:^rq a b))) + :: +isclose: [@rq @rq] -> ? + :: + :: Returns the comparison of two floating-point atoms, within a relative + :: tolerance (provided by the +rq door). + :: Examples + :: > (isclose .~~~1 .~~~2) + :: %.n + :: > (isclose .~~~1 .~~~1.0000001) + :: %.n + :: > (~(isclose rq [%z .~~~1e-3]) .~~~1 .~~~1.0001) + :: %.y + :: > (~(isclose rq [%z .~~~1e-30]) .~~~1 .~~~1.0001) + :: %.n + :: Source + ++ isclose + |= [p=@rq r=@rq] + (lth (abs (sub p r)) rtol) + :: +allclose: [@rq (list @rq)] -> ? + :: + :: Returns the comparison of a floating-point atom to a list of floating- + :: point atoms, within a relative tolerance (provided by the +rq door). + :: Examples + :: > (allclose .~~~1 ~[.~~~1 .~~~2]) + :: %.n + :: > (allclose .~~~1 ~[.~~~1 .~~~1.0000001]) + :: %.n + :: > (~(allclose rq [%z .~~~1e-3]) .~~~1 ~[.~~~1 .~~~1.0001]) + :: %.y + :: Source + ++ allclose + |= [p=@rq q=(list @rq)] + =/ i 0 + =/ n (lent q) + |- ^- ? + ?: =(n i) + %.y + ?. (isclose p (snag i q)) + %.n + $(i +(i)) + :: +isint: @rq -> ? + :: + :: Returns whether a floating-point value is an integer (no fractional part). + :: Examples + :: > (isint .~~~1) + :: %.y + :: > (isint .~~~1.1) + :: %.n + :: Source + ++ isint + |= x=@rq ^- ? + (equ x (san (need (toi x)))) + :: + :: Algebraic + :: + :: +add: [@rq @rq] -> @rq + :: + :: Returns the sum of two floating-point atoms. + :: Examples + :: > (add .~~~1 .~~~2) + :: .~~~3 + :: Source + ++ add add:^rq + :: +sub: [@rq @rq] -> @rq + :: + :: Returns the difference of two floating-point atoms. + :: Examples + :: > (sub .~~~1 .~~~2) + :: .~~~-1 + :: Source + ++ sub sub:^rq + :: +mul: [@rq @rq] -> @rq + :: + :: Returns the product of two floating-point atoms. + :: Examples + :: > (mul .~~~1 .~~~2) + :: .~~~2 + :: Source + ++ mul mul:^rq + :: +div: [@rq @rq] -> @rq + :: + :: Returns the quotient of two floating-point atoms. + :: Examples + :: > (div .~~~1 .~~~2) + :: .~~~0.5 + :: Source + ++ div div:^rq + :: +fma: [@rq @rq @rq] -> @rq + :: + :: Returns the fused multiply-add of three floating-point atoms. + :: Examples + :: > (fma .~~~1 .~~~2 .~~~3) + :: .~~~5 + :: > (fma .~~~2 .~~~3 .~~~4) + :: .~~~10 + :: Source + ++ fma fma:^rq + :: +sig: @rq -> ? + :: + :: Returns the sign of a floating-point atom. + :: Examples + :: > (sig .~~~1) + :: %.y + :: > (sig .~~~-1) + :: %.n + :: Source + ++ sig |=(x=@rq =(0 (rsh [0 127] x))) + :: +sgn: @rq -> ? + :: + :: Returns the sign of a floating-point atom. + :: Alias for +sig. + :: Examples + :: > (sgn .~~~1) + :: %.y + :: > (sgn .~~~-1) + :: %.n + :: Source + ++ sgn sig + :: +neg: @rq -> @rq + :: + :: Returns the negation of a floating-point atom. + :: Examples + :: > (neg .~~~1) + :: .~~~-1 + :: > (neg .~~~-1) + :: .~~~1 + :: Source + ++ neg |=(x=@rq (sub .~~~0 x)) + :: +factorial: @rq -> @rq + :: + :: Returns the factorial of a floating-point atom. Assumes integer input. + :: Examples + :: > (factorial .~~~1) + :: .~~~1 + :: > (factorial .~~~2) + :: .~~~2 + :: > (factorial .~~~3) + :: .~~~6 + :: Source + ++ factorial + |= x=@rq ^- @rq + ?> (gte x .~~~0) + =/ t=@rq .~~~1 + ?: (isclose x .~~~0) + t + |- ^- @rq + ?: (isclose x .~~~1) + t + $(x (sub x .~~~1), t (mul t x)) + :: +abs: @rq -> @rq + :: + :: Returns the absolute value of a floating-point atom. + :: Examples + :: > (abs .~~~1) + :: .~~~1 + :: > (abs .~~~-1) + :: .~~~1 + :: Source + ++ abs + |= x=@rq ^- @rq + ?:((sgn x) x (neg x)) + :: +exp: @rq -> @rq + :: + :: Returns the exponential of a floating-point atom. + :: Examples + :: > (exp .~~~1) + :: .~~~2.7182818284590452353602471108690483 + :: > (exp .~~~2) + :: .~~~7.389056098930650227230362414146335 + :: > (~(exp rq [%z .~~~1e-20]) .~~~2) + :: .~~~7.389056098930650227230362414146335 + :: > (exp .~~~inf) + :: .~~~inf + :: Source + ++ exp + |= x=@rq ^- @rq + :: filter out non-finite arguments + ?: =(x 0x0) .~~~1 + :: check infinities + ?: =(x 0x7fff.0000.0000.0000.0000.0000.0000.0000) `@rq`0x7fff.0000.0000.0000.0000.0000.0000.0000 :: exp(+inf) -> inf + ?: =(x 0xffff.0000.0000.0000.0000.0000.0000.0000) .~~~0.0 :: exp(-inf) -> 0 + :: check NaN + ?. (^gte (dis 0x7fff.8000.0000.0000.0000.0000.0000.0000 x) 0) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: exp(NaN) -> NaN + :: check overflow to infinity + =/ o-threshold `@rq`0x400c.62e4.2fef.a39e.f357.93c7.6730.0601 :: 1.135652340629414394949193107797e4, value above which exp(x) overflows + ?: (gth x o-threshold) (mul huge huge) + :: check underflow to zero + =/ u-threshold `@rq`0xc00c.62e4.2fef.a39e.f357.93c7.6730.0601 :: -1.135652340629414394949193107797e4, value below which exp(x) underflows + ?: (lth x u-threshold) (mul tiny tiny) + :: otherwise, use Taylor series + =/ p .~~~1 + =/ po .~~~-1 + =/ i .~~~1 + |- ^- @rq + ?: (lth (abs (sub po p)) rtol) + p + $(i (add i .~~~1), p (add p (div (pow-n x i) (factorial i))), po p) + :: +sin: @rq -> @rq + :: + :: Returns the sine of a floating-point atom. + :: Examples + :: > (sin .~~~1) + :: .~~~0.8414709848078965066525022572525196 + :: > (sin .~~~2) + :: .~~~0.9092974268256816953960201260866781 + :: > (sin pi) + :: .~~~2.4143733100361875441251426417684949e-23 + :: Source + ++ sin + |= x=@rq ^- @rq + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7fff.0000.0000.0000.0000.0000.0000.0000) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: sin(+inf) -> NaN + ?: =(x 0xffff.0000.0000.0000.0000.0000.0000.0000) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: sin(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7fff.8000.0000.0000.0000.0000.0000.0000 x) 0) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: sin(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p x + =/ po .~~~-2 + =/ i 1 + =/ term x + |- ^- @rq + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (add i2 .~~~1)))) + $(i +(i), p (add p term), po p) + :: +cos: @rq -> @rq + :: + :: Returns the cosine of a floating-point atom. + :: Examples + :: > (cos .~~~1) + :: .~~~0.5403023058681397174009349981817251 + :: > (cos .~~~2) + :: .~~~-0.41614683654714238699756419777191616 + :: > (cos pi) + :: .~~~-1.0000000000000000000000021077555518 + :: Source + ++ cos + |= x=@rq ^- @rq + :: filter out non-finite arguments + :: check infinities + ?: =(x 0x7fff.0000.0000.0000.0000.0000.0000.0000) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: cos(+inf) -> NaN + ?: =(x 0xffff.0000.0000.0000.0000.0000.0000.0000) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: cos(-inf) -> NaN + :: check NaN + ?. (^gte (dis 0x7fff.8000.0000.0000.0000.0000.0000.0000 x) 0) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: cos(NaN) -> NaN + :: map into domain + =. x (mod x tau) + :: otherwise, use Taylor series + =/ p .~~~1 + =/ po .~~~-2 + =/ i 1 + =/ term .~~~1 + |- ^- @rq + ?. (gth (abs term) rtol) + p + =/ i2 (add (sun i) (sun i)) + =. term (mul (neg term) (div (mul x x) (mul i2 (sub i2 .~~~1)))) + $(i +(i), p (add p term), po p) + :: +tan: @rq -> @rq + :: + :: Returns the tangent of a floating-point atom. + :: Examples + :: > (tan .~~~1) + :: .~~~1.5574077246549022305069793269617903 + :: > (tan .~~~2) + :: .~~~-2.1850398632615189916433278966958165 + :: > (tan pi) + :: .~~~-2.1850398632615189916433278966958165 + :: Source + ++ tan + |= x=@rq ^- @rq + (div (sin x) (cos x)) + :: +pow-n: [@rq @rq] -> @rq + :: + :: Returns the power of a floating-point atom to a signed integer exponent. + :: Examples + :: > (pow-n .~~~2 .~~~2) + :: .~~~4 + :: > (pow-n .~~~2 .~~~-2) + :: .~~~0.25 + :: Source + ++ pow-n + |= [x=@rq n=@rq] ^- @rq + ?: =(n .~~~0) .~~~1 + ?> &((gth n .~~~0) (isint n)) + =/ p x + |- ^- @rq + ?: (lth n .~~~2) + p + $(n (sub n .~~~1), p (mul p x)) + :: +log: @rq -> @rq + :: + :: Returns the natural logarithm of a floating-point atom. + :: Examples + :: > (log .~~~1) + :: .~~~0 + :: > (log .~~~2) + :: .~~~0.6931471805599453094170735934298606 + :: > (~(log rq [%z .~~~1e-5]) .~~~2) + :: .~~~0.6931470737597852366942444674497712 + :: > (log .~~~inf) + :: .~~~inf + :: Source + ++ log + |= z=@rq ^- @rq + :: filter out non-finite arguments + :: check infinities + ?: =(z 0x7fff.0000.0000.0000.0000.0000.0000.0000) `@rq`0x7fff.0000.0000.0000.0000.0000.0000.0000 :: exp(+inf) -> inf + ?: =(z 0xffff.0000.0000.0000.0000.0000.0000.0000) .~~~0.0 :: exp(-inf) -> 0 + :: check NaN + ?. (^gte (dis 0x7fff.8000.0000.0000.0000.0000.0000.0000 z) 0) `@rq`0x7fff.8000.0000.0000.0000.0000.0000.0000 :: exp(NaN) -> NaN + :: otherwise, use Taylor series + =/ p .~~~0 + =/ po .~~~-1 + =/ i .~~~0 + |- ^- @rq + ?: (lth (abs (sub po p)) rtol) + (mul (div (mul .~~~2 (sub z .~~~1)) (add z .~~~1)) p) + =/ term1 (div .~~~1 (add .~~~1 (mul .~~~2 i))) + =/ term2 (mul (sub z .~~~1) (sub z .~~~1)) + =/ term3 (mul (add z .~~~1) (add z .~~~1)) + =/ term (mul term1 (pow-n (div term2 term3) i)) + $(i (add i .~~~1), p (add p term), po p) + :: +pow: [@rq @rq] -> @rq + :: + :: Returns the power of a floating-point atom to a floating-point exponent. + :: Examples + :: > (pow .~~~1 .~~~2) + :: .~~~1 + :: > (pow .~~~2 .~~~2) + :: .~~~4 + :: > (~(pow rq:math [%z .~~~1e-5]) .~~~2 .~~~3.5) + :: .~~~11.313703735926135014164384135726204 + :: Source + ++ pow + |= [x=@rq n=@rq] ^- @rq + :: fall through on integers (faster) + ?: =(n (san (need (toi n)))) (pow-n x (san (need (toi n)))) + (exp (mul n (log x))) + :: +sqrt: @rq -> @rq + :: + :: Returns the square root of a floating-point atom. + :: Alias for +sqt. + :: Examples + :: > (sqrt .~~~1) + :: .~~~1 + :: > (sqrt .~~~2) + :: .~~~1.4142135623730950488015335862957159 + :: > (~(sqrt rq:math [%z .~~~1e-10]) .~~~2) + :: .~~~1.4142135623721439870165294373250435 + :: Source + ++ sqrt sqt + :: +sqt: @rq -> @rq + :: + :: Returns the square root of a floating-point atom. + :: Examples + :: > (sqt .~~~1) + :: .~~~1 + :: > (sqt .~~~2) + :: .~~~1.4142135623730950488015335862957159 + :: > (~(sqt rq:math [%z .~~~1e-10]) .~~~2) + :: .~~~1.4142135623721439870165294373250435 + :: Source + ++ sqt + |= x=@rq ^- @rq + ?> (sgn x) + (pow x .~~~0.5) + :: +cbrt: @rq -> @rq + :: + :: Returns the cube root of a floating-point atom. + :: Alias for +cbt. + :: Examples + :: > (cbrt .~~~1) + :: .~~~1 + :: > (cbrt .~~~2) + :: .~~~1.2598919398737178526805575821133312 + :: > (~(cbrt rq:math [%z .~~~1e-10]) .~~~2) + :: .~~~1.2598919398731638759238176665172822 + :: Source + ++ cbrt cbt + :: +cbt: @rq -> @rq + :: + :: Returns the cube root of a floating-point atom. + :: Examples + :: > (cbt .~~~1) + :: .~~~1 + :: > (cbt .~~~2) + :: .~~~1.2598919398737178526805575821133312 + :: > (~(cbt rq:math [%z .~~~1e-10]) .~~~2) + :: .~~~1.2598919398731638759238176665172822 + :: Source + ++ cbt + |= x=@rq ^- @rq + ?> (sgn x) + (pow x .~~~0.3333) + :: +arg: @rq -> @rq + :: + :: Returns the argument of a floating-point atom (real argument = absolute + :: value). + :: Examples + :: > (arg .~~~1) + :: .~~~1 + :: > (arg .~~~-1) + :: .~~~1 + :: Source + ++ arg abs + -- +:: reference values +++ reference + |% + :: hardcoded string constants for your viewing pleasure + :: OEIS A019692 + ++ tau '6.28318530717958647692528676655900576839433879875021164194988918461563281257241799625606965068423413596428' + :: OEIS A000796 + ++ pi '3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214' + :: OEIS A001113 + ++ e '2.71828182845904523536028747135266249775724709369995957496696762772407663035354759457138217852516642742746' + :: OEIS A001622 + ++ phi '1.61803398874989484820458683436563811772030917980576286213544862270526046281890244970720720418939113748475' + :: OEIS A002193 + ++ sqt2 '1.41421356237309504880168872420969807856967187537694807317667973799073247846210703885038753432764157273' + :: OEIS A010503 + ++ invsqt2 '0.70710678118654752440084436210484903928483593768847403658833986899536623923105351942519376716382086' + :: OEIS A002162 + ++ log2 '0.69314718055994530941723212145817656807550013436025525412068000949339362196969471560586332699641868754' + :: OEIS A002392 + ++ log10 '2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599726645985502929' + -- +-- From 7b9463111b8b1f31e183ff3d6a8f54ceef3738dc Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 15:31:39 +0100 Subject: [PATCH 15/20] Use +isclose for +test-expected-score --- src/tests/elo.hoon | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tests/elo.hoon b/src/tests/elo.hoon index 368da0a..cf84c9f 100644 --- a/src/tests/elo.hoon +++ b/src/tests/elo.hoon @@ -1,34 +1,34 @@ -/+ *test, *elo +/+ *test, *elo, math |% ++ test-expected-score ;: weld %+ expect-eq - !> .~0.500 - !> (expected-score 1.200 1.200) + !> %.y + !> (~(isclose rd:math [%z .~1e-3]) (expected-score 1.200 1.200) .~0.500) :: %+ expect-eq - !> .~0.752 - !> (expected-score 1.400 1.200) + !> %.y + !> (~(isclose rd:math [%z .~1e-3]) (expected-score 1.400 1.200) .~0.752) :: %+ expect-eq - !> .~0.902 - !> (expected-score 1.600 1.200) + !> %.y + !> (~(isclose rd:math [%z .~1e-3]) (expected-score 1.600 1.200) .~0.902) :: %+ expect-eq - !> .~0.965 - !> (expected-score 1.800 1.200) + !> %.y + !> (~(isclose rd:math [%z .~1e-3]) (expected-score 1.800 1.200) .~0.965) :: %+ expect-eq - !> .~0.248 - !> (expected-score 1.200 1.400) + !> %.y + !> (~(isclose rd:math [%z .~1e-3]) (expected-score 1.200 1.400) .~0.248) :: %+ expect-eq - !> .~0.098 - !> (expected-score 1.200 1.600) + !> %.y + !> (~(isclose rd:math [%z .~1e-3]) (expected-score 1.200 1.600) .~0.098) :: %+ expect-eq - !> .~0.035 - !> (expected-score 1.200 1.800) + !> %.y + !> (~(isclose rd:math [%z .~1e-3]) (expected-score 1.200 1.800) .~0.035) == :: ++ test-scaling-factor From 538568ca677532fc056f20d0fa105059e6419711 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 15:32:19 +0100 Subject: [PATCH 16/20] Space out +test-scaling-factor --- src/tests/elo.hoon | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/elo.hoon b/src/tests/elo.hoon index cf84c9f..56d16c9 100644 --- a/src/tests/elo.hoon +++ b/src/tests/elo.hoon @@ -36,9 +36,11 @@ %+ expect-eq !> 40 !> (scaling-factor 20) + :: %+ expect-eq !> 32 !> (scaling-factor 40) + :: %+ expect-eq !> 24 !> (scaling-factor 75) From ba2c450bb36e0eb14b149388bd25dd0b8c8846ce Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 15:52:35 +0100 Subject: [PATCH 17/20] Draft scries for performance ratings --- src/app/telos.hoon | 4 ++-- src/lib/telos.hoon | 50 ++++++++++++++++++++++++++++++++++++---------- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/app/telos.hoon b/src/app/telos.hoon index 903ea13..7584ede 100644 --- a/src/app/telos.hoon +++ b/src/app/telos.hoon @@ -326,7 +326,7 @@ ratings (~(put by ratings) [game.action ~]) == =/ new-ratings - (compute-ratings-game (flop (~(got by archive) game.action))) + (compute-ratings-game game.action (flop (~(got by archive) game.action))) =/ new-ratings-list ~(tap by new-ratings) :_ %= this @@ -606,7 +606,7 @@ == :: =/ new-ratings - (update-elo-ratings (~(got by ratings) game) (~(got by archive) game) winner loser draw) + (update-elo-ratings game (~(got by ratings) game) (~(got by archive) game) winner loser draw) :: =/ winner-new-data (~(got by new-ratings) winner) diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 4881990..07dd45b 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -106,7 +106,7 @@ =(rank (clan:title player)) :: ++ compute-ratings-game - |= matches=(list match) + |= [=game matches=(list match)] ^- (map player rating) =/ player-ratings `(map player rating)`~ |- @@ -115,6 +115,7 @@ %= $ matches (tail matches) player-ratings %: update-elo-ratings + game player-ratings matches winner:(head matches) @@ -196,6 +197,13 @@ ^- ? =(player loser.match) :: +++ find-opponent-in-match + |= [our=ship =match] + ^- ship + ?: =(our winner.match) + loser.match + winner.match +:: ++ has-player-in-ratings |= [[game ratings=(map player rating)] player=@] ^- ? @@ -205,7 +213,7 @@ :: ++ update-elo-ratings :: XX matches should include the match just played - |= [players=(map player rating) matches=(list match) =winner =loser draw=?] + |= [=game players=(map player rating) matches=(list match) =winner =loser draw=?] ^+ players =/ new-winner-elo=rating =/ our-rating @@ -222,12 +230,21 @@ :: ?: (lth (lent our-matches) 10) %: new-performance-rating:elo - :: XX sum up opps' ratings from previous games - :: would need to know what the opponents' - :: ratings were at the time of the match. - :: could change id.match to @da and scry - :: for the rating at that case. - (~(gut by players) loser 1.500) + :: sum opponents' ratings + %+ roll + our-matches + |= [=match sum=@ud] + ^+ sum + %+ add + sum + %- need + .^ (unit rating) + %gx + /=telos + /(scot %da date.match) + /[game] + /(scot %p (find-opponent-in-match winner match)) + == (lent our-matches) (lent (skim our-matches |=(=match (has-winner-in-match match winner)))) (lent (skim our-matches |=(=match (has-loser-in-match match winner)))) @@ -253,8 +270,21 @@ :: ?: (lth (lent our-matches) 10) %: new-performance-rating:elo - :: XX sum up opps' ratings from previous games - (~(gut by players) loser 1.500) + :: sum opponents' ratings + %+ roll + our-matches + |= [=match sum=@ud] + ^+ sum + %+ add + sum + %- need + .^ (unit rating) + %gx + /=telos + /(scot %da date.match) + /[game] + /(scot %p (find-opponent-in-match loser match)) + == (lent our-matches) (lent (skim our-matches |=(=match (has-winner-in-match match loser)))) (lent (skim our-matches |=(=match (has-loser-in-match match loser)))) From 8125950d561634e821880ec80999f6f1860baa87 Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 16:19:31 +0100 Subject: [PATCH 18/20] Reduce +update-elo-rating to handle one player --- src/app/telos.hoon | 28 ++++++-- src/lib/telos.hoon | 157 +++++++++++++++++++-------------------------- 2 files changed, 88 insertions(+), 97 deletions(-) diff --git a/src/app/telos.hoon b/src/app/telos.hoon index 7584ede..b4aeff7 100644 --- a/src/app/telos.hoon +++ b/src/app/telos.hoon @@ -605,14 +605,32 @@ our.bowl == :: - =/ new-ratings - (update-elo-ratings game (~(got by ratings) game) (~(got by archive) game) winner loser draw) + =/ new-game-ratings + %- %~ put by + %- %~ put by + (~(got by ratings) game) + :- loser + %: update-elo-rating + game + draw + loser + (~(got by ratings) game) + (~(got by archive) game) + == + :- winner + %: update-elo-rating + game + draw + winner + (~(got by ratings) game) + (~(got by archive) game) + == :: =/ winner-new-data - (~(got by new-ratings) winner) + (~(got by new-game-ratings) winner) :: =/ loser-new-data - (~(got by new-ratings) loser) + (~(got by new-game-ratings) loser) :: :: confirm results :- :~ :: update players with their new ratings @@ -643,7 +661,7 @@ == == %= this - ratings (~(put by ratings) game new-ratings) + ratings (~(put by ratings) game new-game-ratings) archive (~(put by archive) game :-(new-match (~(got by archive) game))) == :: diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 07dd45b..4f220e3 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -108,20 +108,33 @@ ++ compute-ratings-game |= [=game matches=(list match)] ^- (map player rating) - =/ player-ratings `(map player rating)`~ + =/ player-ratings + *(map player rating) |- ?~ matches player-ratings %= $ matches (tail matches) - player-ratings %: update-elo-ratings + player-ratings %- %~ put by + %- %~ put by + player-ratings + :- loser:(head matches) + %: update-elo-rating + game + draw:(head matches) + loser:(head matches) + player-ratings + matches + == + :- winner:(head matches) + %: update-elo-rating game + draw:(head matches) + winner:(head matches) player-ratings matches - winner:(head matches) - loser:(head matches) - draw:(head matches) - == == + == + == +| %kick-helpers :: ++ kick-game-players @@ -211,93 +224,53 @@ :: +| %ratings :: -++ update-elo-ratings +++ update-elo-rating + |= [=game draw=? our=ship players=(map player rating) matches=(list match)] + ^- rating :: XX matches should include the match just played - |= [=game players=(map player rating) matches=(list match) =winner =loser draw=?] - ^+ players - =/ new-winner-elo=rating - =/ our-rating - (~(gut by players) winner 1.500) - =/ opp-rating - (~(gut by players) loser 1.500) - =/ our-matches - (skim matches |=(=match (has-player-in-match match winner))) - =/ our-outcome - :: XX assuming (head matches) is most recent match - ?. draw:(head matches) - %win - %draw - :: - ?: (lth (lent our-matches) 10) - %: new-performance-rating:elo - :: sum opponents' ratings - %+ roll - our-matches - |= [=match sum=@ud] - ^+ sum - %+ add - sum - %- need - .^ (unit rating) - %gx - /=telos - /(scot %da date.match) - /[game] - /(scot %p (find-opponent-in-match winner match)) - == - (lent our-matches) - (lent (skim our-matches |=(=match (has-winner-in-match match winner)))) - (lent (skim our-matches |=(=match (has-loser-in-match match winner)))) - == - %: new-rating:elo - our-rating - (expected-score:elo our-rating opp-rating) - (scaling-factor:elo (lent our-matches)) - our-outcome - == - =/ new-loser-elo=rating - =/ our-rating - (~(gut by players) loser 1.500) - =/ opp-rating - (~(gut by players) winner 1.500) - =/ our-matches - (skim matches |=(=match (has-player-in-match match loser))) - =/ our-outcome - :: XX assuming (head matches) is most recent match - ?. draw:(head matches) - %loss + :: XX assuming (head matches) is most recent match + =/ this-match + (head matches) + =/ opp + (find-opponent-in-match our this-match) + =/ our-rating + (~(gut by players) our 1.500) + =/ opp-rating + (~(gut by players) opp 1.500) + =/ our-matches + (skim matches |=(=match (has-player-in-match match our))) + =/ our-outcome + ?: draw:this-match %draw - :: - ?: (lth (lent our-matches) 10) - %: new-performance-rating:elo - :: sum opponents' ratings - %+ roll - our-matches - |= [=match sum=@ud] - ^+ sum - %+ add - sum - %- need - .^ (unit rating) - %gx - /=telos - /(scot %da date.match) - /[game] - /(scot %p (find-opponent-in-match loser match)) - == - (lent our-matches) - (lent (skim our-matches |=(=match (has-winner-in-match match loser)))) - (lent (skim our-matches |=(=match (has-loser-in-match match loser)))) - == - %: new-rating:elo - our-rating - (expected-score:elo our-rating opp-rating) - (scaling-factor:elo (lent our-matches)) - our-outcome + ?: =(our winner:this-match) + %win + %loss + :: + ?: (lth (lent our-matches) 10) + %: new-performance-rating:elo + :: sum all opponents' ratings + %+ roll + our-matches + |= [=match sum=@ud] + ^+ sum + %+ add + sum + %- need + .^ (unit rating) + %gx + /=telos + /(scot %da date.match) + /[game] + /(scot %p (find-opponent-in-match our match)) + == + (lent our-matches) + (lent (skim our-matches |=(=match (has-winner-in-match match our)))) + (lent (skim our-matches |=(=match (has-loser-in-match match our)))) == - %- %~ put by - %- %~ put by - players - [loser new-loser-elo] - [winner new-winner-elo] + %: new-rating:elo + our-rating + (expected-score:elo our-rating opp-rating) + (scaling-factor:elo (lent our-matches)) + our-outcome + == -- From fcb8536c420782e1ca5300ce456b0b60cf2be3fc Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 16:24:47 +0100 Subject: [PATCH 19/20] Send latest match to +update-elo-rating --- src/app/telos.hoon | 4 ++-- src/lib/telos.hoon | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/app/telos.hoon b/src/app/telos.hoon index b4aeff7..2d13ca2 100644 --- a/src/app/telos.hoon +++ b/src/app/telos.hoon @@ -615,7 +615,7 @@ draw loser (~(got by ratings) game) - (~(got by archive) game) + :-(new-match (~(got by archive) game)) == :- winner %: update-elo-rating @@ -623,7 +623,7 @@ draw winner (~(got by ratings) game) - (~(got by archive) game) + :-(new-match (~(got by archive) game)) == :: =/ winner-new-data diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index 4f220e3..e972fda 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -227,8 +227,6 @@ ++ update-elo-rating |= [=game draw=? our=ship players=(map player rating) matches=(list match)] ^- rating - :: XX matches should include the match just played - :: XX assuming (head matches) is most recent match =/ this-match (head matches) =/ opp From 0046718fc3c37962164dfc9d62790b76c6648aae Mon Sep 17 00:00:00 2001 From: bonbud-macryg Date: Sun, 7 Apr 2024 17:54:46 +0100 Subject: [PATCH 20/20] Handle unrated players for +new-performance-rating --- src/lib/telos.hoon | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/lib/telos.hoon b/src/lib/telos.hoon index e972fda..2753106 100644 --- a/src/lib/telos.hoon +++ b/src/lib/telos.hoon @@ -251,16 +251,19 @@ our-matches |= [=match sum=@ud] ^+ sum + =/ opp-rating + .^ (unit rating) + %gx + /=telos + /(scot %da date.match) + /[game] + /(scot %p (find-opponent-in-match our match)) + == %+ add sum - %- need - .^ (unit rating) - %gx - /=telos - /(scot %da date.match) - /[game] - /(scot %p (find-opponent-in-match our match)) - == + ?~ opp-rating + 1.500 + (need opp-rating) (lent our-matches) (lent (skim our-matches |=(=match (has-winner-in-match match our)))) (lent (skim our-matches |=(=match (has-loser-in-match match our))))