1// Package hof is the hall of fame realm.
2// The Hall of Fame is an exhibition that holds items. Users can add their realms to the Hall of Fame by
3// importing the Hall of Fame realm and calling hof.Register() from their init function.
4package hof
5
6import (
7 "std"
8
9 "gno.land/p/demo/avl"
10 "gno.land/p/demo/ownable"
11 "gno.land/p/demo/pausable"
12 "gno.land/p/demo/seqid"
13)
14
15var (
16 exhibition *Exhibition
17
18 // Safe objects
19 Ownable *ownable.Ownable
20 Pausable *pausable.Pausable
21)
22
23type (
24 Exhibition struct {
25 itemCounter seqid.ID
26 description string
27 items *avl.Tree // pkgPath > Item
28 itemsSorted *avl.Tree // same data but sorted, storing pointers
29 }
30
31 Item struct {
32 id seqid.ID
33 pkgpath string
34 blockNum int64
35 upvote *avl.Tree // std.Addr > struct{}{}
36 downvote *avl.Tree // std.Addr > struct{}{}
37 }
38)
39
40func init() {
41 exhibition = &Exhibition{
42 items: avl.NewTree(),
43 itemsSorted: avl.NewTree(),
44 }
45
46 Ownable = ownable.NewWithAddress(std.Address("g125em6arxsnj49vx35f0n0z34putv5ty3376fg5"))
47 Pausable = pausable.NewFromOwnable(Ownable)
48}
49
50// Register registers your realm to the Hall of Fame
51// Should be called from within code
52func Register() {
53 if Pausable.IsPaused() {
54 return
55 }
56
57 submission := std.PrevRealm()
58 pkgpath := submission.PkgPath()
59
60 // Must be called from code
61 if submission.IsUser() {
62 return
63 }
64
65 // Must not yet exist
66 if exhibition.items.Has(pkgpath) {
67 return
68 }
69
70 id := exhibition.itemCounter.Next()
71 i := &Item{
72 id: id,
73 pkgpath: pkgpath,
74 blockNum: std.GetHeight(),
75 upvote: avl.NewTree(),
76 downvote: avl.NewTree(),
77 }
78
79 exhibition.items.Set(pkgpath, i)
80 exhibition.itemsSorted.Set(id.String(), i)
81
82 std.Emit("Registration")
83}
84
85func Upvote(pkgpath string) {
86 rawItem, ok := exhibition.items.Get(pkgpath)
87 if !ok {
88 panic(ErrNoSuchItem.Error())
89 }
90
91 item := rawItem.(*Item)
92 caller := std.PrevRealm().Addr().String()
93
94 if item.upvote.Has(caller) {
95 panic(ErrDoubleUpvote.Error())
96 }
97
98 item.upvote.Set(caller, struct{}{})
99}
100
101func Downvote(pkgpath string) {
102 rawItem, ok := exhibition.items.Get(pkgpath)
103 if !ok {
104 panic(ErrNoSuchItem.Error())
105 }
106
107 item := rawItem.(*Item)
108 caller := std.PrevRealm().Addr().String()
109
110 if item.downvote.Has(caller) {
111 panic(ErrDoubleDownvote.Error())
112 }
113
114 item.downvote.Set(caller, struct{}{})
115}
116
117func Delete(pkgpath string) {
118 if !Ownable.CallerIsOwner() {
119 panic(ownable.ErrUnauthorized.Error())
120 }
121
122 i, ok := exhibition.items.Get(pkgpath)
123 if !ok {
124 panic(ErrNoSuchItem.Error())
125 }
126
127 if _, removed := exhibition.itemsSorted.Remove(i.(*Item).id.String()); !removed {
128 panic(ErrNoSuchItem.Error())
129 }
130
131 if _, removed := exhibition.items.Remove(pkgpath); !removed {
132 panic(ErrNoSuchItem.Error())
133 }
134}
hof.gno
2.66 Kb ยท 134 lines