Why is my [Flag] Enum validation failing? - c#

Am I fundamentally misunderstanding how HasFlags works? I cannot understand why this code is failing.
This code takes a value and determines if it is a valid combination of values of my Enum.
Two sub groups of Enum values are identified by ORing other members: JustTheMonths and Exclusives. JustTheMonths is declared in the Enum, and Exclusives is built in the validation method.
When I pass 1 or 2 (Unassigned or Unknown) to this method, it correctly identifies them as valid - Exclusives, but not members of JustTheMonths.
But when I pass 4 to this code, it correctly identifies it as a member of the whole set, but incorrectly identifies it as a member of sub-group JustTheMonths.
What am I doing wrong here? Why does my code think that 4 is a member of (8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8172 | 16344) ?
private void Form1_Load(object sender, EventArgs e)
{
FloweringMonth test = FloweringMonth.NotApplicable;
if (IsValidFloweringMonthValue((int)test))
{
System.Diagnostics.Debug.WriteLine("Valid");
}
else
{
System.Diagnostics.Debug.WriteLine("Not Valid");
}
}
[Flags]
public enum FloweringMonth
{
Unassigned = 1, Unknown = 2, NotApplicable = 4,
Jan = 8, Feb = 16, Mar = 32, Apr = 64, May = 128, Jun = 256,
Jul = 512, Aug = 1024, Sep = 2048, Oct = 4086, Nov = 8172, Dec = 16344,
JustMonths = (Jan | Feb | Mar | Apr | May | Jun | Jul | Aug | Sep | Oct | Nov | Dec)
}
public static bool IsValidFloweringMonthValue(int value)
{
FloweringMonth incoming = (FloweringMonth)value;
FloweringMonth AllVals = FloweringMonth.Unassigned | FloweringMonth.Unknown |
FloweringMonth.NotApplicable | FloweringMonth.Jan | FloweringMonth.Feb |
FloweringMonth.Mar | FloweringMonth.Apr | FloweringMonth.May |
FloweringMonth.Jun | FloweringMonth.Jul | FloweringMonth.Aug |
FloweringMonth.Sep | FloweringMonth.Oct | FloweringMonth.Nov | FloweringMonth.Dec;
// does the incoming value contain any enum values from AllVals?
bool HasMembersOfAll = AllVals.HasFlag(incoming);
if (!HasMembersOfAll) return false;
// does the incoming value contain any enum values from JustTheMonths?
bool HasMembersOfMonths = FloweringMonth.JustMonths.HasFlag(incoming);
// does it contain any enum values from the set of three exclusive values?
FloweringMonth Exclusives = (FloweringMonth.Unassigned |
FloweringMonth.Unknown | FloweringMonth.NotApplicable);
bool HasMembersOfExclusives = Exclusives.HasFlag(incoming);
// an exclusive value cannot be mixed with any month values
if (HasMembersOfMonths && HasMembersOfExclusives) return false; // bad combo
// an exclusive value cannot be mixed with other exclusive values
if (incoming.HasFlag(FloweringMonth.Unassigned) &&
incoming.HasFlag(FloweringMonth.Unknown)) return false;
if (incoming.HasFlag(FloweringMonth.Unassigned) &&
incoming.HasFlag(FloweringMonth.NotApplicable)) return false;
if (incoming.HasFlag(FloweringMonth.Unknown) &&
incoming.HasFlag(FloweringMonth.NotApplicable)) return false;
return true;
}

Following #dukedukes answer, the problem was there your multiples of 2 were off.
One way to avoid this mistake is to use bitwise operations on the right-hand side.
[Flags]
enum Months
{
January = 1 << 3, // 8
February = 1 << 4, // 16
March = 1 << 5, // 32
}

Your multiples of 2 are incorrect. 4086 should be 4096, 8172 should be 8192, etc...

Related

Replace a Number with a Random Number

I want to make my own little encryption (it not must be secure).
I thought it would be a good idea, if the entered password would be converted to binary and then I want to change all the 1 to (2 | 3 | 9 | 7) so if we had
1101 = 2907 | 9703 ... and so on
So if we would enter 9703 we could decrypt it to 1101 again.
But I can’t find a Method to Replace these.
The Replace() Method would only do this:
1101 -> 2202 | 1101 -> 9909
And yes, i know that is not a good Method to encrypt something but I just want to code a very simple encryption on my own.
int[] replace_Ones = { 2, 3, 9, 7 };
int ServerEncryption = 1101010000111001;
ServerEncryption.Replace(1, 2);
Starting from this:
int[] replace_Ones = { 2, 3, 9, 7 }; // I removed the 0 ;)
long ServerEncryption = 1101010000111001;
You can make a method that does the following:
long FunnyEncrypt( long pseudobinary )
{
long result = 0;
long scope = 1;
while( pseudobinary > 0 )
{
// place 2 or 3 or 7 or 9 0 or 1
result += scope * GetRandomReplacement() * ( pseudobinary % 10 );
scope *= 10;
pseudobinary = pseudobinary / 10; // decimal right shift 110 / 10 -> 11
}
return result;
}
Disclaimer: untested! Corrections welcome.
GetRandomReplacement is left for practice :D - but it basically is "pick a random int out of [0..3] and use it as index into the array of [2,3,7,9]".
Example:
example input: 1101
| iteration | input | result | scope | -> | input | result | scope | GetRandomRepl |
| 1 | 1101 | 0 | 1 | -> | 110 | 7 | 10 | 7 |
| 2 | 110 | 7 | 10 | -> | 11 | 7 | 100 | - |
| 3 | 11 | 7 | 100 | -> | 1 | 307 | 1000 | 3 |
| 4 | 1 | 307 | 1000 | -> | 0 | 2307 | 10000 | 2 |
=> Result = 2307
EDIT: changed to long after testing, did not see the number is too big for int: https://dotnetfiddle.net/5X4lZu
If the problem is to replace '1' value of a binary string to a random value in { 2, 3, 9, 7 } you could do like this:
char[] replace_Ones = { '2', '3', '9', '7' };
StringBuilder ServerEncryption =new StringBuilder("1101010000111001");
Random r = new Random();
for (int i=0 ; i < ServerEncryption.Length ; i++)
{
if (ServerEncryption[i] != '0')
ServerEncryption[i] = replace_Ones[r.Next(replace_Ones.Length)];
}
Console.WriteLine(ServerEncryption);
dotnetFiddle

Adding values in ASP.NET controller ​from the SQL Server database column for a specific user

My problem: I need to add 'overtime' for all previous months from the beginning of the year to the month selected.
My table in SQL Server:
Overtime : varchar(20)
Id | Login | Year | Month | Day | Overtime
---+-------+------+-------+-----+----------
1 | MIPA | 2020 | 1 | 1 | 08:00
2 | MIPA | 2020 | 1 | 2 | 08:00
3 | MIPA | 2020 | 1 | 3 | 07:30
4 | MIPA | 2020 | 1 | 4 | 12:00
...
30 | MIPA | 2020 | 1 | 30 | 04:00
...
41 | MIPA | 2020 | 2 | 1 | 08:00
42 | MIPA | 2020 | 2 | 2 | 08:00
43 | MIPA | 2020 | 2 | 3 | 07:30
44 | MIPA | 2020 | 2 | 4 | 12:00
...
52 | MIPA | 2020 | 2 | 25 | 04:00
So if the user chose March (3) and year 2020 (in dropdownlist), this function must extract the aggregated information from the overtime column of the previous months of the selected year.
(that is, in the example for January (1) and February (2) and for 2020)
Controller:
[HttpPost]
public async Task<ActionResult> PartialTableEcp() //change nothing
{
// Data is already extracted from other operations
// So e.g. user enters chooses year: 2020 month: March (3)
int numberMonth= 3;
int numberYear= 2020;
int numberOfDays= 31;
// person identification by login
var userName = _httpContextAccessor.HttpContext.User.Identity.Name;
// retrieve all month records from the table, (i dont know it works)
var existingRecords = _tableEcpContext.Karta
.Where(x => x.Login == userName &&
x.Year == numberYear &&
x.Month == numberMonth-1) ////will mathematical calculation work here?
.Select(i => new { i.Overtime })
.ToList();
// and now here is a problem how to sum all these values ​​..
// preferably in HHH: mm format
var thisValue = that this value would be written to the variable var;
var viewModel = new ParentView { Model1 = karta };
return PartialView("_TableViewEcp", viewModel); //change nothing
}
Model:
public partial class Karta_Model
{
[Key]
public int Id { get; set; }
public string? Login { get; set; }
public int Year { get; set; }
public int Month{ get; set; }
public int? DayOfMonth { get; set; }
public string? Overtime { get; set; }
}
public partial class ParentView
{
public List<Karta_Model> Model1 { get; set; }
}
Does anyone have any idea?
Change your select to parse the strings to TimeSpans
.Select(i => string.IsNullOrEmpty(i) ? TimeSpan.Zero : TimeSpan.Parse(i))
Then you can use Aggregate to sum the TimeSpans
.Aggregate(TimeSpan.Zero, (t1, t2) => t1 + t2)
dotnetfiddle

How to efficiently get unique combinations of a list of objects

I have a single list of objects that I want to make unique combinations from.
The objects that I have are (CityObj);
public string City_Name;
public int Population;
double xcord;
double ycord;
double zcord;
The result would be a list that contains a new object (CityComboObj)
public string City_NameA;
public int PopulationA;
double xcordA;
double ycordA;
double zcordA;
public string City_NameB;
public int PopulationB;
double xcordB;
double ycordB;
double zcordB;
A sample of the dataset is as follows;
City1 | 3840 | 42 | -12 | 5
City2 | 39402 | 1 | 59 | -5
City3 | 5934 | 99 | -55 | 3
City4 | 12394 | -56 | 9 | 16
The resultant list of objects would look like;
City1 | 3840 | 42 | -12 | 5 City2 | 39402 | 1 | 59 | -5
City1 | 3840 | 42 | -12 | 5 City3 | 5934 | 99 | -55 | 3
City1 | 3840 | 42 | -12 | 5 City4 | 12394 | -56 | 9 | 16
City2 | 39402 | 1 | 59 | -5 City3 | 5934 | 99 | -55 | 3
City2 | 39402 | 1 | 59 | -5 City4 | 12394 | -56 | 9 | 16
City3 | 5934 | 99 | -55 | 3 City4 | 12394 | -56 | 9 | 16
As you can see its only the unique results returned.
Currently I am using a horribly inefficient apporach to do going this;
foreach (var element in CityListA)
{
if (!CityListB.Any(o => o.City_NameA == element.City_NameA && o.City_NameB == element.City_NameB))
{
if (!CityListB.Any(o => o.City_NameA == element.City_NameB && o.City_NameB == element.City_NameA))
{
CityListB.add(element)
}
}
}
In a nutshell the approach is to take two lists one full and one empty, compare each element of the full list with the empty list to see if it exists or the transpose exists and if it doesn't add it.
It works but it is slow, is there a better way of doing this?
Thanks
Your code needs some reengineering, for example:
internal class CityObjs : List<CityObj>
{
}
internal class CityObj
{
public string City_Name;
public int Population;
double xcord;
double ycord;
double zcord;
}
internal class CityComboObj
{
internal CityObj CityA ;
internal CityObj CityB ;
internal CityComboObj(CityObj A,CityObj B) { CityA=A ; CityB=B;}
}
internal class CityComboObjs: List<CityComboObj>
{
}
Assuming that the list CityObjs is initialized:
CityComboObjs = new CityComboObjs() ;
for (int i=0;i<CityObjs.Count-1;i++) for (int j=i+1;j<CityObjs.Count;j++)
CityComboObjs.Add(new CityComboObj(CityObjs[i],CityObjs[j]) ;
This actually works. Just replace simple integers with real objects. The idea of this code is to do it more efficiently, as you asked, without checking if the pair already exists. In your case myList[i] will return a CITY object
using System;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var myList = (new []{1 , 2, 3, 4}).ToList();
var newList = new List<ListObject>();
var count = myList.Count;
for (int i = 0; i < count - 1; i++)
{
for(int j = i + 1; j < count; j++)
{
newList.Add(new ListObject(){ I = myList[i], J = myList[j]});
}
}
newList.ForEach(x => Console.WriteLine(x));
}
class ListObject
{
public int I {get; set;}
public int J {get; set;}
public override string ToString()
{
return I + " - " + J;
}
}
}
Output
1 - 2
1 - 3
1 - 4
2 - 3
2 - 4
3 - 4

Generate a sentence from a pre defined words

I'm working on a system that generates a password for a user, place a telephonic call, and speaks the password one character at a time. For example, let the password be "BlaBla123"
Now I have this basic words:
"Capitol", "Small", and "as in"
Also, I have this table:
// Letter | Word | Code |
// --------+----------+---------|
// a | Alpha | 97, 65 |
// b | Bravo | 98, 66 |
// c | Charlie | 99, 67 |
// d | Delta | 100, 68 |
// e | Echo | 101, 69 |
// f | Foxtrot | 102, 70 |
// g | Golf | 103, 71 |
// h | Hotel | 104, 72 |
// i | India | 105, 73 |
// j | Juliet | 106, 74 |
// k | Kilo | 107, 75 |
// l | Lima | 108, 76 |
// m | Mike | 109, 77 |
// n | November | 110, 78 |
// o | Oscar | 111, 79 |
// p | Papa | 112, 80 |
// q | Quebec | 113, 81 |
// r | Romeo | 114, 82 |
// s | Sierra | 115, 83 |
// t | Tango | 116, 84 |
// u | Uniform | 117, 85 |
// v | Victor | 118, 86 |
// w | Whiskey | 119, 87 |
// x | X-ray | 120, 88 |
// y | Yankee | 121, 89 |
// z | Zulu | 122, 90 |
// 1 | One | 49 |
// 2 | Two | 50 |
// 3 | Three | 51 |
// 4 | Four | 52 |
// 5 | Five | 53 |
// 6 | Six | 54 |
// 7 | Seven | 55 |
// 8 | Eight | 56 |
// 9 | Nine | 57 |
// 0 | Zero | 48 |
Now, I seek to make a sentences like:
"Capitol B as in Bravo"
"Small L as in Lima"
"Small A as in Alpha"
"Capitol B as in Bravo"
"Small L as in Lima"
"Small A as in Alpha"
"One"
"Two"
"Three"
Against the supposed password.
Can anyone share a thought or so as to how I store the table in memory and just ForEach a password String and get a sentence for every encountered character?
Thanks.
Something like this:
Fill the dictionary like characterLookup.Add('a', "Alpha"), note 'ToLower' in the code example, only store the lower case letters.
A key-value store (Dictionary) is the data structure of choice because we are doing a lookup by key (in this case the letter).
private Dictionary<char, string> characterLookup = new Dictionary<char, string>();
public string[] GetSentences(string password)
{
string[] sentences = new string[password.Length];
for (int i = 0; i < password.Length; i++)
{
char currentChar = password[i];
if (char.IsLetter(currentChar))
{
sentences[i] = string.Format("{0} {1} as in {2}",
char.IsLower(currentChar) ? "Lower" : "Upper",
currentChar.ToUpper(),
characterLookup[currentChar.ToLower()]);
}
else if (char.IsDigit(currentChar))
{
sentences[i] = characterLookup[currentChar];
}
}
return sentences;
}
One approach could be to create your class to contain the letter, word and code, something like:
public class MyClass
{
public char Letter { get; set; }
public string Word { get; set; }
public string Code { get; set; }
}
Then you may define a HashSet<MyClass> to contain the letter something like:
HashSet<MyClass> letters = new HashSet<MyClass>();
letters.Add(new MyClass { Letter = 'a', Word = "alpha", Code = "123,23" });
letters.Add(new MyClass { Letter = 'b', Word = "bravo", Code = "123,23" });
letters.Add(new MyClass { Letter = 'c', Word = "charlie", Code = "123,23" });
letters.Add(new MyClass { Letter = 'd', Word = "delta", Code = "123,23" });
//.......................
Then you can use StringBuilder to build your string.
string password = "acd";
StringBuilder sb = new StringBuilder();
foreach (var val in password)
{
if (char.IsUpper(val))
sb.Append("Capital " + val + " as in " + Letters.Where(r => r.Letter == val).FirstOrDefault().Word + Environment.NewLine);
else
sb.Append("Small " + val + " as in " + Letters.Where(r => r.Letter == val).FirstOrDefault().Word + Environment.NewLine);
}
string test = sb.ToString();

How to Convert decimal number to time or vice versa

here is an example
if 8.30 is there it should be 8 hours 30 minute
if 8 hour 20 minutes then 8.20
Please tell whether it is possible ? if yes
how ?
When people talk about decimal hours, they usually mean 0.1 = 6 minutes.
So, the correct formula to convert 8.3 would be:
8 hours + 3 * 6 minutes = 8:18
To convert 8:20 to decimal it would be:
8 + 20/6 = 8.333333 (probably round to 8.3)
If it always be separated with . and you want it for displaying then simply use this:
var ar="8.30".split(new[]{'.'});
Console.Write("{0} hours {1} minutes",ar[0], ar[1]);
PS: Here we are sure to have two elements in array, but please check length of array ar before using ar[1]
My approach would look something like this. (This is ruby so you'll have to convert it yourself but the logic is whats important here)
def zeropad(number)
return ((number.to_f < 10) ? "0" : "") + number.round.to_s
end
def decimal_to_time(value)
t = value.split(".") #returns an array of ["hour", "minutes"]
hours, minutes = t[0], t[1]
minutes = zeropad( (minutes.to_f / 10**minutes.length) * 60 ) # parse the minutes into a time value
return (minutes.to_i == 0) ? hours : hours + ":" + minutes
end
def findTime(value)
value =~ /^\d+\.\d+/ ? decimal_to_time(value) : value
end
Where findTime("5.015") gives you the appropriate time value.
I've tested this across the following tests and they all pass.
| entered_time | expected_results|
| "5.6" | "5:36" |
| "5.9" | "5:54" |
| "5.09" | "5:05" |
| "5.0" | "5" |
| "5.00" | "5" |
| "5.015" | "5:01" |
| "6.03" | "6:02" |
| "5.30" | "5:18" |
| "4.2" | "4:12" |
| "8.3" | "8:18" |
| "8.33" | "8:20" |
| "105.5" | "105:30" |
| "16.7" | "16:42" |
| "Abc" | "Abc" |
| "5:36" | "5:36" |
| "5:44" | "5:44" |
Here's a couple of extension methods (for DateTime and Decimal) that do the job:
public static class DecimalToTimeConverters
{
public static DateTime ToDateTime(this decimal value)
{
string[] parts = value.ToString().Split(new char[] { '.' });
int hours = Convert.ToInt32(parts[0]);
int minutes = Convert.ToInt32(parts[1]);
if ((hours > 23) || (hours < 0))
{
throw new ArgumentOutOfRangeException("value", "decimal value must be no greater than 23.59 and no less than 0");
}
if ((minutes > 59) || (minutes < 0))
{
throw new ArgumentOutOfRangeException("value", "decimal value must be no greater than 23.59 and no less than 0");
}
DateTime d = new DateTime(1, 1, 1, hours, minutes, 0);
return d;
}
public static Decimal ToDecimal(this DateTime datetime)
{
Decimal d = new decimal();
d = datetime.Hour;
d = d + Convert.ToDecimal((datetime.Minute * 0.01));
return d;
}
}
I tested this very quickly in an ASP.net webpage (I had a web project open at the time) using the following in a new blank page, and it seemed to work a treat:
protected void Page_Load(object sender, EventArgs e)
{
Response.Clear();
Decimal d = new decimal();
d = 3.45M;
Response.Write(d.ToDateTime().ToString());
Response.Write("<br />");
DateTime d2 = new DateTime(2009, 1, 1, 4, 55, 0);
Response.Write(d2.ToDecimal().ToString());
}
As per Rob but substitute
string[] parts = value.ToString().Split(new char[] { '.' });
int hours = Convert.ToInt32(parts[0]);
int minutes = Convert.ToInt32(parts[1]);
as
int hours = (int)value;
int minutes = (int)((value - minutes) * 100);
no strings or reliance on current culture (the assumption that the '.' is the decimal point)
How can I parse the txtDuration.Text Value into a decimal value?
if (txtDuration.Text)
{
var duration = int.Parse(txtDuration.Text);
var timespan = Boolean.Parse(hdfToggleDuration.Value) ? new TimeSpan (0, 0, duration, 0) : new TimeSpan (0, duration, 0, 0);
DateTime end = start.Add(timespan);
}

Categories

Resources