PathrockNetwork Gno Explorer
HomeBlocksTransactionsTokensRealmsPackagesValidatorsAnalytics

PathrockNetwork Gno Explorer — an independent explorer for Gno.land Mainnet (gnoland-1), operated by PathrockNetwork. Not an official Gno.land service.

gnowebarchive RPC

gno.land/r/g1t2kg2vtr3fukg43eujkn6x53gfdyakhngt4sfd/gnofly/arena/v0

Realm
Open in gnoweb ↗

Overview

Kind
Realm (renderable)
Name
v0
Namespace
g1t2kg2vtr3fukg43eujkn6x53gfdyakhngt4sfd / gnofly / arena
Files
15 (gnomod.toml)
Exported functions
21
Module
gno.land/r/g1t2kg2vtr3fukg43eujkn6x53gfdyakhngt4sfd/gnofly/arena/v0
gno
0.9

Files (15)

  • gnomod.tomltoml
  • arena.gnogno
  • claims.gnogno
  • doc.gnogno
  • earnings.gnogno
  • errors.gnogno
  • escrow.gnogno
  • json.gnogno
  • lobby.gnogno
  • render.gnogno
  • results.gnogno
  • roles.gnogno
  • rounds.gnogno
  • spec.gnogno
  • validate.gnogno
  • earnings.gnogno
    1package arena23import "gno.land/p/g1t2kg2vtr3fukg43eujkn6x53gfdyakhngt4sfd/gnofly/arena/payout/v0"45// Earnings are what players won, added up round after round. Like the6// results they are a record for readers: no payment is ever computed from7// them.

    Functions

    • ArenaJSON(id string) string

    • ArenasJSON() string

    • CancelRound(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string)

    • Claim(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}) int64

    • Claimable(addr string) int64

    • ClaimsJSON(addr string) string

    • EarningsJSON() string

    • Enter(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, spec string, ticket string) string

    • Escrowed() int64

    • ExpireLobby(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string)

    • Leave(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string)

    • PlayerJSON(addr string) string

    • RefundDelay() int64

    • RefundRound(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string)

    • Render(path string) string

    • ResultJSON(id string) string

    • ResultsJSON() string

    • SetRefundDelay(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, seconds int64)

    • SettleRound(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string, deaths string)

    • StartRound(cur interface {.seal func(); Address func() .uverse.address; IsCode func() bool; IsCurrent func() bool; IsEphemeral func() bool; IsUser func() bool; IsUserCall func() bool; IsUserRun func() bool; PkgPath func() string; Previous func() .uverse.realm; String func() string; Sub func(string) .uverse.realm; Subpath func() string}, id string) int64

    • Version() int64

    Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.

    Rendered

    RenderedRawgnoweb ↗
    8
    //
    9// For one settled round a player's winnings are what they were paid above
    10// their own stake, and never less than zero: losing a stake does not take
    11// anything back from what was won before. Cancelled and refunded rounds
    12// count for nothing, nobody won or lost in them.
    13
    14// topSize is how many players the list of top winners holds.
    15const topSize = 10
    16
    17// totals is what the realm remembers about one player.
    18type totals struct {
    19 won int64 // ugnot won above the stakes, over every settled round
    20 rounds int64 // settled rounds played
    21}
    22
    23// Totals are stored as a single string, "won:rounds", for the same reason
    24// as the pilots of the game realm: a struct would be one more stored object
    25// per player, and the referee pays for up to 16 new players per settlement.
    26
    27// encode returns the stored form of t.
    28func (t totals) encode() string {
    29 return itoa(t.won) + ":" + itoa(t.rounds)
    30}
    31
    32// totalsOf returns the totals of a player, zero for a player who never
    33// finished a round.
    34func totalsOf(addr address) totals {
    35 v := earnings.Get(addr.String())
    36 if v == nil {
    37 return totals{}
    38 }
    39 s := v.(string)
    40 colon := indexFrom(s, 0, ':')
    41 if colon == len(s) {
    42 panic(errCorruptEarnings)
    43 }
    44 won, ok := digits(s[:colon])
    45 if !ok {
    46 panic(errCorruptEarnings)
    47 }
    48 rounds, ok := digits(s[colon+1:])
    49 if !ok {
    50 panic(errCorruptEarnings)
    51 }
    52 return totals{won: won, rounds: rounds}
    53}
    54
    55// creditRound records a settled round for each of its players: one more
    56// round played, and what they were paid above their stake, if anything.
    57func creditRound(stake int64, players []address, payouts []payout.Payout) {
    58 for _, p := range players {
    59 gain := int64(0)
    60 for _, paid := range payouts {
    61 if paid.Address == p && paid.Amount > stake {
    62 gain = paid.Amount - stake
    63 }
    64 }
    65
    66 t := totalsOf(p)
    67 before := t.won
    68 t.won += gain
    69 t.rounds++
    70 earnings.Set(p.String(), t.encode())
    71
    72 if gain > 0 {
    73 if next, changed := winners.raise(p, before, t.won, topSize); changed {
    74 winners = next
    75 }
    76 }
    77 }
    78}
    79
    80// ranking is the list of top winners: the players who won the most, best
    81// first, at most topSize lines and one line per player. With equal winnings,
    82// the player who got there first stays ahead.
    83//
    84// It is the ranking of the game realm. It is kept sorted at write time, so
    85// reading it never has to look at every player. Winnings only going up is
    86// what makes that exact: a player outside the list can only enter it through
    87// raise.
    88//
    89// The two slices are parallel: slices of plain values are one stored object
    90// each, where a slice of structs would be one object per line.
    91type ranking struct {
    92 addrs []address
    93 scores []int64
    94}
    95
    96// raise puts a player at their place after their score went up from old to
    97// score. It returns the ranking to store, and changed == false when it is
    98// left as it is: the player is not on a full list and still not good enough
    99// to get on.
    100func (r ranking) raise(addr address, old, score int64, size int) (next ranking, changed bool) {
    101 from := r.lineOf(addr, old)
    102 to := r.search(score - 1) // after every line with this score or more
    103 if from < 0 && to >= size {
    104 return r, false
    105 }
    106 if from >= 0 && to > from {
    107 to = from // cannot happen: a score only goes up
    108 }
    109 next = ranking{
    110 addrs: spliceAddrs(r.addrs, from, to, addr, size),
    111 scores: spliceInts(r.scores, from, to, score, size),
    112 }
    113 return next, true
    114}
    115
    116// search returns the index of the first line with a score of limit or less,
    117// the number of lines when there is none. The list is sorted, so this is a
    118// binary search.
    119func (r ranking) search(limit int64) int {
    120 lo, hi := 0, len(r.scores)
    121 for lo < hi {
    122 mid := (lo + hi) / 2
    123 if r.scores[mid] <= limit {
    124 hi = mid
    125 } else {
    126 lo = mid + 1
    127 }
    128 }
    129 return lo
    130}
    131
    132// lineOf returns the index of a player's line, -1 when they have none. old
    133// is the player's score before the change being applied.
    134//
    135// A line always carries the current score of its player, because every
    136// change of a score goes through raise. So the line can only be among those
    137// with exactly old. A player whose score was zero has never been through
    138// raise and has no line.
    139func (r ranking) lineOf(addr address, old int64) int {
    140 if old <= 0 {
    141 return -1
    142 }
    143 for i := r.search(old); i < len(r.scores) && r.scores[i] == old; i++ {
    144 if r.addrs[i] == addr {
    145 return i
    146 }
    147 }
    148 return -1
    149}
    150
    151// spliceAddrs returns a copy of a ranking column with v inserted at index
    152// to. With from >= 0 the element at that index, the player's previous line,
    153// is left out; to must not be past it. With from < 0 the result is kept to
    154// size elements by dropping the tail; to must be below size.
    155//
    156// The copy has exactly the length of its content, so that nothing else stays
    157// in storage.
    158func spliceAddrs(list []address, from, to int, v address, size int) []address {
    159 if from < 0 {
    160 if len(list) >= size {
    161 list = list[:size-1]
    162 }
    163 out := make([]address, 0, len(list)+1)
    164 out = append(out, list[:to]...)
    165 out = append(out, v)
    166 return append(out, list[to:]...)
    167 }
    168 out := make([]address, 0, len(list))
    169 out = append(out, list[:to]...)
    170 out = append(out, v)
    171 out = append(out, list[to:from]...)
    172 return append(out, list[from+1:]...)
    173}
    174
    175// spliceInts is spliceAddrs for a column of numbers.
    176func spliceInts(list []int64, from, to int, v int64, size int) []int64 {
    177 if from < 0 {
    178 if len(list) >= size {
    179 list = list[:size-1]
    180 }
    181 out := make([]int64, 0, len(list)+1)
    182 out = append(out, list[:to]...)
    183 out = append(out, v)
    184 return append(out, list[to:]...)
    185 }
    186 out := make([]int64, 0, len(list))
    187 out = append(out, list[:to]...)
    188 out = append(out, v)
    189 out = append(out, list[to:from]...)
    190 return append(out, list[from+1:]...)
    191}
    192

    vm/qrender output, sanitized (docs/render-security.md) and displayed in an empty-sandbox iframe — scripts, forms and popups cannot run. Links stay inert in-preview; right-click to open.