public void CreatePack() { Pack pack = new Pack(); PackContainer po = pack.Containers.AddItem("#ProjectOutput"); po.Files.AddItem("bin/release/QQnUtils.dll").FileHash = "qwqq"; po.Files.AddItem("bin/release/QQnUtils.pdb").FileSize = long.MaxValue; po.Files.AddItem("bin/release/QQnUtils.xml").LastWriteTimeUtc = DateTime.Now; PackContainer pc = pack.Containers.AddItem("#ProjectContent"); po.Files.AddItem("QQnUtils.doc").FileHash = "q"; po.Files.AddItem("QQnDef.xsd").FileSize = 123456; PackContainer ps = pack.Containers.AddItem("#Scripts"); ps.Files.AddItem("Setup/QQnUtils.wxs").LastWriteTimeUtc = DateTime.Now; XmlDocument doc = new XmlDocument(); using (XmlWriter xw = doc.CreateNavigator().AppendChild()) { xw.WriteStartElement("Pack", ""); // Place al elements in default namespace for easy quering Tokenizer.TryWriteXml(xw, pack); } Assert.That(doc.SelectSingleNode("/*"), Is.Not.Null); Assert.That(doc.SelectNodes("//Item").Count, Is.EqualTo(6)); Pack pack2; Tokenizer.TryParseXml(doc.DocumentElement, out pack2); foreach (PackContainer ipc in pack.Containers) { PackContainer ipc2 = pack2.Containers[ipc.Name]; Assert.That(ipc2, Is.Not.Null); Assert.That(ipc2.Name, Is.EqualTo(ipc.Name)); foreach (PackFile ipf in ipc.Files) { PackFile ipf2 = ipc2.Files[ipf.Name]; Assert.That(ipf2.Name, Is.EqualTo(ipf.Name)); Assert.That(ipf2.FileHash, Is.EqualTo(ipf.FileHash)); Assert.That(ipf2.FileSize, Is.EqualTo(ipf.FileSize)); Assert.That(ipf2.LastWriteTimeUtc, Is.EqualTo(ipf.LastWriteTimeUtc)); // This also checks time normalization } } }
public Pack CreateDefinition(TBLogFile file) { BuildOrigin myOrigin = null; foreach (BuildOrigin bo in BuildOrigins) { if (bo.LogFile == file) { myOrigin = bo; break; } } Pack p = new Pack(); TBLogConfiguration config = file.Configurations[0]; TBLogTarget target = config.Target; TBLogAssembly asm = config.Assembly; if (!string.IsNullOrEmpty(target.KeySrc)) { p.StrongNameKey = StrongNameKey.LoadFrom(QQnPath.Combine(file.ProjectPath, target.KeySrc)); } else if (!string.IsNullOrEmpty(target.KeyContainer)) { p.StrongNameKey = StrongNameKey.LoadFromContainer(target.KeyContainer, false); } if (asm != null && !string.IsNullOrEmpty(asm.AssemblyName)) { AssemblyName name = new AssemblyName(asm.AssemblyName); p.Version = name.Version; } PackContainer po = p.Containers.AddItem("#ProjectOutput"); po.ContainerDir = config.OutputPath; po.BaseDir = QQnPath.Combine(file.ProjectPath); foreach (TBLogItem item in file.AllProjectOutput) { if (item.IsShared) { continue; } PackFile pf = po.Files.AddItem(QQnPath.EnsureRelativePath(po.BaseDir, item.FullSrc)); pf.StreamName = item.Src; } PackContainer ct = p.Containers.AddItem("#Content"); ct.ContainerDir = ""; po.BaseDir = file.ProjectPath; foreach (TBLogItem item in file.AllContents) { if (item.IsShared) { continue; } PackFile pf = po.Files.AddItem(QQnPath.EnsureRelativePath(po.BaseDir, item.FullSrc)); } myOrigin.Pack = p; return(p); }
public Dictionary<int, List<PackContainer>> divisiblePacks; //List of all possible pack divisibles between 0 and maximum. //Setup function to create the divisible amounts for storage and quick access. (Dictionary divisiblePacks). //Processes all pack sizes with preference being for larger pack sizes allocated first. /*Pseudocode version: * Obtain single pack multiples, e.g. (15), 15, 30, 45. * Add these to divisiblePacks, and save a seperate copy for later convenience in step 2 and 4. * Obtain combination packs between two different packs (combinations). e.g. (15, 3), 15+3, 15 + 3 + 3. * Find values between minimum and maximum that have been missed (as this section is meant to be covered consecutively). * Using the conveniently saved singles pack multiples, subtract this value from the missing values and check the result against the divisiblePacks library. * This will take advantage of the combo packs in step 2. (15, 10, 4) e.g. 31 - 15 = 16. 16 is in the list as 4 x 4. */ public void CreateDivisibles() { //Temporary storage of divisibles between 0 and max using only one pack size. Dictionary<int, List<PackContainer>> temporarySingleDivisibles = new Dictionary<int, List<PackContainer>>(); HashSet<int> alreadyContained = new HashSet<int>(); //Quick storage of already covered values. //1st: Get list of all single pack multiples between 0 and max; Stop upon value match or out of bounds. //Iterates through all pack sizes and stores seperately from divisiblePacks. for (int i = 0; i < packSizes.Count; i++) { int packSize = packSizes[i]; //For convenient access. List<PackContainer> results = new List<PackContainer>(); //Imitates divisiblePacks however ONLY FOR SINGLE COMBINATIONS, seperate storage. int iteration = 1; //Current iteration (used to store quantity) int current = packSize; //Current quantity * pack size. //Multiply pack size within bounds. while (current < maximum) { //Ignore duplicate entries. if (alreadyContained.Contains(current)) { break; } PackContainer pack = new PackContainer(); //Temporary storage, AS MENTIONED IN DECLARATION, SECONDARY USE OF STRUCT. See List<PackContainer> results pack.packSize = current; //Saves the current divisible total (similar to Dictionary key of divisible packs). pack.quantity = iteration; //Saves the quantity for this particular total. results.Add(pack); alreadyContained.Add(current); //This total is covered, remember to prevent later duplicates. iteration++; current += packSize; } temporarySingleDivisibles.Add(packSize, results); //Save the divisibles between the bounds for this single pack size. } //For each pack possible pack size, add to divisiblePacks to save temporary storage single divisibles (only needed later). foreach (int packSize in packSizes) { List<PackContainer> packSizeMultiples = temporarySingleDivisibles[packSize]; //Iterate through each pack multiple, eg pack size of 3: 3, 6, 9, 12. foreach (PackContainer packMultiple in packSizeMultiples) { List<PackContainer> toAdd = new List<PackContainer>(); //List of only one pack container (as only one pack size is used). PackContainer temp = new PackContainer(); temp.packSize = packSize; //Proper use of pack container, pack size is now size, not total including quantity. temp.quantity = packMultiple.quantity; //Quantity of pack size to reach total. toAdd.Add(temp); divisiblePacks.Add(packMultiple.packSize, toAdd); //Add new divisible pack with actual divisible number and associated pack size and quantity. } } //2nd: Get list of combinations between two packs, max height is count. //First pack combo. Should not hit very last pack size. Hand shake circle problem (mentioned at top of script). for (int i = 0; i < packSizes.Count - 1; i++) { List<PackContainer> outerTemp = temporarySingleDivisibles[packSizes[i]]; //Outer pack size. //Second pack to make up two pack combo. Allowed to hit final pack. for (int x = i + 1; x < packSizes.Count; x++) { //here we can add directly to the divisible packs. No use for temporary storage. List<PackContainer> innerTemp = temporarySingleDivisibles[packSizes[x]]; //Inner pack size. //Iterate through first pack combo's second. foreach (PackContainer outer in outerTemp) { //Cover all possible combo's with pack one (iterating through pack twos combo's). foreach (PackContainer inner in innerTemp) { int result = outer.packSize + inner.packSize; //The combination total. //Within bounds. if (result > maximum) { break; } //If this total has not yet been covered. if (!alreadyContained.Contains(result)) { List<PackContainer> toAdd = new List<PackContainer>(); //Pack combination to be added, more than one pack size. PackContainer temp = new PackContainer(); //Temp storage for pack, data changed with each pack size. //Pack size 1. temp.packSize = packSizes[i]; temp.quantity = outer.quantity; toAdd.Add(temp); //Pack size 2. temp.packSize = packSizes[x]; temp.quantity = inner.quantity; toAdd.Add(temp); //Save total to memory (to prevent duplicates) and add to divisible packs. alreadyContained.Add(result); divisiblePacks.Add(result, toAdd); } } } } } //3rd: Find any values between the minimum and maximum that still require calculating. List<int> missingValues = new List<int>(); //Missing values to be covered between min and max. for (int i = minimum; i <= maximum; i++) //Between bounds, find missing values and add to list. { if (!alreadyContained.Contains(i)) { missingValues.Add(i); } } //4th: Traverse missing values. Subtract values from the temp singles list in decreasing order, then compare result to already divisible packs. foreach (int missingValue in missingValues) { //Traverse pack sizes. for (int i = 0; i < packSizes.Count; i++) { List<PackContainer> outerTemp = temporarySingleDivisibles[packSizes[i]]; //Convenient access to single pack size combinations. //For each total combination in that pack. foreach (PackContainer pack in outerTemp) { int result = missingValue - pack.packSize; //New result to find from divisibles list. //Success, found number in divisibles list. if (divisiblePacks.ContainsKey(result)) { //Save initially subtracted pack size and quantity. PackContainer outerContainerTemp = new PackContainer(); outerContainerTemp.packSize = packSizes[i]; outerContainerTemp.quantity = pack.quantity; //Creates a temporary list for what to add. Saves the packs and quantities for the new value. List<PackContainer> toAdd = new List<PackContainer>(); List<PackContainer> FromBase = divisiblePacks[result]; //Combine initially subtracted pack and new pack division. Preference to keep in sorted decreasing order. foreach (PackContainer toCheck in FromBase) { //If the outer pack has a higher value, add before the other packs. if (outerContainerTemp.packSize > toCheck.packSize) { toAdd.Add(outerContainerTemp); } toAdd.Add(toCheck); } //Save the new total and pack size + quantities list to of divisiblePacks. divisiblePacks.Add(missingValue, toAdd); alreadyContained.Add(missingValue); break; //Escape this missing value. } } //From above break, with value already added, escape this missing value. if (alreadyContained.Contains(missingValue)) { break; //Escape this missing value. } } } }
public override async Task <EntityView> Run(EntityView entityView, CommercePipelineExecutionContext context) { if (entityView == null || !entityView.Action.Equals("ListMaster-ExportList", StringComparison.OrdinalIgnoreCase)) { return(entityView); } try { var listName = entityView.ItemId; var directoryPath = @"C:\Users\kha\Documents\ExportedEntities\"; var asPack = entityView.Properties.First(p => p.Name == "AsPack").Value ?? ""; var incremental = entityView.Properties.First(p => p.Name == "Incremental").Value ?? ""; var listFriendlyName = entityView.ItemId.Replace("Entity-ManagedList-", ""); var asPackBool = System.Convert.ToBoolean(asPack); var incrementalBool = System.Convert.ToBoolean(incremental); var listCount = await this._commerceCommander.Command <GetListCountCommand>().Process(context.CommerceContext, listFriendlyName); var listMembers = new StringBuilder(); var listMembersSerialized = new StringBuilder(); var packContainer = new PackContainer(); var managedList = await this._commerceCommander.Command <GetManagedListCommand>().Process(context.CommerceContext, listFriendlyName); if (managedList != null) { var publishedListEntities = managedList.GetComponent <ListEntitiesInPublish>(); publishedListEntities.LastPublishStart = DateTimeOffset.UtcNow; publishedListEntities.LastPublishCount = 0; if (!incrementalBool) { publishedListEntities.LastRow = 0; publishedListEntities.PublishCycle++; publishedListEntities.PublishIteration = 0; } else { publishedListEntities.PublishIteration++; } var historyComponent = managedList.GetComponent <HistoryComponent>(); historyComponent.History.Add(new HistoryEntryModel { Name = "StartPublish", EventMessage = $"Start Publish of List:{listName} ({listCount})" }); var managedListPersistResult = await this._commerceCommander.PersistEntity(context.CommerceContext, managedList); JsonSerializerSettings serializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, NullValueHandling = NullValueHandling.Ignore, MaxDepth = 100, Formatting = Formatting.Indented }; while (publishedListEntities.LastRow < listCount) { var arg = new FindEntitiesInListArgument(typeof(CommerceEntity), listFriendlyName, publishedListEntities.LastRow, 100); var result = await this._commerceCommander.Pipeline <FindEntitiesInListPipeline>().Run(arg, context.CommerceContext.GetPipelineContextOptions()); foreach (var listEntity in result.List.Items) { var serializedEntity = JsonConvert.SerializeObject(listEntity, serializerSettings); listMembersSerialized.Append(serializedEntity + ","); managedList.TotalItemCount++; packContainer.Entities.Add(listEntity); listMembers.AppendLine(); publishedListEntities.LastPublishCount++; } publishedListEntities.LastRow = publishedListEntities.LastRow + 100; } if (asPackBool) { packContainer.ManagedLists.Add(managedList); var serializedPackContainer = JsonConvert.SerializeObject(packContainer, serializerSettings); var writePath = directoryPath + $"{context.CommerceContext.Environment.Name}-Pack-" + managedList.Id + $"_{DateTime.UtcNow.ToString("yyyy-MM-dd-hh-mm")}.json"; if (incrementalBool) { writePath = directoryPath + $"{context.CommerceContext.Environment.Name}.{managedList.Name}-Pack-{publishedListEntities.PublishCycle.ToString("00#")}-{publishedListEntities.PublishIteration.ToString("00#")}-{DateTime.UtcNow.ToString("yyyy-MM-dd-hh-mm")}.json"; } else { writePath = directoryPath + $"{context.CommerceContext.Environment.Name}.{managedList.Name}-Pack-{publishedListEntities.PublishCycle.ToString("00#")}-000-{DateTime.UtcNow.ToString("yyyy-MM-dd-hh-mm")}.json"; } File.WriteAllText(writePath, serializedPackContainer); this._commerceCommander.Command <GzipCommand>().Compress(context.CommerceContext, new DirectoryInfo(directoryPath)); } historyComponent.History.Add(new HistoryEntryModel { Name = "ListPublish", EventMessage = $"Published List:{listName} ({listCount})" }); publishedListEntities.LastPublishEnd = DateTimeOffset.UtcNow; await this._commerceCommander.PersistEntity(context.CommerceContext, managedList); } } catch (Exception ex) { context.Logger.LogError($"Catalog.DoActionAddList.Exception: Message={ex.Message}"); } return(entityView); }