Files
Scoreboard/server/internal/rules/convert.go
T
AskaEth bc8b1ee6c0 feat: M3-M7 全模块落地 + 集成接线
- M3 认证/权限/审计/限流 + 全部 REST 接口
- M4 管理面板(MIUIx + 成绩录入/积分榜下钻/大屏控制)
- M5a 大屏页面(六页 + 明细覆盖层 + 缩放适配)
- M6 WebSocket 实时同步中心
- M7 xlsx 导出 + 赛事包 zip + 备份
- 规则包 YAML 导入导出(差异预览)
- 字体 vendor 子集化(4 套 x2 字重)
- 集成:realtime/export/rules 接入 main+httpapi;backup 子命令
- 修复:中间件包装 ResponseWriter 丢失 Hijacker,导致 WS 握手 501
2026-09-09 19:02:24 +08:00

121 lines
3.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package rules
import "git.yeij.top/AskaEth/Scoreboard/server/internal/domain"
// 本文件是规则包类型与 domain 类型之间的唯一转换入口;
// 转换只搬字段、不填默认值(默认值统一由 Canonical 负责),避免两处口径打架。
// ToDomain 把模板转成 domain.ScoringProfile;id 由调用方(仓储层)决定。
func (p Profile) ToDomain(id int64) domain.ScoringProfile {
tie := p.TieMode
if tie == "" {
tie = domain.TieSkip
}
bonus := p.RecordBonusMode
if bonus == "" {
bonus = domain.RecordBonusMax
}
rules := make([]domain.ScoringRule, 0, len(p.Rules))
for _, r := range p.Rules {
rules = append(rules, domain.ScoringRule{Rank: r.Rank, Points: r.Points})
}
return domain.ScoringProfile{
ID: id,
Code: p.Code,
Name: p.Name,
AwardRanks: p.AwardRanks,
LastPlaceZero: p.LastPlaceZero,
TieMode: tie,
RecordBonusMode: bonus,
Rules: rules,
}
}
// ProfileFromDomain 把 domain 模板转回规则包类型。
func ProfileFromDomain(p domain.ScoringProfile) Profile {
rules := make([]Rule, 0, len(p.Rules))
for _, r := range p.Rules {
rules = append(rules, Rule{Rank: r.Rank, Points: r.Points})
}
return Profile{
Code: p.Code,
Name: p.Name,
AwardRanks: p.AwardRanks,
LastPlaceZero: p.LastPlaceZero,
TieMode: p.TieMode,
RecordBonusMode: p.RecordBonusMode,
Rules: rules,
}
}
// ToDomain 把通道转成 domain.ScoreChannel;profileID 由调用方按模板编码查出。
func (c Channel) ToDomain(eventID, profileID int64, sortOrder int) domain.ScoreChannel {
return domain.ScoreChannel{
EventID: eventID,
Scope: c.Scope,
Basis: c.Basis,
ProfileID: profileID,
Aggregate: c.Aggregate,
SortOrder: sortOrder,
}
}
// ChannelFromDomain 把 domain 通道转回规则包类型;profileCode 由调用方按模板 ID 查出。
func ChannelFromDomain(c domain.ScoreChannel, profileCode string) Channel {
return Channel{
Scope: c.Scope,
Basis: c.Basis,
Profile: profileCode,
Aggregate: c.Aggregate,
}
}
// ProfileIndex 按模板编码建索引,便于通道引用解析。
func (p *RulePack) ProfileIndex() map[string]Profile {
out := make(map[string]Profile, len(p.Profiles))
for _, prof := range p.Profiles {
out[prof.Code] = prof
}
return out
}
// ToStandingsInput 把榜单口径映射成 domain 聚合输入。
func (s Standings) ToStandingsInput() domain.StandingsInput {
return domain.StandingsInput{
IndividualToTeamWeight: s.IndividualToTeamWeight,
ExcludeTeamEventMedals: !s.MedalCountsTeamEventsEnabled(),
}
}
// ToDomain 把破纪录配置转成 domain.RecordBonusConfig。
func (r RecordBonus) ToDomain() domain.RecordBonusConfig {
mode := r.Mode
if mode == "" {
mode = domain.RecordBonusMax
}
levels := make([]domain.RecordLevel, 0, len(r.Levels))
for _, lv := range r.Levels {
levels = append(levels, domain.RecordLevel{Code: lv.Code, Name: lv.Name, Points: lv.Points})
}
return domain.RecordBonusConfig{Enabled: r.Enabled, Mode: mode, Levels: levels}
}
// RecordBonusFromDomain 把 domain 破纪录配置转回规则包类型。
func RecordBonusFromDomain(c domain.RecordBonusConfig) RecordBonus {
levels := make([]RecordLevel, 0, len(c.Levels))
for _, lv := range c.Levels {
levels = append(levels, RecordLevel{Code: lv.Code, Name: lv.Name, Points: lv.Points})
}
return RecordBonus{Enabled: c.Enabled, Mode: c.Mode, Levels: levels}
}
// ToDomain 把人工调整开关转成 domain.ManualAdjustmentConfig。
func (m ManualAdjustment) ToDomain() domain.ManualAdjustmentConfig {
return domain.ManualAdjustmentConfig{Enabled: m.Enabled, ReasonRequired: m.ReasonRequired}
}
// ManualAdjustmentFromDomain 把 domain 人工调整开关转回规则包类型。
func ManualAdjustmentFromDomain(c domain.ManualAdjustmentConfig) ManualAdjustment {
return ManualAdjustment{Enabled: c.Enabled, ReasonRequired: c.ReasonRequired}
}