- LocalizationManager: 新增翻译表(SetFormatted/SetDuration/LocalizeOperateMsg) - LoginPanel: InputField placeholder本地化、字体颜色保持 - HistoryPanel: 用时数据本地化、placeholder本地化 - RecordDetailPanel: 操作详情消息本地化(LanguageChanged重建) - AppraiseWindowBase: 评价等级本地化、操作消息重建 - EditorAppraiser: 所有评估消息改用InjectOperateMsgLocalized - StudentOperateRecorder: 新增InjectOperateMsgLocalized方法 - LocalizationLanguageTestBar: 单例模式、ScreenSpaceOverlay筛选 - 字体切换时保留颜色和verticalOverflow
1026 lines
48 KiB
C#
1026 lines
48 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
/// <summary>
|
||
/// 编辑评估类 按照提供规则评估扣分情况 并直接计入操作纪录类
|
||
/// </summary>
|
||
public class EditorAppraiser
|
||
{
|
||
#region //行军编队评估
|
||
static Dictionary<FormationGroupingEnum, List<string>> rightPersonDic = new Dictionary<FormationGroupingEnum, List<string>>()
|
||
{
|
||
{ FormationGroupingEnum.前进保障队, new List<string>() { "连长", "指导员", "副连长", "装甲技师", "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "火炮修理工", "火控修理工", "通信修理工", "液压修理工", "车辆综合电子系统修理工", "汽车修理工" } },
|
||
{ FormationGroupingEnum.指挥组, new List<string>() { "连长", "指导员", "副连长", "装甲技师", "汽车技师" } },
|
||
{ FormationGroupingEnum.前出保障组, new List<string>() { "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "火炮修理工", "火控修理工", "通信修理工", "车辆综合电子修理工", "液压修理工", "汽车修理工" } },
|
||
{ FormationGroupingEnum.抢救抢修队, new List<string>() { "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "火炮修理工", "火控修理工", "通信修理工", "车辆综合电子修理工", "液压修理工", "汽车修理工" } },
|
||
//{ FormationGroupingEnum.主体编队, new List<string>() { "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "火炮修理工", "火控修理工", "通信修理工", "车辆综合电子修理工", "液压修理工", "汽车修理工" } },
|
||
{ FormationGroupingEnum.殿后保障组, new List<string>() { "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "车辆抢救工", "汽车修理工" } },
|
||
};
|
||
|
||
static Dictionary<FormationGroupingEnum, List<string>> rightCarDic = new Dictionary<FormationGroupingEnum, List<string>>()
|
||
{
|
||
{ FormationGroupingEnum.前进保障队, new List<string>() {"NY033H型轮式轻型防化分队指挥车", "ZJQ84Q式中型坦克抢救车", "VME104履带装甲抢修车","VMG101履带装甲补给车", "CXZ411型装甲能源工程车", "CXZ311型装甲拆装工程车", "CXZ511型装甲保养工程车", "CXC012汽车修理工程车","VME301-5型轮式装备抢救车", "CXC022汽车保养车" } },
|
||
{ FormationGroupingEnum.指挥组, new List<string>() { "NY033H型轮式轻型防化分队指挥车" } },
|
||
{ FormationGroupingEnum.前出保障组, new List<string>() { "ZJQ84Q式中型坦克抢救车", "96A坦克抢救车", "VME104履带装甲抢修车","VMG101履带装甲补给车", "CXZ411型装甲能源工程车", "CXZ511型装甲保养工程车", "徐工QY25K型汽车起重机", "VME301-5型轮式装备抢救车", "CXC022汽车保养车" } },
|
||
{ FormationGroupingEnum.抢救抢修队, new List<string>() { "ZJQ84Q式中型坦克抢救车", "96A坦克抢救车", "VME104履带装甲抢修车", "VMG101履带装甲补给车", "CXZ411型装甲能源工程车", "CXZ511型装甲保养工程车", "VMG101履带装甲补给车", "VME301-5型轮式装备抢救车", "CXC022汽车保养车", "CXC012汽车修理工程车" } },
|
||
//{ FormationGroupingEnum.主体编队, new List<string>() { "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "火炮修理工", "火控修理工", "通信修理工", "车辆综合电子修理工", "液压修理工", "汽车修理工" } },
|
||
{ FormationGroupingEnum.殿后保障组, new List<string>() { "ZJQ84Q式中型坦克抢救车", "徐工QY25K型汽车起重机", "徐工QY16K型汽车起重机", "VME301-5型轮式装备抢救车"} },
|
||
};
|
||
|
||
/// <summary>
|
||
/// 评估编队得分 记录扣分项
|
||
/// </summary>
|
||
public void AppraiseTeam(Dictionary<FormationGroupingEnum, List<CarIconInstanceCtrl>> onMapCarsGroups)
|
||
{
|
||
foreach (var item in onMapCarsGroups)
|
||
{
|
||
switch (item.Key)
|
||
{
|
||
case FormationGroupingEnum.前进保障队://不连贯训练时的默认分组
|
||
AppraisFrontTeam(item.Value, item.Key.ToString());
|
||
break;
|
||
case FormationGroupingEnum.指挥组:
|
||
AppraisLeaderGroup(item.Value);
|
||
break;
|
||
case FormationGroupingEnum.前出保障组:
|
||
AppraisFrontGroup(item.Value, item.Key.ToString());
|
||
break;
|
||
case FormationGroupingEnum.抢救抢修队://暂时无评估规则
|
||
|
||
break;
|
||
case FormationGroupingEnum.主体编队://暂时无评估规则
|
||
|
||
break;
|
||
case FormationGroupingEnum.殿后保障组:
|
||
AppraisFollowGroup(item.Value, item.Key.ToString());
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
//StudentOperateRecorder.Instance.InjectOperateMsg($"行军编队部分评估结束!");
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 训练模式操作过程中检查车辆类型是否为当前车队的标准配置人员
|
||
/// </summary>
|
||
/// <param name="carType"> 车辆类型</param>
|
||
/// <param name="groupingEnum">编组</param>
|
||
/// <returns></returns>
|
||
public static bool CheckCar(string carType, FormationGroupingEnum groupingEnum)
|
||
{
|
||
if (rightCarDic.ContainsKey(groupingEnum))
|
||
return rightCarDic[groupingEnum].Contains(carType);
|
||
else
|
||
return true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 训练模式操作过程中检查人员类型是为当前车队的标准配置人员
|
||
/// </summary>
|
||
/// <param name="personName"></param>
|
||
/// <param name="groupingEnum"></param>
|
||
/// <returns></returns>
|
||
public static bool CheckPerson(string personName, FormationGroupingEnum groupingEnum)
|
||
{
|
||
if (rightPersonDic.ContainsKey(groupingEnum))
|
||
return rightPersonDic[groupingEnum].Contains(personName);
|
||
else
|
||
return true;
|
||
}
|
||
|
||
//评价指挥组 与其他分组评价方法略有差异 不做整合
|
||
private void AppraisLeaderGroup(List<CarIconInstanceCtrl> item)
|
||
{
|
||
float deductsScore = 0;
|
||
//指挥车数量
|
||
int leaderCarCount = 0;
|
||
//电源车 和电子检修车
|
||
int PowerAndConnectCarCount = 0;
|
||
//其它不应该出现的车型
|
||
List<string> otherCars = new List<string>();
|
||
|
||
//车队中具备的人员
|
||
List<string> personType = new List<string>();
|
||
|
||
for (int i = 0; i < item.Count; i++)
|
||
{
|
||
string carName = item[i].text_IconName.text;
|
||
foreach (var personItem in item[i].personNames)//统计指挥组中的人员类型
|
||
{
|
||
if (!personType.Contains(personItem.Key))
|
||
personType.Add(personItem.Key);
|
||
}
|
||
if (carName.Contains("NY033H"))//模糊检查 避免个别名称不太符合的情况和新增装备的情况
|
||
{
|
||
leaderCarCount++;
|
||
}
|
||
else if (carName.Contains("电源") || carName.Contains("电子检测维修"))
|
||
PowerAndConnectCarCount++;
|
||
else
|
||
{
|
||
if (!otherCars.Contains(carName))
|
||
otherCars.Add(carName);
|
||
}
|
||
}
|
||
|
||
//增加多余车型 每种车型扣1分
|
||
if (otherCars.Count != 0)
|
||
{
|
||
deductsScore += otherCars.Count * 1;
|
||
|
||
string otherCarsStr = GetStrFromList(otherCars);
|
||
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}增加{1}等{2}种车型,扣{3}分", "指挥组", otherCarsStr, otherCars.Count, otherCars.Count);
|
||
}
|
||
int groupCount = item.Count;
|
||
|
||
|
||
if (leaderCarCount == 0)
|
||
{
|
||
deductsScore += 10;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}缺少标准车型:{1},扣{2}分", "指挥组", "NY033H型轮式轻型防化分队指挥车", 10);
|
||
}
|
||
|
||
if (leaderCarCount == 1)
|
||
{
|
||
deductsScore += 3;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("指挥组仅有一台分队指挥车,扣3分");
|
||
}
|
||
|
||
StudentOperateRecorder.Instance.InjectDecScore(deductsScore, EvaluationFactorsEnum.型号组成.ToString());
|
||
deductsScore = 0;
|
||
//装备数量超过四台 每超一台扣0.5分
|
||
if (groupCount > 4) //数量超出
|
||
{
|
||
deductsScore += ((groupCount - 4) * 0.5f);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}装备数量为{1}台,超出{2}台,扣{3}分", "指挥组", groupCount, 4, otherCars.Count * 0.5f);
|
||
}
|
||
StudentOperateRecorder.Instance.InjectDecScore(deductsScore, EvaluationFactorsEnum.装备数量.ToString());
|
||
deductsScore = 0;
|
||
List<string> targetPerson = new List<string>() { "连长", "指导员", "副连长", "装甲技师", "汽车技师" }; //车队应该配备的人员
|
||
List<string> anyPerson = GetAny<string>(targetPerson, personType);//不存在的标准人员
|
||
if (anyPerson.Count > 0)
|
||
{
|
||
deductsScore += anyPerson.Count;
|
||
string anyPersonsStr = GetStrFromList(anyPerson);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}人员工种缺少{1},扣{2}分", "指挥组", anyPersonsStr, anyPerson.Count);
|
||
}
|
||
StudentOperateRecorder.Instance.InjectDecScore(deductsScore, EvaluationFactorsEnum.人员工种.ToString());
|
||
}
|
||
|
||
|
||
//评价前出保障组
|
||
private void AppraisFrontGroup(List<CarIconInstanceCtrl> item, string groupName)
|
||
{
|
||
List<string> carTypes = GetCarTypes(item);//已有车队类型
|
||
List<string> dueCars = new List<string>() { "ZJQ84Q式中型坦克抢救车", "96A坦克抢救车", "VME104履带装甲抢修车",
|
||
"VMG101履带装甲补给车", "CXZ411型装甲能源工程车", "CXZ511型装甲保养工程车", "徐工QY25K型汽车起重机", "VME301-5型轮式装备抢救车", "CXC022汽车保养车" };//应当具备的车型
|
||
List<string> notDeductCars = new List<string>() { "VME301机械维修车", "VME105履带装甲抢修车", "CXZ311型装甲拆装工程车", "CXZ321型装甲拆装工程车", "徐工QY16K型汽车起重机", "高机动电源挂车" };//多出但不扣分的车型
|
||
GetCarTypesScore(carTypes, groupName, dueCars, 2, notDeductCars, item.Count, 12);
|
||
Dictionary<string, int> personDic;//车队人员类型+数量字典
|
||
List<string> personTypes;//车队人员类型
|
||
GetPersonTypes(item, out personDic, out personTypes);
|
||
List<string> targetPerson = new List<string>() { "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "火炮修理工", "火控修理工", "通信修理工", "车辆综合电子修理工", "液压修理工", "汽车修理工" };
|
||
List<string> notDeductPerson = new List<string>() { "钳工", "制配工", "充电工", "车工", "钣焊工", "光电修理工" };//多出不扣分的工种
|
||
Dictionary<string, int> aloneCheckPersons = new Dictionary<string, int>();//需要单独检查不得低于某数量的工种 每工种少一人扣一分
|
||
aloneCheckPersons.Add("抢救工", 6);
|
||
aloneCheckPersons.Add("装甲底盘修理工", 5);
|
||
aloneCheckPersons.Add("汽车修理工", 4);
|
||
GetPersonScore(groupName, personDic, personTypes, targetPerson, notDeductPerson, aloneCheckPersons);
|
||
}
|
||
|
||
//评价殿后保障组
|
||
private float AppraisFollowGroup(List<CarIconInstanceCtrl> item, string groupName)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(item);//已有车队类型
|
||
List<string> dueCars = new List<string>() { "ZJQ84Q式中型坦克抢救车", "徐工QY25K型汽车起重机", "徐工QY16K型汽车起重机", "VME301-5型轮式装备抢救车" };//应当具备的车型
|
||
List<string> notDeductCars = new List<string>() { "96式坦克抢救车", "VME105履带装甲抢修车", "CXZ311型装甲拆装工程车", "CXZ321型装甲拆装工程车" };//多出但不扣分的车型
|
||
GetCarTypesScore(carTypes, groupName, dueCars, 2, notDeductCars, item.Count, 6);
|
||
|
||
Dictionary<string, int> personDic;//车队人员类型+数量字典
|
||
List<string> personTypes;//车队人员类型
|
||
GetPersonTypes(item, out personDic, out personTypes);
|
||
List<string> targetPerson = new List<string>() { "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "车辆抢救工", "汽车修理工" };//标准人员工种
|
||
List<string> notDeductPerson = new List<string>() { "钳工", "制配工", "充电工", "车工", "钣焊工", "液压修理工" };//多出不扣分的工种
|
||
Dictionary<string, int> aloneCheckPersons = new Dictionary<string, int>();//需要单独检查不得低于某数量的工种 每工种少一人扣一分
|
||
aloneCheckPersons.Add("抢救工", 2);
|
||
aloneCheckPersons.Add("装甲底盘修理工", 1);
|
||
aloneCheckPersons.Add("汽车修理工", 2);
|
||
GetPersonScore(groupName, personDic, personTypes, targetPerson, notDeductPerson, aloneCheckPersons);
|
||
return deductsScore;
|
||
}
|
||
|
||
//评价前进保障队 不连贯训练
|
||
private void AppraisFrontTeam(List<CarIconInstanceCtrl> item, string groupName)
|
||
{
|
||
List<string> carTypes = GetCarTypes(item);//已有车队类型
|
||
List<string> dueCars = new List<string>() { "NY033H型轮式轻型防化分队指挥车", "ZJQ84Q式中型坦克抢救车", "VME104履带装甲抢修车",
|
||
"VMG101履带装甲补给车", "CXZ411型装甲能源工程车", "CXZ311型装甲拆装工程车", "CXZ511型装甲保养工程车", "CXC012汽车修理工程车","VME301-5型轮式装备抢救车", "CXC022汽车保养车" };//应当具备的车型
|
||
List<string> notDeductCars = new List<string>() { "96式坦克抢救车", "VME105履带装甲抢修车", "CXZ321型装甲拆装工程车", "徐工QY16K型汽车起重机", "徐工QY25K型汽车起重机", "VME301机械维修车", "VMD301型电源车" };//多出但不扣分的车型
|
||
GetCarTypesScore(carTypes, groupName, dueCars, 2, notDeductCars, item.Count, 12);
|
||
|
||
Dictionary<string, int> personDic;//车队人员类型+数量字典
|
||
List<string> personTypes;//车队人员类型
|
||
GetPersonTypes(item, out personDic, out personTypes);
|
||
List<string> targetPerson = new List<string>() { "连长", "指导员", "副连长", "装甲技师", "抢救工", "起重工", "装甲底盘修理工", "电气修理工", "火炮修理工", "火控修理工", "通信修理工", "液压修理工", "车辆综合电子系统修理工", "汽车修理工" };
|
||
List<string> notDeductPerson = new List<string>() { "钳工", "制配工", "充电工", "钣焊工" };//多出不扣分的工种
|
||
Dictionary<string, int> aloneCheckPersons = new Dictionary<string, int>();//需要单独检查不得低于某数量的工种 每工种少一人扣一分
|
||
aloneCheckPersons.Add("抢救工", 6);
|
||
aloneCheckPersons.Add("装甲底盘修理工", 7);
|
||
aloneCheckPersons.Add("汽车修理工", 4);
|
||
aloneCheckPersons.Add("电气修理工", 3);
|
||
GetPersonScore(groupName, personDic, personTypes, targetPerson, notDeductPerson, aloneCheckPersons);
|
||
|
||
}
|
||
|
||
|
||
//计算编组中人员扣分情况
|
||
/// <summary>
|
||
/// 缺少必要工种扣1分 增加非必要的多余工种扣1分 某工种少于一定数量 每少一人扣0.5分
|
||
/// </summary>
|
||
/// <param name="groupName">编组名称</param>
|
||
/// <param name="deductsScore">最终扣分</param>
|
||
/// <param name="personDic">人员类型+数量字典</param>
|
||
/// <param name="personTypes">人员类型集合</param>
|
||
/// <param name="targetPerson">标准人员</param>
|
||
/// <param name="notDeductPerson">超出不扣分人员</param>
|
||
/// <param name="checkPersonCountDic">需检查数量的某工种+最少数量</param>
|
||
/// <returns></returns>
|
||
private float GetPersonScore(string groupName, /*ref float deductsScore,*/ Dictionary<string, int> personDic, List<string> personTypes, List<string> targetPerson, List<string> notDeductPerson, Dictionary<string, int> checkPersonCountDic)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> anyPerson = GetAny<string>(targetPerson, personTypes);//缺少的标准工种
|
||
List<string> unnecessaryPerson = GetAny<string>(personTypes, targetPerson);//多出的工种
|
||
List<string> deductPerson = GetAny<string>(unnecessaryPerson, notDeductPerson);//多出待扣分的工种
|
||
if (anyPerson.Count > 0)
|
||
{
|
||
deductsScore += anyPerson.Count;
|
||
string anyPersonsStr = GetStrFromList(anyPerson);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}人员工种缺少{1}\u201C等\u201D{2}种,扣{3}分", groupName, anyPersonsStr, anyPerson.Count, anyPerson.Count);
|
||
}
|
||
|
||
if (deductPerson.Count > 0)
|
||
{
|
||
deductsScore += (deductPerson.Count * 1f);
|
||
string deductsPersonStr = GetStrFromList(deductPerson);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}人员工种增加:{1}\u201C等\u201D{2}种,扣{3}分", groupName, deductsPersonStr, deductPerson.Count, deductPerson.Count * 1f);
|
||
}
|
||
|
||
|
||
StudentOperateRecorder.Instance.InjectDecScore(deductsScore, EvaluationFactorsEnum.人员工种.ToString());
|
||
|
||
|
||
foreach (var item in checkPersonCountDic)
|
||
{
|
||
CheckPersonCount(groupName, personDic, item.Key, item.Value, 0.5f);
|
||
}
|
||
return deductsScore;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 梳理 车队中人员工种信息
|
||
/// </summary>
|
||
/// <param name="item"></param>
|
||
/// <param name="personDic">返回车载人员字典类</param>
|
||
/// <param name="personTypes">返回车载人员类型集合</param>
|
||
private void GetPersonTypes(List<CarIconInstanceCtrl> item, out Dictionary<string, int> personDic, out List<string> personTypes)
|
||
{
|
||
personDic = new Dictionary<string, int>();
|
||
personTypes = new List<string>();
|
||
for (int i = 0; i < item.Count; i++)
|
||
{
|
||
foreach (var personItem in item[i].personNames)//统计所有车中的人员类型
|
||
{
|
||
if (!personTypes.Contains(personItem.Key))
|
||
personTypes.Add(personItem.Key);
|
||
if (!personDic.ContainsKey(personItem.Key))
|
||
personDic[personItem.Key] = 0;
|
||
personDic[personItem.Key] += 1;
|
||
}
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 计算某组中某一类型的工种 是否满足人员要求,并计算应扣除的分数
|
||
/// </summary>
|
||
/// <param name="groupName">组名 用于生成扣分记录</param>
|
||
/// <param name="personDic">人员字典</param>
|
||
/// <param name="personType">待检查的人员类型</param>
|
||
/// <param name="LeastCount">最少人数</param>
|
||
/// <param name="onePersonDeductScore">少一人扣除的分数</param>
|
||
/// <param name="score">改变当前分数</param>
|
||
private void CheckPersonCount(string groupName, Dictionary<string, int> personDic, string personType, int LeastCount, float onePersonDeductScore)
|
||
{
|
||
float score = 0;
|
||
int personCount = 0;
|
||
if (personDic.ContainsKey(personType))
|
||
personCount = personDic[personType];
|
||
|
||
|
||
if (personCount < LeastCount)
|
||
{
|
||
score += ((LeastCount - personCount) * onePersonDeductScore);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}{1}人数为{2},少于{3}人,扣{4}分", groupName, personType, personCount, LeastCount, (LeastCount - personCount) * onePersonDeductScore);
|
||
}
|
||
StudentOperateRecorder.Instance.InjectDecScore(score, EvaluationFactorsEnum.人员数量.ToString());
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 遍历集合A 取出未在集合B中出现过的元素
|
||
/// </summary>
|
||
/// <typeparam name="T">类型</typeparam>
|
||
/// <param name="listA">待遍历查找的集合</param>
|
||
/// <param name="listB">待排除元素的集合</param>
|
||
/// <returns>不存在的值</returns>
|
||
private List<T> GetAny<T>(List<T> listA, List<T> listB)
|
||
{
|
||
List<T> anyT = new List<T>();
|
||
for (int i = 0; i < listA.Count; i++)
|
||
{
|
||
if (!listB.Contains(listA[i]))
|
||
anyT.Add(listA[i]);
|
||
}
|
||
return anyT;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 将一系列字符串以、号分割组成一个长字符串
|
||
/// </summary>
|
||
/// <param name="strList"></param>
|
||
/// <returns></returns>
|
||
private string GetStrFromList(List<string> strList)
|
||
{
|
||
string longStr = "";
|
||
for (int i = 0; i < strList.Count; i++)
|
||
{
|
||
longStr += $"{strList[i]}、";
|
||
}
|
||
return longStr;
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
|
||
|
||
#region//修理厂开展评估
|
||
|
||
/// <summary>
|
||
/// 评估修理区布置间距和车型
|
||
/// </summary>
|
||
/// <param name="areaCars">存储了厂区+车辆集合的字典 key 厂区名称 value 该厂区中的车辆</param>
|
||
/// <param xixiaoToRiverDis="areaCars">铣消场距离水源的最近距离</param>
|
||
/// <returns></returns>
|
||
public void AppraiseRepairArea(Dictionary<string, List<Transform>> areaCars)
|
||
{
|
||
float score = 0;//修理厂展开部分扣除总分数
|
||
AppraiseAreaDistanceAndTime(areaCars, ref score);//评估厂区间距 和转运时间
|
||
AppraiseWaterToXiXiao(areaCars["洗消场"]);//评估洗消场距离河边的距离
|
||
|
||
foreach (var item in areaCars)//遍历各厂区 分别评估厂区内部扣分
|
||
{
|
||
switch (item.Key)
|
||
{
|
||
case "指控区":
|
||
score += AppraiseCC(item.Key, item.Value);
|
||
break;
|
||
case "油料场":
|
||
score += AppraiseYouLiao(item.Key, item.Value);
|
||
break;
|
||
case "器材存放场":
|
||
score += AppraiseQiCai(item.Key, item.Value);
|
||
break;
|
||
case "弹药场"://距离已经评价完成 无需评价其他内容
|
||
|
||
break;
|
||
case "修竣装备停放场":
|
||
score += AppraiseXiuJun(item.Key, item.Value);
|
||
|
||
break;
|
||
case "修理场"://无相关评价规则
|
||
|
||
break;
|
||
case "待修装备停放场":
|
||
score += AppraiseDaiXiu(item.Key, item.Value);
|
||
break;
|
||
case "洗消场":
|
||
score += AppraiseXiXiao(item.Key, item.Value);
|
||
break;
|
||
case "待后送装备停放场":
|
||
score += AppraiseDaiHouSong(item.Key, item.Value);
|
||
break;
|
||
case "接收场":
|
||
score += AppraiseJieShou(item.Key, item.Value);
|
||
break;
|
||
default:
|
||
Debug.Log($"{item.Key}无评估规则");
|
||
break;
|
||
}
|
||
}
|
||
//StudentOperateRecorder.Instance.InjectOperateMsg($"修理厂开设布置扣分{score}");
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 训练模式中检查当前厂区与其他厂区位置是否合适
|
||
/// </summary>
|
||
/// <param name="allPlanedAreas">完成规划的厂区</param>
|
||
/// <returns>距离异常提示</returns>
|
||
public static string CheckAreaDistance(List<AreaFlageCtrl> allPlanedAreas)
|
||
{
|
||
if (allPlanedAreas.Count < 2) return "";//单个厂区时无需检测厂区间距距离是否合适
|
||
for (int i = 0; i < allPlanedAreas.Count - 1; i++)//从开始到结尾依次取出一个厂区 和剩余厂区分别计算距离 计算统一规则的距离得分
|
||
{
|
||
for (int j = i + 1; j < allPlanedAreas.Count; j++)
|
||
{
|
||
float distance = Vector3.Distance(allPlanedAreas[i].transform.position, allPlanedAreas[j].transform.position) - allPlanedAreas[i].Radius - allPlanedAreas[j].Radius; // 计算厂区间距 标志距离-厂区半径
|
||
if (allPlanedAreas[i].AreaName == "弹药场" || allPlanedAreas[j].AreaName == "弹药场") //弹药场与其他厂区的间距限制在200M
|
||
{
|
||
if (distance < 200)
|
||
{
|
||
return $"{allPlanedAreas[i].AreaName}与{allPlanedAreas[j].AreaName}边界间距为{(distance).ToString("0.0")}M,小于200M";
|
||
}
|
||
}
|
||
else //其他厂区间距限制在100M
|
||
{
|
||
if (distance < 100)
|
||
{
|
||
return $"{allPlanedAreas[i].AreaName}与{allPlanedAreas[j].AreaName}边界间距为{(distance).ToString("0.0")}M,小于100M";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return "";
|
||
}
|
||
|
||
/// <summary>
|
||
/// 训练模式中检查 洗销厂和水源的距离
|
||
/// </summary>
|
||
/// <param name="xixiaoPos"></param>
|
||
/// <returns></returns>
|
||
public static string CheckAreaToWaterDistance(Transform xixiaoPos)
|
||
{
|
||
float distance= GetXiXiaoToWaterDistance(new List<Transform>() { xixiaoPos });
|
||
|
||
if (distance > 100)
|
||
return $"{AreaNameEnum.洗消场.ToString()}距离水源距离为{distance.ToString("0.0")}M,超出100M";
|
||
return "";
|
||
}
|
||
|
||
//评估洗消场和水源距离扣分情况
|
||
private void AppraiseWaterToXiXiao(List<Transform> xixiao)
|
||
{
|
||
|
||
float xixiaoToRiverDis = GetXiXiaoToWaterDistance(xixiao);
|
||
if (xixiaoToRiverDis == -1)
|
||
{
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("当前场景无水源,不计算洗消场与水源间距扣分项");
|
||
return;
|
||
}
|
||
|
||
if (xixiaoToRiverDis > 100)
|
||
{
|
||
float decScore = 0.05f + ((int)(xixiaoToRiverDis - 100)) / 10 * 0.05f;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("洗消场与水源间距为{0}M,大于100M,每10米扣0.05f,计扣{1}分", xixiaoToRiverDis.ToString("0.0"), decScore);
|
||
StudentOperateRecorder.Instance.InjectDecScore(decScore, null);//水源不做为权重调整因素
|
||
}
|
||
}
|
||
|
||
private static float GetXiXiaoToWaterDistance(List<Transform> xixiao)
|
||
{
|
||
|
||
WaterManager[] distanceManagers = GameObject.FindObjectsOfType<WaterManager>();//查找所有的水源
|
||
if (distanceManagers == null || distanceManagers.Length == 0)//不存在水源
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
float xixiaoToRiverDis = 0;
|
||
WaterManager nearWater = ArrayHelper.Min(distanceManagers, (p) => p.GetDistanceFromWater(xixiao[0].position));
|
||
|
||
Transform trans = ArrayHelper.Min(xixiao, (p) => nearWater.GetNearestPointDistance(p.position));//找洗消场中距离水源最近的Trans
|
||
|
||
//Debug.Log(nearWater.name);
|
||
xixiaoToRiverDis = nearWater.GetNearestPointDistance(trans.position);//距离水源的距离
|
||
|
||
if (xixiao.Count == 1 && "Flag" == LayerMask.LayerToName(xixiao[0].gameObject.layer))//如果洗消场中不存在车辆 距离需要扣除洗消场默认半径
|
||
{
|
||
xixiaoToRiverDis -= xixiao[0].GetComponent<AreaFlageCtrl>().Radius;
|
||
}
|
||
return xixiaoToRiverDis;
|
||
}
|
||
|
||
|
||
//评估各厂区间的间距 和转运时间
|
||
private void AppraiseAreaDistanceAndTime(Dictionary<string, List<Transform>> areaCars, ref float refScore)
|
||
{
|
||
float score=0;
|
||
Dictionary<string, Dictionary<string, float>> areasDistanceDic = new Dictionary<string, Dictionary<string, float>>();//记录每个厂区与其他厂区之间的距离 Kye=当前厂区名称 ,value.Key = 与当前厂区计算距离的目标厂区名称 , value.value = 当前厂区与目标厂区之间的距离
|
||
List<string> dicKeys = new List<string>();
|
||
List<List<Transform>> dicValues = new List<List<Transform>>();
|
||
foreach (var item in areaCars)//按照顺序取出字典形成有序的集合 便于后续计算厂区间距
|
||
{
|
||
dicKeys.Add(item.Key);
|
||
dicValues.Add(item.Value);
|
||
}
|
||
for (int i = 0; i < dicKeys.Count - 1; i++)//从开始到结尾依次取出一个厂区 和剩余厂区分别计算距离 计算统一规则的距离得分
|
||
{
|
||
for (int j = i + 1; j < dicKeys.Count; j++)
|
||
{
|
||
float distance = GetAreasDistance(dicValues[i], dicValues[j]); //每计算出一个距离 分别为两个厂区建立各自的距离字典
|
||
if (dicKeys[i] == "弹药场" || dicKeys[j] == "弹药场") //弹药场与其他厂区的间距限制在200M
|
||
{
|
||
if (distance < 200)
|
||
{
|
||
score += 1;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}与{1}间距为{2}M,小于200M,扣1分", dicKeys[i], dicKeys[j], distance.ToString("0.0"));
|
||
}
|
||
}
|
||
else //其他厂区间距限制在100M
|
||
{
|
||
if (distance < 100)
|
||
{
|
||
score += 1;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}与{1}间距为{2}M,小于100M,扣1分", dicKeys[i], dicKeys[j], distance.ToString("0.0"));
|
||
}
|
||
}
|
||
if (!areasDistanceDic.ContainsKey(dicKeys[i])) //存入字典便于提取单个厂区的间距情况
|
||
{
|
||
areasDistanceDic.Add(dicKeys[i], new Dictionary<string, float>());
|
||
}
|
||
if (!areasDistanceDic.ContainsKey(dicKeys[j]))
|
||
{
|
||
areasDistanceDic.Add(dicKeys[j], new Dictionary<string, float>());
|
||
}
|
||
areasDistanceDic[dicKeys[i]].Add(dicKeys[j], distance);
|
||
areasDistanceDic[dicKeys[j]].Add(dicKeys[i], distance);
|
||
}
|
||
}
|
||
if (areasDistanceDic.ContainsKey("指控区"))
|
||
{
|
||
if (areasDistanceDic["指控区"].ContainsKey("修理场"))
|
||
{
|
||
float dis1 = areasDistanceDic["指控区"]["修理场"];
|
||
if (dis1 < 300)
|
||
{
|
||
float decScore = 0.5f + ((int)(300 - dis1)) / 50 * 0.5f;
|
||
score += decScore;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("指控区与修理场间距为{0}M,小于300M,每50米扣0.5f,计扣{1}分", dis1.ToString("0.0"), decScore);
|
||
}
|
||
else if (dis1 > 600)
|
||
{
|
||
float decScore = 0.5f + ((int)(dis1 - 600)) / 50 * 0.5f;
|
||
score += decScore;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("指控区与修理场间距为{0}M,大于600M,每50米扣0.5f,计扣{1}分", dis1.ToString("0.0"), decScore);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("指控区与修理厂无距离数据");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
Debug.Log("无指控区距离数据");
|
||
}
|
||
|
||
if (areasDistanceDic.ContainsKey("器材存放场"))
|
||
{
|
||
if (areasDistanceDic["器材存放场"].ContainsKey("修理场"))
|
||
{
|
||
float dis2 = areasDistanceDic["器材存放场"]["修理场"];
|
||
if (dis2 > 50)
|
||
{
|
||
float decScore = 0.05f + ((int)(dis2 - 50)) / 10 * 0.05f;
|
||
score += decScore;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("器材存放场与修理场间距为{0}M,大于50M,每10米扣0.05f,计扣{1}分", dis2.ToString("0.0"), decScore);
|
||
}
|
||
}
|
||
else {
|
||
Debug.Log("器材存放场与修理厂无距离数据");
|
||
}
|
||
}
|
||
else {
|
||
Debug.Log("无器材存放场距离数据");
|
||
}
|
||
|
||
refScore += score;
|
||
StudentOperateRecorder.Instance.InjectDecScore(score, EvaluationFactorsEnum.厂区间距.ToString());
|
||
|
||
int time = AppraiseRepairTime(areasDistanceDic);//计算转运用时
|
||
StudentOperateRecorder.Instance.InjectTransportTime(time);
|
||
}
|
||
|
||
|
||
//评估指控区域
|
||
private float AppraiseCC(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "NY033H型轮式轻型防化分队指挥车" };//应当具备的车型
|
||
List<string> notDeductCars = new List<string>() { "VMD301型电源车", "VMZ308型通指装备电子检测维修车" };//多出不扣分的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, notDeductCars, 0, 0, 0.5f);//评估装备型号部分扣分情况
|
||
GetInAreaCarDistanceScore(areaName, cars, ref deductsScore);//评估区域内车辆之间的间距的扣分情况
|
||
return deductsScore;
|
||
}
|
||
|
||
//评估接收场
|
||
private float AppraiseJieShou(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "徐工QY25K型汽车起重机", "96A坦克抢救车", "VME301-5型轮式装备抢救车", "CXZ211型装甲检测工程车", "VMZ306机电检测维修车" };//应当具备的车型
|
||
List<string> notDeductCars = new List<string>() { "ZJQ84Q式中型坦克抢救车", "CXL211型雷达检测车", "CXL221型雷达检测车", "CXL231型雷达检测车" };//多出不扣分的车型
|
||
List<string> notDeductLessCars = new List<string>() { "徐工QY25K型汽车起重机" };//缺少不扣分的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, notDeductCars, 0, 0, 0.5f, notDeductLessCars);//评估装备型号部分扣分情况
|
||
GetInAreaCarDistanceScore(areaName, cars, ref deductsScore);//评估区域内车辆之间的间距的扣分情况
|
||
return deductsScore;
|
||
}
|
||
|
||
//评估铣消场
|
||
private float AppraiseXiXiao(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "CXF111-1型防化修理车" };//应当具备的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, null, 0, 0, 0.5f);//评估装备型号部分扣分情况
|
||
GetInAreaCarDistanceScore(areaName, cars, ref deductsScore);//评估区域内车辆之间的间距的扣分情况
|
||
return deductsScore;
|
||
}
|
||
|
||
|
||
//评估油料场
|
||
private float AppraiseYouLiao(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "油料运输车" };//应当具备的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, null, 0, 0, 0.5f);//评估装备型号部分扣分情况
|
||
return deductsScore;
|
||
}
|
||
|
||
//评估待修装备停放场
|
||
private float AppraiseDaiXiu(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "ZJQ84Q式中型坦克抢救车"};//应当具备的车型
|
||
List<string> notDeductCars = new List<string>() { "徐工QY25K型汽车起重机", "徐工QY16K型汽车起重机", "96式坦克抢救车", "VME301-5型轮式装备抢救车" };//多出不扣分的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, notDeductCars, 0, 0, 0.5f);//评估装备型号部分扣分情况
|
||
GetInAreaCarDistanceScore(areaName, cars, ref deductsScore);//评估区域内车辆之间的间距的扣分情况
|
||
//GetMainLoadDisScore();//评估距离主通路距离
|
||
return deductsScore;
|
||
}
|
||
|
||
//评估器材存放场
|
||
private float AppraiseQiCai(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "VMG101履带装甲补给车" };//应当具备的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, null, 0, 0, 0.5f);//评估装备型号部分扣分情况
|
||
return deductsScore;
|
||
}
|
||
|
||
//评估修竣装备停放场
|
||
private float AppraiseXiuJun(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "VMZ301电子检测维修车", "CXZ511型装甲保养工程车" };//应当具备的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, null, 0, 0, 0.5f);//评估装备型号部分扣分情况
|
||
GetInAreaCarDistanceScore(areaName, cars, ref deductsScore);//评估区域内车辆之间的间距的扣分情况
|
||
//GetMainLoadDisScore();//评估距离主通路距离
|
||
return deductsScore;
|
||
}
|
||
|
||
//评估待后送装备停放场
|
||
private float AppraiseDaiHouSong(string areaName, List<Transform> cars)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> carTypes = GetCarTypes(cars);
|
||
List<string> dueCars = new List<string>() { "ZJQ84Q式中型坦克抢救车", "VME301-5型轮式装备抢救车" };//应当具备的车型
|
||
GetCarTypesScore(carTypes, areaName, dueCars, 0.5f, null, 0, 0, 0.5f);//评估装备型号部分扣分情况
|
||
GetInAreaCarDistanceScore(areaName, cars, ref deductsScore);//评估区域内车辆之间的间距的扣分情况
|
||
//GetMainLoadDisScore();//评估距离主通路距离
|
||
return deductsScore;
|
||
}
|
||
|
||
|
||
//评估距离主通路距离 待实现
|
||
private void GetMainLoadDisScore()
|
||
{
|
||
|
||
}
|
||
|
||
|
||
//评估区域内部的距离扣分情况
|
||
private void GetInAreaCarDistanceScore(string areaName, List<Transform> cars, ref float refScore)
|
||
{
|
||
float score = 0;
|
||
for (int i = 0; i < cars.Count - 1; i++)
|
||
{
|
||
for (int j = i; j < cars.Count; j++)//双循环依次计算车队中每两个之间的距离
|
||
{
|
||
float carsDistance = Vector3.Distance(cars[i].transform.position, cars[j].transform.position);
|
||
if (carsDistance < 50)//小于50m的 扣0.5f
|
||
{
|
||
score += 0.5f;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}中{1}与{2}间距为{3}M,小于50M,扣0.5分", areaName, cars[i].transform.name, cars[j].transform.name, carsDistance.ToString("0.0"));
|
||
}
|
||
}
|
||
}
|
||
refScore = score;
|
||
StudentOperateRecorder.Instance.InjectDecScore(score, EvaluationFactorsEnum.车辆间距.ToString());
|
||
}
|
||
|
||
//根据车辆/图标名称获取所选车辆类型
|
||
private List<string> GetCarTypes<T>(List<T> carCtrls) where T : Component
|
||
{
|
||
List<string> names = new List<string>();
|
||
for (int i = 0; i < carCtrls.Count; i++)
|
||
{
|
||
string type = carCtrls[i].transform.name.Split('(')[0];//取括号前的部分
|
||
if (!names.Contains(type))
|
||
names.Add(type);
|
||
}
|
||
return names;
|
||
}
|
||
|
||
/// <summary>
|
||
///计算两个厂区之间的间距
|
||
/// </summary>
|
||
private float GetAreasDistance(List<Transform> area1, List<Transform> area2)
|
||
{
|
||
//if (area1.Count == 0 || area2.Count == 0) return -1;//负一代表无效数据 出现未安置车辆的厂区时为-1
|
||
float nearestDistance = float.MaxValue;
|
||
for (int i = 0; i < area1.Count; i++)
|
||
{
|
||
for (int j = 0; j < area2.Count; j++)//遍历两个数组 依次计算两个数组中的所有元素的间距 记录最小间距
|
||
{
|
||
float currenDis = Vector3.Distance(area1[i].transform.position, area2[j].transform.position);
|
||
if (currenDis < nearestDistance)
|
||
nearestDistance = currenDis;
|
||
}
|
||
}
|
||
|
||
if (area1.Count == 1 && "Flag" == LayerMask.LayerToName(area1[0].gameObject.layer)) //厂区1 内部无车辆
|
||
{
|
||
nearestDistance -= area1[0].GetComponent<AreaFlageCtrl>().Radius; //以厂区1边缘计算距离 需扣除厂区1半径
|
||
if (area2.Count == 1 && "Flag" == LayerMask.LayerToName(area2[0].gameObject.layer))//厂区2内部也无车辆
|
||
{
|
||
nearestDistance -= area2[0].GetComponent<AreaFlageCtrl>().Radius;//以厂区2边缘计算距离 需扣除厂区2半径
|
||
}
|
||
}
|
||
if (nearestDistance < 0)//两个厂区有交集时 避免出现负数
|
||
nearestDistance = 0;
|
||
return nearestDistance;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 评估修理时在各厂区间的转运时间 暂时使用直线距离计算 后续若出现厂区中阻挡目标的情况时 使用寻路系统获取距离
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private int AppraiseRepairTime(Dictionary<string, Dictionary<string, float>> areasDistanceDic)
|
||
{
|
||
if (areasDistanceDic.Count < 10)
|
||
{
|
||
Debug.Log("存在空厂区,无法判定转运时间");
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("存在未安置装备的厂区,无法判定距离和转运时间!");
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("按照15km/h速度计算转运时间:");//15KM每小时 等于4.16米每秒
|
||
List<string> repairOrder = new List<string>() { AreaNameEnum.接收场.ToString(), AreaNameEnum.洗消场.ToString(), AreaNameEnum.弹药场.ToString(), AreaNameEnum.油料场.ToString(), AreaNameEnum.待修装备停放场.ToString(), AreaNameEnum.修理场.ToString(), AreaNameEnum.修竣装备停放场.ToString(), AreaNameEnum.油料场.ToString(), AreaNameEnum.弹药场.ToString() };
|
||
float totalTime = 0;
|
||
for (int i = 0; i < repairOrder.Count - 1; i++)//依次计算 两场地之间的转运时间
|
||
{
|
||
totalTime += AppraiseTwoAreaRepairTime(areasDistanceDic, repairOrder[i], repairOrder[i + 1]);
|
||
}
|
||
System.TimeSpan ts = System.TimeSpan.FromSeconds(totalTime);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("修理厂转运总用时:{0}时{1}分{2}秒", ts.Hours, ts.Minutes, ts.Seconds);
|
||
return (int)totalTime;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取在两个厂区间的转运时间
|
||
/// </summary>
|
||
/// <param name="area1"></param>
|
||
/// <param name="area2"></param>
|
||
/// <returns>耗时</returns>
|
||
private float AppraiseTwoAreaRepairTime(Dictionary<string, Dictionary<string, float>> areasDistanceDic, string area1, string area2)
|
||
{
|
||
float dis = areasDistanceDic[area1][area2];
|
||
float time = dis / 4.16f;
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}距离{1}:{2}米,预计转运用时:{3}秒", area1, area2, dis.ToString("0"), time.ToString("0.0"));
|
||
return time;
|
||
}
|
||
|
||
|
||
#endregion
|
||
|
||
//部分科目共用的评估方法
|
||
#region
|
||
|
||
/// <summary>
|
||
/// 获取编队中车型部分扣分分值 并梳理当前车队中的人员种类列表 种类+数量 排除允许增加车型后的多余车型默认扣1分 超出最大数量扣0.5分
|
||
/// </summary>
|
||
/// <param name="carTypes">编组集合</param>
|
||
/// <param name="groupName">编组名称</param>
|
||
/// <param name="dueCars">标准车型</param>
|
||
/// <param name="notDeductCars">多出但不扣分的车型</param>
|
||
/// <param name="groupCount">编组当前数量</param>
|
||
/// <param name="maxCount">编组最大允许数量 不计算最大数量时赋0</param>
|
||
/// <param name="deductsScore">当前分数字段 传入引用</param>
|
||
/// <param name="unnecessOneScore">排除允许增加车型后的多余车型扣分 默认1</param>
|
||
/// <param name="unnecessOneScore">缺少但不扣分的车型 默认1</param>
|
||
private void GetCarTypesScore(List<string> carTypes, string groupName, List<string> dueCars, float lessDueScore, List<string> notDeductCars, int groupCount, int maxCount, /*ref float deductsScore,*/ float unnecessOneScore = 1, List<string> lessNotDeductCars = null)
|
||
{
|
||
float deductsScore = 0;
|
||
List<string> anyCars = GetAny<string>(dueCars, carTypes);//梳理缺少的车型
|
||
if (lessNotDeductCars != null)
|
||
anyCars = GetAny<string>(anyCars, lessNotDeductCars);
|
||
List<string> unnecessaryCars = GetAny<string>(carTypes, dueCars);//梳理多出的车型
|
||
List<string> deductCars;
|
||
if (notDeductCars != null)
|
||
deductCars = GetAny<string>(unnecessaryCars, notDeductCars);//梳理多出车型中需要扣分的车型
|
||
else//多出的车型都需要扣分
|
||
deductCars = unnecessaryCars;
|
||
|
||
if (anyCars.Count > 0)
|
||
{
|
||
deductsScore += (anyCars.Count * lessDueScore);
|
||
string anyCarsStr = GetStrFromList(anyCars);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}缺少标准车型:{1},扣{2}分", groupName, anyCarsStr, anyCars.Count * lessDueScore);
|
||
}
|
||
|
||
|
||
if (deductCars.Count > 0)
|
||
{
|
||
deductsScore += (deductCars.Count * 1f);
|
||
string deductsCarsStr = GetStrFromList(deductCars);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}增加车型:{1}\u201C等\u201D{2}种,扣{3}分", groupName, deductsCarsStr, deductCars.Count, deductCars.Count * unnecessOneScore);
|
||
}
|
||
|
||
StudentOperateRecorder.Instance.InjectDecScore(deductsScore, EvaluationFactorsEnum.型号组成.ToString());
|
||
|
||
deductsScore = 0;//记录后清空开始计算装备数量扣分情况
|
||
if (maxCount != 0 && groupCount > maxCount)//部分组别无需评估最大数量
|
||
{
|
||
deductsScore += ((groupCount - maxCount) * 0.5f);
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0}装备数量为{1}台,超出{2}台,扣{3}分", groupName, groupCount, maxCount, (groupCount - maxCount) * 0.5f);
|
||
}
|
||
|
||
StudentOperateRecorder.Instance.InjectDecScore( deductsScore, EvaluationFactorsEnum.装备数量.ToString());
|
||
}
|
||
#endregion
|
||
|
||
|
||
#region//装备修理科目评估
|
||
//判断维修逻辑是否正确 判断依据是前置步骤是否已经完成 完成规划返回空 未完成时返回错误描述
|
||
internal string AppraiseSteps(List<StepData> rightSteps)
|
||
{
|
||
List<StepData> checkOver = new List<StepData>();//检查通过的步骤 认为规划正确可以完成
|
||
for (int i = 0; i < rightSteps.Count; i++)//一次检查规划的步骤
|
||
{
|
||
if (rightSteps[i].preIDs != null && rightSteps[i].preIDs.Length > 0)//存在前置步骤 需要判断前置步骤是否完成
|
||
{
|
||
for (int j = 0; j < rightSteps[i].preIDs.Length; j++)
|
||
{
|
||
StepData stepData = CollectionHelper.Find(checkOver, p => p.id == rightSteps[i].preIDs[j]);//在已完成的步骤中寻找是否存在前置步骤
|
||
if (stepData == default(StepData))//不存在前置步骤,代表前置步骤还未完成
|
||
{
|
||
string errorMsg;//规划步骤错误描述
|
||
stepData = CollectionHelper.Find(rightSteps, p => p.id == rightSteps[i].preIDs[j]);//在传入的所有步骤中查找是否存在前置步骤
|
||
if (stepData == default(StepData))//所有的步骤中都不存在前置步骤 证明教员端发送的步骤库有误 此时只记录 但认为该步骤通过
|
||
{
|
||
errorMsg = $"规划的维修步骤不完善,缺少id为{rightSteps[i].preIDs[j]}的操作步骤,导致{rightSteps[i].describe} 操作无法正确评估";
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
else
|
||
{
|
||
errorMsg = $"{rightSteps[i].describe} 之前需要先完成 {stepData.describe}";
|
||
return errorMsg;
|
||
}
|
||
StudentOperateRecorder.Instance.InjectOperateMsgLocalized("{0} 之前需要先完成 {1}", rightSteps[i].describe, stepData.describe);//记录评估结果
|
||
}
|
||
}
|
||
}
|
||
|
||
checkOver.Add(rightSteps[i]);//通过检查的添加
|
||
}
|
||
return string.Empty;
|
||
}
|
||
#endregion
|
||
}
|
||
|
||
|
||
//评估因素枚举 便于后续教师端调整权重时统一名称
|
||
public enum EvaluationFactorsEnum
|
||
{
|
||
//两科目共用本因素 连贯训练时累加扣分
|
||
型号组成,
|
||
装备数量,
|
||
人员工种,
|
||
人员数量,
|
||
//修理所展开时 厂区内部的车辆间距
|
||
车辆间距,
|
||
通路距离,
|
||
厂区间距,
|
||
} |