golang-yitisheng-server/server/common/score_calculator.go

197 lines
6.0 KiB
Go

package common
import (
"math"
"regexp"
"server/modules/user/vo"
"server/modules/yx/dto"
"strconv"
"strings"
)
// ScoreCalculator 分数计算工具函数集合
// 移植自 Java 版本的 ScoreUtil.java
var (
BigDecimal0 = 0.0
BigDecimal05 = 0.5
BigDecimal075 = 0.75
BigDecimal0133 = 0.133
BigDecimal0667 = 0.667
BigDecimal004 = 0.04
BigDecimal0467 = 0.467
BigDecimal0067 = 0.067
BigDecimal0333 = 0.333
BigDecimal0093 = 0.093
BigDecimal02 = 0.2
BigDecimal07 = 0.7
BigDecimal03 = 0.3
BigDecimal04 = 0.4
BigDecimal06 = 0.6
BigDecimal1 = 1.0
BigDecimal100 = 100.0
BigDecimal150 = 150.0
BigDecimal95x = 95.0
BigDecimal85x = 85.0
BigDecimal7p5 = 7.5
BigDecimal5 = 5.0
)
// ComputeHistoryMajorEnrollScoreLineDifferenceWithRulesEnrollProbability 计算历年录取分差
func ComputeHistoryMajorEnrollScoreLineDifferenceWithRulesEnrollProbability(majorType string,
rulesEnrollProbability, probabilityOperator string,
HistoryMajorEnrollMap map[string]dto.YxHistoryMajorEnrollDTO) map[string]any {
if len(HistoryMajorEnrollMap) == 0 {
return map[string]any{"scoreDifference": 0.0}
}
sum := 0.0
validYearCount := 0
for _, enrollData := range HistoryMajorEnrollMap {
admissionLine := enrollData.AdmissionLine
controlLine := enrollData.ControlLine
if admissionLine <= 0 || controlLine <= 0 {
continue
}
// 计算分差
currentDiff := admissionLine - controlLine
// currentDiff := enrollData.ScoreLineDifference
// 特殊逻辑:高职高专(非体育类)需计算分差率(分差/省控线)
// Java: boolean isVocationalCollege = "高职高专".equals(enrollData.getBatch());
// boolean isSportsMajor = "体育类".equals(enrollData.getMajorType());
if "体育类" == majorType {
if "2024" == enrollData.Year && "专过文排" != enrollData.EnrollmentCode && "文过专排" != enrollData.EnrollmentCode {
currentDiff = currentDiff * Number7p5
} else if "2024" == enrollData.Year && "文过专排" == enrollData.EnrollmentCode { // Placeholder
currentDiff = currentDiff * Number5
} else if "2023" == enrollData.Year {
continue
} else if rulesEnrollProbability == enrollData.RulesEnrollProbability { // Need field
sum += currentDiff
validYearCount++
continue
}
} else {
// 非高职高专 or 体育类:检查录取方式是否一致
if probabilityOperator != enrollData.ProbabilityOperator {
continue
}
}
sum += currentDiff
validYearCount++
}
averageDiff := 0.0
if validYearCount > 0 {
averageDiff = sum / float64(validYearCount)
}
return map[string]any{"scoreDifference": averageDiff}
}
// ConvertIntoScore 计算折合分
func ConvertIntoScore(rulesEnrollProbability string, culturalScore, professionalScore float64, operator string) float64 {
score := 0.0
if operator != "" {
// operator: 例如: "文*0.5+专*0.5"
parts := strings.Split(operator, "+")
for _, part := range parts {
subParts := strings.Split(part, "*")
if len(subParts) == 2 {
ratio, _ := strconv.ParseFloat(subParts[1], 64)
if strings.Contains(subParts[0], "文") {
score += culturalScore * ratio
} else {
score += professionalScore * ratio
}
}
}
}
return round(score, 4)
}
// CrossingControlLine 判断是否过省控线
func CrossingControlLine(rulesEnrollProbability string, culturalScore, professionalScore, culturalControlLine, specialControlLine float64) bool {
if rulesEnrollProbability == CulturalControlLineGuo {
return culturalScore >= culturalControlLine
} else if rulesEnrollProbability == SpecialControlLineGuo {
return professionalScore >= specialControlLine
} else if rulesEnrollProbability == CulturalControlLineGuoMain {
return culturalScore >= specialControlLine
}
return culturalScore >= culturalControlLine && professionalScore >= specialControlLine
}
// CommonCheckEnrollProbability 计算录取率
func CommonCheckEnrollProbability(nowYearDiff, historyThreeYearDiff float64) float64 {
enrollProbability := 0.0
if nowYearDiff == 0 && historyThreeYearDiff > 0 {
enrollProbability = 75.0 / historyThreeYearDiff
} else if nowYearDiff == 0 && historyThreeYearDiff <= 0 {
enrollProbability = 50.0
} else if nowYearDiff > 0 && historyThreeYearDiff <= 0 {
enrollProbability = nowYearDiff * 100 * 0.75
} else if nowYearDiff < 0 && historyThreeYearDiff <= 0 {
enrollProbability = 0.0
} else {
// (当前年分差/去年分差)*0.75 * 100
if historyThreeYearDiff != 0 {
enrollProbability = (nowYearDiff / historyThreeYearDiff) * 100 * 0.75
}
}
return enrollProbability
}
// CommonCheckEnrollProbabilityBeilv 录取率倍率调整
func CommonCheckEnrollProbabilityBeilv(enrollProbability float64) float64 {
if enrollProbability > 150 {
return 95.0
} else if enrollProbability > 100 {
return 85.0
} else if enrollProbability <= 0 {
return 0.0
}
return enrollProbability
}
// OtherScoreJudge 其他录取要求
func OtherScoreJudge(professionalScore float64, userScoreVO vo.UserScoreVO, schoolMajorDTO dto.SchoolMajorDTO) bool {
// 简单实现,参考 Java 逻辑
if schoolMajorDTO.EnglishScoreLimitation > 0 && userScoreVO.EnglishScore < schoolMajorDTO.EnglishScoreLimitation {
return false
}
if schoolMajorDTO.CulturalScoreLimitation > 0 && userScoreVO.CulturalScore < schoolMajorDTO.CulturalScoreLimitation {
return false
}
// 专业分限制等...
return true
}
// HasComputeEnrollProbabilityPermissions 判断是否有权限计算
func HasComputeEnrollProbabilityPermissions(nowBatch, majorBatch string) bool {
return "" != nowBatch && "" != majorBatch
}
// round 四舍五入
func round(val float64, precision int) float64 {
ratio := math.Pow(10, float64(precision))
return math.Round(val*ratio) / ratio
}
// ReplaceLastZeroChar 格式化操作符字符串 (Java: replaceLastZeroChar)
func ReplaceLastZeroChar(input string) string {
if input == "" {
return ""
}
re := regexp.MustCompile(`(\d+\.\d*?)0+(\D|$)`)
input = re.ReplaceAllString(input, "$1$2")
input = strings.ReplaceAll(input, "1.", "1")
// 简化处理
return input
}