// Copyright (C) 2019 rameshvk. All rights reserved.
// Use of this source code is governed by a MIT-style license
// that can be found in the LICENSE file.

package crdt

import (
	"math/big"
	"strconv"
	"strings"
)

// NextOrd returns the next ordinal.
//
// Less(key, next(key)) is guaranteed to always be true
func NextOrd(key string) string {
	return fromString(key).next().toString()
}

// PrevOrd returns the prev ordinal.
//
// LessOrd(prev(key), key) is guaranteed to always be true
func PrevOrd(key string) string {
	return fromString(key).prev().toString()
}

// LessOrd returns true if a < b
func LessOrd(a, b string) bool {
	return fromString(a).less(fromString(b))
}

// BetweenOrd returns keys between the two provided keys.
func BetweenOrd(a, b string, count int) []string {
	ak, bk := fromString(a), fromString(b)
	if ak.less(bk) {
		return ak.between(bk, count)
	}
	return bk.between(ak, count)
}

func fromString(s string) *ordkey {
	if s == "" {
		return &ordkey{}
	}

	parts := strings.Split(s, ",")
	var k ordkey
	k.r.Num().SetString(parts[1], 62)
	logd, _ := strconv.Atoi(parts[0])
	k.r.Denom().Lsh(one, uint(logd-1))
	return &k
}

type ordkey struct {
	r big.Rat
}

func (k ordkey) toString() string {
	n, d := k.r.Num(), k.r.Denom()
	if d.Cmp(one) == 0 && n.BitLen() == 0 {
		return ""
	}
	return strconv.Itoa(d.BitLen()) + "," + n.Text(62)
}

func (k *ordkey) less(o *ordkey) bool {
	return k.r.Cmp(&o.r) < 0
}

func (k *ordkey) prev() *ordkey {
	var result ordkey
	result.r.Num().Quo(k.r.Num(), k.r.Denom())
	result.r.Num().Sub(result.r.Num(), one)
	return &result
}

func (k *ordkey) next() *ordkey {
	var result ordkey
	result.r.Num().Quo(k.r.Num(), k.r.Denom())
	result.r.Num().Add(result.r.Num(), one)
	return &result
}

var one = big.NewInt(1)

func (k *ordkey) between(o *ordkey, count int) []string {
	result := []string{}
	inc := big.NewRat(int64(1), int64(count+1))
	var diff big.Rat
	diff.Sub(&k.r, &o.r).Abs(&diff).Mul(&diff, inc)

	var last ordkey
	last.r.Set(&k.r)

	for count > 0 {
		last.r.Add(&last.r, &diff)
		result = append(result, last.toString())
		count--
	}
	return result
}

Related articles

dot heading_test

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package data_test import ( "reflect" "testing" "github.com/dotchain/dot/changes" "github.c

dot typename

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package sjson import ( "errors" "reflect" "strconv" "strings" "time" ) func typeName(v re

dot go

github.com/etcd-io/bbolt v1.3.2 h1:RLRQ0TKLX7DlBRXAJHvbmXL17Q3KNnTBtZ9B6Qo+/Y0= github.com/etcd-io/bbolt v1.3.2/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.

dot setattr_test

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package rich_test import ( "testing" "github.com/dotchain/dot/changes" "github.com/dotchain

dot poller_test

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package ops_test import ( "context" "errors" "testing" "time" "github.com/dotchain/dot/op

dot row

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package data import ( "github.com/dotchain/dot/changes" "github.com/dotchain/dot/changes/type

dot int_test

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package streams_test import ( "reflect" "testing" "github.com/dotchain/dot/changes" "githu

dot request

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package nw import ( "bytes" "context" "io" "strconv" "time" "github.com/dotchain/dot/log

dot heap

// Copyright (C) 2018 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. // Package heap implements a heap value type package heap import ( "math/rand" "sort" "time"

dot ref_test

// Copyright (C) 2019 rameshvk. All rights reserved. // Use of this source code is governed by a MIT-style license // that can be found in the LICENSE file. package data_test import ( "reflect" "testing" "github.com/dotchain/dot/changes" "github.c