【text】根据本地化 TextTable 对Text作转换

main
walon 2021-06-17 12:51:35 +08:00
parent 35bafee063
commit 97c2342cfc
27 changed files with 503 additions and 207 deletions

View File

@ -23,11 +23,11 @@ namespace Luban.Job.Cfg.Cache
{
public DefTable Table { get; }
public List<DType> Records { get; }
public List<Record> Records { get; }
public volatile int LastAccessTime;
public FileRecordCache(DefTable table, List<DType> records)
public FileRecordCache(DefTable table, List<Record> records)
{
Table = table;
Records = records;
@ -39,7 +39,7 @@ namespace Luban.Job.Cfg.Cache
private readonly object _shrinkLocker = new object();
public bool TryGetCacheLoadedRecords(DefTable table, string md5, string originFile, string sheetName, bool exportTestData, out List<DType> cacheRecords)
public bool TryGetCacheLoadedRecords(DefTable table, string md5, string originFile, string sheetName, bool exportTestData, out List<Record> cacheRecords)
{
// TODO text localization check
cacheRecords = null;
@ -60,7 +60,7 @@ namespace Luban.Job.Cfg.Cache
}
}
public void AddCacheLoadedRecords(DefTable table, string md5, string sheetName, bool exportTestData, List<DType> cacheRecords)
public void AddCacheLoadedRecords(DefTable table, string md5, string sheetName, bool exportTestData, List<Record> cacheRecords)
{
lock (_shrinkLocker)
{

View File

@ -132,12 +132,12 @@ namespace Luban.Job.Cfg.DataSources.Excel
return Titles.TryGetValue(name, out var title) ? title : null;
}
public ExcelStream GetColumn(string name, string sep)
public ExcelStream GetColumn(string name, string sep, bool namedMode)
{
if (Titles.TryGetValue(name, out var title))
{
CheckEmptySinceSecondRow(name, title.FromIndex, title.ToIndex);
var es = new ExcelStream(Rows[0], title.FromIndex, title.ToIndex, sep, true);
var es = new ExcelStream(Rows[0], title.FromIndex, title.ToIndex, sep, namedMode);
return es;
}
else

View File

@ -6,81 +6,90 @@ using System.Collections.Generic;
namespace Luban.Job.Cfg.DataVisitors
{
class BinaryExportor : IDataActionVisitor<ByteBuf>
class BinaryExportor : IDataActionVisitor<DefAssembly, ByteBuf>
{
public static BinaryExportor Ins { get; } = new BinaryExportor();
public void Accept(DBool type, ByteBuf x)
public void WriteList(List<Record> datas, DefAssembly ass, ByteBuf x)
{
x.WriteSize(datas.Count);
foreach (var d in datas)
{
d.Data.Apply(this, ass, x);
}
}
public void Accept(DBool type, DefAssembly ass, ByteBuf x)
{
x.WriteBool(type.Value);
}
public void Accept(DByte type, ByteBuf x)
public void Accept(DByte type, DefAssembly ass, ByteBuf x)
{
x.WriteByte(type.Value);
}
public void Accept(DShort type, ByteBuf x)
public void Accept(DShort type, DefAssembly ass, ByteBuf x)
{
x.WriteShort(type.Value);
}
public void Accept(DFshort type, ByteBuf x)
public void Accept(DFshort type, DefAssembly ass, ByteBuf x)
{
x.WriteFshort(type.Value);
}
public void Accept(DInt type, ByteBuf x)
public void Accept(DInt type, DefAssembly ass, ByteBuf x)
{
x.WriteInt(type.Value);
}
public void Accept(DFint type, ByteBuf x)
public void Accept(DFint type, DefAssembly ass, ByteBuf x)
{
x.WriteFint(type.Value);
}
public void Accept(DLong type, ByteBuf x)
public void Accept(DLong type, DefAssembly ass, ByteBuf x)
{
x.WriteLong(type.Value);
}
public void Accept(DFlong type, ByteBuf x)
public void Accept(DFlong type, DefAssembly ass, ByteBuf x)
{
x.WriteFlong(type.Value);
}
public void Accept(DFloat type, ByteBuf x)
public void Accept(DFloat type, DefAssembly ass, ByteBuf x)
{
x.WriteFloat(type.Value);
}
public void Accept(DDouble type, ByteBuf x)
public void Accept(DDouble type, DefAssembly ass, ByteBuf x)
{
x.WriteDouble(type.Value);
}
public void Accept(DEnum type, ByteBuf x)
public void Accept(DEnum type, DefAssembly ass, ByteBuf x)
{
x.WriteInt(type.Value);
}
public void Accept(DString type, ByteBuf x)
public void Accept(DString type, DefAssembly ass, ByteBuf x)
{
x.WriteString(type.Value);
}
public void Accept(DBytes type, ByteBuf x)
public void Accept(DBytes type, DefAssembly ass, ByteBuf x)
{
x.WriteBytes(type.Value);
}
public void Accept(DText type, ByteBuf x)
public void Accept(DText type, DefAssembly ass, ByteBuf x)
{
x.WriteString(type.Value);
x.WriteString(type.GetText(ass.ExportTextTable, ass.NotConvertTextSet));
}
public void Accept(DBean type, ByteBuf x)
public void Accept(DBean type, DefAssembly ass, ByteBuf x)
{
var bean = type.Type;
if (bean.IsAbstractType)
@ -108,7 +117,7 @@ namespace Luban.Job.Cfg.DataVisitors
if (field != null)
{
x.WriteBool(true);
field.Apply(this, x);
field.Apply(this, ass, x);
}
else
{
@ -117,62 +126,62 @@ namespace Luban.Job.Cfg.DataVisitors
}
else
{
field.Apply(this, x);
field.Apply(this, ass, x);
}
}
}
public void WriteList(List<DType> datas, ByteBuf x)
public void WriteList(List<DType> datas, DefAssembly ass, ByteBuf x)
{
x.WriteSize(datas.Count);
foreach (var d in datas)
{
d.Apply(this, x);
d.Apply(this, ass, x);
}
}
public void Accept(DArray type, ByteBuf x)
public void Accept(DArray type, DefAssembly ass, ByteBuf x)
{
WriteList(type.Datas, x);
WriteList(type.Datas, ass, x);
}
public void Accept(DList type, ByteBuf x)
public void Accept(DList type, DefAssembly ass, ByteBuf x)
{
WriteList(type.Datas, x);
WriteList(type.Datas, ass, x);
}
public void Accept(DSet type, ByteBuf x)
public void Accept(DSet type, DefAssembly ass, ByteBuf x)
{
WriteList(type.Datas, x);
WriteList(type.Datas, ass, x);
}
public void Accept(DMap type, ByteBuf x)
public void Accept(DMap type, DefAssembly ass, ByteBuf x)
{
Dictionary<DType, DType> datas = type.Datas;
x.WriteSize(datas.Count);
foreach (var e in datas)
{
e.Key.Apply(this, x);
e.Value.Apply(this, x);
e.Key.Apply(this, ass, x);
e.Value.Apply(this, ass, x);
}
}
public void Accept(DVector2 type, ByteBuf x)
public void Accept(DVector2 type, DefAssembly ass, ByteBuf x)
{
x.WriteVector2(type.Value);
}
public void Accept(DVector3 type, ByteBuf x)
public void Accept(DVector3 type, DefAssembly ass, ByteBuf x)
{
x.WriteVector3(type.Value);
}
public void Accept(DVector4 type, ByteBuf x)
public void Accept(DVector4 type, DefAssembly ass, ByteBuf x)
{
x.WriteVector4(type.Value);
}
public void Accept(DDateTime type, ByteBuf x)
public void Accept(DDateTime type, DefAssembly ass, ByteBuf x)
{
x.WriteInt(type.UnixTime);
}

View File

@ -75,7 +75,7 @@ namespace Luban.Job.Cfg.DataVisitors
public bool Accept(DText type)
{
return string.IsNullOrEmpty(type.Value);
return string.IsNullOrEmpty(type.Key);
}
public bool Accept(DBean type)

View File

@ -6,81 +6,91 @@ using System.Text.Json;
namespace Luban.Job.Cfg.DataVisitors
{
class JsonExportor : IDataActionVisitor<Utf8JsonWriter>
class JsonExportor : IDataActionVisitor<DefAssembly, Utf8JsonWriter>
{
public static JsonExportor Ins { get; } = new JsonExportor();
public void Accept(DBool type, Utf8JsonWriter x)
public void WriteList(List<Record> datas, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStartArray();
foreach (var d in datas)
{
d.Data.Apply(this, ass, x);
}
x.WriteEndArray();
}
public void Accept(DBool type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteBooleanValue(type.Value);
}
public void Accept(DByte type, Utf8JsonWriter x)
public void Accept(DByte type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DShort type, Utf8JsonWriter x)
public void Accept(DShort type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DFshort type, Utf8JsonWriter x)
public void Accept(DFshort type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DInt type, Utf8JsonWriter x)
public void Accept(DInt type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DFint type, Utf8JsonWriter x)
public void Accept(DFint type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DLong type, Utf8JsonWriter x)
public void Accept(DLong type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DFlong type, Utf8JsonWriter x)
public void Accept(DFlong type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DFloat type, Utf8JsonWriter x)
public void Accept(DFloat type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DDouble type, Utf8JsonWriter x)
public void Accept(DDouble type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DEnum type, Utf8JsonWriter x)
public void Accept(DEnum type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.Value);
}
public void Accept(DString type, Utf8JsonWriter x)
public void Accept(DString type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStringValue(type.Value);
}
public void Accept(DBytes type, Utf8JsonWriter x)
public void Accept(DBytes type, DefAssembly ass, Utf8JsonWriter x)
{
throw new NotImplementedException();
}
public void Accept(DText type, Utf8JsonWriter x)
public void Accept(DText type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStringValue(type.Value);
x.WriteStringValue(type.GetText(ass.ExportTextTable, ass.NotConvertTextSet));
}
public void Accept(DBean type, Utf8JsonWriter x)
public void Accept(DBean type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStartObject();
@ -108,51 +118,51 @@ namespace Luban.Job.Cfg.DataVisitors
}
else
{
d.Apply(this, x);
d.Apply(this, ass, x);
}
}
x.WriteEndObject();
}
public void WriteList(List<DType> datas, Utf8JsonWriter x)
public void WriteList(List<DType> datas, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStartArray();
foreach (var d in datas)
{
d.Apply(this, x);
d.Apply(this, ass, x);
}
x.WriteEndArray();
}
public void Accept(DArray type, Utf8JsonWriter x)
public void Accept(DArray type, DefAssembly ass, Utf8JsonWriter x)
{
WriteList(type.Datas, x);
WriteList(type.Datas, ass, x);
}
public void Accept(DList type, Utf8JsonWriter x)
public void Accept(DList type, DefAssembly ass, Utf8JsonWriter x)
{
WriteList(type.Datas, x);
WriteList(type.Datas, ass, x);
}
public void Accept(DSet type, Utf8JsonWriter x)
public void Accept(DSet type, DefAssembly ass, Utf8JsonWriter x)
{
WriteList(type.Datas, x);
WriteList(type.Datas, ass, x);
}
public void Accept(DMap type, Utf8JsonWriter x)
public void Accept(DMap type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStartArray();
foreach (var d in type.Datas)
{
x.WriteStartArray();
d.Key.Apply(this, x);
d.Value.Apply(this, x);
d.Key.Apply(this, ass, x);
d.Value.Apply(this, ass, x);
x.WriteEndArray();
}
x.WriteEndArray();
}
public void Accept(DVector2 type, Utf8JsonWriter x)
public void Accept(DVector2 type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStartObject();
x.WriteNumber("x", type.Value.X);
@ -160,7 +170,7 @@ namespace Luban.Job.Cfg.DataVisitors
x.WriteEndObject();
}
public void Accept(DVector3 type, Utf8JsonWriter x)
public void Accept(DVector3 type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStartObject();
x.WriteNumber("x", type.Value.X);
@ -169,7 +179,7 @@ namespace Luban.Job.Cfg.DataVisitors
x.WriteEndObject();
}
public void Accept(DVector4 type, Utf8JsonWriter x)
public void Accept(DVector4 type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteStartObject();
x.WriteNumber("x", type.Value.X);
@ -179,7 +189,7 @@ namespace Luban.Job.Cfg.DataVisitors
x.WriteEndObject();
}
public void Accept(DDateTime type, Utf8JsonWriter x)
public void Accept(DDateTime type, DefAssembly ass, Utf8JsonWriter x)
{
x.WriteNumberValue(type.UnixTime);
}

View File

@ -7,52 +7,54 @@ using System.Text;
namespace Luban.Job.Cfg.DataVisitors
{
class LuaExportor : IDataActionVisitor<StringBuilder>
class LuaExportor : IDataActionVisitor<DefAssembly, StringBuilder>
{
public static LuaExportor Ins { get; } = new LuaExportor();
public void ExportTableOne(DefTable t, List<DType> records, List<string> result)
public void ExportTableOne(DefTable t, List<Record> records, List<string> result)
{
result.Add("return ");
var s = new StringBuilder();
Accept((DBean)records[0], s);
Accept(records[0].Data, t.Assembly, s);
result.Add(s.ToString());
}
public void ExportTableOneKeyMap(DefTable t, List<DType> records, List<string> result)
public void ExportTableOneKeyMap(DefTable t, List<Record> records, List<string> result)
{
result.Add("return ");
result.Add("{");
var s = new StringBuilder();
var ks = new StringBuilder();
foreach (DBean r in records)
foreach (Record r in records)
{
DBean d = r.Data;
s.Clear();
s.Append($"[{ToLuaCodeString(r.GetField(t.Index), ks)}] = ");
Accept(r, s);
s.Append($"[{ToLuaCodeString(d.GetField(t.Index), t.Assembly, ks)}] = ");
Accept(d, t.Assembly, s);
s.Append(',');
result.Add(s.ToString());
}
result.Add("}");
}
public void ExportTableTwoKeyMap(DefTable t, List<DType> records, List<string> result)
public void ExportTableTwoKeyMap(DefTable t, List<Record> records, List<string> result)
{
result.Add("return ");
result.Add("{");
var s = new StringBuilder();
var ks = new StringBuilder();
foreach (var g in records.GroupBy(r => ((DBean)r).GetField(t.Index1)))
foreach (var g in records.GroupBy(r => r.Data.GetField(t.Index1)))
{
result.Add($"[{ToLuaCodeString(g.Key, ks)}] =");
result.Add($"[{ToLuaCodeString(g.Key, t.Assembly, ks)}] =");
result.Add("{");
foreach (DBean r in g)
foreach (Record r in g)
{
DBean d = r.Data;
s.Clear();
s.Append($"[{ToLuaCodeString(r.GetField(t.Index2), ks)}] = ");
Accept(r, s);
s.Append($"[{ToLuaCodeString(d.GetField(t.Index2), t.Assembly, ks)}] = ");
Accept(d, t.Assembly, s);
s.Append(',');
result.Add(s.ToString());
}
@ -63,64 +65,64 @@ namespace Luban.Job.Cfg.DataVisitors
result.Add("}");
}
private string ToLuaCodeString(DType data, StringBuilder b)
private string ToLuaCodeString(DType data, DefAssembly ass, StringBuilder b)
{
b.Clear();
data.Apply(this, b);
data.Apply(this, ass, b);
return b.ToString();
}
public void Accept(DBool type, StringBuilder line)
public void Accept(DBool type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value ? "true" : "false");
}
public void Accept(DByte type, StringBuilder line)
public void Accept(DByte type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DShort type, StringBuilder line)
public void Accept(DShort type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DFshort type, StringBuilder line)
public void Accept(DFshort type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DInt type, StringBuilder line)
public void Accept(DInt type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DFint type, StringBuilder line)
public void Accept(DFint type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DLong type, StringBuilder line)
public void Accept(DLong type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DFlong type, StringBuilder line)
public void Accept(DFlong type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DFloat type, StringBuilder line)
public void Accept(DFloat type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DDouble type, StringBuilder line)
public void Accept(DDouble type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
public void Accept(DEnum type, StringBuilder line)
public void Accept(DEnum type, DefAssembly ass, StringBuilder line)
{
line.Append(type.Value);
}
@ -130,22 +132,22 @@ namespace Luban.Job.Cfg.DataVisitors
return s.Replace("\\", "\\\\").Replace("'", "\\'");
}
public void Accept(DString type, StringBuilder line)
public void Accept(DString type, DefAssembly ass, StringBuilder line)
{
line.Append('\'').Append(EscapeString(type.Value)).Append('\'');
}
public void Accept(DBytes type, StringBuilder line)
public void Accept(DBytes type, DefAssembly ass, StringBuilder line)
{
throw new NotImplementedException();
}
public void Accept(DText type, StringBuilder line)
public void Accept(DText type, DefAssembly ass, StringBuilder line)
{
line.Append('\'').Append(EscapeString(type.Value)).Append('\'');
line.Append('\'').Append(EscapeString(type.GetText(ass.ExportTextTable, ass.NotConvertTextSet))).Append('\'');
}
public void Accept(DBean type, StringBuilder line)
public void Accept(DBean type, DefAssembly ass, StringBuilder line)
{
var bean = type.Type;
if (bean.IsAbstractType)
@ -174,76 +176,76 @@ namespace Luban.Job.Cfg.DataVisitors
if (field != null)
{
line.Append(defField.Name).Append('=');
field.Apply(this, line);
field.Apply(this, ass, line);
line.Append(',');
}
}
line.Append("}");
}
public void Accept(DArray type, StringBuilder line)
public void Accept(DArray type, DefAssembly ass, StringBuilder line)
{
line.Append('{');
foreach (var d in type.Datas)
{
d.Apply(this, line);
d.Apply(this, ass, line);
line.Append(',');
}
line.Append('}');
}
public void Accept(DList type, StringBuilder line)
public void Accept(DList type, DefAssembly ass, StringBuilder line)
{
line.Append('{');
foreach (var d in type.Datas)
{
d.Apply(this, line);
d.Apply(this, ass, line);
line.Append(',');
}
line.Append('}');
}
public void Accept(DSet type, StringBuilder line)
public void Accept(DSet type, DefAssembly ass, StringBuilder line)
{
line.Append('{');
foreach (var d in type.Datas)
{
d.Apply(this, line);
d.Apply(this, ass, line);
line.Append(',');
}
line.Append('}');
}
public void Accept(DMap type, StringBuilder line)
public void Accept(DMap type, DefAssembly ass, StringBuilder line)
{
line.Append('{');
foreach ((var k, var v) in type.Datas)
{
line.Append('[');
k.Apply(this, line);
k.Apply(this, ass, line);
line.Append("]=");
v.Apply(this, line);
v.Apply(this, ass, line);
line.Append(',');
}
line.Append('}');
}
public void Accept(DVector2 type, StringBuilder line)
public void Accept(DVector2 type, DefAssembly ass, StringBuilder line)
{
line.Append($"{{x={type.Value.X},y={type.Value.Y}}}");
}
public void Accept(DVector3 type, StringBuilder line)
public void Accept(DVector3 type, DefAssembly ass, StringBuilder line)
{
line.Append($"{{x={type.Value.X},y={type.Value.Y},z={type.Value.Z}}}");
}
public void Accept(DVector4 type, StringBuilder line)
public void Accept(DVector4 type, DefAssembly ass, StringBuilder line)
{
line.Append($"{{x={type.Value.X},y={type.Value.Y},z={type.Value.Z},w={type.Value.W}}}");
}
public void Accept(DDateTime type, StringBuilder line)
public void Accept(DDateTime type, DefAssembly ass, StringBuilder line)
{
line.Append(type.UnixTime);
}

View File

@ -0,0 +1,135 @@
using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.Defs;
using Luban.Job.Cfg.i10n;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.DataVisitors
{
/// <summary>
/// 检查 相同key的text,原始值必须相同
/// </summary>
class TextValidatorVisitor : IDataActionVisitor<RawTextTable>
{
public static TextValidatorVisitor Ins { get; } = new TextValidatorVisitor();
public void Accept(DBool type, RawTextTable x)
{
}
public void Accept(DByte type, RawTextTable x)
{
}
public void Accept(DShort type, RawTextTable x)
{
}
public void Accept(DFshort type, RawTextTable x)
{
}
public void Accept(DInt type, RawTextTable x)
{
}
public void Accept(DFint type, RawTextTable x)
{
}
public void Accept(DLong type, RawTextTable x)
{
}
public void Accept(DFlong type, RawTextTable x)
{
}
public void Accept(DFloat type, RawTextTable x)
{
}
public void Accept(DDouble type, RawTextTable x)
{
}
public void Accept(DEnum type, RawTextTable x)
{
}
public void Accept(DString type, RawTextTable x)
{
}
public void Accept(DBytes type, RawTextTable x)
{
}
public void Accept(DText type, RawTextTable x)
{
x.AddText(ValidatorContext.CurrentVisitor.CurrentValidateRecord, type.Key, type.RawValue);
}
public void Accept(DBean type, RawTextTable x)
{
}
public void Accept(DArray type, RawTextTable x)
{
}
public void Accept(DList type, RawTextTable x)
{
}
public void Accept(DSet type, RawTextTable x)
{
}
public void Accept(DMap type, RawTextTable x)
{
}
public void Accept(DVector2 type, RawTextTable x)
{
}
public void Accept(DVector3 type, RawTextTable x)
{
}
public void Accept(DVector4 type, RawTextTable x)
{
}
public void Accept(DDateTime type, RawTextTable x)
{
}
}
}

View File

@ -75,7 +75,7 @@ namespace Luban.Job.Cfg.DataVisitors
public void Accept(DText type, StringBuilder x)
{
x.Append(type.Value);
x.Append(type.Key).Append('|').Append(type.RawValue);
}
public void Accept(DBean type, StringBuilder x)

View File

@ -7,8 +7,6 @@ using System.Collections.Generic;
namespace Luban.Job.Cfg.DataVisitors
{
public class ValidatorVisitor : IDataActionVisitor<DefAssembly>
{
private readonly Stack<object> _path = new Stack<object>();
@ -17,33 +15,34 @@ namespace Luban.Job.Cfg.DataVisitors
public ValidatorContext Ctx { get; }
public DBean CurrentValidateRecord { get; private set; }
public Record CurrentValidateRecord { get; set; }
public ValidatorVisitor(ValidatorContext ctx)
{
Ctx = ctx;
}
public void ValidateTable(DefTable table, List<DType> records)
public void ValidateTable(DefTable table, List<Record> records)
{
DefAssembly ass = table.Assembly;
var keyIndex = table.IndexFieldIdIndex;
foreach (DBean r in records)
foreach (Record r in records)
{
CurrentValidateRecord = r;
DBean data = r.Data;
_path.Clear();
_path.Push(table.FullName);
if (table.IsMapTable)
{
_path.Push(r.Fields[keyIndex]);
_path.Push(data.Fields[keyIndex]);
}
else if (table.IsTwoKeyMapTable)
{
_path.Push(r.Fields[keyIndex]);
_path.Push(r.Fields[table.IndexFieldIdIndex2]);
_path.Push(data.Fields[keyIndex]);
_path.Push(data.Fields[table.IndexFieldIdIndex2]);
}
Accept(r, ass);
Accept(data, ass);
}
}

View File

@ -1,16 +1,37 @@
using Luban.Job.Cfg.DataVisitors;
using Luban.Job.Cfg.i10n;
using System.Collections.Generic;
namespace Luban.Job.Cfg.Datas
{
public class DText : DType<string>
public class DText : DType
{
public string Key { get; }
public DText(string key, string x) : base(x)
private readonly string _rawValue;
public string RawValue => _rawValue;
public DText(string key, string x)
{
Key = key;
_rawValue = x;
}
System.Console.WriteLine("== text. key:{0} text:{1}", key, x);
public string GetText(TextTable stringTable, NotConvertTextSet notConvertKeys)
{
if (stringTable != null)
{
if (stringTable.TryGetText(Key, out var text))
{
return text;
}
else if (notConvertKeys != null)
{
notConvertKeys.Add(Key, _rawValue);
}
}
return _rawValue;
}
public override void Apply<T>(IDataActionVisitor<T> visitor, T x)
@ -35,12 +56,12 @@ namespace Luban.Job.Cfg.Datas
public override bool Equals(object obj)
{
return obj is DText o && o.Value == this.Value;
return obj is DText o && o._rawValue == this._rawValue && o.Key == this.Key;
}
public override int GetHashCode()
{
return Value.GetHashCode();
return _rawValue.GetHashCode();
}
}
}

View File

@ -20,11 +20,6 @@ namespace Luban.Job.Cfg.Datas
this.Apply(ToStringVisitor.Ins, s);
return s.ToString();
}
/// <summary>
/// 从哪儿创建的. 一般来说会保存它的源文件
/// </summary>
public object Source { get; set; }
}
public abstract class DType<T> : DType

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.Datas
{
public class Record
{
public DBean Data { get; }
public string Source { get; }
public Record(DBean data, string source)
{
Data = data;
Source = source;
}
}
}

View File

@ -1,5 +1,6 @@
using Luban.Config.Common.RawDefs;
using Luban.Job.Cfg.Datas;
using Luban.Job.Cfg.i10n;
using Luban.Job.Cfg.TypeVisitors;
using Luban.Job.Common.Defs;
using Luban.Server.Common;
@ -34,12 +35,16 @@ namespace Luban.Job.Cfg.Defs
private readonly List<Service> _cfgServices = new List<Service>();
private readonly ConcurrentDictionary<string, List<DType>> _recordsByTables = new ConcurrentDictionary<string, List<DType>>();
private readonly ConcurrentDictionary<string, Dictionary<DType, DBean>> _recordsMapByTables = new ConcurrentDictionary<string, Dictionary<DType, DBean>>();
private readonly ConcurrentDictionary<string, List<Record>> _recordsByTables = new();
private readonly ConcurrentDictionary<string, Dictionary<DType, Record>> _recordsMapByTables = new();
public Dictionary<string, DefTable> CfgTables { get; } = new Dictionary<string, DefTable>();
private readonly ConcurrentDictionary<string, string> _texts = new ConcurrentDictionary<string, string>();
public RawTextTable RawTextTable { get; } = new RawTextTable();
public TextTable ExportTextTable { get; } = new TextTable();
public NotConvertTextSet NotConvertTextSet { get; } = new NotConvertTextSet();
public void AddCfgTable(DefTable table)
{
@ -54,22 +59,22 @@ namespace Luban.Job.Cfg.Defs
return CfgTables.TryGetValue(name, out var t) ? t : null;
}
public void AddDataTable(DefTable table, List<DType> records)
public void AddDataTable(DefTable table, List<Record> records)
{
_recordsByTables[table.FullName] = records;
}
public void SetDataTableMap(DefTable table, Dictionary<DType, DBean> recordMap)
public void SetDataTableMap(DefTable table, Dictionary<DType, Record> recordMap)
{
_recordsMapByTables[table.FullName] = recordMap;
}
public List<DType> GetTableDataList(DefTable table)
public List<Record> GetTableDataList(DefTable table)
{
return _recordsByTables[table.FullName];
}
public Dictionary<DType, DBean> GetTableDataMap(DefTable table)
public Dictionary<DType, Record> GetTableDataMap(DefTable table)
{
return _recordsMapByTables[table.FullName];
}
@ -111,22 +116,6 @@ namespace Luban.Job.Cfg.Defs
return refTypes.Values.ToList();
}
public void AddText(string key, string text)
{
if (key == null || text == null)
{
throw new Exception("text的key或text属性不能为null");
}
if (key == "" && text != "")
{
throw new InvalidExcelDataException($"text key为空, 但text:{text}不为空");
}
if (!_texts.TryAdd(key, text) && _texts[key] != text)
{
throw new Exception($"text key:{key} 出现多次,但值不相同. 当前:{text} 之前:{_texts[key]}");
}
}
public void Load(string outputService, Defines defines, RemoteAgent agent)
{
this.Agent = agent;

View File

@ -1089,26 +1089,27 @@ class Vector4:
return index >= 0 ? file[(index + 1)..] : file;
}
private List<DType> LoadCfgRecords(DefTable table, string originFile, string sheetName, byte[] content, bool multiRecord, bool exportTestData)
private List<Record> LoadCfgRecords(DefTable table, string originFile, string sheetName, byte[] content, bool multiRecord, bool exportTestData)
{
// (md5,sheet,multiRecord,exportTestData) -> (valuetype, List<(datas)>)
var dataSourc = DataSourceFactory.Create(originFile, sheetName, new MemoryStream(content), exportTestData);
var dataSource = DataSourceFactory.Create(originFile, sheetName, new MemoryStream(content), exportTestData);
try
{
List<DType> datas;
if (multiRecord)
{
datas = dataSourc.ReadMulti(table.ValueTType);
datas = dataSource.ReadMulti(table.ValueTType);
}
else
{
datas = new List<DType> { dataSourc.ReadOne(table.ValueTType) };
datas = new List<DType> { dataSource.ReadOne(table.ValueTType) };
}
var records = new List<Record>(datas.Count);
foreach (var data in datas)
{
data.Source = originFile;
records.Add(new Record((DBean)data, originFile));
}
return datas;
return records;
}
catch (Exception e)
{
@ -1163,7 +1164,7 @@ class Vector4:
public async Task LoadTableAsync(RemoteAgent agent, DefTable table, string dataDir, bool exportTestData)
{
var tasks = new List<Task<List<DType>>>();
var tasks = new List<Task<List<Record>>>();
var inputFiles = await CollectInputFilesAsync(agent, table, dataDir);
@ -1194,7 +1195,7 @@ class Vector4:
}));
}
var records = new List<DType>(tasks.Count);
var records = new List<Record>(tasks.Count);
foreach (var task in tasks)
{
records.AddRange(await task);
@ -1207,14 +1208,14 @@ class Vector4:
s_logger.Trace("table:{name} record num:{num}", table.FullName, records.Count);
}
private byte[] ToOutputData(DefTable table, List<DType> records, string dataType)
private byte[] ToOutputData(DefTable table, List<Record> records, string dataType)
{
switch (dataType)
{
case "data_bin":
{
var buf = ThreadLocalTemporalByteBufPool.Alloc(1024 * 1024);
BinaryExportor.Ins.WriteList(records, buf);
BinaryExportor.Ins.WriteList(records, table.Assembly, buf);
var bytes = buf.CopyData();
ThreadLocalTemporalByteBufPool.Free(buf);
return bytes;
@ -1228,7 +1229,7 @@ class Vector4:
SkipValidation = false,
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(System.Text.Unicode.UnicodeRanges.All),
});
JsonExportor.Ins.WriteList(records, jsonWriter);
JsonExportor.Ins.WriteList(records, table.Assembly, jsonWriter);
jsonWriter.Flush();
return DataUtil.StreamToBytes(ss);
}
@ -1267,12 +1268,12 @@ class Vector4:
}
}
private List<ResourceInfo> ExportResourceList(List<DType> records)
private List<ResourceInfo> ExportResourceList(List<Record> records)
{
var resList = new List<ResourceInfo>();
foreach (DBean res in records)
foreach (Record res in records)
{
ResourceExportor.Ins.Accept(res, null, resList);
ResourceExportor.Ins.Accept(res.Data, null, resList);
}
return resList;
}

View File

@ -291,7 +291,7 @@ namespace Luban.Job.Cfg.TypeVisitors
}
string key = ParseString(x.Read(x.NamedMode));
string text = ParseString(x.Read(x.NamedMode));
ass.AddText(key, text);
DataUtil.ValidateText(key, text);
return new DText(key, text);
}

View File

@ -160,7 +160,7 @@ namespace Luban.Job.Cfg.TypeVisitors
}
else
{
ExcelStream stream = row.GetColumn(f.Name, sep);
ExcelStream stream = row.GetColumn(f.Name, sep, !f.CType.Apply(IsMultiData.Ins));
try
{
list.Add(f.CType.Apply(ExcelDataCreator.Ins, f.Remapper, stream, (DefAssembly)bean.AssemblyBase));
@ -180,7 +180,7 @@ namespace Luban.Job.Cfg.TypeVisitors
var originBean = (DefBean)type.Bean;
if (originBean.IsAbstractType)
{
string subType = row.GetColumn(DefBean.TYPE_NAME_KEY, null).Read().ToString().Trim();
string subType = row.GetColumn(DefBean.TYPE_NAME_KEY, null, true).Read().ToString().Trim();
if (subType.ToLower() == "null")
{
return new DBean(originBean, null, null);

View File

@ -100,7 +100,7 @@ namespace Luban.Job.Cfg.TypeVisitors
throw new Exception("text text不是字符串");
}
ass.AddText(key, text);
DataUtil.ValidateText(key, text);
return new DText(key, text);
}

View File

@ -140,7 +140,7 @@ namespace Luban.Job.Cfg.TypeVisitors
{
throw new Exception("text缺失text属性");
}
ass.AddText(key, text);
DataUtil.ValidateText(key, text);
return new DText(key, text);
}

View File

@ -84,7 +84,7 @@ namespace Luban.Job.Cfg.TypeVisitors
{
var key = x.Element("key").Value;
var text = x.Element("text").Value;
ass.AddText(key, text);
DataUtil.ValidateText(key, text);
return new DText(key, text);
}
@ -102,15 +102,11 @@ namespace Luban.Job.Cfg.TypeVisitors
}
var fullName = TypeUtil.MakeFullName(bean.Namespace, subType);
var defType = (DefBean)bean.GetNotAbstractChildType(subType);
if (defType == null)
{
throw new Exception($"type:{fullName} 不是合法类型");
}
//if (defType.IsAbstractType)
//{
// throw new Exception($"type:{fullName} 是抽象类. 不能创建实例");
//}
implBean = defType;
implBean = defType ?? throw new Exception($"type:{fullName} 不是合法类型");
}
else
{

View File

@ -59,11 +59,6 @@ namespace Luban.Job.Cfg.Utils
return bytes;
}
public static string GetSourceFile(DType data)
{
return (string)data.Source;
}
public static string UnEscapeString(string s)
{
if (s == "null" || s == "\"\"")
@ -83,6 +78,18 @@ namespace Luban.Job.Cfg.Utils
return (keyAndText[0], keyAndText[1]);
}
public static void ValidateText(string key, string text)
{
if (key == null || text == null)
{
throw new Exception("text的key或text属性不能为null");
}
if (key == "" && text != "")
{
throw new Exception($"text key为空, 但text:{text}不为空");
}
}
//public static string Data2String(DType data)
//{
// var s = new StringBuilder();

View File

@ -69,6 +69,7 @@ namespace Luban.Job.Cfg
{
var records = t.Assembly.GetTableDataList(t);
ValidateTableModeIndex(t, records);
}));
}
await Task.WhenAll(tasks);
@ -86,6 +87,7 @@ namespace Luban.Job.Cfg
{
CurrentVisitor = visitor;
visitor.ValidateTable(t, records);
ValidateText(t, records);
}
finally
{
@ -102,6 +104,16 @@ namespace Luban.Job.Cfg
}
}
private void ValidateText(DefTable table, List<Record> records)
{
foreach (var r in records)
{
CurrentVisitor.CurrentValidateRecord = r;
r.Data.Apply(TextValidatorVisitor.Ins, this.Assembly.RawTextTable);
}
CurrentVisitor.CurrentValidateRecord = null;
}
private async Task ValidatePaths()
{
var queryFiles = new HashSet<string>(_pathQuerys.Count * 2);
@ -160,9 +172,9 @@ namespace Luban.Job.Cfg
}
}
private void ValidateTableModeIndex(DefTable table, List<DType> records)
private void ValidateTableModeIndex(DefTable table, List<Record> records)
{
var recordMap = new Dictionary<DType, DBean>();
var recordMap = new Dictionary<DType, Record>();
switch (table.Mode)
{
@ -176,14 +188,14 @@ namespace Luban.Job.Cfg
}
case ETableMode.MAP:
{
foreach (DBean r in records)
foreach (Record r in records)
{
DType key = r.Fields[table.IndexFieldIdIndex];
DType key = r.Data.Fields[table.IndexFieldIdIndex];
if (!recordMap.TryAdd(key, r))
{
throw new Exception($@"配置表 {table.FullName} 主键字段:{table.Index} 主键值:{key} 重复.
1 :{DataUtil.GetSourceFile(r)}
2 :{DataUtil.GetSourceFile(recordMap[key])}
1 :{r.Source}
2 :{recordMap[key].Source}
");
}
@ -192,16 +204,16 @@ namespace Luban.Job.Cfg
}
case ETableMode.BMAP:
{
var twoKeyMap = new Dictionary<(DType, DType), DBean>();
foreach (DBean r in records)
var twoKeyMap = new Dictionary<(DType, DType), Record>();
foreach (Record r in records)
{
DType key1 = r.Fields[table.IndexFieldIdIndex1];
DType key2 = r.Fields[table.IndexFieldIdIndex2];
DType key1 = r.Data.Fields[table.IndexFieldIdIndex1];
DType key2 = r.Data.Fields[table.IndexFieldIdIndex2];
if (!twoKeyMap.TryAdd((key1, key2), r))
{
throw new Exception($@"配置表 {table.FullName} 主键字段:{table.Index} 主键值:({key1},{key2})重复.
1 :{DataUtil.GetSourceFile(r)}
2 :{DataUtil.GetSourceFile(twoKeyMap[(key1, key2)])}
1 :{r.Source}
2 :{twoKeyMap[(key1, key2)].Source}
");
}
// 目前不支持 双key索引检查,但支持主key索引检查.

View File

@ -175,7 +175,7 @@ namespace Luban.Job.Cfg.Validators
return;
}
string source = DataUtil.GetSourceFile(ValidatorContext.CurrentVisitor.CurrentValidateRecord);
string source = ValidatorContext.CurrentVisitor.CurrentValidateRecord.Source;
object finalPaths = PathPattern.CalcFinalPath(value);
if (finalPaths == null)
{

View File

@ -134,7 +134,7 @@ namespace Luban.Job.Cfg.Validators
return true;
}
public string Source => DataUtil.GetSourceFile(ValidatorContext.CurrentVisitor.CurrentValidateRecord);
public string Source => ValidatorContext.CurrentVisitor.CurrentValidateRecord.Source;
public void Validate(ValidatorContext ctx, DType data, bool nullable)
{

View File

@ -72,7 +72,7 @@ namespace Luban.Job.Cfg.Validators
actualTable = table;
}
DefTable ct = assembly.GetCfgTable(actualTable);
string source = DataUtil.GetSourceFile(ValidatorContext.CurrentVisitor.CurrentValidateRecord);
string source = ValidatorContext.CurrentVisitor.CurrentValidateRecord.Source;
assembly.Agent.Error("记录 {0} = {1} (来自文件:{2}) 在引用表:{3} 中不存在", ValidatorContext.CurrentRecordPath, key, source, table);
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.i10n
{
public class NotConvertTextSet
{
private readonly ConcurrentDictionary<string, string> _notConvertTexts = new();
public void Add(string key, string text)
{
_notConvertTexts.TryAdd(key, text);
}
}
}

View File

@ -0,0 +1,48 @@
using Luban.Job.Cfg.Datas;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.i10n
{
public class RawTextTable
{
private readonly ConcurrentDictionary<string, (Record Record, string Text)> _texts = new();
public void AddText(Record record, string key, string text)
{
if (key == null || text == null)
{
throw new Exception("text的key或text属性不能为null");
}
if (key == "" && text != "")
{
throw new Exception($"text key为空, 但text:{text}不为空");
}
if (!_texts.TryAdd(key, (record, text)) && _texts[key].Text != text)
{
throw new Exception($@"text key:{key} 出现多次,但值不相同.
:{text} :{record.Source}
:{_texts[key].Text} :{_texts[key].Record.Source}");
}
}
public bool TryGetText(string key, out string text)
{
if (_texts.TryGetValue(key, out var e))
{
text = e.Text;
return true;
}
else
{
text = null;
return false;
}
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Luban.Job.Cfg.i10n
{
public class TextTable
{
private readonly Dictionary<string, string> _key2Texts = new();
public TextTable()
{
_key2Texts.Add("test/a", "这是本地化数据 test/a");
_key2Texts.Add("name", "这是本地化数据 name");
}
public void AddText(string key, string text)
{
if (!_key2Texts.TryAdd(key, text))
{
throw new Exception($"text key:{key} 重复");
}
}
public bool TryGetText(string key, out string text)
{
return _key2Texts.TryGetValue(key, out text);
}
}
}