golang-yitisheng-server/server/modules/yx/service/yx_calculation_major_servic...

418 lines
14 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 service 业务逻辑层
package service
import (
"fmt"
"server/common"
"server/modules/user/vo"
"server/modules/yx/dto"
yxDto "server/modules/yx/dto"
"server/modules/yx/entity"
"server/modules/yx/mapper"
"strings"
"time"
"github.com/google/uuid"
)
type YxCalculationMajorService struct {
historyMajorEnrollService *YxHistoryMajorEnrollService
mapper *mapper.YxCalculationMajorMapper
historyScoreControlLineService *YxHistoryScoreControlLineService
}
func (s *YxCalculationMajorService) RecommendMajorList(schoolMajorQuery yxDto.SchoolMajorQuery) (any, int64, error) {
if schoolMajorQuery.UserScoreVO.ProfessionalCategory == "" {
return nil, 0, fmt.Errorf("专业类型错误")
}
if schoolMajorQuery.Batch != "" {
schoolMajorQuery.Batch = strings.ReplaceAll(schoolMajorQuery.Batch, "批", "")
}
// if len(schoolMajorQuery.MajorTypeChildren) > 0 && "高职高专" != schoolMajorQuery.Batch {
// if "表演类" == schoolMajorQuery.MajorType {
// }
// }
calculationMajors, total, err := s.mapper.FindRecommendList(schoolMajorQuery)
if err != nil {
return nil, 0, err
}
return calculationMajors, total, nil
}
func (s *YxCalculationMajorService) BatchCreateBySchoolMajorDTO(items []dto.SchoolMajorDTO, scoreID string) error {
entities := make([]entity.YxCalculationMajor, 0, len(items))
now := time.Now()
for _, item := range items {
// 构建 OtherScoreLimitation
var otherScoreLimitation strings.Builder
if item.ChineseScoreLimitation > 0 {
otherScoreLimitation.WriteString(fmt.Sprintf("语文成绩不低于%.1f分,", item.ChineseScoreLimitation))
}
if item.EnglishScoreLimitation > 0 {
otherScoreLimitation.WriteString(fmt.Sprintf("外语成绩不低于%.1f分,", item.EnglishScoreLimitation))
}
if item.CulturalScoreLimitation > 0 {
otherScoreLimitation.WriteString(fmt.Sprintf("文化成绩不低于%.1f分,", item.CulturalScoreLimitation))
}
if item.ProfessionalScoreLimitation > 0 {
otherScoreLimitation.WriteString(fmt.Sprintf("专业成绩不低于%.1f分,", item.ProfessionalScoreLimitation))
}
otherScoreLimitationStr := otherScoreLimitation.String()
if len(otherScoreLimitationStr) > 0 {
otherScoreLimitationStr = otherScoreLimitationStr[:len(otherScoreLimitationStr)-1]
}
entities = append(entities, entity.YxCalculationMajor{
ScoreID: scoreID,
SchoolCode: item.SchoolCode,
MajorCode: item.MajorCode,
MajorName: item.MajorName,
EnrollmentCode: item.EnrollmentCode,
Tuition: item.Tuition,
Detail: item.Detail,
Category: item.Category,
RulesEnrollProbability: item.RulesEnrollProbability,
Batch: item.Batch,
StudentOldConvertedScore: item.StudentScore,
StudentConvertedScore: item.StudentConvertedScore,
EnrollProbability: item.EnrollProbability,
ProbabilityOperator: item.ProbabilityOperator,
CreateTime: now,
MajorType: item.MajorType,
MajorTypeChild: item.MajorTypeChild,
PlanNum: item.PlanNum,
MainSubjects: item.MainSubjects,
Limitation: item.Limitation,
OtherScoreLimitation: otherScoreLimitationStr,
RulesEnrollProbabilitySx: item.RulesEnrollProbabilitySx,
Kslx: item.Kslx,
PrivateStudentConvertedScore: item.PrivateStudentScore,
PrivateRulesEnrollProbability: item.PrivateRulesEnrollProbability,
PrivateProbabilityOperator: item.PrivateProbabilityOperator,
State: item.State,
})
}
return s.BatchCreate(entities)
}
func NewYxCalculationMajorService() *YxCalculationMajorService {
return &YxCalculationMajorService{
historyMajorEnrollService: NewYxHistoryMajorEnrollService(),
mapper: mapper.NewYxCalculationMajorMapper(),
historyScoreControlLineService: NewYxHistoryScoreControlLineService(),
}
}
func (s *YxCalculationMajorService) List(page, size int) ([]entity.YxCalculationMajor, int64, error) {
return s.mapper.FindAll(page, size)
}
func (s *YxCalculationMajorService) GetByID(id string) (*entity.YxCalculationMajor, error) {
return s.mapper.FindByID(id)
}
func (s *YxCalculationMajorService) Create(item *entity.YxCalculationMajor) error {
item.ID = uuid.New().String()
return s.mapper.Create(item)
}
func (s *YxCalculationMajorService) Update(item *entity.YxCalculationMajor) error {
return s.mapper.Update(item)
}
func (s *YxCalculationMajorService) UpdateFields(id string, fields map[string]interface{}) error {
return s.mapper.UpdateFields(id, fields)
}
func (s *YxCalculationMajorService) Delete(id string) error {
return s.mapper.Delete(id)
}
func (s *YxCalculationMajorService) GetByScoreID(scoreID string) ([]entity.YxCalculationMajor, error) {
return s.mapper.FindByScoreID(scoreID)
}
func (s *YxCalculationMajorService) BatchCreate(items []entity.YxCalculationMajor) error {
for i := range items {
items[i].ID = uuid.New().String()
}
return s.mapper.BatchCreate(items, 100)
}
func (s *YxCalculationMajorService) BatchUpdate(items []entity.YxCalculationMajor) error {
return s.mapper.BatchUpdate(items)
}
func (s *YxCalculationMajorService) BatchUpsert(items []entity.YxCalculationMajor, updateColumns []string) error {
for i := range items {
if items[i].ID == "" {
items[i].ID = uuid.New().String()
}
}
return s.mapper.BatchUpsert(items, updateColumns)
}
func (s *YxCalculationMajorService) BatchDelete(ids []string) error {
return s.mapper.BatchDelete(ids)
}
func (s *YxCalculationMajorService) DeleteByScoreID(scoreID string) error {
return s.mapper.DeleteByScoreID(scoreID)
}
// 函数名 根据用户查询类型获取专业列表
// 详细描述(可选)
//
// 参数说明:
//
// professionalCategory - 专业分类
// cognitioPolyclinic - 文理文科
// professionalCategoryChildren - 专业分类子项
//
// 返回值说明:
//
// 返回值类型 - 返回值描述
func (s *YxCalculationMajorService) ListByUserQueryType(professionalCategory string, cognitioPolyclinic string,
professionalCategoryChildren []string) ([]dto.SchoolMajorDTO, error) {
// 构造查询条件
query := dto.SchoolMajorQuery{
MajorType: professionalCategory,
Category: cognitioPolyclinic,
// MainSubjects: "器乐",
// MajorTypeChildren: []string{
// "音乐教育",
// },
}
years := []string{"2025", "2024"}
// 执行院校查询
majorItems, err := mapper.NewYxSchoolMajorMapper().SelectSchoolMajor(query)
if err != nil {
return nil, err
}
// 分别收集专业名称和院校代码集合(去重)
majorNameSet := make(map[string]bool)
schoolCodeSet := make(map[string]bool)
for _, dto := range majorItems {
majorNameSet[dto.MajorName] = true
schoolCodeSet[dto.SchoolCode] = true
}
// 转换为切片用于查询
majorNames := make([]string, 0, len(majorNameSet))
schoolCodes := make([]string, 0, len(schoolCodeSet))
for name := range majorNameSet {
majorNames = append(majorNames, name)
}
for code := range schoolCodeSet {
schoolCodes = append(schoolCodes, code)
}
// 执行查询院校专业的历年数据 - 类似Java中的in查询
historyItems, err := s.historyMajorEnrollService.ListBySchoolCodesAndMajorNames(
schoolCodes,
majorNames,
query.Category, // 文科/理科
query.MajorType, // 专业类型
years, // 年份
)
if err != nil {
return nil, err
}
// 构建历史数据映射schoolCode_majorName_batch_year -> historyItem
allHistoryMajorEnrollMap := make(map[string]entity.YxHistoryMajorEnroll)
for _, historyItem := range historyItems {
key := historyItem.SchoolCode + "_" + historyItem.MajorName + "_" + historyItem.Batch + "_" + historyItem.Year
allHistoryMajorEnrollMap[key] = historyItem
}
// 将历史数据填充到每个专业数据中
for i, majorItem := range majorItems {
// 为每个majorItem创建独立的历史数据映射
historyMap := make(map[string]dto.YxHistoryMajorEnrollDTO)
for _, year := range years {
key := majorItem.SchoolCode + "_" + majorItem.MajorName + "_" + majorItem.Batch + "_" + year
if historyItem, ok := allHistoryMajorEnrollMap[key]; ok {
// 类型转换entity -> dto
dtoItem := dto.YxHistoryMajorEnrollDTO{
Year: historyItem.Year,
EnrollmentCode: historyItem.EnrollmentCode,
RulesEnrollProbability: historyItem.RulesEnrollProbability,
ProbabilityOperator: historyItem.ProbabilityOperator,
AdmissionLine: historyItem.AdmissionLine,
ControlLine: historyItem.ControlLine,
// 复制其他需要的字段
}
historyMap[year] = dtoItem
}
}
majorItems[i].HistoryMajorEnrollMap = historyMap
}
return majorItems, nil
}
// 函数名 给专业列表计算录取率
// 详细描述(可选)
//
// 参数说明:
//
// schoolMajorDTOList - 专业列表
// professionalCategory - 专业分类
// cognitioPolyclinic - 文理文科
// professionalCategoryChildren - 专业分类子项
//
// 返回值说明:
//
// 返回值类型 - 返回值描述
func (s *YxCalculationMajorService) CheckEnrollProbability(schoolMajorDTOList *[]dto.SchoolMajorDTO, userScoreVO vo.UserScoreVO) error {
professionalCategory := userScoreVO.ProfessionalCategory
if "表演类" == professionalCategory {
// TODO: biaoyanService
} else if "音乐类" == professionalCategory {
// TODO: musicService
} else {
s.betaRecommendMajorListSetEnrollProbability(schoolMajorDTOList, userScoreVO)
}
return nil
}
// betaRecommendMajorListSetEnrollProbability 美术与设计类,书法类,体育类 按这个走 获取录取率
func (s *YxCalculationMajorService) betaRecommendMajorListSetEnrollProbability(recommendMajorList *[]dto.SchoolMajorDTO, userScoreVO vo.UserScoreVO) {
if recommendMajorList == nil || len(*recommendMajorList) == 0 {
return
}
professionalCategory := userScoreVO.ProfessionalCategory
nowBatch := "本科" // TODO 默认为本科需根据实际情况获取Java中是从 userScore 获取,这里 VO 中似乎没有 Batch? 假设为本科或从 VO 获取
// userScoreVO.Batch? 检查 VO 定义
// 假设 userScoreVO 没有 Batch需要确认。Entity YxUserScore 有 Batch。VO 可能需要补充。
// 暂时假设为 "本科" 或 ""
// 获取省控线 Map
historyScoreControlLineMap, err := s.historyScoreControlLineService.MapsBatchByProfessionalCategoryOfYear(common.NowYear, professionalCategory, userScoreVO.CognitioPolyclinic)
if err != nil {
// Log error
return
}
culturalScore := userScoreVO.CulturalScore
professionalScore := userScoreVO.ProfessionalScore
for i := range *recommendMajorList {
item := &(*recommendMajorList)[i]
rulesEnrollProbability := item.PrivateRulesEnrollProbability
probabilityOperator := item.PrivateProbabilityOperator
// 获取对应批次的省控线
controlLineData, ok := historyScoreControlLineMap[item.Batch]
if !ok {
// 尝试默认批次
if val, okDefault := historyScoreControlLineMap["本科"]; okDefault {
controlLineData = val
} else {
continue // 没有省控线无法计算
}
}
culturalControlLine := controlLineData.CulturalScore
specialControlLine := controlLineData.SpecialScore
if rulesEnrollProbability == "" {
continue
}
// 补全 probabilityOperator 逻辑
if rulesEnrollProbability == "文过专排" && probabilityOperator == "" {
probabilityOperator = "文*0+专*1"
} else if rulesEnrollProbability == "专过文排" && probabilityOperator == "" {
probabilityOperator = "文*1+专*0"
}
if probabilityOperator == "" {
item.EnrollProbability = common.Number5
continue
}
// 判断其他录取要求
if !OtherScoreJudge(professionalScore, userScoreVO, *item) {
item.EnrollProbability = common.Number0
continue
}
// 25年专业录取原则变动 (体育类特殊逻辑,硬编码 ID 列表)
if item.MajorType == "体育类" {
specialSchoolCodes := []string{"6530", "6085", "6110", "6065", "6050"}
isSpecial := false
for _, code := range specialSchoolCodes {
if item.SchoolCode == code {
isSpecial = true
break
}
}
if isSpecial {
item.EnrollProbability = common.Number0
continue
}
}
// 判断是否过省控线
if !CrossingControlLine(rulesEnrollProbability, culturalScore, professionalScore, culturalControlLine, specialControlLine) {
item.EnrollProbability = common.Number0
continue
}
// 计算学生折合分
studentScore := ConvertIntoScore(rulesEnrollProbability, culturalScore, professionalScore, probabilityOperator)
item.PrivateStudentScore = studentScore
item.StudentScore = studentScore // 展示用
// 权限检查
if !HasComputeEnrollProbabilityPermissions(nowBatch, item.Batch) {
item.EnrollProbability = common.Number0
continue
}
// 录取方式计算
if common.CulturalControlLineGuoMain == rulesEnrollProbability {
if len(item.HistoryMajorEnrollList) == 0 {
item.EnrollProbability = common.Number0
continue
}
item.EnrollProbability = (studentScore * item.HistoryMajorEnrollList[0].AdmissionLine) * common.Number0p75
if studentScore >= item.HistoryMajorEnrollList[0].AdmissionLine {
item.EnrollProbability *= common.Number0p5
}
continue
} else {
// 当前年省控线 折合后
nowYearProvincialControlLine := ConvertIntoScore(rulesEnrollProbability, culturalControlLine, specialControlLine, probabilityOperator)
if nowYearProvincialControlLine <= 0 {
item.EnrollProbability = common.Number0
continue
}
// 历年分差
diffMap := ComputeHistoryMajorEnrollScoreLineDifferenceWithRulesEnrollProbability(item.MajorType, rulesEnrollProbability, probabilityOperator, item.HistoryMajorEnrollMap)
historyThreeYearDiff := diffMap["scoreDifference"].(float64)
if historyThreeYearDiff == 0 {
item.EnrollProbability = common.Number0
continue
}
// 当前年线差
nowYearDiff := studentScore - nowYearProvincialControlLine
// 计算录取率
enrollProbability := CommonCheckEnrollProbability(nowYearDiff, historyThreeYearDiff)
item.EnrollProbability = CommonCheckEnrollProbabilityBeilv(enrollProbability)
}
}
// log time...
}