private void FinishAddingRecord(string primaryId, string value, FeaturedRecLists recs, FeaturedRecCondition c) { //NOTE: This assumes one product field with a comma separated list for includes // and a second for excludes for each product // includes will be ranked in order of how they are listed var newRecs = value.Split(',').Select(p => p.Trim()) .Where(r => !string.IsNullOrEmpty(r) && !r.Equals("-1")).ToList(); if (!newRecs.Any()) return; foreach (var r in newRecs) { if (c.Include) //items are recommended { if (recs.Blocked.Count > 0 && recs.Blocked.Any(x => x.Equals(r))) //remove from blocked list Records[primaryId].Blocked.Remove(r); if (recs.Recommended.Count > 0 && recs.Recommended.Any(x => x.Equals(r))) continue; //already in the recommended list Records[primaryId].Recommended.Add(r); } else //items are blocked { if (recs.Recommended.Count > 0 && recs.Recommended.Any(x => x.Equals(r))) //remove from recommended list Records[primaryId].Recommended.Remove(r); if (recs.Blocked.Count > 0 && recs.Blocked.Any(x => x.Equals(r))) continue; //already in the blocked list Records[primaryId].Blocked.Add(r); } } }
public FeaturedRecommendations(List<string[]> data) { if (data == null) return; //get column order (data[0] holds the column headers) and determine whether the file has ranking or likelihood columns var columnNames = new string[] { "ProductId", "RecId", "Ranking", "Likelihood" }; var headerPositions = new int[columnNames.Length]; var headerRow = data[0]; data.RemoveAt(0); for (var i = 0; i < columnNames.Length; i++) { var found = false; for (var j = 0; j < headerRow.Length; j++) { if (!headerRow[j].Equals(columnNames[i], StringComparison.OrdinalIgnoreCase)) continue; headerPositions[i] = j; found = true; break; } if (!found) { if (i > 1) //ranking and Likelihood columns are optional headerPositions[i] = -1; else throw new Exception(string.Format("Cannot read Featured Recs. Missing column {0}", columnNames[i])); } } var convertLikelihood = headerPositions[2] == -1 && headerPositions[3] > -1; //Ranking is missing and Likelihood exists //first parse the rows into an initial dictionary that preserves any rankings from the file var firstPass = new Dictionary<string, List<GeneratorFeaturedRec>>(); foreach (var row in data) { var rec = new GeneratorFeaturedRec { PrimaryId = row[headerPositions[0]], RecommendedId = row[headerPositions[1]] }; if (convertLikelihood) { var likelihood = Input.SafeFloatConvert(row[headerPositions[3]]); rec.Ranking = likelihood <= 0F ? 0 : (int)Math.Floor(100 * (1.0 - likelihood) + .001); } else if (headerPositions[2] >= 0) rec.Ranking = Input.SafeIntConvert(row[headerPositions[2]]); else rec.Ranking = -1; //set it below instead List<GeneratorFeaturedRec> existing; if (firstPass.TryGetValue(rec.PrimaryId, out existing)) { if (rec.Ranking == -1) rec.Ranking = existing.Select(x => x.Ranking).Max() + 1; firstPass[rec.PrimaryId].Add(rec); } else { if (rec.Ranking == -1) rec.Ranking = 1; firstPass.Add(rec.PrimaryId, new List<GeneratorFeaturedRec> { rec }); } } //now cleanup rankings and convert to ManualRec format Records = new Dictionary<string, FeaturedRecLists>(); foreach (var f in firstPass) { var rec = new FeaturedRecLists(); var blocked = f.Value.Where(x => x.Ranking.Equals(0)); if (blocked.Any()) rec.Blocked.AddRange(blocked.Select(x => x.RecommendedId)); var recommended = f.Value.Where(x => x.Ranking > 0).ToList(); if (recommended.Any()) { recommended.Sort(); //sorts by ranking rec.Recommended.AddRange(recommended.Select(x => x.RecommendedId)); } Records.Add(f.Key, rec); } }
public void AddRecords(string primaryId, XElement product, List<FeaturedRecCondition> conditions) { if (conditions == null || !conditions.Any()) return; //each condition defines all recs for a given primary id FeaturedRecLists recs; if (!Records.TryGetValue(primaryId, out recs)) { recs = new FeaturedRecLists(); Records.Add(primaryId, recs); } //note: there could be a second condition for the same id if one is for excludes foreach (var c in conditions) { var value = Input.GetValue(product, c.ResultField); if (string.IsNullOrEmpty(value)) continue; FinishAddingRecord(primaryId, value, recs, c); } }