using System.Collections.Generic;
using System.Linq;
namespace PKHeX.Core
{
///
/// Logic for applying ribbons.
///
public static class RibbonApplicator
{
private static List GetAllRibbonNames(PKM pkm) => RibbonInfo.GetRibbonInfo(pkm).Select(z => z.Name).ToList();
///
/// Gets a list of valid ribbons for the .
///
/// Entity to fetch the list for.
/// All ribbon names.
/// List of all valid ribbon names.
public static IReadOnlyList GetValidRibbons(PKM pkm, IList allRibbons)
{
var pk = pkm.Clone();
return SetAllValidRibbons(allRibbons, pk);
}
///
/// Gets a list of valid ribbons for the .
///
/// Entity to fetch the list for.
/// List of all valid ribbon names.
public static IReadOnlyList GetValidRibbons(PKM pkm)
{
var names = GetAllRibbonNames(pkm);
return GetValidRibbons(pkm, names);
}
///
/// Gets a list of valid ribbons for the that can be removed.
///
/// Entity to fetch the list for.
/// All ribbon names.
/// List of all removable ribbon names.
public static IReadOnlyList GetRemovableRibbons(PKM pkm, IList allRibbons)
{
var pk = pkm.Clone();
return RemoveAllValidRibbons(allRibbons, pk);
}
///
/// Gets a list of valid ribbons for the that can be removed.
///
/// Entity to fetch the list for.
/// List of all removable ribbon names.
public static IReadOnlyList GetRemovableRibbons(PKM pkm)
{
var names = GetAllRibbonNames(pkm);
return GetRemovableRibbons(pkm, names);
}
///
/// Sets all valid ribbons to the .
///
/// Entity to set ribbons for.
/// True if any ribbons were applied.
public static bool SetAllValidRibbons(PKM pkm)
{
var ribNames = GetAllRibbonNames(pkm);
ribNames.RemoveAll(z => z.StartsWith("RibbonMark")); // until marking legality is handled
return SetAllValidRibbons(pkm, ribNames);
}
///
/// Sets all valid ribbons to the .
///
/// Entity to set ribbons for.
/// Ribbon names to try setting.
/// True if any ribbons were applied.
public static bool SetAllValidRibbons(PKM pkm, List ribNames)
{
var list = SetAllValidRibbons(ribNames, pkm);
return list.Count != 0;
}
private static IReadOnlyList SetAllValidRibbons(IList allRibbons, PKM pk)
{
var la = new LegalityAnalysis(pk);
var valid = new List();
while (TryApplyAllRibbons(pk, la, allRibbons, valid) != 0)
{
// Repeat the operation until no more ribbons are set.
}
return valid;
}
///
/// Sets all valid ribbons to the .
///
/// Entity to set ribbons for.
/// True if any ribbons were removed.
public static bool RemoveAllValidRibbons(PKM pkm)
{
var ribNames = GetAllRibbonNames(pkm);
return RemoveAllValidRibbons(pkm, ribNames);
}
///
/// Sets all valid ribbons to the .
///
/// Entity to set ribbons for.
/// Ribbon names to try setting.
/// True if any ribbons were removed.
public static bool RemoveAllValidRibbons(PKM pkm, List ribNames)
{
var list = RemoveAllValidRibbons(ribNames, pkm);
return list.Count != 0;
}
private static IReadOnlyList RemoveAllValidRibbons(IList allRibbons, PKM pk)
{
var la = new LegalityAnalysis(pk);
var valid = new List();
while (TryRemoveAllRibbons(pk, la, allRibbons, valid) != 0)
{
// Repeat the operation until no more ribbons are set.
}
return valid;
}
private static int TryApplyAllRibbons(PKM pk, LegalityAnalysis la, IList allRibbons, ICollection valid)
{
int applied = 0;
for (int i = 0; i < allRibbons.Count;)
{
la.ResetParse();
var rib = allRibbons[i];
var success = TryApplyRibbon(pk, la, rib);
if (success)
{
++applied;
allRibbons.RemoveAt(i);
valid.Add(rib);
}
else
{
RemoveRibbon(pk, rib);
++i;
}
}
return applied;
}
private static int TryRemoveAllRibbons(PKM pk, LegalityAnalysis la, IList allRibbons, ICollection valid)
{
int removed = 0;
for (int i = 0; i < allRibbons.Count;)
{
la.ResetParse();
var rib = allRibbons[i];
var success = TryRemoveRibbon(pk, la, rib);
if (success)
{
++removed;
allRibbons.RemoveAt(i);
valid.Add(rib);
}
else
{
SetRibbonValue(pk, rib, 1);
++i;
}
}
return removed;
}
private static void RemoveRibbon(PKM pk, string rib) => SetRibbonValue(pk, rib, 0);
private static bool TryRemoveRibbon(PKM pk, LegalityAnalysis la, string rib)
{
RemoveRibbon(pk, rib);
LegalityAnalysis.Ribbon.Verify(la);
return la.Results.All(z => z.Valid);
}
private static bool TryApplyRibbon(PKM pk, LegalityAnalysis la, string rib)
{
SetRibbonValue(pk, rib, 1);
LegalityAnalysis.Ribbon.Verify(la);
return la.Results.All(z => z.Valid);
}
private static void SetRibbonValue(PKM pk, string rib, int value)
{
switch (rib)
{
case nameof(PK7.RibbonCountMemoryBattle):
ReflectUtil.SetValue(pk, rib, value * (pk.Gen4 ? 6 : 8));
break;
case nameof(PK7.RibbonCountMemoryContest):
ReflectUtil.SetValue(pk, rib, value * (pk.Gen4 ? 20 : 40));
break;
default:
if (rib.StartsWith("RibbonCountG3"))
ReflectUtil.SetValue(pk, rib, value * 4);
else
ReflectUtil.SetValue(pk, rib, value != 0);
break;
}
}
}
}