NHibernate - Multiply price by 100 before saving - nhibernate

I'm using Fluent NHibernate with SQlite and I need to store prices. I prefer to multiply the price by 100 before storing it in order to remove the decimal place so that I can use INTEGER datatype instead of REAL, since REAL always uses 8 bytes whereas INTEGER may take 1, 2, 3, 4, 6, or 8 bytes according to SQlite documentation.
Do I need to declare a custom type to take care of the multiplication by 100 (and division by 100 when retrieving the price) and use it in the mapping with Map(p => p.PriceValue).CustomType<PriceWithoutDecimalPlace>(); ?
Or is there an easier way?

In NHibernate 5.2+ you may try to register your custom type as default for all decimal properties.
Something like:
//Somewhere before SessionFactory is created
TypeFactory.RegisterType(typeof(decimal), new PriceWithoutDecimalPlace(), new[] {"decimal"});

Related

What is the difference between var map=HashMap<Int,String>() and var map=HashMap<Int,String>(n)?

Consider n is any integer with any particular value in the range of Int data type. so What is the difference between var map=HashMap<Int,String>() and var map=HashMap<Int,String>(n) ?
The HashMap(n) overload accepts the initial capacity, which is used to initialize the HashMap with the provided capacity instead of the default one (which is rather small to reduce memory usage, 16 in JDK 8).
Use it when you know how many items you are going to put into the map, at least approximately, because it allows you to avoid overhead of re-allocating the map and re-hashing the keys as you put entries into it

Why are these hashcodes equals?

This test is failing :
var hashCode = new
{
CustomerId = 3354,
ServiceId = 3,
CmsThematicId = (int?)605,
StartDate = (DateTime?)new DateTime(2013, 1, 5),
EndDate = (DateTime?)new DateTime(2013, 1, 6)
}.GetHashCode();
var hashCode2 = new
{
CustomerId = 1210,
ServiceId = 3,
CmsThematicId = (int?)591,
StartDate = (DateTime?)new DateTime(2013, 3, 31),
EndDate = (DateTime?)new DateTime(2013, 4, 1)
}.GetHashCode();
Assert.AreNotEqual(hashCode, hashCode2);
Can you tell me why ?
It's kinda amazing you found this coincidence.
Anonymous classes have a generated GetHashCode() method that generates a hash code by combining the hash codes of all properties.
The calculation is basically this:
public override int GetHashCode()
{
return -1521134295 *
( -1521134295 *
( -1521134295 *
( -1521134295 *
( -1521134295 *
1170354300 +
CustomerId.GetHashCode()) +
ServiceId.GetHashCode()) +
CmsThematicId.GetHashCode()) +
StartDate.GetHashCode()) +
EndDate.GetHashCode();
}
If you change any of the values of any of the fields, the hash code does change. The fact that you found two different sets of values that happen to get the same hash codes is a coincidence.
Note that hash codes are not necessarily unique. It's impossible to say hash codes would always be unique since there can be more objects than hash codes (although that is a lot of objects). Good hash codes provide a random distribution of values.
NOTE: The above is from .NET 4. Different versions of .NET may different and Mono differs.
If you want to actually compare two objects for equality then use .Equals(). For anonymous objects it compares each field. An even better option is to use an NUnit constraint that compares each field and reports back which field differs. I posted a constraint here:
https://stackoverflow.com/a/2046566/118703
Your test is not valid.
Because hash codes are not guaranteed to be unique (see other answers for a good explanation), you should not test for uniqueness of hash codes.
When writing your own GetHashCode() method, it is a good idea to test for even distribution of random input, just not for uniqueness. Just make sure that you use enough random input to get a good test.
The MSDN spec on GetHashCode specifically states:
For the best performance, a hash function must generate a random
distribution for all input.
This is all relative, of course. A GetHashCode() method that is being used to put 100 objects in a dictionary doesn't need to be nearly as random as a GetHashCode() that puts 10,000,000 objects in a dictionary.
Did you run into this when processing a fairly large amount of data?
Welcome to the wonderful world of hash codes. A hash code is not a "unique identifier." It can't be. There is an essentially infinite number of possible different instances of that anonymous type, but only 2^32 possible hash codes. So it's guaranteed that if you create enough of those objects, you're going to see some duplicates. In fact, if you generate 70,000 of those objects randomly, the odds are better than 50% that two of them will have the same hash code.
See Birthdays, Random Numbers, and Hash Codes, and the linked Wikipedia article for more info.
As for why some people didn't see a duplicate and others did, it's likely that they ran the program on different versions of .NET. The algorithm for generating hash codes is not guaranteed to remain the same across versions or platforms:
The GetHashCode method for an object must consistently return the same
hash code as long as there is no modification to the object state that
determines the return value of the object's Equals method. Note that
this is true only for the current execution of an application, and
that a different hash code can be returned if the application is run
again.
Jim suggested me (in the chat room) to store my parameters so when i display my parameters, select the not used ones, then when someone registers I flag it as used. But it's a big PITA to generate all the parameters.
So my solution is to build a int64 hashcode like this
const long i = -1521134295;
return -i * (-i * (-i * (-i * -117147284 + customerId.GetHashCode()) + serviceId.GetHashCode()) + cmsThematicId.GetHashCode()) + startDate.GetHashCode();
I removed the end date because Its value was depending on serviceId and startDate so I shouldn't have add this to the hashcode in the firstplace.
I copy/pasted it from a decompilation of the generated class. I got not colision if I do a test with 300 000 differents combinations.

OpenISO8583.Net BCD Formatted Track 2

Here is another question.
My requirement for Track 2 (bit 35) is:
Z (Numeric + X 'D' (BCD, ½ byte representation of D [1101] as a field separator between Primary Account Number and Expiration Date), BCD — When an odd number of digits, pack right-most half byte to '0'. Size: Variable to 37, preceded by a one-byte, BCD length indicator
The default template definition has bit 35 as a 2 byte length Ascii field so I am sure that is not it. I changed it to BcdVar(1, 37, Formatters.Bcd).
Taking a dummy track2 example of:
12345678901234567=9999999999999999999
I replace the '=' separator with the 0x0D integer value which translates to "13" (1101). We now have:
12345678901234567139999999999999999999
Does this make sense? I don't think this is the correct way of doing it.
You've run into a "feature" of OpenIso8583.Net. When you work with the field values using msg[3] = "123456", you must always work with the unpacked values.
For this track2 data, you need to build up the track 2 as 12345678901234567D9999999999999999999. Note the 'D' in the middle of the data as a separator.
Now in your Template set field 35 to have a BCD formatter, essentially.
template[Bit._035_TRACK_2_DATA] = FieldDescriptor.BcdVar(2, 37, FieldValidators.Track2)
I sort of duplicated the question (Track2 in BCD - 'D' character).
Treating the field as Binary (with a BCD-Length-Indicator!!!) is a cute trick, which might do the trick. But, still - there is no method:
public static FieldDescriptor.BinaryVar(..., ILengthFormatter lengthFormatter)
so instead of adding it (which should be done anyway, for cases of BinaryVar fields), one can add a:
public static FieldDescriptor.BcdVar(..., IFieldValidator validator)
and call:
msg[Bit._035_TRACK_2_DATA] = FieldDescriptor.BcdVar(2, 37, FieldValidators.Track2);
the 'D' will be treated as BCD - what do banks know...
Regarding the right-padding - I guess that's where the Adjuster comes handy. Again, we need to add a static method with an Adjuster parameter like this:
var setAdjuster = new LambdaAdjuster(setLambda: value => value.PadRight(value.length + 1, '0'));
It's true - you can pad the value prior to setting the field, but that's not fun (we're geeks, aren't we?).
Regarding adding static methods to FieldDescriptor - I guess it's possible to use the generic
public static IFieldDescriptor Create(ILengthFormatter lengthFormatter, IFieldValidator fieldValidator, IFormatter formatter, Adjuster adjuster)
but I'm new to C# and would be glad to get confirmation regarding my theories.
Thanks.

How to make rand() more likely to select certain numbers?

Is it possible to use rand() or any other pseudo-random generator to pick out random numbers, but have it be more likely that it will pick certain numbers that the user feeds it? In other words, is there a way, with rand() or something else, to pick a pseudo random number, but be able to adjust the odds of getting certain outcomes, and how do you do that if it is possible.
BTW, I'm just asking how to change the numbers that rand() outputs, not how to get the user input.
Well, your question is a bit vague... but if you wanted to pick a number from 0-100 but with a bias for (say) 43 and 27, you could pick a number in the range [0, 102] and map 101 to 43 and 102 to 27. It will really depend on how much bias you want to put in, what your range is etc.
You want a mapping function between uniform density of rand() and the probability density that you desire. The mapping function can be done lots of different ways.
You can certainly use any random number generator to skew the results. Example in C#, since I don't know objective-c syntax. I assume that rand() return a number tween 0 and 1, 0 inclusive and 1 exclusive. It should be quite easy to understand the idear and convert the code to any other language.
/// <summary>
/// Dice roll with a double chance of rolling a 6.
/// </summary>
int SkewedDiceRoll()
{
// Set diceRool to a value from 1 to 7.
int diceRool = Math.Floor(7 * rand()) + 1;
// Treat a value of 7 as a 6.
if (diceRoll == 7)
{
diceRoll = 6;
}
return diceRoll;
}
This is not too difficult..
simply create an array of all possible numbers, then pad the array with extra numbers of which you want to result more often.
ie:
array('1',1','1','1','2','3','4','4');
Obviously when you query that array, it will call "1" the most, followed by "4"
In other words, is there a way, with rand() or something else, to pick a pseudo random number, but be able to adjust the odds of getting certain outcomes, and how do you do that if it is possible.
For simplicity sake, let's use the drand48() which returns "values uniformly distributed over the interval [0.0,1.0)".
To make the values close to one more likely to appear, apply skew function log2():
log2( drand48() + 1.0 ); // +1 since log2() in is [0.0, 1.0) for values in [1.0, 2.0)
To make the values close to zero more likely to appear, use the e.g. exp():
(exp(drand48()) - 1.0) * (1/(M_E-1.0)); // exp(0)=1, exp(1)=e
Generally you need to crate a function which would map the uniformly distributed values from the random function into values which are distributed differently, non-uniformly.
You can use the follwing trick
This example has a 50 percent chance of producing one of your 'favourite' numbers
int[] highlyProbable = new int[]{...};
public int biasedRand() {
double rand = rand();
if (rand < 0.5) {
return highlyProbable[(int)(highlyProbable.length * rand())];
} else {
return (int)YOUR_RANGE * rand();
}
}
In addition to what Kevin suggested, you could have your regular group of numbers (the wide range) chopped into a number of smaller ranges, and have the RNG pick from the ranges you find favorable. You could access these ranges in a particular order, or, you can access them in some random order (but I can assume this wouldn't be what you want.) Since you're using manually specified ranges to be accessed within the wide range of elements, you're likely to see the numbers you want pop up more than others. Of course, this is just how I'd approach it, and it may not seem all that rational.
Good luck.
By definition the output of a random number generator is random, which means that each number is equally likely to occur next (1/10 chance) and you should not be able to affect the outcome.
Of-course, a pseudo-random generator creates an output that will always follow the same pattern for a given input seed. So if you know the seed, then you may have some idea of the output sequence. You can, of-course, use the modulus operator to play around with the set of numbers being output from the generator (eg. %5 + 2 to generate numbers from 2 to 7).

Game Design: Data structures for Stackable Attributes (DFP, HP, MP, etc) in an RPG (VB.Net)

I'm wrangling with issues regarding how character equipment and attributes are stored within my game.
My characters and equippable items have 22 different total attributes (HP, MP, ATP, DFP). A character has their base-statistics and can equip up to four items at one time.
For example:
BASE ATP: 55
WEAPON ATP: 45
ARMOR1 ATP: -10
ARMOR2 ATP: -5
ARMOR3 ATP: 3
Final character ATP in this case would be 88.
I'm looking for a way to implement this in my code. Well, I already have this implemented but it isn't elegant. Right now, I have ClassA that stores these attributes in an array. Then, I have ClassB that takes five ClassA and will add up the values and return the final attribute.
However, I need to emphasize that this isn't an elegant solution.
There has to be some better way to access and manipulate these attributes, including data structures that I haven't thought of using. Any suggestions?
EDIT: I should note that there are some restrictions on these attributes that I need to be put in place. E.g., these are the baselines.
For instance, the character's own HP and MP cannot be more than the baseline and cannot be less than 0, whereas the ATP and MST can be. I also currently cannot enforce these constraints without hacking what I currently have :(
Make an enum called CharacterAttributes to hold each of STR, DEX, etc.
Make an Equipment class to represent any equippable item. This class will have a Dictionary which is a list of any stats modified by this equipment. For a sword that gives +10 damage, use Dictionary[CharacterAttributes.Damage] = 10. Magic items might influence more than one stat, so just add as many entries as you like.
The equipment class might also have an enum representing which inventory it slots to (Boots, Weapon, Helm).
Your Character class will have a List to represent current gear. It will also have a dictionary of CharacterAttributes just like the equipment class, which represents the character's base stats.
To calculate final stats, make a method in your Character class something like this:
int GetFinalAttribute(CharacterAttributes attribute)
{
int x = baseStats[attribute];
foreach (Equipment e in equipment)
{
if (e.StatModifiers[attribute] != null)
{
x += e.StatModifiers[attribute];
}
}
// do bounds checking here, e.g. ensure non-negative numbers, max and min
return x;
}
I know this is C# and your post was tagged VB.NET, but it should be easy to understand the method. I haven't tested this code so apologies if there's a syntax error or something.