Search Apps Documentation Source Content File Folder Download Copy

hof.gno

2.66 Kb ยท 134 lines
  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}