update everything

This commit is contained in:
2024-09-23 01:27:01 +02:00
parent 4a6378dab0
commit 27f87cefda
10 changed files with 710 additions and 469 deletions

View File

@@ -29,14 +29,19 @@ public class BitWise
{
return result;
}
if(numberOfElementToSelect == 0)
{
result.Add(0);
return result;
}
long v = (1L << numberOfElementToSelect) - 1;
long v = (1L << numberOfElementToSelect) - 1L;
long end = 1L << totalNumberOfElement;
while (v < end)
{
result.Add(v);
long t = (v | (v - 1)) + 1;
v = t | ((((t & -t) / (v & -v)) >> 1) - 1);
long t = (v | (v - 1L)) + 1L;
v = t | ((((t & -t) / (v & -v)) >> 1) - 1L);
}
return result;

View File

@@ -47,6 +47,12 @@ namespace Assets.Data
return BitWise.HammingWeight(champions);
}
/// <summary>
/// 0 to n-1
/// </summary>
/// <param name="champions"></param>
/// <param name="n"></param>
/// <returns></returns>
public static long GetNthChampion(long champions, int n)
{
int kThFoundChampion = 0;

View File

@@ -1,3 +1,4 @@
using System.Collections;
using System.Collections.Generic;
using Assets.Data;
using TMPro;
@@ -20,33 +21,50 @@ public class TraitSelectorManager : MonoBehaviour
[SerializeField]
private int _traitThreshold = 7;
private Dictionary<TraitsEnum, int> emblemList;
public void ListAllActivableCompo()
{
emblemList = _emblemSelector.GetEmblems();
var emblemList = _emblemSelector.GetEmblems();
var mandatoryChampions = ChampionUtils.ToLong(_mandatorychampionSelector.GetSelectedChampions());
var acceptableChampions = ChampionUtils.ToLong(_acceptablechampionSelector.GetSelectedChampions());
int compositionSize = _compositionSize.text == "" ? 1 : int.Parse(_compositionSize.text);
var composition = TraitsMapping.GenerateCombinations(mandatoryChampions, acceptableChampions, compositionSize);
Coroutine coroutine = StartCoroutine(TraitsMapping.DisplayCompositions(composition));
//var coroutine = StartCoroutine(TraitsMapping.GetChampionSubsetsAsync(champList, compositionSize,emblemList, HandleCombination));
Coroutine coroutine = StartCoroutine(ComputeCompositionAsync(mandatoryChampions, acceptableChampions, compositionSize, emblemList));
}
public IEnumerator<float> ComputeCompositionAsync(long mandatoryChampions, long acceptableChampions, int compositionSize, Dictionary<int, int> emblemList)
{
var compositions = TraitsMapping.GenerateCombinations(mandatoryChampions, acceptableChampions, compositionSize);
Debug.Log($"{compositions.Count} Compositions generated.");
yield return 0f;
foreach (var composition in compositions)
{
HandleCombination(composition, emblemList);
yield return 0f;
}
}
private void HandleCombination(long combination)
private void HandleCombination(long combination, Dictionary<int, int> emblemList)
{
// var synergies = TraitsMapping.MergeEmblems(
// TraitsMapping.TraitCountInCompo(combination),
// emblemList
// );
// var activeSynergies = TraitsMapping.FilterActiveTraits(synergies);
// if (TraitUtils.TraitCountFromInt(activeSynergies) >= _traitThreshold)
// {
// var s = TraitsMapping.CompositionToString(combination, activeSynergies);
// Debug.Log(s);
// } else {
// Debug.LogWarning("Combination not valid");
// }
var synergies = TraitsMapping.TraitCountInCompo(combination);
var synergiesWithEmblem = TraitsMapping.MergeEmblems(
synergies,
emblemList
);
var activeSynergies = TraitsMapping.FilterActiveTraits(synergiesWithEmblem);
if (TraitUtils.TraitCountFromInt(activeSynergies) >= _traitThreshold)
{
HashSet<ChampionsEnum> champions = ChampionUtils.FromLong(combination);
var s = TraitsMapping.CompositionToString(champions);
Debug.Log(s);
}
// else
// {
// //Debug.LogWarning("Combination not valid");
// }
}
}

View File

@@ -826,14 +826,14 @@ namespace Assets.Data
},
};
public static Dictionary<int, int> minimalActivation = TraitsSteps.ToDictionary(
kvp => kvp.Key,
kvp => kvp.Value[0]
);
public static int GetMinimalActivation(int trait)
{
return TraitsSteps[trait][0];
}
public bool TraitEnabled(int trait, int traitChampCount)
{
return traitChampCount >= minimalActivation[trait];
return traitChampCount >= GetMinimalActivation(trait);
}
/// <summary>
@@ -844,24 +844,24 @@ namespace Assets.Data
public static Dictionary<int, int> TraitCountInCompo(long compo)
{
Dictionary<int, int> synergies = new Dictionary<int, int>();
for (int i = 0; i < 64; i++)
for (int i = 0; i < 60; i++)
{
if ((compo & (1L << i)) != 0)
{
var champ = (long)i;
var champ = (long)(1L << i);
var traits = ChampsTraits[champ];
// combine the traits within synergies using bitwise operation
for (int trait = 0; trait < 22; trait++)
{
if ((traits & (1 << trait)) != 0)
{
if (synergies.ContainsKey(trait))
if (synergies.ContainsKey(1 << trait))
{
synergies[trait]++;
synergies[1 << trait]++;
}
else
{
synergies.Add(trait, 1);
synergies.Add(1 << trait, 1);
}
}
}
@@ -882,7 +882,7 @@ namespace Assets.Data
int output = 0;
foreach (var kvp in synergies)
{
if (kvp.Value >= minimalActivation[kvp.Key])
if (kvp.Value >= GetMinimalActivation(kvp.Key))
{
output |= kvp.Key;
}
@@ -910,11 +910,6 @@ namespace Assets.Data
return mergedEmblems;
}
void Start()
{
}
public void DisplayTraits(Dictionary<TraitsEnum, int> traits)
{
@@ -934,139 +929,6 @@ namespace Assets.Data
return sb.ToString();
}
// public static IEnumerator GetChampionSubsetsAsync(
// long possibleChamp,
// long mandatoryChamps,
// int size,
// Dictionary<int, int> emblemList,
// System.Action<long> onCombinationGenerated
// )
// {
// List<long> possibleChampList = new List<long>();
// foreach (var champ in ChampsTraits.Keys)
// {
// if ((possibleChamp & champ) != 0)
// {
// possibleChampList.Add(champ);
// }
// }
// int n = possibleChampList.Count;
// }
/// <summary>
/// Create a list of compositions based on the possible champions, mandatory champions, size of the composition, and the list of emblems.
/// each composition much contain all mandatory champs, and can contain any number of possible champs.
/// No other champions are allowed in the composition.
/// Composition is stored in the shape of a long, where each bit represents a champion.
///
/// </summary>
/// <param name="possibleChamp"></param>
/// <param name="mandatoryChamps"></param>
/// <param name="size"></param>
/// <param name="emblemList"></param>
/// <param name="onCombinationGenerated"></param>
// /// <returns></returns>
// public static List<long> GetCompositionList(
// long possibleChamp,
// long mandatoryChamps,
// int size,
// Dictionary<int, int> emblemList,
// System.Action<long> onCombinationGenerated
// )
// {
// Dictionary<int,int> allTraits = emblemList;
// int alreadySelectionChampCount = mandatoryChamps.CountSetBits();
// }
public static List<HashSet<ChampionsEnum>> GetChampionSubsets(
HashSet<ChampionsEnum> champs,
int size
)
{
List<HashSet<ChampionsEnum>> result = new List<HashSet<ChampionsEnum>>();
if (size == 0)
{
result.Add(new HashSet<ChampionsEnum>());
return result;
}
List<ChampionsEnum> champList = champs.ToList();
// Handle the edge case when size is greater than the number of available champions.
if (size > champList.Count)
{
return result; // No valid subsets if size is too large.
}
// Use a bit mask approach to generate all subsets of the specified size.
int n = champList.Count;
int[] indices = new int[size];
for (int i = 0; i < size; i++)
indices[i] = i;
while (true)
{
HashSet<ChampionsEnum> subset = new HashSet<ChampionsEnum>();
foreach (int index in indices)
{
subset.Add(champList[index]);
}
result.Add(subset);
// Generate the next combination of indices
int i;
for (i = size - 1; i >= 0; i--)
{
if (indices[i] != i + n - size)
{
break;
}
}
if (i < 0)
{
break; // All combinations have been generated.
}
indices[i]++;
for (int j = i + 1; j < size; j++)
{
indices[j] = indices[j - 1] + 1;
}
}
return result;
}
public static List<HashSet<ChampionsEnum>> GetChampionSubsetsRec(
HashSet<ChampionsEnum> champs,
int size
)
{
List<HashSet<ChampionsEnum>> result = new List<HashSet<ChampionsEnum>>();
if (size == 0)
{
result.Add(new HashSet<ChampionsEnum>());
return result;
}
if (champs.Count == 0)
{
return result;
}
ChampionsEnum first = champs.First();
HashSet<ChampionsEnum> rest = new HashSet<ChampionsEnum>(champs);
rest.Remove(first);
List<HashSet<ChampionsEnum>> subResult = GetChampionSubsetsRec(rest, size - 1);
foreach (var set in subResult)
{
set.Add(first);
}
result.AddRange(subResult);
result.AddRange(GetChampionSubsetsRec(rest, size));
return result;
}
public static int MaxIntForCombinationOfn(int n)
{
@@ -1117,21 +979,8 @@ namespace Assets.Data
HashSet<long> combinations = BitWise.GetAllPermutation(champToSelectCount, possibleChampCount);
foreach (var combinationOfPossibleChamps in combinations)
{
// generating one composition based on the combination.
// combination 10010 will add the second and fifth champion of the possibleChamps list to the composition.
long composition = mandatoryChamps;
int possibleChampIterator = 0;
int kThChampFound = 0;
while (possibleChampIterator < champToSelectCount)
{
if ((combinationOfPossibleChamps & (1 << possibleChampIterator)) != 0)
{
long champ = ChampionUtils.GetNthChampion(possibleChamps,kThChampFound);
composition |= champ;
kThChampFound++;
}
possibleChampIterator++;
}
var composition = SelectSublistOfChampion(possibleChamps, combinationOfPossibleChamps);
composition |= mandatoryChamps;
compositions.Add(composition);
}
return compositions;
@@ -1149,5 +998,22 @@ namespace Assets.Data
yield return null;
}
}
public static long SelectSublistOfChampion(long accessibleChampions, long subselectedChampions)
{
var champs = ChampionUtils.FromLong(accessibleChampions).ToList<ChampionsEnum>();
// this list of champ is ordered. I want to filter this with the subselectedChampions bit flag
// where all bit to 1 are the champions I want to keep, and all bit to 0 are the champions I want to remove
HashSet<ChampionsEnum> selectedChamps = new HashSet<ChampionsEnum>();
for (int i = 0; i < champs.Count; i++)
{
if ((subselectedChampions & (1L << i)) != 0)
{
selectedChamps.Add(champs[i]);
}
}
return ChampionUtils.ToLong(selectedChamps);
}
}
}

View File

@@ -3273,7 +3273,7 @@ MonoBehaviour:
_mandatorychampionSelector: {fileID: 479329100}
_acceptablechampionSelector: {fileID: 1418508558}
_emblemSelector: {fileID: 1032725645}
_traitThreshold: 7
_traitThreshold: 5
--- !u!114 &1418508558 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 8148431447111668956, guid: c027171600fc2d34e89847fce2ced78b, type: 3}

View File

@@ -36,7 +36,7 @@ namespace Assets.Data
0b01101,
0b10011,
0b01011,
0b00111,
7,
}
);
yield return new TestCaseData(
@@ -47,6 +47,21 @@ namespace Assets.Data
0b001
}
);
yield return new TestCaseData(
0,
1,
new HashSet<long>()
{
0b0
}
);
yield return new TestCaseData(
3,
1,
new HashSet<long>()
{
}
);
yield return new TestCaseData(
2,
3,

View File

@@ -31,6 +31,18 @@ namespace Assets.Data
Assert.IsTrue(expected.Contains(champ));
}
}
[Test]
[TestCaseSource(typeof(TraitsMappingCase), "TestFilteringChampCombination")]
public void TestFilteringChampCombination(
long accessibleChampions,
long subselectedChampions,
long expected
)
{
var output = TraitsMapping.SelectSublistOfChampion(accessibleChampions, subselectedChampions);
Assert.AreEqual(expected, output);
}
}
public class TraitsMappingCase
@@ -76,7 +88,7 @@ namespace Assets.Data
ChampionsEnum.ELISE,
ChampionsEnum.AHRI,
ChampionsEnum.CASSIOPEIA,
ChampionsEnum.EZREAL
ChampionsEnum.EZREAL,
}
),
5,
@@ -89,7 +101,7 @@ namespace Assets.Data
ChampionsEnum.BLITZCRANK,
ChampionsEnum.ELISE,
ChampionsEnum.AHRI,
ChampionsEnum.CASSIOPEIA
ChampionsEnum.CASSIOPEIA,
}
),
ChampionUtils.ToLong(
@@ -99,7 +111,7 @@ namespace Assets.Data
ChampionsEnum.BLITZCRANK,
ChampionsEnum.ELISE,
ChampionsEnum.AHRI,
ChampionsEnum.EZREAL
ChampionsEnum.EZREAL,
}
),
ChampionUtils.ToLong(
@@ -109,7 +121,7 @@ namespace Assets.Data
ChampionsEnum.BLITZCRANK,
ChampionsEnum.ELISE,
ChampionsEnum.CASSIOPEIA,
ChampionsEnum.EZREAL
ChampionsEnum.EZREAL,
}
),
ChampionUtils.ToLong(
@@ -119,19 +131,28 @@ namespace Assets.Data
ChampionsEnum.BLITZCRANK,
ChampionsEnum.AHRI,
ChampionsEnum.CASSIOPEIA,
ChampionsEnum.EZREAL
ChampionsEnum.EZREAL,
}
),
}
);
yield return new TestCaseData(
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>() { ChampionsEnum.AHRI, ChampionsEnum.AKALI }
),
ChampionUtils.ToLong(new HashSet<ChampionsEnum>() { ChampionsEnum.ELISE }),
ChampionUtils.ToLong(new HashSet<ChampionsEnum>() { ChampionsEnum.AHRI }),
1,
3,
new List<long>()
{
ChampionUtils.ToLong(new HashSet<ChampionsEnum>() { ChampionsEnum.ELISE }),
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.AHRI,
ChampionsEnum.AKALI,
ChampionsEnum.ELISE,
}
),
}
);
@@ -142,11 +163,15 @@ namespace Assets.Data
ChampionsEnum.AHRI,
ChampionsEnum.POPPY,
ChampionsEnum.SORAKA,
ChampionsEnum.HWEI,
ChampionsEnum.XERATH,
}
),
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>() { ChampionsEnum.SMOLDER, ChampionsEnum.XERATH }
new HashSet<ChampionsEnum>()
{
ChampionsEnum.SMOLDER,
ChampionsEnum.MORDEKAISER,
}
),
4,
new List<long>()
@@ -157,12 +182,111 @@ namespace Assets.Data
ChampionsEnum.AHRI,
ChampionsEnum.POPPY,
ChampionsEnum.SORAKA,
ChampionsEnum.HWEI,
ChampionsEnum.XERATH,
}
),
}
);
yield return new TestCaseData(
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.RUMBLE,
ChampionsEnum.GALIO,
ChampionsEnum.AKALI,
ChampionsEnum.BARD,
}
),
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.MORGANA,
ChampionsEnum.FIORA,
ChampionsEnum.VARUS,
}
),
7,
new List<long>()
{
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.RUMBLE,
ChampionsEnum.GALIO,
ChampionsEnum.AKALI,
ChampionsEnum.BARD,
ChampionsEnum.MORGANA,
ChampionsEnum.FIORA,
ChampionsEnum.VARUS
}
),
}
);
yield return new TestCaseData(
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.RUMBLE,
ChampionsEnum.GALIO,
ChampionsEnum.AKALI,
ChampionsEnum.BARD,
ChampionsEnum.MORGANA,
ChampionsEnum.FIORA,
ChampionsEnum.VARUS
}
),
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.XERATH
}
),
7,
new List<long>()
{
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.RUMBLE,
ChampionsEnum.GALIO,
ChampionsEnum.AKALI,
ChampionsEnum.BARD,
ChampionsEnum.MORGANA,
ChampionsEnum.FIORA,
ChampionsEnum.VARUS
}
),
}
);
}
}
public static IEnumerable TestFilteringChampCombination
{
get
{
yield return new TestCaseData(
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.ASHE,
ChampionsEnum.BLITZCRANK,
ChampionsEnum.ELISE,
ChampionsEnum.JAX
}
),
0b0101,
ChampionUtils.ToLong(
new HashSet<ChampionsEnum>()
{
ChampionsEnum.ASHE,
ChampionsEnum.ELISE
}
)
);
}
}
}
}

View File

@@ -78,32 +78,32 @@ public class EmblemSelector : MonoBehaviour
// Start is called before the first frame update
void Start() { }
public Dictionary<TraitsEnum, int> GetEmblems()
public Dictionary<int, int> GetEmblems()
{
Dictionary<TraitsEnum, int> emblems = new Dictionary<TraitsEnum, int>();
emblems[TraitsEnum.ARCANA] = int.Parse(_arcanaEmblems.text);
emblems[TraitsEnum.CHRONO] = int.Parse(_chronoEmblems.text);
emblems[TraitsEnum.DRAGON] = int.Parse(_dragonEmblems.text);
emblems[TraitsEnum.DRUID] = int.Parse(_druidEmblems.text);
emblems[TraitsEnum.ELDRICHT] = int.Parse(_eldrichtEmblems.text);
emblems[TraitsEnum.FAERIE] = int.Parse(_faerieEmblems.text);
emblems[TraitsEnum.FROST] = int.Parse(_frostEmblems.text);
emblems[TraitsEnum.HONEYMANCY] = int.Parse(_honeymancyEmblems.text);
emblems[TraitsEnum.PORTAL] = int.Parse(_portalEmblems.text);
emblems[TraitsEnum.PYRO] = int.Parse(_pyroEmblems.text);
emblems[TraitsEnum.SUGARCRAFT] = int.Parse(_sugarcraftEmblems.text);
emblems[TraitsEnum.WITCHCRAFT] = int.Parse(_witchcraftEmblems.text);
emblems[TraitsEnum.BASTION] = int.Parse(_bastionEmblems.text);
emblems[TraitsEnum.BLASTER] = int.Parse(_blasterEmblems.text);
emblems[TraitsEnum.HUNTER] = int.Parse(_hunterEmblems.text);
emblems[TraitsEnum.INCANTATOR] = int.Parse(_incantatorEmblems.text);
emblems[TraitsEnum.MAGE] = int.Parse(_mageEmblems.text);
emblems[TraitsEnum.MULTISTRIKER] = int.Parse(_multistrikerEmblems.text);
emblems[TraitsEnum.PRESERVER] = int.Parse(_preserverEmblems.text);
emblems[TraitsEnum.SCHOLAR] = int.Parse(_scholarEmblems.text);
emblems[TraitsEnum.SHAPESHIFTER] = int.Parse(_shapeshifterEmblems.text);
emblems[TraitsEnum.VANGUARD] = int.Parse(_vanguardEmblems.text);
emblems[TraitsEnum.WARRIOR] = int.Parse(_warriorEmblems.text);
Dictionary<int, int> emblems = new Dictionary<int, int>();
emblems[(int)TraitsEnum.ARCANA] = int.Parse(_arcanaEmblems.text);
emblems[(int)TraitsEnum.CHRONO] = int.Parse(_chronoEmblems.text);
emblems[(int)TraitsEnum.DRAGON] = int.Parse(_dragonEmblems.text);
emblems[(int)TraitsEnum.DRUID] = int.Parse(_druidEmblems.text);
emblems[(int)TraitsEnum.ELDRICHT] = int.Parse(_eldrichtEmblems.text);
emblems[(int)TraitsEnum.FAERIE] = int.Parse(_faerieEmblems.text);
emblems[(int)TraitsEnum.FROST] = int.Parse(_frostEmblems.text);
emblems[(int)TraitsEnum.HONEYMANCY] = int.Parse(_honeymancyEmblems.text);
emblems[(int)TraitsEnum.PORTAL] = int.Parse(_portalEmblems.text);
emblems[(int)TraitsEnum.PYRO] = int.Parse(_pyroEmblems.text);
emblems[(int)TraitsEnum.SUGARCRAFT] = int.Parse(_sugarcraftEmblems.text);
emblems[(int)TraitsEnum.WITCHCRAFT] = int.Parse(_witchcraftEmblems.text);
emblems[(int)TraitsEnum.BASTION] = int.Parse(_bastionEmblems.text);
emblems[(int)TraitsEnum.BLASTER] = int.Parse(_blasterEmblems.text);
emblems[(int)TraitsEnum.HUNTER] = int.Parse(_hunterEmblems.text);
emblems[(int)TraitsEnum.INCANTATOR] = int.Parse(_incantatorEmblems.text);
emblems[(int)TraitsEnum.MAGE] = int.Parse(_mageEmblems.text);
emblems[(int)TraitsEnum.MULTISTRIKER] = int.Parse(_multistrikerEmblems.text);
emblems[(int)TraitsEnum.PRESERVER] = int.Parse(_preserverEmblems.text);
emblems[(int)TraitsEnum.SCHOLAR] = int.Parse(_scholarEmblems.text);
emblems[(int)TraitsEnum.SHAPESHIFTER] = int.Parse(_shapeshifterEmblems.text);
emblems[(int)TraitsEnum.VANGUARD] = int.Parse(_vanguardEmblems.text);
emblems[(int)TraitsEnum.WARRIOR] = int.Parse(_warriorEmblems.text);
return emblems;
}
public void Reset()

File diff suppressed because it is too large Load Diff