public void IsEnabled_WhenPercentageIsAboveMinimum_ShouldReturnTrue() { var groupId = string.Empty; var minimumPercentage = StrategyUtils.GetNormalizedNumber(SessionId, groupId); var context = new UnleashContext.Builder().SessionId(SessionId).Build(); var parameters = new Dictionary <string, string>(); for (var percentage = 0; percentage <= 100; percentage++) { parameters[GradualRolloutSessionIdStrategy.Percentage] = percentage.ToString(); parameters[GradualRolloutSessionIdStrategy.GroupId] = groupId; var actual = Strategy.IsEnabled(parameters, context); if (percentage < minimumPercentage) { Assert.False(actual); } else { Assert.True(actual); } } }
public void GetPercentageVariants() { StrategyUtils.GetPercentage(null).Should().Be(0); StrategyUtils.GetPercentage("").Should().Be(0); // Normal cases StrategyUtils.GetPercentage("0").Should().Be(0); StrategyUtils.GetPercentage("50").Should().Be(50); StrategyUtils.GetPercentage("100").Should().Be(100); // Whitespace StrategyUtils.GetPercentage(" 0 ").Should().Be(0); StrategyUtils.GetPercentage(" 50 ").Should().Be(50); StrategyUtils.GetPercentage(" 100 ").Should().Be(100); // Edge cases StrategyUtils.GetPercentage("-1").Should().Be(0); StrategyUtils.GetPercentage("101").Should().Be(100); // Min/max StrategyUtils.GetPercentage(int.MaxValue.ToString()).Should().Be(100); StrategyUtils.GetPercentage(int.MinValue.ToString()).Should().Be(0); // Overflow StrategyUtils.GetPercentage(int.MaxValue + "0").Should().Be(0); StrategyUtils.GetPercentage(int.MinValue + "0").Should().Be(0); }
public static Variant SelectVariant(FeatureToggle featureToggle, UnleashContext context, Variant defaultVariant) { var variantDefinitions = featureToggle.Variants; var totalWeight = variantDefinitions.Sum(v => v.Weight); if (totalWeight == 0) { return(defaultVariant); } var variantOverride = GetOverride(variantDefinitions, context); if (variantOverride != null) { return(variantOverride.ToVariant()); } var target = StrategyUtils.GetNormalizedNumber(GetIdentifier(context), featureToggle.Name, totalWeight); var counter = 0; foreach (var variantDefinition in variantDefinitions) { if (variantDefinition.Weight != 0) { counter += variantDefinition.Weight; if (counter >= target) { return(variantDefinition.ToVariant()); } } } return(defaultVariant); }
public void GetNormalizedNumber_Variants() { // Normal cases StrategyUtils.GetNormalizedNumber("user1", "group1").Should().BeInRange(0, 100); // Strange inputs StrategyUtils.GetNormalizedNumber(null, null).Should().BeInRange(0, 100); StrategyUtils.GetNormalizedNumber("", "").Should().BeInRange(0, 100); StrategyUtils.GetNormalizedNumber("#%&/(", "ยง~:<> ").Should().BeInRange(0, 100); }
public void should_be_enabled_above_minimum_percentage() { var userId = "1574576830"; var groupId = ""; var minimumPercentage = StrategyUtils.GetNormalizedNumber(userId, groupId); var context = UnleashContext.New().UserId(userId).Build(); var gradualRolloutStrategy = new GradualRolloutUserIdStrategy(); for (var p = minimumPercentage; p <= 100; p++) { var paramseters = buildParams(p, groupId); var actual = gradualRolloutStrategy.IsEnabled(paramseters, context); actual.Should().BeTrue("should be enabled when " + p + "% rollout"); } }
public void should_be_enabled_above_minimum_percentage() { const string sessionId = "1574576830"; const string groupId = ""; var minimumPercentage = StrategyUtils.GetNormalizedNumber(sessionId, groupId); var context = UnleashContext.CreateBuilder().SessionId(sessionId).Build(); var gradualRolloutStrategy = new GradualRolloutSessionIdStrategy(); for (int p = minimumPercentage; p <= 100; p++) { var parms = BuildParams(p, groupId); var actual = gradualRolloutStrategy.IsEnabled(parms, context); Assert.True(actual); //"should be enabled when " + p + "% rollout" } }
private static StructureOffset IngameDataOffsets(StructureOffset inGameState) { var inGameDataAreaNameStructSearch = StrategyUtils.StringInSubStruct("Lush Hideout", subStructSize: 0x10, checkVmt: false); var inGameDataStructSearch = inGameDataAreaNameStructSearch.SubStructSearch(subStructSize: 0x600, checkVmt: true); var inGameData = new StructureOffset("InGameData", inGameDataStructSearch, maxStructSize: 0x800);//don't set to 0x1000 coz it can find multiple player offsets inGameState.Child.Add(inGameData); inGameData.Child.Add(new DataOffset("Area Name", inGameDataAreaNameStructSearch)); inGameData.AddByteSearch("Area Level", 60, false, 8); inGameData.Child.Add(new DataOffset("Tgt.Cols/Tgt.Rows(+0x8)/PtrAddr(+0x10)", new ValueReaderStrategy(new MultipleIntValueReader( new DefaultValueCompare <int>(33), new DefaultValueCompare <int>(0), new DefaultValueCompare <int>(33), new DefaultValueCompare <int>(0) ), 4))); inGameData.Child.Add(new DataOffset("NavPtr", new ValueReaderStrategy(new ArrayByteLengthValueCompare(288420), 8)));//288420 / 8 inGameData.Child.Add(new DataOffset("MapWidth", new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(380)), 4))); return(inGameData); }
protected override bool Run() { _ctrlRebellionOrganize.Run(); return(StrategyUtils.ChkStateRebellionTaskIsRun(StrategyRebellionTaskManagerMode.Organize)); }
public void GetNormalizedNumber_Is_Compatible_With_Java_And_Go_Implementations() { Assert.AreEqual(73, StrategyUtils.GetNormalizedNumber("123", "gr1")); Assert.AreEqual(25, StrategyUtils.GetNormalizedNumber("999", "groupX")); }
public bool IsEnabled(Dictionary <string, string> parameters, UnleashContext context, List <Constraint> constraints) { return(StrategyUtils.IsEnabled(this, parameters, context, constraints)); }
protected override bool Run() { return(StrategyUtils.ChkStateRebellionTaskIsRun(StrategyRebellionTaskManagerMode.StrategyRebellionTaskManager_ST)); }
public void normalized_values_are_the_same_across_node_java_go_and_dotnet_clients() { Assert.Equal(73, StrategyUtils.GetNormalizedNumber("123", "gr1")); Assert.Equal(25, StrategyUtils.GetNormalizedNumber("999", "groupX")); }
private void PlayerOffsets(StructureOffset inGameData) { var player = new StructureOffset("Player", StrategyUtils.StringSearch(new StringValueComparer("Metadata/Characters/", StringCompareType.StartWith)).SubStructSearch(0x50, true) .SubStructSearch(8, false), maxStructSize: 0x60); #region PositionedComponent var worldX = new FloatValueCompare(compareValue: 2375, tolerance: 50); var worldY = new FloatValueCompare(compareValue: 3646.739f, tolerance: 50); var worldPos = new MultipleFloatValueReader(worldX, worldY); var worldPosReader = new ValueReaderStrategy(worldPos, alignment: 4); var entityPositionedComponent = new StructureOffset("Entity.PositionedComponent", new SubPointersSearchStrategy(worldPosReader.Adapter(), subStructSize: 0x200, checkVmt: true), maxStructSize: 0x300); player.Child.Add(entityPositionedComponent); inGameData.Child.Add(player); #endregion #region Entity.ComponentLookup //Positioned seems always the first component, so you can pointerscan inside Entity to Positioned string using Structure Spider Advanced var entityComponentLookupSearch = new PointersSearchStrategy(new EntityComponentLookupPointerCompare(new List <string> { "Life", "Player" })); var entityLookupDeph2 = entityComponentLookupSearch.SubStructSearch(0x100, false); var entityLookupDeph1 = entityLookupDeph2.SubStructSearch(0x100, true); var entityInternalStruct = new StructureOffset("Entity.ComponentLookup", entityLookupDeph1, 8); player.Child.Add(entityInternalStruct); entityInternalStruct.OnOffsetsFound += delegate { var finalOffsets = new List <int>(); finalOffsets.AddRange(entityLookupDeph1.FoundOffsets); finalOffsets.AddRange(entityLookupDeph2.FoundOffsets); finalOffsets.AddRange(entityComponentLookupSearch.FoundOffsets); entityInternalStruct.FoundOffsets = finalOffsets; entityInternalStruct.DebugInfo = $"({entityLookupDeph1.FoundOffsets.Format()}, " + $"{entityLookupDeph2.FoundOffsets.Format()}, " + $"{entityComponentLookupSearch.FoundOffsets.Format()})"; if (entityInternalStruct.SearchStatus == OffsetSearchStatus.FoundSingle) { Entity.ComponentLookupOffset1 = entityLookupDeph1.FoundOffsets[0]; Entity.ComponentLookupOffset2 = entityLookupDeph2.FoundOffsets[0]; Entity.ComponentLookupOffset3 = entityComponentLookupSearch.FoundOffsets[0]; } }; var listSearch = new PointerValueCompare(new DelegateReferenceValueCompare <long>(() => entityPositionedComponent.BaseAddress)); var listPointerSearch = new PointersSearchStrategy(listSearch).SubStructSearch(100, false); var entityComponentList = new StructureOffset("Entity.ComponentList", listPointerSearch, 0x30); //not 0x30, actually it is on 0x8 entityComponentList.ShouldProcess = () => entityPositionedComponent.OffsetIsFound; player.Child.Add(entityComponentList); entityComponentList.OnOffsetsFound += delegate { if (entityComponentList.SearchStatus == OffsetSearchStatus.FoundSingle) { Entity.ComponentListOffset = entityComponentList.FoundOffsets[0]; } }; #endregion #region Components Fix #region Life var lifeComponent = new StructureOffset("LifeComponent", null, maxStructSize: 0x300); _initialStates.Add(lifeComponent); player.OnOffsetsFound += delegate { lifeComponent.BaseAddress = Entity.GetComponentAddress(player.BaseAddress, "Life"); }; //var searchMaxHp = new ValueReaderStrategy(new MultipleIntValueReader( // new DefaultValueCompare<int>(97), // new DefaultValueCompare<int>(97)), 4); //lifeComponent.Child.Add(new DataOffset("MaxHp", searchMaxHp)); //this will work only when they goes strictly one after another //lifeComponent.Child.Add(new DataOffset("CurHp", new ReturnExistingOffsetStrategy(searchMaxHp, 0x4))); lifeComponent.Child.Add(new DataOffset("MaxHp", new MultipleOffsetsSelectorOffsetSearch(new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(97)), 4), 2, 0))); lifeComponent.Child.Add(new DataOffset("CurHp", new MultipleOffsetsSelectorOffsetSearch(new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(97)), 4), 2, 1))); //var searchMaxMana = new ValueReaderStrategy(new MultipleIntValueReader( // new DefaultValueCompare<int>(74), // new DefaultValueCompare<int>(66)), 4); //lifeComponent.Child.Add(new DataOffset("MaxMana", searchMaxMana)); //lifeComponent.Child.Add(new DataOffset("CurMana", new ReturnExistingOffsetStrategy(searchMaxMana, 0x4))); lifeComponent.Child.Add(new DataOffset("MaxMana", new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(74)), 4))); lifeComponent.Child.Add(new DataOffset("CurMana", new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(66)), 4))); //var searchReservedMana = new ValueReaderStrategy(new MultipleIntValueReader( // new DefaultValueCompare<int>(0), // new DefaultValueCompare<int>(10)), 4); //lifeComponent.Child.Add(new DataOffset("ReservedFlatMana", searchReservedMana)); //lifeComponent.Child.Add(new DataOffset("ReservedPercentMana", new ReturnExistingOffsetStrategy(searchReservedMana, 0x4))); lifeComponent.Child.Add(new DataOffset("ReservedFlatMana", new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(0)), 4))); lifeComponent.Child.Add(new DataOffset("ReservedPercentMana", new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(10)), 4))); //var searchEs = new ValueReaderStrategy(new MultipleIntValueReader( // new DefaultValueCompare<int>(34), // new DefaultValueCompare<int>(34)), 4); //lifeComponent.Child.Add(new DataOffset("MaxEs", searchEs)); //lifeComponent.Child.Add(new DataOffset("CurEs", new ReturnExistingOffsetStrategy(searchEs, 0x4))); lifeComponent.Child.Add(new DataOffset("MaxEs", new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(34)), 4))); lifeComponent.Child.Add(new DataOffset("CurEs", new ValueReaderStrategy(new IntValueReader(new DefaultValueCompare <int>(34)), 4))); var buffStruct = StrategyUtils.StringInSubStruct("sand_stance", 0x20, false, false); //todo:set to 0x10 var buffStruct1 = buffStruct.SubStructSearch(0x20, false); var buffStruct2 = buffStruct1.SubStructSearch(0x20, false); var buffStruct3 = buffStruct2.SubStructSearch(0x20, false); lifeComponent.Child.Add(new StructureOffset("Buffs", buffStruct3, 0x20)); #endregion #region Positioned var positionedComponent = new StructureOffset("PositionedComponent", null, maxStructSize: 0x300); _initialStates.Add(positionedComponent); player.OnOffsetsFound += delegate { positionedComponent.BaseAddress = Entity.GetComponentAddress(player.BaseAddress, "Positioned"); }; positionedComponent.AddIntSearch("GridPosX", 218); positionedComponent.AddIntSearch("GridPosY", 335); positionedComponent.AddFloatSearch("WorldPosX", 2375, 50); positionedComponent.AddFloatSearch("WorldPosY", 3646.739f, 50); positionedComponent.AddFloatSearch("Rotation", 1.570f, 0.02f); positionedComponent.AddByteSearch("Reaction", 1); #endregion #region PlayerComponent var playerComponent = new StructureOffset("PlayerComponent", null, maxStructSize: 0x100); _initialStates.Add(playerComponent); player.OnOffsetsFound += delegate { playerComponent.BaseAddress = Entity.GetComponentAddress(player.BaseAddress, "Player"); }; playerComponent.AddIntSearch("Exp", 4219); playerComponent.AddIntSearch("Strength", 14); playerComponent.AddIntSearch("Dexterity", 29); playerComponent.AddIntSearch("Intelligence", 32); playerComponent.AddIntSearch("Level", 4); #endregion #endregion }