We have to present a list of options with the following rules
* you can select multiple items, as many as you want
* however, some of the items are mutually exclusive, i.e. selecting itemA should automatically deselects itemC ( if itemC is selected prviously )
this is best explained with the following list example of fules for a car
Gas
Diesel
Electric
BioFuel
Ethanol
a car can have multiple fuel types selected such as
biofuel and Gas
Gas and Electric
Gas, Ethanol and Biofuel
but not
Diesel and Gas at the same time
Trying to come up with some configurable logic such that the code reads the configuration and applies the rules rather than knowing about specifics esp. since there's another list which has similar constraints
Any help/pointers on how to model this behavior ?
UPDATE -
Thanks everyone for the great ideas, the simplest solution seems to define a list of Incompatible Types in a config file/table for each fuel type as follows
FuelID/FuelName/IncompatibleTypes 1/Gas/2 2/Diesel/1 3/Electric/ 4/BioFuel/ 5/Ethanol/ etc.
Where IncomatibleTypes is say nvarchar(50) and will store the incompatible types like so 2,5,6,... etc.
So the code will read the definitions and if an item is selected, it will read the other selected items and if it finds anything on the incomatible list, it can either display a message or simply auto deselect the other incompatible item etc.
this may be inelegant but seems the most generic solution without the code knowing anything about specific items at all, plus it can be freely extended as in reality * there will likely be a couple dozen max selections at best * if the list of incomatibilities increases the storage can be changed to say nvarchar(100) without any changes to code itself
I would most probably write a property or function, that loads the configuration when first needed (or just load it on application load, depending on the scenario). After that I would assign a bit to every possible value (so they are represented by powers of 2), and store the rules as numbers. When checking if a combination is valid, I would just iterate through the list of items, and check, if there is a compatible number with the checked rule. The simplest case of this is if you list all acceptable combinations, and just run a .Any expression on it, and throw an exception, when nothing is found, or in reverse, you store forbidden combinations, and throw an exception, when something is found.
This approach is way faster, than using a dictionary for example. You can even implement some effective data structure for finding the correct key, if you need performance.
For example:
Name | Value
----------------------
Gas | 00001 = 1
Diesel | 00010 = 2
Electric | 00100 = 4
BioFuel | 01000 = 8
Ethanol | 10000 = 16
Possible values are:
Combination | Value
----------------------
Biofuel + Gas | 01001=9
Gas + Electric| 00101=5
etc.
When you need to check for Biofuel + Gas, you check for 9. It is found, everything is all right. When you need to check for diesel and gas, you check for 3. It is not found, you throw an exception.
I would assign a "compatibility group" number to each of the values, where the number should be viewed digit by digit.
FuelType | CompatibilityGroup
---------|-------------------
Gas | 2
Diesel | 3
Electric | 123
BioFuel | 123
Ethanol | 123
FuelType
could be a class with a property .CompatibilityGroup
of type String
or anything that's easy to check character for character.
So for any combination of FuelType
s, just check if they all have a common digit/character. If the CompatibilityGroup
s have nothing in common, they are not compatible.
E.g.
Biofuel
and Gas
both have the digit 2
in common, so they are compatible.
Gas
and Diesel
have no digit in common, so they are incompatible.
Boolean IsCompatible(params FuelType types[])
{
//Finding an algorithm that finds a common character/digit should be trivial.
return HasCommonDigit(types.Select(t => t.CompatibilityGroup));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With