Convert SQL query to C# (SQL query converts base36 code to DateTime) - c#

I'd like to be able to encode \ decode id's containing the datetime in a 7 digit \ base36 configuration, but despite having a SQL query that decodes Id's, so far have had no luck.
I have a SQL query that is able to convert the code to a date time.
Using the following ids, I'm hoping to get the corresponding datetimes.
id Date Time
------------------------------------
A7LXZMM 2004-02-02 09:34:47.000
KWZKXEX 2018-11-09 11:15:46.000
LIZTMR9 2019-09-13 11:49:46.000
Query:
DECLARE #xdate DATETIME, #offset INT
DECLARE #recid VARCHAR(20)
SET #recid = 'KWZKXEX'
SET #offset = (SELECT DATEDIFF(ss, GETUTCDATE(), GETDATE())) /************* Number of hours offset from GMT ************/
SELECT
DATEADD(ss, #offset +
(POWER(CAST(36 AS BIGINT), 6) *
CASE
WHEN (SELECT ISNUMERIC(SUBSTRING(#recid, 1, 1))) = 0
THEN (SELECT ASCII(SUBSTRING(#recid, 1, 1))) - 55
ELSE (SELECT ASCII(SUBSTRING(#recid, 1, 1))) - 48
END +
POWER(CAST(36 AS BIGINT), 5) *
case
when(select isnumeric(substring(#recid,2,1))) = 0
then(select ascii(substring(#recid,2,1))) - 55
else (select ascii(substring(#recid,2,1))) - 48
End
+
POWER(cast(36 as bigint),4) *
case
when(select isnumeric(substring(#recid,3,1))) = 0
then(select ascii(substring(#recid,3,1))) - 55
else (select ascii(substring(#recid,3,1))) - 48
End
+
POWER(cast(36 as bigint),3) *
case
when(select isnumeric(substring(#recid,4,1))) = 0
then(select ascii(substring(#recid,4,1))) - 55
else (select ascii(substring(#recid,4,1))) - 48
End
+
POWER(cast(36 as bigint),2) *
case
when(select isnumeric(substring(#recid,5,1))) = 0
then(select ascii(substring(#recid,5,1))) - 55
else (select ascii(substring(#recid,5,1))) - 48
End
+
POWER(cast(36 as bigint),1) *
case
when(select isnumeric(substring(#recid,6,1))) = 0
then(select ascii(substring(#recid,6,1))) - 55
else (select ascii(substring(#recid,6,1))) - 48
End
+
POWER(cast(36 as bigint),0) *
case
when(select isnumeric(substring(#recid,7,1))) = 0
then(select ascii(substring(#recid,7,1))) - 55
else (select ascii(substring(#recid,7,1))) - 48
End
)
/50
,'1/1/1990')
using System;
using System.Globalization;
using System.Text;
using System.Numerics;
public class Program
{
public static void Main()
{
string sRecid = "A7LXZMM";
char c0 = sRecid[0];
char c1 = sRecid[1];
char c2 = sRecid[2];
char c3 = sRecid[3];
char c4 = sRecid[4];
char c5 = sRecid[5];
char c6 = sRecid[6];
double d6, d5, d4, d3, d2, d1, d0, dsecs;
Console.WriteLine("c0 = " + c0.ToString());
Console.WriteLine();
d6 = Math.Pow(36, 6) * ((Char.IsNumber(c0)) ? (byte)c0 - 55 : (byte)c0 - 48);
d5 = Math.Pow(36, 5) * ((Char.IsNumber(c1)) ? (byte)c1 - 55 : (byte)c1 - 48);
d4 = Math.Pow(36, 4) * ((Char.IsNumber(c2)) ? (byte)c2 - 55 : (byte)c2 - 48);
d3 = Math.Pow(36, 3) * ((Char.IsNumber(c3)) ? (byte)c3 - 55 : (byte)c3 - 48);
d2 = Math.Pow(36, 2) * ((Char.IsNumber(c4)) ? (byte)c4 - 55 : (byte)c4 - 48);
d1 = Math.Pow(36, 1) * ((Char.IsNumber(c5)) ? (byte)c5 - 55 : (byte)c5 - 48);
d0 = Math.Pow(36, 0) * ((Char.IsNumber(c6)) ? (byte)c6 - 55 : (byte)c6 - 48);
dsecs = d6 + d5 + d4 + d3 + d2 + d1 + d0 / 50;
DateTime dt = new DateTime(1990, 1, 1, 0, 0, 0,0, System.DateTimeKind.Utc);
dt = dt.AddSeconds( dsecs ).ToLocalTime();
Console.WriteLine("d6 = " + d6.ToString());
Console.WriteLine("d5 = " + d5.ToString());
Console.WriteLine("d4 = " + d4.ToString());
Console.WriteLine("d3 = " + d3.ToString());
Console.WriteLine("d2 = " + d2.ToString());
Console.WriteLine("d1 = " + d1.ToString());
Console.WriteLine("d0 = " + d0.ToString());
Console.WriteLine("dsecs = " + dsecs.ToString());
Console.WriteLine("dt = " + dt.ToString());
}
}
When I use the following Ids in SQL, I get the following dates.
id Date Time
------------------------------------
A7LXZMM 2004-02-02 09:34:47.000
KWZKXEX 2018-11-09 11:15:46.000
LIZTMR9 2019-09-13 11:49:46.000
Unfortunately my C# "conversion" is wildly inaccurate.
Any suggestions as to where I'm going wrong?

you have the Char.IsNumber... checks flipped in your C# code compared to your SQL script.
In your SQL, you're subtracting 55 if the character is not a number, and 48 otherwise.
In your C# code you're subtracting 55 if the character is a number, and 48 otherwise.
You're also not calculating dsecs correctly I don't think. You need to add d6 through d0 then divide by 50. The way you have it now, you'll divide d0 by 50 then add all the other dn variables.
In other words...
dsecs = d6 + d5 + d4 + d3 + d2 + d1 + d0 / 50;
Should be
dsecs = (d6 + d5 + d4 + d3 + d2 + d1 + d0) / 50;

Related

Transform IDA Pro il2cpp pseudo code to C# code

Mean problem is this 3 line, and strPath seems is string type, but looks like it casting to int type?
*(_DWORD *)(v6 + 24)
*(_QWORD *)(v6 + 8i64 * v20 + 32)
enryptedMemory->m_Items[(int)strPath]
I had try do some code clear and transform for referance. And need help to finish it.
v6 is System Runtime CompilerServices RuntimeHelpers InitializeArray and I think the hex in metadata
3D 06 F4 2B C5 7A 9E 18 D1 64 F2 8B 05 EA 97 3C
C3 F7 D5 91 04 A2 6B E8 A4 2F 1E D0 73 8B 9C 56
will to be ulong array, because (ulong___TypeInfo, 4i64 )
public byte[] DecryptMemory(string strPath, byte[] enryptedMemory)
{
int v20, v23;
long v21;
byte[] v4 = enryptedMemory;
string v5 = strPath;
if ( v4.Length < 8 )
return 0;
ulong[] v6 = new ulong[]{ 0x189E7AC52BF4063D, 0x3C97EA058BF264D1, 0xE86BA20491D5F7C3, 0x569C8B73D01E2FA4 };
int v7 = v4.Length;
byte[] v10 = new byte[v7 - 8];
int v11 = (v7 - 8) / 16;
byte[] v16 = new byte[16];
byte[] src = new byte[16];
byte[] dst = new byte[16];
if ( v11 > 0 )
{
for (int v18=0, v19=0; v18 < v11; v18++, v19 += 16)
{
Array.Copy(v4, v19 + 8, v16, 0, 16);
v20 = v18 % *(UInt32 *)(v6 + 24);
v21 = *(UInt64 *)(v6 + 8 * v20 + 32);
Utility__shuffle16(dst, src, v21, 0);
Array.Copy(dst, 0, v10, v19, 16);
v16 = src;
}
}
int v22 = 16 * v11;
while ( true )
{
v23 = *(UInt32 *)(v10 + 24);
if ( v22 >= v23 )
break;
*(UINT8 *)(v24 + v10 + 32) = v4->m_Items[v22 + 8];
v22++;
}
int v17 = 0;
string v27 = Utility__sha1Hashed(Path.GetFileNameWithoutExtension(v5));
for ( enryptedMemory = Encoding.ASCII.GetBytes(v27); ; *(UInt8 *)(v17++ + v10 + 32) ^= enryptedMemory->m_Items[(int)strPath] )
{
this = *(unsigned int *)(v10 + 24);
if ( v17 >= (int)this )
break;
strPath = (string)(uint)(v17 >> 31);
LODWORD(strPath) = v17 % enryptedMemory.Length;
}
return v10;
}

List update in every loop run - Unexpected behavior

I tried to write simple program, that simulates lottery and I got some behavior I cannot understand, nor fix:
To keep it simple I excluded code that is irrelevant to the problem
PROGRAM: On click it should Get six different numbers (between 1 and 49) entered by user, get six different random numbers (between 1 and 49) compare them and repeat getting random numbers and comparing with entered until there are three matches.
What is relevant, I am calling function GetResults() on button click and passing to it two parameters (method definition below). I simplified it to button click to show you. There are some conditions and function calls there, but they are working and problem exists even without them so that's why image example on the bottom may be a little different.
private void btnCheck_Click(object sender, EventArgs e)
{
lotto.GetResults(3, ref listRndNumLabels);
lblMatches.Text = lotto.CurrentMatches.ToString();
lblTryCounter.Text = lotto.NumberOfTries.ToString();
lblBalance.Text = lotto.Balance.ToString() + " zł";
lblThreesAmmount.Text = lotto.ThreesAmmount.ToString();
lblFoursAmmount.Text = lotto.FoursAmmount.ToString();
lblFivesAmmount.Text = lotto.FivesAmmount.ToString();
lblSixesAmmount.Text = lotto.SixesAmmount.ToString();
}
The method GetResults() takes 3 as number of desired matches and List of Labels which is updated at the end
public void GetResults(int Choice, ref List<Label> listLblRndNum)
{
_currentMatches = 0;
int desiredNumberOfMatches = Choice;
// while we got other ammount of matches than three, go again
while (_currentMatches != desiredNumberOfMatches)
{
_numberOfTries++;
// get list of mutually exclusive 6 numbers betweeen 1 and 49
var tempList = GetRndNums();
// insert random numbers to list
_listLotteryNumbers.Clear();
for (int i = 0; i < 6; i++)
{
_listLotteryNumbers.Insert(i, tempList[i]);
}
_balance -= _ticketCost;
_currentMatches = 0;
// get number of matches
for (int i = 0; i < 6; i++)
{
foreach (int num in _listLotteryNumbers)
{
if (_listSelectedNumbers[i] == num)
{
_currentMatches++;
}
}
}
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _currentMatches: " + _currentMatches.ToString());
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - tempList { " + tempList[0] + " " + tempList[1] + " " + tempList[2] + " " + tempList[3] + " " + tempList[4] + " " + tempList[5] + " }");
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _listLotteryNumbers { " + _listLotteryNumbers[0] + " " + _listLotteryNumbers[1] + " " + _listLotteryNumbers[2] + " " + _listLotteryNumbers[3] + " " + _listLotteryNumbers[4] + " " + _listLotteryNumbers[5] + " }");
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - _listSelectedNumbers { " + _listSelectedNumbers[0] + " " + _listSelectedNumbers[1] + " " + _listSelectedNumbers[2] + " " + _listSelectedNumbers[3] + " " + _listSelectedNumbers[4] + " " + _listSelectedNumbers[5] + " }");
// update stats
if (_currentMatches == 3)
{
_threesAmmount++;
_balance += 10;
}
else if (_currentMatches == 4)
{
_foursAmmount++;
_balance += 100;
}
else if (_currentMatches == 5)
{
_fivesAmmount++;
_balance += 3500;
}
else if (_currentMatches == 6)
{
_sixesAmmount++;
_balance += 1000000;
}
//FrmLotto.lbResults.Items.Add(_numberOfTries.ToString() + " - Threes Ammount right after updating: " + _threesAmmount);
//FrmLotto.lbResults.Items.Add("");
// this gets out of the loop if user has chosen from ddl to run once, it is irrelevant here
if (desiredNumberOfMatches == -1)
break;
}
// finally update Labels with the desired result
for (int i = 0; i < 6; i++)
{
listLblRndNum[i].Text = _listLotteryNumbers[i].ToString();
}
}
And this is the function which gets random numbers:
public List<int> GetRndNums()
{
List<int> listRndNums = new List<int>();
Random rndNum = new Random();
for (int i = 0; i < 6; i++)
{
int myNum = 0;
do
myNum = rndNum.Next(1, 49);
while (listRndNums.Contains(myNum));
listRndNums.Add(myNum);
}
listRndNums.Sort();
return listRndNums;
}
So program works as expected if loop run once, or if there is delay after each loop, or if I put breakpoint in the loop.
OTHERWISE there is an unexpected behavior, loop run more than once for the same data (for the same lists), I don't understand why.
look at the images:
Program run once, I clicked button five times, to show you that results are fine:
(btw = Sprawdź = Check, raz = once, do pierwszej trójki = until 3 matches)
http://ultraimg.com/jHQY
And when I select until 3 matches (or click button from the code example above) I am receiving wrong result, loop runs multiple times for the same values.
http://ultraimg.com/jHQn
Would be really grateful for help, I am learning, I know that many parts of code could be improved, many parts are for temp debugging purposes only. But this behavior, I simply don't get it.
In order to fix this problem you should try making
Random rndNum = new Random();
a static variable.
See this :
http://msdn.microsoft.com/en-us/library/system.random.aspx
Pseudo-random numbers are chosen with equal probability from a finite set of numbers. The chosen numbers are not completely random because a definite mathematical algorithm is used to select them, but they are sufficiently random for practical purposes. The current implementation of the Random class is based on Donald E. Knuth's subtractive random number generator algorithm. For more information, see D. E. Knuth. "The Art of Computer Programming, volume 2: Seminumerical Algorithms". Addison-Wesley, Reading, MA, second edition, 1981.
The random number generation starts from a seed value. If the same
seed is used repeatedly, the same series of numbers is generated. One
way to produce different sequences is to make the seed value
time-dependent, thereby producing a different series with each new
instance of Random. By default, the parameterless constructor of the
Random class uses the system clock to generate its seed value, while
its parameterized constructor can take an Int32 value based on the
number of ticks in the current time. However, because the clock has
finite resolution, using the parameterless constructor to create
different Random objects in close succession creates random number
generators that produce identical sequences of random numbers. The
following example illustrates that two Random objects that are
instantiated in close succession generate an identical series of
random numbers.
byte[] bytes1 = new byte[100];
byte[] bytes2 = new byte[100];
Random rnd1 = new Random();
Random rnd2 = new Random();
rnd1.NextBytes(bytes1);
rnd2.NextBytes(bytes2);
Console.WriteLine("First Series:");
for (int ctr = bytes1.GetLowerBound(0);
ctr <= bytes1.GetUpperBound(0);
ctr++) {
Console.Write("{0, 5}", bytes1[ctr]);
if ((ctr + 1) % 10 == 0) Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("Second Series:");
for (int ctr = bytes2.GetLowerBound(0);
ctr <= bytes2.GetUpperBound(0);
ctr++) {
Console.Write("{0, 5}", bytes2[ctr]);
if ((ctr + 1) % 10 == 0) Console.WriteLine();
}
// The example displays the following output to the console:
// First Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
//
// Second Series:
// 97 129 149 54 22 208 120 105 68 177
// 113 214 30 172 74 218 116 230 89 18
// 12 112 130 105 116 180 190 200 187 120
// 7 198 233 158 58 51 50 170 98 23
// 21 1 113 74 146 245 34 255 96 24
// 232 255 23 9 167 240 255 44 194 98
// 18 175 173 204 169 171 236 127 114 23
// 167 202 132 65 253 11 254 56 214 127
// 145 191 104 163 143 7 174 224 247 73
// 52 6 231 255 5 101 83 165 160 231
This problem can be avoided by creating a single Random object rather
than multiple ones. To improve performance, create one Random object
to generate many random numbers over time, instead of repeatedly
creating a new Random objects to generate one random number. To
generate a cryptographically secure random number suitable for
creating a random password, for example, use a class derived from
System.Security.Cryptography.RandomNumberGenerator such as
System.Security.Cryptography.RNGCryptoServiceProvider.

Is Microsoft Solver Foundation bugged?

I wrote this infeasible oml by mistake while trying to do another thing. What's wrong about it is that the constraint at the bottom is impossible since the minimum value on the right must be zero and the maximum on the left must be bigger than zero (unless of course I'm missing something).
The problem is that if you run it MSF will happily give you an answer instead of telling you is infeasible.
string oml = #"
Model[
Decisions[Integers[0,Infinity], d1],
Decisions[Integers[0,Infinity], d2],
Decisions[Integers[0,Infinity], d3],
Decisions[Integers[0,Infinity], d4],
Decisions[Integers[0,Infinity], d5],
Decisions[Integers[0,Infinity], d6],
Decisions[Integers[0,Infinity], d7],
Decisions[Integers[0,Infinity], d8],
Decisions[Integers[0,Infinity], d9],
Decisions[Integers[0,Infinity], d10],
Decisions[Integers[0,Infinity], d11],
Decisions[Integers[0,Infinity], d12],
Decisions[Integers[0,Infinity], d13],
Decisions[Integers[0,Infinity], d14],
Decisions[Integers[0,Infinity], d15],
Decisions[Integers[0,Infinity], d16],
Constraints[d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8 == 2],
Constraints[d9 + d10 + d11 + d12 + d13 + d14 + d15 + d16 == 2],
Constraints[d1 + d9 <= 1],
Constraints[d2 + d10 <= 1],
Constraints[d3 + d11 <= 1],
Constraints[d4 + d12 <= 1],
Constraints[d5 + d13 <= 1],
Constraints[d6 + d14 <= 1],
Constraints[d7 + d15 <= 1],
Constraints[d8 + d16 <= 1],
Constraints[Max[d1 * 1, d2 * 2, d3 * 3, d4 * 4, d5 * 1, d6 * 2, d7 * 3, d8 * 4] <= Min[d9 * 1, d10 * 2, d11 * 3, d12 * 4, d13 * 1, d14 * 2, d15 * 3, d16 * 4]]
]
";
SolverContext sc = SolverContext.GetContext();
sc.LoadModel(FileFormat.OML, new StringReader(oml));
var sol = sc.Solve();
Console.WriteLine(sol.GetReport());
Edit:
This is what my report gives me:
===Solver Foundation Service Report===
Date: 6/26/2012 11:00:55 AM
Version: Microsoft Solver Foundation 3.0.1.10599 Express Edition
Model Name: DefaultModel
Capabilities Applied: CP
Solve Time (ms): 135
Total Time (ms): 338
Solve Completion Status: Feasible
Solver Selected: Microsoft.SolverFoundation.Solvers.ConstraintSystem
Directives:
Microsoft.SolverFoundation.Services.Directive
Algorithm: TreeSearch
Variable Selection: DomainOverWeightedDegree
Value Selection: ForwardOrder
Move Selection: Any
Backtrack Count: 0
===Solution Details===
Goals:
Decisions:
d1: 0
d2: 0
d3: 0
d4: 0
d5: 0
d6: 0
d7: 1
d8: 1
d9: 0
d10: 0
d11: 1
d12: 1
d13: 0
d14: 0
d15: 0
d16: 0
It seems to be a version problem. When running the same problem in the latest release (standard edition) of MSF, the solver reports the problem as Infeasible. Apart from this, the report lists the same properties as the report from 3.0 above, just not the decision values.
So yes, it seems like there is some kind of bug in MSF 3.0. To overcome this bug, try and upgrade to the latest MSF version, 3.1.

Delphi Extended to C#

how to convert a floating point 10 byte Hex string (Extended datatype in Delphi) to a C# datatype?
For example:
00 00 00 00 00 00 00 80 ff 3f is at Delphi 1
Was involved in same issue, sharing my solution somebody can find useful:
var extendedSize = 10;
var buf = new byte[extendedSize];
// Populate buffer with something like: { 0x00, 0x68, 0x66, 0x66, 0x66, 0x66, 0x66, 0xA2, 0x02, 0x40 } = 10.15
// Read(buf, extendedSize);
var sign = (buf[extendedSize - 1] & 0x80) == 0x80 ? -1 : 1;
buf[extendedSize - 1] = (byte)(buf[extendedSize - 1] & 0x7F);
var exp = BitConverter.ToUInt16(buf, extendedSize - 2);
var integral = (buf[extendedSize - 3] & 0x80) == 0x80 ? 1 : 0;
// Calculate mantissa
var mantissa = 0.0;
var value = 1.0;
var fractal = BitConverter.ToUInt64(buf, 0);
while (fractal != 0)
{
value = value / 2;
if ((fractal & 0x4000000000000000) == 0x4000000000000000) // Latest bit is sign, just skip it
{
mantissa += value;
}
fractal <<= 1;
}
return sign * (Math.Pow(2, exp - 16383)) * (integral + mantissa);
Code needs to be improved with NaN and Inf checks and probably "double" needs to be replaced by "decimal".
Ok, here is my solution:
Every string contains a factor byte at the second position. In my example the factor is ff.
Now I have to convert the string via Floating-Point Conversion to decimal and multiply with the factor byte to get the result.
Example:
3f ff 80 00 00 (32bit) -> remove the factor byte (ff) -> 3f 80 00 00 -> convert to decimal -> result: 1 -> multiply with factor -> 1 * 1 -> result: 1
I hope this was helpfully

Music major scale converter

i am trying to create music major scale converter.
Dose anyone have info how do to it
so far i have
rootNote is scale base note like cMajor or gMajor
note is note that i want to convert into major scale 0-126
if i insert rootNote 60 and note 60 the right return would be 0,
if i insert rootNote 60 and note 61 the right return would be 2,
if i insert rootNote 60 and note 62 the right return would be 4,
if i insert rootNote 60 and note 63 the right return would be 5,
if i insert rootNote 61 and note 60 the right return would be 0,
if i insert rootNote 61 and note 61 the right return would be 1,
if i insert rootNote 61 and note 62 the right return would be 3,
if i insert rootNote 61 and note 63 the right return would be 5,
ok i have this other one and it seems to work
i want to map my sequence out put in major scale
but is there some kind of formula what can i use?
.
public int getINMajorScale(int note, int rootNote)
{
List<int> majorScale = new List<int>();
//int bNote = (int)_bNote.CurrentValue;
int bNoteMpl = bNote / 12;
bNote = 12 + (bNote - (12 * bNoteMpl)) - 7;
majorScale.Add(bNote + (12 * bNoteMpl));
int tBnote = bNote;
int res = 0;
for (int i = bNote; i < bNote + 6; i++)
{
//algorytm
res = tBnote + 7;
int mod = 0;
if (res >= 12)
{
mod = res / 12;
res = res - 12 * mod;
}
tBnote = res;
majorScale.Add(res + (bNoteMpl * 12));
}
majorScale.Sort();
int modNuller = 0;
if (nmr >= 7)
{
modNuller = nmr / 7;
nmr = nmr - 7 * modNuller;
}
return (majorScale[nmr] + (modNuller *12));
}
but it's obviously faulty.
Problems with the code as it stands:
modScaling does nothing more than rootNote % 12 as you always pass in 0 and 11
You define mNote but never use it
i is never used in the for loop and so each of the 5 iterations prints the same thing.
OK, lets translate your examples into actual notes to make it easier to understand (numbers presumably correspond to MIDI notes):
rootNote = 60 (C), note = 60 (C) - output 0
rootNote = 60 (C), note = 61 (C#) - output 2
rootNote = 60 (C), note = 62 (D) - output 4
rootNote = 60 (C), note = 63 (D#) - output 5
rootNote = 61 (C#), note = 60 (C) - output 0
rootNote = 61 (C#), note = 61 (C#) - output 1
rootNote = 61 (C#), note = 62 (D) - output 3
rootNote = 61 (C#), note = 63 (D#) - output 5
I might be being really dense but I'm afraid I can't see the pattern there.
A Major scale is of course made up of the sequence Tone, Tone, Semi-tone, Tone, Tone, Tone, Semi-tone, but how does that map to your outputs?
Given your input-outputs, I think I know what you are looking for.
determine steps = note - rootNote
determine interval = number of semi-tones between rootNote and the note steps up the scale
determine phase = rootNote - 60
This algorithm provides accurate results:
static int getINMajorScale(int note, int rootNote)
{
if (note < rootNote) return 0;
var scale = new[] { 2, 2, 1, 2, 2, 2, 1 };
var phase = rootNote - 60;
var steps = note - rootNote;
var interval = steps == 0
? 0 : Enumerable.Range(0, steps).Sum(step => scale[step % scale.Length]);
var number = phase + interval;
return number;
}
yielding:
static void Main(string[] args)
{
//rootNote = 60(C), note = 60(C) - output 0
//rootNote = 60(C), note = 61(C#) - output 2
//rootNote = 60(C), note = 62(D) - output 4
//rootNote = 60(C), note = 63(D#) - output 5
//rootNote = 61(C#), note = 60 (C) - output 0
//rootNote = 61(C#), note = 61 (C#) - output 1
//rootNote = 61(C#), note = 62 (D) - output 3
//rootNote = 61(C#), note = 63 (D#) - output 5
Console.WriteLine(getINMajorScale(60, 60)); // 0
Console.WriteLine(getINMajorScale(61, 60)); // 2
Console.WriteLine(getINMajorScale(62, 60)); // 4
Console.WriteLine(getINMajorScale(63, 60)); // 5
Console.WriteLine(getINMajorScale(60, 61)); // 0
Console.WriteLine(getINMajorScale(61, 61)); // 1
Console.WriteLine(getINMajorScale(62, 61)); // 3
Console.WriteLine(getINMajorScale(63, 61)); // 5
Console.ReadKey();
}

Categories