private void SetCellValue(int value) { if (IsConstrained) { throw new InvalidOperationException("Value cannot be set on constrained cells."); } if (value != 0 && PossibleValues.All(v => v != value)) { throw new InvalidOperationException($"Value {value} must be within the list of possible values [{string.Join(", ",PossibleValues)}]"); } var oldValue = CurrentValue; CurrentValue = 0; row.RestoreValueOnAllCells(oldValue); column.RestoreValueOnAllCells(oldValue); quadrant.RestoreValueOnAllCells(oldValue); CurrentValue = value; row.RemoveValueFromAllCells(CurrentValue); column.RemoveValueFromAllCells(CurrentValue); quadrant.RemoveValueFromAllCells(CurrentValue); }
public Rule(SortedSet <string> premise, SortedSet <string> conclusion, double c) { this.premise = premise; this.conclusion = conclusion; this.confidence = c; var itemsWithPremise = Program.data.Where(x => premise.All(x.tags.ContainsKey) && (x.rank != null)); var itemsWithPremiseNotConclusion = itemsWithPremise.Where(x => !(conclusion.All(x.tags.ContainsKey))); var ratingWithPremiseAndConclusion = itemsWithPremise.Where(x => conclusion.All(x.tags.ContainsKey)).Average(i => i.rank.Value); var ratingWithPremiseNotConclusion = (itemsWithPremiseNotConclusion.Count() > 0) ?itemsWithPremiseNotConclusion.Average(i => i.rank.Value) : ratingWithPremiseAndConclusion; deltaRating = ratingWithPremiseAndConclusion - ratingWithPremiseNotConclusion; }
private And(SortedSet <Regex <T> > regexes) : base( regexes.All(r => r.AcceptsEmptyString), regexes.Aggregate(RegexType.And.GetHashCode(), (hash, rex) => hash * 7 + rex.GetHashCode())) { _regexes = regexes; }
/// <summary> /// Verify the 2 sorted sets are equivalent. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="set1"></param> /// <param name="set2"></param> internal static void VerifySortedSetsAreEquivalent <T>(SortedSet <T> set1, SortedSet <T> set2) { set1.Count.Should().Be(set2.Count); // Verify that the 2 sets are different (set1 == set2).Should().BeFalse(); set1.All(s => set2.Contains(s)).Should().BeTrue(); }
/// <summary> /// Linear ordering of vertices in Directed Acyclic Graph(DAG). /// </summary> /// <returns></returns> public List <T> Kahnsalgorithm() { var L = new List <T>(); // will contain the sorted elements var S = new SortedSet <T>(AdjacencyList.Keys.Where(n => EdgeSortedSet.All(e => !e.Item2.Equals(n)))); // no incoming edges while (S.Any()) { var n = S.First(); S.Remove(n); L.Add(n); foreach (var e in EdgeSortedSet.Where(e => e.Item1.Equals(n)).ToList()) { var m = e.Item2; EdgeSortedSet.Remove(e); if (EdgeSortedSet.All(incoming => !incoming.Item2.Equals(m))) { S.Add(m); } } } return(EdgeSortedSet.Any() ? null : L); }
private static double GetConfidence(SortedSet <string> sub, SortedSet <string> candidate, List <string[]> data) { double x = data.Where(s => sub.All(s.Contains)).Count(); if (x == 1) { return(0); } double supportSub = (x) / data.Count(); double supportCandidate = ((double)data.Where(s => candidate.All(s.Contains)).Count()) / data.Count(); return(supportCandidate / supportSub); }
private static Dictionary <SortedSet <string>, int> generateFrequentItemSets(int supportThreshold, List <string[]> data, Dictionary <SortedSet <string>, int> lowerLevelItemSets) { Dictionary <SortedSet <string>, int> candidates = new Dictionary <SortedSet <string>, int>(); // generate candidate itemsets from the lower level itemsets foreach (SortedSet <string> itemSet1 in lowerLevelItemSets.Keys) { foreach (SortedSet <string> itemSet2 in lowerLevelItemSets.Keys) { if (!itemSet1.All(itemSet2.Contains) && almostEqual(itemSet1, itemSet2)) //not the same and first k-1 elements are equal { SortedSet <string> newSet = joinSets(itemSet1, itemSet2); if (newSet.Count == itemSet1.Count + 1) // if they had k-1 elements in common { int i = 0; //Pruning while (i < newSet.Count) { var e = newSet.ElementAt(i); SortedSet <string> subset = new SortedSet <string>(newSet.Where(x => !x.Equals(e))); if (!lowerLevelItemSets.Any(kv => subset.All(kv.Key.Contains))) { break; } i++; } //if all subsets are in the lower level sets if (i == newSet.Count) { if (!candidates.Any(c => newSet.All(s => c.Key.Contains(s)))) { candidates[newSet] = 0; } } } } } } Console.WriteLine("generated " + candidates.Count + " candidates."); //check the support for all candidates and returns only those that have enough support to the set return(candidates.ToDictionary(kv => kv.Key, kv => countSupport(kv.Key, data)).Where(c => c.Value >= supportThreshold).ToDictionary(kv => kv.Key, kv => kv.Value)); }
private T Recompute() { if (_names.All(name => _values.ContainsKey(name))) { var valuesArray = _names.Select(name => this._values[name]).ToArray(); try { return((T)_parser.DynamicInvoke(valuesArray)); } catch (Exception e) { _logger.Error("Exception while parsing flag", e); return(_defaultValue); } } return(_defaultValue); }
public IEnumerable <ModuleDefinition> GetConfigModules() { if (_cachedConfigModules.Any()) { return(_cachedConfigModules); } var menuModules = MetadataProvider.Modules(ClientPlatform.Web); var configModules = _dao.FindByQuery <String>(PropertyValue.DistinctModules); foreach (var moduleDefinition in menuModules) { _cachedConfigModules.Add(moduleDefinition); } foreach (var configModule in configModules) { if (!string.IsNullOrEmpty(configModule) && _cachedConfigModules.All(f => !f.Id.Equals(configModule, StringComparison.CurrentCultureIgnoreCase))) { _cachedConfigModules.Add(new ModuleDefinition(configModule, String.Format("{0} -- not declared yet --", configModule))); } } return(_cachedConfigModules); }
private void TrackDependencies(IPlugin dependent, IEnumerable <PluginIdentifier> dependencies) { _missingDependencies.Remove(dependent.Info); foreach (var dependency in dependencies) { if (_sortedPlugins.All(d => d.Info != dependency)) { _missingDependencies.Add(dependency); } if (_trackedDependencies.TryGetValue(dependency, out var existingRegistry)) { existingRegistry.Add(dependent.Info); } else { _trackedDependencies.Add(dependency, new List <PluginIdentifier>() { dependent.Info }); } } }
static void Main() { var sortedSet = new SortedSet <Person>(new PersonComparer()); var hashSet = new HashSet <Person>(); int num = int.Parse(Console.ReadLine()); for (int i = 0; i < num; i++) { var input = Console.ReadLine().Split(); var person = new Person(input[0], int.Parse(input[1])); if (sortedSet.All(e => !e.Equals(person))) { sortedSet.Add(person); } hashSet.Add(person); } Console.WriteLine(sortedSet.Count); Console.WriteLine(hashSet.Count); }
public LocationData FindItems(GameData game) { ItemLocs allLocs = FindItemLocs(game); SortedDictionary <int, List <EntityId> > usedItemLots = allLocs.usedItemLots; SortedDictionary <int, List <EntityId> > usedBaseShops = allLocs.usedBaseShops; PARAM shops = game.Param("ShopLineupParam"); PARAM itemLots = game.Param("ItemLotParam"); PARAM materials = game.Param("EquipMtrlSetParam"); PARAM npcs = game.Param("NpcParam"); // First we may have to create lots - easier to do this at the start than keep data in side channels all the way through int baseEvent = 52500960; foreach (KeyValuePair <int, int> toCreate in allLocs.baseLotsToCreate) { PARAM.Row baseRow = itemLots[toCreate.Value]; int newLot = toCreate.Key; PARAM.Row row = itemLots[newLot]; if (row == null) { row = game.AddRow("ItemLotParam", newLot); foreach (PARAM.Cell newCell in row.Cells) { newCell.Value = baseRow[newCell.Def.InternalName].Value; } } // TODO: Re-enable this with flag id validation row["getItemFlagId"].Value = baseEvent; baseEvent++; } LocationData data = new LocationData(); data.NewEntityLots = allLocs.newEntityLots; LocationKey prevLocation = null; foreach (KeyValuePair <int, List <EntityId> > entry in usedItemLots) { int itemLot = entry.Key; if (prevLocation != null) { // TODO: If event flag is tracked in script, allow 1 maxslot prevLocation.MaxSlots = Math.Max(Math.Min(itemLot - prevLocation.ID - 1, 8), 1); if (prevLocation.MaxSlots < 1) { Console.WriteLine($"XX Overlapping slots at {itemLot}"); } prevLocation = null; } List <EntityId> entities = entry.Value; string locs = string.Join(", ", entities.Select(e => game.EntityName(e, true) + (e.MapName == "" ? "" : " " + e.MapName))); if (itemLots[itemLot] == null) { string text = game.LotName(itemLot); // These are fine - no-ops to game if (logUnused) { Console.WriteLine($"MISSING connected item lot!! {itemLot}: {text} @ {locs}"); } continue; } LocationKey baseLocation = null; while (itemLots[itemLot] != null) { bool isBase = itemLot == entry.Key; string text = game.LotName(itemLot); PARAM.Row row = itemLots[itemLot]; int clearCount = (sbyte)row["ClearCount"].Value; int eventFlag = (int)row["getItemFlagId"].Value; int totalPoints = 0; for (int i = 1; i <= 8; i++) { totalPoints += (short)row[$"LotItemBasePoint0{i}"].Value; } List <string> itemLotOutput = new List <string>(); for (int i = 1; i <= 8; i++) { int id = (int)row[$"ItemLotId{i}"].Value; if (id != 0) { uint type = (uint)row[$"LotItemCategory0{i}"].Value; int points = (short)row[$"LotItemBasePoint0{i}"].Value; int quantity = (ushort)row[$"NewLotItemNum{i}"].Value; if (type == 0xFFFFFFFF) { continue; } ItemKey item = new ItemKey(LocationData.LotTypes[type], id); string itemText = $"{itemLot}[{locs}]"; List <string> lotInfo = new List <string>(); if (quantity > 1) { lotInfo.Add($"{quantity}x"); } if (points != totalPoints) { lotInfo.Add($"{100.0 * points / totalPoints:0.##}%"); } PARAM.Row itemRow = game.Item(item); if (itemRow != null && item.Type == ItemType.GOOD && (byte)itemRow["goodsType"].Value == 7) { // Items which are not shown in inventory menu for various reasons, but having them still does something. lotInfo.Add($"(hidden)"); } itemLotOutput.Add($"{game.Name(item)} " + string.Join(" ", lotInfo)); if (lotInfo.Count() > 0) { itemText += $" {string.Join(", ", lotInfo)}"; } if (quantity <= 0) { Console.WriteLine($"XX There is 0! of {itemText}"); } ItemScope scope; if (eventFlag != -1) { if (equivalentEvents.ContainsKey(eventFlag)) { eventFlag = equivalentEvents[eventFlag]; } scope = new ItemScope(ScopeType.EVENT, eventFlag); // Note this doesn't necessarily have to be slot 1. But it should be only one slot... if (points != totalPoints) { Console.WriteLine($"Has event flag? But random? {itemText}"); } } else { // One time drops that directly award, that aren't covered by event flags. Mostly crystal lizards. if (entities.Count() == 1 && entityItemLots.ContainsKey(entities[0].EventEntityID) && entityItemLots[entities[0].EventEntityID] == entry.Key) { scope = new ItemScope(ScopeType.ENTITY, entities[0].EventEntityID); } // Non-respawning enemies with drops which can be missed. These are reused between different entities, so can drop multiple times. else if (entities.All(e => nonRespawningEntities.Contains(e.EventEntityID))) { scope = new ItemScope(ScopeType.ENTITY, entities.Select(e => e.EventEntityID).Min()); } else { int model = entities.Select(e => e.GetModelID()).Min(); // Infinite guaranteed or scripted drops are not randomized unless specifically added to entityItemLots if (model == -1 || points == totalPoints) { if (logUnused) { Console.WriteLine($"XX Item {game.Name(item)} {itemLot} has no associated event, but is guaranteed or global: {itemText}"); } continue; } scope = new ItemScope(ScopeType.MODEL, model); } } LocationKey location = new LocationKey(LocationType.LOT, itemLot, itemText, entities, quantity, baseLocation); data.AddLocation(item, scope, location); if (baseLocation == null) { baseLocation = location; } } } // Write out the info. Some deduplication of sources to make prettier output. string lotOutput = string.Join(", ", itemLotOutput); bool simple = false; string text2; if (simple) { SortedSet <string> locations = new SortedSet <string>(entities.Select(e => game.LocationNames[e.MapName])); SortedSet <string> models = new SortedSet <string>(entities.Select(e => e.EntityName.StartsWith("o") ? "Treasure" : game.EntityName(e))); text2 = $"{string.Join(", ", models)}: {string.Join(", ", locations)}"; if (models.All(x => x == "unknown")) { text2 = "Unused/Unknown"; } if (models.All(x => x == "Unused NPC")) { text2 = "Unused NPC"; } else if (models.Any(x => x == "Unused NPC")) { models.Remove("Unused NPC"); if (locations.Count > 1) { locations.Remove("Global"); } text2 = $"{string.Join(", ", models)}: {string.Join(", ", locations)}"; } } else { // e.NPCParamID > -1 ? $" #{e.NPCParamID}" : "" // SortedSet<string> models = new SortedSet<string>(entities.Select(e => e.EntityName.StartsWith("o") ? $"Treasure in {e.MapName}" : $"{game.ModelName(e, true)} in {e.MapName}")); SortedSet <string> models = new SortedSet <string>(entities.Select(e => game.EntityName(e, true) + (e.MapName == "" ? "" : $" in {e.MapName}"))); text2 = $"{string.Join(", ", models)}"; } // Console.WriteLine($"{itemLot} [{text2}] {lotOutput}"); if (itemLot == 2014) { break; // Unused, and item lot immediately after it is used. Won't be an issue once. ... ?? } // Try to navigate resource drops (affected by Bell Demon). if ((byte)row["LotItemNum1"].Value == 1) { int curOffset = itemLot % 100; int curBase = itemLot / 100 * 100; int offset; for (offset = curOffset + 10; offset <= 50; offset += 10) { PARAM.Row offRow = itemLots[curBase + offset]; if (offRow != null && (byte)offRow["LotItemNum1"].Value == 1) { break; } } if (offset <= 50) { itemLot = curBase + offset; } else { itemLot++; } } else { itemLot++; } } prevLocation = baseLocation; } if (prevLocation != null) { prevLocation.MaxSlots = 5; } SortedDictionary <int, List <string> > qwcs = new SortedDictionary <int, List <string> >(); Dictionary <int, LocationKey> baseShops = new Dictionary <int, LocationKey>(); foreach (PARAM.Row row in shops.Rows) { int shopID = (int)row.ID; int baseShop = GetShopType(shopID); string shopName = shopSplits[baseShop]; if (shopName == null) { if (!addUnused) { continue; } shopName = "Unknown shop"; } if (shopID >= 9000000) { continue; } int qwc = (int)row["qwcID"].Value; int type = (byte)row["equipType"].Value; int id = (int)row["EquipId"].Value; int quantity = (short)row["sellQuantity"].Value; int eventFlag = (int)row["EventFlag"].Value; int material = (int)row["mtrlId"].Value; int value = (int)row["value"].Value; float priceRate = (float)row["PriceRate"].Value; string quantityText = quantity == -1 ? "" : $" ({quantity})"; // (unlimited) string qwcText = qwc == -1 ? "" : $" {game.QwcName(qwc)}"; string costText = ""; ItemKey item = new ItemKey((ItemType)type, id); if (material != -1) { PARAM.Row matRow = materials[material]; int materialQuant = (sbyte)matRow["ItemNum01"].Value; int materialItem = (int)matRow["MaterialId01"].Value; costText = $" for {materialQuant} {game.Name(new ItemKey(ItemType.GOOD, materialItem))}"; } if (value != 0 || costText == "") { int actualCost = value; if (actualCost == -1) { actualCost = (int)game.Item(item)["shopId"].Value; } if (priceRate != 0) { actualCost = (int)(actualCost * priceRate); } costText = costText == "" ? $" for {actualCost} Sen" : $"{costText} and {actualCost} Sen"; } string shopText = $"{shopName}{qwcText}{quantityText}{costText} - event {eventFlag}"; string text = $"{shopID}[{shopText}]"; // Console.WriteLine($"{shopID} [{shopName}{qwcText}] {game.Name(item)}{quantityText}{costText}"); LocationKey location = new LocationKey( LocationType.SHOP, shopID, text, usedBaseShops.ContainsKey(baseShop) ? usedBaseShops[baseShop] : new List <EntityId>(), quantity, null); // try not to use base shops - baseShops.ContainsKey(baseShop) ? baseShops[baseShop] : null); if (shopID == baseShop) { baseShops[baseShop] = location; } ItemScope scope; AddMulti(qwcs, qwc, $"{game.Name(item)}: {text}"); if (eventFlag != -1) { if (equivalentEvents.ContainsKey(eventFlag)) { eventFlag = equivalentEvents[eventFlag]; } if (quantity <= 0) { Console.WriteLine("XX No quantity for event flag shop entry {text}"); } ScopeType scopeType = ScopeType.EVENT; if (restrictiveQwcs.Contains(qwc)) { // If item becomes unavailable at some point, it returns in infinite form scopeType = ScopeType.SHOP_INFINITE_EVENT; } scope = new ItemScope(scopeType, eventFlag); } else if (material != -1) { int materialItem = (int)materials[material]["MaterialId01"].Value; scope = new ItemScope(ScopeType.MATERIAL, materialItem); } else { scope = new ItemScope(ScopeType.SHOP_INFINITE, -1); } data.AddLocation(item, scope, location); } // Merge infinite and finite shops. Mostly done via heuristic (when event and infinite both exist), with exception of one event ItemScope infiniteKey = new ItemScope(ScopeType.SHOP_INFINITE, -1); foreach (ItemLocations locations in data.Data.Values) { foreach (ItemLocation restrict in locations.Locations.Values.Where(loc => loc.Scope.Type == ScopeType.SHOP_INFINITE_EVENT).ToList()) { if (locations.Locations.ContainsKey(infiniteKey)) { // Combine infinite shops into event ItemLocation infinite = locations.Locations[infiniteKey]; restrict.Keys.AddRange(infinite.Keys); locations.Locations.Remove(infiniteKey); } else { Console.WriteLine($"XX: No 1:1 match between event shops and infinite shops for {restrict}"); // No infinite shops, turn this into a regular event shop. (Doesn't happen in base DS3) ItemLocation eventLoc = new ItemLocation(new ItemScope(ScopeType.EVENT, restrict.Scope.ID)); eventLoc.Keys.AddRange(restrict.Keys); locations.Locations[eventLoc.Scope] = eventLoc; locations.Locations.Remove(restrict.Scope); } } } // Now can find all location scopes List <ScopeType> uniqueTypes = new List <ScopeType> { ScopeType.EVENT, ScopeType.ENTITY, ScopeType.MATERIAL }; foreach (KeyValuePair <ItemKey, ItemLocations> entry in data.Data) { int unique = 0; foreach (KeyValuePair <ItemScope, ItemLocation> entry2 in entry.Value.Locations) { ItemScope scope = entry2.Key; ItemLocation loc = entry2.Value; int id = uniqueTypes.Contains(scope.Type) ? scope.ID : -1; unique = unique == -1 ? -1 : (id == -1 ? -1 : unique + 1); SortedSet <int> shopIds = new SortedSet <int>(loc.Keys.Where(k => k.Type == LocationType.SHOP).Select(k => GetShopType(k.ID))); SortedSet <int> shopQwcs = new SortedSet <int>(loc.Keys.Where(k => k.Type == LocationType.SHOP).Select(k => (int)shops[k.ID]["qwcID"].Value) .Select(qwc => equivalentEvents.ContainsKey(qwc) ? equivalentEvents[qwc] : qwc) .Where(qwc => qwc != -1 && !restrictiveQwcs.Contains(qwc))); SortedSet <int> allShop = new SortedSet <int>(shopIds.Union(shopQwcs)); if (shopIds.Count() + shopQwcs.Count() != allShop.Count()) { Console.WriteLine($"XX Overlapping qwc/shop ids for location {loc}"); } SortedSet <int> modelBase = scope.Type == ScopeType.MODEL ? new SortedSet <int>(loc.Keys.Select(k => k.BaseID)) : new SortedSet <int>(); bool onlyShops = loc.Keys.All(k => k.Type == LocationType.SHOP) && allShop.Count() > 0; LocationScope locationScope = new LocationScope(scope.Type, id, allShop, modelBase, onlyShops); data.AddLocationScope(entry.Key, scope, locationScope); loc.LocScope = locationScope; } entry.Value.Unique = unique > 0; } if (logUnused) { Console.WriteLine("---------------------------------------------------------------------------"); foreach (KeyValuePair <ItemKey, string> entry in game.Names()) { ItemKey item = entry.Key; if (item.Type == 0) { item = new ItemKey(item.Type, item.ID - (item.ID % 10000)); } if (!data.Data.ContainsKey(item)) { // Mostly pulls up old DS1 items, crow items, and gestures. Console.WriteLine($"Unused item {item.Type}-{entry.Key.ID}: {entry.Value}"); } } } return(data); }
public static bool pressedContainsCombo(SortedSet <Keys> pressed, SortedSet <Keys> combo) { return(combo.All(key => pressed.Contains(key))); }
private RelativeLayout MakeLayout(IEnumerable <Event> events, double startHour) { RelativeLayout layout = new RelativeLayout(Context); layout.LayoutParameters = new LayoutParams(0, LayoutParams.WrapContent, 0.5f); List <SortedSet <Event> > horizontalEventGroups = GroupHorizontalEvents(events); SortedSet <Event> lastHEG = null; foreach (SortedSet <Event> horizontalEventGroup in horizontalEventGroups) { Event firstEvent = events.Min(); double groupStart = (firstEvent.StartTime - Day.StartTime).TotalHours; LinearLayout horizontalEvents = new LinearLayout(Context); horizontalEvents.Orientation = Orientation.Horizontal; RelativeLayout.LayoutParams groupParams = new RelativeLayout.LayoutParams(LayoutParams.MatchParent, LayoutParams.WrapContent); groupParams.AddRule(LayoutRules.AlignParentTop); double emptyTime = groupStart - startHour; groupParams.TopMargin = (int)(emptyTime * HourHeight); List <SortedSet <Event> > verticalEventGroups = GroupVerticalEvents(horizontalEventGroup); foreach (SortedSet <Event> verticalEventGroup in verticalEventGroups) { Event ev = verticalEventGroup.First(); double eventStart = (ev.StartTime - Day.StartTime).TotalHours; double emptyGroupTime = eventStart - groupStart; if (verticalEventGroup.Count == 1) { EventView view = new EventView(Context, ev); view.HourHeight = HourHeight; if (lastHEG != null) { view.SetBorder(true, !lastHEG.All(lastEvent => lastEvent.EndTime == ev.StartTime), true, true); } LayoutParams lp = (LayoutParams)view.LayoutParameters; lp.TopMargin = (int)(emptyGroupTime * HourHeight); view.LayoutParameters = lp; horizontalEvents.AddView(view); } else { RelativeLayout groupLayout = MakeLayout(verticalEventGroup, eventStart); groupLayout.SetPadding(0, (int)emptyGroupTime, 0, 0); horizontalEvents.AddView(groupLayout); } } layout.AddView(horizontalEvents, groupParams); lastHEG = horizontalEventGroup; } return(layout); }
//returns how many tuples in our data set, that contains all items of the given set. // Assumes that items in ItemSets and transactions are both unique private static int countSupport(SortedSet <string> itemSet, List <string[]> data) => data.Where(item => itemSet.All(str => item.Contains(str))).Count();
public static CronStructure ParseString(string cronString) { string[] cronParts = cronString.Split(new char[] { ' ' }); if (cronParts.Length != 5) { throw new ArgumentException("Cron string not formatted properly (number of parts)"); } Func <string, int, int, SortedSet <int> > convertToList = (part, min, max) => { SortedSet <int> values = new SortedSet <int>(); // Parse direct list if (part.Contains(',')) { string[] singleItems = part.Split(','); try { values = new SortedSet <int>(singleItems.Select(int.Parse)); bool test = values.All(v => v <= max && v >= min); if (!test) { throw new ArgumentException("Cron part list value outside the values range."); } if (values.Count == 0) { throw new ArgumentException("Cron part values list is empty."); } return(values); } catch (FormatException) { throw new ArgumentException("Cron part list not parsable."); } } // Parse cycles int?cycle = null; if (part.Contains('/')) { int index = part.IndexOf('/'); string cycleString = part.Substring(index + 1, part.Length - index - 1); try { int cycleValue = int.Parse(cycleString); if (cycleValue > max || cycleValue < min) { throw new ArgumentException("Cron part cycle value outside the values range."); } cycle = cycleValue; } catch (FormatException) { throw new ArgumentException("Cron part cycle not parsable."); } part = part.Substring(0, index); } // Parts ranges or literal if (part == "*") { values = new SortedSet <int>(Enumerable.Range(min, max - min + 1)); } else if (part.Contains('-')) { string[] ranges = part.Split('-'); if (ranges.Length != 2) { throw new ArgumentException("Cron part range not formatted properly (number of parts)"); } try { int start = int.Parse(ranges[0]); int end = int.Parse(ranges[1]); if (start > max || end > max || start < min || end < min || start > end) { throw new ArgumentException("Cron part range value outside the values range."); } values = new SortedSet <int>(Enumerable.Range(start, end)); } catch (FormatException) { throw new ArgumentException("Cron part range not parsable."); } } else { try { int literal = int.Parse(part); if (literal > max || literal < min) { throw new ArgumentException("Cron part literal outside the values range."); } if (cycle.HasValue) { throw new ArgumentException("Cron part literal with cycle."); } values = new SortedSet <int> { literal }; } catch (FormatException) { throw new ArgumentException("Cron part type not parsable."); } } if (cycle.HasValue) { values = new SortedSet <int>(values.Where(v => v % cycle == 0)); } if (values.Count == 0) { throw new ArgumentException("Cron part values list is empty."); } return(values); }; return(new CronStructure { Minutes = convertToList(cronParts[0], 0, 59), Hours = convertToList(cronParts[1], 0, 23), Days = convertToList(cronParts[2], 1, 31), Months = convertToList(cronParts[3], 1, 12), DaysOfWeek = convertToList(cronParts[4], 0, 6), }); }