using System; using System.Collections; using System.Collections.Generic; namespace Luneraria.Core { /// /// Map with a defined iteration order: insertion order; removing a key keeps the order of /// the others and a key added again goes to the end. The rules iterate buildings, effects /// and damage-over-time entries; with this map that order never depends on hashing or on /// the history of a Dictionary (docs/port/U1-RULES.md, determinism). /// public sealed class OrderedMap : IEnumerable> { readonly Dictionary _index = new Dictionary(); readonly List _keys = new List(); readonly List _values = new List(); public int Count { get { return _keys.Count; } } public IReadOnlyList Keys { get { return _keys; } } public IReadOnlyList Values { get { return _values; } } public bool ContainsKey(TKey key) { return _index.ContainsKey(key); } public TValue this[TKey key] { get { return _values[_index[key]]; } set { int at; if (_index.TryGetValue(key, out at)) { _values[at] = value; return; } _index[key] = _keys.Count; _keys.Add(key); _values.Add(value); } } public bool TryGetValue(TKey key, out TValue value) { int at; if (_index.TryGetValue(key, out at)) { value = _values[at]; return true; } value = default(TValue); return false; } public TValue GetValueOrDefault(TKey key, TValue fallback) { int at; return _index.TryGetValue(key, out at) ? _values[at] : fallback; } public bool Remove(TKey key) { int at; if (!_index.TryGetValue(key, out at)) return false; _keys.RemoveAt(at); _values.RemoveAt(at); _index.Remove(key); for (int i = at; i < _keys.Count; i++) _index[_keys[i]] = i; return true; } public void Clear() { _index.Clear(); _keys.Clear(); _values.Clear(); } /// Copy in the same order; values are copied with the given function. public OrderedMap Clone(Func copy = null) { var result = new OrderedMap(); for (int i = 0; i < _keys.Count; i++) result[_keys[i]] = copy != null ? copy(_values[i]) : _values[i]; return result; } public IEnumerator> GetEnumerator() { for (int i = 0; i < _keys.Count; i++) yield return new KeyValuePair(_keys[i], _values[i]); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } }