From f13bd3d529bf7e7ac562261da1b6c0b458ae9bf6 Mon Sep 17 00:00:00 2001 From: Huangzj Date: Wed, 28 Oct 2020 17:10:55 +0800 Subject: [PATCH] =?UTF-8?q?feat(Go-Tool)=EF=BC=9A=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E4=BA=8C=E8=BF=9B=E5=88=B6=E4=BD=8D=E6=95=B0?= =?UTF-8?q?=E6=9D=A5=E5=AD=98=E5=82=A8=E5=A5=96=E5=8A=B1=E9=A2=86=E5=8F=96?= =?UTF-8?q?=E6=83=85=E5=86=B5=E5=B7=A5=E5=85=B7=E7=B1=BB=EF=BC=8CBitStoreT?= =?UTF-8?q?ool=E3=80=81=E4=BD=BF=E7=94=A8=E8=AF=B4=E6=98=8E=E5=8F=8A?= =?UTF-8?q?=E5=85=B6=E5=8D=95=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme.md | 2 + util/bitStore/BitStoreTool.go | 132 ++++++++++++++ util/bitStore/BitStoreTool_test.go | 231 ++++++++++++++++++++++++ util/bitStore/readme.md | 83 +++++++++ util/timed/TestTimeIntervalUtil_test.go | 3 + 5 files changed, 451 insertions(+) create mode 100644 util/bitStore/BitStoreTool.go create mode 100644 util/bitStore/BitStoreTool_test.go create mode 100644 util/bitStore/readme.md diff --git a/readme.md b/readme.md index bb171ac..f612491 100644 --- a/readme.md +++ b/readme.md @@ -50,6 +50,8 @@ 2020/8/26: 新增Horspool字符串查找算法及其单测、新增Horspool字符串查找算法及其单测、新增计数排序及其单测 +2020/10/28: 新增根据二进制位数来存储奖励领取情况工具类,BitStoreTool、使用说明及其单测 + # mod vendor模式加载包 通过go mod的方式加载的github上面的包会有报红的问题,但是包本身是可以运行的,这样就是会有一个问题,如果你想要点击去看方法的内容,没办法做到 diff --git a/util/bitStore/BitStoreTool.go b/util/bitStore/BitStoreTool.go new file mode 100644 index 0000000..d4f89a9 --- /dev/null +++ b/util/bitStore/BitStoreTool.go @@ -0,0 +1,132 @@ +/* + * @Author : huangzj + * @Time : 2020/10/27 15:19 + * @Description:按照位数进行存储.这里主要是针对(0,1)状态的场景。比如说奖励领取情况,0表示未领取,1表示领取 + * 这边有两个参数 + * MaxGear:当前存储的最大挡位是什么,在初始化的时候,需要对对应的领取情况进行数组初始化 + * GearPickList:挡位领取情况,这边初始化的bit为32,总共有32位,每一位代表一个挡位的领取情况,并且这是一个数组,就代表了 32 - 64 - 96 ...最大 32 * list长度 挡位的所有领取情况 + */ + +package bitStore + +import "fmt" + +const ( + bit = 32 +) + +type BitStore struct { + MaxGear int //存储的最大挡位 + GearPickList []int +} + +//初始化方法,gear表示最大的领取档位是多少.(档位刚开始计算,没有值的情况) +func NewBitStore(gear int, gearPickList []int) *BitStore { + //校验传入的档位是否正确 + if gear < 1 { + panic("对应的最大档位不能小于1") + } + //初始化不初始化他的长度,而是后面需要的时候再进行动态增长 + return &BitStore{ + MaxGear: gear, + GearPickList: gearPickList, + } +} + +//获取所有档位对应的Map +func (bitStore *BitStore) FindAllGearMap() map[int]bool { + length := bitStore.getGearListLength(bitStore.MaxGear) //获取最大档位的长度 + listSize := bitStore.getSizeOrInit() //获取当前数组长度,如果数组没有初始化,进行初始化 + if listSize < length { + return bitStore.shortListDeal(listSize, length) //短数组的处理(没有达到最大大小的数组长度) + } + return bitStore.fullListDeal(listSize, length) //完整的数组的处理 +} + +//判断当前挡位是否被领取,true表示已经领取,false表示未领取 +func (bitStore *BitStore) IsGearReceive(gear int) bool { + bitStore.checkGearRight(gear) //检验一下档位是否正确 + length := bitStore.getGearListLength(gear) + if bitStore.getSizeOrInit() < length { + return false + } + position := bitStore.getGearPosition(gear, length) + return (bitStore.GearPickList[length-1] & (2 << position)) > 0 +} + +//获取对应档位奖励 +func (bitStore *BitStore) ReceiveByGear(gear int) ([]int, map[int]bool) { + bitStore.checkIfReceive(gear) //校验是否被领取了 + length := bitStore.dynamicGrowth(gear) //数组进行动态增长 + position := bitStore.getGearPosition(gear, length) //获取档位在数组中的位数位置 + bitStore.GearPickList[length-1] = bitStore.GearPickList[length-1] + (2 << uint(position)) + return bitStore.GearPickList, bitStore.FindAllGearMap() +} + +//判断档位是否正确 +func (bitStore *BitStore) checkGearRight(gear int) { + if gear > bitStore.MaxGear { + panic(fmt.Sprintf("档位信息有误,最大档位为:%d", bitStore.MaxGear)) + } +} + +//获取当前档位对应的数组长度(这边的length是从1开始的.) +func (bitStore *BitStore) getGearListLength(gear int) int { + return (gear + bit - 1) / bit +} + +//获取档位所在的二进制位置 +func (bitStore *BitStore) getGearPosition(gear, length int) int { + return (gear - bit*(length-1)) - 1 +} + +func (bitStore *BitStore) getSizeOrInit() int { + if bitStore.GearPickList == nil { + bitStore.GearPickList = make([]int, 0) + } + return len(bitStore.GearPickList) +} + +func (bitStore *BitStore) fullListDeal(listSize int, length int) map[int]bool { + resultMap := make(map[int]bool, 0) + for i := 0; i < length; i++ { + for j := 0; j < bit && bitStore.MaxGear > i*bit+j; j++ { + resultMap[i*bit+j+1] = (bitStore.GearPickList[i] & (2 << uint(j))) > 0 + } + } + return resultMap +} + +func (bitStore *BitStore) shortListDeal(listSize, length int) map[int]bool { + resultMap := make(map[int]bool, 0) + for i := 0; i < listSize; i++ { + for j := 0; j < bit; j++ { + resultMap[i*bit+j+1] = (bitStore.GearPickList[i] & (2 << uint(j))) > 0 + } + } + for i := listSize; i < length; i++ { + for j := 0; j < bit && bitStore.MaxGear > i*bit+j; j++ { + resultMap[i*bit+j+1] = false + } + } + return resultMap +} + +func (bitStore *BitStore) dynamicGrowth(gear int) int { + listSize := bitStore.getSizeOrInit() //获取当前数组长度,如果数组没有初始化,进行初始化 + length := bitStore.getGearListLength(gear) + //如果数组的长度小于对应的档位长度,这个时候需要去扩展这个数组 + if listSize < length { + for i := 0; i < (length - listSize); i++ { + bitStore.GearPickList = append(bitStore.GearPickList, 0) + } + } + return length +} + +func (bitStore *BitStore) checkIfReceive(gear int) { + //判断是否领取已经进行了档位的校验 + if bitStore.IsGearReceive(gear) { + panic("当前档位已被领取,不可重复领取") + } +} diff --git a/util/bitStore/BitStoreTool_test.go b/util/bitStore/BitStoreTool_test.go new file mode 100644 index 0000000..da2cce8 --- /dev/null +++ b/util/bitStore/BitStoreTool_test.go @@ -0,0 +1,231 @@ +/* + * @Author : huangzj + * @Time : 2020/10/27 15:19 + * @Description: + */ + +package bitStore + +import ( + "Go-Tool/util/sort" + "fmt" + "testing" +) + +func TestBitStore(t *testing.T) { + //fmt.Println("测试2档的情况") + //testTwo() + //fmt.Println() + // + //fmt.Println("测试10档的情况") + //testTen() + //fmt.Println() + // + //fmt.Println("测试18档的情况") + //testEighteen() + //fmt.Println() + + //fmt.Println("测试33档的情况") + //testThirtyThree() + //fmt.Println() + + //fmt.Println("测试58档的情况") + //testFiftyEight() + //fmt.Println() + + fmt.Println("测试1000档的情况") + testOneThousand() + fmt.Println() +} + +func newStoreMap(bitStore *BitStore) { + gearMap := bitStore.FindAllGearMap() + falseList := make([]int, 0) + for key, value := range gearMap { + if value == true { + falseList = append(falseList, key) + } + } + if len(falseList) == 0 { + fmt.Println("当前无未领取档位") + } +} + +func getReceiveResult(bitStore *BitStore) { + gearMap1 := bitStore.FindAllGearMap() + keyList := make([]int, 0) + for key, value := range gearMap1 { + if value == true { + keyList = append(keyList, key) + } + } + sort.BubbleSort(keyList) + fmt.Println("已经领取的档位信息如下") + for value := range keyList { + fmt.Print(fmt.Sprintf("%d,", keyList[value])) + } +} + +func testOneThousand() { + bitStore := NewBitStore(1000, nil) + + newStoreMap(bitStore) //初始化的校验 + + fmt.Println() + bitStore.ReceiveByGear(3) + fmt.Println(fmt.Sprintf("这个时候领取结果 3应该返回true,结果是:%v", bitStore.IsGearReceive(3))) + bitStore.ReceiveByGear(8) + fmt.Println(fmt.Sprintf("这个时候领取结果 8应该返回true,结果是:%v", bitStore.IsGearReceive(8))) + bitStore.ReceiveByGear(16) + fmt.Println(fmt.Sprintf("这个时候领取结果 16应该返回true,结果是:%v", bitStore.IsGearReceive(16))) + bitStore.ReceiveByGear(18) + fmt.Println(fmt.Sprintf("这个时候领取结果 18应该返回true,结果是:%v", bitStore.IsGearReceive(18))) + bitStore.ReceiveByGear(27) + fmt.Println(fmt.Sprintf("这个时候领取结果 27应该返回true,结果是:%v", bitStore.IsGearReceive(27))) + bitStore.ReceiveByGear(32) + fmt.Println(fmt.Sprintf("这个时候领取结果 32应该返回true,结果是:%v", bitStore.IsGearReceive(32))) + bitStore.ReceiveByGear(33) + fmt.Println(fmt.Sprintf("这个时候领取结果 33应该返回true,结果是:%v", bitStore.IsGearReceive(33))) + bitStore.ReceiveByGear(53) + fmt.Println(fmt.Sprintf("这个时候领取结果 53应该返回true,结果是:%v", bitStore.IsGearReceive(53))) + bitStore.ReceiveByGear(44) + fmt.Println(fmt.Sprintf("这个时候领取结果 44应该返回true,结果是:%v", bitStore.IsGearReceive(44))) + bitStore.ReceiveByGear(48) + + fmt.Println(fmt.Sprintf("判断当前数组是否动态增长,当前数组长度为:%d", len(bitStore.GearPickList))) + + fmt.Println(fmt.Sprintf("这个时候领取结果 48应该返回true,结果是:%v", bitStore.IsGearReceive(48))) + bitStore.ReceiveByGear(123) + fmt.Println(fmt.Sprintf("这个时候领取结果 123应该返回true,结果是:%v", bitStore.IsGearReceive(123))) + + fmt.Println(fmt.Sprintf("判断当前数组是否动态增长,当前数组长度为:%d", len(bitStore.GearPickList))) + getReceiveResult(bitStore) + fmt.Println() + + bitStore.ReceiveByGear(376) + fmt.Println(fmt.Sprintf("这个时候领取结果 376应该返回true,结果是:%v", bitStore.IsGearReceive(376))) + fmt.Println(fmt.Sprintf("判断当前数组是否动态增长,当前数组长度为:%d", len(bitStore.GearPickList))) + bitStore.ReceiveByGear(588) + fmt.Println(fmt.Sprintf("这个时候领取结果 588应该返回true,结果是:%v", bitStore.IsGearReceive(588))) + fmt.Println(fmt.Sprintf("判断当前数组是否动态增长,当前数组长度为:%d", len(bitStore.GearPickList))) + bitStore.ReceiveByGear(997) + fmt.Println(fmt.Sprintf("这个时候领取结果 997应该返回true,结果是:%v", bitStore.IsGearReceive(997))) + + fmt.Println() + getReceiveResult(bitStore) +} + +func testFiftyEight() { + bitStore := NewBitStore(58, nil) + + newStoreMap(bitStore) //初始化的校验 + + fmt.Println() + bitStore.ReceiveByGear(3) + fmt.Println(fmt.Sprintf("这个时候领取结果 3应该返回true,结果是:%v", bitStore.IsGearReceive(3))) + bitStore.ReceiveByGear(8) + fmt.Println(fmt.Sprintf("这个时候领取结果 8应该返回true,结果是:%v", bitStore.IsGearReceive(8))) + bitStore.ReceiveByGear(16) + fmt.Println(fmt.Sprintf("这个时候领取结果 16应该返回true,结果是:%v", bitStore.IsGearReceive(16))) + bitStore.ReceiveByGear(18) + fmt.Println(fmt.Sprintf("这个时候领取结果 18应该返回true,结果是:%v", bitStore.IsGearReceive(18))) + bitStore.ReceiveByGear(27) + fmt.Println(fmt.Sprintf("这个时候领取结果 27应该返回true,结果是:%v", bitStore.IsGearReceive(27))) + bitStore.ReceiveByGear(32) + fmt.Println(fmt.Sprintf("这个时候领取结果 32应该返回true,结果是:%v", bitStore.IsGearReceive(32))) + bitStore.ReceiveByGear(33) + fmt.Println(fmt.Sprintf("这个时候领取结果 33应该返回true,结果是:%v", bitStore.IsGearReceive(33))) + bitStore.ReceiveByGear(53) + fmt.Println(fmt.Sprintf("这个时候领取结果 53应该返回true,结果是:%v", bitStore.IsGearReceive(53))) + bitStore.ReceiveByGear(44) + fmt.Println(fmt.Sprintf("这个时候领取结果 44应该返回true,结果是:%v", bitStore.IsGearReceive(44))) + bitStore.ReceiveByGear(48) + fmt.Println(fmt.Sprintf("这个时候领取结果 48应该返回true,结果是:%v", bitStore.IsGearReceive(48))) + fmt.Println() + gearMap1 := bitStore.FindAllGearMap() + for key, value := range gearMap1 { + fmt.Println(fmt.Sprintf("当前map的key为%d,当前map的value为%v", key, value)) + } +} + +func testThirtyThree() { + bitStore := NewBitStore(33, nil) + + newStoreMap(bitStore) //初始化的校验 + fmt.Println() + bitStore.ReceiveByGear(3) + fmt.Println(fmt.Sprintf("这个时候领取结果 3应该返回true,结果是:%v", bitStore.IsGearReceive(3))) + bitStore.ReceiveByGear(8) + fmt.Println(fmt.Sprintf("这个时候领取结果 8应该返回true,结果是:%v", bitStore.IsGearReceive(8))) + bitStore.ReceiveByGear(16) + fmt.Println(fmt.Sprintf("这个时候领取结果 16应该返回true,结果是:%v", bitStore.IsGearReceive(16))) + bitStore.ReceiveByGear(18) + fmt.Println(fmt.Sprintf("这个时候领取结果 18应该返回true,结果是:%v", bitStore.IsGearReceive(18))) + bitStore.ReceiveByGear(27) + fmt.Println(fmt.Sprintf("这个时候领取结果 27应该返回true,结果是:%v", bitStore.IsGearReceive(27))) + bitStore.ReceiveByGear(32) + fmt.Println(fmt.Sprintf("这个时候领取结果 32应该返回true,结果是:%v", bitStore.IsGearReceive(32))) + bitStore.ReceiveByGear(33) + fmt.Println(fmt.Sprintf("这个时候领取结果 33应该返回true,结果是:%v", bitStore.IsGearReceive(33))) + + fmt.Println() + gearMap1 := bitStore.FindAllGearMap() + for key, value := range gearMap1 { + fmt.Println(fmt.Sprintf("当前map的key为%d,当前map的value为%v", key, value)) + } +} + +func testEighteen() { + bitStore := NewBitStore(18, nil) + + newStoreMap(bitStore) //初始化的校验 + fmt.Println() + bitStore.ReceiveByGear(3) + fmt.Println(fmt.Sprintf("这个时候领取结果 3应该返回true,结果是:%v", bitStore.IsGearReceive(3))) + bitStore.ReceiveByGear(8) + fmt.Println(fmt.Sprintf("这个时候领取结果 8应该返回true,结果是:%v", bitStore.IsGearReceive(8))) + bitStore.ReceiveByGear(16) + fmt.Println(fmt.Sprintf("这个时候领取结果 16应该返回true,结果是:%v", bitStore.IsGearReceive(16))) + bitStore.ReceiveByGear(18) + fmt.Println(fmt.Sprintf("这个时候领取结果 18应该返回true,结果是:%v", bitStore.IsGearReceive(18))) + + fmt.Println() + gearMap1 := bitStore.FindAllGearMap() + for key, value := range gearMap1 { + fmt.Println(fmt.Sprintf("当前map的key为%d,当前map的value为%v", key, value)) + } +} + +func testTen() { + bitStore := NewBitStore(10, nil) + + newStoreMap(bitStore) //初始化的校验 + fmt.Println() + bitStore.ReceiveByGear(3) + fmt.Println(fmt.Sprintf("这个时候领取结果 3应该返回true,结果是:%v", bitStore.IsGearReceive(3))) + + fmt.Println() + bitStore.ReceiveByGear(7) + fmt.Println(fmt.Sprintf("这个时候领取结果 7应该返回true,结果是:%v", bitStore.IsGearReceive(7))) + + fmt.Println() + gearMap1 := bitStore.FindAllGearMap() + for key, value := range gearMap1 { + fmt.Println(fmt.Sprintf("当前map的key为%d,当前map的value为%v", key, value)) + } +} + +func testTwo() { + bitStore := NewBitStore(2, nil) + + newStoreMap(bitStore) //初始化的校验 + fmt.Println() + bitStore.ReceiveByGear(1) + fmt.Println(fmt.Sprintf("这个时候领取结果 1应该返回true,结果是:%v", bitStore.IsGearReceive(1))) + + fmt.Println() + gearMap1 := bitStore.FindAllGearMap() + for key, value := range gearMap1 { + fmt.Println(fmt.Sprintf("当前map的key为%d,当前map的value为%v", key, value)) + } +} diff --git a/util/bitStore/readme.md b/util/bitStore/readme.md new file mode 100644 index 0000000..48a23cf --- /dev/null +++ b/util/bitStore/readme.md @@ -0,0 +1,83 @@ +# 基本说明 + +作者:黄志军 + +代码审核:老施 + +时间: 2020/10/27 15:19 + + + +# 设计目的 + +​ 本工具类设计主要目的是为了实现通过bit位来存储不同档位奖励的领取情况,这边领取情况分为**0**,**1**两种,也就是当前档位奖励**已经被领取**和**未被领取**两种情况。 + + + +# 参数说明 + +#### const静态参数 + +​ bit:表示当前数组的**每个数字代表的档位**,比如说当前bit=32,如此的话,下面的属性**GearPickList**数组的每个元素就是代表了32个档位,如果bit = 30,则代表了30个档位。 + +​ 因为int类型最大是64位,所以在修改的时候设置bit最多为64位,超过则会出现奇怪的问题,无法保证。 + +​ 且有些机器int只支持32位,则需要根据不同的机器进行对应的设置,才能保证程序的完整功能实现。 + +#### BitStore属性参数 + +​ MaxGear:当前支持存储的最大档位,这边的最大档位是初始化的时候进行设置的。根据bit的值,拆分出对应数量的数组来表示每一个对应的档位。比如说这边的bit = 32.需要存储的最大档位是33,则数组通过两个元素进行档位确认。第一个数最多达到32位的存储,第二个数,最多存储1位。 + +​ GearPickList:数组,用来表示对应档位的奖励,举例,bit = 32,数组的第一个元素表示的是1-32档的档位领取情况,第二个数组表示33-64档的档位领取情况...当然这边最大的档位取决于MaxGear。 + +​ 支持动态增长、初始化。某一时刻数组长度不能代表对应的档位信息,因为其支持动态增长,长度与所属所有档位不一定对的上。 + + + +# 方法使用说明 + +#### 初始化方法 + +NewBitStore:这边接受两个参数 + +- 一个是最大的档位设置,这个是根据每次处理的最大档位进行传入的 + +- 一个是档位数组,这边支持传入nil,[]int,0 、或者是带有元素的数组(表示有存档信息,比如说从数据库中获取到的,表示前一次存储的结果.) + + + +#### 所有档位领取情况Map + +FindAllGearMap: + +​ 该方法支持返回所有档位领取情况的map.奖励已经领取则返回true,奖励未领取则返回false。 + +​ 因为**GearPickList**数组支持动态增长,所以该方法对应完整数组和非完整数组拥有两套不同的实现方案,具体详见代码 + +#### + + + +#### 判断奖励是否被领取 + +IsGearReceive: + +​ 该方法会先检测传入的档位信息是否正确 + +​ 若当前**GearPickList**数组未被初始化,则进行初始化(动态性) + +​ 判断档位长度和数组长度对应关系,如果数组长度非完整,直接返回false,如果是被领取的,则当前档位对应的数组必定是完整的 + +​ 若档位完整,则通过与运算计算对应档位的领取情况.(true表示已领取,false表示未领取) + + + +#### 获取对应档位奖励 + +ReceiveByGear: + +​ 领取对应档位的奖励,返回奖励档位数组**GearPickList**及所有档位领取情况map。 + +​ 判断对应档位是否被领取,如果被领取则直接报错 + +​ 此方法对**GearPickList**的长度进行动态增长,并将对应档位的移位信息加到数组对应位置的元素上 \ No newline at end of file diff --git a/util/timed/TestTimeIntervalUtil_test.go b/util/timed/TestTimeIntervalUtil_test.go index 3155017..02da6f9 100644 --- a/util/timed/TestTimeIntervalUtil_test.go +++ b/util/timed/TestTimeIntervalUtil_test.go @@ -42,6 +42,9 @@ func TestTimeIntervalUtil(t *testing.T) { o2 := GetIntervalBetweenTimes(time.Now().AddDate(3, 2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix(), time.Now().Unix()) o3 := GetIntervalBetweenTimes(time.Now().Unix(), time.Now().AddDate(3, -2, 5).Add(5*time.Hour).Add(7*time.Minute).Add(10*time.Second).Unix()) + ox := GetIntervalBetweenTimes(time.Now().Unix(), time.Date(2020, 5, 6, 0, 0, 0, 0, time.Local).Unix()) + fmt.Println(ox) + fmt.Println(o1.IntervalYear, " y ", o1.IntervalMonth, " m ", o1.IntervalDay, " d ", o1.IntervalHour, " H ", o1.IntervalMinute, " mm ", o1.IntervalSecond, " ss ") fmt.Println(o2.IntervalYear, " y ", o2.IntervalMonth, " m ", o2.IntervalDay, " d ", o2.IntervalHour, " H ", o2.IntervalMinute, " mm ", o2.IntervalSecond, " ss ") fmt.Println(o3.IntervalYear, " y ", o3.IntervalMonth, " m ", o3.IntervalDay, " d ", o3.IntervalHour, " H ", o3.IntervalMinute, " mm ", o3.IntervalSecond, " ss ")