Пример #1
0
        // Returns true if ranges are covering value, false otherwise.
        internal bool IsCovering(Value value)
        {
            int from = 1, to = MAX_LEVEL;

            if (value is ValueAt)
            {
                ValueAt at = (ValueAt)value;
                if (at.LevelSpecified)
                {
                    from = to = at.Level;
                }
                else if (at.QualitySpecified)
                {
                    from = to = at.Quality;
                }
                // Else keep from = 1 and to = MAX_LEVEL.
            }
            else if (value is ValueForLevelRange)
            {
                ValueForLevelRange range = (ValueForLevelRange)value;
                from = range.From;
                if (range.ToSpecified)
                {
                    to = range.To;
                }
            }
            else if (value is ValueForQualityRange)
            {
                ValueForQualityRange range = (ValueForQualityRange)value;
                from = range.From;
                if (range.ToSpecified)
                {
                    to = range.To;
                }
            }
            else if (value is ValuePerLevel)
            {
                from = 2;
            }
            // Else keep from = 1 and to = MAX_LEVEL.

            // Traverse all ranges and move 'from' to end of range when 'from' is inside of that range.
            foreach (Range range in Ranges)
            {
                if (from >= range.From && from <= range.To)
                {
                    from = range.To;
                }
            }

            // A <from, to> range is covered by our ranges when 'from' reached 'to'.
            return(from >= to);
        }
Пример #2
0
        // Returns true if table defines all values as specified value.
        internal bool IsCovering(Value value)
        {
            int from = 1, to = MAX_LEVEL;

            if (value is ValueAt)
            {
                ValueAt at = (ValueAt)value;
                if (at.LevelSpecified)
                {
                    from = to = at.Level;
                }
                else if (at.QualitySpecified)
                {
                    from = to = at.Quality;
                }
                // Else keep from = 1 and to = MAX_LEVEL.
            }
            else if (value is ValueForLevelRange)
            {
                ValueForLevelRange range = (ValueForLevelRange)value;
                from = range.From;
                if (range.ToSpecified)
                {
                    to = range.To;
                }
            }
            else if (value is ValueForQualityRange)
            {
                ValueForQualityRange range = (ValueForQualityRange)value;
                from = range.From;
                if (range.ToSpecified)
                {
                    to = range.To;
                }
            }
            else if (value is ValuePerLevel) // ValuePerLevel doesn't define value for level 1.
            {
                from = 2;
            }
            // Else keep from = 1 and to = MAX_LEVEL.

            for (int level = from - 1; level < to; ++level)
            {
                if (Values[level] == null)
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #3
0
        // 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);
                }
            }
        }
Пример #4
0
        override public int Compare(Value x, Value y)
        {
            if (x is ValueAt)
            {
                ValueAt xAt = (ValueAt)x;
                if (y is ValueAt)
                {
                    ValueAt yAt = (ValueAt)y;
                    if (xAt.LevelSpecified)
                    {
                        return(yAt.LevelSpecified ? xAt.Level.CompareTo(yAt.Level) : -1); // x.Level specified < y.Quality specified/unspecified
                    }
                    else if (xAt.QualitySpecified)
                    {
                        return(yAt.QualitySpecified ? xAt.Quality.CompareTo(yAt.Quality) : (yAt.LevelSpecified ? 1 : -1)); // x.Quality specified > y.Level specified, x.Quality specified < y.Level unspecified
                    }
                    return(yAt.LevelSpecified || yAt.QualitySpecified ? 1 : 0);                                            // x.Level & x.Quality unspecified > y.Level/Quality specified
                }
                else if (y is ValueForLevelRange)
                {
                    ValueForLevelRange yRange = (ValueForLevelRange)y;
                    if (xAt.LevelSpecified && yRange.ToSpecified && xAt.Level > yRange.To) // x.Level vs. y.To => x > y
                    {
                        return(1);
                    }
                    // Fall through (x < y)
                }
                else if (y is ValueForQualityRange)
                {
                    ValueForQualityRange yRange = (ValueForQualityRange)y;
                    if (xAt.QualitySpecified && yRange.ToSpecified && xAt.Quality > yRange.To) // x.Quality vs. y.To => x > y
                    {
                        return(1);
                    }
                    // Fall through (x < y)
                }

                return(-1);
            }
            else if (x is ValueForLevelRange)
            {
                ValueForLevelRange xRange = (ValueForLevelRange)x;
                if (y is ValueForLevelRange)
                {
                    ValueForLevelRange yRange = (ValueForLevelRange)y;
                    if (xRange.From == yRange.From)
                    {
                        if (xRange.ToSpecified)
                        {
                            return(yRange.ToSpecified ? xRange.To.CompareTo(yRange.To) : -1); // x.To specified < y.To unspecified
                        }
                        else
                        {
                            return(yRange.ToSpecified ? 1 : 0); // x.To unspecified > y.To specified
                        }
                    }

                    return(xRange.From < yRange.From ? -1 : 1);
                }
                else if (y is ValueAt)
                {
                    ValueAt yAt = (ValueAt)y;
                    if (yAt.LevelSpecified && xRange.To < yAt.Level) // x.To vs. y.Level => x < y
                    {
                        return(-1);
                    }
                    // Fall through (x > y).
                }

                return(y is ValueAt ? 1 : -1);
            }
            else if (x is ValueForQualityRange)
            {
                ValueForQualityRange xRange = (ValueForQualityRange)x;
                if (y is ValueForQualityRange)
                {
                    ValueForQualityRange yRange = (ValueForQualityRange)y;
                    if (xRange.From == yRange.From)
                    {
                        if (xRange.ToSpecified)
                        {
                            return(yRange.ToSpecified ? xRange.To.CompareTo(yRange.To) : -1); // x.To specified < y.To unspecified
                        }
                        else
                        {
                            return(yRange.ToSpecified ? 1 : 0); // x.To unspecified > y.To specified
                        }
                    }

                    return(xRange.From < yRange.From ? -1 : 1);
                }
                else if (y is ValueAt)
                {
                    ValueAt yAt = (ValueAt)y;
                    if (yAt.QualitySpecified && xRange.To < yAt.Quality) // x.To vs. y.Quality => x < y
                    {
                        return(-1);
                    }
                    // Fall through (x > y).
                }

                return(y is ValueAt || y is ValueForLevelRange ? 1 : -1);
            }
            else if (x is ValuePerLevel)
            {
                return(y is ValuePerLevel ? 0 : (y is ValuePerQuality ? -1 : 1));
            }
            else if (x is ValuePerQuality)
            {
                return(y is ValuePerQuality ? 0 : 1);
            }

            return(0);
        }
Пример #5
0
 // Merges value.
 public void Merge(Value value)
 {
     if (value is ValueAt)
     {
         ValueAt merge = (ValueAt)value;
         ValueAt with  = (ValueAt)Values.Find(v => v is ValueAt && ((ValueAt)v).Level == merge.Level && ((ValueAt)v).Quality == merge.Quality);
         if (with == null)
         {
             if (merge.LevelSpecified)
             {
                 // No need to add ValueAt, if there is ValueForLevelRange covering specified Level with same Text.
                 ValueForLevelRange covers = (ValueForLevelRange)Values.Find(v => v is ValueForLevelRange && ((ValueForLevelRange)v).From <= merge.Level && ((ValueForLevelRange)v).To >= merge.Level && v.Text == merge.Text);
                 if (covers == null)
                 {
                     Values.Add(merge);
                 }
             }
             else if (merge.QualitySpecified)
             {
                 // No need to add ValueAt, if there is ValueForQualityRange covering specified Quality with same Text.
                 ValueForQualityRange covers = (ValueForQualityRange)Values.Find(v => v is ValueForQualityRange && ((ValueForQualityRange)v).From <= merge.Quality && ((ValueForQualityRange)v).To >= merge.Quality && v.Text == merge.Text);
                 if (covers == null)
                 {
                     Values.Add(merge);
                 }
             }
             else
             {
                 // Value with no level nor quality specified replaces all values.
                 Values.Clear();
                 Values.Add(merge);
             }
         }
         else
         {
             with.Text = merge.Text;
         }
     }
     else if (value is ValueForLevelRange)
     {
         ValueForLevelRange merge = (ValueForLevelRange)value;
         // Remove all ValueAt.LevelSpecified inside of range being merged and all ranges covered by it.
         Values.RemoveAll(v => v is ValueAt && ((ValueAt)v).LevelSpecified && ((ValueAt)v).Level >= merge.From && ((ValueAt)v).Level <= merge.To ||
                          v is ValueForLevelRange && ((ValueForLevelRange)v).From >= merge.From && ((ValueForLevelRange)v).To <= merge.To);
         // Split range covering merged one (<with.From  <merge.From  with.To>  range.To>).
         ValueForLevelRange with = (ValueForLevelRange)Values.Find(v => v is ValueForLevelRange && ((ValueForLevelRange)v).From <merge.From && ((ValueForLevelRange)v).To> merge.To);
         if (with != null)
         {
             Values.Add(new ValueForLevelRange {
                 From = merge.To + 1, To = with.To, Text = with.Text
             });
             with.To = merge.From - 1;
         }
         else
         {
             // Shorten range intersecting merged one from left (<with.From  <merge.From  with.To>  merge.To>).
             with = (ValueForLevelRange)Values.Find(v => v is ValueForLevelRange && ((ValueForLevelRange)v).From < merge.From && ((ValueForLevelRange)v).To >= merge.From);
             if (with != null)
             {
                 with.To = merge.From - 1;
                 // Replace single-level shortened range with ValueAt.
                 if (with.From == with.To)
                 {
                     Values.Add(new ValueAt {
                         Level = with.From, Text = with.Text
                     });
                     Values.Remove(with);
                 }
             }
             // Shorten range intersecting merged one from right (<merge.From  <with.From  merge.To>  with.To>).
             with = (ValueForLevelRange)Values.Find(v => v is ValueForLevelRange && ((ValueForLevelRange)v).From <= merge.To && ((ValueForLevelRange)v).To > merge.To);
             if (with != null)
             {
                 with.From = merge.To + 1;
                 // Replace single-level shortened range with ValueAt.
                 if (with.From == with.To)
                 {
                     Values.Add(new ValueAt {
                         Level = with.From, Text = with.Text
                     });
                     Values.Remove(with);
                 }
             }
         }
         Values.Add(merge);
     }
     else if (value is ValueForQualityRange)
     {
         ValueForQualityRange merge = (ValueForQualityRange)value;
         // Remove all ValueAt.QualitySpecified inside of range being merged and all ranges covered by it.
         Values.RemoveAll(v => v is ValueAt && ((ValueAt)v).QualitySpecified && ((ValueAt)v).Quality >= merge.From && ((ValueAt)v).Quality <= merge.To ||
                          v is ValueForQualityRange && ((ValueForQualityRange)v).From >= merge.From && ((ValueForQualityRange)v).To <= merge.To);
         // Split range covering merged one (<with.From  <merge.From  with.To>  range.To>).
         ValueForQualityRange with = (ValueForQualityRange)Values.Find(v => v is ValueForQualityRange && ((ValueForQualityRange)v).From <merge.From && ((ValueForQualityRange)v).To> merge.To);
         if (with != null)
         {
             Values.Add(new ValueForQualityRange {
                 From = merge.To + 1, To = with.To, Text = with.Text
             });
             with.To = merge.From - 1;
         }
         else
         {
             // Shorten range intersecting merged one from left (<with.From  <merge.From  with.To>  merge.To>).
             with = (ValueForQualityRange)Values.Find(v => v is ValueForQualityRange && ((ValueForQualityRange)v).From < merge.From && ((ValueForQualityRange)v).To >= merge.From);
             if (with != null)
             {
                 with.To = merge.From - 1;
                 // Replace single-quality shortened range with ValueAt.
                 if (with.From == with.To)
                 {
                     Values.Add(new ValueAt {
                         Quality = with.From, Text = with.Text
                     });
                     Values.Remove(with);
                 }
             }
             // Shorten range intersecting merged one from right (<merge.From  <with.From  merge.To>  with.To>).
             with = (ValueForQualityRange)Values.Find(v => v is ValueForQualityRange && ((ValueForQualityRange)v).From <= merge.To && ((ValueForQualityRange)v).To > merge.To);
             if (with != null)
             {
                 with.From = merge.To + 1;
                 // Replace single-quality shortened range with ValueAt.
                 if (with.From == with.To)
                 {
                     Values.Add(new ValueAt {
                         Quality = with.From, Text = with.Text
                     });
                     Values.Remove(with);
                 }
             }
         }
         Values.Add(merge);
     }
     else if (value is ValuePerLevel)
     {
         ValuePerLevel merge = (ValuePerLevel)value;
         ValuePerLevel with  = (ValuePerLevel)Values.Find(v => v is ValuePerLevel);
         if (with == null)
         {
             // Value per level replaces any level specific values and ranges.
             Values.RemoveAll(v => (v is ValueAt && ((ValueAt)v).LevelSpecified) || v is ValueForLevelRange);
             Values.Add(merge);
         }
         else
         {
             with.Text = merge.Text;
         }
     }
     else if (value is ValuePerQuality)
     {
         ValuePerQuality merge = (ValuePerQuality)value;
         ValuePerQuality with  = (ValuePerQuality)Values.Find(v => v is ValuePerQuality);
         if (with == null)
         {
             // Value per quality replaces any quality specific values and ranges.
             Values.RemoveAll(v => (v is ValueAt && ((ValueAt)v).QualitySpecified) || v is ValueForQualityRange);
             Values.Add(merge);
         }
         else
         {
             with.Text = merge.Text;
         }
     }
 }