// Indexes attributes. internal void Index() { LevelIndex.Clear(); QualityIndex.Clear(); if (Attributes == null) { return; } foreach (GemAttribute attr in Attributes) { LookupTable levelTable = new LookupTable(); LookupTable qualityTable = new LookupTable(); LookupRanges levelRanges = new LookupRanges(); LookupRanges qualityRanges = new LookupRanges(); LookupGain levelGain = null; LookupGain qualityGain = null; LookupFixed fixedValue = null; foreach (Value value in attr.Values) { // Ignore values which doesn't have required cardinality of attribute. if (value.Cardinality != attr.Cardinality) { continue; } if (value is ValueAt) { ValueAt valueAt = (ValueAt)value; if (valueAt.LevelSpecified) { levelTable.Add(valueAt.Level, valueAt.ToValue()); } else if (valueAt.QualitySpecified) { qualityTable.Add(valueAt.Quality, valueAt.ToValue()); } else { fixedValue = new LookupFixed { Value = valueAt.ToValue() } }; } else if (value is ValueForLevelRange) { ValueForLevelRange range = (ValueForLevelRange)value; levelRanges.Add(range.From, range.To, range.ToValue()); } else if (value is ValueForQualityRange) { ValueForQualityRange range = (ValueForQualityRange)value; qualityRanges.Add(range.From, range.To, range.ToValue()); } else if (value is ValuePerLevel) { levelGain = new LookupGain { From = 2, Value = ((ValuePerLevel)value).ToValue() }; } else // value is ValuePerQuality { qualityGain = new LookupGain { Value = ((ValuePerQuality)value).ToValue() }; } } // Add level dependant attribute to index. // LookupFixed is added to LevelIndex only (due to quality-based attributes not being defined for non-quality gems). LookupBase.Method method = LookupBase.Method.None; if (!levelTable.IsEmpty()) { method |= LookupBase.Method.Table; } if (!levelRanges.IsEmpty()) { method |= LookupBase.Method.Range; } if (levelGain != null) { method |= LookupBase.Method.Gain; } if (fixedValue != null) { method |= LookupBase.Method.Fixed; } if (method != LookupBase.Method.None && method != LookupBase.Method.Table && method != LookupBase.Method.Range && method != LookupBase.Method.Gain && method != LookupBase.Method.Fixed) { LevelIndex.Add(attr.Name, new LookupMixed { Table = method.HasFlag(LookupBase.Method.Table) ? levelTable : null, Ranges = method.HasFlag(LookupBase.Method.Range) ? levelRanges : null, Gain = method.HasFlag(LookupBase.Method.Gain) ? levelGain : null, Fixed = method.HasFlag(LookupBase.Method.Fixed) ? fixedValue : null }); } else if (method.HasFlag(LookupBase.Method.Table)) { LevelIndex.Add(attr.Name, levelTable); } else if (method.HasFlag(LookupBase.Method.Range)) { LevelIndex.Add(attr.Name, levelRanges); } else if (method.HasFlag(LookupBase.Method.Gain)) { LevelIndex.Add(attr.Name, levelGain); } else if (method.HasFlag(LookupBase.Method.Fixed)) { LevelIndex.Add(attr.Name, fixedValue); } // Add quality dependant attribute to index. method = LookupBase.Method.None; if (!qualityTable.IsEmpty()) { method |= LookupBase.Method.Table; } if (!qualityRanges.IsEmpty()) { method |= LookupBase.Method.Range; } if (qualityGain != null) { method |= LookupBase.Method.Gain; } if (method != LookupBase.Method.None && method != LookupBase.Method.Table && method != LookupBase.Method.Range && method != LookupBase.Method.Gain) { QualityIndex.Add(attr.Name, new LookupMixed { Table = method.HasFlag(LookupBase.Method.Table) ? qualityTable : null, Ranges = method.HasFlag(LookupBase.Method.Range) ? qualityRanges : null, Gain = method.HasFlag(LookupBase.Method.Gain) ? qualityGain : null }); } else if (method.HasFlag(LookupBase.Method.Table)) { QualityIndex.Add(attr.Name, qualityTable); } else if (method.HasFlag(LookupBase.Method.Range)) { QualityIndex.Add(attr.Name, qualityRanges); } else if (method.HasFlag(LookupBase.Method.Gain)) { QualityIndex.Add(attr.Name, qualityGain); } } }
// Cleans up redundancies. public void CleanUp() { // Replace ValueForRange where From == To with ValueAt. List <Value> values = Values.FindAll(v => v is ValueForLevelRange && ((ValueForLevelRange)v).From == ((ValueForLevelRange)v).To); if (values.Count > 0) { foreach (Value value in values) { Replace(value, new ValueAt { Level = ((ValueForLevelRange)value).From, Text = value.Text }); } } values = Values.FindAll(v => v is ValueForQualityRange && ((ValueForQualityRange)v).From == ((ValueForQualityRange)v).To); if (values.Count > 0) { foreach (Value value in values) { Replace(value, new ValueAt { Quality = ((ValueForQualityRange)value).From, Text = value.Text }); } } // Get level-based table values and perform redundancy checks. LookupTable table; List <ValueAt> tableValues = Values.FindAll(v => v is ValueAt && ((ValueAt)v).LevelSpecified).Cast <ValueAt>().ToList(); bool hasLevelTable = false; bool levelTableIsFull = false; if (tableValues.Count > 0) { float[] dummy = new float[] { 1 }; table = new LookupTable(); foreach (ValueAt value in tableValues) { table.Add(value.Level, dummy); } hasLevelTable = true; levelTableIsFull = table.IsFull(); // Remove obsolete level ranges and per level gains. Values.RemoveAll(v => (v is ValueForLevelRange || v is ValuePerLevel) && table.IsCovering(v)); } // Get quality-based table values and perform redundancy checks. tableValues = Values.FindAll(v => v is ValueAt && ((ValueAt)v).QualitySpecified).Cast <ValueAt>().ToList(); bool qualityTableIsFull = false; if (tableValues.Count > 0) { float[] dummy = new float[] { 1 }; table = new LookupTable(); foreach (ValueAt value in tableValues) { table.Add(value.Quality, dummy); } qualityTableIsFull = table.IsFull(); // Remove obsolete quality ranges and per quality gains. Values.RemoveAll(v => v is ValueForQualityRange && table.IsCovering(v) || v is ValuePerQuality && qualityTableIsFull); } // Remove obsolete ValueAt for any level if level table is full. if (hasLevelTable && levelTableIsFull) { Values.RemoveAll(v => v is ValueAt && !((ValueAt)v).LevelSpecified && !((ValueAt)v).QualitySpecified); } LookupRanges ranges; List <ValueForLevelRange> levelRangeValues = Values.FindAll(v => v is ValueForLevelRange).Cast <ValueForLevelRange>().ToList(); bool hasLevelRanges = false; bool levelRangeIsFull = false; if (levelRangeValues.Count > 0) { float[] dummy = new float[] { 1 }; ranges = new LookupRanges(); foreach (ValueForLevelRange value in levelRangeValues) { ranges.Add(value.From, value.To, dummy); } hasLevelRanges = true; levelRangeIsFull = ranges.IsFull(); // Remove obsolete level gains. Values.RemoveAll(v => v is ValuePerLevel && ranges.IsCovering(v)); } List <ValueForQualityRange> qualityRangeValues = Values.FindAll(v => v is ValueForQualityRange).Cast <ValueForQualityRange>().ToList(); bool qualityRangesIsFull = false; if (qualityRangeValues.Count > 0) { float[] dummy = new float[] { 1 }; ranges = new LookupRanges(); foreach (ValueForQualityRange value in qualityRangeValues) { ranges.Add(value.From, value.To, dummy); } qualityRangesIsFull = ranges.IsFull(); // Remove obsolete level gains. if (qualityRangesIsFull) { Values.RemoveAll(v => v is ValuePerQuality); } } // Remove obsolete ValueAt for any level if level range is full. if (hasLevelRanges && levelRangeIsFull) { Values.RemoveAll(v => v is ValueAt && !((ValueAt)v).LevelSpecified && !((ValueAt)v).QualitySpecified); } }