Skip to content

Commit

Permalink
feat: add filter object
Browse files Browse the repository at this point in the history
Signed-off-by: Norman Meier <[email protected]>
  • Loading branch information
n0izn0iz committed May 27, 2024
1 parent cbd14a7 commit f190423
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 13 deletions.
81 changes: 81 additions & 0 deletions examples/gno.land/r/demo/teritori/projects_manager/filter.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package projects_manager

import (
"std"

"gno.land/p/demo/dao_maker/jsonutil"
"gno.land/p/demo/json"
"gno.land/p/demo/ufmt"
)

type Filter interface {
FromJSON(ast *json.Node)
}

func FilterFromJSON(ast *json.Node) Filter {
if ast.IsNull() {
return nil
}
var filter Filter
key, member := jsonutil.MustUnion(ast)
switch key {
case "byCandidatesForFunder":
filter = &FilterByCandidatesForFunder{}
case "byFunder":
filter = &FilterByFunder{}
case "byContractor":
filter = &FilterByContractor{}
case "byContractorAndFunder":
filter = &FilterByContractorAndFunder{}
default:
panic(ufmt.Sprintf("invalid filter kind `%s`", key))
}
filter.FromJSON(member)
return filter
}

type FilterByCandidatesForFunder struct {
Funder std.Address
}

func (f *FilterByCandidatesForFunder) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Funder = jsonutil.MustAddress(obj["funder"])
}

var _ Filter = &FilterByCandidatesForFunder{}

type FilterByFunder struct {
Funder std.Address
}

func (f *FilterByFunder) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Funder = jsonutil.MustAddress(obj["funder"])
}

var _ Filter = &FilterByFunder{}

type FilterByContractor struct {
Contractor std.Address
}

func (f *FilterByContractor) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Contractor = jsonutil.MustAddress(obj["contractor"])
}

var _ Filter = &FilterByContractor{}

type FilterByContractorAndFunder struct {
Contractor std.Address
Funder std.Address
}

func (f *FilterByContractorAndFunder) FromJSON(ast *json.Node) {
obj := ast.MustObject()
f.Contractor = jsonutil.MustAddress(obj["contractor"])
f.Funder = jsonutil.MustAddress(obj["funder"])
}

var _ Filter = &FilterByContractorAndFunder{}
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ var (
contractsByFunder = avl.NewTree() // std.Address(funder) => contractID => *Contract
contractsByContractor = avl.NewTree() // std.Address(contractor) => contractID => *Contract
contractsByFunderAndContractor = avl.NewTree() // std.Address(funder) + std.Address(contractor) => contractID => *Contract
contractsWithCandidates = avl.NewTree() // std.Address(funder) => contractID => *Contract
)

func setIndices(contract *Contract) {
Expand Down Expand Up @@ -578,6 +579,18 @@ func AcceptContractor(contractId uint64, contractor std.Address) {
}

contracts[contractId].contractor = contractor

funderKey := contract.funder.String()
byIDTreeIface, ok := contractsWithCandidates.Get(funderKey)
if !ok {
byIDTreeIface = avl.NewTree()
contractsWithCandidates.Set(funderKey, byIDTreeIface)
}
byIDTree := byIDTreeIface.(*avl.Tree)
byIDTree.Remove(seqid.ID(contract.id).String())
if byIDTree.Size() == 0 {
contractsWithCandidates.Remove(funderKey)
}
}

func SubmitContractorCandidate(contractId uint64) {
Expand Down Expand Up @@ -608,6 +621,14 @@ func SubmitContractorCandidate(contractId uint64) {
}

contracts[contractId].contractorCandidates = append(candidates, caller)

funderKey := contract.funder.String()
byIDTree, ok := contractsWithCandidates.Get(funderKey)
if !ok {
byIDTree = avl.NewTree()
contractsWithCandidates.Set(funderKey, byIDTree)
}
byIDTree.(*avl.Tree).Set(seqid.ID(contract.id).String(), contract)
}

// Complete any milestone in review status and pay the needed amount
Expand Down Expand Up @@ -822,7 +843,7 @@ func GetContractorCandidatesJSON(contractId uint64) string {
return string(ret)
}

func GetContracts(offset, limit int, filterByFunder string, filterByContractor string) []*Contract {
func GetContracts(offset, limit int, filter Filter) []*Contract {
if offset < 0 {
offset = 0
}
Expand All @@ -831,21 +852,28 @@ func GetContracts(offset, limit int, filterByFunder string, filterByContractor s
return nil
}

var tree interface{}
if filterByFunder != "" && filterByContractor != "" {
tree, _ = contractsByFunderAndContractor.Get(filterByFunder + filterByContractor)
} else if filterByFunder != "" {
tree, _ = contractsByFunder.Get(filterByFunder)
} else if filterByContractor != "" {
tree, _ = contractsByContractor.Get(filterByContractor)
} else {
if filter == nil {
end := offset + limit
if end > len(contracts) {
end = len(contracts)
}
return contracts[offset:end]
}

var tree interface{}
switch f := filter.(type) {
case *FilterByCandidatesForFunder:
tree, _ = contractsWithCandidates.Get(f.Funder.String())
case *FilterByContractorAndFunder:
tree, _ = contractsByFunderAndContractor.Get(f.Funder.String() + f.Contractor.String())
case *FilterByContractor:
tree, _ = contractsByContractor.Get(f.Contractor.String())
case *FilterByFunder:
tree, _ = contractsByFunder.Get(f.Funder.String())
default:
panic("unknown filter")
}

if tree == nil {
return nil
}
Expand Down Expand Up @@ -873,10 +901,15 @@ func RenderContractJSON(contractId uint64) string {
return string(ret)
}

func RenderContractsJSON(offset, limit int, filterByFunder string, filterByContractor string) string {
contracts := GetContracts(offset, limit, filterByFunder, filterByContractor)
contractsJSON := make([]*json.Node, len(contracts))
for i, c := range contracts {
func RenderContractsJSON(offset, limit int, filterJSON string) string {
filter := FilterFromJSON(json.Must(json.Unmarshal([]byte(filterJSON))))
contractsRes := GetContracts(offset, limit, filter)
return renderContractsJSON(contractsRes)
}

func renderContractsJSON(contractsRes []*Contract) string {
contractsJSON := make([]*json.Node, len(contractsRes))
for i, c := range contractsRes {
contractsJSON[i] = c.ToJSON()
}

Expand Down

0 comments on commit f190423

Please sign in to comment.