private static void SetUserAgent(VisitorSegment segment) { var userAgent = FileHelpers.ReadLinesFromResource <GeoData>("ExperienceGenerator.Data.useragents.txt") .Exponential(.8, 8); segment.RequestVariables.Add(Variables.Random("UserAgent", userAgent)); }
public void DevicesFactory_WithDeviceDistibution_ShouldSetRequiredUserAgents(XGenParser parser, DeviceRepository repo) { var factory = XGenParser.Factories["Devices"]; var devices = repo.GetAll(); List <string> userAgentList = new List <string>(); var definition = JObject.Parse(@"{ 'sony xperia z3':0.1, 'sony xperia z2':0.1, 'nokia lumia 930':0.3, 'macintosh pc':0.3, 'microsoft xbox one':0.2}"); for (int i = 0; i < 1000; i++) { var segment = new VisitorSegment(""); factory.UpdateSegment(segment, definition, parser); var target = new Request(); segment.VisitorVariables.First(x => x.ProvidedVariables.Contains("UserAgent")).SetValues(target); userAgentList.Add(target.Variables["UserAgent"].ToString()); } userAgentList.Count.Should().Be(1000); foreach (var device in definition) { var dev = devices.First(x => x.Id == device.Key); var expected = device.Value.Value <double>(); (userAgentList.Count(x => x == dev.UserAgent) / 1000d).Should().BeApproximately(expected, 0.04); } }
public override void SetDefaults(VisitorSegment segment, XGenParser parser) { if (_setDefaults != null) { _setDefaults(segment, parser); } }
public override void UpdateSegment(VisitorSegment segment, JToken definition, XGenParser parser) { if (_updateSegment != null) { _updateSegment(segment, definition, parser); } }
private static void Main2(string[] args) { Randomness.Seed(1337); var segment = new VisitorSegment("Test"); segment.VisitorVariables.Add(Variables.Fixed("Country", "DK")); //Simulate visitors from Jan 1 2012 until now segment.StartDateTime(new DateTime(2012, 1, 1), DateTime.Now, //Create a linear trend in year d => d.Year(trend => trend.SetLevel(0).LineRelativePercentage(1, 1)) //Add a peak in the summer .PartOfYear(trend => trend.AddPeak(0.5, 0.1, pct: true))); var simulator = new SegmentBasedSimulator(segment); //Create a 1000 visitors. These are ordered by start date foreach (var visitor in simulator.NextVisitors(1000)) { System.Console.Out.WriteLine("."); var ctx = new SitecoreRequestContext("http://sc80rev150209/", visitor); using (var visit = ctx.NewVisit()) { //Request home page as if coming from Google visit.Request("/", TimeSpan.FromSeconds(2), new { Referrer = "http://www.google.com" }); //Request home page again var info = visit.Request("/", TimeSpan.FromSeconds(2)); //"info" contains information from Sitecore, including the item displayed, it's fields, the visit's current VisitData from the tracker etc. //This can be used to change the behavior of the visit if (info.VisitData.ContactVisitIndex == 2) { } } //Wait 14 days before making the next visit ctx.Pause(TimeSpan.FromDays(14)); using (var visit = ctx.NewVisit()) { visit.Request("/", TimeSpan.FromSeconds(2)); System.Console.Out.WriteLine(visit.VisitData.ContactVisitIndex); } } }
static void Skynet() { var serverUrl = "http://xdbrpc.local/"; var testUrl = "/testPage"; var goalPage1 = "/trigger-goal1"; //var goalPage2 = "/trigger-goal2"; Randomness.Seed(1337); var random = Randomness.Random; var segment = new VisitorSegment("Test visitors"); var sim = new SegmentBasedSimulator(segment); foreach (var visitorContext in sim.NextVisitors(1000) .Select(v => new SitecoreRequestContext(serverUrl, v))) { using (var visitContext = visitorContext.NewVisit()) { visitContext.Request(goalPage1); var response = visitContext.Request(testUrl); if (response.Test == null) { throw new Exception("A test was expected"); } var pageVersionIndex = response.Test.Variables.FindIndex(v => v.Label == "Page version"); if (pageVersionIndex == -1) { throw new Exception("Component not found"); } var conversionRate = response.Test.Combination[pageVersionIndex] == 0 ? 0.5 : 0.1; if (random.NextDouble() < conversionRate) { visitContext.Request(goalPage1); } } } }
public override void UpdateSegment(VisitorSegment segment, JToken definition, XGenParser parser) { var weights = Enumerable.Range(1, 12).Select(i => 0d).ToArray(); foreach (var kv in (JObject)definition) { weights[int.Parse(kv.Key) - 1] = kv.Value.Value <double>(); } segment.DateGenerator.PartOfYear(t => { t.Clear(); t.MoveAbsolute(0, (weights[0] + weights[11]) / 2); for (var i = 0; i < weights.Length; i++) { t.LineAbsolute(_partsOfYears[i + 1], weights[i]); } t.LineAbsolute(1, (weights[0] + weights[11]) / 2); }); }
public void DevicesFactory_EmptyDefinition_ShouldSetRandomUserAgent() { var factory = XGenParser.Factories["Devices"]; List <string> userAgentList = new List <string>(); var definition = JObject.Parse(@"{}"); for (int i = 0; i < 10; i++) { var segment = new VisitorSegment(""); factory.UpdateSegment(segment, definition, null); var target = new Request(); segment.VisitorVariables.First(x => x.ProvidedVariables.Contains("UserAgent")).SetValues(target); userAgentList.Add(target.Variables["UserAgent"].ToString()); } //all useragent should be set and not be null userAgentList.Count.Should().Be(10); userAgentList.All(x => !string.IsNullOrWhiteSpace(x)).Should().BeTrue(); }
public virtual Func <VisitorSegment> ParseSegments(JToken definition, JobType type) { if (definition == null || !definition.Any()) { throw new Exception("At least one segment is required"); } var segments = new Dictionary <string, KeyValuePair <VisitorSegment, double> >(); foreach (var kv in (JObject)definition) { var segment = new VisitorSegment(kv.Key); var def = (JObject)kv.Value; segment.DateGenerator.Hour(t => t.AddPeak(0.4, 0.25, 0, pct: true).AddPeak(0.8, 0.1, 2, 0.2, pct: true)); //SetUserAgent(segment); if (type != JobType.Contacts) { segment.VisitorVariables.Add(Variables.Random("VisitCount", new PoissonGenerator(3).Truncate(1, 10))); segment.VisitorVariables.Add(Variables.Random("PageViews", new PoissonGenerator(3).Truncate(1, 10))); segment.VisitVariables.Add(Variables.Random("Pause", new NormalGenerator(7, 7).Truncate(0.25))); } var visitorBehavior = new RandomWalk(_sitecoreRoot); segment.Behavior = () => visitorBehavior; segments.Add(kv.Key, new KeyValuePair <VisitorSegment, double>(segment, def.Value <double?>("Weight") ?? 1d)); var copy = def["Copy"]; if (copy != null) { foreach (var name in copy.Values <string>()) { segment.Copy(segments[name].Key); } } var usedFactories = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); foreach (var prop in def) { if (prop.Key == "Weight" || prop.Key == "Copy") { continue; } try { Factories[prop.Key].UpdateSegment(segment, prop.Value, this); usedFactories.Add(prop.Key); } catch (KeyNotFoundException) { throw new Exception(string.Format("No factory registered for {0}", prop.Key)); } } foreach (var factory in Factories.Where(factory => !usedFactories.Contains(factory.Key))) { factory.Value.SetDefaults(segment, this); } segment.SortVariables(); } return(segments.Values.Weighted()); }
private static void SetUserAgent(VisitorSegment segment) { var userAgent = new DeviceRepository().GetAll().Select(d => d.UserAgent).Exponential(.8, 8); segment.RequestVariables.Add(Variables.Random("UserAgent", userAgent)); }
public virtual IEnumerable <VisitorSegment> ParseContacts(JToken definition, JobType type) { var segments = new List <VisitorSegment>(); if (JobType.Contacts != type) { return(segments); } foreach (var contact in (JArray)definition) { if (contact["interactions"] == null) { continue; } foreach (var interactionJObject in contact["interactions"]) { var segment = new VisitorSegment(contact.Value <string>("email")); var interaction = interactionJObject.ToObject <Interaction>(); //set city if (interaction.GeoData != null) { var city = _geoDataRepository.Cities.FirstOrDefault(x => x.GeoNameId == interaction.GeoData.GeoNameId); segment.VisitorVariables.Add(new GeoVariables(() => city)); } //set contact segment.VisitVariables.Add(ExtractContact(contact)); //set channel (can be overriden below) segment.VisitVariables.Add(new SingleVisitorVariable <string>("Channel", visit => interaction.ChannelId)); //set search options if (!string.IsNullOrEmpty(interaction.SearchEngine)) { var searchEngine = SearchEngine.SearchEngines.First(s => s.Id.Equals(interaction.SearchEngine, StringComparison.InvariantCultureIgnoreCase)); if (!string.IsNullOrEmpty(interaction.SearchKeyword)) { var searchKeywords = interaction.SearchKeyword.Split(' '); segment.VisitVariables.AddOrReplace(new ExternalSearchVariable(() => searchEngine, () => searchKeywords)); } } var pageItemInfos = interaction.Pages?.ToArray() ?? Enumerable.Empty <PageItemInfo>(); var pages = new List <PageDefinition>(); foreach (var page in pageItemInfos) { var pageDefinition = new PageDefinition { Path = page.Path }; //set goals if (page.Goals != null) { pageDefinition.RequestVariables.Add("TriggerEvents", page.Goals.Select(x => new TriggerEventData { Id = x.Id, Name = x.DisplayName, IsGoal = true }).ToList()); } pages.Add(pageDefinition); } //set userAgent SetUserAgent(segment); //set datetime segment.DateGenerator.Start = DateTime.Today.AddHours(12).AddMinutes(Randomness.Random.Next(-240, 240)).AddSeconds(Randomness.Random.Next(-240, 240)).Add(TimeSpan.Parse(interaction.Recency)); //set outcomes if (interaction.Outcomes != null) { var outcomes = interaction.Outcomes.Select(x => x.Id.ToString()); var value = new NormalGenerator(10, 5).Truncate(1); segment.VisitVariables.AddOrReplace(new OutcomeVariable(() => new HashSet <string>(outcomes), value.Next)); } //set campaign (can be overriden below) if (!string.IsNullOrEmpty(interaction.CampaignId) && pageItemInfos.Any()) { var pageItemInfo = pageItemInfos.First(); pageItemInfo.Path = pageItemInfo.Path + "?sc_camp=" + interaction.CampaignId; } var visitorBehavior = new StrictWalk(_sitecoreRoot, pages); segment.Behavior = () => visitorBehavior; segments.Add(segment); } } return(segments); }
public virtual IEnumerable <VisitorSegment> ParseContacts(JToken definition, JobType type) { var segments = new List <VisitorSegment>(); if (JobType.Contacts != type) { return(segments); } foreach (var contact in (JArray)definition) { if (contact["interactions"] == null) { continue; } foreach (var interactionJObject in contact["interactions"]) { var segment = new VisitorSegment(contact.Value <string>("email")); var interaction = interactionJObject.ToObject <Interaction>(); //set city if (interaction.GeoData != null) { var city = _geoDataRepository.Cities.FirstOrDefault(x => x.GeoNameId == interaction.GeoData.GeoNameId); segment.VisitorVariables.Add(new GeoVariables(() => city)); } //set contact segment.VisitVariables.Add(ExtractContact(contact)); //set channel (can be overriden below) segment.VisitVariables.Add(new SingleVisitorVariable <string>("Channel", visit => interaction.ChannelId)); //set search options if (!string.IsNullOrEmpty(interaction.SearchEngine)) { var searchEngine = SearchEngine.SearchEngines.First(s => s.Id.Equals(interaction.SearchEngine, StringComparison.InvariantCultureIgnoreCase)); if (!string.IsNullOrEmpty(interaction.SearchKeyword)) { var searchKeywords = interaction.SearchKeyword.Split(' '); segment.VisitVariables.AddOrReplace(new ExternalSearchVariable(() => searchEngine, () => searchKeywords)); } } //set userAgent SetUserAgent(segment); //set datetime //Visits while happen in this interval adjusted for the interaction's local time. const double minHour = 6, maxHour = 23; //Does the interaction have a time zone? If not use UTC. var tz = interaction.GeoData?.TimeZoneInfo ?? TimeZoneInfo.Utc; //Pick a random time between min and max hour. DateTimeKind.Unspecified is used because we are converting to local time next. var startDate = DateTime.SpecifyKind(DateTime.Today.AddHours(minHour + Randomness.Random.NextDouble() * (maxHour - minHour)), DateTimeKind.Unspecified); startDate = TimeZoneInfo.ConvertTimeToUtc(startDate, tz); //Convert from local time to UTC. //"Recency" indicates how many days ago the visit happened. Hence substract this number of days. int parseRecency; var success = Int32.TryParse(interaction.Recency, out parseRecency); if (!success) { throw new Exception("Error parsing interaction recency (days since interaction) to integer value"); } var ensurePositiveRecency = Math.Abs(parseRecency); segment.DateGenerator.Start = startDate.Add(-TimeSpan.Parse(ensurePositiveRecency.ToString())); //set outcomes if (interaction.Outcomes != null) { var outcomes = interaction.Outcomes.Select(x => x.Id.ToString()); var value = new NormalGenerator(10, 5).Truncate(1); segment.VisitVariables.AddOrReplace(new OutcomeVariable(() => new HashSet <string>(outcomes), value.Next)); } var pageItemInfos = interaction.Pages?.ToArray() ?? Enumerable.Empty <PageItemInfo>(); var pages = new List <PageDefinition>(); //set campaign (can be overriden below) if (!string.IsNullOrEmpty(interaction.CampaignId) && pageItemInfos.Any()) { var pageItemInfo = pageItemInfos.First(); pageItemInfo.Path = pageItemInfo.Path + "?sc_camp=" + interaction.CampaignId; } foreach (var page in pageItemInfos) { var pageDefinition = new PageDefinition { Path = page.Path }; //set goals if (page.Goals != null) { pageDefinition.RequestVariables.Add("TriggerEvents", page.Goals.Select(x => new TriggerEventData { Id = x.Id, Name = x.DisplayName, IsGoal = true }).ToList()); } pages.Add(pageDefinition); } var visitorBehavior = new StrictWalk(_sitecoreRoot, pages); segment.Behavior = () => visitorBehavior; segments.Add(segment); } } return(segments); }
public virtual void UpdateSegment(VisitorSegment segment, JToken definition, XGenParser parser) { }
public virtual void SetDefaults(VisitorSegment segment, XGenParser parser) { }
public override void SetDefaults(VisitorSegment segment, XGenParser parser) { UpdateSegment(segment, new JObject(), parser); }
public override void UpdateSegment(VisitorSegment segment, JToken definition, XGenParser parser) { var randomPagePct = definition.Value <double?>("RandomPagePercentage") ?? 0.2; Func <string> siteId = () => "website"; if (definition["Site"] != null && definition["Site"].Any()) { siteId = parser.ParseWeightedSet <string>(definition["Site"]); } Func <string> landingPage = () => null; if (definition["Item"] != null && definition["Item"].Any()) { landingPage = parser.ParseWeightedSet <string>(definition["Item"]); } else { randomPagePct = 1d; } var randomPages = new Dictionary <string, Func <ItemInfo> >(); foreach (var site in parser.InfoClient.Sites.Values .Where(s => !string.IsNullOrEmpty(s.StartPath))) { var root = parser.InfoClient.Query(site.StartPath, maxDepth: null).FirstOrDefault(); if (root == null) { throw new Exception(string.Format("Root item for site {0} does not exist ({1})", site.Id, site.StartPath)); } var homePct = 0.5; if (root.Children.Count == 0) { homePct = 1; } var other = GetDescendants(root.Children).Select(t => t.Item1) .Where(item => item.HasLayout).OrderBy(item => Randomness.Random.NextDouble()) .Exponential(0.8, 10); randomPages[site.Id] = () => Randomness.Random.NextDouble() < homePct ? root : other(); } segment.VisitVariables.AddOrReplace(new LandingPageVariable(() => { var page = parser.InfoClient.GetItemInfo(landingPage()); var site = parser.InfoClient.Sites[siteId()]; if (page == null || Randomness.Random.NextDouble() < randomPagePct) { return(Tuple.Create(site, randomPages[site.Id]())); } for (var i = 0; i < 10 && !page.Path.StartsWith(site.StartPath); i++) { site = parser.InfoClient.Sites[siteId()]; } return(Tuple.Create(site, page)); }, parser.InfoClient)); }