I'm developing an application for taking orders in C# and DevExpress, and I need a function that generates a unique order number. The order number must contain letters and digits and has a length of 20 ..
I've seen things like Guid.NewGuid() but I don't want it to be totally random, nor to be just an auto increment number ..
Can anyone help? even if it's a script in a different language, I need ideas desperately :)
You can create type of your own .
lets say yyyyMMddWWW-YYY-XXXXXXX where WWW is the store number, YYY the cashier id XXXXXXX is a hexadecimal number ( -> maybe an actual autoincrement number that you turn it into hex ) . This is just an idea . Im afraid you have to decide by the elements of your system how it will be .
edited : also if you can apply a check digit algorithm on it will also help in avoiding mistakes
Two different methods:
Create MD5 or SHA1 hash of current time
Hash of increment number
One thought comes to mind.
Take the DateTime.Now.Ticks convert it to hexadecimal string.
Voila, String.Format("{0:X}", value);
If not long enough , you said you need 20 digits, you can always pad with zeros.
Get the mother board ID
Get the hdd ID
Merge it by any way
Add your secret code
Apply MD5
Apply Base54
Result: the serial code which is linked to the currect client PC :)
My two cents.
If you need ideas then take a look at the Luhn and Luhn mod N algorithms.
While these algorithms are not unique code generators, they may give you some ideas on how to generate codes that can be validated (such that you could validate the code for correctness before sending it off to the database).
Like Oded suggested, Guid is not random (well, not if you have a network card). It's based on time and location coordinates. See Raymond Chens blog post for a detailed explanation.
You are best off using an auto incremented int for order ids. I don't understand why you wouldn't want to use it or failing that a Guid?
I can't think of any way other then an auto id to maintain uniqueness and represent the order of your different orders in your system.
Related
I'm using C# language for a project. I need to provide user with large (9+ digit) number, which they will have to reenter into another system (for later data correlation). Having a user enter a number that large (by hand) with no errors will be almost impossible.
I have been trying to come up with a solution to shorten that number using base64, but all the code I have found will create a string combination of character and digits. Is there a simple math algorithm I can use to make a large number smaller? The result should be numeric not alpha numeric.
You address the problem in a wrong way, instead of changing the number size just build a convenient way for the user to copy past the number , a simple key event wich will copy the number to the buffer, then the user will not have to write the number down.
Reducing a number using only numbers will never work.
What you really need is some form of error checking.
One that works very good is the Verhoeff Algorithm that will detect almost every typo. There are many examples to find online.
like:
https://www.codeproject.com/articles/15939/verhoeff-check-digit-in-c
You can use a Hash algorithm to hash your large number, but you need to deal with hash collision.
One of those very easy to implement is checksum sum16:
https://en.wikipedia.org/wiki/List_of_hash_functions
See sum16 you can only have 0-65536. Think about sum18 ?
I have the following three pieces of information. A group name, a group type, and group ranking.
As a quick example
"Mom's cats", "Cats", "Top10"
The example is way off from what I'm doing with this, but you get the basic idea.
The group name is a large selection of possible values (like around 20k) and the group type and group ranking are smaller amounts (like 10 each)
Trying to find a better way to come up with a short unique identifier for these group of things rather than having to use a sha1 with a huge ugly URL.
Any better ideas?
Open to all language solutions, so just pinning a lot of programmers here since I can't think of a better tag to assign to this.
Thanks.
EDIT: One solution that I found elsewhere a while back stated about taking the last few characters in the SHA-1 and converting them to a decimal value. Not sure how reliable this idea is and the chance of collision.
EDIT2: Using mongoDB and storing this sha1 value in the DB along with the members to make querying easy at the moment. Trying to find an alternative solution to creating an autoincrement field in a seperate table/collection which means a lot more queries when running updating scripts.
For python mappings you could use (grouptype, groupranking, groupname) as a dictionary key or you could reduce the size of the dictionaries by splitting something like a dictionary with a key of grouptype -> groupranking -> groupname.
For generating a unique url what is wrong with grouptype.rank.name or the same with / as a seperator - you could use the valid url type functions to replace invalid chars in each with %nn format.
You could use urllib.quote('/'.join([baseurl, grouptype, groupranking, groupname]) to generate such a path or even baseurl + urllib.urlencode({'grouptype':grouptype,'groupranking':groupranking,'groupname':groupname}) - the latter will result in the typical query format of baseurl?grouptype=Whatever&....
One of my clients wants to use a unique code for his items (long story..) and he asked me for a solution. The code will consist in 4 parts in which the first one is the zip code where the item is sent from, the second one is the supplier registration number, the third number is the year when the item is sent and the last part is a three division alphanumeric unique character.
As you can see the first three parts are static fields which will never change for the same sender in the same year. So we can say that the last part is the identifier part for that year. This part is 3-division alpahnumeric which means starting from 000 and ending with ZZZ.
The problem is that my client, for some reasonable reasons, wants this part to be not sequential. For example this is not what he wants:
06450-05-2012-000
06450-05-2012-001
06450-05-2012-002
...
06450-05-2012-ZZY
06450-05-2012-ZZZ
The last part should produced randomly like:
06450-05-2012-A17
06450-05-2012-0BF
06450-05-2012-002
...
06450-05-2012-T7W
06450-05-2012-22C
But it should also non-repetitive. So once a possible id is generated the possibility should be discarded from the selection pool.
I am looking for an effective way to do this.
If I only record selected possibilities and check a newly created one against them there is always a worst case possibility that it keeps producing already selected ones, especially near the end.
If I create all possibilities at once and record them in a table or a file it may take a while after every item creation because it will lookup for a non-selected record. By the way 26 letters + 10 digits means 46.656 possible combinations, and there is a chance that there may be a 4th divison added which means 1.679.616 possible combinations.
Is there a more effective way you can suggest? I will use C# for coding and MS SQL for databese..
If it doesn't have to be random, you could maybe simply choose a fixed but "unpredictable" addend which is relatively prime to 26 + 10 == 36 == 2²·3². This means, just choose a fixed addend divisible by neither 2 nor 3.
Then keep adding this fixed number to your previous serial number every time you need a new serial number. This is to be done modulo 46656 (or 1679616) of course.
Mathematics guarantees you won't get the same number twice (before no more "free" numbers are left).
As the addend, you could use const int addend = 26075 since it's 5 modulo 6.
If you expect to create far less than 36^3 entries for each zip-supplier-year tuple, you should probably just pick a random value for the last field and then check to see if it exists, repeating if it does.
Even if you create half of the maximum number of possible entries, new entries still have an expected value of only one failure. Assuming your database is indexed on the overall identifier, this isn't too great a price to pay.
That said, if you expect to use all but a few possible identifiers, then you should probably create all the possible records in advance. It may sounds like a high cost, but each space in memory storing an unused record will eventually store a real record.
I'd expect the first situation is more likely, but if not, or if there's some other combination of the two, please add a comment with some more information and I'll revise my answer.
I think options depend on the amount of the codes that are going to be used:
If you expect to use most of them within a year, then it is better to pre-generate. If done right, lookup should be really fast. And you are going to have 1.679.616 items per year in your DB anyway, so you will have to do such things right.
On the other hand, is it good that you are expecting to use most of them? It may leave you without codes if there are suddenly more items than expected.
If you expect to use only a small amount, then random+existence check might be a way to go, however it is unclear what amount it should be for that to be best (I am pretty sure it is possible to calculate that though).
Here is what I need (language: C# 4):
I am building a system where you can submit complaints. After complaint has been submitted you are given a unique 9 digits number that identifies your complaint in the system.
For security (security through obscurity) purposes I do not want ticket IDs to be sequential. But I do want to use database to generate sequential id.
So what I need is a injective function that is fast both ways: sequential number to my ticket id, and back from ticket id to the sequential number.
So that my ticketId in database is sequential, but before showing it to a user I will obfuscate it, similarly, when I get a number back from the user, I de-obfuscate it and use it to look up complaint in the database.
The obfuscation part does not need to be too complicated, just "not apparent enough" for general public.
For example I could simply change bitness of the value, which will get me (for 8-bit values):
0 -> 0
1 -> 128
2 -> 192
3 -> 64
4 -> 160
5 -> 96
etc.
I think you can solve this problem perfectly: Encrypt the ticket number with a constant key. There is a 32-bit block-size block cipher that you can use.
I would suggest something along the lines of symmetric encryption. For example, if you apply the substitution and diffusion steps of the DES encryption algorithm, you can get a number that can be quickly mapped back and forth but difficult to find a pattern. It is almost the same as your example but the S-Box and P-Box values are proved to be effective against cryptanalysis.
Why not just do something like this:
SHA1 your number, then store it in a table in your database along with your sequential number. Then when you receive the hash, just look up the sequential number in the database.
FYI, this is not really security. You should implement a real password system.
I am working on the front end of an application. I have to introduce one more filter criteria LoanNumber. Now loan number is E-100. Business layer and domain object is not in my control. So i cannot change it. Domain object which holds loannumber is integer, I have to do
ingeoFilterData.intLoanNumber="E-100"
ingeoFilterData is the domain object. intLoanNumber is declared as Nullable Int32 Now this domainobject is very critical and it goes to some external engine,so i cannot change it.
Please suggest some workaround.
Edit-
I am copying down loannumber from database table.
RT1
RT2
PT1
pt10
PT11
PT12
PT13
PT14
PT15
pt16
pt17
pt8
pt9
MDR1
MDR2
MDR3
If you have only one character, you can do this:
multiply your int by 100. (for example E-51 -> 5100)
Then keep the char as int in the rest of the number (for example 5106).
Do the reverse when you need to show the UI id (E-51).
If you have no limitations (as you mentioned) then you can have your int as a protocol (according to me that is even harder because you are limited by Int32 - 4,294,967,296).
You can set your number to something like
<meaning><number><meaning><number>
and meaning is - 1 - number, 2 - letter, 3 - hyphon.
then 11 will mean 1; 201 will mean A, 3 will mean hyphon, and 113201 will mean 1-A;
It's complicated and not very likely to be usable...
This solution limits your id to length of 5 numbers or 3 letters and 1 number. You can squeez some more by using your int bit-wize and optimize your "protocol" as much as possible.
I hope this helps,
Danail
Is "E-100" a string. ie. E is not a variable?
No, you can't set an int to a string value.
No, an int type cannot store a string. But you can parse your value to an int, before passing this to your domain object for filtering.
If the "prefix" of the loan number is always "E-" you could just exclude it.
Otherwise maybe you could add a property "LoanNumberPrefix" and store the "E-" in it.
Unfortunately at some point, bad design will give you unsolvable problems.
I don't know if this is one of them, but if the domain model has specified that loan numbers are integers, then either you, or the people that made that model clearly hasn't done their job.
Why the E in there? What does it signify? Is it just a prefix, can you remove it when storing it and put it back before displaying it?
Unfortunately, if the prefix can change, so that at some point you will have F-100 and so on, then you need to find a way to encode that into the integer you send to the domain model and business logic.
If you can't do that, you need to find a different place to store that prefix, or possibly the entire code.
If you can't do that, well, then you're screwed.
But to be blunt, this smells badly of someone who has been asleep while designing.
"Yeah, that's a good idea, we'll make the loan identification number an integer. I know somewhere, someplace, that someone has an example of what those loan identification numbers look like, but it's just numbers right? I mean, what could go wrong...?"
i think thats possible if you can convert the char into ASCII code.
string --- ASCII
0-10---48-57
A-Z----65-90
a-z----97-122
check out the ASCII table for more info..
Conversion:
so you can convert
RT1 to 082084049
RT2 to 082084050 and
MDR3 to 077068082051
i just prepend 0's to each character if the value is not 3 digit one(because max possible ASCII (z) value is in 3 digits ). R is actually 82, it becomes 082. And the final integer (no of digits) would be in multiples of 3.
Extraction:
This helps to extract the info in the other end. just split this into seperate 3 digit values and convert them to char and append them. you wil get the final string.
082,084,049 - R,T,1. thats all.
p.s: this method may end up in arithmetic overflow problem for large strings
I suggest that you talk to someone in the business/domain layer, or who is responsible for the design of the system, and point out to them that loannumber need to be changed to a string. No one will thank you for bodging your code to get around what is a design flaw--it can only lead to trouble and confusion later.