|
@@ -3,6 +3,7 @@ package api
|
|
|
import (
|
|
|
"cicv-data-closedloop/amd64/web_server/src/domain/competition"
|
|
|
"cicv-data-closedloop/amd64/web_server/src/infrastructure/config"
|
|
|
+ "cicv-data-closedloop/amd64/web_server/src/infrastructure/global"
|
|
|
"cicv-data-closedloop/amd64/web_server/src/infrastructure/persistence"
|
|
|
"cicv-data-closedloop/common/config/c_db"
|
|
|
"cicv-data-closedloop/common/config/c_log"
|
|
@@ -19,20 +20,9 @@ import (
|
|
|
"net/http"
|
|
|
"os"
|
|
|
"strconv"
|
|
|
- "sync"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
-var (
|
|
|
- defaultTime = time.Date(2006, time.January, 2, 15, 4, 5, 0, time.Local)
|
|
|
- cacheTeamName sync.Map // = make(map[string]time.Time)
|
|
|
- heartBeatTimeThreshold = 5 * time.Second // 心跳时间
|
|
|
- InitialPositionX = 565266.0482367771 // todo 需要比赛确认起点
|
|
|
- InitialPositionY = 4329773.48728322 // todo 需要比赛确认起点
|
|
|
- trialBegin = time.Date(2024, time.June, 16, 13, 00, 00, 0, time.Local)
|
|
|
- trialEnd = time.Date(2024, time.June, 19, 23, 59, 59, 0, time.Local)
|
|
|
-)
|
|
|
-
|
|
|
// 考试心跳
|
|
|
func Tick(c *gin.Context) {
|
|
|
param := new(competition.ExamPao)
|
|
@@ -50,7 +40,7 @@ func Tick(c *gin.Context) {
|
|
|
var positionY float64
|
|
|
numStr := param.PositionY
|
|
|
_, _ = fmt.Sscanf(numStr, "%e", &positionY)
|
|
|
- if !util.ContainsKey(&cacheTeamName, teamName) && math.Abs(positionX-InitialPositionX) < 5.00 && math.Abs(positionY-InitialPositionY) < 5.00 { // (在起点开始)
|
|
|
+ if !util.ContainsKey(&global.CacheTeamName, teamName) && math.Abs(positionX-global.InitialPositionX) < 5.00 && math.Abs(positionY-global.InitialPositionY) < 5.00 { // (在起点开始)
|
|
|
|
|
|
result := persistence.SelectLatestByTeamName(teamName)
|
|
|
if len(result) == 1 {
|
|
@@ -59,11 +49,11 @@ func Tick(c *gin.Context) {
|
|
|
c_log.GlobalLogger.Infof("上一条数据记录为【%v】,距离当前时间为【%v】分钟", result[0].Id, temp)
|
|
|
if temp < 2 {
|
|
|
// 添加队伍名到缓存中
|
|
|
- cacheTeamName.Store(teamName, time.Now())
|
|
|
+ global.CacheTeamName.Store(teamName, time.Now())
|
|
|
// 更新记录结束时间为默认时间
|
|
|
sqlTemplate, _ := util.ReadFile(c_db.SqlFilesMap["exam-reset-by-id.sql"])
|
|
|
if err := c_db.DoTx(sqlTemplate, []any{
|
|
|
- defaultTime,
|
|
|
+ global.DefaultTime,
|
|
|
result[0].Id,
|
|
|
}); err != nil {
|
|
|
c_log.GlobalLogger.Error("插入数据报错:", err)
|
|
@@ -80,16 +70,16 @@ func Tick(c *gin.Context) {
|
|
|
{
|
|
|
sqlTemplate, _ := util.ReadFile(c_db.SqlFilesMap["exam-insert-begin_time-and-topic-and-equipment_no-by-team_name.sql"])
|
|
|
stage := ""
|
|
|
- if time.Now().Before(trialBegin) {
|
|
|
+ if time.Now().Before(global.TrialBegin) {
|
|
|
stage = "表演赛"
|
|
|
- } else if time.Now().After(trialBegin) && time.Now().Before(trialEnd) {
|
|
|
+ } else if time.Now().After(global.TrialBegin) && time.Now().Before(global.TrialEnd) {
|
|
|
stage = "预赛"
|
|
|
} else {
|
|
|
stage = "决赛"
|
|
|
}
|
|
|
competitionBegin := time.Now()
|
|
|
// 添加队伍名到缓存中
|
|
|
- cacheTeamName.Store(teamName, competitionBegin)
|
|
|
+ global.CacheTeamName.Store(teamName, competitionBegin)
|
|
|
c_log.GlobalLogger.Infof("当前比赛阶段为 %v ,队伍 %v 在起始点范围内第一次启动,保存新一条比赛记录的开始时间 %v", stage, teamName, competitionBegin)
|
|
|
if err := c_db.DoTx(sqlTemplate, []any{param.TeamName, stage, competitionBegin, param.EquipmentNo}); err != nil {
|
|
|
c_log.GlobalLogger.Error("保存比赛开始时间报错:", err)
|
|
@@ -103,19 +93,19 @@ func Tick(c *gin.Context) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- } else if !util.ContainsKey(&cacheTeamName, teamName) && (math.Abs(positionX-InitialPositionX) > 5.00 || math.Abs(positionY-InitialPositionY) > 5.00) { // 不在起点(开始)
|
|
|
+ } else if !util.ContainsKey(&global.CacheTeamName, teamName) && (math.Abs(positionX-global.InitialPositionX) > 5.00 || math.Abs(positionY-global.InitialPositionY) > 5.00) { // 不在起点(开始)
|
|
|
// 车辆不是在起点启动的自动驾驶模式
|
|
|
result := persistence.SelectLatestByTeamName(teamName)
|
|
|
if len(result) == 1 {
|
|
|
if time.Since(result[0].EndTime).Minutes() <= 5 { // 5分钟之内重启就还算上一条数据
|
|
|
c_log.GlobalLogger.Info("上一条数据记录为:", result[0])
|
|
|
// 添加队伍名到缓存中
|
|
|
- cacheTeamName.Store(teamName, time.Now())
|
|
|
+ global.CacheTeamName.Store(teamName, time.Now())
|
|
|
//cacheTeamName[teamName] = time.Now()
|
|
|
// 更新记录结束时间为默认时间
|
|
|
sqlTemplate, _ := util.ReadFile(c_db.SqlFilesMap["exam-reset-by-id.sql"])
|
|
|
if err := c_db.DoTx(sqlTemplate, []any{
|
|
|
- defaultTime,
|
|
|
+ global.DefaultTime,
|
|
|
result[0].Id,
|
|
|
}); err != nil {
|
|
|
c_log.GlobalLogger.Error("插入数据报错:", err)
|
|
@@ -142,8 +132,8 @@ func Tick(c *gin.Context) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- } else if util.ContainsKey(&cacheTeamName, teamName) { // 进行中
|
|
|
- cacheTeamName.Store(teamName, time.Now())
|
|
|
+ } else if util.ContainsKey(&global.CacheTeamName, teamName) { // 进行中
|
|
|
+ global.CacheTeamName.Store(teamName, time.Now())
|
|
|
//cacheTeamName[teamName] = time.Now()
|
|
|
c_log.GlobalLogger.Errorf("接收到心跳信息,队伍名字为 %s,x坐标为 %.f,y坐标为 %.f ", teamName, positionX, positionY)
|
|
|
c.JSON(http.StatusOK, commonEntity.Response{
|
|
@@ -161,90 +151,6 @@ func Tick(c *gin.Context) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-func ExamEndTicker() {
|
|
|
- // 创建一个定时器,每隔一秒触发一次
|
|
|
- ticker := time.NewTicker(1 * time.Second)
|
|
|
- for {
|
|
|
- select {
|
|
|
- // 定时器触发时执行的代码
|
|
|
- case <-ticker.C:
|
|
|
- var keysToDelete []string
|
|
|
- cacheTeamName.Range(func(teamName, heartBeatTimeAny interface{}) bool {
|
|
|
- heartBeatTime, _ := util.AnyToTime(heartBeatTimeAny)
|
|
|
- if time.Since(heartBeatTime) > heartBeatTimeThreshold { // 检查缓存中的队名,如果超过心跳时间,则代表考试结束,删除缓存中的队名
|
|
|
- c_log.GlobalLogger.Infof("队伍 %v 心跳超时,比赛结束。", teamName)
|
|
|
- keysToDelete = append(keysToDelete, fmt.Sprintf("%v", teamName))
|
|
|
- }
|
|
|
- return true // 如果要终止遍历,返回 false
|
|
|
- })
|
|
|
-
|
|
|
- //for teamName, heartBeatTime := range cacheTeamName {
|
|
|
- // if time.Since(heartBeatTime) > heartBeatTimeThreshold { // 检查缓存中的队名,如果超过心跳时间,则代表考试结束,删除缓存中的队名
|
|
|
- // c_log.GlobalLogger.Infof("队伍 %v 心跳超时,比赛结束。", teamName)
|
|
|
- //
|
|
|
- // keysToDelete = append(keysToDelete, teamName)
|
|
|
- // }
|
|
|
- //}
|
|
|
- for _, teamName := range keysToDelete { // 检查缓存中的队名,如果超过心跳时间,则代表考试结束,删除缓存中的队名
|
|
|
- cacheTeamName.Delete(teamName)
|
|
|
- //delete(cacheTeamName, teamName)
|
|
|
- // 1 查询指定队伍的开始时间最新的考试是否有结束时间,如果有则不在处理,如果没有则更新
|
|
|
- var result []competition.ExamPo
|
|
|
- selectSql, err := util.ReadFile(c_db.SqlFilesMap["exam-select-latest-by-team_name.sql"])
|
|
|
- if err != nil {
|
|
|
- c_log.GlobalLogger.Error("读取sql文件报错:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- // 可以传参数
|
|
|
- if err = c_db.MysqlDb.Select(&result, selectSql, teamName); err != nil {
|
|
|
- c_log.GlobalLogger.Error("数据库查询报错:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- if !result[0].EndTime.Equal(defaultTime) {
|
|
|
- c_log.GlobalLogger.Error("赛队", teamName, "考试已结束!")
|
|
|
- return
|
|
|
- }
|
|
|
- // 更新到数据库(只更新最新一条)
|
|
|
- stage := ""
|
|
|
- if time.Now().Before(trialBegin) {
|
|
|
- stage = "表演赛"
|
|
|
- } else if time.Now().After(trialBegin) && time.Now().Before(trialEnd) {
|
|
|
- stage = "预赛"
|
|
|
- } else {
|
|
|
- stage = "决赛"
|
|
|
- }
|
|
|
- // 查询最新一条的id
|
|
|
- selectSql, err = util.ReadFile(c_db.SqlFilesMap["exam-select-max-id-by-team_name-and-topic.sql"])
|
|
|
- if err != nil {
|
|
|
- c_log.GlobalLogger.Error("读取sql文件报错:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- // 可以传参数
|
|
|
- var resultId []int
|
|
|
- if err = c_db.MysqlDb.Select(&resultId, selectSql, teamName, stage); err != nil {
|
|
|
- c_log.GlobalLogger.Error("数据库查询报错:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- if len(resultId) == 1 {
|
|
|
- c_log.GlobalLogger.Info("更新数据结束时间,id为:", resultId)
|
|
|
-
|
|
|
- sqlTemplate, _ := util.ReadFile(c_db.SqlFilesMap["exam-update-end_time-by-id.sql"])
|
|
|
- if err := c_db.DoTx(sqlTemplate, []any{
|
|
|
- time.Now(),
|
|
|
- resultId[0],
|
|
|
- }); err != nil {
|
|
|
- c_log.GlobalLogger.Error("插入数据报错:", err)
|
|
|
- return
|
|
|
- }
|
|
|
- } else {
|
|
|
- c_log.GlobalLogger.Error("查询id失败:", resultId)
|
|
|
- }
|
|
|
- c_log.GlobalLogger.Infof("队伍 %v 的考试结束。", teamName)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
// 分页查询,如果日期为默认值,则返回空""
|
|
|
func Page(c *gin.Context) {
|
|
|
param := new(competition.ExamPagePao)
|
|
@@ -643,7 +549,12 @@ func Report(c *gin.Context) {
|
|
|
c.String(http.StatusNotFound, "文件未找到")
|
|
|
return
|
|
|
}
|
|
|
- defer file.Close()
|
|
|
+ defer func(file *os.File) {
|
|
|
+ err := file.Close()
|
|
|
+ if err != nil {
|
|
|
+ log.Fatal(err)
|
|
|
+ }
|
|
|
+ }(file)
|
|
|
|
|
|
// 将文件复制到响应主体
|
|
|
_, err = io.Copy(c.Writer, file)
|