docs: 优化文档展示,适配部分无目录文档,适配非结构体的类型定义,增加测试用例文档

This commit is contained in:
kercylan 2024-01-14 18:32:44 +08:00
parent 83beeb43ce
commit b2fdaa2ae6
80 changed files with 9523 additions and 1473 deletions

View File

@ -1,19 +1,20 @@
# Configuration
configuration 基于配置导表功能实现的配置加载及刷新功能
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/configuration)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
configuration 基于配置导表功能实现的配置加载及刷新功能
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Init](#Init)|配置初始化
|[Load](#Load)|加载配置
@ -24,54 +25,66 @@ configuration 基于配置导表功能实现的配置加载及刷新功能
|[OnConfigRefreshEvent](#OnConfigRefreshEvent)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[RefreshEventHandle](#refresheventhandle)|配置刷新事件处理函数
|[Loader](#loader)|配置加载器
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[RefreshEventHandle](#refresheventhandle)|配置刷新事件处理函数
|`INTERFACE`|[Loader](#loader)|配置加载器
</details>
***
## 详情信息
#### func Init(loader ...Loader)
<span id="Init"></span>
> 配置初始化
> - 在初始化后会立即加载配置
***
#### func Load()
<span id="Load"></span>
> 加载配置
> - 加载后并不会刷新线上配置,需要执行 Refresh 函数对线上配置进行刷新
***
#### func Refresh()
<span id="Refresh"></span>
> 刷新配置
***
#### func WithTickerLoad(ticker *timer.Ticker, interval time.Duration)
<span id="WithTickerLoad"></span>
> 通过定时器加载配置
> - 通过定时器加载配置后,会自动刷新线上配置
> - 调用该函数后不会立即刷新,而是在 interval 后加载并刷新一次配置,之后每隔 interval 加载并刷新一次配置
***
#### func StopTickerLoad()
<span id="StopTickerLoad"></span>
> 停止通过定时器加载配置
***
#### func RegConfigRefreshEvent(handle RefreshEventHandle)
<span id="RegConfigRefreshEvent"></span>
> 当配置刷新时将立即执行被注册的事件处理函数
***
#### func OnConfigRefreshEvent()
<span id="OnConfigRefreshEvent"></span>
***
### RefreshEventHandle
### RefreshEventHandle `STRUCT`
配置刷新事件处理函数
```go
type RefreshEventHandle struct{}
type RefreshEventHandle func()
```
### Loader
### Loader `INTERFACE`
配置加载器
```go
type Loader struct{}
type Loader interface {
Load()
Refresh()
}
```

View File

@ -1,27 +1,22 @@
# Main
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/main)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,27 +1,22 @@
# Main
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/main)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,27 +1,22 @@
# Main
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/main)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,27 +1,22 @@
# Main
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/main)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,27 +1,22 @@
# Main
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/main)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,27 +1,10 @@
# Game
game 目录下包含了各类通用的游戏玩法性内容,其中该目录主要为基础性内容,具体目录将对应不同的游戏功能性内容。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/game)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
> 包级函数定义
|函数|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
game 目录下包含了各类通用的游戏玩法性内容,其中该目录主要为基础性内容,具体目录将对应不同的游戏功能性内容。
***
## 详情信息

View File

@ -1,19 +1,20 @@
# Activity
activity 活动状态管理
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/activity)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
activity 活动状态管理
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[SetTicker](#SetTicker)|设置自定义定时器,该方法必须在使用活动系统前调用,且只能调用一次
|[LoadGlobalData](#LoadGlobalData)|加载所有活动全局数据
@ -38,111 +39,134 @@ activity 活动状态管理
|[NewOptions](#NewOptions)|创建活动选项
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Activity](#activity)|活动描述
|[Controller](#controller)|活动控制器
|[BasicActivityController](#basicactivitycontroller)|暂无描述...
|[NoneDataActivityController](#nonedataactivitycontroller)|无数据活动控制器
|[GlobalDataActivityController](#globaldataactivitycontroller)|全局数据活动控制器
|[EntityDataActivityController](#entitydataactivitycontroller)|实体数据活动控制器
|[GlobalAndEntityDataActivityController](#globalandentitydataactivitycontroller)|全局数据和实体数据活动控制器
|[DataMeta](#datameta)|全局活动数据
|[EntityDataMeta](#entitydatameta)|活动实体数据
|[UpcomingEventHandler](#upcomingeventhandler)|暂无描述...
|[Options](#options)|活动选项
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Activity](#activity)|活动描述
|`STRUCT`|[Controller](#controller)|活动控制器
|`INTERFACE`|[BasicActivityController](#basicactivitycontroller)|暂无描述...
|`INTERFACE`|[NoneDataActivityController](#nonedataactivitycontroller)|无数据活动控制器
|`INTERFACE`|[GlobalDataActivityController](#globaldataactivitycontroller)|全局数据活动控制器
|`INTERFACE`|[EntityDataActivityController](#entitydataactivitycontroller)|实体数据活动控制器
|`INTERFACE`|[GlobalAndEntityDataActivityController](#globalandentitydataactivitycontroller)|全局数据和实体数据活动控制器
|`STRUCT`|[DataMeta](#datameta)|全局活动数据
|`STRUCT`|[EntityDataMeta](#entitydatameta)|活动实体数据
|`STRUCT`|[UpcomingEventHandler](#upcomingeventhandler)|暂无描述...
|`STRUCT`|[Options](#options)|活动选项
</details>
***
## 详情信息
#### func SetTicker(size int, options ...timer.Option)
<span id="SetTicker"></span>
> 设置自定义定时器,该方法必须在使用活动系统前调用,且只能调用一次
***
#### func LoadGlobalData(handler func (activityType any))
<span id="LoadGlobalData"></span>
> 加载所有活动全局数据
***
#### func LoadEntityData(handler func (activityType any))
<span id="LoadEntityData"></span>
> 加载所有活动实体数据
***
#### func LoadOrRefreshActivity(activityType Type, activityId ID, options ...*Options) error
<span id="LoadOrRefreshActivity"></span>
> 加载或刷新活动
> - 通常在活动配置刷新时候将活动通过该方法注册或刷新
***
#### func DefineNoneDataActivity(activityType Type) NoneDataActivityController[Type, ID, *none, none, *none]
<span id="DefineNoneDataActivity"></span>
> 声明无数据的活动类型
***
#### func DefineGlobalDataActivity(activityType Type) GlobalDataActivityController[Type, ID, Data, none, *none]
<span id="DefineGlobalDataActivity"></span>
> 声明拥有全局数据的活动类型
***
#### func DefineEntityDataActivity(activityType Type) EntityDataActivityController[Type, ID, *none, EntityID, EntityData]
<span id="DefineEntityDataActivity"></span>
> 声明拥有实体数据的活动类型
***
#### func DefineGlobalAndEntityDataActivity(activityType Type) GlobalAndEntityDataActivityController[Type, ID, Data, EntityID, EntityData]
<span id="DefineGlobalAndEntityDataActivity"></span>
> 声明拥有全局数据和实体数据的活动类型
***
#### func RegUpcomingEvent(activityType Type, handler UpcomingEventHandler[ID], priority ...int)
<span id="RegUpcomingEvent"></span>
> 注册即将开始的活动事件处理器
***
#### func OnUpcomingEvent(activity *Activity[Type, ID])
<span id="OnUpcomingEvent"></span>
> 即将开始的活动事件
***
#### func RegStartedEvent(activityType Type, handler StartedEventHandler[ID], priority ...int)
<span id="RegStartedEvent"></span>
> 注册活动开始事件处理器
***
#### func OnStartedEvent(activity *Activity[Type, ID])
<span id="OnStartedEvent"></span>
> 活动开始事件
***
#### func RegEndedEvent(activityType Type, handler EndedEventHandler[ID], priority ...int)
<span id="RegEndedEvent"></span>
> 注册活动结束事件处理器
***
#### func OnEndedEvent(activity *Activity[Type, ID])
<span id="OnEndedEvent"></span>
> 活动结束事件
***
#### func RegExtendedShowStartedEvent(activityType Type, handler ExtendedShowStartedEventHandler[ID], priority ...int)
<span id="RegExtendedShowStartedEvent"></span>
> 注册活动结束后延长展示开始事件处理器
***
#### func OnExtendedShowStartedEvent(activity *Activity[Type, ID])
<span id="OnExtendedShowStartedEvent"></span>
> 活动结束后延长展示开始事件
***
#### func RegExtendedShowEndedEvent(activityType Type, handler ExtendedShowEndedEventHandler[ID], priority ...int)
<span id="RegExtendedShowEndedEvent"></span>
> 注册活动结束后延长展示结束事件处理器
***
#### func OnExtendedShowEndedEvent(activity *Activity[Type, ID])
<span id="OnExtendedShowEndedEvent"></span>
> 活动结束后延长展示结束事件
***
#### func RegNewDayEvent(activityType Type, handler NewDayEventHandler[ID], priority ...int)
<span id="RegNewDayEvent"></span>
> 注册新的一天事件处理器
***
#### func OnNewDayEvent(activity *Activity[Type, ID])
<span id="OnNewDayEvent"></span>
> 新的一天事件
***
#### func NewOptions() *Options
<span id="NewOptions"></span>
> 创建活动选项
***
### Activity
### Activity `STRUCT`
活动描述
```go
type Activity[Type generic.Basic, ID generic.Basic] struct {
@ -161,7 +185,7 @@ type Activity[Type generic.Basic, ID generic.Basic] struct {
initializeData func()
}
```
### Controller
### Controller `STRUCT`
活动控制器
```go
type Controller[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] struct {
@ -175,32 +199,53 @@ type Controller[Type generic.Basic, ID generic.Basic, Data any, EntityID generic
mutex sync.RWMutex
}
```
### BasicActivityController
### BasicActivityController `INTERFACE`
```go
type BasicActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] struct{}
type BasicActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] interface {
IsOpen(activityId ID) bool
IsShow(activityId ID) bool
IsOpenOrShow(activityId ID) bool
Refresh(activityId ID)
}
```
### NoneDataActivityController
### NoneDataActivityController `INTERFACE`
无数据活动控制器
```go
type NoneDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] struct{}
type NoneDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] interface {
BasicActivityController[Type, ID, Data, EntityID, EntityData]
InitializeNoneData(handler func(activityId ID, data *DataMeta[Data])) NoneDataActivityController[Type, ID, Data, EntityID, EntityData]
}
```
### GlobalDataActivityController
### GlobalDataActivityController `INTERFACE`
全局数据活动控制器
```go
type GlobalDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] struct{}
type GlobalDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] interface {
BasicActivityController[Type, ID, Data, EntityID, EntityData]
GetGlobalData(activityId ID) Data
InitializeGlobalData(handler func(activityId ID, data *DataMeta[Data])) GlobalDataActivityController[Type, ID, Data, EntityID, EntityData]
}
```
### EntityDataActivityController
### EntityDataActivityController `INTERFACE`
实体数据活动控制器
```go
type EntityDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] struct{}
type EntityDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] interface {
BasicActivityController[Type, ID, Data, EntityID, EntityData]
GetEntityData(activityId ID, entityId EntityID) EntityData
InitializeEntityData(handler func(activityId ID, entityId EntityID, data *EntityDataMeta[EntityData])) EntityDataActivityController[Type, ID, Data, EntityID, EntityData]
}
```
### GlobalAndEntityDataActivityController
### GlobalAndEntityDataActivityController `INTERFACE`
全局数据和实体数据活动控制器
```go
type GlobalAndEntityDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] struct{}
type GlobalAndEntityDataActivityController[Type generic.Basic, ID generic.Basic, Data any, EntityID generic.Basic, EntityData any] interface {
BasicActivityController[Type, ID, Data, EntityID, EntityData]
GetGlobalData(activityId ID) Data
GetEntityData(activityId ID, entityId EntityID) EntityData
InitializeGlobalAndEntityData(handler func(activityId ID, data *DataMeta[Data]), entityHandler func(activityId ID, entityId EntityID, data *EntityDataMeta[EntityData])) GlobalAndEntityDataActivityController[Type, ID, Data, EntityID, EntityData]
}
```
### DataMeta
### DataMeta `STRUCT`
全局活动数据
```go
type DataMeta[Data any] struct {
@ -209,7 +254,7 @@ type DataMeta[Data any] struct {
LastNewDay time.Time
}
```
### EntityDataMeta
### EntityDataMeta `STRUCT`
活动实体数据
```go
type EntityDataMeta[Data any] struct {
@ -218,12 +263,12 @@ type EntityDataMeta[Data any] struct {
LastNewDay time.Time
}
```
### UpcomingEventHandler
### UpcomingEventHandler `STRUCT`
```go
type UpcomingEventHandler[ID generic.Basic] struct{}
type UpcomingEventHandler[ID generic.Basic] func(activityId ID)
```
### Options
### Options `STRUCT`
活动选项
```go
type Options struct {

View File

@ -1,27 +1,22 @@
# Main
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/main)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,27 +1,22 @@
# Activities
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/activities)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,27 +1,22 @@
# Demoactivity
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/demoactivity)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,32 +1,29 @@
# Types
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/types)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
> 类型定义
|函数|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
|[DemoActivityData](#demoactivitydata)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[DemoActivityData](#demoactivitydata)|暂无描述...
</details>
### DemoActivityData
***
## 详情信息
### DemoActivityData `STRUCT`
```go
type DemoActivityData struct {

View File

@ -1,42 +1,46 @@
# Fight
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/fight)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewTurnBased](#NewTurnBased)|创建一个新的回合制
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[TurnBased](#turnbased)|回合制
|[TurnBasedControllerInfo](#turnbasedcontrollerinfo)|暂无描述...
|[TurnBasedControllerAction](#turnbasedcontrolleraction)|暂无描述...
|[TurnBasedController](#turnbasedcontroller)|回合制控制器
|[TurnBasedEntitySwitchEventHandler](#turnbasedentityswitcheventhandler)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[TurnBased](#turnbased)|回合制
|`INTERFACE`|[TurnBasedControllerInfo](#turnbasedcontrollerinfo)|暂无描述...
|`INTERFACE`|[TurnBasedControllerAction](#turnbasedcontrolleraction)|暂无描述...
|`STRUCT`|[TurnBasedController](#turnbasedcontroller)|回合制控制器
|`STRUCT`|[TurnBasedEntitySwitchEventHandler](#turnbasedentityswitcheventhandler)|暂无描述...
</details>
***
## 详情信息
#### func NewTurnBased(calcNextTurnDuration func ( Camp, Entity) time.Duration) *TurnBased[CampID, EntityID, Camp, Entity]
<span id="NewTurnBased"></span>
> 创建一个新的回合制
> - calcNextTurnDuration 将返回下一次行动时间间隔,适用于按照速度计算下一次行动时间间隔的情况。当返回 0 时,将使用默认的行动超时时间
***
### TurnBased
### TurnBased `STRUCT`
回合制
```go
type TurnBased[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] struct {
@ -60,25 +64,37 @@ type TurnBased[CampID comparable, EntityID comparable, Camp generic.IdR[CampID],
closed bool
}
```
### TurnBasedControllerInfo
### TurnBasedControllerInfo `INTERFACE`
```go
type TurnBasedControllerInfo[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] struct{}
type TurnBasedControllerInfo[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] interface {
GetRound() int
GetCamp() Camp
GetEntity() Entity
GetActionTimeoutDuration() time.Duration
GetActionStartTime() time.Time
GetActionEndTime() time.Time
Stop()
}
```
### TurnBasedControllerAction
### TurnBasedControllerAction `INTERFACE`
```go
type TurnBasedControllerAction[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] struct{}
type TurnBasedControllerAction[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] interface {
TurnBasedControllerInfo[CampID, EntityID, Camp, Entity]
Finish()
Refresh(duration time.Duration) time.Time
}
```
### TurnBasedController
### TurnBasedController `STRUCT`
回合制控制器
```go
type TurnBasedController[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] struct {
tb *TurnBased[CampID, EntityID, Camp, Entity]
}
```
### TurnBasedEntitySwitchEventHandler
### TurnBasedEntitySwitchEventHandler `STRUCT`
```go
type TurnBasedEntitySwitchEventHandler[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] struct{}
type TurnBasedEntitySwitchEventHandler[CampID comparable, EntityID comparable, Camp generic.IdR[CampID], Entity generic.IdR[EntityID]] func(controller TurnBasedControllerAction[CampID, EntityID, Camp, Entity])
```

View File

@ -1,45 +1,60 @@
# Space
space 游戏中常见的空间设计,例如房间、地图等
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/space)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
space 游戏中常见的空间设计,例如房间、地图等
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewRoomManager](#NewRoomManager)|创建房间管理器 RoomManager 的实例
|[NewRoomControllerOptions](#NewRoomControllerOptions)|创建房间控制器选项
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[RoomController](#roomcontroller)|对房间进行操作的控制器,由 RoomManager 接管后返回
|[RoomManager](#roommanager)|房间管理器是用于对房间进行管理的基本单元,通过该实例可以对房间进行增删改查等操作
|[RoomAssumeControlEventHandle](#roomassumecontroleventhandle)|暂无描述...
|[RoomControllerOptions](#roomcontrolleroptions)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[RoomController](#roomcontroller)|对房间进行操作的控制器,由 RoomManager 接管后返回
|`STRUCT`|[RoomManager](#roommanager)|房间管理器是用于对房间进行管理的基本单元,通过该实例可以对房间进行增删改查等操作
|`STRUCT`|[RoomAssumeControlEventHandle](#roomassumecontroleventhandle)|暂无描述...
|`STRUCT`|[RoomControllerOptions](#roomcontrolleroptions)|暂无描述...
</details>
***
## 详情信息
#### func NewRoomManager() *RoomManager[EntityID, RoomID, Entity, Room]
<span id="NewRoomManager"></span>
> 创建房间管理器 RoomManager 的实例
示例代码:
```go
func ExampleNewRoomManager() {
var rm = space.NewRoomManager[string, int64, *Player, *Room]()
fmt.Println(rm == nil)
}
```
***
#### func NewRoomControllerOptions() *RoomControllerOptions[EntityID, RoomID, Entity, Room]
<span id="NewRoomControllerOptions"></span>
> 创建房间控制器选项
***
### RoomController
### RoomController `STRUCT`
对房间进行操作的控制器,由 RoomManager 接管后返回
```go
type RoomController[EntityID comparable, RoomID comparable, Entity generic.IdR[EntityID], Room generic.IdR[RoomID]] struct {
@ -53,7 +68,7 @@ type RoomController[EntityID comparable, RoomID comparable, Entity generic.IdR[E
owner *EntityID
}
```
### RoomManager
### RoomManager `STRUCT`
房间管理器是用于对房间进行管理的基本单元,通过该实例可以对房间进行增删改查等操作
- 该实例是线程安全的
```go
@ -63,12 +78,12 @@ type RoomManager[EntityID comparable, RoomID comparable, Entity generic.IdR[Enti
rooms map[RoomID]*RoomController[EntityID, RoomID, Entity, Room]
}
```
### RoomAssumeControlEventHandle
### RoomAssumeControlEventHandle `STRUCT`
```go
type RoomAssumeControlEventHandle[EntityID comparable, RoomID comparable, Entity generic.IdR[EntityID], Room generic.IdR[RoomID]] struct{}
type RoomAssumeControlEventHandle[EntityID comparable, RoomID comparable, Entity generic.IdR[EntityID], Room generic.IdR[RoomID]] func(controller *RoomController[EntityID, RoomID, Entity, Room])
```
### RoomControllerOptions
### RoomControllerOptions `STRUCT`
```go
type RoomControllerOptions[EntityID comparable, RoomID comparable, Entity generic.IdR[EntityID], Room generic.IdR[RoomID]] struct {

View File

@ -1,19 +1,20 @@
# Task
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/task)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Cond](#Cond)|创建任务条件
|[RegisterRefreshTaskCounterEvent](#RegisterRefreshTaskCounterEvent)|注册特定任务类型的刷新任务计数器事件处理函数
@ -29,48 +30,95 @@
|[NewTask](#NewTask)|生成任务
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Condition](#condition)|任务条件
|[RefreshTaskCounterEventHandler](#refreshtaskcountereventhandler)|暂无描述...
|[Option](#option)|任务选项
|[Status](#status)|暂无描述...
|[Task](#task)|是对任务信息进行描述和处理的结构体
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Condition](#condition)|任务条件
|`STRUCT`|[RefreshTaskCounterEventHandler](#refreshtaskcountereventhandler)|暂无描述...
|`STRUCT`|[Option](#option)|任务选项
|`STRUCT`|[Status](#status)|暂无描述...
|`STRUCT`|[Task](#task)|是对任务信息进行描述和处理的结构体
</details>
***
## 详情信息
#### func Cond(k any, v any) Condition
<span id="Cond"></span>
> 创建任务条件
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestCond(t *testing.T) {
task := NewTask(WithType("T"), WithCounter(5), WithCondition(Cond("N", 5).Cond("M", 10)))
task.AssignConditionValueAndRefresh("N", 5)
task.AssignConditionValueAndRefresh("M", 10)
RegisterRefreshTaskCounterEvent[*Player](task.Type, func(taskType string, trigger *Player, count int64) {
fmt.Println("Player", count)
for _, t := range trigger.tasks[taskType] {
fmt.Println(t.CurrCount, t.IncrementCounter(count).Status)
}
})
RegisterRefreshTaskConditionEvent[*Player](task.Type, func(taskType string, trigger *Player, condition Condition) {
fmt.Println("Player", condition)
for _, t := range trigger.tasks[taskType] {
fmt.Println(t.CurrCount, t.AssignConditionValueAndRefresh("N", 5).Status)
}
})
RegisterRefreshTaskCounterEvent[*Monster](task.Type, func(taskType string, trigger *Monster, count int64) {
fmt.Println("Monster", count)
})
player := &Player{tasks: map[string][]*Task{task.Type: {task}}}
OnRefreshTaskCounterEvent(task.Type, player, 1)
OnRefreshTaskCounterEvent(task.Type, player, 2)
OnRefreshTaskCounterEvent(task.Type, player, 3)
OnRefreshTaskCounterEvent(task.Type, new(Monster), 3)
}
```
</details>
***
#### func RegisterRefreshTaskCounterEvent(taskType string, handler RefreshTaskCounterEventHandler[Trigger])
<span id="RegisterRefreshTaskCounterEvent"></span>
> 注册特定任务类型的刷新任务计数器事件处理函数
***
#### func OnRefreshTaskCounterEvent(taskType string, trigger any, count int64)
<span id="OnRefreshTaskCounterEvent"></span>
> 触发特定任务类型的刷新任务计数器事件
***
#### func RegisterRefreshTaskConditionEvent(taskType string, handler RefreshTaskConditionEventHandler[Trigger])
<span id="RegisterRefreshTaskConditionEvent"></span>
> 注册特定任务类型的刷新任务条件事件处理函数
***
#### func OnRefreshTaskConditionEvent(taskType string, trigger any, condition Condition)
<span id="OnRefreshTaskConditionEvent"></span>
> 触发特定任务类型的刷新任务条件事件
***
#### func WithType(taskType string) Option
<span id="WithType"></span>
> 设置任务类型
***
#### func WithCondition(condition Condition) Option
<span id="WithCondition"></span>
> 设置任务完成条件,当满足条件时,任务状态为完成
> - 任务条件值需要变更时可通过 Task.AssignConditionValueAndRefresh 方法变更
> - 当多次设置该选项时,后面的设置会覆盖之前的设置
***
#### func WithCounter(counter int64, initCount ...int64) Option
<span id="WithCounter"></span>
@ -78,29 +126,34 @@
> - 一些场景下,任务计数器可能会溢出,此时可通过 WithOverflowCounter 设置可溢出的任务计数器
> - 当多次设置该选项时,后面的设置会覆盖之前的设置
> - 如果需要初始化计数器的值,可通过 initCount 参数设置
***
#### func WithOverflowCounter(counter int64, initCount ...int64) Option
<span id="WithOverflowCounter"></span>
> 设置可溢出的任务计数器,当计数器达到要求时,任务状态为完成
> - 当多次设置该选项时,后面的设置会覆盖之前的设置
> - 如果需要初始化计数器的值,可通过 initCount 参数设置
***
#### func WithDeadline(deadline time.Time) Option
<span id="WithDeadline"></span>
> 设置任务截止时间,超过截至时间并且任务未完成时,任务状态为失败
***
#### func WithLimitedDuration(start time.Time, duration time.Duration) Option
<span id="WithLimitedDuration"></span>
> 设置任务限时,超过限时时间并且任务未完成时,任务状态为失败
***
#### func NewTask(options ...Option) *Task
<span id="NewTask"></span>
> 生成任务
***
### Condition
### Condition `STRUCT`
任务条件
```go
type Condition struct{}
type Condition map[any]any
```
#### func (Condition) Cond(k any, v any) Condition
> 创建任务条件
@ -168,24 +221,24 @@ type Condition struct{}
#### func (Condition) GetAny(key any) any
> 获取特定类型的任务条件值,该值必须与预期类型一致,否则返回零值
***
### RefreshTaskCounterEventHandler
### RefreshTaskCounterEventHandler `STRUCT`
```go
type RefreshTaskCounterEventHandler[Trigger any] struct{}
type RefreshTaskCounterEventHandler[Trigger any] func(taskType string, trigger Trigger, count int64)
```
### Option
### Option `STRUCT`
任务选项
```go
type Option struct{}
type Option func(task *Task)
```
### Status
### Status `STRUCT`
```go
type Status struct{}
type Status byte
```
#### func (Status) String() string
***
### Task
### Task `STRUCT`
是对任务信息进行描述和处理的结构体
```go
type Task struct {

View File

@ -1,39 +1,43 @@
# Notify
notify 包含了对外部第三方通知的实现,如机器人消息等
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/notify)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
notify 包含了对外部第三方通知的实现,如机器人消息等
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewManager](#NewManager)|通过指定的 Sender 创建一个通知管理器, senders 包中提供了一些内置的 Sender
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Manager](#manager)|通知管理器,可用于将通知同时发送至多个渠道
|[Notify](#notify)|通用通知接口定义
|[Sender](#sender)|通知发送器接口声明
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Manager](#manager)|通知管理器,可用于将通知同时发送至多个渠道
|`INTERFACE`|[Notify](#notify)|通用通知接口定义
|`INTERFACE`|[Sender](#sender)|通知发送器接口声明
</details>
***
## 详情信息
#### func NewManager(senders ...Sender) *Manager
<span id="NewManager"></span>
> 通过指定的 Sender 创建一个通知管理器, senders 包中提供了一些内置的 Sender
***
### Manager
### Manager `STRUCT`
通知管理器,可用于将通知同时发送至多个渠道
```go
type Manager struct {
@ -48,13 +52,17 @@ type Manager struct {
#### func (*Manager) Release()
> 释放通知管理器
***
### Notify
### Notify `INTERFACE`
通用通知接口定义
```go
type Notify struct{}
type Notify interface {
Format() (string, error)
}
```
### Sender
### Sender `INTERFACE`
通知发送器接口声明
```go
type Sender struct{}
type Sender interface {
Push(notify Notify) error
}
```

View File

@ -1,19 +1,20 @@
# Notifies
notifies 包含了内置通知内容的实现
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/notifies)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
notifies 包含了内置通知内容的实现
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewFeiShu](#NewFeiShu)|创建飞书通知消息
|[FeiShuMessageWithText](#FeiShuMessageWithText)|飞书文本消息
@ -30,21 +31,24 @@ notifies 包含了内置通知内容的实现
|[NewFeiShuRichText](#NewFeiShuRichText)|创建一个飞书富文本
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[FeiShu](#feishu)|飞书通知消息
|[FeiShuMessage](#feishumessage)|暂无描述...
|[FeiShuRichText](#feishurichtext)|飞书富文本结构
|[FeiShuRichTextContent](#feishurichtextcontent)|飞书富文本内容体
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[FeiShu](#feishu)|飞书通知消息
|`STRUCT`|[FeiShuMessage](#feishumessage)|暂无描述...
|`STRUCT`|[FeiShuRichText](#feishurichtext)|飞书富文本结构
|`STRUCT`|[FeiShuRichTextContent](#feishurichtextcontent)|飞书富文本内容体
</details>
***
## 详情信息
#### func NewFeiShu(message FeiShuMessage) *FeiShu
<span id="NewFeiShu"></span>
> 创建飞书通知消息
***
#### func FeiShuMessageWithText(text string) FeiShuMessage
<span id="FeiShuMessageWithText"></span>
@ -62,20 +66,24 @@ notifies 包含了内置通知内容的实现
> 超链接使用说明
> - 超链接的使用格式为[文本](链接) 如[Feishu Open Platform](https://open.feishu.cn) 。
> - 请确保链接是合法的,否则会以原始内容发送消息。
***
#### func FeiShuMessageWithRichText(richText *FeiShuRichText) FeiShuMessage
<span id="FeiShuMessageWithRichText"></span>
> 飞书富文本消息
***
#### func FeiShuMessageWithImage(imageKey string) FeiShuMessage
<span id="FeiShuMessageWithImage"></span>
> 飞书图片消息
> - imageKey 可通过上传图片接口获取
***
#### func FeiShuMessageWithInteractive(json string) FeiShuMessage
<span id="FeiShuMessageWithInteractive"></span>
> 飞书卡片消息
> - json 表示卡片的 json 数据或者消息模板的 json 数据
***
#### func FeiShuMessageWithShareChat(chatId string) FeiShuMessage
<span id="FeiShuMessageWithShareChat"></span>
@ -83,6 +91,7 @@ notifies 包含了内置通知内容的实现
> - chatId 群ID获取方式请参见群ID说明
>
> 群ID说明https://open.feishu.cn/document/server-docs/group/chat/chat-id-description
***
#### func FeiShuMessageWithShareUser(userId string) FeiShuMessage
<span id="FeiShuMessageWithShareUser"></span>
@ -90,6 +99,7 @@ notifies 包含了内置通知内容的实现
> - userId 表示用户的 OpenID 获取方式请参见了解更多:如何获取 Open ID
>
> 如何获取 Open IDhttps://open.feishu.cn/document/faq/trouble-shooting/how-to-obtain-openid
***
#### func FeiShuMessageWithAudio(fileKey string) FeiShuMessage
<span id="FeiShuMessageWithAudio"></span>
@ -97,6 +107,7 @@ notifies 包含了内置通知内容的实现
> - fileKey 语音文件Key可通过上传文件接口获取
>
> 上传文件https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/file/create
***
#### func FeiShuMessageWithMedia(fileKey string) FeiShuMessage
<span id="FeiShuMessageWithMedia"></span>
@ -104,6 +115,7 @@ notifies 包含了内置通知内容的实现
> - fileKey 视频文件Key可通过上传文件接口获取
>
> 上传文件https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/file/create
***
#### func FeiShuMessageWithMediaAndCover(fileKey string, imageKey string) FeiShuMessage
<span id="FeiShuMessageWithMediaAndCover"></span>
@ -112,6 +124,7 @@ notifies 包含了内置通知内容的实现
> - imageKey 图片文件Key可通过上传文件接口获取
>
> 上传文件https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/file/create
***
#### func FeiShuMessageWithFile(fileKey string) FeiShuMessage
<span id="FeiShuMessageWithFile"></span>
@ -119,6 +132,7 @@ notifies 包含了内置通知内容的实现
> - fileKey 文件Key可通过上传文件接口获取
>
> 上传文件https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/file/create
***
#### func FeiShuMessageWithSticker(fileKey string) FeiShuMessage
<span id="FeiShuMessageWithSticker"></span>
@ -126,12 +140,14 @@ notifies 包含了内置通知内容的实现
> - fileKey 表情包文件Key目前仅支持发送机器人收到的表情包可通过接收消息事件的推送获取表情包 file_key。
>
> 接收消息事件https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/message/events/receive
***
#### func NewFeiShuRichText() *FeiShuRichText
<span id="NewFeiShuRichText"></span>
> 创建一个飞书富文本
***
### FeiShu
### FeiShu `STRUCT`
飞书通知消息
```go
type FeiShu struct {
@ -142,12 +158,12 @@ type FeiShu struct {
#### func (*FeiShu) Format() string, error
> 格式化通知内容
***
### FeiShuMessage
### FeiShuMessage `STRUCT`
```go
type FeiShuMessage struct{}
type FeiShuMessage func(feishu *FeiShu)
```
### FeiShuRichText
### FeiShuRichText `STRUCT`
飞书富文本结构
```go
type FeiShuRichText struct {
@ -157,7 +173,7 @@ type FeiShuRichText struct {
#### func (*FeiShuRichText) Create(lang string, title string) *FeiShuRichTextContent
> 创建一个特定语言和标题的富文本内容
***
### FeiShuRichTextContent
### FeiShuRichTextContent `STRUCT`
飞书富文本内容体
```go
type FeiShuRichTextContent struct {

View File

@ -1,37 +1,41 @@
# Senders
senders Package 包含了内置通知发送器的实现
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/senders)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
senders Package 包含了内置通知发送器的实现
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewFeiShu](#NewFeiShu)|根据特定的 webhook 地址创建飞书发送器
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[FeiShu](#feishu)|飞书发送器
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[FeiShu](#feishu)|飞书发送器
</details>
***
## 详情信息
#### func NewFeiShu(webhook string) *FeiShu
<span id="NewFeiShu"></span>
> 根据特定的 webhook 地址创建飞书发送器
***
### FeiShu
### FeiShu `STRUCT`
飞书发送器
```go
type FeiShu struct {
@ -41,4 +45,24 @@ type FeiShu struct {
```
#### func (*FeiShu) Push(notify notify.Notify) error
> 推送通知
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestFeiShu_Push(t *testing.T) {
fs := NewFeiShu("https://open.feishu.cn/open-apis/bot/v2/hook/d886f30f-814c-47b1-aeb0-b508da0f7f22")
rt := notifies.NewFeiShu(notifies.FeiShuMessageWithRichText(notifies.NewFeiShuRichText().Create("zh_cn", "标题咯").AddText("哈哈哈").Ok()))
if err := fs.Push(rt); err != nil {
panic(err)
}
}
```
</details>
***

View File

@ -1,27 +1,10 @@
# Planner
planner 包含了策划工具相关的内容
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/planner)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
> 包级函数定义
|函数|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
planner 包含了策划工具相关的内容
***
## 详情信息

View File

@ -1,19 +1,20 @@
# Pce
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/pce)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewExporter](#NewExporter)|创建导出器
|[GetFieldGolangType](#GetFieldGolangType)|获取字段的 Golang 类型
@ -21,81 +22,112 @@
|[NewLoader](#NewLoader)|创建加载器
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Config](#config)|配置解析接口
|[DataTmpl](#datatmpl)|数据导出模板
|[Exporter](#exporter)|导出器
|[Field](#field)|基本字段类型接口
|[Int](#int)|暂无描述...
|[Int8](#int8)|暂无描述...
|[Int16](#int16)|暂无描述...
|[Int32](#int32)|暂无描述...
|[Int64](#int64)|暂无描述...
|[Uint](#uint)|暂无描述...
|[Uint8](#uint8)|暂无描述...
|[Uint16](#uint16)|暂无描述...
|[Uint32](#uint32)|暂无描述...
|[Uint64](#uint64)|暂无描述...
|[Float32](#float32)|暂无描述...
|[Float64](#float64)|暂无描述...
|[String](#string)|暂无描述...
|[Bool](#bool)|暂无描述...
|[Byte](#byte)|暂无描述...
|[Rune](#rune)|暂无描述...
|[Complex64](#complex64)|暂无描述...
|[Complex128](#complex128)|暂无描述...
|[Uintptr](#uintptr)|暂无描述...
|[Double](#double)|暂无描述...
|[Float](#float)|暂无描述...
|[Long](#long)|暂无描述...
|[Short](#short)|暂无描述...
|[Char](#char)|暂无描述...
|[Number](#number)|暂无描述...
|[Integer](#integer)|暂无描述...
|[Boolean](#boolean)|暂无描述...
|[Loader](#loader)|配置加载器
|[DataInfo](#datainfo)|配置数据
|[DataField](#datafield)|配置数据字段
|[Tmpl](#tmpl)|配置结构模板接口
|[TmplField](#tmplfield)|模板字段
|[TmplStruct](#tmplstruct)|模板结构
|类型|名称|描述
|:--|:--|:--
|`INTERFACE`|[Config](#config)|配置解析接口
|`INTERFACE`|[DataTmpl](#datatmpl)|数据导出模板
|`STRUCT`|[Exporter](#exporter)|导出器
|`INTERFACE`|[Field](#field)|基本字段类型接口
|`STRUCT`|[Int](#int)|暂无描述...
|`STRUCT`|[Int8](#int8)|暂无描述...
|`STRUCT`|[Int16](#int16)|暂无描述...
|`STRUCT`|[Int32](#int32)|暂无描述...
|`STRUCT`|[Int64](#int64)|暂无描述...
|`STRUCT`|[Uint](#uint)|暂无描述...
|`STRUCT`|[Uint8](#uint8)|暂无描述...
|`STRUCT`|[Uint16](#uint16)|暂无描述...
|`STRUCT`|[Uint32](#uint32)|暂无描述...
|`STRUCT`|[Uint64](#uint64)|暂无描述...
|`STRUCT`|[Float32](#float32)|暂无描述...
|`STRUCT`|[Float64](#float64)|暂无描述...
|`STRUCT`|[String](#string)|暂无描述...
|`STRUCT`|[Bool](#bool)|暂无描述...
|`STRUCT`|[Byte](#byte)|暂无描述...
|`STRUCT`|[Rune](#rune)|暂无描述...
|`STRUCT`|[Complex64](#complex64)|暂无描述...
|`STRUCT`|[Complex128](#complex128)|暂无描述...
|`STRUCT`|[Uintptr](#uintptr)|暂无描述...
|`STRUCT`|[Double](#double)|暂无描述...
|`STRUCT`|[Float](#float)|暂无描述...
|`STRUCT`|[Long](#long)|暂无描述...
|`STRUCT`|[Short](#short)|暂无描述...
|`STRUCT`|[Char](#char)|暂无描述...
|`STRUCT`|[Number](#number)|暂无描述...
|`STRUCT`|[Integer](#integer)|暂无描述...
|`STRUCT`|[Boolean](#boolean)|暂无描述...
|`STRUCT`|[Loader](#loader)|配置加载器
|`STRUCT`|[DataInfo](#datainfo)|配置数据
|`STRUCT`|[DataField](#datafield)|配置数据字段
|`INTERFACE`|[Tmpl](#tmpl)|配置结构模板接口
|`STRUCT`|[TmplField](#tmplfield)|模板字段
|`STRUCT`|[TmplStruct](#tmplstruct)|模板结构
</details>
***
## 详情信息
#### func NewExporter() *Exporter
<span id="NewExporter"></span>
> 创建导出器
***
#### func GetFieldGolangType(field Field) string
<span id="GetFieldGolangType"></span>
> 获取字段的 Golang 类型
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestGetFieldGolangType(t *testing.T) {
fmt.Println(pce.GetFieldGolangType(new(pce.String)))
}
```
</details>
***
#### func GetFields() []Field
<span id="GetFields"></span>
> 获取所有内置支持的字段
***
#### func NewLoader(fields []Field) *Loader
<span id="NewLoader"></span>
> 创建加载器
> - 加载器被用于加载配置表的数据和结构信息
***
### Config
### Config `INTERFACE`
配置解析接口
- 用于将配置文件解析为可供分析的数据结构
- 可以在 cs 包中找到内置提供的实现及其模板,例如 cs.XlsxIndexConfig
```go
type Config struct{}
type Config interface {
GetConfigName() string
GetDisplayName() string
GetDescription() string
GetIndexCount() int
GetFields() []DataField
GetData() [][]DataInfo
}
```
### DataTmpl
### DataTmpl `INTERFACE`
数据导出模板
```go
type DataTmpl struct{}
type DataTmpl interface {
Render(data map[any]any) (string, error)
}
```
### Exporter
### Exporter `STRUCT`
导出器
```go
type Exporter struct{}
@ -106,15 +138,19 @@ type Exporter struct{}
#### func (*Exporter) ExportData(tmpl DataTmpl, data map[any]any) []byte, error
> 导出数据
***
### Field
### Field `INTERFACE`
基本字段类型接口
```go
type Field struct{}
type Field interface {
TypeName() string
Zero() any
Parse(value string) any
}
```
### Int
### Int `STRUCT`
```go
type Int struct{}
type Int int
```
#### func (Int) TypeName() string
***
@ -122,10 +158,10 @@ type Int struct{}
***
#### func (Int) Parse(value string) any
***
### Int8
### Int8 `STRUCT`
```go
type Int8 struct{}
type Int8 int8
```
#### func (Int8) TypeName() string
***
@ -133,10 +169,10 @@ type Int8 struct{}
***
#### func (Int8) Parse(value string) any
***
### Int16
### Int16 `STRUCT`
```go
type Int16 struct{}
type Int16 int16
```
#### func (Int16) TypeName() string
***
@ -144,10 +180,10 @@ type Int16 struct{}
***
#### func (Int16) Parse(value string) any
***
### Int32
### Int32 `STRUCT`
```go
type Int32 struct{}
type Int32 int32
```
#### func (Int32) TypeName() string
***
@ -155,10 +191,10 @@ type Int32 struct{}
***
#### func (Int32) Parse(value string) any
***
### Int64
### Int64 `STRUCT`
```go
type Int64 struct{}
type Int64 int64
```
#### func (Int64) TypeName() string
***
@ -166,10 +202,10 @@ type Int64 struct{}
***
#### func (Int64) Parse(value string) any
***
### Uint
### Uint `STRUCT`
```go
type Uint struct{}
type Uint uint
```
#### func (Uint) TypeName() string
***
@ -177,10 +213,10 @@ type Uint struct{}
***
#### func (Uint) Parse(value string) any
***
### Uint8
### Uint8 `STRUCT`
```go
type Uint8 struct{}
type Uint8 uint8
```
#### func (Uint8) TypeName() string
***
@ -188,10 +224,10 @@ type Uint8 struct{}
***
#### func (Uint8) Parse(value string) any
***
### Uint16
### Uint16 `STRUCT`
```go
type Uint16 struct{}
type Uint16 uint16
```
#### func (Uint16) TypeName() string
***
@ -199,10 +235,10 @@ type Uint16 struct{}
***
#### func (Uint16) Parse(value string) any
***
### Uint32
### Uint32 `STRUCT`
```go
type Uint32 struct{}
type Uint32 uint32
```
#### func (Uint32) TypeName() string
***
@ -210,10 +246,10 @@ type Uint32 struct{}
***
#### func (Uint32) Parse(value string) any
***
### Uint64
### Uint64 `STRUCT`
```go
type Uint64 struct{}
type Uint64 uint64
```
#### func (Uint64) TypeName() string
***
@ -221,10 +257,10 @@ type Uint64 struct{}
***
#### func (Uint64) Parse(value string) any
***
### Float32
### Float32 `STRUCT`
```go
type Float32 struct{}
type Float32 float32
```
#### func (Float32) TypeName() string
***
@ -232,10 +268,10 @@ type Float32 struct{}
***
#### func (Float32) Parse(value string) any
***
### Float64
### Float64 `STRUCT`
```go
type Float64 struct{}
type Float64 float64
```
#### func (Float64) TypeName() string
***
@ -243,10 +279,10 @@ type Float64 struct{}
***
#### func (Float64) Parse(value string) any
***
### String
### String `STRUCT`
```go
type String struct{}
type String string
```
#### func (String) TypeName() string
***
@ -254,10 +290,10 @@ type String struct{}
***
#### func (String) Parse(value string) any
***
### Bool
### Bool `STRUCT`
```go
type Bool struct{}
type Bool bool
```
#### func (Bool) TypeName() string
***
@ -265,10 +301,10 @@ type Bool struct{}
***
#### func (Bool) Parse(value string) any
***
### Byte
### Byte `STRUCT`
```go
type Byte struct{}
type Byte byte
```
#### func (Byte) TypeName() string
***
@ -276,10 +312,10 @@ type Byte struct{}
***
#### func (Byte) Parse(value string) any
***
### Rune
### Rune `STRUCT`
```go
type Rune struct{}
type Rune rune
```
#### func (Rune) TypeName() string
***
@ -287,10 +323,10 @@ type Rune struct{}
***
#### func (Rune) Parse(value string) any
***
### Complex64
### Complex64 `STRUCT`
```go
type Complex64 struct{}
type Complex64 complex64
```
#### func (Complex64) TypeName() string
***
@ -298,10 +334,10 @@ type Complex64 struct{}
***
#### func (Complex64) Parse(value string) any
***
### Complex128
### Complex128 `STRUCT`
```go
type Complex128 struct{}
type Complex128 complex128
```
#### func (Complex128) TypeName() string
***
@ -309,10 +345,10 @@ type Complex128 struct{}
***
#### func (Complex128) Parse(value string) any
***
### Uintptr
### Uintptr `STRUCT`
```go
type Uintptr struct{}
type Uintptr uintptr
```
#### func (Uintptr) TypeName() string
***
@ -320,10 +356,10 @@ type Uintptr struct{}
***
#### func (Uintptr) Parse(value string) any
***
### Double
### Double `STRUCT`
```go
type Double struct{}
type Double float64
```
#### func (Double) TypeName() string
***
@ -331,10 +367,10 @@ type Double struct{}
***
#### func (Double) Parse(value string) any
***
### Float
### Float `STRUCT`
```go
type Float struct{}
type Float float32
```
#### func (Float) TypeName() string
***
@ -342,10 +378,10 @@ type Float struct{}
***
#### func (Float) Parse(value string) any
***
### Long
### Long `STRUCT`
```go
type Long struct{}
type Long int64
```
#### func (Long) TypeName() string
***
@ -353,10 +389,10 @@ type Long struct{}
***
#### func (Long) Parse(value string) any
***
### Short
### Short `STRUCT`
```go
type Short struct{}
type Short int16
```
#### func (Short) TypeName() string
***
@ -364,10 +400,10 @@ type Short struct{}
***
#### func (Short) Parse(value string) any
***
### Char
### Char `STRUCT`
```go
type Char struct{}
type Char int8
```
#### func (Char) TypeName() string
***
@ -375,10 +411,10 @@ type Char struct{}
***
#### func (Char) Parse(value string) any
***
### Number
### Number `STRUCT`
```go
type Number struct{}
type Number float64
```
#### func (Number) TypeName() string
***
@ -386,10 +422,10 @@ type Number struct{}
***
#### func (Number) Parse(value string) any
***
### Integer
### Integer `STRUCT`
```go
type Integer struct{}
type Integer int64
```
#### func (Integer) TypeName() string
***
@ -397,10 +433,10 @@ type Integer struct{}
***
#### func (Integer) Parse(value string) any
***
### Boolean
### Boolean `STRUCT`
```go
type Boolean struct{}
type Boolean bool
```
#### func (Boolean) TypeName() string
***
@ -408,7 +444,7 @@ type Boolean struct{}
***
#### func (Boolean) Parse(value string) any
***
### Loader
### Loader `STRUCT`
配置加载器
```go
type Loader struct {
@ -421,7 +457,7 @@ type Loader struct {
#### func (*Loader) LoadData(config Config) map[any]any
> 加载配置并得到配置数据
***
### DataInfo
### DataInfo `STRUCT`
配置数据
```go
type DataInfo struct {
@ -429,7 +465,7 @@ type DataInfo struct {
Value string
}
```
### DataField
### DataField `STRUCT`
配置数据字段
```go
type DataField struct {
@ -440,12 +476,14 @@ type DataField struct {
ExportType string
}
```
### Tmpl
### Tmpl `INTERFACE`
配置结构模板接口
```go
type Tmpl struct{}
type Tmpl interface {
Render(templates ...*TmplStruct) (string, error)
}
```
### TmplField
### TmplField `STRUCT`
模板字段
```go
type TmplField struct {
@ -467,7 +505,7 @@ type TmplField struct {
#### func (*TmplField) IsSlice() bool
> 是否是切片类型
***
### TmplStruct
### TmplStruct `STRUCT`
模板结构
```go
type TmplStruct struct {

View File

@ -1,42 +1,46 @@
# Cs
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/cs)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewXlsx](#NewXlsx)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[XlsxExportType](#xlsxexporttype)|暂无描述...
|[Xlsx](#xlsx)|内置的 Xlsx 配置
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[XlsxExportType](#xlsxexporttype)|暂无描述...
|`STRUCT`|[Xlsx](#xlsx)|内置的 Xlsx 配置
</details>
***
## 详情信息
#### func NewXlsx(sheet *xlsx.Sheet, exportType XlsxExportType) *Xlsx
<span id="NewXlsx"></span>
***
### XlsxExportType
### XlsxExportType `STRUCT`
```go
type XlsxExportType struct{}
type XlsxExportType int
```
### Xlsx
### Xlsx `STRUCT`
内置的 Xlsx 配置
```go
type Xlsx struct {

View File

@ -1,27 +1,22 @@
# Main
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/main)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,32 +1,113 @@
# Cmd
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/cmd)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Execute](#Execute)|将所有子命令添加到根命令并适当设置标志。这是由 main.main() 调用的。 rootCmd 只需要发生一次
> 结构体定义
***
## 详情信息
#### func Execute()
<span id="Execute"></span>
> 将所有子命令添加到根命令并适当设置标志。这是由 main.main() 调用的。 rootCmd 只需要发生一次
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestExecute(t *testing.T) {
var filePath, outPath, exclude, exportType, prefix string
exportType = "s"
filePath = `.\游戏配置.xlsx`
filePath = `../xlsx_template.xlsx`
outPath = `.`
isDir, err := file.IsDir(outPath)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
isDir = filepath.Ext(outPath) == ""
} else {
panic(err)
}
}
if !isDir {
panic(errors.New("output must be a directory path"))
}
_ = os.MkdirAll(outPath, os.ModePerm)
fpd, err := file.IsDir(filePath)
if err != nil {
panic(err)
}
var xlsxFiles []string
if fpd {
files, err := os.ReadDir(filePath)
if err != nil {
panic(err)
}
for _, f := range files {
if f.IsDir() || !strings.HasSuffix(f.Name(), ".xlsx") || strings.HasPrefix(f.Name(), "~") {
continue
}
xlsxFiles = append(xlsxFiles, filepath.Join(filePath, f.Name()))
}
} else {
xlsxFiles = append(xlsxFiles, filePath)
}
var exporter = pce.NewExporter()
loader := pce.NewLoader(pce.GetFields())
excludes := collection.ConvertSliceToBoolMap(str.SplitTrimSpace(exclude, ","))
for _, xlsxFile := range xlsxFiles {
xf, err := xlsx.OpenFile(xlsxFile)
if err != nil {
panic(err)
}
for _, sheet := range xf.Sheets {
var cx *cs.Xlsx
switch strings.TrimSpace(strings.ToLower(exportType)) {
case "c":
cx = cs.NewXlsx(sheet, cs.XlsxExportTypeClient)
case "s":
cx = cs.NewXlsx(sheet, cs.XlsxExportTypeServer)
}
if strings.HasPrefix(cx.GetDisplayName(), "#") || strings.HasPrefix(cx.GetConfigName(), "#") || excludes[cx.GetConfigName()] || excludes[cx.GetDisplayName()] {
continue
}
if raw, err := exporter.ExportData(tmpls.NewJSON(), loader.LoadData(cx)); err != nil {
panic(err)
} else {
var jsonPath string
if len(prefix) == 0 {
jsonPath = filepath.Join(outPath, fmt.Sprintf("%s.json", cx.GetConfigName()))
} else {
jsonPath = filepath.Join(outPath, fmt.Sprintf("%s.%s.json", prefix, cx.GetConfigName()))
}
if err := file.WriterFile(jsonPath, raw); err != nil {
panic(err)
}
}
}
}
}
```
|结构体|描述
|:--|:--
</details>
#### func Execute()
<span id="Execute"></span>
> 将所有子命令添加到根命令并适当设置标志。这是由 main.main() 调用的。 rootCmd 只需要发生一次
***

View File

@ -1,42 +1,47 @@
# Tmpls
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/tmpls)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewGolang](#NewGolang)|创建一个 Golang 配置导出模板
|[NewJSON](#NewJSON)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Golang](#golang)|配置导出模板
|[JSON](#json)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Golang](#golang)|配置导出模板
|`STRUCT`|[JSON](#json)|暂无描述...
</details>
***
## 详情信息
#### func NewGolang(packageName string) *Golang
<span id="NewGolang"></span>
> 创建一个 Golang 配置导出模板
***
#### func NewJSON() *JSON
<span id="NewJSON"></span>
***
### Golang
### Golang `STRUCT`
配置导出模板
```go
type Golang struct {
@ -52,7 +57,7 @@ type Golang struct {
***
#### func (*Golang) HasIndex(config *pce.TmplStruct) bool
***
### JSON
### JSON `STRUCT`
```go
type JSON struct {

View File

@ -1,19 +1,20 @@
# Server
server 提供了包含多种网络类型的服务器实现
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/server)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
server 提供了包含多种网络类型的服务器实现
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewBot](#NewBot)|创建一个机器人,目前仅支持 Socket 服务器
|[WithBotNetworkDelay](#WithBotNetworkDelay)|设置机器人网络延迟及波动范围
@ -49,157 +50,221 @@ server 提供了包含多种网络类型的服务器实现
|[BindService](#BindService)|绑定服务到特定 Server被绑定的服务将会在 Server 初始化时执行 Service.OnInit 方法
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Bot](#bot)|暂无描述...
|[BotOption](#botoption)|暂无描述...
|[Conn](#conn)|服务器连接单次消息的包装
|[ConsoleParams](#consoleparams)|控制台参数
|[MessageReadyEventHandler](#messagereadyeventhandler)|暂无描述...
|[Http](#http)|基于 gin.Engine 包装的 http 服务器
|[HttpContext](#httpcontext)|基于 gin.Context 的 http 请求上下文
|[HandlerFunc](#handlerfunc)|暂无描述...
|[ContextPacker](#contextpacker)|暂无描述...
|[HttpRouter](#httprouter)|暂无描述...
|[HttpWrapperHandleFunc](#httpwrapperhandlefunc)|暂无描述...
|[HttpWrapper](#httpwrapper)|http 包装器
|[HttpWrapperGroup](#httpwrappergroup)|http 包装器
|[MessageType](#messagetype)|暂无描述...
|[Message](#message)|服务器消息
|[MultipleServer](#multipleserver)|暂无描述...
|[Network](#network)|暂无描述...
|[Option](#option)|暂无描述...
|[Server](#server)|网络服务器
|[Service](#service)|兼容传统 service 设计模式的接口
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Bot](#bot)|暂无描述...
|`STRUCT`|[BotOption](#botoption)|暂无描述...
|`STRUCT`|[Conn](#conn)|服务器连接单次消息的包装
|`STRUCT`|[ConsoleParams](#consoleparams)|控制台参数
|`STRUCT`|[MessageReadyEventHandler](#messagereadyeventhandler)|暂无描述...
|`STRUCT`|[Http](#http)|基于 gin.Engine 包装的 http 服务器
|`STRUCT`|[HttpContext](#httpcontext)|基于 gin.Context 的 http 请求上下文
|`STRUCT`|[HandlerFunc](#handlerfunc)|暂无描述...
|`STRUCT`|[ContextPacker](#contextpacker)|暂无描述...
|`STRUCT`|[HttpRouter](#httprouter)|暂无描述...
|`STRUCT`|[HttpWrapperHandleFunc](#httpwrapperhandlefunc)|暂无描述...
|`STRUCT`|[HttpWrapper](#httpwrapper)|http 包装器
|`STRUCT`|[HttpWrapperGroup](#httpwrappergroup)|http 包装器
|`STRUCT`|[MessageType](#messagetype)|暂无描述...
|`STRUCT`|[Message](#message)|服务器消息
|`STRUCT`|[MultipleServer](#multipleserver)|暂无描述...
|`STRUCT`|[Network](#network)|暂无描述...
|`STRUCT`|[Option](#option)|暂无描述...
|`STRUCT`|[Server](#server)|网络服务器
|`INTERFACE`|[Service](#service)|兼容传统 service 设计模式的接口
</details>
***
## 详情信息
#### func NewBot(srv *Server, options ...BotOption) *Bot
<span id="NewBot"></span>
> 创建一个机器人,目前仅支持 Socket 服务器
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewBot(t *testing.T) {
srv := server.New(server.NetworkWebsocket)
srv.RegConnectionOpenedEvent(func(srv *server.Server, conn *server.Conn) {
t.Logf("connection opened: %s", conn.GetID())
conn.Close()
conn.Write([]byte("hello"))
})
srv.RegConnectionClosedEvent(func(srv *server.Server, conn *server.Conn, err any) {
t.Logf("connection closed: %s", conn.GetID())
})
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
t.Logf("connection %s receive packet: %s", conn.GetID(), string(packet))
conn.Write([]byte("world"))
})
srv.RegStartFinishEvent(func(srv *server.Server) {
bot := server.NewBot(srv, server.WithBotNetworkDelay(100, 20), server.WithBotWriter(func(bot *server.Bot) io.Writer {
return &Writer{t: t, bot: bot}
}))
bot.JoinServer()
time.Sleep(time.Second)
bot.SendPacket([]byte("hello"))
})
_ = srv.Run(":9600")
}
```
</details>
***
#### func WithBotNetworkDelay(delay time.Duration, fluctuation time.Duration) BotOption
<span id="WithBotNetworkDelay"></span>
> 设置机器人网络延迟及波动范围
> - delay 延迟
> - fluctuation 波动范围
***
#### func WithBotWriter(construction func (bot *Bot) io.Writer) BotOption
<span id="WithBotWriter"></span>
> 设置机器人写入器,默认为 os.Stdout
***
#### func DefaultWebsocketUpgrader() *websocket.Upgrader
<span id="DefaultWebsocketUpgrader"></span>
***
#### func NewHttpHandleWrapper(srv *Server, packer ContextPacker[Context]) *Http[Context]
<span id="NewHttpHandleWrapper"></span>
> 创建一个新的 http 处理程序包装器
> - 默认使用 server.HttpContext 作为上下文,如果需要依赖其作为新的上下文,可以通过 NewHttpContext 创建
***
#### func NewHttpContext(ctx *gin.Context) *HttpContext
<span id="NewHttpContext"></span>
> 基于 gin.Context 创建一个新的 HttpContext
***
#### func NewGinWrapper(server *gin.Engine, pack func (ctx *gin.Context) CTX) *HttpWrapper[CTX]
<span id="NewGinWrapper"></span>
> 创建 gin 包装器,用于对 NewHttpWrapper 函数的替代
***
#### func HasMessageType(mt MessageType) bool
<span id="HasMessageType"></span>
> 检查是否存在指定的消息类型
***
#### func NewMultipleServer(serverHandle ...func () (addr string, srv *Server)) *MultipleServer
#### func NewMultipleServer(serverHandle ...func () ((addr string, srv *Server))) *MultipleServer
<span id="NewMultipleServer"></span>
***
#### func GetNetworks() []Network
<span id="GetNetworks"></span>
> 获取所有支持的网络模式
***
#### func WithLowMessageDuration(duration time.Duration) Option
<span id="WithLowMessageDuration"></span>
> 通过指定慢消息时长的方式创建服务器,当消息处理时间超过指定时长时,将会输出 WARN 类型的日志
> - 默认值为 DefaultLowMessageDuration
> - 当 duration <= 0 时,表示关闭慢消息检测
***
#### func WithAsyncLowMessageDuration(duration time.Duration) Option
<span id="WithAsyncLowMessageDuration"></span>
> 通过指定异步消息的慢消息时长的方式创建服务器,当消息处理时间超过指定时长时,将会输出 WARN 类型的日志
> - 默认值为 DefaultAsyncLowMessageDuration
> - 当 duration <= 0 时,表示关闭慢消息检测
***
#### func WithWebsocketConnInitializer(initializer func (writer http.ResponseWriter, request *http.Request, conn *websocket.Conn) error) Option
<span id="WithWebsocketConnInitializer"></span>
> 通过 websocket 连接初始化的方式创建服务器,当 initializer 返回错误时,服务器将不会处理该连接的后续逻辑
> - 该选项仅在创建 NetworkWebsocket 服务器时有效
***
#### func WithWebsocketUpgrade(upgrader *websocket.Upgrader) Option
<span id="WithWebsocketUpgrade"></span>
> 通过指定 websocket.Upgrader 的方式创建服务器
> - 默认值为 DefaultWebsocketUpgrader
> - 该选项仅在创建 NetworkWebsocket 服务器时有效
***
#### func WithConnWriteBufferSize(size int) Option
<span id="WithConnWriteBufferSize"></span>
> 通过连接写入缓冲区大小的方式创建服务器
> - 默认值为 DefaultConnWriteBufferSize
> - 设置合适的缓冲区大小可以提高服务器性能,但是会占用更多的内存
***
#### func WithDispatcherBufferSize(size int) Option
<span id="WithDispatcherBufferSize"></span>
> 通过消息分发器缓冲区大小的方式创建服务器
> - 默认值为 DefaultDispatcherBufferSize
> - 设置合适的缓冲区大小可以提高服务器性能,但是会占用更多的内存
***
#### func WithMessageStatistics(duration time.Duration, limit int) Option
<span id="WithMessageStatistics"></span>
> 通过消息统计的方式创建服务器
> - 默认不开启,当 duration 和 limit 均大于 0 的时候,服务器将记录每 duration 期间的消息数量,并保留最多 limit 条
***
#### func WithPacketWarnSize(size int) Option
<span id="WithPacketWarnSize"></span>
> 通过数据包大小警告的方式创建服务器,当数据包大小超过指定大小时,将会输出 WARN 类型的日志
> - 默认值为 DefaultPacketWarnSize
> - 当 size <= 0 时,表示不设置警告
***
#### func WithLimitLife(t time.Duration) Option
<span id="WithLimitLife"></span>
> 通过限制最大生命周期的方式创建服务器
> - 通常用于测试服务器,服务器将在到达最大生命周期时自动关闭
***
#### func WithWebsocketWriteCompression() Option
<span id="WithWebsocketWriteCompression"></span>
> 通过数据写入压缩的方式创建Websocket服务器
> - 默认不开启数据压缩
***
#### func WithWebsocketCompression(level int) Option
<span id="WithWebsocketCompression"></span>
> 通过数据压缩的方式创建Websocket服务器
> - 默认不开启数据压缩
***
#### func WithDeadlockDetect(t time.Duration) Option
<span id="WithDeadlockDetect"></span>
> 通过死锁、死循环、永久阻塞检测的方式创建服务器
> - 当检测到死锁、死循环、永久阻塞时,服务器将会生成 WARN 类型的日志,关键字为 "SuspectedDeadlock"
> - 默认不开启死锁检测
***
#### func WithDisableAsyncMessage() Option
<span id="WithDisableAsyncMessage"></span>
> 通过禁用异步消息的方式创建服务器
***
#### func WithAsyncPoolSize(size int) Option
<span id="WithAsyncPoolSize"></span>
> 通过指定异步消息池大小的方式创建服务器
> - 当通过 WithDisableAsyncMessage 禁用异步消息时,此选项无效
> - 默认值为 DefaultAsyncPoolSize
***
#### func WithWebsocketReadDeadline(t time.Duration) Option
<span id="WithWebsocketReadDeadline"></span>
> 设置 Websocket 读取超时时间
> - 默认: DefaultWebsocketReadDeadline
> - 当 t <= 0 时,表示不设置超时时间
***
#### func WithTicker(poolSize int, size int, connSize int, autonomy bool) Option
<span id="WithTicker"></span>
@ -208,33 +273,119 @@ server 提供了包含多种网络类型的服务器实现
> - size服务器定时器时间轮大小
> - connSize服务器连接定时器时间轮大小当该值小于等于 0 的时候,在新连接建立时将不再为其创建定时器
> - autonomy定时器是否独立运行独立运行的情况下不会作为服务器消息运行会导致并发问题
***
#### func WithTLS(certFile string, keyFile string) Option
<span id="WithTLS"></span>
> 通过安全传输层协议TLS创建服务器
> - 支持Http、Websocket
***
#### func WithGRPCServerOptions(options ...grpc.ServerOption) Option
<span id="WithGRPCServerOptions"></span>
> 通过GRPC的可选项创建GRPC服务器
***
#### func WithWebsocketMessageType(messageTypes ...int) Option
<span id="WithWebsocketMessageType"></span>
> 设置仅支持特定类型的Websocket消息
***
#### func WithPProf(pattern ...string) Option
<span id="WithPProf"></span>
> 通过性能分析工具PProf创建服务器
***
#### func New(network Network, options ...Option) *Server
<span id="New"></span>
> 根据特定网络类型创建一个服务器
示例代码:
```go
func ExampleNew() {
srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond))
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
conn.Write(packet)
})
if err := srv.Run(":9999"); err != nil {
panic(err)
}
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNew(t *testing.T) {
srv := server.New(server.NetworkWebsocket, server.WithPProf())
srv.RegStartBeforeEvent(func(srv *server.Server) {
fmt.Println("启动前")
})
srv.RegStartFinishEvent(func(srv *server.Server) {
fmt.Println("启动完成")
})
srv.RegConnectionClosedEvent(func(srv *server.Server, conn *server.Conn, err any) {
fmt.Println("关闭", conn.GetID(), err, "IncrCount", srv.GetOnlineCount())
})
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
conn.Write(packet)
})
if err := srv.Run(":9999"); err != nil {
panic(err)
}
}
```
</details>
***
#### func BindService(srv *Server, services ...Service)
<span id="BindService"></span>
> 绑定服务到特定 Server被绑定的服务将会在 Server 初始化时执行 Service.OnInit 方法
示例代码:
```go
func ExampleBindService() {
srv := server.New(server.NetworkNone, server.WithLimitLife(time.Second))
server.BindService(srv, new(TestService))
if err := srv.RunNone(); err != nil {
panic(err)
}
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestBindService(t *testing.T) {
srv := server.New(server.NetworkNone, server.WithLimitLife(time.Second))
server.BindService(srv, new(TestService))
if err := srv.RunNone(); err != nil {
t.Fatal(err)
}
}
```
</details>
***
### Bot
### Bot `STRUCT`
```go
type Bot struct {
@ -262,12 +413,12 @@ type Bot struct {
#### func (*Bot) SendWSPacket(wst int, packet []byte)
> 发送 WebSocket 数据包到服务器
***
### BotOption
### BotOption `STRUCT`
```go
type BotOption struct{}
type BotOption func(bot *Bot)
```
### Conn
### Conn `STRUCT`
服务器连接单次消息的包装
```go
type Conn struct {
@ -350,10 +501,10 @@ type Conn struct {
#### func (*Conn) Close(err ...error)
> 关闭连接
***
### ConsoleParams
### ConsoleParams `STRUCT`
控制台参数
```go
type ConsoleParams struct{}
type ConsoleParams map[string][]string
```
#### func (ConsoleParams) Get(key string) string
> 获取参数值
@ -376,12 +527,12 @@ type ConsoleParams struct{}
#### func (ConsoleParams) Clear()
> 清空参数
***
### MessageReadyEventHandler
### MessageReadyEventHandler `STRUCT`
```go
type MessageReadyEventHandler struct{}
type MessageReadyEventHandler func(srv *Server)
```
### Http
### Http `STRUCT`
基于 gin.Engine 包装的 http 服务器
```go
type Http[Context any] struct {
@ -392,7 +543,7 @@ type Http[Context any] struct {
```
#### func (*Http) Gin() *gin.Engine
***
### HttpContext
### HttpContext `STRUCT`
基于 gin.Context 的 http 请求上下文
```go
type HttpContext struct {
@ -405,17 +556,17 @@ type HttpContext struct {
#### func (*HttpContext) ReadTo(dest any) error
> 读取请求数据到指定结构体,如果失败则返回错误
***
### HandlerFunc
### HandlerFunc `STRUCT`
```go
type HandlerFunc[Context any] struct{}
type HandlerFunc[Context any] func(ctx Context)
```
### ContextPacker
### ContextPacker `STRUCT`
```go
type ContextPacker[Context any] struct{}
type ContextPacker[Context any] func(ctx *gin.Context) Context
```
### HttpRouter
### HttpRouter `STRUCT`
```go
type HttpRouter[Context any] struct {
@ -488,12 +639,12 @@ type HttpRouter[Context any] struct {
#### func (*HttpRouter) Use(middleware ...HandlerFunc[Context]) *HttpRouter[Context]
> 将中间件附加到路由组。
***
### HttpWrapperHandleFunc
### HttpWrapperHandleFunc `STRUCT`
```go
type HttpWrapperHandleFunc[CTX any] struct{}
type HttpWrapperHandleFunc[CTX any] func(ctx CTX)
```
### HttpWrapper
### HttpWrapper `STRUCT`
http 包装器
```go
type HttpWrapper[CTX any] struct {
@ -552,7 +703,7 @@ type HttpWrapper[CTX any] struct {
#### func (*HttpWrapper) Group(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
> 创建一个新的路由组。您应该添加所有具有共同中间件的路由。
***
### HttpWrapperGroup
### HttpWrapperGroup `STRUCT`
http 包装器
```go
type HttpWrapperGroup[CTX any] struct {
@ -587,15 +738,15 @@ type HttpWrapperGroup[CTX any] struct {
#### func (*HttpWrapperGroup) Group(relativePath string, handlers ...HttpWrapperHandleFunc[CTX]) *HttpWrapperGroup[CTX]
> 创建分组
***
### MessageType
### MessageType `STRUCT`
```go
type MessageType struct{}
type MessageType byte
```
#### func (MessageType) String() string
> 返回消息类型的字符串表示
***
### Message
### Message `STRUCT`
服务器消息
```go
type Message struct {
@ -620,7 +771,7 @@ type Message struct {
#### func (*Message) String() string
> 返回消息的字符串表示
***
### MultipleServer
### MultipleServer `STRUCT`
```go
type MultipleServer struct {
@ -636,20 +787,20 @@ type MultipleServer struct {
***
#### func (*MultipleServer) OnExitEvent()
***
### Network
### Network `STRUCT`
```go
type Network struct{}
type Network string
```
#### func (Network) IsSocket() bool
> 返回当前服务器的网络模式是否为 Socket 模式
***
### Option
### Option `STRUCT`
```go
type Option struct{}
type Option func(srv *Server)
```
### Server
### Server `STRUCT`
网络服务器
```go
type Server struct {
@ -690,6 +841,21 @@ type Server struct {
> - server.NetworkWebsocket (addr:":8888/ws")
> - server.NetworkKcp (addr:":8888")
> - server.NetworkNone (addr:"")
示例代码:
```go
func ExampleServer_Run() {
srv := server.New(server.NetworkWebsocket, server.WithLimitLife(time.Millisecond))
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
conn.Write(packet)
})
if err := srv.Run(":9999"); err != nil {
panic(err)
}
}
```
***
#### func (*Server) IsSocket() bool
> 是否是 Socket 模式
@ -800,8 +966,10 @@ type Server struct {
#### func (*Server) HasMessageStatistics() bool
> 是否了开启消息统计
***
### Service
### Service `INTERFACE`
兼容传统 service 设计模式的接口
```go
type Service struct{}
type Service interface {
OnInit(srv *Server)
}
```

View File

@ -1,19 +1,20 @@
# Client
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/client)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewClient](#NewClient)|创建客户端
|[CloneClient](#CloneClient)|克隆客户端
@ -22,40 +23,47 @@
|[NewWebsocket](#NewWebsocket)|创建 websocket 客户端
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Client](#client)|客户端
|[Core](#core)|暂无描述...
|[ConnectionClosedEventHandle](#connectionclosedeventhandle)|暂无描述...
|[Packet](#packet)|暂无描述...
|[TCP](#tcp)|暂无描述...
|[UnixDomainSocket](#unixdomainsocket)|暂无描述...
|[Websocket](#websocket)|websocket 客户端
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Client](#client)|客户端
|`INTERFACE`|[Core](#core)|暂无描述...
|`STRUCT`|[ConnectionClosedEventHandle](#connectionclosedeventhandle)|暂无描述...
|`STRUCT`|[Packet](#packet)|暂无描述...
|`STRUCT`|[TCP](#tcp)|暂无描述...
|`STRUCT`|[UnixDomainSocket](#unixdomainsocket)|暂无描述...
|`STRUCT`|[Websocket](#websocket)|websocket 客户端
</details>
***
## 详情信息
#### func NewClient(core Core) *Client
<span id="NewClient"></span>
> 创建客户端
***
#### func CloneClient(client *Client) *Client
<span id="CloneClient"></span>
> 克隆客户端
***
#### func NewTCP(addr string) *Client
<span id="NewTCP"></span>
***
#### func NewUnixDomainSocket(addr string) *Client
<span id="NewUnixDomainSocket"></span>
***
#### func NewWebsocket(addr string) *Client
<span id="NewWebsocket"></span>
> 创建 websocket 客户端
***
### Client
### Client `STRUCT`
客户端
```go
type Client struct {
@ -86,6 +94,43 @@ type Client struct {
#### func (*Client) WriteWS(wst int, packet []byte, callback ...func (err error))
> 向连接中写入指定 websocket 数据类型
> - wst: websocket模式中指定消息类型
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestClient_WriteWS(t *testing.T) {
var wait sync.WaitGroup
wait.Add(1)
srv := server.New(server.NetworkWebsocket)
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
srv.Shutdown()
})
srv.RegStopEvent(func(srv *server.Server) {
wait.Done()
})
srv.RegMessageReadyEvent(func(srv *server.Server) {
cli := client.NewWebsocket("ws://127.0.0.1:9999")
cli.RegConnectionOpenedEvent(func(conn *client.Client) {
conn.WriteWS(2, []byte("Hello"))
})
if err := cli.Run(); err != nil {
panic(err)
}
})
if err := srv.Run(":9999"); err != nil {
panic(err)
}
wait.Wait()
}
```
</details>
***
#### func (*Client) Write(packet []byte, callback ...func (err error))
> 向连接中写入数据
@ -93,17 +138,23 @@ type Client struct {
#### func (*Client) GetServerAddr() string
> 获取服务器地址
***
### Core
### Core `INTERFACE`
```go
type Core struct{}
type Core interface {
Run(runState chan error, receive func(wst int, packet []byte))
Write(packet *Packet) error
Close()
GetServerAddr() string
Clone() Core
}
```
### ConnectionClosedEventHandle
### ConnectionClosedEventHandle `STRUCT`
```go
type ConnectionClosedEventHandle struct{}
type ConnectionClosedEventHandle func(conn *Client, err any)
```
### Packet
### Packet `STRUCT`
```go
type Packet struct {
@ -112,7 +163,7 @@ type Packet struct {
callback func(err error)
}
```
### TCP
### TCP `STRUCT`
```go
type TCP struct {
@ -131,7 +182,7 @@ type TCP struct {
***
#### func (*TCP) Clone() Core
***
### UnixDomainSocket
### UnixDomainSocket `STRUCT`
```go
type UnixDomainSocket struct {
@ -143,6 +194,48 @@ type UnixDomainSocket struct {
#### func (*UnixDomainSocket) Run(runState chan error, receive func (wst int, packet []byte))
***
#### func (*UnixDomainSocket) Write(packet *Packet) error
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestUnixDomainSocket_Write(t *testing.T) {
var closed = make(chan struct{})
srv := server.New(server.NetworkUnix)
srv.RegConnectionReceivePacketEvent(func(srv *server.Server, conn *server.Conn, packet []byte) {
t.Log(string(packet))
conn.Write(packet)
})
srv.RegStartFinishEvent(func(srv *server.Server) {
time.Sleep(time.Second)
cli := client.NewUnixDomainSocket("./test.sock")
cli.RegConnectionOpenedEvent(func(conn *client.Client) {
conn.Write([]byte("Hello~"))
})
cli.RegConnectionReceivePacketEvent(func(conn *client.Client, wst int, packet []byte) {
t.Log(packet)
closed <- struct{}{}
})
if err := cli.Run(); err != nil {
panic(err)
}
})
go func() {
if err := srv.Run("./test.sock"); err != nil {
panic(err)
}
}()
<-closed
srv.Shutdown()
}
```
</details>
***
#### func (*UnixDomainSocket) Close()
***
@ -150,7 +243,7 @@ type UnixDomainSocket struct {
***
#### func (*UnixDomainSocket) Clone() Core
***
### Websocket
### Websocket `STRUCT`
websocket 客户端
```go
type Websocket struct {

View File

@ -1,19 +1,20 @@
# Gateway
gateway 是用于处理服务器消息的网关模块,适用于对客户端消息进行处理、转发的情况。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/gateway)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
gateway 是用于处理服务器消息的网关模块,适用于对客户端消息进行处理、转发的情况。
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewEndpoint](#NewEndpoint)|创建网关端点
|[WithEndpointStateEvaluator](#WithEndpointStateEvaluator)|设置端点健康值评估函数
@ -27,28 +28,32 @@ gateway 是用于处理服务器消息的网关模块,适用于对客户端消
|[UnmarshalGatewayInPacket](#UnmarshalGatewayInPacket)|将网关入网数据包转换为数据包
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Endpoint](#endpoint)|网关端点
|[EndpointOption](#endpointoption)|网关端点选项
|[ConnectionOpenedEventHandle](#connectionopenedeventhandle)|暂无描述...
|[EndpointSelector](#endpointselector)|暂无描述...
|[Gateway](#gateway)|基于 server.Server 实现的网关服务器
|[Option](#option)|网关选项
|[Scanner](#scanner)|端点扫描器
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Endpoint](#endpoint)|网关端点
|`STRUCT`|[EndpointOption](#endpointoption)|网关端点选项
|`STRUCT`|[ConnectionOpenedEventHandle](#connectionopenedeventhandle)|暂无描述...
|`STRUCT`|[EndpointSelector](#endpointselector)|暂无描述...
|`STRUCT`|[Gateway](#gateway)|基于 server.Server 实现的网关服务器
|`STRUCT`|[Option](#option)|网关选项
|`INTERFACE`|[Scanner](#scanner)|端点扫描器
</details>
***
## 详情信息
#### func NewEndpoint(name string, cli *client.Client, options ...EndpointOption) *Endpoint
<span id="NewEndpoint"></span>
> 创建网关端点
***
#### func WithEndpointStateEvaluator(evaluator func (costUnixNano float64) float64) EndpointOption
<span id="WithEndpointStateEvaluator"></span>
> 设置端点健康值评估函数
***
#### func WithEndpointConnectionPoolSize(size int) EndpointOption
<span id="WithEndpointConnectionPoolSize"></span>
@ -56,43 +61,51 @@ gateway 是用于处理服务器消息的网关模块,适用于对客户端消
> - 默认为 DefaultEndpointConnectionPoolSize
> - 端点连接池大小决定了网关服务器与端点服务器建立的连接数,如果 <= 0 则会使用默认值
> - 在网关服务器中,多个客户端在发送消息到端点服务器时,会共用一个连接,适当的增大连接池大小可以提高网关服务器的承载能力
***
#### func WithEndpointReconnectInterval(interval time.Duration) EndpointOption
<span id="WithEndpointReconnectInterval"></span>
> 设置端点重连间隔
> - 默认为 DefaultEndpointReconnectInterval
> - 端点在连接失败后会在该间隔后重连,如果 <= 0 则不会重连
***
#### func NewGateway(srv *server.Server, scanner Scanner, options ...Option) *Gateway
<span id="NewGateway"></span>
> 基于 server.Server 创建 Gateway 网关服务器
***
#### func WithEndpointSelector(selector EndpointSelector) Option
<span id="WithEndpointSelector"></span>
> 设置端点选择器
> - 默认情况下,网关会随机选择一个端点作为目标,如果需要自定义端点选择器,可以通过该选项设置
***
#### func MarshalGatewayOutPacket(addr string, packet []byte) []byte, error
<span id="MarshalGatewayOutPacket"></span>
> 将数据包转换为网关出网数据包
> - | identifier(4) | ipv4(4) | port(2) | packet |
***
#### func UnmarshalGatewayOutPacket(data []byte) (addr string, packet []byte, err error)
<span id="UnmarshalGatewayOutPacket"></span>
> 将网关出网数据包转换为数据包
> - | identifier(4) | ipv4(4) | port(2) | packet |
***
#### func MarshalGatewayInPacket(addr string, currentTime int64, packet []byte) []byte, error
<span id="MarshalGatewayInPacket"></span>
> 将数据包转换为网关入网数据包
> - | ipv4(4) | port(2) | cost(4) | packet |
***
#### func UnmarshalGatewayInPacket(data []byte) (addr string, sendTime int64, packet []byte, err error)
<span id="UnmarshalGatewayInPacket"></span>
> 将网关入网数据包转换为数据包
> - | ipv4(4) | port(2) | cost(4) | packet |
***
### Endpoint
### Endpoint `STRUCT`
网关端点
- 每一个端点均表示了一个目标服务,网关会将数据包转发到该端点,由该端点负责将数据包转发到目标服务。
- 每个端点会建立一个连接池,默认大小为 DefaultEndpointConnectionPoolSize可通过 WithEndpointConnectionPoolSize 进行设置。
@ -128,22 +141,22 @@ type Endpoint struct {
> 转发数据包到该端点
> - 端点在处理数据包时,应区分数据包为普通直连数据包还是网关数据包。可通过 UnmarshalGatewayOutPacket 进行数据包解析,当解析失败且无其他数据包协议时,可认为该数据包为普通直连数据包。
***
### EndpointOption
### EndpointOption `STRUCT`
网关端点选项
```go
type EndpointOption struct{}
type EndpointOption func(endpoint *Endpoint)
```
### ConnectionOpenedEventHandle
### ConnectionOpenedEventHandle `STRUCT`
```go
type ConnectionOpenedEventHandle struct{}
type ConnectionOpenedEventHandle func(gateway *Gateway, conn *server.Conn)
```
### EndpointSelector
### EndpointSelector `STRUCT`
```go
type EndpointSelector struct{}
type EndpointSelector func(endpoints []*Endpoint) *Endpoint
```
### Gateway
### Gateway `STRUCT`
基于 server.Server 实现的网关服务器
- 网关服务器是一个特殊的服务器,它会通过扫描器扫描端点列表,然后连接到端点列表中的所有端点,当端点连接成功后,网关服务器会将客户端的连接数据转发到端点服务器
- 由于该网关为多个客户端共享一个端点的连接,所以不会受限于单机 65535 个端口的限制
@ -170,6 +183,34 @@ type Gateway struct {
```
#### func (*Gateway) Run(addr string) error
> 运行网关
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestGateway_Run(t *testing.T) {
gw := gateway.NewGateway(server.New(server.NetworkWebsocket, server.WithDeadlockDetect(time.Second*3)), new(Scanner))
gw.RegConnectionReceivePacketEventHandle(func(gateway *gateway.Gateway, conn *server.Conn, packet []byte) {
endpoint, err := gateway.GetConnEndpoint("test", conn)
if err == nil {
endpoint.Forward(conn, packet)
}
})
gw.RegEndpointConnectReceivePacketEventHandle(func(gateway *gateway.Gateway, endpoint *gateway.Endpoint, conn *server.Conn, packet []byte) {
conn.Write(packet)
})
if err := gw.Run(":8888"); err != nil {
panic(err)
}
}
```
</details>
***
#### func (*Gateway) Shutdown()
> 关闭网关
@ -189,15 +230,18 @@ type Gateway struct {
#### func (*Gateway) SwitchEndpoint(source *Endpoint, dest *Endpoint)
> 将端点端点的所有连接切换到另一个端点
***
### Option
### Option `STRUCT`
网关选项
```go
type Option struct{}
type Option func(gateway *Gateway)
```
### Scanner
### Scanner `INTERFACE`
端点扫描器
```go
type Scanner struct{}
type Scanner interface {
GetEndpoints() ([]*Endpoint, error)
GetInterval() time.Duration
}
```
#### func (*Scanner) GetEndpoints() []*gateway.Endpoint, error
***

View File

@ -1,47 +1,171 @@
# Dispatcher
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/dispatcher)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewDispatcher](#NewDispatcher)|创建一个新的消息分发器 Dispatcher 实例
|[NewManager](#NewManager)|生成消息分发器管理器
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Action](#action)|消息分发器操作器,用于暴露外部可操作的消息分发器函数
|[Handler](#handler)|消息处理器
|[Dispatcher](#dispatcher)|用于服务器消息处理的消息分发器
|[Manager](#manager)|消息分发器管理器
|[Message](#message)|暂无描述...
|[Producer](#producer)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Action](#action)|消息分发器操作器,用于暴露外部可操作的消息分发器函数
|`STRUCT`|[Handler](#handler)|消息处理器
|`STRUCT`|[Dispatcher](#dispatcher)|用于服务器消息处理的消息分发器
|`STRUCT`|[Manager](#manager)|消息分发器管理器
|`INTERFACE`|[Message](#message)|暂无描述...
|`INTERFACE`|[Producer](#producer)|暂无描述...
</details>
***
## 详情信息
#### func NewDispatcher(bufferSize int, name string, handler Handler[P, M]) *Dispatcher[P, M]
<span id="NewDispatcher"></span>
> 创建一个新的消息分发器 Dispatcher 实例
示例代码:
```go
func ExampleNewDispatcher() {
m := new(atomic.Int64)
fm := new(atomic.Int64)
w := new(sync.WaitGroup)
w.Add(1)
d := dispatcher.NewDispatcher(1024, "example-dispatcher", func(dispatcher *dispatcher.Dispatcher[string, *TestMessage], message *TestMessage) {
m.Add(1)
})
d.SetClosedHandler(func(dispatcher *dispatcher.Action[string, *TestMessage]) {
w.Done()
})
var producers = []string{"producer1", "producer2", "producer3"}
for i := 0; i < len(producers); i++ {
p := producers[i]
for i := 0; i < 10; i++ {
d.Put(&TestMessage{producer: p})
}
d.SetProducerDoneHandler(p, func(p string, dispatcher *dispatcher.Action[string, *TestMessage]) {
fm.Add(1)
})
}
d.Start()
d.Expel()
w.Wait()
fmt.Println(fmt.Sprintf("producer num: %d, producer done: %d, finished: %d", len(producers), fm.Load(), m.Load()))
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewDispatcher(t *testing.T) {
var cases = []struct {
name string
bufferSize int
handler dispatcher.Handler[string, *TestMessage]
shouldPanic bool
}{{name: "TestNewDispatcher_BufferSize0AndHandlerNil", bufferSize: 0, handler: nil, shouldPanic: true}, {name: "TestNewDispatcher_BufferSize0AndHandlerNotNil", bufferSize: 0, handler: func(dispatcher *dispatcher.Dispatcher[string, *TestMessage], message *TestMessage) {
}, shouldPanic: true}, {name: "TestNewDispatcher_BufferSize1AndHandlerNil", bufferSize: 1, handler: nil, shouldPanic: true}, {name: "TestNewDispatcher_BufferSize1AndHandlerNotNil", bufferSize: 1, handler: func(dispatcher *dispatcher.Dispatcher[string, *TestMessage], message *TestMessage) {
}, shouldPanic: false}}
for _, c := range cases {
c := c
t.Run(c.name, func(t *testing.T) {
defer func() {
if r := recover(); r != nil && !c.shouldPanic {
t.Errorf("NewDispatcher() should not panic, but panic: %v", r)
}
}()
dispatcher.NewDispatcher(c.bufferSize, c.name, c.handler)
})
}
}
```
</details>
***
#### func NewManager(bufferSize int, handler Handler[P, M]) *Manager[P, M]
<span id="NewManager"></span>
> 生成消息分发器管理器
示例代码:
```go
func ExampleNewManager() {
mgr := dispatcher.NewManager[string, *TestMessage](10124*16, func(dispatcher *dispatcher.Dispatcher[string, *TestMessage], message *TestMessage) {
})
mgr.BindProducer("player_001", "shunt-001")
mgr.BindProducer("player_002", "shunt-002")
mgr.BindProducer("player_003", "shunt-sys")
mgr.BindProducer("player_004", "shunt-sys")
mgr.UnBindProducer("player_001")
mgr.UnBindProducer("player_002")
mgr.UnBindProducer("player_003")
mgr.UnBindProducer("player_004")
mgr.Wait()
fmt.Println("done")
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewManager(t *testing.T) {
var cases = []struct {
name string
bufferSize int
handler dispatcher.Handler[string, *TestMessage]
shouldPanic bool
}{{name: "TestNewManager_BufferSize0AndHandlerNil", bufferSize: 0, handler: nil, shouldPanic: true}, {name: "TestNewManager_BufferSize0AndHandlerNotNil", bufferSize: 0, handler: func(dispatcher *dispatcher.Dispatcher[string, *TestMessage], message *TestMessage) {
}, shouldPanic: true}, {name: "TestNewManager_BufferSize1AndHandlerNil", bufferSize: 1, handler: nil, shouldPanic: true}, {name: "TestNewManager_BufferSize1AndHandlerNotNil", bufferSize: 1, handler: func(dispatcher *dispatcher.Dispatcher[string, *TestMessage], message *TestMessage) {
}, shouldPanic: false}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
defer func() {
if r := recover(); r != nil && !c.shouldPanic {
t.Errorf("NewManager() should not panic, but panic: %v", r)
}
}()
dispatcher.NewManager[string, *TestMessage](c.bufferSize, c.handler)
})
}
}
```
</details>
***
### Action
### Action `STRUCT`
消息分发器操作器,用于暴露外部可操作的消息分发器函数
```go
type Action[P Producer, M Message[P]] struct {
@ -49,12 +173,12 @@ type Action[P Producer, M Message[P]] struct {
d *Dispatcher[P, M]
}
```
### Handler
### Handler `STRUCT`
消息处理器
```go
type Handler[P Producer, M Message[P]] struct{}
type Handler[P Producer, M Message[P]] func(dispatcher *Dispatcher[P, M], message M)
```
### Dispatcher
### Dispatcher `STRUCT`
用于服务器消息处理的消息分发器
这个消息分发器为并发安全的生产者和消费者模型,生产者可以是任意类型,消费者必须是 Message 接口的实现。
@ -83,7 +207,7 @@ type Dispatcher[P Producer, M Message[P]] struct {
abort chan struct{}
}
```
### Manager
### Manager `STRUCT`
消息分发器管理器
```go
type Manager[P Producer, M Message[P]] struct {
@ -99,13 +223,17 @@ type Manager[P Producer, M Message[P]] struct {
createdHandler func(name string)
}
```
### Message
### Message `INTERFACE`
```go
type Message[P comparable] struct{}
type Message[P comparable] interface {
GetProducer() P
}
```
### Producer
### Producer `INTERFACE`
```go
type Producer struct{}
type Producer interface {
comparable
}
```

View File

@ -1,40 +1,37 @@
# Logger
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/logger)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
> 类型定义
|函数|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
|[Ants](#ants)|暂无描述...
|[GNet](#gnet)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Ants](#ants)|暂无描述...
|`STRUCT`|[GNet](#gnet)|暂无描述...
</details>
### Ants
***
## 详情信息
### Ants `STRUCT`
```go
type Ants struct{}
```
#### func (*Ants) Printf(format string, args ...interface {})
***
### GNet
### GNet `STRUCT`
```go
type GNet struct{}

View File

@ -1,19 +1,20 @@
# Lockstep
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/lockstep)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewLockstep](#NewLockstep)|创建一个锁步(帧)同步默认实现的组件(Lockstep)进行返回
|[WithFrameLimit](#WithFrameLimit)|通过特定逻辑帧上限创建锁步(帧)同步组件
@ -22,31 +23,72 @@
|[WithInitFrame](#WithInitFrame)|通过特定的初始帧创建锁步(帧)同步组件
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Client](#client)|帧同步客户端接口定义
|[StoppedEventHandle](#stoppedeventhandle)|暂无描述...
|[Lockstep](#lockstep)|锁步(帧)同步默认实现
|[Option](#option)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`INTERFACE`|[Client](#client)|帧同步客户端接口定义
|`STRUCT`|[StoppedEventHandle](#stoppedeventhandle)|暂无描述...
|`STRUCT`|[Lockstep](#lockstep)|锁步(帧)同步默认实现
|`STRUCT`|[Option](#option)|暂无描述...
</details>
***
## 详情信息
#### func NewLockstep(options ...Option[ClientID, Command]) *Lockstep[ClientID, Command]
<span id="NewLockstep"></span>
> 创建一个锁步(帧)同步默认实现的组件(Lockstep)进行返回
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewLockstep(t *testing.T) {
ls := lockstep.NewLockstep[string, int](lockstep.WithInitFrame[string, int](1))
ls.JoinClient(&Cli{id: "player_1"})
ls.JoinClient(&Cli{id: "player_2"})
count := 0
ls.StartBroadcast()
endChan := make(chan bool)
go func() {
for {
ls.AddCommand(random.Int(1, 9999))
count++
if count >= 10 {
break
}
time.Sleep(time.Millisecond * time.Duration(random.Int(10, 200)))
}
ls.StopBroadcast()
endChan <- true
}()
<-endChan
time.Sleep(time.Second)
fmt.Println("end")
}
```
</details>
***
#### func WithFrameLimit(frameLimit int64) Option[ClientID, Command]
<span id="WithFrameLimit"></span>
> 通过特定逻辑帧上限创建锁步(帧)同步组件
> - 当达到上限时将停止广播
***
#### func WithFrameRate(frameRate int64) Option[ClientID, Command]
<span id="WithFrameRate"></span>
> 通过特定逻辑帧率创建锁步(帧)同步组件
> - 默认情况下为 15/s
***
#### func WithSerialization(handle func (frame int64, commands []Command) []byte) Option[ClientID, Command]
<span id="WithSerialization"></span>
@ -58,24 +100,29 @@
> Frame int `json:"frame"`
> Commands []Command `json:"commands"`
> }
***
#### func WithInitFrame(initFrame int64) Option[ClientID, Command]
<span id="WithInitFrame"></span>
> 通过特定的初始帧创建锁步(帧)同步组件
> - 默认情况下为 0即第一帧索引为 0
***
### Client
### Client `INTERFACE`
帧同步客户端接口定义
- 客户端应该具备ID及写入数据包的实现
```go
type Client[ID comparable] struct{}
type Client[ID comparable] interface {
GetID() ID
Write(packet []byte, callback ...func(err error))
}
```
### StoppedEventHandle
### StoppedEventHandle `STRUCT`
```go
type StoppedEventHandle[ClientID comparable, Command any] struct{}
type StoppedEventHandle[ClientID comparable, Command any] func(lockstep *Lockstep[ClientID, Command])
```
### Lockstep
### Lockstep `STRUCT`
锁步(帧)同步默认实现
- 支持最大帧上限 WithFrameLimit
- 自定逻辑帧频率默认为每秒15帧(帧/66ms) WithFrameRate
@ -102,8 +149,8 @@ type Lockstep[ClientID comparable, Command any] struct {
lockstepStoppedEventHandles []StoppedEventHandle[ClientID, Command]
}
```
### Option
### Option `STRUCT`
```go
type Option[ClientID comparable, Command any] struct{}
type Option[ClientID comparable, Command any] func(lockstep *Lockstep[ClientID, Command])
```

View File

@ -1,53 +1,67 @@
# Router
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/router)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewMultistage](#NewMultistage)|创建一个支持多级分类的路由器
|[WithRouteTrim](#WithRouteTrim)|路由修剪选项
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[MultistageBind](#multistagebind)|多级分类路由绑定函数
|[Multistage](#multistage)|支持多级分类的路由器
|[MultistageOption](#multistageoption)|路由器选项
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[MultistageBind](#multistagebind)|多级分类路由绑定函数
|`STRUCT`|[Multistage](#multistage)|支持多级分类的路由器
|`STRUCT`|[MultistageOption](#multistageoption)|路由器选项
</details>
***
## 详情信息
#### func NewMultistage(options ...MultistageOption[HandleFunc]) *Multistage[HandleFunc]
<span id="NewMultistage"></span>
> 创建一个支持多级分类的路由器
示例代码:
```go
func ExampleNewMultistage() {
router.NewMultistage[func()]()
}
```
***
#### func WithRouteTrim(handle func (route any) any) MultistageOption[HandleFunc]
<span id="WithRouteTrim"></span>
> 路由修剪选项
> - 将在路由注册前对路由进行对应处理
***
### MultistageBind
### MultistageBind `STRUCT`
多级分类路由绑定函数
```go
type MultistageBind[HandleFunc any] struct{}
type MultistageBind[HandleFunc any] func(HandleFunc)
```
#### func (MultistageBind) Bind(handleFunc HandleFunc)
> 将处理函数绑定到预设的路由中
***
### Multistage
### Multistage `STRUCT`
支持多级分类的路由器
```go
type Multistage[HandleFunc any] struct {
@ -60,19 +74,98 @@ type Multistage[HandleFunc any] struct {
#### func (*Multistage) Register(routes ...any) MultistageBind[HandleFunc]
> 注册路由是结合 Sub 和 Route 的快捷方式,用于一次性注册多级路由
> - 该函数将返回一个注册函数可通过调用其将路由绑定到特定处理函数例如router.Register("a", "b").Bind(onExec())
示例代码:
```go
func ExampleMultistage_Register() {
r := router.NewMultistage[func()]()
r.Register("System", "Network", "Ping")(func() {
})
}
```
***
#### func (*Multistage) Route(route any, handleFunc HandleFunc)
> 为特定路由绑定处理函数,被绑定的处理函数将可以通过 Match 函数进行匹配
示例代码:
```go
func ExampleMultistage_Route() {
r := router.NewMultistage[func()]()
r.Route("ServerTime", func() {
})
}
```
***
#### func (*Multistage) Match(routes ...any) HandleFunc
> 匹配已绑定处理函数的路由,返回处理函数
> - 如果未找到将会返回空指针
示例代码:
```go
func ExampleMultistage_Match() {
r := router.NewMultistage[func()]()
r.Route("ServerTime", func() {
})
r.Register("System", "Network", "Ping").Bind(func() {
})
r.Match("ServerTime")()
r.Match("System", "Network", "Ping")()
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestMultistage_Match(t *testing.T) {
r := router.NewMultistage[func()]()
r.Sub("System").Route("Heartbeat", func() {
fmt.Println("Heartbeat")
})
r.Route("ServerTime", func() {
fmt.Println("ServerTime")
})
r.Register("System", "Network", "Ping")(func() {
fmt.Println("Ping")
})
r.Register("System", "Network", "Echo").Bind(onEcho)
r.Match("System", "Heartbeat")()
r.Match("ServerTime")()
r.Match("System", "Network", "Ping")()
r.Match("System", "Network", "Echo")()
fmt.Println(r.Match("None") == nil)
}
```
</details>
***
#### func (*Multistage) Sub(route any) *Multistage[HandleFunc]
> 获取子路由器
示例代码:
```go
func ExampleMultistage_Sub() {
r := router.NewMultistage[func()]()
r.Sub("System").Route("Heartbeat", func() {
})
}
```
***
### MultistageOption
### MultistageOption `STRUCT`
路由器选项
```go
type MultistageOption[HandleFunc any] struct{}
type MultistageOption[HandleFunc any] func(multistage *Multistage[HandleFunc])
```

View File

@ -1,35 +1,38 @@
# Writeloop
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/writeloop)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewChannel](#NewChannel)|创建基于 Channel 的写循环
|[NewUnbounded](#NewUnbounded)|创建写循环
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Channel](#channel)|基于 chan 的写循环,与 Unbounded 相同,但是使用 Channel 实现
|[Unbounded](#unbounded)|写循环
|[WriteLoop](#writeloop)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Channel](#channel)|基于 chan 的写循环,与 Unbounded 相同,但是使用 Channel 实现
|`STRUCT`|[Unbounded](#unbounded)|写循环
|`INTERFACE`|[WriteLoop](#writeloop)|暂无描述...
</details>
***
## 详情信息
#### func NewChannel(pool *hub.ObjectPool[Message], channelSize int, writeHandler func (message Message) error, errorHandler func (err any)) *Channel[Message]
<span id="NewChannel"></span>
> 创建基于 Channel 的写循环
@ -39,6 +42,7 @@
> - errorHandler 错误处理函数
>
> 传入 writeHandler 的消息对象是从 Channel 中获取的,因此 writeHandler 不应该持有消息对象的引用,同时也不应该主动释放消息对象
***
#### func NewUnbounded(pool *hub.ObjectPool[Message], writeHandler func (message Message) error, errorHandler func (err any)) *Unbounded[Message]
<span id="NewUnbounded"></span>
@ -48,8 +52,61 @@
> - errorHandler 错误处理函数
>
> 传入 writeHandler 的消息对象是从 pool 中获取的,并且在 writeHandler 执行完成后会被放回 pool 中,因此 writeHandler 不应该持有消息对象的引用,同时也不应该主动释放消息对象
示例代码:
```go
func ExampleNewUnbounded() {
pool := hub.NewObjectPool[Message](func() *Message {
return &Message{}
}, func(data *Message) {
data.ID = 0
})
var wait sync.WaitGroup
wait.Add(10)
wl := writeloop.NewUnbounded(pool, func(message *Message) error {
fmt.Println(message.ID)
wait.Done()
return nil
}, func(err any) {
fmt.Println(err)
})
for i := 0; i < 10; i++ {
m := pool.Get()
m.ID = i
wl.Put(m)
}
wait.Wait()
wl.Close()
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewUnbounded(t *testing.T) {
wl := writeloop.NewUnbounded(wp, func(message *Message) error {
t.Log(message.ID)
return nil
}, func(err any) {
t.Log(err)
})
assert.NotNil(t, wl)
wl.Close()
}
```
</details>
***
### Channel
### Channel `STRUCT`
基于 chan 的写循环,与 Unbounded 相同,但是使用 Channel 实现
```go
type Channel[T any] struct {
@ -62,7 +119,7 @@ type Channel[T any] struct {
#### func (*Channel) Close()
> 关闭写循环
***
### Unbounded
### Unbounded `STRUCT`
写循环
- 用于将数据并发安全的写入到底层连接
```go
@ -72,12 +129,99 @@ type Unbounded[Message any] struct {
```
#### func (*Unbounded) Put(message Message)
> 将数据放入写循环message 应该来源于 hub.ObjectPool
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestUnbounded_Put(t *testing.T) {
wl := writeloop.NewUnbounded(wp, func(message *Message) error {
t.Log(message.ID)
return nil
}, func(err any) {
t.Log(err)
})
assert.NotNil(t, wl)
for i := 0; i < 100; i++ {
m := wp.Get()
m.ID = i
wl.Put(m)
}
wl.Close()
}
```
</details>
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkUnbounded_Put(b *testing.B) {
wl := writeloop.NewUnbounded(wp, func(message *Message) error {
return nil
}, nil)
defer func() {
wl.Close()
}()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
wl.Put(wp.Get())
}
})
b.StopTimer()
}
```
</details>
***
#### func (*Unbounded) Close()
> 关闭写循环
***
### WriteLoop
<details>
<summary>查看 / 收起单元测试</summary>
```go
type WriteLoop[Message any] struct{}
func TestUnbounded_Close(t *testing.T) {
wl := writeloop.NewUnbounded(wp, func(message *Message) error {
t.Log(message.ID)
return nil
}, func(err any) {
t.Log(err)
})
assert.NotNil(t, wl)
for i := 0; i < 100; i++ {
m := wp.Get()
m.ID = i
wl.Put(m)
}
wl.Close()
}
```
</details>
***
### WriteLoop `INTERFACE`
```go
type WriteLoop[Message any] interface {
Put(message Message)
Close()
}
```

View File

@ -1,5 +1,8 @@
# Utils
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/utils)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
utils 旨在提供一组用于处理通用功能的函数和数据结构。该包旨在简化通用功能的实现,并提供一致的接口和易于使用的功能。
主要特性:
- 通用功能utils 包支持处理各种通用功能,如字符串处理、日期时间操作和文件操作等。您可以使用这些功能来解决各种通用问题,并提高代码的复用性和可维护性。
@ -7,26 +10,6 @@ utils 旨在提供一组用于处理通用功能的函数和数据结构。该
- 算法实现utils 包还提供了一些常用的算法实现,如排序算法、搜索算法和图算法等。这些算法可以用于解决各种问题,并提供高效的计算和处理能力。
- 工具函数:该包还提供了一些通用的工具函数,如字符串处理、日期时间操作和文件操作等。这些工具函数可以帮助您简化代码编写,处理文本数据,操作日期时间,读写文件等。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/utils)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
> 包级函数定义
|函数|描述
|:--|:--
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息

View File

@ -1,5 +1,8 @@
# Aoi
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/aoi)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
aoi 提供了一种有效的方法来处理 AOIArea of Interest问题。
AOI 问题是在大规模多人在线游戏中常见的问题,它涉及到确定哪些对象对玩家来说是“感兴趣的”,
@ -7,37 +10,62 @@ AOI 问题是在大规模多人在线游戏中常见的问题,它涉及到确
这个包提供了一种数据结构和一些方法来有效地解决这个问题。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/aoi)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewTwoDimensional](#NewTwoDimensional)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[TwoDimensional](#twodimensional)|暂无描述...
|[TwoDimensionalEntity](#twodimensionalentity)|基于2D定义的AOI对象功能接口
|[EntityJoinVisionEventHandle](#entityjoinvisioneventhandle)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[TwoDimensional](#twodimensional)|暂无描述...
|`INTERFACE`|[TwoDimensionalEntity](#twodimensionalentity)|基于2D定义的AOI对象功能接口
|`STRUCT`|[EntityJoinVisionEventHandle](#entityjoinvisioneventhandle)|暂无描述...
</details>
***
## 详情信息
#### func NewTwoDimensional(width int, height int, areaWidth int, areaHeight int) *TwoDimensional[EID, PosType, E]
<span id="NewTwoDimensional"></span>
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewTwoDimensional(t *testing.T) {
aoiTW := aoi.NewTwoDimensional[int64, float64, *Ent](10000, 10000, 100, 100)
start := time.Now()
for i := 0; i < 50000; i++ {
aoiTW.AddEntity(&Ent{guid: int64(i), pos: geometry.NewPoint[float64](float64(random.Int64(0, 10000)), float64(random.Int64(0, 10000))), vision: 200})
}
fmt.Println("添加耗时:", time.Since(start))
start = time.Now()
aoiTW.SetSize(10100, 10100)
fmt.Println("重设大小耗时:", time.Since(start))
}
```
</details>
***
### TwoDimensional
### TwoDimensional `STRUCT`
```go
type TwoDimensional[EID generic.Basic, PosType generic.SignedNumber, E TwoDimensionalEntity[EID, PosType]] struct {
@ -54,14 +82,18 @@ type TwoDimensional[EID generic.Basic, PosType generic.SignedNumber, E TwoDimens
repartitionQueue []func()
}
```
### TwoDimensionalEntity
### TwoDimensionalEntity `INTERFACE`
基于2D定义的AOI对象功能接口
- AOI 对象提供了 AOI 系统中常用的属性,诸如位置坐标和视野范围等
```go
type TwoDimensionalEntity[EID generic.Basic, PosType generic.SignedNumber] struct{}
type TwoDimensionalEntity[EID generic.Basic, PosType generic.SignedNumber] interface {
GetTwoDimensionalEntityID() EID
GetVision() float64
GetPosition() geometry.Point[PosType]
}
```
### EntityJoinVisionEventHandle
### EntityJoinVisionEventHandle `STRUCT`
```go
type EntityJoinVisionEventHandle[EID generic.Basic, PosType generic.SignedNumber, E TwoDimensionalEntity[EID, PosType]] struct{}
type EntityJoinVisionEventHandle[EID generic.Basic, PosType generic.SignedNumber, E TwoDimensionalEntity[EID, PosType]] func(entity E)
```

View File

@ -1,21 +1,22 @@
# Arrangement
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/arrangement)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
arrangement 包提供了一些有用的函数来处理数组的排列。
更多的详细信息和使用示例,可以参考每个函数的文档。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/arrangement)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[WithAreaConstraint](#WithAreaConstraint)|设置编排区域的约束条件
|[WithAreaConflict](#WithAreaConflict)|设置编排区域的冲突条件,冲突处理函数需要返回造成冲突的成员列表
@ -29,62 +30,72 @@ arrangement 包提供了一些有用的函数来处理数组的排列。
|[WithConflictHandle](#WithConflictHandle)|设置编排时触发冲突时的处理函数
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Area](#area)|编排区域
|[AreaOption](#areaoption)|编排区域选项
|[AreaConstraintHandle](#areaconstrainthandle)|暂无描述...
|[Arrangement](#arrangement)|用于针对多条数据进行合理编排的数据结构
|[Editor](#editor)|提供了大量辅助函数的编辑器
|[Item](#item)|编排成员
|[ItemOption](#itemoption)|编排成员选项
|[ItemFixedAreaHandle](#itemfixedareahandle)|暂无描述...
|[Option](#option)|编排选项
|[ConstraintHandle](#constrainthandle)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Area](#area)|编排区域
|`STRUCT`|[AreaOption](#areaoption)|编排区域选项
|`STRUCT`|[AreaConstraintHandle](#areaconstrainthandle)|暂无描述...
|`STRUCT`|[Arrangement](#arrangement)|用于针对多条数据进行合理编排的数据结构
|`STRUCT`|[Editor](#editor)|提供了大量辅助函数的编辑器
|`INTERFACE`|[Item](#item)|编排成员
|`STRUCT`|[ItemOption](#itemoption)|编排成员选项
|`STRUCT`|[ItemFixedAreaHandle](#itemfixedareahandle)|暂无描述...
|`STRUCT`|[Option](#option)|编排选项
|`STRUCT`|[ConstraintHandle](#constrainthandle)|暂无描述...
</details>
***
## 详情信息
#### func WithAreaConstraint(constraint AreaConstraintHandle[ID, AreaInfo]) AreaOption[ID, AreaInfo]
<span id="WithAreaConstraint"></span>
> 设置编排区域的约束条件
> - 该约束用于判断一个成员是否可以被添加到该编排区域中
> - 与 WithAreaConflict 不同的是,约束通常用于非成员关系导致的硬性约束,例如:成员的等级过滤、成员的性别等
***
#### func WithAreaConflict(conflict AreaConflictHandle[ID, AreaInfo]) AreaOption[ID, AreaInfo]
<span id="WithAreaConflict"></span>
> 设置编排区域的冲突条件,冲突处理函数需要返回造成冲突的成员列表
> - 该冲突用于判断一个成员是否可以被添加到该编排区域中
> - 与 WithAreaConstraint 不同的是,冲突通常用于成员关系导致的软性约束,例如:成员的职业唯一性、成员的种族唯一性等
***
#### func WithAreaEvaluate(evaluate AreaEvaluateHandle[ID, AreaInfo]) AreaOption[ID, AreaInfo]
<span id="WithAreaEvaluate"></span>
> 设置编排区域的评估函数
> - 该评估函数将影响成员被编入区域的优先级
***
#### func NewArrangement(options ...Option[ID, AreaInfo]) *Arrangement[ID, AreaInfo]
<span id="NewArrangement"></span>
> 创建一个新的编排
***
#### func WithItemFixed(matcher ItemFixedAreaHandle[AreaInfo]) ItemOption[ID, AreaInfo]
<span id="WithItemFixed"></span>
> 设置成员的固定编排区域
***
#### func WithItemPriority(priority ItemPriorityHandle[ID, AreaInfo]) ItemOption[ID, AreaInfo]
<span id="WithItemPriority"></span>
> 设置成员的优先级
***
#### func WithItemNotAllow(verify ItemNotAllowVerifyHandle[ID, AreaInfo]) ItemOption[ID, AreaInfo]
<span id="WithItemNotAllow"></span>
> 设置成员不允许的编排区域
***
#### func WithRetryThreshold(threshold int) Option[ID, AreaInfo]
<span id="WithRetryThreshold"></span>
> 设置编排时的重试阈值
> - 当每一轮编排结束任有成员未被编排时,将会进行下一轮编排,直到编排次数达到该阈值
> - 默认的阈值为 10 次
***
#### func WithConstraintHandle(handle ConstraintHandle[ID, AreaInfo]) Option[ID, AreaInfo]
<span id="WithConstraintHandle"></span>
@ -94,6 +105,7 @@ arrangement 包提供了一些有用的函数来处理数组的排列。
> - 当所有的约束处理函数都无法处理约束时,将会进入下一个编排区域的尝试,如果均无法完成,将会将该成员加入到编排队列的末端,等待下一次编排
>
> 有意思的是,硬性约束应该永远是无解的,而当需要进行一些打破规则的操作时,则可以透过该函数传入的 editor 进行操作
***
#### func WithConflictHandle(handle ConflictHandle[ID, AreaInfo]) Option[ID, AreaInfo]
<span id="WithConflictHandle"></span>
@ -101,8 +113,9 @@ arrangement 包提供了一些有用的函数来处理数组的排列。
> - 当冲突条件触发时,将会调用该函数。如果无法在该函数中处理冲突,应该继续返回这一批成员,尝试进行下一层的冲突处理
> - 当该函数的返回值长度为 0 时,表示冲突已经被处理,将会命中当前的编排区域
> - 当所有的冲突处理函数都无法处理冲突时,将会进入下一个编排区域的尝试,如果均无法完成,将会将该成员加入到编排队列的末端,等待下一次编排
***
### Area
### Area `STRUCT`
编排区域
```go
type Area[ID comparable, AreaInfo any] struct {
@ -113,17 +126,17 @@ type Area[ID comparable, AreaInfo any] struct {
evaluate AreaEvaluateHandle[ID, AreaInfo]
}
```
### AreaOption
### AreaOption `STRUCT`
编排区域选项
```go
type AreaOption[ID comparable, AreaInfo any] struct{}
type AreaOption[ID comparable, AreaInfo any] func(area *Area[ID, AreaInfo])
```
### AreaConstraintHandle
### AreaConstraintHandle `STRUCT`
```go
type AreaConstraintHandle[ID comparable, AreaInfo any] struct{}
type AreaConstraintHandle[ID comparable, AreaInfo any] func(area *Area[ID, AreaInfo], item Item[ID]) error
```
### Arrangement
### Arrangement `STRUCT`
用于针对多条数据进行合理编排的数据结构
- 我不知道这个数据结构的具体用途,但是我觉得这个数据结构应该是有用的
- 目前我能想到的用途只有我的过往经历:排课
@ -140,7 +153,7 @@ type Arrangement[ID comparable, AreaInfo any] struct {
conflictHandles []ConflictHandle[ID, AreaInfo]
}
```
### Editor
### Editor `STRUCT`
提供了大量辅助函数的编辑器
```go
type Editor[ID comparable, AreaInfo any] struct {
@ -151,28 +164,31 @@ type Editor[ID comparable, AreaInfo any] struct {
retryCount int
}
```
### Item
### Item `INTERFACE`
编排成员
```go
type Item[ID comparable] struct{}
type Item[ID comparable] interface {
GetID() ID
Equal(item Item[ID]) bool
}
```
### ItemOption
### ItemOption `STRUCT`
编排成员选项
```go
type ItemOption[ID comparable, AreaInfo any] struct{}
type ItemOption[ID comparable, AreaInfo any] func(arrangement *Arrangement[ID, AreaInfo], item Item[ID])
```
### ItemFixedAreaHandle
### ItemFixedAreaHandle `STRUCT`
```go
type ItemFixedAreaHandle[AreaInfo any] struct{}
type ItemFixedAreaHandle[AreaInfo any] func(areaInfo AreaInfo) bool
```
### Option
### Option `STRUCT`
编排选项
```go
type Option[ID comparable, AreaInfo any] struct{}
type Option[ID comparable, AreaInfo any] func(arrangement *Arrangement[ID, AreaInfo])
```
### ConstraintHandle
### ConstraintHandle `STRUCT`
```go
type ConstraintHandle[ID comparable, AreaInfo any] struct{}
type ConstraintHandle[ID comparable, AreaInfo any] func(editor *Editor[ID, AreaInfo], area *Area[ID, AreaInfo], item Item[ID], err error) error
```

View File

@ -1,5 +1,8 @@
# Buffer
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/buffer)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
buffer 提供了缓冲区相关的实用程序。
包括创建、读取和写入缓冲区的函数。
@ -8,45 +11,67 @@ buffer 提供了缓冲区相关的实用程序。
无界缓冲区的所有方法都是线程安全的,除了用于同步的互斥锁外,不会阻塞任何东西。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/buffer)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewRing](#NewRing)|创建一个并发不安全的环形缓冲区
|[NewRingUnbounded](#NewRingUnbounded)|创建一个并发安全的基于环形缓冲区实现的无界缓冲区
|[NewUnbounded](#NewUnbounded)|创建一个无界缓冲区
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Ring](#ring)|环形缓冲区
|[RingUnbounded](#ringunbounded)|基于环形缓冲区实现的无界缓冲区
|[Unbounded](#unbounded)|是无界缓冲区的实现
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Ring](#ring)|环形缓冲区
|`STRUCT`|[RingUnbounded](#ringunbounded)|基于环形缓冲区实现的无界缓冲区
|`STRUCT`|[Unbounded](#unbounded)|是无界缓冲区的实现
</details>
***
## 详情信息
#### func NewRing(initSize ...int) *Ring[T]
<span id="NewRing"></span>
> 创建一个并发不安全的环形缓冲区
> - initSize: 初始容量
>
> 当初始容量小于 2 或未设置时,将会使用默认容量 2
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewRing(t *testing.T) {
ring := buffer.NewRing[int]()
for i := 0; i < 100; i++ {
ring.Write(i)
t.Log(ring.Read())
}
}
```
</details>
***
#### func NewRingUnbounded(bufferSize int) *RingUnbounded[T]
<span id="NewRingUnbounded"></span>
> 创建一个并发安全的基于环形缓冲区实现的无界缓冲区
***
#### func NewUnbounded() *Unbounded[V]
<span id="NewUnbounded"></span>
@ -55,8 +80,9 @@ buffer 提供了缓冲区相关的实用程序。
>
> 该缓冲区来源于 gRPC 的实现,用于在不使用额外 goroutine 的情况下实现无界缓冲区
> - 该缓冲区的所有方法都是线程安全的,除了用于同步的互斥锁外,不会阻塞任何东西
***
### Ring
### Ring `STRUCT`
环形缓冲区
```go
type Ring[T any] struct {
@ -69,6 +95,29 @@ type Ring[T any] struct {
```
#### func (*Ring) Read() T, error
> 读取数据
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkRing_Read(b *testing.B) {
ring := buffer.NewRing[int](1024)
for i := 0; i < b.N; i++ {
ring.Write(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = ring.Read()
}
}
```
</details>
***
#### func (*Ring) ReadAll() []T
> 读取所有数据
@ -78,6 +127,26 @@ type Ring[T any] struct {
***
#### func (*Ring) Write(v T)
> 写入数据
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkRing_Write(b *testing.B) {
ring := buffer.NewRing[int](1024)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ring.Write(i)
}
}
```
</details>
***
#### func (*Ring) IsEmpty() bool
> 是否为空
@ -91,7 +160,7 @@ type Ring[T any] struct {
#### func (*Ring) Reset()
> 重置缓冲区
***
### RingUnbounded
### RingUnbounded `STRUCT`
基于环形缓冲区实现的无界缓冲区
```go
type RingUnbounded[T any] struct {
@ -106,17 +175,87 @@ type RingUnbounded[T any] struct {
```
#### func (*RingUnbounded) Write(v T)
> 写入数据
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkRingUnbounded_Write(b *testing.B) {
ring := buffer.NewRingUnbounded[int](1024 * 16)
b.ResetTimer()
for i := 0; i < b.N; i++ {
ring.Write(i)
}
}
```
</details>
***
#### func (*RingUnbounded) Read() chan T
> 读取数据
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkRingUnbounded_Read(b *testing.B) {
ring := buffer.NewRingUnbounded[int](1024 * 16)
for i := 0; i < b.N; i++ {
ring.Write(i)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
<-ring.Read()
}
}
```
</details>
***
#### func (*RingUnbounded) Closed() bool
> 判断缓冲区是否已关闭
***
#### func (*RingUnbounded) Close() chan struct {}
> 关闭缓冲区,关闭后将不再接收新数据,但是已有数据仍然可以读取
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestRingUnbounded_Close(t *testing.T) {
ring := buffer.NewRingUnbounded[int](1024 * 16)
for i := 0; i < 100; i++ {
ring.Write(i)
}
t.Log("write done")
ring.Close()
t.Log("close done")
for v := range ring.Read() {
ring.Write(v)
t.Log(v)
}
t.Log("read done")
}
```
</details>
***
### Unbounded
### Unbounded `STRUCT`
是无界缓冲区的实现
```go
type Unbounded[V any] struct {
@ -135,6 +274,27 @@ type Unbounded[V any] struct {
***
#### func (*Unbounded) Get() chan V
> 获取读取通道
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestUnbounded_Get(t *testing.T) {
ub := buffer.NewUnbounded[int]()
for i := 0; i < 100; i++ {
ub.Put(i + 1)
fmt.Println(<-ub.Get())
ub.Load()
}
}
```
</details>
***
#### func (*Unbounded) Close()
> 关闭

View File

@ -5,7 +5,7 @@ import (
"testing"
)
func BenchmarkRingWrite(b *testing.B) {
func BenchmarkRing_Write(b *testing.B) {
ring := buffer.NewRing[int](1024)
b.ResetTimer()
for i := 0; i < b.N; i++ {
@ -13,7 +13,7 @@ func BenchmarkRingWrite(b *testing.B) {
}
}
func BenchmarkRingRead(b *testing.B) {
func BenchmarkRing_Read(b *testing.B) {
ring := buffer.NewRing[int](1024)
for i := 0; i < b.N; i++ {
ring.Write(i)

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,20 @@
# Listings
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/listings)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewMatrix](#NewMatrix)|创建一个新的 Matrix 实例。
|[NewPagedSlice](#NewPagedSlice)|创建一个新的 PagedSlice 实例。
@ -21,35 +22,41 @@
|[NewSyncSlice](#NewSyncSlice)|创建一个 SyncSlice
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Matrix](#matrix)|暂无描述...
|[PagedSlice](#pagedslice)|是一个高效的动态数组,它通过分页管理内存并减少频繁的内存分配来提高性能。
|[PrioritySlice](#priorityslice)|是一个优先级切片
|[SyncSlice](#syncslice)|是基于 sync.RWMutex 实现的线程安全的 slice
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Matrix](#matrix)|暂无描述...
|`STRUCT`|[PagedSlice](#pagedslice)|是一个高效的动态数组,它通过分页管理内存并减少频繁的内存分配来提高性能。
|`STRUCT`|[PrioritySlice](#priorityslice)|是一个优先级切片
|`STRUCT`|[SyncSlice](#syncslice)|是基于 sync.RWMutex 实现的线程安全的 slice
</details>
***
## 详情信息
#### func NewMatrix(dimensions ...int) *Matrix[V]
<span id="NewMatrix"></span>
> 创建一个新的 Matrix 实例。
***
#### func NewPagedSlice(pageSize int) *PagedSlice[T]
<span id="NewPagedSlice"></span>
> 创建一个新的 PagedSlice 实例。
***
#### func NewPrioritySlice(lengthAndCap ...int) *PrioritySlice[V]
<span id="NewPrioritySlice"></span>
> 创建一个优先级切片
***
#### func NewSyncSlice(length int, cap int) *SyncSlice[V]
<span id="NewSyncSlice"></span>
> 创建一个 SyncSlice
***
### Matrix
### Matrix `STRUCT`
```go
type Matrix[V any] struct {
@ -69,7 +76,7 @@ type Matrix[V any] struct {
#### func (*Matrix) Clear()
> 清空矩阵。
***
### PagedSlice
### PagedSlice `STRUCT`
是一个高效的动态数组,它通过分页管理内存并减少频繁的内存分配来提高性能。
```go
type PagedSlice[T any] struct {
@ -97,7 +104,7 @@ type PagedSlice[T any] struct {
#### func (*PagedSlice) Range(f func (index int, value T) bool)
> 迭代 PagedSlice 中的所有元素。
***
### PrioritySlice
### PrioritySlice `STRUCT`
是一个优先级切片
```go
type PrioritySlice[V any] struct {
@ -115,6 +122,25 @@ type PrioritySlice[V any] struct {
***
#### func (*PrioritySlice) Append(v V, p int)
> 添加元素
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestPrioritySlice_Append(t *testing.T) {
var s = listings.NewPrioritySlice[string]()
s.Append("name_1", 2)
s.Append("name_2", 1)
fmt.Println(s)
}
```
</details>
***
#### func (*PrioritySlice) Appends(priority int, vs ...V)
> 添加元素
@ -155,7 +181,7 @@ type PrioritySlice[V any] struct {
#### func (*PrioritySlice) String() string
> 返回切片字符串
***
### SyncSlice
### SyncSlice `STRUCT`
是基于 sync.RWMutex 实现的线程安全的 slice
```go
type SyncSlice[V any] struct {

View File

@ -1,37 +1,41 @@
# Mappings
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/mappings)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewSyncMap](#NewSyncMap)|创建一个 SyncMap
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[SyncMap](#syncmap)|是基于 sync.RWMutex 实现的线程安全的 map
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[SyncMap](#syncmap)|是基于 sync.RWMutex 实现的线程安全的 map
</details>
***
## 详情信息
#### func NewSyncMap(source ...map[K]V) *SyncMap[K, V]
<span id="NewSyncMap"></span>
> 创建一个 SyncMap
***
### SyncMap
### SyncMap `STRUCT`
是基于 sync.RWMutex 实现的线程安全的 map
- 适用于要考虑并发读写但是并发读写的频率不高的情况
```go

View File

@ -1,19 +1,20 @@
# Combination
combination 包提供了一些实用的组合函数。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/combination)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
combination 包提供了一些实用的组合函数。
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewCombination](#NewCombination)|创建一个新的组合器
|[WithEvaluation](#WithEvaluation)|设置组合评估函数
@ -47,24 +48,27 @@ combination 包提供了一些实用的组合函数。
|[WithValidatorHandleNCarryIndependentM](#WithValidatorHandleNCarryIndependentM)|校验组合成员是否匹配 N 携带独立的 M 的组合
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Combination](#combination)|用于从多个匹配器内提取组合的数据结构
|[Option](#option)|组合器选项
|[Item](#item)|暂无描述...
|[Matcher](#matcher)|用于从一组数据内提取组合的数据结构
|[MatcherOption](#matcheroption)|匹配器选项
|[Validator](#validator)|用于对组合进行验证的校验器
|[ValidatorOption](#validatoroption)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Combination](#combination)|用于从多个匹配器内提取组合的数据结构
|`STRUCT`|[Option](#option)|组合器选项
|`INTERFACE`|[Item](#item)|暂无描述...
|`STRUCT`|[Matcher](#matcher)|用于从一组数据内提取组合的数据结构
|`STRUCT`|[MatcherOption](#matcheroption)|匹配器选项
|`STRUCT`|[Validator](#validator)|用于对组合进行验证的校验器
|`STRUCT`|[ValidatorOption](#validatoroption)|暂无描述...
</details>
***
## 详情信息
#### func NewCombination(options ...Option[T]) *Combination[T]
<span id="NewCombination"></span>
> 创建一个新的组合器
***
#### func WithEvaluation(evaluate func (items []T) float64) Option[T]
<span id="WithEvaluation"></span>
@ -73,48 +77,57 @@ combination 包提供了一些实用的组合函数。
> - 通过该选项将设置所有匹配器的默认评估函数为该函数
> - 通过匹配器选项 WithMatcherEvaluation 可以覆盖该默认评估函数
> - 默认的评估函数将返回一个随机数
***
#### func NewMatcher(options ...MatcherOption[T]) *Matcher[T]
<span id="NewMatcher"></span>
> 创建一个新的匹配器
***
#### func WithMatcherEvaluation(evaluate func (items []T) float64) MatcherOption[T]
<span id="WithMatcherEvaluation"></span>
> 设置匹配器评估函数
> - 用于对组合进行评估,返回一个分值的评价函数
> - 通过该选项将覆盖匹配器的默认(WithEvaluation)评估函数
***
#### func WithMatcherLeastLength(length int) MatcherOption[T]
<span id="WithMatcherLeastLength"></span>
> 通过匹配最小长度的组合创建匹配器
> - length: 组合的长度,表示需要匹配的组合最小数量
***
#### func WithMatcherLength(length int) MatcherOption[T]
<span id="WithMatcherLength"></span>
> 通过匹配长度的组合创建匹配器
> - length: 组合的长度,表示需要匹配的组合数量
***
#### func WithMatcherMostLength(length int) MatcherOption[T]
<span id="WithMatcherMostLength"></span>
> 通过匹配最大长度的组合创建匹配器
> - length: 组合的长度,表示需要匹配的组合最大数量
***
#### func WithMatcherIntervalLength(min int, max int) MatcherOption[T]
<span id="WithMatcherIntervalLength"></span>
> 通过匹配长度区间的组合创建匹配器
> - min: 组合的最小长度,表示需要匹配的组合最小数量
> - max: 组合的最大长度,表示需要匹配的组合最大数量
***
#### func WithMatcherContinuity(getIndex func (item T) Index) MatcherOption[T]
<span id="WithMatcherContinuity"></span>
> 通过匹配连续的组合创建匹配器
> - index: 用于获取组合中元素的索引值,用于判断是否连续
***
#### func WithMatcherSame(count int, getType func (item T) E) MatcherOption[T]
<span id="WithMatcherSame"></span>
> 通过匹配相同的组合创建匹配器
> - count: 组合中相同元素的数量,当 count <= 0 时,表示相同元素的数量不限
> - getType: 用于获取组合中元素的类型,用于判断是否相同
***
#### func WithMatcherNCarryM(n int, m int, getType func (item T) E) MatcherOption[T]
<span id="WithMatcherNCarryM"></span>
@ -122,6 +135,7 @@ combination 包提供了一些实用的组合函数。
> - n: 组合中元素的数量表示需要匹配的组合数量n 的类型需要全部相同
> - m: 组合中元素的数量表示需要匹配的组合数量m 的类型需要全部相同
> - getType: 用于获取组合中元素的类型,用于判断是否相同
***
#### func WithMatcherNCarryIndependentM(n int, m int, getType func (item T) E) MatcherOption[T]
<span id="WithMatcherNCarryIndependentM"></span>
@ -129,70 +143,87 @@ combination 包提供了一些实用的组合函数。
> - n: 组合中元素的数量表示需要匹配的组合数量n 的类型需要全部相同
> - m: 组合中元素的数量表示需要匹配的组合数量m 的类型无需全部相同
> - getType: 用于获取组合中元素的类型,用于判断是否相同
***
#### func NewValidator(options ...ValidatorOption[T]) *Validator[T]
<span id="NewValidator"></span>
> 创建一个新的校验器
***
#### func WithValidatorHandle(handle func (items []T) bool) ValidatorOption[T]
<span id="WithValidatorHandle"></span>
> 通过特定的验证函数对组合进行验证
***
#### func WithValidatorHandleLength(length int) ValidatorOption[T]
<span id="WithValidatorHandleLength"></span>
> 校验组合的长度是否符合要求
***
#### func WithValidatorHandleLengthRange(min int, max int) ValidatorOption[T]
<span id="WithValidatorHandleLengthRange"></span>
> 校验组合的长度是否在指定的范围内
***
#### func WithValidatorHandleLengthMin(min int) ValidatorOption[T]
<span id="WithValidatorHandleLengthMin"></span>
> 校验组合的长度是否大于等于指定的最小值
***
#### func WithValidatorHandleLengthMax(max int) ValidatorOption[T]
<span id="WithValidatorHandleLengthMax"></span>
> 校验组合的长度是否小于等于指定的最大值
***
#### func WithValidatorHandleLengthNot(length int) ValidatorOption[T]
<span id="WithValidatorHandleLengthNot"></span>
> 校验组合的长度是否不等于指定的值
***
#### func WithValidatorHandleTypeLength(length int, getType func (item T) E) ValidatorOption[T]
<span id="WithValidatorHandleTypeLength"></span>
> 校验组合成员类型数量是否为指定的值
***
#### func WithValidatorHandleTypeLengthRange(min int, max int, getType func (item T) E) ValidatorOption[T]
<span id="WithValidatorHandleTypeLengthRange"></span>
> 校验组合成员类型数量是否在指定的范围内
***
#### func WithValidatorHandleTypeLengthMin(min int, getType func (item T) E) ValidatorOption[T]
<span id="WithValidatorHandleTypeLengthMin"></span>
> 校验组合成员类型数量是否大于等于指定的最小值
***
#### func WithValidatorHandleTypeLengthMax(max int, getType func (item T) E) ValidatorOption[T]
<span id="WithValidatorHandleTypeLengthMax"></span>
> 校验组合成员类型数量是否小于等于指定的最大值
***
#### func WithValidatorHandleTypeLengthNot(length int, getType func (item T) E) ValidatorOption[T]
<span id="WithValidatorHandleTypeLengthNot"></span>
> 校验组合成员类型数量是否不等于指定的值
***
#### func WithValidatorHandleContinuous(getIndex func (item T) Index) ValidatorOption[T]
<span id="WithValidatorHandleContinuous"></span>
> 校验组合成员是否连续
***
#### func WithValidatorHandleContinuousNot(getIndex func (item T) Index) ValidatorOption[T]
<span id="WithValidatorHandleContinuousNot"></span>
> 校验组合成员是否不连续
***
#### func WithValidatorHandleGroupContinuous(getType func (item T) E, getIndex func (item T) Index) ValidatorOption[T]
<span id="WithValidatorHandleGroupContinuous"></span>
> 校验组合成员是否能够按类型分组并且连续
***
#### func WithValidatorHandleGroupContinuousN(n int, getType func (item T) E, getIndex func (item T) Index) ValidatorOption[T]
<span id="WithValidatorHandleGroupContinuousN"></span>
> 校验组合成员是否能够按分组为 n 组类型并且连续
***
#### func WithValidatorHandleNCarryM(n int, m int, getType func (item T) E) ValidatorOption[T]
<span id="WithValidatorHandleNCarryM"></span>
@ -200,6 +231,7 @@ combination 包提供了一些实用的组合函数。
> - n: 组合中元素的数量表示需要匹配的组合数量n 的类型需要全部相同
> - m: 组合中元素的数量表示需要匹配的组合数量m 的类型需要全部相同
> - getType: 用于获取组合中元素的类型,用于判断是否相同
***
#### func WithValidatorHandleNCarryIndependentM(n int, m int, getType func (item T) E) ValidatorOption[T]
<span id="WithValidatorHandleNCarryIndependentM"></span>
@ -207,8 +239,9 @@ combination 包提供了一些实用的组合函数。
> - n: 组合中元素的数量表示需要匹配的组合数量n 的类型需要全部相同
> - m: 组合中元素的数量表示需要匹配的组合数量m 的类型无需全部相同
> - getType: 用于获取组合中元素的类型,用于判断是否相同
***
### Combination
### Combination `STRUCT`
用于从多个匹配器内提取组合的数据结构
```go
type Combination[T Item] struct {
@ -234,21 +267,54 @@ type Combination[T Item] struct {
***
#### func (*Combination) Best(items []T) (name string, result []T)
> 从一组数据中提取符合匹配器规则的最佳组合
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestCombination_Best(t *testing.T) {
combine := combination.NewCombination(combination.WithEvaluation(func(items []*Poker) float64 {
var total float64
for _, item := range items {
total += float64(item.Point)
}
return total
}))
combine.NewMatcher("炸弹", combination.WithMatcherSame[*Poker, int](4, func(item *Poker) int {
return item.Point
})).NewMatcher("三带一", combination.WithMatcherNCarryM[*Poker, int](3, 1, func(item *Poker) int {
return item.Point
}))
var cards = []*Poker{{Point: 2, Color: 1}, {Point: 2, Color: 2}, {Point: 2, Color: 3}, {Point: 3, Color: 4}, {Point: 4, Color: 1}, {Point: 4, Color: 2}, {Point: 5, Color: 3}, {Point: 6, Color: 4}, {Point: 7, Color: 1}, {Point: 8, Color: 2}, {Point: 9, Color: 3}, {Point: 10, Color: 4}, {Point: 11, Color: 1}, {Point: 12, Color: 2}, {Point: 13, Color: 3}, {Point: 10, Color: 3}, {Point: 11, Color: 2}, {Point: 12, Color: 1}, {Point: 13, Color: 4}, {Point: 10, Color: 2}}
name, result := combine.Worst(cards)
fmt.Println("best:", name)
for _, item := range result {
fmt.Println(item)
}
}
```
</details>
***
#### func (*Combination) Worst(items []T) (name string, result []T)
> 从一组数据中提取符合匹配器规则的最差组合
***
### Option
### Option `STRUCT`
组合器选项
```go
type Option[T Item] struct{}
type Option[T Item] func(*Combination[T])
```
### Item
### Item `INTERFACE`
```go
type Item struct{}
type Item interface{}
```
### Matcher
### Matcher `STRUCT`
用于从一组数据内提取组合的数据结构
```go
type Matcher[T Item] struct {
@ -269,12 +335,12 @@ type Matcher[T Item] struct {
#### func (*Matcher) Worst(items []T) []T
> 从一组数据中提取符筛选器规则的最差组合
***
### MatcherOption
### MatcherOption `STRUCT`
匹配器选项
```go
type MatcherOption[T Item] struct{}
type MatcherOption[T Item] func(matcher *Matcher[T])
```
### Validator
### Validator `STRUCT`
用于对组合进行验证的校验器
```go
type Validator[T Item] struct {
@ -283,9 +349,41 @@ type Validator[T Item] struct {
```
#### func (*Validator) Validate(items []T) bool
> 校验组合是否符合要求
***
### ValidatorOption
<details>
<summary>查看 / 收起单元测试</summary>
```go
type ValidatorOption[T Item] struct{}
func TestValidator_Validate(t *testing.T) {
v := combination.NewValidator[*Card](combination.WithValidatorHandleContinuous[*Card, int](func(item *Card) int {
switch item.Point {
case "A":
return 1
case "2", "3", "4", "5", "6", "7", "8", "9", "10":
return super.StringToInt(item.Point)
case "J":
return 11
case "Q":
return 12
case "K":
return 13
}
return -1
}), combination.WithValidatorHandleLength[*Card](3))
cards := []*Card{{Point: "2", Color: "Spade"}, {Point: "4", Color: "Heart"}, {Point: "3", Color: "Diamond"}}
fmt.Println(v.Validate(cards))
}
```
</details>
***
### ValidatorOption `STRUCT`
```go
type ValidatorOption[T Item] func(validator *Validator[T])
```

View File

@ -1,19 +1,20 @@
# Compress
compress 提供了一些用于压缩和解压缩数据的函数。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/compress)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
compress 提供了一些用于压缩和解压缩数据的函数。
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[GZipCompress](#GZipCompress)|对数据进行GZip压缩返回bytes.Buffer和错误信息
|[GZipUnCompress](#GZipUnCompress)|对已进行GZip压缩的数据进行解压缩返回字节数组及错误信息
@ -23,35 +24,35 @@ compress 提供了一些用于压缩和解压缩数据的函数。
|[ZIPUnCompress](#ZIPUnCompress)|对已进行ZIP压缩的数据进行解压缩返回字节数组及错误信息
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func GZipCompress(data []byte) bytes.Buffer, error
<span id="GZipCompress"></span>
> 对数据进行GZip压缩返回bytes.Buffer和错误信息
***
#### func GZipUnCompress(dataByte []byte) []byte, error
<span id="GZipUnCompress"></span>
> 对已进行GZip压缩的数据进行解压缩返回字节数组及错误信息
***
#### func TARCompress(data []byte) bytes.Buffer, error
<span id="TARCompress"></span>
> 对数据进行TAR压缩返回bytes.Buffer和错误信息
***
#### func TARUnCompress(dataByte []byte) []byte, error
<span id="TARUnCompress"></span>
> 对已进行TAR压缩的数据进行解压缩返回字节数组及错误信息
***
#### func ZIPCompress(data []byte) bytes.Buffer, error
<span id="ZIPCompress"></span>
> 对数据进行ZIP压缩返回bytes.Buffer和错误信息
***
#### func ZIPUnCompress(dataByte []byte) []byte, error
<span id="ZIPUnCompress"></span>
> 对已进行ZIP压缩的数据进行解压缩返回字节数组及错误信息
***

View File

@ -1,19 +1,20 @@
# Crypto
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/crypto)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[EncryptBase64](#EncryptBase64)|对数据进行Base64编码
|[DecodedBase64](#DecodedBase64)|对数据进行Base64解码
@ -27,51 +28,55 @@
|[DecodedSHA256](#DecodedSHA256)|对字节数组进行SHA256加密并返回其结果。
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func EncryptBase64(data []byte) string
<span id="EncryptBase64"></span>
> 对数据进行Base64编码
***
#### func DecodedBase64(data string) []byte, error
<span id="DecodedBase64"></span>
> 对数据进行Base64解码
***
#### func EncryptCRC32(str string) uint32
<span id="EncryptCRC32"></span>
> 对字符串进行CRC加密并返回其结果。
***
#### func DecodedCRC32(data []byte) uint32
<span id="DecodedCRC32"></span>
> 对字节数组进行CRC加密并返回其结果。
***
#### func EncryptMD5(str string) string
<span id="EncryptMD5"></span>
> 对字符串进行MD5加密并返回其结果。
***
#### func DecodedMD5(data []byte) string
<span id="DecodedMD5"></span>
> 对字节数组进行MD5加密并返回其结果。
***
#### func EncryptSHA1(str string) string
<span id="EncryptSHA1"></span>
> 对字符串进行SHA1加密并返回其结果。
***
#### func DecodedSHA1(data []byte) string
<span id="DecodedSHA1"></span>
> 对字节数组进行SHA1加密并返回其结果。
***
#### func EncryptSHA256(str string) string
<span id="EncryptSHA256"></span>
> 对字符串进行SHA256加密并返回其结果。
***
#### func DecodedSHA256(data []byte) string
<span id="DecodedSHA256"></span>
> 对字节数组进行SHA256加密并返回其结果。
***

View File

@ -1,44 +1,49 @@
# Deck
deck 包中的内容用于针对一堆内容的管理,适用但不限于牌堆、麻将牌堆等情况。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/deck)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
deck 包中的内容用于针对一堆内容的管理,适用但不限于牌堆、麻将牌堆等情况。
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewDeck](#NewDeck)|创建一个新的甲板
|[NewGroup](#NewGroup)|创建一个新的组
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Deck](#deck)|甲板,用于针对一堆 Group 进行管理的数据结构
|[Group](#group)|甲板中的组,用于针对一堆内容进行管理的数据结构
|[Item](#item)|甲板成员
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Deck](#deck)|甲板,用于针对一堆 Group 进行管理的数据结构
|`STRUCT`|[Group](#group)|甲板中的组,用于针对一堆内容进行管理的数据结构
|`INTERFACE`|[Item](#item)|甲板成员
</details>
***
## 详情信息
#### func NewDeck() *Deck[I]
<span id="NewDeck"></span>
> 创建一个新的甲板
***
#### func NewGroup(guid int64, fillHandle func (guid int64) []I) *Group[I]
<span id="NewGroup"></span>
> 创建一个新的组
***
### Deck
### Deck `STRUCT`
甲板,用于针对一堆 Group 进行管理的数据结构
```go
type Deck[I Item] struct {
@ -67,7 +72,7 @@ type Deck[I Item] struct {
#### func (*Deck) GetPrev(guid int64) *Group[I]
> 获取特定组的上一个组
***
### Group
### Group `STRUCT`
甲板中的组,用于针对一堆内容进行管理的数据结构
```go
type Group[I Item] struct {
@ -121,8 +126,8 @@ type Group[I Item] struct {
#### func (*Group) GetItem(index int) I
> 获取组中的指定内容
***
### Item
### Item `INTERFACE`
甲板成员
```go
type Item struct{}
type Item interface{}
```

View File

@ -1,19 +1,20 @@
# File
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/file)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[PathExist](#PathExist)|路径是否存在
|[IsDir](#IsDir)|路径是否是文件夹
@ -28,57 +29,60 @@
|[FindLineChunksByOffset](#FindLineChunksByOffset)|该函数与 FindLineChunks 类似,不同的是该函数可以指定 offset 从指定位置开始读取文件
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func PathExist(path string) bool, error
<span id="PathExist"></span>
> 路径是否存在
***
#### func IsDir(path string) bool, error
<span id="IsDir"></span>
> 路径是否是文件夹
***
#### func WriterFile(filePath string, content []byte) error
<span id="WriterFile"></span>
> 向特定文件写入内容
***
#### func ReadOnce(filePath string) []byte, error
<span id="ReadOnce"></span>
> 单次读取文件
> - 一次性对整个文件进行读取,小文件读取可以很方便的一次性将文件内容读取出来,而大文件读取会造成性能影响。
***
#### func ReadBlockHook(filePath string, bufferSize int, hook func (data []byte)) error
<span id="ReadBlockHook"></span>
> 分块读取文件
> - 将filePath路径对应的文件数据并将读到的每一部分传入hook函数中当过程中如果产生错误则会返回error。
> - 分块读取可以在读取速度和内存消耗之间有一个很好的平衡。
***
#### func ReadLine(filePath string, hook func (line string)) error
<span id="ReadLine"></span>
> 分行读取文件
> - 将filePath路径对应的文件数据并将读到的每一行传入hook函数中当过程中如果产生错误则会返回error。
***
#### func LineCount(filePath string) int
<span id="LineCount"></span>
> 统计文件行数
***
#### func Paths(dir string) []string
<span id="Paths"></span>
> 获取指定目录下的所有文件路径
> - 包括了子目录下的文件
> - 不包含目录
***
#### func ReadLineWithParallel(filename string, chunkSize int64, handlerFunc func ( string), start ...int64) (n int64, err error)
<span id="ReadLineWithParallel"></span>
> 并行的分行读取文件并行处理,处理过程中会将每一行的内容传入 handlerFunc 中进行处理
> - 由于是并行处理,所以处理过程中的顺序是不确定的。
> - 可通过 start 参数指定开始读取的位置,如果不指定则从文件开头开始读取。
***
#### func FindLineChunks(file *os.File, chunkSize int64) [][2]int64
<span id="FindLineChunks"></span>
@ -86,8 +90,10 @@
> - 使用该函数得到的分块是完整的行,不会出现行被分割的情况
> - 当过程中发生错误将会发生 panic
> - 返回值的成员是一个长度为 2 的数组,第一个元素是分块的起始位置,第二个元素是分块的结束位置
***
#### func FindLineChunksByOffset(file *os.File, offset int64, chunkSize int64) [][2]int64
<span id="FindLineChunksByOffset"></span>
> 该函数与 FindLineChunks 类似,不同的是该函数可以指定 offset 从指定位置开始读取文件
***

View File

@ -1,19 +1,20 @@
# Fsm
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/fsm)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewFSM](#NewFSM)|创建一个新的状态机
|[WithEnterBeforeEvent](#WithEnterBeforeEvent)|设置状态进入前的回调
@ -23,44 +24,52 @@
|[WithExitAfterEvent](#WithExitAfterEvent)|设置状态退出后的回调
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[FSM](#fsm)|状态机
|[Option](#option)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[FSM](#fsm)|状态机
|`STRUCT`|[Option](#option)|暂无描述...
</details>
***
## 详情信息
#### func NewFSM(data Data) *FSM[State, Data]
<span id="NewFSM"></span>
> 创建一个新的状态机
***
#### func WithEnterBeforeEvent(fn func (state *FSM[State, Data])) Option[State, Data]
<span id="WithEnterBeforeEvent"></span>
> 设置状态进入前的回调
> - 在首次设置状态时,状态机本身的当前状态为零值状态
***
#### func WithEnterAfterEvent(fn func (state *FSM[State, Data])) Option[State, Data]
<span id="WithEnterAfterEvent"></span>
> 设置状态进入后的回调
***
#### func WithUpdateEvent(fn func (state *FSM[State, Data])) Option[State, Data]
<span id="WithUpdateEvent"></span>
> 设置状态内刷新的回调
***
#### func WithExitBeforeEvent(fn func (state *FSM[State, Data])) Option[State, Data]
<span id="WithExitBeforeEvent"></span>
> 设置状态退出前的回调
> - 该阶段状态机的状态为退出前的状态,而非新的状态
***
#### func WithExitAfterEvent(fn func (state *FSM[State, Data])) Option[State, Data]
<span id="WithExitAfterEvent"></span>
> 设置状态退出后的回调
> - 该阶段状态机的状态为新的状态,而非退出前的状态
***
### FSM
### FSM `STRUCT`
状态机
```go
type FSM[State comparable, Data any] struct {
@ -75,8 +84,8 @@ type FSM[State comparable, Data any] struct {
exitAfterEventHandles map[State][]func(state *FSM[State, Data])
}
```
### Option
### Option `STRUCT`
```go
type Option[State comparable, Data any] struct{}
type Option[State comparable, Data any] func(fsm *FSM[State, Data], state State)
```

View File

@ -1,42 +1,66 @@
# Astgo
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/astgo)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewPackage](#NewPackage)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Comment](#comment)|暂无描述...
|[Field](#field)|暂无描述...
|[File](#file)|暂无描述...
|[Function](#function)|暂无描述...
|[Package](#package)|暂无描述...
|[Struct](#struct)|暂无描述...
|[Type](#type)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Comment](#comment)|暂无描述...
|`STRUCT`|[Field](#field)|暂无描述...
|`STRUCT`|[File](#file)|暂无描述...
|`STRUCT`|[Function](#function)|暂无描述...
|`STRUCT`|[Package](#package)|暂无描述...
|`STRUCT`|[Struct](#struct)|暂无描述...
|`STRUCT`|[Type](#type)|暂无描述...
</details>
***
## 详情信息
#### func NewPackage(dir string) *Package, error
<span id="NewPackage"></span>
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewPackage(t *testing.T) {
p, err := astgo.NewPackage(`/Users/kercylan/Coding.localized/Go/minotaur/server`)
if err != nil {
panic(err)
}
fmt.Println(string(super.MarshalIndentJSON(p, "", " ")))
}
```
</details>
***
### Comment
### Comment `STRUCT`
```go
type Comment struct {
@ -44,7 +68,7 @@ type Comment struct {
Clear []string
}
```
### Field
### Field `STRUCT`
```go
type Field struct {
@ -54,7 +78,7 @@ type Field struct {
Comments *Comment
}
```
### File
### File `STRUCT`
```go
type File struct {
@ -68,10 +92,11 @@ type File struct {
```
#### func (*File) Package() string
***
### Function
### Function `STRUCT`
```go
type Function struct {
decl *ast.FuncDecl
Name string
Internal bool
Generic []*Field
@ -85,14 +110,17 @@ type Function struct {
Test bool
}
```
### Package
#### func (*Function) Code() string
***
### Package `STRUCT`
```go
type Package struct {
Dir string
Name string
Dirs []string
Files []*File
Dir string
Name string
Dirs []string
Files []*File
Functions map[string]*Function
}
```
#### func (*Package) StructFunc(name string) []*Function
@ -103,19 +131,27 @@ type Package struct {
***
#### func (*Package) FileComments() *Comment
***
### Struct
#### func (*Package) GetUnitTest(f *Function) *Function
***
#### func (*Package) GetExampleTest(f *Function) *Function
***
#### func (*Package) GetBenchmarkTest(f *Function) *Function
***
### Struct `STRUCT`
```go
type Struct struct {
Name string
Internal bool
Comments *Comment
Generic []*Field
Fields []*Field
Test bool
Name string
Internal bool
Interface bool
Comments *Comment
Generic []*Field
Fields []*Field
Type *Type
Test bool
}
```
### Type
### Type `STRUCT`
```go
type Type struct {

View File

@ -1,6 +1,7 @@
package astgo
import (
"fmt"
"go/ast"
)
@ -14,6 +15,9 @@ func newField(field *ast.Field) []*Field {
} else {
var fs []*Field
for _, name := range field.Names {
if name.String() == "Format" {
fmt.Println()
}
fs = append(fs, &Field{
Anonymous: false,
Name: name.String(),

View File

@ -1,12 +1,16 @@
package astgo
import (
"bytes"
"go/ast"
"go/format"
"go/token"
"strings"
)
func newFunction(astFunc *ast.FuncDecl) *Function {
f := &Function{
decl: astFunc,
Name: astFunc.Name.String(),
Comments: newComment(astFunc.Doc),
}
@ -37,6 +41,7 @@ func newFunction(astFunc *ast.FuncDecl) *Function {
}
type Function struct {
decl *ast.FuncDecl
Name string // 函数名
Internal bool // 内部函数
Generic []*Field // 泛型定义
@ -49,3 +54,11 @@ type Function struct {
IsBenchmark bool // 是否为基准测试
Test bool // 是否为测试函数
}
func (f *Function) Code() string {
var bb bytes.Buffer
if err := format.Node(&bb, token.NewFileSet(), f.decl); err != nil {
panic(err)
}
return bb.String() + "\n"
}

View File

@ -2,12 +2,14 @@ package astgo
import (
"errors"
"fmt"
"github.com/kercylan98/minotaur/utils/str"
"os"
"path/filepath"
)
func NewPackage(dir string) (*Package, error) {
pkg := &Package{Dir: dir}
pkg := &Package{Dir: dir, Functions: map[string]*Function{}}
fs, err := os.ReadDir(dir)
if err != nil {
return nil, err
@ -26,7 +28,14 @@ func NewPackage(dir string) (*Package, error) {
continue
}
pkg.Files = append(pkg.Files, f)
for _, function := range f.Functions {
function := function
key := function.Name
if function.Struct != nil {
key = fmt.Sprintf("%s.%s", function.Struct.Name, key)
}
pkg.Functions[key] = function
}
}
if len(pkg.Files) == 0 {
return nil, errors.New("not found go ext file")
@ -37,10 +46,11 @@ func NewPackage(dir string) (*Package, error) {
}
type Package struct {
Dir string
Name string
Dirs []string
Files []*File
Dir string
Name string
Dirs []string
Files []*File
Functions map[string]*Function
}
func (p *Package) StructFunc(name string) []*Function {
@ -92,3 +102,24 @@ func (p *Package) FileComments() *Comment {
}
return comment
}
func (p *Package) GetUnitTest(f *Function) *Function {
if f.Struct == nil {
return p.Functions[fmt.Sprintf("Test%s", str.FirstUpper(f.Name))]
}
return p.Functions[fmt.Sprintf("Test%s_%s", f.Struct.Type.Name, f.Name)]
}
func (p *Package) GetExampleTest(f *Function) *Function {
if f.Struct == nil {
return p.Functions[fmt.Sprintf("Example%s", str.FirstUpper(f.Name))]
}
return p.Functions[fmt.Sprintf("Example%s_%s", f.Struct.Type.Name, f.Name)]
}
func (p *Package) GetBenchmarkTest(f *Function) *Function {
if f.Struct == nil {
return p.Functions[fmt.Sprintf("Benchmark%s", str.FirstUpper(f.Name))]
}
return p.Functions[fmt.Sprintf("Benchmark%s_%s", f.Struct.Type.Name, f.Name)]
}

View File

@ -17,20 +17,33 @@ func newStruct(astGen *ast.GenDecl) *Struct {
}
}
t, ok := astTypeSpec.Type.(*ast.StructType)
if ok && t.Fields != nil {
for _, field := range t.Fields.List {
s.Fields = append(s.Fields, newField(field)...)
switch ts := astTypeSpec.Type.(type) {
case *ast.StructType:
if ts.Fields != nil {
for _, field := range ts.Fields.List {
s.Fields = append(s.Fields, newField(field)...)
}
}
case *ast.InterfaceType:
s.Interface = true
if ts.Methods != nil {
for _, field := range ts.Methods.List {
s.Fields = append(s.Fields, newField(field)...)
}
}
default:
s.Type = newType(ts)
}
return s
}
type Struct struct {
Name string // 结构体名称
Internal bool // 内部结构体
Comments *Comment // 注释
Generic []*Field // 泛型类型
Fields []*Field // 结构体字段
Test bool // 是否是测试结构体
Name string // 结构体名称
Internal bool // 内部结构体
Interface bool // 接口定义
Comments *Comment // 注释
Generic []*Field // 泛型类型
Fields []*Field // 结构体字段
Type *Type // 和结构体字段二选一,处理类似 type a string 的情况
Test bool // 是否是测试结构体
}

View File

@ -65,7 +65,13 @@ func newType(expr ast.Expr) *Type {
return "(" + f + ")"
}
return f
}(), handler(e.Results))))
}(), func() string {
f := handler(e.Results)
if e.Results != nil && len(e.Results.List) >= 2 && !strings.HasSuffix(f, "(") {
return "(" + f + ")"
}
return f
}())))
case *ast.InterfaceType:
str.WriteString("interface {")
if e.Methods != nil && len(e.Methods.List) > 0 {

View File

@ -1,36 +1,40 @@
# Genreadme
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/genreadme)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[New](#New)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Builder](#builder)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Builder](#builder)|暂无描述...
</details>
***
## 详情信息
#### func New(pkgDirPath string, output string) *Builder, error
<span id="New"></span>
***
### Builder
### Builder `STRUCT`
```go
type Builder struct {
@ -40,4 +44,35 @@ type Builder struct {
}
```
#### func (*Builder) Generate() error
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestBuilder_Generate(t *testing.T) {
filepath.Walk("/Users/kercylan/Coding.localized/Go/minotaur", func(path string, info fs.FileInfo, err error) error {
if !info.IsDir() {
return nil
}
if strings.Contains(strings.TrimPrefix(path, "/Users/kercylan/Coding.localized/Go/minotaur"), ".") {
return nil
}
b, err := New(path, filepath.Join(path, "README.md"))
if err != nil {
return nil
}
if err = b.Generate(); err != nil {
panic(err)
}
return nil
})
}
```
</details>
***

View File

@ -42,31 +42,15 @@ func (b *Builder) Generate() error {
func (b *Builder) genHeader() {
b.title(1, str.FirstUpper(b.p.Name))
b.newLine()
b.newLine(b.p.FileComments().Clear...).newLine()
b.newLine(fmt.Sprintf(`[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/%s)`, b.p.Name))
b.newLine(fmt.Sprintf(`![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)`))
b.newLine().newLine(b.p.FileComments().Clear...).newLine()
b.newLine()
}
func (b *Builder) genMenus() {
b.title(2, "目录")
b.newLine("列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️")
b.detailsStart("展开 / 折叠目录")
b.quote("包级函数定义").newLine()
b.tableCel("函数", "描述")
for _, function := range b.p.PackageFunc() {
if function.Test || function.Internal {
continue
}
b.tableRow(
fmt.Sprintf("[%s](#%s)", function.Name, function.Name),
collection.FindFirstOrDefaultInSlice(function.Comments.Clear, "暂无描述..."),
)
}
b.newLine().newLine()
b.quote("结构体定义").newLine()
b.tableCel("结构体", "描述")
packageFunction := b.p.PackageFunc()
var structList []*astgo.Struct
for _, f := range b.p.Files {
if strings.HasSuffix(f.FilePath, "_test.go") {
continue
@ -75,16 +59,53 @@ func (b *Builder) genMenus() {
if structInfo.Test || structInfo.Internal {
continue
}
structList = append(structList, structInfo)
}
}
if len(packageFunction)+len(structList) > 0 {
b.title(2, "目录导航")
b.newLine("列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️")
b.detailsStart("展开 / 折叠目录导航")
}
if len(packageFunction) > 0 {
b.quote("包级函数定义").newLine()
b.tableCel("函数名称", "描述")
for _, function := range packageFunction {
if function.Test || function.Internal {
continue
}
b.tableRow(
fmt.Sprintf("[%s](#%s)", function.Name, function.Name),
collection.FindFirstOrDefaultInSlice(function.Comments.Clear, "暂无描述..."),
)
}
b.newLine().newLine()
}
if len(structList) > 0 {
b.quote("类型定义").newLine()
b.tableCel("类型", "名称", "描述")
for _, structInfo := range structList {
if structInfo.Test || structInfo.Internal {
continue
}
b.tableRow(
super.If(structInfo.Interface, "`INTERFACE`", "`STRUCT`"),
fmt.Sprintf("[%s](#%s)", structInfo.Name, strings.ToLower(structInfo.Name)),
collection.FindFirstOrDefaultInSlice(structInfo.Comments.Clear, "暂无描述..."),
)
}
b.detailsEnd()
}
b.detailsEnd()
b.newLine("***")
}
func (b *Builder) genStructs() {
b.title(2, "详情信息")
var funcHandler = func(params []*astgo.Field) string {
var s string
var brackets bool
@ -122,6 +143,20 @@ func (b *Builder) genStructs() {
for _, comment := range function.Comments.Clear {
b.quote(comment)
}
b.newLine()
if example := b.p.GetExampleTest(function); example != nil {
b.newLine("示例代码:", "```go\n", example.Code(), "```\n")
}
if unitTest := b.p.GetUnitTest(function); unitTest != nil {
b.detailsStart("查看 / 收起单元测试")
b.newLine("```go\n", unitTest.Code(), "```\n")
b.detailsEnd()
}
if benchmarkTest := b.p.GetBenchmarkTest(function); benchmarkTest != nil {
b.detailsStart("查看 / 收起基准测试")
b.newLine("```go\n", benchmarkTest.Code(), "```\n")
b.detailsEnd()
}
b.newLine("***")
}
@ -130,10 +165,10 @@ func (b *Builder) genStructs() {
if structInfo.Internal || structInfo.Test {
continue
}
b.title(3, structInfo.Name)
b.title(3, fmt.Sprintf("%s `%s`", structInfo.Name, super.If(structInfo.Interface, "INTERFACE", "STRUCT")))
b.newLine(structInfo.Comments.Clear...)
b.newLine("```go")
structDefine := fmt.Sprintf("type %s struct {%s}",
structDefine := fmt.Sprintf("type %s %s",
func() string {
var sb strings.Builder
sb.WriteString(structInfo.Name)
@ -150,11 +185,27 @@ func (b *Builder) genStructs() {
}(),
func() string {
var sb strings.Builder
if len(structInfo.Fields) > 0 {
sb.WriteString("\n")
}
for _, field := range structInfo.Fields {
sb.WriteString(fmt.Sprintf("\t%s %s\n", field.Name, field.Type.Sign))
if structInfo.Type == nil {
var head = "struct"
if structInfo.Interface {
head = "interface"
}
sb.WriteString(head + " {")
if len(structInfo.Fields) > 0 {
sb.WriteString("\n")
}
if structInfo.Interface {
for _, field := range structInfo.Fields {
sb.WriteString(fmt.Sprintf("\t%s %s\n", field.Name, strings.TrimPrefix(field.Type.Sign, "func")))
}
} else {
for _, field := range structInfo.Fields {
sb.WriteString(fmt.Sprintf("\t%s %s\n", field.Name, field.Type.Sign))
}
}
sb.WriteString("}")
} else {
sb.WriteString(structInfo.Type.Sign)
}
return sb.String()
}())
@ -183,11 +234,26 @@ func (b *Builder) genStructs() {
}(),
funcHandler(function.Results),
)))
//b.newLine(fmt.Sprintf(`<span id="%s"></span>`, function.Name))
b.quote()
for _, comment := range function.Comments.Clear {
b.quote(comment)
}
if function.Name == "Write" {
fmt.Println()
}
if example := b.p.GetExampleTest(function); example != nil {
b.newLine("示例代码:", "```go\n", example.Code(), "```\n")
}
if unitTest := b.p.GetUnitTest(function); unitTest != nil {
b.detailsStart("查看 / 收起单元测试")
b.newLine("```go\n", unitTest.Code(), "```\n")
b.detailsEnd()
}
if benchmarkTest := b.p.GetBenchmarkTest(function); benchmarkTest != nil {
b.detailsStart("查看 / 收起基准测试")
b.newLine("```go\n", benchmarkTest.Code(), "```\n")
b.detailsEnd()
}
b.newLine("***")
}
}
@ -243,7 +309,7 @@ func (b *Builder) tableRow(str ...string) *Builder {
}
func (b *Builder) detailsStart(title string) *Builder {
return b.newLine("<details>", "<summary>"+title+"</summary").newLine().newLine()
return b.newLine("<details>", "<summary>"+title+"</summary>").newLine().newLine()
}
func (b *Builder) detailsEnd() *Builder {

View File

@ -1,134 +1,163 @@
# Generic
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/generic)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
generic 目的在于提供一组基于泛型的用于处理通用功能的函数和数据结构。该包旨在简化通用功能的实现,并提供一致的接口和易于使用的功能。
主要特性:
- 通用功能generic 包支持处理各种通用功能,如数据结构操作、算法实现和常用工具等。您可以使用这些功能来解决各种通用问题,并提高代码的复用性和可维护性。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/generic)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[IsNil](#IsNil)|检查指定的值是否为 nil
|[IsAllNil](#IsAllNil)|检查指定的值是否全部为 nil
|[IsHasNil](#IsHasNil)|检查指定的值是否存在 nil
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[IdR](#idr)|暂无描述...
|[IDR](#idr)|暂无描述...
|[IdW](#idw)|暂无描述...
|[IDW](#idw)|暂无描述...
|[IdR2W](#idr2w)|暂无描述...
|[IDR2W](#idr2w)|暂无描述...
|[Ordered](#ordered)|可排序类型
|[Number](#number)|数字类型
|[SignedNumber](#signednumber)|有符号数字类型
|[Integer](#integer)|整数类型
|[Signed](#signed)|有符号整数类型
|[Unsigned](#unsigned)|无符号整数类型
|[UnsignedNumber](#unsignednumber)|无符号数字类型
|[Float](#float)|浮点类型
|[Basic](#basic)|基本类型
|类型|名称|描述
|:--|:--|:--
|`INTERFACE`|[IdR](#idr)|暂无描述...
|`INTERFACE`|[IDR](#idr)|暂无描述...
|`INTERFACE`|[IdW](#idw)|暂无描述...
|`INTERFACE`|[IDW](#idw)|暂无描述...
|`INTERFACE`|[IdR2W](#idr2w)|暂无描述...
|`INTERFACE`|[IDR2W](#idr2w)|暂无描述...
|`INTERFACE`|[Ordered](#ordered)|可排序类型
|`INTERFACE`|[Number](#number)|数字类型
|`INTERFACE`|[SignedNumber](#signednumber)|有符号数字类型
|`INTERFACE`|[Integer](#integer)|整数类型
|`INTERFACE`|[Signed](#signed)|有符号整数类型
|`INTERFACE`|[Unsigned](#unsigned)|无符号整数类型
|`INTERFACE`|[UnsignedNumber](#unsignednumber)|无符号数字类型
|`INTERFACE`|[Float](#float)|浮点类型
|`INTERFACE`|[Basic](#basic)|基本类型
</details>
***
## 详情信息
#### func IsNil(v V) bool
<span id="IsNil"></span>
> 检查指定的值是否为 nil
***
#### func IsAllNil(v ...V) bool
<span id="IsAllNil"></span>
> 检查指定的值是否全部为 nil
***
#### func IsHasNil(v ...V) bool
<span id="IsHasNil"></span>
> 检查指定的值是否存在 nil
***
### IdR
### IdR `INTERFACE`
```go
type IdR[ID comparable] struct{}
type IdR[ID comparable] interface {
GetId() ID
}
```
### IDR
### IDR `INTERFACE`
```go
type IDR[ID comparable] struct{}
type IDR[ID comparable] interface {
GetID() ID
}
```
### IdW
### IdW `INTERFACE`
```go
type IdW[ID comparable] struct{}
type IdW[ID comparable] interface {
SetId(id ID)
}
```
### IDW
### IDW `INTERFACE`
```go
type IDW[ID comparable] struct{}
type IDW[ID comparable] interface {
SetID(id ID)
}
```
### IdR2W
### IdR2W `INTERFACE`
```go
type IdR2W[ID comparable] struct{}
type IdR2W[ID comparable] interface {
IdR[ID]
IdW[ID]
}
```
### IDR2W
### IDR2W `INTERFACE`
```go
type IDR2W[ID comparable] struct{}
type IDR2W[ID comparable] interface {
IDR[ID]
IDW[ID]
}
```
### Ordered
### Ordered `INTERFACE`
可排序类型
```go
type Ordered struct{}
type Ordered interface {
}
```
### Number
### Number `INTERFACE`
数字类型
```go
type Number struct{}
type Number interface {
}
```
### SignedNumber
### SignedNumber `INTERFACE`
有符号数字类型
```go
type SignedNumber struct{}
type SignedNumber interface {
}
```
### Integer
### Integer `INTERFACE`
整数类型
```go
type Integer struct{}
type Integer interface {
}
```
### Signed
### Signed `INTERFACE`
有符号整数类型
```go
type Signed struct{}
type Signed interface {
}
```
### Unsigned
### Unsigned `INTERFACE`
无符号整数类型
```go
type Unsigned struct{}
type Unsigned interface {
}
```
### UnsignedNumber
### UnsignedNumber `INTERFACE`
无符号数字类型
```go
type UnsignedNumber struct{}
type UnsignedNumber interface {
}
```
### Float
### Float `INTERFACE`
浮点类型
```go
type Float struct{}
type Float interface {
}
```
### Basic
### Basic `INTERFACE`
基本类型
```go
type Basic struct{}
type Basic interface {
}
```

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,8 @@
# Astar
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/astar)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
astar 提供用于实现 A* 算法的函数和数据结构。A* 算法是一种常用的路径搜索算法,用于在图形或网络中找到最短路径。该包旨在简化 A* 算法的实现过程,并提供一致的接口和易于使用的功能。
主要特性:
- 图形表示astar 包支持使用图形或网络来表示路径搜索的环境。您可以定义节点和边,以构建图形,并在其中执行路径搜索。
@ -7,31 +10,31 @@ astar 提供用于实现 A* 算法的函数和数据结构。A* 算法是一种
- 自定义启发式函数:您可以根据具体问题定义自己的启发式函数,以指导 A* 算法的搜索过程。启发式函数用于估计从当前节点到目标节点的代价,以帮助算法选择最佳路径。
- 可定制性astar 包提供了一些可定制的选项,以满足不同场景下的需求。您可以设置节点的代价、边的权重等参数,以调整算法的行为。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/astar)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Find](#Find)|使用 A* 算法在导航网格上查找从起点到终点的最短路径,并返回路径上的节点序列。
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Graph](#graph)|适用于 A* 算法的图数据结构接口定义,表示导航网格,其中包含了节点和连接节点的边。
|类型|名称|描述
|:--|:--|:--
|`INTERFACE`|[Graph](#graph)|适用于 A* 算法的图数据结构接口定义,表示导航网格,其中包含了节点和连接节点的边。
</details>
***
## 详情信息
#### func Find(graph Graph[Node], start Node, end Node, cost func (a Node) V, heuristic func (a Node) V) []Node
<span id="Find"></span>
> 使用 A* 算法在导航网格上查找从起点到终点的最短路径,并返回路径上的节点序列。
@ -54,11 +57,32 @@ astar 提供用于实现 A* 算法的函数和数据结构。A* 算法是一种
> - 函数使用了 A* 算法来搜索最短路径。
> - 函数内部使用了堆数据结构来管理待处理的节点。
> - 函数返回一个节点序列,表示从起点到终点的最短路径。如果找不到路径,则返回空序列。
示例代码:
```go
func ExampleFind() {
graph := Graph{FloorPlan: geometry.FloorPlan{"===========", "X XX X X", "X X XX X", "X XX X", "X XXX X", "X XX X X", "X XX X X", "==========="}}
paths := astar.Find[geometry.Point[int], int](graph, geometry.NewPoint(1, 1), geometry.NewPoint(8, 6), func(a, b geometry.Point[int]) int {
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a, b))
}, func(a, b geometry.Point[int]) int {
return geometry.CalcDistanceWithCoordinate(geometry.DoublePointToCoordinate(a, b))
})
for _, path := range paths {
graph.Put(path, '.')
}
fmt.Println(graph)
}
```
***
### Graph
### Graph `INTERFACE`
适用于 A* 算法的图数据结构接口定义,表示导航网格,其中包含了节点和连接节点的边。
```go
type Graph[Node comparable] struct{}
type Graph[Node comparable] interface {
Neighbours(node Node) []Node
}
```
#### func (Graph) Neighbours(point geometry.Point[int]) []geometry.Point[int]
***

View File

@ -1,42 +1,75 @@
# Dp
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/dp)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
dp (DistributionPattern) 提供用于在二维数组中根据不同的特征标记为数组成员建立分布链接的函数和数据结构。该包的目标是实现快速查找与给定位置成员具有相同特征且位置紧邻的其他成员。
主要特性:
- 分布链接机制dp 包提供了一种分布链接的机制,可以根据成员的特征将它们链接在一起。这样,可以快速查找与给定成员具有相同特征且位置紧邻的其他成员。
- 二维数组支持:该包支持在二维数组中建立分布链接。可以将二维数组中的成员视为节点,并根据其特征进行链接。
- 快速查找功能:使用 dp 包提供的函数,可以快速查找与给定位置成员具有相同特征且位置紧邻的其他成员。这有助于在二维数组中进行相关性分析或查找相邻成员。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/dp)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewDistributionPattern](#NewDistributionPattern)|构建一个分布图实例
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[DistributionPattern](#distributionpattern)|分布图
|[Link](#link)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[DistributionPattern](#distributionpattern)|分布图
|`STRUCT`|[Link](#link)|暂无描述...
</details>
***
## 详情信息
#### func NewDistributionPattern(sameKindVerifyHandle func (itemA Item) bool) *DistributionPattern[Item]
<span id="NewDistributionPattern"></span>
> 构建一个分布图实例
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewDistributionPattern(t *testing.T) {
dp := NewDistributionPattern[int](func(itemA, itemB int) bool {
return itemA == itemB
})
matrix := []int{1, 1, 2, 2, 2, 2, 1, 2, 2}
dp.LoadMatrixWithPos(3, matrix)
for pos, link := range dp.links {
fmt.Println(pos, link, fmt.Sprintf("%p", link))
}
fmt.Println()
matrix[6] = 2
dp.Refresh(6)
for pos, link := range dp.links {
fmt.Println(pos, link, fmt.Sprintf("%p", link))
}
}
```
</details>
***
### DistributionPattern
### DistributionPattern `STRUCT`
分布图
```go
type DistributionPattern[Item any] struct {
@ -71,7 +104,7 @@ type DistributionPattern[Item any] struct {
> 通过特定的成员刷新特定位置的分布关系
> - 如果矩阵通过 LoadMatrixWithPos 加载,将会重定向至 Refresh
***
### Link
### Link `STRUCT`
```go
type Link[V any] struct {

View File

@ -1,39 +1,43 @@
# Matrix
matrix 提供了一个简单的二维数组的实现
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/matrix)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
matrix 提供了一个简单的二维数组的实现
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewMatrix](#NewMatrix)|生成特定宽高的二维矩阵
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Matrix](#matrix)|二维矩阵
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Matrix](#matrix)|二维矩阵
</details>
***
## 详情信息
#### func NewMatrix(width int, height int) *Matrix[T]
<span id="NewMatrix"></span>
> 生成特定宽高的二维矩阵
> - 虽然提供了通过x、y坐标的操作函数但是建议无论如何使用pos进行处理
> - 该矩阵为XY而非YX
***
### Matrix
### Matrix `STRUCT`
二维矩阵
```go
type Matrix[T any] struct {

View File

@ -1,35 +1,38 @@
# Navmesh
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/navmesh)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
navmesh 提供了用于导航网格处理的函数和数据结构。导航网格是一种常用的数据结构,用于在游戏开发和虚拟环境中进行路径规划和导航。该包旨在简化导航网格的创建、查询和操作过程,并提供高效的导航功能。
主要特性:
- 导航网格表示navmesh 包支持使用导航网格来表示虚拟环境中的可行走区域和障碍物。您可以定义多边形区域和连接关系,以构建导航网格,并在其中执行路径规划和导航。
- 导航算法:采用了 A* 算法作为导航算法,用于在导航网格中找到最短路径或最优路径。这些算法使用启发式函数和代价评估来指导路径搜索,并提供高效的路径规划能力。
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/navmesh)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewNavMesh](#NewNavMesh)|创建一个新的导航网格,并返回一个指向该导航网格的指针。
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[NavMesh](#navmesh)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[NavMesh](#navmesh)|暂无描述...
</details>
***
## 详情信息
#### func NewNavMesh(shapes []geometry.Shape[V], meshShrinkAmount V) *NavMesh[V]
<span id="NewNavMesh"></span>
> 创建一个新的导航网格,并返回一个指向该导航网格的指针。
@ -49,8 +52,9 @@ navmesh 提供了用于导航网格处理的函数和数据结构。导航网格
>
> 使用建议:
> - 确保 NavMesh 计算精度的情况下V 建议使用 float64 类型
***
### NavMesh
### NavMesh `STRUCT`
```go
type NavMesh[V generic.SignedNumber] struct {
@ -94,4 +98,32 @@ type NavMesh[V generic.SignedNumber] struct {
> - 如果起点或终点不在任何形状内部,且 NavMesh 的 meshShrinkAmount 大于0则会考虑缩小的形状。
> - 使用 A* 算法在 NavMesh 上搜索从起点形状到终点形状的最短路径。
> - 使用漏斗算法对路径进行优化,以得到最终的路径点序列。
示例代码:
```go
func ExampleNavMesh_FindPath() {
fp := geometry.FloorPlan{"=================================", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "X X", "================================="}
var walkable []geometry.Shape[int]
walkable = append(walkable, geometry.NewShape(geometry.NewPoint(5, 5), geometry.NewPoint(15, 5), geometry.NewPoint(15, 15), geometry.NewPoint(5, 15)), geometry.NewShape(geometry.NewPoint(15, 5), geometry.NewPoint(25, 5), geometry.NewPoint(25, 15), geometry.NewPoint(15, 15)), geometry.NewShape(geometry.NewPoint(15, 15), geometry.NewPoint(25, 15), geometry.NewPoint(25, 25), geometry.NewPoint(15, 25)))
for _, shape := range walkable {
for _, edge := range shape.Edges() {
sx, bx := maths.MinMax(edge.GetStart().GetX(), edge.GetEnd().GetX())
sy, by := maths.MinMax(edge.GetStart().GetY(), edge.GetEnd().GetY())
for x := sx; x <= bx; x++ {
for y := sy; y <= by; y++ {
fp.Put(geometry.NewPoint[int](x, y), '+')
}
}
}
}
nm := navmesh.NewNavMesh(walkable, 0)
path := nm.FindPath(geometry.NewPoint(6, 6), geometry.NewPoint(18, 24))
for _, point := range path {
fp.Put(geometry.NewPoint(point.GetX(), point.GetY()), 'G')
}
fmt.Println(fp)
}
```
***

View File

@ -1,37 +1,95 @@
# Hub
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/hub)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewObjectPool](#NewObjectPool)|创建一个 ObjectPool
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[ObjectPool](#objectpool)|基于 sync.Pool 实现的线程安全的对象池
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[ObjectPool](#objectpool)|基于 sync.Pool 实现的线程安全的对象池
</details>
***
## 详情信息
#### func NewObjectPool(generator func () *T, releaser func (data *T)) *ObjectPool[*T]
<span id="NewObjectPool"></span>
> 创建一个 ObjectPool
示例代码:
```go
func ExampleNewObjectPool() {
var p = hub.NewObjectPool[map[int]int](func() *map[int]int {
return &map[int]int{}
}, func(data *map[int]int) {
collection.ClearMap(*data)
})
m := *p.Get()
m[1] = 1
p.Release(&m)
fmt.Println(m)
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewObjectPool(t *testing.T) {
var cases = []struct {
name string
generator func() *map[string]int
releaser func(data *map[string]int)
shouldPanic bool
}{{name: "TestNewObjectPool_NilGenerator", generator: nil, releaser: func(data *map[string]int) {
}, shouldPanic: true}, {name: "TestNewObjectPool_NilReleaser", generator: func() *map[string]int {
return &map[string]int{}
}, releaser: nil, shouldPanic: true}, {name: "TestNewObjectPool_NilGeneratorAndReleaser", generator: nil, releaser: nil, shouldPanic: true}, {name: "TestNewObjectPool_Normal", generator: func() *map[string]int {
return &map[string]int{}
}, releaser: func(data *map[string]int) {
}, shouldPanic: false}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
defer func() {
if err := recover(); c.shouldPanic && err == nil {
t.Error("TestNewObjectPool should panic")
}
}()
_ = hub.NewObjectPool[map[string]int](c.generator, c.releaser)
})
}
}
```
</details>
***
### ObjectPool
### ObjectPool `STRUCT`
基于 sync.Pool 实现的线程安全的对象池
- 一些高频临时生成使用的对象可以通过 ObjectPool 进行管理,例如属性计算等
```go
@ -42,7 +100,79 @@ type ObjectPool[T any] struct {
```
#### func (*ObjectPool) Get() T
> 获取一个对象
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestObjectPool_Get(t *testing.T) {
var cases = []struct {
name string
generator func() *map[string]int
releaser func(data *map[string]int)
}{{name: "TestObjectPool_Get_Normal", generator: func() *map[string]int {
return &map[string]int{}
}, releaser: func(data *map[string]int) {
for k := range *data {
delete(*data, k)
}
}}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pool := hub.NewObjectPool[map[string]int](c.generator, c.releaser)
if actual := pool.Get(); len(*actual) != 0 {
t.Error("TestObjectPool_Get failed")
}
})
}
}
```
</details>
***
#### func (*ObjectPool) Release(data T)
> 将使用完成的对象放回缓冲区
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestObjectPool_Release(t *testing.T) {
var cases = []struct {
name string
generator func() *map[string]int
releaser func(data *map[string]int)
}{{name: "TestObjectPool_Release_Normal", generator: func() *map[string]int {
return &map[string]int{}
}, releaser: func(data *map[string]int) {
for k := range *data {
delete(*data, k)
}
}}}
for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
pool := hub.NewObjectPool[map[string]int](c.generator, c.releaser)
msg := pool.Get()
m := *msg
m["test"] = 1
pool.Release(msg)
if len(m) != 0 {
t.Error("TestObjectPool_Release failed")
}
})
}
}
```
</details>
***

View File

@ -1,19 +1,20 @@
# Huge
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/huge)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewFloat](#NewFloat)|创建一个 Float
|[NewFloatByString](#NewFloatByString)|通过字符串创建一个 Float
@ -21,38 +22,44 @@
|[NewIntByString](#NewIntByString)|通过字符串创建一个 Int
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Float](#float)|暂无描述...
|[Int](#int)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Float](#float)|暂无描述...
|`STRUCT`|[Int](#int)|暂无描述...
</details>
***
## 详情信息
#### func NewFloat(x T) *Float
<span id="NewFloat"></span>
> 创建一个 Float
***
#### func NewFloatByString(i string) *Float
<span id="NewFloatByString"></span>
> 通过字符串创建一个 Float
> - 如果字符串不是一个合法的数字,则返回 0
***
#### func NewInt(x T) *Int
<span id="NewInt"></span>
> 创建一个 Int
***
#### func NewIntByString(i string) *Int
<span id="NewIntByString"></span>
> 通过字符串创建一个 Int
> - 如果字符串不是一个合法的数字,则返回 0
***
### Float
### Float `STRUCT`
```go
type Float struct{}
type Float big.Float
```
#### func (*Float) Copy() *Float
***
@ -110,10 +117,10 @@ type Float struct{}
#### func (*Float) IsNegative() bool
> 是否为负数
***
### Int
### Int `STRUCT`
```go
type Int struct{}
type Int big.Int
```
#### func (*Int) Copy() *Int
***

View File

@ -1,51 +1,67 @@
# Leaderboard
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/leaderboard)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewBinarySearch](#NewBinarySearch)|创建一个基于内存的二分查找排行榜
|[WithBinarySearchCount](#WithBinarySearchCount)|通过限制排行榜竞争者数量来创建排行榜
|[WithBinarySearchASC](#WithBinarySearchASC)|通过升序的方式创建排行榜
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[BinarySearch](#binarysearch)|暂无描述...
|[BinarySearchRankChangeEventHandle](#binarysearchrankchangeeventhandle)|暂无描述...
|[BinarySearchOption](#binarysearchoption)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[BinarySearch](#binarysearch)|暂无描述...
|`STRUCT`|[BinarySearchRankChangeEventHandle](#binarysearchrankchangeeventhandle)|暂无描述...
|`STRUCT`|[BinarySearchOption](#binarysearchoption)|暂无描述...
</details>
***
## 详情信息
#### func NewBinarySearch(options ...BinarySearchOption[CompetitorID, Score]) *BinarySearch[CompetitorID, Score]
<span id="NewBinarySearch"></span>
> 创建一个基于内存的二分查找排行榜
示例代码:
```go
func ExampleNewBinarySearch() {
bs := leaderboard2.NewBinarySearch[string, int](leaderboard2.WithBinarySearchCount[string, int](10))
fmt.Println(bs != nil)
}
```
***
#### func WithBinarySearchCount(rankCount int) BinarySearchOption[CompetitorID, Score]
<span id="WithBinarySearchCount"></span>
> 通过限制排行榜竞争者数量来创建排行榜
> - 默认情况下允许100位竞争者
***
#### func WithBinarySearchASC() BinarySearchOption[CompetitorID, Score]
<span id="WithBinarySearchASC"></span>
> 通过升序的方式创建排行榜
> - 默认情况下为降序
***
### BinarySearch
### BinarySearch `STRUCT`
```go
type BinarySearch[CompetitorID comparable, Score generic.Ordered] struct {
@ -58,13 +74,13 @@ type BinarySearch[CompetitorID comparable, Score generic.Ordered] struct {
rankClearBeforeEventHandles []BinarySearchRankClearBeforeEventHandle[CompetitorID, Score]
}
```
### BinarySearchRankChangeEventHandle
### BinarySearchRankChangeEventHandle `STRUCT`
```go
type BinarySearchRankChangeEventHandle[CompetitorID comparable, Score generic.Ordered] struct{}
type BinarySearchRankChangeEventHandle[CompetitorID comparable, Score generic.Ordered] func(leaderboard *BinarySearch[CompetitorID, Score], competitorId CompetitorID, oldRank int, oldScore Score)
```
### BinarySearchOption
### BinarySearchOption `STRUCT`
```go
type BinarySearchOption[CompetitorID comparable, Score generic.Ordered] struct{}
type BinarySearchOption[CompetitorID comparable, Score generic.Ordered] func(list *BinarySearch[CompetitorID, Score])
```

View File

@ -1,19 +1,20 @@
# Log
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/log)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[CallerBasicFormat](#CallerBasicFormat)|返回调用者的基本格式
|[Println](#Println)|暂无描述...
@ -72,255 +73,339 @@
|[NewOptions](#NewOptions)|创建一个新的日志选项
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Field](#field)|暂无描述...
|[Logger](#logger)|暂无描述...
|[MultiHandler](#multihandler)|暂无描述...
|[Option](#option)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Field](#field)|暂无描述...
|`STRUCT`|[Logger](#logger)|暂无描述...
|`STRUCT`|[MultiHandler](#multihandler)|暂无描述...
|`STRUCT`|[Option](#option)|暂无描述...
</details>
***
## 详情信息
#### func CallerBasicFormat(file string, line int) (repFile string, refLine string)
<span id="CallerBasicFormat"></span>
> 返回调用者的基本格式
***
#### func Println(str string, color string, desc string)
<span id="Println"></span>
***
#### func Default() *Logger
<span id="Default"></span>
> 获取默认的日志记录器
***
#### func SetDefault(l *Logger)
<span id="SetDefault"></span>
> 设置默认的日志记录器
***
#### func SetDefaultBySlog(l *slog.Logger)
<span id="SetDefaultBySlog"></span>
> 设置默认的日志记录器
***
#### func Debug(msg string, args ...any)
<span id="Debug"></span>
> 在 DebugLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
***
#### func Info(msg string, args ...any)
<span id="Info"></span>
> 在 InfoLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
***
#### func Warn(msg string, args ...any)
<span id="Warn"></span>
> 在 WarnLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
***
#### func Error(msg string, args ...any)
<span id="Error"></span>
> 在 ErrorLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
***
#### func DPanic(msg string, args ...any)
<span id="DPanic"></span>
> 在 DPanicLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
> - 如果记录器处于开发模式,它就会出现 panicDPanic 的意思是“development panic”。这对于捕获可恢复但不应该发生的错误很有用
> - 该 panic 仅在 NewHandler 中创建的处理器会生效
***
#### func Panic(msg string, args ...any)
<span id="Panic"></span>
> 在 PanicLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
> - 即使禁用了 PanicLevel 的日志记录,记录器也会出现 panic
***
#### func Fatal(msg string, args ...any)
<span id="Fatal"></span>
> 在 FatalLevel 记录一条消息。该消息包括在日志站点传递的任何字段以及记录器上累积的任何字段
> - 然后记录器调用 os.Exit(1),即使 FatalLevel 的日志记录被禁用
***
#### func Skip(vs ...any) slog.Attr
<span id="Skip"></span>
> 构造一个无操作字段,这在处理其他 Field 构造函数中的无效输入时通常很有用
> - 该函数还支持将其他字段快捷的转换为 Skip 字段
***
#### func Duration(key string, val time.Duration) slog.Attr
<span id="Duration"></span>
> 使用给定的键和值构造一个字段。编码器控制持续时间的序列化方式
***
#### func DurationP(key string, val *time.Duration) slog.Attr
<span id="DurationP"></span>
> 构造一个带有 time.Duration 的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Bool(key string, val bool) slog.Attr
<span id="Bool"></span>
> 构造一个带有布尔值的字段
***
#### func BoolP(key string, val *bool) slog.Attr
<span id="BoolP"></span>
> 构造一个带有布尔值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func String(key string, val string) slog.Attr
<span id="String"></span>
> 构造一个带有字符串值的字段
***
#### func StringP(key string, val *string) slog.Attr
<span id="StringP"></span>
> 构造一个带有字符串值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Int(key string, val I) slog.Attr
<span id="Int"></span>
> 构造一个带有整数值的字段
***
#### func IntP(key string, val *I) slog.Attr
<span id="IntP"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Int8(key string, val I) slog.Attr
<span id="Int8"></span>
> 构造一个带有整数值的字段
***
#### func Int8P(key string, val *I) slog.Attr
<span id="Int8P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Int16(key string, val I) slog.Attr
<span id="Int16"></span>
> 构造一个带有整数值的字段
***
#### func Int16P(key string, val *I) slog.Attr
<span id="Int16P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Int32(key string, val I) slog.Attr
<span id="Int32"></span>
> 构造一个带有整数值的字段
***
#### func Int32P(key string, val *I) slog.Attr
<span id="Int32P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Int64(key string, val I) slog.Attr
<span id="Int64"></span>
> 构造一个带有整数值的字段
***
#### func Int64P(key string, val *I) slog.Attr
<span id="Int64P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Uint(key string, val I) slog.Attr
<span id="Uint"></span>
> 构造一个带有整数值的字段
***
#### func UintP(key string, val *I) slog.Attr
<span id="UintP"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Uint8(key string, val I) slog.Attr
<span id="Uint8"></span>
> 构造一个带有整数值的字段
***
#### func Uint8P(key string, val *I) slog.Attr
<span id="Uint8P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Uint16(key string, val I) slog.Attr
<span id="Uint16"></span>
> 构造一个带有整数值的字段
***
#### func Uint16P(key string, val *I) slog.Attr
<span id="Uint16P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Uint32(key string, val I) slog.Attr
<span id="Uint32"></span>
> 构造一个带有整数值的字段
***
#### func Uint32P(key string, val *I) slog.Attr
<span id="Uint32P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Uint64(key string, val I) slog.Attr
<span id="Uint64"></span>
> 构造一个带有整数值的字段
***
#### func Uint64P(key string, val *I) slog.Attr
<span id="Uint64P"></span>
> 构造一个带有整数值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Float(key string, val F) slog.Attr
<span id="Float"></span>
> 构造一个带有浮点值的字段
***
#### func FloatP(key string, val *F) slog.Attr
<span id="FloatP"></span>
> 构造一个带有浮点值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Float32(key string, val F) slog.Attr
<span id="Float32"></span>
> 构造一个带有浮点值的字段
***
#### func Float32P(key string, val *F) slog.Attr
<span id="Float32P"></span>
> 构造一个带有浮点值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Float64(key string, val F) slog.Attr
<span id="Float64"></span>
> 构造一个带有浮点值的字段
***
#### func Float64P(key string, val *F) slog.Attr
<span id="Float64P"></span>
> 构造一个带有浮点值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Time(key string, val time.Time) slog.Attr
<span id="Time"></span>
> 构造一个带有时间值的字段
***
#### func TimeP(key string, val *time.Time) slog.Attr
<span id="TimeP"></span>
> 构造一个带有时间值的字段。返回的 Field 将在适当的时候安全且显式地表示 "null"
***
#### func Any(key string, val any) slog.Attr
<span id="Any"></span>
> 构造一个带有任意值的字段
***
#### func Group(key string, args ...any) slog.Attr
<span id="Group"></span>
> 返回分组字段
***
#### func Stack(key string) slog.Attr
<span id="Stack"></span>
> 返回堆栈字段
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestStack(t *testing.T) {
var i int
for {
time.Sleep(time.Second)
Debug("TestStack")
Info("TestStack")
Warn("TestStack")
Error("TestStack")
i++
if i == 3 {
Default().Logger.Handler().(*handler).opts.GerRuntimeHandler().ChangeLevel(slog.LevelInfo)
}
}
}
```
</details>
***
#### func Err(err error) slog.Attr
<span id="Err"></span>
> 构造一个带有错误值的字段
***
#### func NewHandler(w io.Writer, opts *Options) slog.Handler
<span id="NewHandler"></span>
> 创建一个更偏向于人类可读的处理程序,该处理程序也是默认的处理程序
***
#### func NewLogger(handlers ...slog.Handler) *Logger
<span id="NewLogger"></span>
> 创建一个新的日志记录器
***
#### func NewMultiHandler(handlers ...slog.Handler) slog.Handler
<span id="NewMultiHandler"></span>
> 创建一个新的多处理程序
***
#### func NewOptions() *Options
<span id="NewOptions"></span>
> 创建一个新的日志选项
***
### Field
### Field `STRUCT`
```go
type Field struct{}
type Field slog.Attr
```
### Logger
### Logger `STRUCT`
```go
type Logger struct {
*slog.Logger
}
```
### MultiHandler
### MultiHandler `STRUCT`
```go
type MultiHandler struct {
@ -335,8 +420,8 @@ type MultiHandler struct {
***
#### func (MultiHandler) WithGroup(name string) slog.Handler
***
### Option
### Option `STRUCT`
```go
type Option struct{}
type Option func(opts *Options)
```

View File

@ -1,19 +1,20 @@
# Survey
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/survey)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewFileFlusher](#NewFileFlusher)|创建一个文件刷新器
|[WithFlushInterval](#WithFlushInterval)|设置日志文件刷新间隔
@ -27,67 +28,132 @@
|[IncrementAnalyze](#IncrementAnalyze)|增量分析,返回一个函数,每次调用该函数都会分析文件中新增的内容
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Analyzer](#analyzer)|分析器
|[Flusher](#flusher)|用于刷新缓冲区的接口
|[FileFlusher](#fileflusher)|暂无描述...
|[Option](#option)|选项
|[Result](#result)|暂无描述...
|[R](#r)|记录器所记录的一条数据
|[Report](#report)|分析报告
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Analyzer](#analyzer)|分析器
|`INTERFACE`|[Flusher](#flusher)|用于刷新缓冲区的接口
|`STRUCT`|[FileFlusher](#fileflusher)|暂无描述...
|`STRUCT`|[Option](#option)|选项
|`STRUCT`|[Result](#result)|暂无描述...
|`STRUCT`|[R](#r)|记录器所记录的一条数据
|`STRUCT`|[Report](#report)|分析报告
</details>
***
## 详情信息
#### func NewFileFlusher(filePath string, layout ...string) *FileFlusher
<span id="NewFileFlusher"></span>
> 创建一个文件刷新器
> - layout 为日志文件名的时间戳格式 (默认为 time.DateOnly)
***
#### func WithFlushInterval(interval time.Duration) Option
<span id="WithFlushInterval"></span>
> 设置日志文件刷新间隔
> - 默认为 3s当日志文件刷新间隔 <= 0 时,将会在每次写入日志时刷新日志文件
***
#### func Reg(name string, flusher Flusher, options ...Option)
<span id="Reg"></span>
> 注册一个运营日志记录器
***
#### func Record(name string, data map[string]any)
<span id="Record"></span>
> 记录一条运营日志
***
#### func RecordBytes(name string, data []byte)
<span id="RecordBytes"></span>
> 记录一条运营日志
***
#### func Flush(names ...string)
<span id="Flush"></span>
> 将运营日志记录器的缓冲区数据写入到文件
> - name 为空时,将所有记录器的缓冲区数据写入到文件
***
#### func Close(names ...string)
<span id="Close"></span>
> 关闭运营日志记录器
***
#### func Analyze(filePath string, handle func (analyzer *Analyzer, record R)) *Report
<span id="Analyze"></span>
> 分析特定文件的记录,当发生错误时,会发生 panic
> - handle 为并行执行的,需要自行处理并发安全
> - 适用于外部进程对于日志文件的读取,但是需要注意的是,此时日志文件可能正在被写入,所以可能会读取到错误的数据
***
#### func AnalyzeMulti(filePaths []string, handle func (analyzer *Analyzer, record R)) *Report
<span id="AnalyzeMulti"></span>
> 与 Analyze 类似,但是可以分析多个文件
***
#### func IncrementAnalyze(filePath string, handle func (analyzer *Analyzer, record R)) func () *Report, error
#### func IncrementAnalyze(filePath string, handle func (analyzer *Analyzer, record R)) func () ( *Report, error)
<span id="IncrementAnalyze"></span>
> 增量分析,返回一个函数,每次调用该函数都会分析文件中新增的内容
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestIncrementAnalyze(t *testing.T) {
path := `./test/day.2023-09-06.log`
reader := survey.IncrementAnalyze(path, func(analyzer *survey.Analyzer, record survey.R) {
switch record.GetString("type") {
case "open_conn":
analyzer.IncreaseValueNonRepeat("开播人数", record, 1, "live_id")
case "report_rank":
analyzer.IncreaseValue("开始游戏次数", 1)
analyzer.Increase("开播时长", record, "game_time")
analyzer.Sub(record.GetString("live_id")).IncreaseValue("开始游戏次数", 1)
analyzer.Sub(record.GetString("live_id")).Increase("开播时长", record, "game_time")
case "statistics":
analyzer.IncreaseValueNonRepeat("活跃人数", record, 1, "active_player")
analyzer.IncreaseValueNonRepeat("评论人数", record, 1, "comment_player")
analyzer.IncreaseValueNonRepeat("点赞人数", record, 1, "like_player")
analyzer.Sub(record.GetString("live_id")).IncreaseValueNonRepeat("活跃人数", record, 1, "active_player")
analyzer.Sub(record.GetString("live_id")).IncreaseValueNonRepeat("评论人数", record, 1, "comment_player")
analyzer.Sub(record.GetString("live_id")).IncreaseValueNonRepeat("点赞人数", record, 1, "like_player")
giftId := record.GetString("gift.gift_id")
if len(giftId) > 0 {
giftPrice := record.GetFloat64("gift.price")
giftCount := record.GetFloat64("gift.count")
giftSender := record.GetString("gift.gift_senders")
analyzer.IncreaseValue("礼物总价值", giftPrice*giftCount)
analyzer.IncreaseValueNonRepeat(fmt.Sprintf("送礼人数_%s", giftId), record, 1, giftSender)
analyzer.IncreaseValue(fmt.Sprintf("礼物总数_%s", giftId), giftCount)
analyzer.Sub(record.GetString("live_id")).IncreaseValue("礼物总价值", giftPrice*giftCount)
analyzer.Sub(record.GetString("live_id")).IncreaseValueNonRepeat(fmt.Sprintf("送礼人数_%s", giftId), record, 1, giftSender)
analyzer.Sub(record.GetString("live_id")).IncreaseValue(fmt.Sprintf("礼物总数_%s", giftId), giftCount)
}
}
})
for i := 0; i < 10; i++ {
report, err := reader()
if err != nil {
t.Fatal(err)
}
fmt.Println(report.FilterSub("warzone0009"))
}
}
```
</details>
***
### Analyzer
### Analyzer `STRUCT`
分析器
```go
type Analyzer struct {
@ -148,12 +214,15 @@ type Analyzer struct {
#### func (*Analyzer) GetValueString(key string) string
> 获取当前记录的值
***
### Flusher
### Flusher `INTERFACE`
用于刷新缓冲区的接口
```go
type Flusher struct{}
type Flusher interface {
Flush(records []string)
Info() string
}
```
### FileFlusher
### FileFlusher `STRUCT`
```go
type FileFlusher struct {
@ -168,20 +237,20 @@ type FileFlusher struct {
***
#### func (*FileFlusher) Info() string
***
### Option
### Option `STRUCT`
选项
```go
type Option struct{}
type Option func(logger *logger)
```
### Result
### Result `STRUCT`
```go
type Result struct{}
type Result gjson.Result
```
### R
### R `STRUCT`
记录器所记录的一条数据
```go
type R struct{}
type R string
```
#### func (R) GetTime(layout string) time.Time
> 获取该记录的时间
@ -211,7 +280,7 @@ type R struct{}
***
#### func (R) String() string
***
### Report
### Report `STRUCT`
分析报告
```go
type Report struct {

View File

@ -1,19 +1,20 @@
# Maths
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/maths)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Compare](#Compare)|根据特定表达式比较两个值
|[IsContinuity](#IsContinuity)|检查一组值是否连续
@ -40,114 +41,180 @@
|[MakeLastDigitsZero](#MakeLastDigitsZero)|返回一个新的数,其中 num 的最后 digits 位数被设为零。
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[CompareExpression](#compareexpression)|比较表达式
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[CompareExpression](#compareexpression)|比较表达式
</details>
***
## 详情信息
#### func Compare(a V, expression CompareExpression, b V) bool
<span id="Compare"></span>
> 根据特定表达式比较两个值
***
#### func IsContinuity(values S) bool
<span id="IsContinuity"></span>
> 检查一组值是否连续
示例代码:
```go
func ExampleIsContinuity() {
fmt.Println(maths.IsContinuity([]int{1, 2, 3, 4, 5, 6, 7}))
fmt.Println(maths.IsContinuity([]int{1, 2, 3, 5, 5, 6, 7}))
}
```
***
#### func IsContinuityWithSort(values S) bool
<span id="IsContinuityWithSort"></span>
> 检查一组值排序后是否连续
***
#### func GetDefaultTolerance() float64
<span id="GetDefaultTolerance"></span>
> 获取默认误差范围
***
#### func Pow(a int, n int) int
<span id="Pow"></span>
> 整数幂运算
***
#### func PowInt64(a int64, n int64) int64
<span id="PowInt64"></span>
> 整数幂运算
***
#### func Min(a V, b V) V
<span id="Min"></span>
> 返回两个数之中较小的值
***
#### func Max(a V, b V) V
<span id="Max"></span>
> 返回两个数之中较大的值
***
#### func MinMax(a V, b V) (min V, max V)
<span id="MinMax"></span>
> 将两个数按照较小的和较大的顺序进行返回
***
#### func MaxMin(a V, b V) (max V, min V)
<span id="MaxMin"></span>
> 将两个数按照较大的和较小的顺序进行返回
***
#### func Clamp(value V, min V, max V) V
<span id="Clamp"></span>
> 将给定值限制在最小值和最大值之间
***
#### func Tolerance(value1 V, value2 V, tolerance V) bool
<span id="Tolerance"></span>
> 检查两个值是否在一个误差范围内
***
#### func Merge(refer V, a V, b V) V
<span id="Merge"></span>
> 通过一个参考值合并两个数字
***
#### func UnMerge(refer V, num V) (a V, b V)
<span id="UnMerge"></span>
> 通过一个参考值取消合并的两个数字
***
#### func MergeToInt64(v1 V, v2 V) int64
<span id="MergeToInt64"></span>
> 将两个数字合并为一个 int64 数字
***
#### func UnMergeInt64(n int64) V, V
<span id="UnMergeInt64"></span>
> 将一个 int64 数字拆分为两个数字
***
#### func ToContinuous(nums S) map[V]V
<span id="ToContinuous"></span>
> 将一组非连续的数字转换为从1开始的连续数字
> - 返回值是一个 mapkey 是从 1 开始的连续数字value 是原始数字
示例代码:
```go
func ExampleToContinuous() {
var nums = []int{1, 2, 3, 5, 6, 7, 9, 10, 11}
var continuous = maths.ToContinuous(nums)
fmt.Println(nums)
fmt.Println(continuous)
}
```
***
#### func CountDigits(num V) int
<span id="CountDigits"></span>
> 接收一个整数 num 作为输入,并返回该数字的位数
***
#### func GetDigitValue(num int64, digit int) int64
<span id="GetDigitValue"></span>
> 接收一个整数 num 和一个表示目标位数的整数 digit 作为输入,并返
> 回数字 num 在指定位数上的数值。我们使用 math.Abs() 函数获取 num 的绝对值,并通
> 过除以10的操作将 num 移动到目标位数上。然后,通过取余运算得到位数上的数值
***
#### func JoinNumbers(num1 V, n ...V) V
<span id="JoinNumbers"></span>
> 将一组数字连接起来
***
#### func IsOdd(n V) bool
<span id="IsOdd"></span>
> 返回 n 是否为奇数
***
#### func IsEven(n V) bool
<span id="IsEven"></span>
> 返回 n 是否为偶数
***
#### func MakeLastDigitsZero(num T, digits int) T
<span id="MakeLastDigitsZero"></span>
> 返回一个新的数,其中 num 的最后 digits 位数被设为零。
> - 函数首先创建一个 10 的 digits 次方的遮罩,然后通过整除和乘以这个遮罩来使 num 的最后 digits 位归零。
> - 当 T 类型为浮点型时,将被向下取整后再进行转换
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestMakeLastDigitsZero(t *testing.T) {
for i := 0; i < 20; i++ {
n := float64(random.Int64(100, 999999))
t.Log(n, 3, maths.MakeLastDigitsZero(n, 3))
}
}
```
</details>
***
### CompareExpression
### CompareExpression `STRUCT`
比较表达式
```go
type CompareExpression struct{}
type CompareExpression int
```

View File

@ -1,19 +1,20 @@
# Memory
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/memory)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Run](#Run)|运行持久化缓存程序
|[BindPersistCacheProgram](#BindPersistCacheProgram)|绑定持久化缓存程序
@ -21,18 +22,21 @@
|[NewOption](#NewOption)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Option](#option)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Option](#option)|暂无描述...
</details>
***
## 详情信息
#### func Run()
<span id="Run"></span>
> 运行持久化缓存程序
***
#### func BindPersistCacheProgram(name string, handler OutputParamHandlerFunc, option ...*Option) func ()
<span id="BindPersistCacheProgram"></span>
@ -46,6 +50,7 @@
> - 持久化程序处理函数参数类型必须与绑定的缓存程序输出参数类型一致,并且相同 name 的持久化程序必须在 BindAction 之后进行绑定
> - 默认情况下只有执行该函数返回的函数才会进行持久化,如果需要持久化策略,可以设置 option 参数或者自行实现策略调用返回的函数
> - 所有持久化程序绑定完成后,应该主动调用 Run 函数运行
***
#### func BindAction(name string, handler Func) Func
<span id="BindAction"></span>
@ -60,11 +65,38 @@
>
> 使用场景:
> - 例如在游戏中,需要根据玩家 ID 查询玩家信息,可以使用该函数进行绑定,当查询玩家信息时,如果缓存中存在该玩家信息,将直接返回缓存中的数据,否则将执行 handler 函数进行查询并缓存
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestBindAction(t *testing.T) {
var player *Player
player = QueryPlayer(1)
fmt.Println(player.ID)
player.ID = 666
player = QueryPlayer(1)
fmt.Println(player.ID)
player = QueryPlayer(2)
fmt.Println(player.ID)
QueryPlayerPersist()
time.Sleep(times.Week)
}
```
</details>
***
#### func NewOption() *Option
<span id="NewOption"></span>
***
### Option
### Option `STRUCT`
```go
type Option struct {

View File

@ -1,19 +1,20 @@
# Moving
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/moving)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewTwoDimensional](#NewTwoDimensional)|创建一个用于2D对象移动的实例(TwoDimensional)
|[WithTwoDimensionalTimeUnit](#WithTwoDimensionalTimeUnit)|通过特定时间单位创建
@ -22,40 +23,79 @@
|[NewEntity](#NewEntity)|暂无描述...
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[TwoDimensional](#twodimensional)|用于2D对象移动的数据结构
|[TwoDimensionalEntity](#twodimensionalentity)|2D移动对象接口定义
|[Position2DChangeEventHandle](#position2dchangeeventhandle)|暂无描述...
|[TwoDimensionalOption](#twodimensionaloption)|暂无描述...
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[TwoDimensional](#twodimensional)|用于2D对象移动的数据结构
|`INTERFACE`|[TwoDimensionalEntity](#twodimensionalentity)|2D移动对象接口定义
|`STRUCT`|[Position2DChangeEventHandle](#position2dchangeeventhandle)|暂无描述...
|`STRUCT`|[TwoDimensionalOption](#twodimensionaloption)|暂无描述...
</details>
***
## 详情信息
#### func NewTwoDimensional(options ...TwoDimensionalOption[EID, PosType]) *TwoDimensional[EID, PosType]
<span id="NewTwoDimensional"></span>
> 创建一个用于2D对象移动的实例(TwoDimensional)
示例代码:
```go
func ExampleNewTwoDimensional() {
m := moving2.NewTwoDimensional[int64, float64]()
defer func() {
m.Release()
}()
fmt.Println(m != nil)
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewTwoDimensional(t *testing.T) {
m := moving2.NewTwoDimensional[int64, float64]()
defer func() {
m.Release()
}()
}
```
</details>
***
#### func WithTwoDimensionalTimeUnit(duration time.Duration) TwoDimensionalOption[EID, PosType]
<span id="WithTwoDimensionalTimeUnit"></span>
> 通过特定时间单位创建
> - 默认单位为1毫秒最小单位也为1毫秒
***
#### func WithTwoDimensionalIdleWaitTime(duration time.Duration) TwoDimensionalOption[EID, PosType]
<span id="WithTwoDimensionalIdleWaitTime"></span>
> 通过特定的空闲等待时间创建
> - 默认情况下在没有新的移动计划时将限制 100毫秒 + 移动间隔事件(默认100毫秒)
***
#### func WithTwoDimensionalInterval(duration time.Duration) TwoDimensionalOption[EID, PosType]
<span id="WithTwoDimensionalInterval"></span>
> 通过特定的移动间隔时间创建
***
#### func NewEntity(guid int64, speed float64) *MoveEntity
<span id="NewEntity"></span>
***
### TwoDimensional
### TwoDimensional `STRUCT`
用于2D对象移动的数据结构
- 通过对象调用 MoveTo 方法后将开始执行该对象的移动
- 移动将在根据设置的每次移动间隔时间(WithTwoDimensionalInterval)进行移动,当无对象移动需要移动时将会进入短暂的休眠
@ -73,18 +113,23 @@ type TwoDimensional[EID generic.Basic, PosType generic.SignedNumber] struct {
position2DStopMoveEventHandles []Position2DStopMoveEventHandle[EID, PosType]
}
```
### TwoDimensionalEntity
### TwoDimensionalEntity `INTERFACE`
2D移动对象接口定义
```go
type TwoDimensionalEntity[EID generic.Basic, PosType generic.SignedNumber] struct{}
type TwoDimensionalEntity[EID generic.Basic, PosType generic.SignedNumber] interface {
GetTwoDimensionalEntityID() EID
GetSpeed() float64
GetPosition() geometry.Point[PosType]
SetPosition(geometry.Point[PosType])
}
```
### Position2DChangeEventHandle
### Position2DChangeEventHandle `STRUCT`
```go
type Position2DChangeEventHandle[EID generic.Basic, PosType generic.SignedNumber] struct{}
type Position2DChangeEventHandle[EID generic.Basic, PosType generic.SignedNumber] func(moving *TwoDimensional[EID, PosType], entity TwoDimensionalEntity[EID, PosType], oldX PosType)
```
### TwoDimensionalOption
### TwoDimensionalOption `STRUCT`
```go
type TwoDimensionalOption[EID generic.Basic, PosType generic.SignedNumber] struct{}
type TwoDimensionalOption[EID generic.Basic, PosType generic.SignedNumber] func(moving *TwoDimensional[EID, PosType])
```

View File

@ -1,32 +1,28 @@
# Network
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/network)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[IP](#IP)|返回本机出站地址
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func IP() (ip net.IP, err error)
<span id="IP"></span>
> 返回本机出站地址
***

View File

@ -1,19 +1,20 @@
# Offset
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/offset)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewTime](#NewTime)|新建一个包含偏移的时间
|[SetGlobal](#SetGlobal)|设置全局偏移时间
@ -22,36 +23,43 @@
|[Since](#Since)|获取当前时间偏移后的时间自从 t 以来经过的时间
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Time](#time)|带有偏移量的时间
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Time](#time)|带有偏移量的时间
</details>
***
## 详情信息
#### func NewTime(offset time.Duration) *Time
<span id="NewTime"></span>
> 新建一个包含偏移的时间
***
#### func SetGlobal(offset time.Duration)
<span id="SetGlobal"></span>
> 设置全局偏移时间
***
#### func GetGlobal() *Time
<span id="GetGlobal"></span>
> 获取全局偏移时间
***
#### func Now() time.Time
<span id="Now"></span>
> 获取当前时间偏移后的时间
***
#### func Since(t time.Time) time.Duration
<span id="Since"></span>
> 获取当前时间偏移后的时间自从 t 以来经过的时间
***
### Time
### Time `STRUCT`
带有偏移量的时间
```go
type Time struct {

View File

@ -1,19 +1,20 @@
# Random
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/random)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Dice](#Dice)|掷骰子
|[DiceN](#DiceN)|掷骰子
@ -45,129 +46,173 @@
|[WeightMapKey](#WeightMapKey)|按权重随机从map中产生一个数据并返回数据和对应 key
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func Dice() int
<span id="Dice"></span>
> 掷骰子
> - 常规掷骰子将返回 1-6 的随机数
***
#### func DiceN(n int) int
<span id="DiceN"></span>
> 掷骰子
> - 与 Dice 不同的是,将返回 1-N 的随机数
***
#### func NetIP() net.IP
<span id="NetIP"></span>
> 返回一个随机的IP地址
***
#### func Port() int
<span id="Port"></span>
> 返回一个随机的端口号
***
#### func IPv4() string
<span id="IPv4"></span>
> 返回一个随机产生的IPv4地址。
***
#### func IPv4Port() string
<span id="IPv4Port"></span>
> 返回一个随机产生的IPv4地址和端口。
***
#### func Int64(min int64, max int64) int64
<span id="Int64"></span>
> 返回一个介于min和max之间的int64类型的随机数。
***
#### func Int(min int, max int) int
<span id="Int"></span>
> 返回一个介于min和max之间的的int类型的随机数。
***
#### func Duration(min int64, max int64) time.Duration
<span id="Duration"></span>
> 返回一个介于min和max之间的的Duration类型的随机数。
***
#### func Float64() float64
<span id="Float64"></span>
> 返回一个0~1的浮点数
***
#### func Float32() float32
<span id="Float32"></span>
> 返回一个0~1的浮点数
***
#### func IntN(n int) int
<span id="IntN"></span>
> 返回一个0~n的整数
***
#### func Bool() bool
<span id="Bool"></span>
> 返回一个随机的布尔值
***
#### func ProbabilitySlice(getProbabilityHandle func (data T) float64, data ...T) (hit T, miss bool)
<span id="ProbabilitySlice"></span>
> 按概率随机从切片中产生一个数据并返回命中的对象及是否未命中
> - 当总概率小于 1 将会发生未命中的情况
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestProbabilitySlice(t *testing.T) {
var awards = []int{1, 2, 3, 4, 5, 6, 7}
var probability = []float64{0.1, 2, 0.1, 0.1, 0.1, 0.1, 0.1}
for i := 0; i < 50; i++ {
t.Log(random.ProbabilitySlice(func(data int) float64 {
return probability[data-1]
}, awards...))
}
}
```
</details>
***
#### func ProbabilitySliceIndex(getProbabilityHandle func (data T) float64, data ...T) (hit T, index int, miss bool)
<span id="ProbabilitySliceIndex"></span>
> 按概率随机从切片中产生一个数据并返回命中的对象及对象索引以及是否未命中
> - 当总概率小于 1 将会发生未命中的情况
***
#### func Probability(p int, full ...int) bool
<span id="Probability"></span>
> 输入一个概率,返回是否命中
> - 当 full 不为空时,将以 full 为基数p 为分子,计算命中概率
***
#### func ProbabilityChooseOne(ps ...int) int
<span id="ProbabilityChooseOne"></span>
> 输入一组概率,返回命中的索引
***
#### func RefreshSeed(seed ...int64)
<span id="RefreshSeed"></span>
***
#### func ChineseName() string
<span id="ChineseName"></span>
> 返回一个随机组成的中文姓名。
***
#### func EnglishName() string
<span id="EnglishName"></span>
> 返回一个随机组成的英文姓名。
***
#### func Name() string
<span id="Name"></span>
> 返回一个随机组成的中文或英文姓名
> - 以1/2的概率决定生产的是中文还是英文姓名。
***
#### func NumberString(min int, max int) string
<span id="NumberString"></span>
> 返回一个介于min和max之间的string类型的随机数。
***
#### func NumberStringRepair(min int, max int) string
<span id="NumberStringRepair"></span>
> 返回一个介于min和max之间的string类型的随机数
> - 通过Int64生成一个随机数当结果的字符串长度小于max的字符串长度的情况下使用0在开头补齐。
***
#### func HostName() string
<span id="HostName"></span>
> 返回一个随机产生的hostname。
***
#### func WeightSlice(getWeightHandle func (data T) int64, data ...T) T
<span id="WeightSlice"></span>
> 按权重随机从切片中产生一个数据并返回
***
#### func WeightSliceIndex(getWeightHandle func (data T) int64, data ...T) (item T, index int)
<span id="WeightSliceIndex"></span>
> 按权重随机从切片中产生一个数据并返回数据和对应索引
***
#### func WeightMap(getWeightHandle func (data T) int64, data map[K]T) T
<span id="WeightMap"></span>
> 按权重随机从map中产生一个数据并返回
***
#### func WeightMapKey(getWeightHandle func (data T) int64, data map[K]T) (item T, key K)
<span id="WeightMapKey"></span>
> 按权重随机从map中产生一个数据并返回数据和对应 key
***

View File

@ -1,19 +1,20 @@
# Reflects
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/reflects)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[WrapperFunc](#WrapperFunc)|包装函数
|[WrapperFuncBefore2After](#WrapperFuncBefore2After)|包装函数,前置函数执行前,后置函数执行后
@ -25,43 +26,45 @@
|[GetPointer](#GetPointer)|获取指针
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func WrapperFunc(f any, wrapper func (call func ( []reflect.Value) []reflect.Value) func (args []reflect.Value) []reflect.Value) (wf Func, err error)
<span id="WrapperFunc"></span>
> 包装函数
***
#### func WrapperFuncBefore2After(f Func, before func (), after func ()) (wf Func, err error)
<span id="WrapperFuncBefore2After"></span>
> 包装函数,前置函数执行前,后置函数执行后
***
#### func WrapperFuncBefore(f Func, before func ()) (wf Func, err error)
<span id="WrapperFuncBefore"></span>
> 包装函数,前置函数执行前
***
#### func WrapperFuncAfter(f Func, after func ()) (wf Func, err error)
<span id="WrapperFuncAfter"></span>
> 包装函数,后置函数执行后
***
#### func GetPtrUnExportFiled(s reflect.Value, filedIndex int) reflect.Value
<span id="GetPtrUnExportFiled"></span>
> 获取指针类型的未导出字段
***
#### func SetPtrUnExportFiled(s reflect.Value, filedIndex int, val reflect.Value)
<span id="SetPtrUnExportFiled"></span>
> 设置指针类型的未导出字段
***
#### func Copy(s reflect.Value) reflect.Value
<span id="Copy"></span>
> 拷贝
***
#### func GetPointer(src T) reflect.Value
<span id="GetPointer"></span>
> 获取指针
***

View File

@ -1,19 +1,20 @@
# Runtimes
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/runtimes)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[GetWorkingDir](#GetWorkingDir)|获取工作目录绝对路径
|[GetTempDir](#GetTempDir)|获取系统临时目录
@ -22,31 +23,30 @@
|[CurrentRunningFuncName](#CurrentRunningFuncName)|获取正在运行的函数名
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func GetWorkingDir() string
<span id="GetWorkingDir"></span>
> 获取工作目录绝对路径
***
#### func GetTempDir() string
<span id="GetTempDir"></span>
> 获取系统临时目录
***
#### func GetExecutablePathByBuild() string
<span id="GetExecutablePathByBuild"></span>
> 获取当前执行文件绝对路径go build
***
#### func GetExecutablePathByCaller() string
<span id="GetExecutablePathByCaller"></span>
> 获取当前执行文件绝对路径go run
***
#### func CurrentRunningFuncName(skip ...int) string
<span id="CurrentRunningFuncName"></span>
> 获取正在运行的函数名
***

View File

@ -1,19 +1,20 @@
# Sole
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/sole)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[RegNameSpace](#RegNameSpace)|注册特定命名空间的唯一标识符
|[UnRegNameSpace](#UnRegNameSpace)|解除注销特定命名空间的唯一标识符
@ -33,80 +34,98 @@
|[AutoIncrementString](#AutoIncrementString)|获取一个自增的字符串
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[Once](#once)|用于数据取值去重的结构体
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[Once](#once)|用于数据取值去重的结构体
</details>
***
## 详情信息
#### func RegNameSpace(name any)
<span id="RegNameSpace"></span>
> 注册特定命名空间的唯一标识符
***
#### func UnRegNameSpace(name any)
<span id="UnRegNameSpace"></span>
> 解除注销特定命名空间的唯一标识符
***
#### func Get() int64
<span id="Get"></span>
> 获取全局唯一标识符
***
#### func Reset()
<span id="Reset"></span>
> 重置全局唯一标识符
***
#### func GetWith(name any) int64
<span id="GetWith"></span>
> 获取特定命名空间的唯一标识符
***
#### func ResetWith(name any)
<span id="ResetWith"></span>
> 重置特定命名空间的唯一标识符
***
#### func NewOnce() *Once[V]
<span id="NewOnce"></span>
> 创建一个用于数据取值去重的结构实例
***
#### func SonyflakeIDE() int64, error
<span id="SonyflakeIDE"></span>
> 获取一个雪花id
***
#### func SonyflakeID() int64
<span id="SonyflakeID"></span>
> 获取一个雪花id
***
#### func SonyflakeSetting(settings sonyflake.Settings)
<span id="SonyflakeSetting"></span>
> 配置雪花id生成策略
***
#### func AutoIncrementUint32() uint32
<span id="AutoIncrementUint32"></span>
> 获取一个自增的 uint32 值
***
#### func AutoIncrementUint64() uint64
<span id="AutoIncrementUint64"></span>
> 获取一个自增的 uint64 值
***
#### func AutoIncrementInt32() int32
<span id="AutoIncrementInt32"></span>
> 获取一个自增的 int32 值
***
#### func AutoIncrementInt64() int64
<span id="AutoIncrementInt64"></span>
> 获取一个自增的 int64 值
***
#### func AutoIncrementInt() int
<span id="AutoIncrementInt"></span>
> 获取一个自增的 int 值
***
#### func AutoIncrementString() string
<span id="AutoIncrementString"></span>
> 获取一个自增的字符串
***
### Once
### Once `STRUCT`
用于数据取值去重的结构体
```go
type Once[V any] struct {

View File

@ -1,31 +1,26 @@
# Sorts
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/sorts)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[Topological](#Topological)|拓扑排序是一种对有向图进行排序的算法,它可以用来解决一些依赖关系的问题,比如计算字段的依赖关系。拓扑排序会将存在依赖关系的元素进行排序,使得依赖关系的元素总是排在被依赖的元素之前。
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func Topological(slice S, queryIndexHandler func (item V) Index, queryDependsHandler func (item V) []Index) S, error
<span id="Topological"></span>
> 拓扑排序是一种对有向图进行排序的算法,它可以用来解决一些依赖关系的问题,比如计算字段的依赖关系。拓扑排序会将存在依赖关系的元素进行排序,使得依赖关系的元素总是排在被依赖的元素之前。
@ -34,4 +29,93 @@
> - queryDependsHandler: 用于查询切片中每个元素的依赖关系,返回的是一个索引切片,如果没有依赖关系,那么返回空切片
>
> 该函数在存在循环依赖的情况下将会返回 ErrCircularDependencyDetected 错误
示例代码:
```go
func ExampleTopological() {
type Item struct {
ID int
Depends []int
}
var items = []Item{{ID: 2, Depends: []int{4}}, {ID: 1, Depends: []int{2, 3}}, {ID: 3, Depends: []int{4}}, {ID: 4, Depends: []int{5}}, {ID: 5, Depends: []int{}}}
var sorted, err = sorts.Topological(items, func(item Item) int {
return item.ID
}, func(item Item) []int {
return item.Depends
})
if err != nil {
return
}
for _, item := range sorted {
fmt.Println(item.ID, "|", item.Depends)
}
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestTopological(t *testing.T) {
type Item struct {
ID int
Depends []int
}
var items = []Item{{ID: 2, Depends: []int{4}}, {ID: 1, Depends: []int{2, 3}}, {ID: 3, Depends: []int{4}}, {ID: 4, Depends: []int{5}}, {ID: 5, Depends: []int{}}}
var sorted, err = sorts.Topological(items, func(item Item) int {
return item.ID
}, func(item Item) []int {
return item.Depends
})
if err != nil {
t.Error(err)
return
}
for _, item := range sorted {
t.Log(item.ID, "|", item.Depends)
}
}
```
</details>
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkTopological(b *testing.B) {
type Item struct {
ID int
Depends []int
}
var items = []Item{{ID: 2, Depends: []int{4}}, {ID: 1, Depends: []int{2, 3}}, {ID: 3, Depends: []int{4}}, {ID: 4, Depends: []int{5}}, {ID: 5, Depends: []int{}}}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, err := Topological(items, func(item Item) int {
return item.ID
}, func(item Item) []int {
return item.Depends
})
if err != nil {
b.Error(err)
return
}
}
}
```
</details>
***

View File

@ -1,19 +1,20 @@
# Str
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/str)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[RangeLine](#RangeLine)|对传入的eachString进行按行切片后再进行遍历
|[SplitTrimSpace](#SplitTrimSpace)|按照空格分割字符串并去除空格
@ -39,91 +40,103 @@
|[FormatSpeedyFloat64](#FormatSpeedyFloat64)|返回numberStr经过格式化后去除空格和“,”分隔符的结果
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func RangeLine(eachString string, eachFunc func (index int, line string) error) error
<span id="RangeLine"></span>
> 对传入的eachString进行按行切片后再进行遍历
> - 该函数会预先对“\r\n”进行处理替换为“\n”。
> - 在遍历到每一行的时候会将结果index和line作为入参传入eachFunc中进行调用。
> - index表示了当前行的行号由0开始line表示了当前行的内容。
***
#### func SplitTrimSpace(str string, sep string) []string
<span id="SplitTrimSpace"></span>
> 按照空格分割字符串并去除空格
***
#### func FirstUpper(str string) string
<span id="FirstUpper"></span>
> 首字母大写
***
#### func FirstLower(str string) string
<span id="FirstLower"></span>
> 首字母小写
***
#### func FirstUpperBytes(str []byte) []byte
<span id="FirstUpperBytes"></span>
> 首字母大写
***
#### func FirstLowerBytes(str []byte) []byte
<span id="FirstLowerBytes"></span>
> 首字母小写
***
#### func IsEmpty(str string) bool
<span id="IsEmpty"></span>
> 判断字符串是否为空
***
#### func IsEmptyBytes(str []byte) bool
<span id="IsEmptyBytes"></span>
> 判断字符串是否为空
***
#### func IsNotEmpty(str string) bool
<span id="IsNotEmpty"></span>
> 判断字符串是否不为空
***
#### func IsNotEmptyBytes(str []byte) bool
<span id="IsNotEmptyBytes"></span>
> 判断字符串是否不为空
***
#### func SnakeString(str string) string
<span id="SnakeString"></span>
> 蛇形字符串
***
#### func SnakeStringBytes(str []byte) []byte
<span id="SnakeStringBytes"></span>
> 蛇形字符串
***
#### func CamelString(str string) string
<span id="CamelString"></span>
> 驼峰字符串
***
#### func CamelStringBytes(str []byte) []byte
<span id="CamelStringBytes"></span>
> 驼峰字符串
***
#### func SortJoin(delimiter string, s ...string) string
<span id="SortJoin"></span>
> 将多个字符串排序后拼接
***
#### func HideSensitivity(str string) (result string)
<span id="HideSensitivity"></span>
> 返回防敏感化后的字符串
> - 隐藏身份证、邮箱、手机号等敏感信息用*号替代
***
#### func ThousandsSeparator(str string) string
<span id="ThousandsSeparator"></span>
> 返回将str进行千位分隔符处理后的字符串。
***
#### func KV(str string, tag ...string) string, string
<span id="KV"></span>
> 返回str经过转换后形成的key、value
> - 这里tag表示使用什么字符串来区分key和value的分隔符。
> - 默认情况即不传入tag的情况下分隔符为“=”。
***
#### func FormatSpeedyInt(numberStr string) int, error
<span id="FormatSpeedyInt"></span>
@ -131,6 +144,7 @@
> - 当字符串为“123,456,789”的时候返回结果为“123456789”。
> - 当字符串为“123 456 789”的时候返回结果为“123456789”。
> - 当字符串为“1 23, 45 6, 789”的时候返回结果为“123456789”。
***
#### func FormatSpeedyInt64(numberStr string) int64, error
<span id="FormatSpeedyInt64"></span>
@ -138,6 +152,7 @@
> - 当字符串为“123,456,789”的时候返回结果为“123456789”。
> - 当字符串为“123 456 789”的时候返回结果为“123456789”。
> - 当字符串为“1 23, 45 6, 789”的时候返回结果为“123456789”。
***
#### func FormatSpeedyFloat32(numberStr string) float64, error
<span id="FormatSpeedyFloat32"></span>
@ -145,6 +160,7 @@
> - 当字符串为“123,456,789.123”的时候返回结果为“123456789.123”。
> - 当字符串为“123 456 789.123”的时候返回结果为“123456789.123”。
> - 当字符串为“1 23, 45 6, 789.123”的时候返回结果为“123456789.123”。
***
#### func FormatSpeedyFloat64(numberStr string) float64, error
<span id="FormatSpeedyFloat64"></span>
@ -152,4 +168,5 @@
> - 当字符串为“123,456,789.123”的时候返回结果为“123456789.123”。
> - 当字符串为“123 456 789.123”的时候返回结果为“123456789.123”。
> - 当字符串为“1 23, 45 6, 789.123”的时候返回结果为“123456789.123”。
***

View File

@ -1,19 +1,20 @@
# Super
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/super)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[NewBitSet](#NewBitSet)|通过指定的 Bit 位创建一个 BitSet
|[TryWriteChannel](#TryWriteChannel)|尝试写入 channel如果 channel 无法写入则忽略,返回是否写入成功
@ -87,249 +88,417 @@
|[CompareVersion](#CompareVersion)|返回一个整数,用于表示两个版本号的比较结果:
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[BitSet](#bitset)|是一个可以动态增长的比特位集合
|[LossCounter](#losscounter)|暂无描述...
|[Matcher](#matcher)|匹配器
|[Permission](#permission)|暂无描述...
|[StackGo](#stackgo)|用于获取上一个协程调用的堆栈信息
|[VerifyHandle](#verifyhandle)|校验句柄
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[BitSet](#bitset)|是一个可以动态增长的比特位集合
|`STRUCT`|[LossCounter](#losscounter)|暂无描述...
|`STRUCT`|[Matcher](#matcher)|匹配器
|`STRUCT`|[Permission](#permission)|暂无描述...
|`STRUCT`|[StackGo](#stackgo)|用于获取上一个协程调用的堆栈信息
|`STRUCT`|[VerifyHandle](#verifyhandle)|校验句柄
</details>
***
## 详情信息
#### func NewBitSet(bits ...Bit) *BitSet[Bit]
<span id="NewBitSet"></span>
> 通过指定的 Bit 位创建一个 BitSet
***
#### func TryWriteChannel(ch chan T, data T) bool
<span id="TryWriteChannel"></span>
> 尝试写入 channel如果 channel 无法写入则忽略,返回是否写入成功
> - 无法写入的情况包括channel 已满、channel 已关闭
***
#### func TryWriteChannelByHandler(ch chan T, data T, handler func ())
<span id="TryWriteChannelByHandler"></span>
> 尝试写入 channel如果 channel 无法写入则执行 handler
> - 无法写入的情况包括channel 已满、channel 已关闭
***
#### func RegError(code int, message string) error
<span id="RegError"></span>
> 通过错误码注册错误,返回错误的引用
***
#### func RegErrorRef(code int, message string, ref error) error
<span id="RegErrorRef"></span>
> 通过错误码注册错误,返回错误的引用
> - 引用将会被重定向到注册的错误信息
***
#### func GetError(err error) int, error
<span id="GetError"></span>
> 通过错误引用获取错误码和真实错误信息,如果错误不存在则返回 0如果错误引用不存在则返回原本的错误
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestGetError(t *testing.T) {
var ErrNotFound = errors.New("not found")
var _ = super.RegErrorRef(100, "test error", ErrNotFound)
t.Log(super.GetError(ErrNotFound))
}
```
</details>
***
#### func RecoverTransform(a any) error
<span id="RecoverTransform"></span>
> recover 错误转换
示例代码:
```go
func ExampleRecoverTransform() {
defer func() {
if err := super.RecoverTransform(recover()); err != nil {
fmt.Println(err)
}
}()
panic("test")
}
```
***
#### func Handle(f func ())
<span id="Handle"></span>
> 执行 f 函数,如果 f 为 nil则不执行
***
#### func HandleErr(f func () error) error
<span id="HandleErr"></span>
> 执行 f 函数,如果 f 为 nil则不执行
***
#### func HandleV(v V, f func (v V))
<span id="HandleV"></span>
> 执行 f 函数,如果 f 为 nil则不执行
***
#### func GoFormat(filePath string)
<span id="GoFormat"></span>
> go 代码格式化
***
#### func If(expression bool, t T, f T) T
<span id="If"></span>
***
#### func MarshalJSON(v interface {}) []byte
<span id="MarshalJSON"></span>
> 将对象转换为 json
> - 当转换失败时,将返回 json 格式的空对象
***
#### func MarshalJSONE(v interface {}) []byte, error
<span id="MarshalJSONE"></span>
> 将对象转换为 json
> - 当转换失败时,将返回错误信息
***
#### func UnmarshalJSON(data []byte, v interface {}) error
<span id="UnmarshalJSON"></span>
> 将 json 转换为对象
***
#### func MarshalIndentJSON(v interface {}, prefix string, indent string) []byte
<span id="MarshalIndentJSON"></span>
> 将对象转换为 json
***
#### func MarshalToTargetWithJSON(src interface {}, dest interface {}) error
<span id="MarshalToTargetWithJSON"></span>
> 将对象转换为目标对象
***
#### func StartLossCounter() *LossCounter
<span id="StartLossCounter"></span>
> 开始损耗计数
***
#### func Match(value Value) *Matcher[Value, Result]
<span id="Match"></span>
> 匹配
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestMatch(t *testing.T) {
Convey("TestMatch", t, func() {
So(super.Match[int, string](1).Case(1, "a").Case(2, "b").Default("c"), ShouldEqual, "a")
So(super.Match[int, string](2).Case(1, "a").Case(2, "b").Default("c"), ShouldEqual, "b")
So(super.Match[int, string](3).Case(1, "a").Case(2, "b").Default("c"), ShouldEqual, "c")
})
}
```
</details>
***
#### func IsNumber(v any) bool
<span id="IsNumber"></span>
> 判断是否为数字
***
#### func NumberToRome(num int) string
<span id="NumberToRome"></span>
> 将数字转换为罗马数字
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNumberToRome(t *testing.T) {
tests := []struct {
input int
output string
}{{input: 1, output: "I"}, {input: 5, output: "V"}, {input: 10, output: "X"}, {input: 50, output: "L"}, {input: 100, output: "C"}, {input: 500, output: "D"}, {input: 1000, output: "M"}}
for _, test := range tests {
result := super.NumberToRome(test.input)
if result != test.output {
t.Errorf("NumberToRome(%d) = %s; want %s", test.input, result, test.output)
}
}
}
```
</details>
***
#### func StringToInt(value string) int
<span id="StringToInt"></span>
> 字符串转换为整数
***
#### func StringToFloat64(value string) float64
<span id="StringToFloat64"></span>
> 字符串转换为 float64
***
#### func StringToBool(value string) bool
<span id="StringToBool"></span>
> 字符串转换为 bool
***
#### func StringToUint64(value string) uint64
<span id="StringToUint64"></span>
> 字符串转换为 uint64
***
#### func StringToUint(value string) uint
<span id="StringToUint"></span>
> 字符串转换为 uint
***
#### func StringToFloat32(value string) float32
<span id="StringToFloat32"></span>
> 字符串转换为 float32
***
#### func StringToInt64(value string) int64
<span id="StringToInt64"></span>
> 字符串转换为 int64
***
#### func StringToUint32(value string) uint32
<span id="StringToUint32"></span>
> 字符串转换为 uint32
***
#### func StringToInt32(value string) int32
<span id="StringToInt32"></span>
> 字符串转换为 int32
***
#### func StringToUint16(value string) uint16
<span id="StringToUint16"></span>
> 字符串转换为 uint16
***
#### func StringToInt16(value string) int16
<span id="StringToInt16"></span>
> 字符串转换为 int16
***
#### func StringToUint8(value string) uint8
<span id="StringToUint8"></span>
> 字符串转换为 uint8
***
#### func StringToInt8(value string) int8
<span id="StringToInt8"></span>
> 字符串转换为 int8
***
#### func StringToByte(value string) byte
<span id="StringToByte"></span>
> 字符串转换为 byte
***
#### func StringToRune(value string) rune
<span id="StringToRune"></span>
> 字符串转换为 rune
***
#### func IntToString(value int) string
<span id="IntToString"></span>
> 整数转换为字符串
***
#### func Float64ToString(value float64) string
<span id="Float64ToString"></span>
> float64 转换为字符串
***
#### func BoolToString(value bool) string
<span id="BoolToString"></span>
> bool 转换为字符串
***
#### func Uint64ToString(value uint64) string
<span id="Uint64ToString"></span>
> uint64 转换为字符串
***
#### func UintToString(value uint) string
<span id="UintToString"></span>
> uint 转换为字符串
***
#### func Float32ToString(value float32) string
<span id="Float32ToString"></span>
> float32 转换为字符串
***
#### func Int64ToString(value int64) string
<span id="Int64ToString"></span>
> int64 转换为字符串
***
#### func Uint32ToString(value uint32) string
<span id="Uint32ToString"></span>
> uint32 转换为字符串
***
#### func Int32ToString(value int32) string
<span id="Int32ToString"></span>
> int32 转换为字符串
***
#### func Uint16ToString(value uint16) string
<span id="Uint16ToString"></span>
> uint16 转换为字符串
***
#### func Int16ToString(value int16) string
<span id="Int16ToString"></span>
> int16 转换为字符串
***
#### func Uint8ToString(value uint8) string
<span id="Uint8ToString"></span>
> uint8 转换为字符串
***
#### func Int8ToString(value int8) string
<span id="Int8ToString"></span>
> int8 转换为字符串
***
#### func ByteToString(value byte) string
<span id="ByteToString"></span>
> byte 转换为字符串
***
#### func RuneToString(value rune) string
<span id="RuneToString"></span>
> rune 转换为字符串
***
#### func StringToSlice(value string) []string
<span id="StringToSlice"></span>
> 字符串转换为切片
***
#### func SliceToString(value []string) string
<span id="SliceToString"></span>
> 切片转换为字符串
***
#### func NewPermission() *Permission[Code, EntityID]
<span id="NewPermission"></span>
> 创建权限
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewPermission(t *testing.T) {
const (
Read = 1 << iota
Write
Execute
)
p := super.NewPermission[int, int]()
p.AddPermission(1, Read, Write)
t.Log(p.HasPermission(1, Read))
t.Log(p.HasPermission(1, Write))
p.SetPermission(2, Read|Write)
t.Log(p.HasPermission(2, Read))
t.Log(p.HasPermission(2, Execute))
p.SetPermission(2, Execute)
t.Log(p.HasPermission(2, Execute))
t.Log(p.HasPermission(2, Read))
t.Log(p.HasPermission(2, Write))
p.RemovePermission(2, Execute)
t.Log(p.HasPermission(2, Execute))
}
```
</details>
***
#### func Retry(count int, interval time.Duration, f func () error) error
<span id="Retry"></span>
> 根据提供的 count 次数尝试执行 f 函数,如果 f 函数返回错误,则在 interval 后重试,直到成功或者达到 count 次数
***
#### func RetryByRule(f func () error, rule func (count int) time.Duration) error
<span id="RetryByRule"></span>
> 根据提供的规则尝试执行 f 函数,如果 f 函数返回错误,则根据 rule 的返回值进行重试
> - rule 将包含一个入参,表示第几次重试,返回值表示下一次重试的时间间隔,当返回值为 0 时,表示不再重试
> - rule 的 count 将在 f 首次失败后变为 1因此 rule 的入参将从 1 开始
***
#### func RetryByExponentialBackoff(f func () error, maxRetries int, baseDelay time.Duration, maxDelay time.Duration, multiplier float64, randomization float64, ignoreErrors ...error) error
<span id="RetryByExponentialBackoff"></span>
@ -340,6 +509,7 @@
> - multiplier延迟时间的乘数通常为 2
> - randomization延迟时间的随机化因子通常为 0.5
> - ignoreErrors忽略的错误当 f 返回的错误在 ignoreErrors 中时,将不会进行重试
***
#### func ConditionalRetryByExponentialBackoff(f func () error, cond func () bool, maxRetries int, baseDelay time.Duration, maxDelay time.Duration, multiplier float64, randomization float64, ignoreErrors ...error) error
<span id="ConditionalRetryByExponentialBackoff"></span>
@ -348,54 +518,164 @@
>
> 该函数通常用于在重试过程中,需要中断重试的场景,例如:
> - 用户请求开始游戏,由于网络等情况,进入重试状态。此时用户再次发送开始游戏请求,此时需要中断之前的重试,避免重复进入游戏
***
#### func RetryAsync(count int, interval time.Duration, f func () error, callback func (err error))
<span id="RetryAsync"></span>
> 与 Retry 类似,但是是异步执行
> - 传入的 callback 函数会在执行完毕后被调用,如果执行成功,则 err 为 nil否则为错误信息
> - 如果 callback 为 nil则不会在执行完毕后被调用
***
#### func RetryForever(interval time.Duration, f func () error)
<span id="RetryForever"></span>
> 根据提供的 interval 时间间隔尝试执行 f 函数,如果 f 函数返回错误,则在 interval 后重试,直到成功
***
#### func NewStackGo() *StackGo
<span id="NewStackGo"></span>
> 返回一个用于获取上一个协程调用的堆栈信息的收集器
***
#### func LaunchTime() time.Time
<span id="LaunchTime"></span>
> 获取程序启动时间
***
#### func Hostname() string
<span id="Hostname"></span>
> 获取主机名
***
#### func PID() int
<span id="PID"></span>
> 获取进程 PID
***
#### func StringToBytes(s string) []byte
<span id="StringToBytes"></span>
> 以零拷贝的方式将字符串转换为字节切片
***
#### func BytesToString(b []byte) string
<span id="BytesToString"></span>
> 以零拷贝的方式将字节切片转换为字符串
***
#### func Convert(src A) B
<span id="Convert"></span>
> 以零拷贝的方式将一个对象转换为另一个对象
> - 两个对象字段必须完全一致
> - 该函数可以绕过私有字段的访问限制
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestConvert(t *testing.T) {
type B struct {
nocmp [0]func()
v atomic.Value
}
var a = atomic.NewString("hello")
var b = super.Convert[*atomic.String, *B](a)
fmt.Println(b.v.Load())
}
```
</details>
***
#### func Verify(handle func ( V)) *VerifyHandle[V]
<span id="Verify"></span>
> 对特定表达式进行校验,当表达式不成立时,将执行 handle
示例代码:
```go
func ExampleVerify() {
var getId = func() int {
return 1
}
var n *super.VerifyHandle[int]
super.Verify(func(err error) {
fmt.Println(err)
}).Case(getId() == 1, errors.New("id can't be 1")).Do()
super.Verify(func(err error) {
fmt.Println(err)
}).PreCase(func() bool {
return n == nil
}, errors.New("n can't be nil"), func(verify *super.VerifyHandle[error]) bool {
return verify.Do()
})
}
```
***
#### func OldVersion(version1 string, version2 string) bool
<span id="OldVersion"></span>
> 检查 version2 对于 version1 来说是不是旧版本
示例代码:
```go
func ExampleOldVersion() {
result := super.OldVersion("1.2.3", "1.2.2")
fmt.Println(result)
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestOldVersion(t *testing.T) {
testCases := []struct {
version1 string
version2 string
want bool
}{{"1.2.3", "1.2.2", true}, {"1.2.1", "1.2.2", false}, {"1.2.3", "1.2.3", false}, {"v1.2.3", "v1.2.2", true}, {"v1.2.3", "v1.2.4", false}, {"v1.2.3", "1.2.3", false}, {"vxx2faf.d2ad5.dd3", "gga2faf.d2ad5.dd2", true}, {"awd2faf.d2ad4.dd3", "vsd2faf.d2ad5.dd3", false}, {"vxd2faf.d2ad5.dd3", "qdq2faf.d2ad5.dd3", false}, {"1.2.3", "vdafe2faf.d2ad5.dd3", false}, {"v1.2.3", "vdafe2faf.d2ad5.dd3", false}}
for _, tc := range testCases {
got := super.OldVersion(tc.version1, tc.version2)
if got != tc.want {
t.Errorf("OldVersion(%q, %q) = %v; want %v", tc.version1, tc.version2, got, tc.want)
}
}
}
```
</details>
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkOldVersion(b *testing.B) {
for i := 0; i < b.N; i++ {
super.OldVersion("vfe2faf.d2ad5.dd3", "vda2faf.d2ad5.dd2")
}
}
```
</details>
***
#### func CompareVersion(version1 string, version2 string) int
<span id="CompareVersion"></span>
@ -403,8 +683,63 @@
> - 如果 version1 大于 version2它将返回 1
> - 如果 version1 小于 version2它将返回 -1
> - 如果 version1 和 version2 相等,它将返回 0
示例代码:
```go
func ExampleCompareVersion() {
result := super.CompareVersion("1.2.3", "1.2.2")
fmt.Println(result)
}
```
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestCompareVersion(t *testing.T) {
testCases := []struct {
version1 string
version2 string
want int
}{{"1.2.3", "1.2.2", 1}, {"1.2.1", "1.2.2", -1}, {"1.2.3", "1.2.3", 0}, {"v1.2.3", "v1.2.2", 1}, {"v1.2.3", "v1.2.4", -1}, {"v1.2.3", "1.2.3", 0}, {"vde2faf.d2ad5.dd3", "e2faf.d2ad5.dd2", 1}, {"vde2faf.d2ad4.dd3", "vde2faf.d2ad5.dd3", -1}, {"vfe2faf.d2ad5.dd3", "ve2faf.d2ad5.dd3", 0}, {"1.2.3", "vdafe2faf.d2ad5.dd3", -1}, {"v1.2.3", "vdafe2faf.d2ad5.dd3", -1}}
for _, tc := range testCases {
got := super.CompareVersion(tc.version1, tc.version2)
if got != tc.want {
t.Errorf("CompareVersion(%q, %q) = %v; want %v", tc.version1, tc.version2, got, tc.want)
}
}
}
```
</details>
<details>
<summary>查看 / 收起基准测试</summary>
```go
func BenchmarkCompareVersion(b *testing.B) {
for i := 0; i < b.N; i++ {
super.CompareVersion("vfe2faf.d2ad5.dd3", "afe2faf.d2ad5.dd2")
}
}
```
</details>
***
### BitSet
### BitSet `STRUCT`
是一个可以动态增长的比特位集合
- 默认情况下将使用 64 位无符号整数来表示比特位,当需要表示的比特位超过 64 位时,将自动增长
```go
@ -414,13 +749,76 @@ type BitSet[Bit generic.Integer] struct {
```
#### func (*BitSet) Set(bit Bit) *BitSet[Bit]
> 将指定的位 bit 设置为 1
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestBitSet_Set(t *testing.T) {
bs := super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
bs.Set(11)
bs.Set(12)
bs.Set(13)
t.Log(bs)
}
```
</details>
***
#### func (*BitSet) Del(bit Bit) *BitSet[Bit]
> 将指定的位 bit 设置为 0
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestBitSet_Del(t *testing.T) {
bs := super.NewBitSet(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
bs.Del(11)
bs.Del(12)
bs.Del(13)
bs.Del(10)
t.Log(bs)
}
```
</details>
***
#### func (*BitSet) Shrink() *BitSet[Bit]
> 将 BitSet 中的比特位集合缩小到最小
> - 正常情况下当 BitSet 中的比特位超出 64 位时,将自动增长,当 BitSet 中的比特位数量减少时,可以使用该方法将 BitSet 中的比特位集合缩小到最小
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestBitSet_Shrink(t *testing.T) {
bs := super.NewBitSet(63)
t.Log(bs.Cap())
bs.Set(200)
t.Log(bs.Cap())
bs.Del(200)
bs.Shrink()
t.Log(bs.Cap())
}
```
</details>
***
#### func (*BitSet) Cap() int
> 返回当前 BitSet 中可以表示的最大比特位数量
@ -509,7 +907,7 @@ type BitSet[Bit generic.Integer] struct {
#### func (*BitSet) UnmarshalJSON(data []byte) error
> 实现 json.Unmarshaler 接口
***
### LossCounter
### LossCounter `STRUCT`
```go
type LossCounter struct {
@ -526,7 +924,7 @@ type LossCounter struct {
***
#### func (*LossCounter) String() string
***
### Matcher
### Matcher `STRUCT`
匹配器
```go
type Matcher[Value any, Result any] struct {
@ -535,7 +933,7 @@ type Matcher[Value any, Result any] struct {
d bool
}
```
### Permission
### Permission `STRUCT`
```go
type Permission[Code generic.Integer, EntityID comparable] struct {
@ -543,7 +941,7 @@ type Permission[Code generic.Integer, EntityID comparable] struct {
l sync.RWMutex
}
```
### StackGo
### StackGo `STRUCT`
用于获取上一个协程调用的堆栈信息
- 应当最先运行 Wait 函数,然后在其他协程中调用 Stack 函数或者 GiveUp 函数
- 适用于跨协程同步通讯,例如单线程的消息处理统计耗时打印堆栈信息
@ -567,7 +965,7 @@ type StackGo struct {
> - 在调用 Wait 函数后调用该函数,将会放弃收集消息堆栈并且释放资源
> - 在调用 GiveUp 函数后调用 Stack 函数,将会 panic
***
### VerifyHandle
### VerifyHandle `STRUCT`
校验句柄
```go
type VerifyHandle[V any] struct {

View File

@ -1,19 +1,20 @@
# Timer
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/timer)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[RegSystemNewDayEvent](#RegSystemNewDayEvent)|注册系统新的一天事件
|[OnSystemNewDayEvent](#OnSystemNewDayEvent)|系统新的一天事件
@ -26,71 +27,82 @@
|[GetTicker](#GetTicker)|获取标准池中的一个定时器
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[SystemNewDayEventHandle](#systemnewdayeventhandle)|暂无描述...
|[Option](#option)|暂无描述...
|[Pool](#pool)|定时器池
|[Scheduler](#scheduler)|调度器
|[Ticker](#ticker)|定时器
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[SystemNewDayEventHandle](#systemnewdayeventhandle)|暂无描述...
|`STRUCT`|[Option](#option)|暂无描述...
|`STRUCT`|[Pool](#pool)|定时器池
|`STRUCT`|[Scheduler](#scheduler)|调度器
|`STRUCT`|[Ticker](#ticker)|定时器
</details>
***
## 详情信息
#### func RegSystemNewDayEvent(ticker *Ticker, name string, trigger bool, handle SystemNewDayEventHandle)
<span id="RegSystemNewDayEvent"></span>
> 注册系统新的一天事件
> - 建议全局注册一个事件后再另行拓展
> - 将特定 name 的定时任务注册到 ticker 中,在系统时间到达每天的 00:00:00 时触发,如果 trigger 为 true则立即触发一次
***
#### func OnSystemNewDayEvent(name string)
<span id="OnSystemNewDayEvent"></span>
> 系统新的一天事件
***
#### func RegOffsetTimeNewDayEvent(ticker *Ticker, name string, offset *offset.Time, trigger bool, handle OffsetTimeNewDayEventHandle)
<span id="RegOffsetTimeNewDayEvent"></span>
> 注册偏移时间新的一天事件
> - 建议全局注册一个事件后再另行拓展
> - 与 RegSystemNewDayEvent 类似,但是触发时间为 offset 时间到达每天的 00:00:00
***
#### func OnOffsetTimeNewDayEvent(name string)
<span id="OnOffsetTimeNewDayEvent"></span>
> 偏移时间新的一天事件
***
#### func WithCaller(handle func (name string, caller func ())) Option
<span id="WithCaller"></span>
> 通过其他的 handle 执行 Caller
***
#### func WithMark(mark string) Option
<span id="WithMark"></span>
> 通过特定的标记创建定时器
***
#### func NewPool(tickerPoolSize int) *Pool
<span id="NewPool"></span>
> 创建一个定时器池,当 tickerPoolSize 小于等于 0 时,将会引发 panic可指定为 DefaultTickerPoolSize
***
#### func SetPoolSize(size int)
<span id="SetPoolSize"></span>
> 设置标准池定时器池大小
> - 默认值为 DefaultTickerPoolSize当定时器池中的定时器不足时会自动创建新的定时器当定时器释放时会将多余的定时器进行释放否则将放入定时器池中
***
#### func GetTicker(size int, options ...Option) *Ticker
<span id="GetTicker"></span>
> 获取标准池中的一个定时器
***
### SystemNewDayEventHandle
### SystemNewDayEventHandle `STRUCT`
```go
type SystemNewDayEventHandle struct{}
type SystemNewDayEventHandle func()
```
### Option
### Option `STRUCT`
```go
type Option struct{}
type Option func(ticker *Ticker)
```
### Pool
### Pool `STRUCT`
定时器池
```go
type Pool struct {
@ -111,7 +123,7 @@ type Pool struct {
> 释放定时器池的资源,释放后由其产生的 Ticker 在 Ticker.Release 后将不再回到池中,而是直接释放
> - 虽然定时器池已被释放,但是依旧可以产出 Ticker
***
### Scheduler
### Scheduler `STRUCT`
调度器
```go
type Scheduler struct {
@ -138,7 +150,7 @@ type Scheduler struct {
#### func (*Scheduler) Caller()
> 可由外部发起调用的执行函数
***
### Ticker
### Ticker `STRUCT`
定时器
```go
type Ticker struct {
@ -168,6 +180,32 @@ type Ticker struct {
***
#### func (*Ticker) Cron(name string, expression string, handleFunc interface {}, args ...interface {})
> 通过 cron 表达式设置一个调度器,当 cron 表达式错误时,将会引发 panic
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestTicker_Cron(t *testing.T) {
ticker := timer.GetTicker(10)
ticker.After("1_sec", time.Second, func() {
t.Log(time.Now().Format(time.DateTime), "1_sec")
})
ticker.Loop("1_sec_loop_3", 0, time.Second, 3, func() {
t.Log(time.Now().Format(time.DateTime), "1_sec_loop_3")
})
ticker.Cron("5_sec_cron", "0/5 * * * * * ?", func() {
t.Log(time.Now().Format(time.DateTime), "5_sec_cron")
})
time.Sleep(times.Week)
}
```
</details>
***
#### func (*Ticker) CronByInstantly(name string, expression string, handleFunc interface {}, args ...interface {})
> 与 Cron 相同,但是会立即执行一次

View File

@ -1,19 +1,20 @@
# Times
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/times)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[CalcNextSec](#CalcNextSec)|计算下一个N秒在多少秒之后
|[CalcNextSecWithTime](#CalcNextSecWithTime)|计算下一个N秒在多少秒之后
@ -65,23 +66,37 @@
|[NewPeriodWithNanosecond](#NewPeriodWithNanosecond)|创建一个时间段,从 t 开始,持续 nanosecond 纳秒
> 结构体定义
> 类型定义
|结构体|描述
|:--|:--
|[StateLine](#stateline)|状态时间线
|[Period](#period)|表示一个时间段
|类型|名称|描述
|:--|:--|:--
|`STRUCT`|[StateLine](#stateline)|状态时间线
|`STRUCT`|[Period](#period)|表示一个时间段
</details>
***
## 详情信息
#### func CalcNextSec(sec int) int
<span id="CalcNextSec"></span>
> 计算下一个N秒在多少秒之后
***
#### func CalcNextSecWithTime(t time.Time, sec int) int
<span id="CalcNextSecWithTime"></span>
> 计算下一个N秒在多少秒之后
示例代码:
```go
func ExampleCalcNextSecWithTime() {
now := time.Date(2023, 9, 20, 0, 0, 3, 0, time.Local)
fmt.Println(times.CalcNextSecWithTime(now, 10))
}
```
***
#### func CalcNextTimeWithRefer(now time.Time, refer time.Duration) time.Time
<span id="CalcNextTimeWithRefer"></span>
@ -90,192 +105,301 @@
> - 假设当 now 为 14:15:16 参考时间为 20 分钟, 则返回 14:20:00
>
> 当 refer 小于 1 分钟时,将会返回当前时间
***
#### func IntervalFormatSet(intervalType int, str string)
<span id="IntervalFormatSet"></span>
> 针对 IntervalFormat 函数设置格式化内容
***
#### func IntervalFormat(time1 time.Time, time2 time.Time) string
<span id="IntervalFormat"></span>
> 返回指定时间戳之间的间隔
> - 使用传入的时间进行计算换算,将结果体现为几年前、几天前、几小时前、几分钟前、几秒前。
***
#### func GetMonthDays(t time.Time) int
<span id="GetMonthDays"></span>
> 获取一个时间当月共有多少天
***
#### func WeekDay(t time.Time) int
<span id="WeekDay"></span>
> 获取一个时间是星期几
> - 1 ~ 7
***
#### func GetNextDayInterval(t time.Time) time.Duration
<span id="GetNextDayInterval"></span>
> 获取一个时间到下一天间隔多少秒
***
#### func GetToday(t time.Time) time.Time
<span id="GetToday"></span>
> 获取一个时间的今天
***
#### func GetSecond(d time.Duration) int
<span id="GetSecond"></span>
> 获取共有多少秒
***
#### func IsSameDay(t1 time.Time, t2 time.Time) bool
<span id="IsSameDay"></span>
> 两个时间是否是同一天
***
#### func IsSameHour(t1 time.Time, t2 time.Time) bool
<span id="IsSameHour"></span>
> 两个时间是否是同一小时
***
#### func GetMondayZero(t time.Time) time.Time
<span id="GetMondayZero"></span>
> 获取本周一零点
***
#### func Date(year int, month time.Month, day int) time.Time
<span id="Date"></span>
> 返回一个特定日期的时间
***
#### func DateWithHMS(year int, month time.Month, day int, hour int, min int, sec int) time.Time
<span id="DateWithHMS"></span>
> 返回一个精确到秒的时间
***
#### func GetDeltaDay(t1 time.Time, t2 time.Time) int
<span id="GetDeltaDay"></span>
> 获取两个时间需要加减的天数
***
#### func GetDeltaWeek(t1 time.Time, t2 time.Time) int
<span id="GetDeltaWeek"></span>
> 获取两个时间需要加减的周数
***
#### func GetHSMFromString(timeStr string, layout string) (hour int, min int, sec int)
<span id="GetHSMFromString"></span>
> 从时间字符串中获取时分秒
***
#### func GetTimeFromString(timeStr string, layout string) time.Time
<span id="GetTimeFromString"></span>
> 将时间字符串转化为时间
***
#### func GetDayZero(t time.Time, day int) time.Time
<span id="GetDayZero"></span>
> 获取 t 增加 day 天后的零点时间
***
#### func GetYesterday(t time.Time) time.Time
<span id="GetYesterday"></span>
> 获取昨天
***
#### func GetDayLast(t time.Time) time.Time
<span id="GetDayLast"></span>
> 获取某天的最后一刻
> - 最后一刻即 23:59:59
***
#### func GetYesterdayLast(t time.Time) time.Time
<span id="GetYesterdayLast"></span>
> 获取昨天最后一刻
***
#### func GetMinuteStart(t time.Time) time.Time
<span id="GetMinuteStart"></span>
> 获取一个时间的 0 秒
***
#### func GetMinuteEnd(t time.Time) time.Time
<span id="GetMinuteEnd"></span>
> 获取一个时间的 59 秒
***
#### func GetHourStart(t time.Time) time.Time
<span id="GetHourStart"></span>
> 获取一个时间的 0 分 0 秒
***
#### func GetHourEnd(t time.Time) time.Time
<span id="GetHourEnd"></span>
> 获取一个时间的 59 分 59 秒
***
#### func GetMonthStart(t time.Time) time.Time
<span id="GetMonthStart"></span>
> 获取一个时间的月初
***
#### func GetMonthEnd(t time.Time) time.Time
<span id="GetMonthEnd"></span>
> 获取一个时间的月末
***
#### func GetYearStart(t time.Time) time.Time
<span id="GetYearStart"></span>
> 获取一个时间的年初
***
#### func GetYearEnd(t time.Time) time.Time
<span id="GetYearEnd"></span>
> 获取一个时间的年末
***
#### func NewStateLine(zero State) *StateLine[State]
<span id="NewStateLine"></span>
> 创建一个从左向右由早到晚的状态时间线
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewStateLine(t *testing.T) {
sl := times.NewStateLine(0)
sl.AddState(1, time.Now())
sl.AddState(2, time.Now().Add(-times.Hour))
sl.Range(func(index int, state int, ts time.Time) bool {
t.Log(index, state, ts)
return true
})
t.Log(sl.GetStateByTime(time.Now()))
}
```
</details>
***
#### func SetGlobalTimeOffset(offset time.Duration)
<span id="SetGlobalTimeOffset"></span>
> 设置全局时间偏移量
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestSetGlobalTimeOffset(t *testing.T) {
fmt.Println(time.Now())
times.SetGlobalTimeOffset(-times.Hour)
fmt.Println(time.Now())
times.SetGlobalTimeOffset(times.Hour)
fmt.Println(time.Now())
fmt.Println(times.NowByNotOffset())
}
```
</details>
***
#### func NowByNotOffset() time.Time
<span id="NowByNotOffset"></span>
> 获取未偏移的当前时间
***
#### func GetGlobalTimeOffset() time.Duration
<span id="GetGlobalTimeOffset"></span>
> 获取全局时间偏移量
***
#### func ResetGlobalTimeOffset()
<span id="ResetGlobalTimeOffset"></span>
> 重置全局时间偏移量
***
#### func NewPeriod(start time.Time, end time.Time) Period
<span id="NewPeriod"></span>
> 创建一个时间段
> - 如果 start 比 end 晚,则会自动交换两个时间
***
#### func NewPeriodWindow(t time.Time, size time.Duration) Period
<span id="NewPeriodWindow"></span>
> 创建一个特定长度的时间窗口
<details>
<summary>查看 / 收起单元测试</summary>
```go
func TestNewPeriodWindow(t *testing.T) {
cur := time.Now()
fmt.Println(cur)
window := times.NewPeriodWindow(cur, times.Day)
fmt.Println(window)
}
```
</details>
***
#### func NewPeriodWindowWeek(t time.Time) Period
<span id="NewPeriodWindowWeek"></span>
> 创建一周长度的时间窗口,从周一零点开始至周日 23:59:59 结束
***
#### func NewPeriodWithTimeArray(times [2]time.Time) Period
<span id="NewPeriodWithTimeArray"></span>
> 创建一个时间段
***
#### func NewPeriodWithDayZero(t time.Time, day int) Period
<span id="NewPeriodWithDayZero"></span>
> 创建一个时间段,从 t 开始,持续到 day 天后的 0 点
***
#### func NewPeriodWithDay(t time.Time, day int) Period
<span id="NewPeriodWithDay"></span>
> 创建一个时间段,从 t 开始,持续 day 天
***
#### func NewPeriodWithHour(t time.Time, hour int) Period
<span id="NewPeriodWithHour"></span>
> 创建一个时间段,从 t 开始,持续 hour 小时
***
#### func NewPeriodWithMinute(t time.Time, minute int) Period
<span id="NewPeriodWithMinute"></span>
> 创建一个时间段,从 t 开始,持续 minute 分钟
***
#### func NewPeriodWithSecond(t time.Time, second int) Period
<span id="NewPeriodWithSecond"></span>
> 创建一个时间段,从 t 开始,持续 second 秒
***
#### func NewPeriodWithMillisecond(t time.Time, millisecond int) Period
<span id="NewPeriodWithMillisecond"></span>
> 创建一个时间段,从 t 开始,持续 millisecond 毫秒
***
#### func NewPeriodWithMicrosecond(t time.Time, microsecond int) Period
<span id="NewPeriodWithMicrosecond"></span>
> 创建一个时间段,从 t 开始,持续 microsecond 微秒
***
#### func NewPeriodWithNanosecond(t time.Time, nanosecond int) Period
<span id="NewPeriodWithNanosecond"></span>
> 创建一个时间段,从 t 开始,持续 nanosecond 纳秒
***
### StateLine
### StateLine `STRUCT`
状态时间线
```go
type StateLine[State generic.Basic] struct {
@ -362,10 +486,10 @@ type StateLine[State generic.Basic] struct {
#### func (*StateLine) RangeReverse(handler func (index int, state State, t time.Time) bool)
> 按照时间逆序遍历时间线
***
### Period
### Period `STRUCT`
表示一个时间段
```go
type Period struct{}
type Period [2]time.Time
```
#### func (Period) Start() time.Time
> 返回时间段的开始时间

View File

@ -1,32 +1,28 @@
# Xlsxtool
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/kercylan98/minotaur/xlsxtool)
![](https://img.shields.io/badge/Email-kercylan@gmail.com-green.svg?style=flat)
## 目录
列出了该 `package` 下所有的函数,可通过目录进行快捷跳转 ❤️
## 目录导航
列出了该 `package` 下所有的函数及类型定义,可通过目录导航进行快捷跳转 ❤️
<details>
<summary>展开 / 折叠目录</summary
<summary>展开 / 折叠目录导航</summary>
> 包级函数定义
|函数|描述
|函数名称|描述
|:--|:--
|[GetSheetMatrix](#GetSheetMatrix)|将sheet转换为二维矩阵
> 结构体定义
|结构体|描述
|:--|:--
</details>
***
## 详情信息
#### func GetSheetMatrix(sheet *xlsx.Sheet) *matrix.Matrix[*xlsx.Cell]
<span id="GetSheetMatrix"></span>
> 将sheet转换为二维矩阵
***