using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.IO; using System.Text; using UnityEngine; using GFGGame; using System.Text.RegularExpressions; using static Google.Protobuf.Reflection.GeneratedCodeInfo.Types; using OfficeOpenXml; namespace GFGEditor { public class CodeBuilder { private const string SQL_PREFIX = "_"; private static StringBuilder _declarationBuilder = new StringBuilder(); private static StringBuilder _assignmentBuilder = new StringBuilder(); private static StringBuilder _parseBuilder = new StringBuilder(); //private static bool _hasSameIds; private static List _names = new List(); private static List _types = new List(); private static List _allNames = new List(); private static List _allTypes = new List(); private static List _indexs = new List(); private static List _allIndexs = new List(); private static Dictionary _idDic = new Dictionary(); private static Dictionary _itemTypeDicByName = new Dictionary(); public static void GenerateCode(ExcelWorksheet worksheet, string configName, string configArrayName) { ET.Log.Debug($"configName {configName}"); _declarationBuilder.Clear(); _assignmentBuilder.Clear(); _parseBuilder.Clear(); _names.Clear(); _allNames.Clear(); _types.Clear(); _allTypes.Clear(); _indexs.Clear(); _allIndexs.Clear(); _idDic.Clear(); //_hasSameIds = false; List keyName = new List();//默认用id查询单条数据 List keyType = new List(); Dictionary> keyNames = new Dictionary>(); Dictionary> keyTypes = new Dictionary>(); Dictionary> groupNames = new Dictionary>(); Dictionary> groupTypes = new Dictionary>(); bool groupOnly = false;//可根据id分组时,不提供根据id查询单条数据的接口 int len = worksheet.Dimension.End.Column; if (len <= 0) { return; } worksheet = HandleExcelWorksheet(worksheet); for (int i = 1; i <= len; ++i) { ET.Log.Debug($"GenerateCode for i {i}"); string annotation = worksheet.Cells[1, i].Text.Trim(); string typeWhole = worksheet.Cells[2, i].Text.Trim(); string type = typeWhole.Split('#')[0]; string nameWhole = worksheet.Cells[3, i].Text.Trim(); string[] nameInfos = nameWhole.Split('#', '&');//#和&不会同时存在,即不会将数组用作数据查询的关键字key string name = nameInfos[0]; if (i == 1) { keyName.Add(name); keyType.Add(type); } for (int j = 1; j < nameInfos.Length; j++) { if (nameInfos[j].Contains("k")) { if (!keyNames.ContainsKey(nameInfos[j])) { keyNames.Add(nameInfos[j], new List()); keyTypes.Add(nameInfos[j], new List()); } keyNames[nameInfos[j]].Add(name); keyTypes[nameInfos[j]].Add(type); } if (nameInfos[j].Contains("g")) { if (!groupNames.ContainsKey(nameInfos[j])) { groupNames.Add(nameInfos[j], new List()); groupTypes.Add(nameInfos[j], new List()); } groupNames[nameInfos[j]].Add(name); groupTypes[nameInfos[j]].Add(type); } } foreach (string key in groupNames.Keys) { if (groupNames[key].Count == 1 && groupNames[key][0] == keyName[0]) { groupOnly = true; } } ParseDataColumn(annotation, type, name, nameWhole, typeWhole, i); } //创建sqlite表 SQLiteHelper.Instance.CreateTable(configArrayName, _names.ToArray(), _types.ToArray()); AddDataToSql(worksheet, configName, configArrayName); //生成管理类代码 string configArrayStr = CodeTemplateFactory.ConfigArrayTemplate; _declarationBuilder.AppendFormat("\t\t//{0}", "key"); _declarationBuilder.AppendLine(); _declarationBuilder.AppendFormat("\t\tpublic {0} {1};", "string", "key"); _declarationBuilder.AppendLine(); // _assignmentBuilder.AppendFormat("\t\t\t{0} = \"{1}\";", "key", keyName); // _assignmentBuilder.AppendLine(); foreach (string key in keyNames.Keys) { _declarationBuilder.AppendFormat("\t\t//{0}{1}", "key_", key); _declarationBuilder.AppendLine(); _declarationBuilder.AppendFormat("\t\tpublic {0} {1}{2};", "string", "combinedKey_", key); _declarationBuilder.AppendLine(); } foreach (string key in groupNames.Keys) { _declarationBuilder.AppendFormat("\t\t//{0}{1}", "groupKey_", key); _declarationBuilder.AppendLine(); _declarationBuilder.AppendFormat("\t\tpublic {0} {1}{2};", "string", "groupKey_", key); _declarationBuilder.AppendLine(); } string strDiapose = "_allDatas = null;\n"; string singleFunction = ""; //处理查询单条数据函数 if (!groupOnly) { singleFunction = HandleSingleFunction("key", keyName, keyType, "GetCfg", "_cfgsDic", configArrayStr); strDiapose = string.Format("{0}\t\t\t{1}\n", strDiapose, "_cfgsDic.Clear();"); } foreach (string key in keyNames.Keys) { string functionName = string.Format("GetCfgBy{0}", string.Join("And", keyNames[key])); string cfgsDicName = string.Format("_cfgsDicBy{0}", string.Join("And", keyNames[key])); singleFunction = singleFunction + HandleSingleFunction("combinedKey_" + key, keyNames[key], keyTypes[key], functionName, cfgsDicName, configArrayStr); strDiapose = string.Format("{0}\t\t\t{1}.Clear();\n", strDiapose, cfgsDicName); } configArrayStr = configArrayStr.Replace("{singleFunction}", singleFunction); string groupFunction = ""; //处理查询多条数据函数 if (groupNames.Count > 0) { int index0 = 0; foreach (string key in groupNames.Keys) { string functionName = groupNames.Count == 1 ? "GetCfgs" : string.Format("GetCfgsBy{0}", string.Join("And", groupNames[key])); string cfgsGroupDicName = string.Format("_cfgsGroupDic{0}", index0); groupFunction = groupFunction + HandleGroupFunction("groupKey_" + key, groupNames[key], groupTypes[key], functionName, cfgsGroupDicName, configArrayStr); strDiapose = string.Format("{0}\t\t\t{1}.Clear();", strDiapose, cfgsGroupDicName); index0++; } } configArrayStr = configArrayStr.Replace("{groupFunction}", groupFunction); //处理全部数据函数 string FunctionAllStr = CodeTemplateFactory.FunctionAllTemplate; configArrayStr = configArrayStr.Replace("{allFunction}", FunctionAllStr); configArrayStr = configArrayStr.Replace("{Init}", CodeTemplateFactory.InitTemplate); configArrayStr = configArrayStr.Replace("{Dispose}", CodeTemplateFactory.DisposeTemplate); configArrayStr = configArrayStr.Replace("{StrDiapose}", strDiapose); configArrayStr = configArrayStr.Replace("{editorConditionStart}", ""); configArrayStr = configArrayStr.Replace("{editorConditionEnd}", ""); List singleStrArry = new List(); if (!groupOnly) { string singleStr = CodeTemplateFactory.FunctionAllSingleBlockTemplate; singleStr = singleStr.Replace("{cfgsDicName}", "_cfgsDic"); singleStr = singleStr.Replace("{combinedKey}", "cfg.key"); singleStrArry.Add(singleStr); } foreach (string key in keyNames.Keys) { string cfgsDicName = string.Format("_cfgsDicBy{0}", string.Join("And", keyNames[key])); string singleStr = CodeTemplateFactory.FunctionAllSingleBlockTemplate; singleStr = singleStr.Replace("{cfgsDicName}", cfgsDicName); singleStr = singleStr.Replace("{combinedKey}", "cfg.combinedKey_" + key); singleStrArry.Add(singleStr); } string singleStrs = string.Join("\n", singleStrArry); List groupStrArry = new List(); int index1 = 0; foreach (string key in groupNames.Keys) { string cfgsDicName = string.Format("_cfgsGroupDic{0}", index1); string singleStr = CodeTemplateFactory.FunctionAllGroupBlockTemplate; singleStr = singleStr.Replace("{cfgsGroupDicName}", cfgsDicName); singleStr = singleStr.Replace("{groupKey}", "cfg.groupKey_" + key); singleStr = singleStr.Replace("{list}", "list" + index1); groupStrArry.Add(singleStr); index1++; } string groupStrs = string.Join("\n", groupStrArry); configArrayStr = configArrayStr.Replace("{FunctionAllBlock}", singleStrs + "\n" + groupStrs); // foreach() //名称处理 configArrayStr = configArrayStr.Replace("{CfgName}", configName); configArrayStr = configArrayStr.Replace("{CfgArrayName}", configArrayName); //生成反序列化代码 string configStr = CodeTemplateFactory.ConfigTemplate.Replace("{CfgName}", configName); configStr = configStr.Replace("{variable declaration}", _declarationBuilder.ToString()); configStr = configStr.Replace("{variable assignment}", _assignmentBuilder.ToString()); configStr = configStr.Replace("{variable parse}", _parseBuilder.ToString()); //创建配置项类代码 using (StreamWriter sw = new StreamWriter(ExcelConfig.configCodePath + configName + ".cs")) { sw.Write(configStr); } //创建管理类代码 using (StreamWriter sw = new StreamWriter(ExcelConfig.configArrayCodePath + configArrayName + ".cs")) { sw.Write(configArrayStr); } Debug.LogFormat("生成{0}", configName); } private static string HandleSingleFunction(string key, List keyNames, List keyTypes, string functionName, string cfgsDicName, string configArrayStr) { string FunctionSingleStr = CodeTemplateFactory.FunctionSingleTemplate; CreateParamsString(keyNames, keyTypes, out string paramsStr, out string colNames, out string colValues); FunctionSingleStr = FunctionSingleStr.Replace("{params}", paramsStr); FunctionSingleStr = FunctionSingleStr.Replace("{colNames}", colNames); FunctionSingleStr = FunctionSingleStr.Replace("{colValues}", colValues); FunctionSingleStr = FunctionSingleStr.Replace("{FunctionName}", functionName); FunctionSingleStr = FunctionSingleStr.Replace("{cfgsDicName}", cfgsDicName); _assignmentBuilder.AppendFormat("\t\t\t{0} = \"{1}\";", key, string.Join("_", keyNames)); _assignmentBuilder.AppendLine(); return FunctionSingleStr; } private static string HandleGroupFunction(string key, List groupNames, List groupTypes, string functionName, string cfgsGroupDicName, string configArrayStr) { string FunctionGroupStr = CodeTemplateFactory.FunctionGroupTemplate; CreateParamsString(groupNames, groupTypes, out string paramsStr, out string colNames, out string colValues); FunctionGroupStr = FunctionGroupStr.Replace("{params}", paramsStr); FunctionGroupStr = FunctionGroupStr.Replace("{colNames}", colNames); FunctionGroupStr = FunctionGroupStr.Replace("{colValues}", colValues); FunctionGroupStr = FunctionGroupStr.Replace("{FunctionName}", functionName); FunctionGroupStr = FunctionGroupStr.Replace("{cfgsGroupDicName}", cfgsGroupDicName); _assignmentBuilder.AppendFormat("\t\t\t{0} = \"{1}\";", key, string.Join("_", groupNames)); _assignmentBuilder.AppendLine(); return FunctionGroupStr; } private static void ParseDataColumn(string annotation, string type, string name, string nameWhole, string typeWhole, int index) { if (type.Length > 0 && name.Length > 0) { _allNames.Add(nameWhole); _allTypes.Add(typeWhole); _allIndexs.Add(index); if (_names.IndexOf(SQL_PREFIX + name) >= 0) return; _names.Add(SQL_PREFIX + name); _types.Add("TEXT"); _indexs.Add(index); //生成解析后的数据变量 _declarationBuilder.AppendFormat("\t\t//{0}", annotation.Split('#')[0]); _declarationBuilder.AppendLine(); if (type.Contains("[]")) { //_declarationBuilder.AppendFormat("\t\tpublic {0} {1};", "string", tempName); //_declarationBuilder.AppendLine(); //_declarationBuilder.AppendLine("\t\t[NonSerialized]"); _declarationBuilder.AppendFormat("\t\tpublic {0} {1}Arr;", type, name); _declarationBuilder.AppendLine(); } else { _declarationBuilder.AppendFormat("\t\tpublic {0} {1};", type, name); _declarationBuilder.AppendLine(); } //添加解析代码 if (type == "int") { //_assignmentBuilder.AppendFormat("\t\t\t{0} = ConfigUtil.GetInt(0, dataRow, {1});", name, index); _assignmentBuilder.AppendFormat("\t\t\t{0} = ConfigUtil.GetInt(reader.GetString(reader.GetOrdinal(\"_{1}\")));", name, name); _assignmentBuilder.AppendLine(); } else if (type == "float") { _assignmentBuilder.AppendFormat("\t\t\t{0} = ConfigUtil.GetFloat(reader.GetString(reader.GetOrdinal(\"_{1}\")));", name, name); _assignmentBuilder.AppendLine(); } else if (type == "string") { _assignmentBuilder.AppendFormat("\t\t\t{0} = reader.GetString(reader.GetOrdinal(\"_{1}\"));", name, name); _assignmentBuilder.AppendLine(); } else { _assignmentBuilder.AppendFormat("\t\t\tvar temp{0} = reader.GetString(reader.GetOrdinal(\"_{1}\"));", name, name); _assignmentBuilder.AppendLine(); if (type.Contains("[][]")) { string subType = type.Replace("[][]", ""); _assignmentBuilder.AppendFormat("\t\t\t{0}Arr = ConfigUtil.GetTwoDimensionalArr<{1}>(temp{2});", name, subType, name); _assignmentBuilder.AppendLine(); } else if (type.Contains("[]")) { string subType = type.Replace("[]", ""); _assignmentBuilder.AppendFormat("\t\t\t{0}Arr = ConfigUtil.GetLinearArr<{1}>(temp{2});", name, subType, name); _assignmentBuilder.AppendLine(); } } } } private static ExcelWorksheet HandleExcelWorksheet(ExcelWorksheet worksheet) { return worksheet; } private static void AddDataToSql(ExcelWorksheet worksheet, string configName, string configArrayName) { int rowNum = worksheet.Dimension.End.Row; for (int i = 5; i <= rowNum; i++) { string key = worksheet.Cells[i, 1].Text.Trim(); if (key.Length == 0) { continue; } //解析每行的数据 WriteRowDataToSqlite(worksheet.Cells, configArrayName, i); if (_idDic.ContainsKey(key)) { //_hasSameIds = true; } else { _idDic[key] = key; } } } private static void WriteRowDataToSqlite(ExcelRange worksheet, string configArrayName, int row) { List values = new List(); var keyValue = worksheet[row, 1].Text.Trim(); foreach (var i in _indexs) { if (configArrayName == "GiftBagCfgArray") { Debug.Log("zoya"); } var fieldName = _allNames[i - 1]; var name = fieldName.Split('#')[0]; var value = worksheet[row, i].Text.Trim(); if (configArrayName == nameof(ItemTypeCfgArray) && name == "name") { CacheItemTypeByName(keyValue, name, value); values.Add(value); } else if (configArrayName == nameof(ItemCfgArray) && (name == "itemType" || name == "subType")) { HandleItemCfgField(keyValue, name, ref value); values.Add(value); } else { string _value = GetValue(configArrayName, worksheet, name, row, i); values.Add(_value); } } SQLiteHelper.Instance.InsertValues(configArrayName, values.ToArray()); } private static void CacheItemTypeByName(string idStr, string fieldName, string value) { _itemTypeDicByName[value] = idStr; } private static void HandleItemCfgField(string idStr, string fieldName, ref string value) { // fieldName = fieldName.Substring(1); ET.Log.Debug($"idStr {idStr} fieldName {fieldName} value {value}"); int id = int.Parse(idStr); int itemType = (int)Mathf.Floor(id / GameConst.MAX_COUNT_EVERY_TYPE_ITEM); if (fieldName == "itemType") { if (itemType <= ConstDressUpItemType.MAX) { value = ConstItemType.DRESS_UP.ToString(); } else { value = itemType.ToString(); } } else if (fieldName == "subType") { if (itemType <= ConstDressUpItemType.MAX) { string subType; if (_itemTypeDicByName.TryGetValue(value, out subType)) { value = subType; } else { Debug.LogError($"请检查物品 {idStr} 的subType值"); } } } } private static void CreateParamsString(List keyNames, List keyTypes, out string paramStr, out string colNames, out string colValues) { paramStr = ""; colNames = ""; colValues = ""; for (var i = 0; i < keyNames.Count; i++) { paramStr += keyTypes[i] + " " + keyNames[i]; colNames += $"nameof({keyNames[i]})"; colValues += $"{keyNames[i]}.ToString()"; if (i < keyNames.Count - 1) { paramStr += ", "; colNames += ", "; colValues += ", "; } } } private static string GetValue(string configArrayName, ExcelRange worksheet, string name, int row, int index) { Dictionary> _twoDimensionalDic = new Dictionary>(); string value = ""; // foreach (var i in _allIndexs) // { for (int i = index - 1; i < _allIndexs.Count; i++) { // int _index = i - 1; string _name = _allNames[i]; string[] _names = _name.Split('#'); string _type = _allTypes[i]; string[] _types = _type.Split('#'); string _value = worksheet[row, i + 1].Text.Trim(); if (_names[0] != name) continue; if (_type.Contains("[][]") && _type.Contains("#")) { if (!_twoDimensionalDic.ContainsKey(_types[1]) && string.IsNullOrEmpty(_value)) { break; } if (string.IsNullOrEmpty(_value)) { ET.Log.Error(configArrayName + " 第" + row + "行 " + _type + " 无数值!"); continue; } if (!_twoDimensionalDic.ContainsKey(_types[1])) { _twoDimensionalDic.Add(_types[1], new List()); } _twoDimensionalDic[_types[1]].Add(_value); } else if (_type.Contains("[]") && _type.Contains("#")) { if (string.IsNullOrEmpty(_value)) continue; if (string.IsNullOrEmpty(value)) { value = _value; } else { value = string.Format("{0};{1}", value, _value); } } else { value = _value; break; } } if (_twoDimensionalDic.Count > 0) { List _values = new List(); foreach (string key in _twoDimensionalDic.Keys) { // if (!_twoDimensionalDic[key].ContainsKey(0)) continue; // string _value0 = _twoDimensionalDic[key][0]; // if (!_twoDimensionalDic[key].ContainsKey(1)) // { // _values.Add(_value0); // } // else // { // string str = string.Format("{0}*{1}", _value0, _twoDimensionalDic[key][1]); // _values.Add(str); // } _values.Add(string.Join("*", _twoDimensionalDic[key])); } value = string.Join(";", _values); } return value; } } }