Writing bytes to file - c++

I'm currently working on a DBF file manager and I'm having some problems...
One of the elements that compose the header is the last date that the file was updated.
The problem is: the field format is YYMMDD and it MUST have 3 bytes.
How is it possible to write a date using that format using only 3 bytes? Also, another field represents the type of the file (if it have a memo or not).
The file type in my case is 03h and this field MUST use only 1 byte. I'm pretty confused.

I would hold your data in 3 bytes as
first byte = year
second byte = month
third byte = day
There's plenty of room in each byte for the domain of each field (year, month, day). You could write them in an integer with bit-shifting operations, like this:
int year = 13;
int month = 7;
int day = 26;
int my_date = (year << 16) | (month << 8) | day;
Edit:
What I did in my_date: I basically concatenated the information you need (year, month, day) into a series of bits (8 bits per information field), as an integer. You know an int is 4 bytes. Consider for starters that my_date is 0, that is, all 32 bits are 0. The 4 bytes of it are as follows ("|" denotes concatenation; that's for ease of reading):
my_date = 0 | 0 | 0 | 0
When I write year << 16 I have
year << 16 = 0 | year | 0 | 0
In a similar fashion,
month << 8 = 0 | 0 | month | 0
day = 0 | 0 | 0 | day
When I apply the OR operator on all of them, my_date looks like this:
my_date = 0 | year | month | day
Accessing them:
year = (my_date & 0xFF0000) >> 16;
month = (my_date & 0xFF00) >> 8;
day = my_date & 0xFF;
Edit: how accessing works. We previously had
my_date = 0 | year | month | day
If you do, for example, an AND with 0xFF00, which is 0 | 0 | FF | 0, you get
my_date & 0xFF00 = 0 | 0 | month | 0
Now all you need to do is shift your data back, so
(my_date & 0xFF00) >> 8 = 0 | 0 | 0 | month = month
Hope it's clearer now.

First byte for year: 2000 + YY. Can count from 2000 till 2255
Second byte for month: 1-12
Third byte for day: 1-31

Related

Find ID's not present in a date represented by a yyyyweek_number

I've 2 data sets, one which represts a list of all of the customers and other with their order dates
The order date are in a yyyyweek_number format, so for instance as today (2020-09-29) is week 40, the order date would be represented as 202040
I want to get a list of dealers who haven't placed orders in 4 day ranges viz. 30 days or less
60 days or less
90 days or less and
90+ days
To illustrate lets say the customer dataset is as under:
+----+
| ID |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 11 |
| 12 |
| 13 |
| 14 |
| 15 |
+----+
and the Order table is as under:
+----+-----------------+
| ID | Order_YYYY_WEEK |
+----+-----------------+
| 1 | 202001 |
| 2 | 202003 |
| 3 | 202004 |
| 5 | 202006 |
| 2 | 202008 |
| 3 | 202010 |
| 6 | 202012 |
| 8 | 202009 |
| 1 | 202005 |
| 10 | 202015 |
| 11 | 202018 |
| 13 | 202038 |
| 15 | 202039 |
| 12 | 202040 |
+----+-----------------+
The slicer format that I've looks like this
Now say for instance the 30 days or less button is selected,
the resulting table should represent a table as under, with all the ID's from the Customer table that aren't present in the ORDER table where ORDER_YYYY_WEEK is 30 days from todays week
+----+
| ID |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 11 |
| 14 |
+----+
Steps:
Create relationship between Customer id's in Customer table and Order table (if not already there)
Create a Date table
Convert Weeks to dates in a new calculated column in the Order table
Create relationship between Customer id's in Customer table and Order table
Create relationship between Dates in Date table and Order table
Create calculated column in Date Table with Day ranges ("30 days or less" etc)
Create measure to identify if an order was placed
Add slicer with date range from Date table and table visual with Customer id.
Add measure to table visual on filter pane and set to "No"
Some of these steps have additional detail below.
2. Create a Date table
We can do this is PowerQuery or in DAX. Here's the DAX version:
Calendar =
VAR
Days = CALENDAR ( DATE ( 2020, 1, 1 ), DATE ( 2020, 12, 31 ) )
RETURN
ADDCOLUMNS (
Days,
"Year Week", YEAR ( [Date] ) & WEEKNUM([Date])
)
Now mark this table as a date table in the "Table Tools" ribbon with the button "Mark as date table"
3. Convert Weeks to dates
For this to work, I have had to create a calculated column in the Order table with the first day of the year first. This can probably be improved upon.
StartYear = DATE(Left(Orders[Year week], 4), 01, 01)
Next the calculated column that we need in the Order table, that identifies the first day of the week. The Variable "DayNoInYear" takes the week number times 7 and substracting 7 to arrive at the first day of the week, returning the nth day of the year. This is then converted to a date with the variable "DateWeek":
Date =
VAR DayNoInYear = RIGHT(Orders[Year week], 2) * 7 - 7
VAR DateWeek = DATEADD(Orders[StartYear].[Date], DayNoInYear, DAY)
RETURN
DateWeek
6. Create calculated column in Date Table with Day ranges
Day ranges =
VAR Today = TODAY()
VAR CheckDate = 'Calendar'[Date] RETURN
SWITCH(TRUE(),
CheckDate - Today <= -90, "90+ days",
CheckDate - Today <= -60 && CheckDate - Today > -90 , "90 days or less",
CheckDate - Today <= -30 && CheckDate - Today > -60 , "60 days or less",
CheckDate - Today <= 0 && CheckDate - Today > -30 , "30 days or less",
"In the future"
)
7. Create measure to identify if an order was placed
Yes - No order =
VAR Yes_No =
IF(
ISBLANK(FIRSTNONBLANK(Orders[Customer id], Orders[Customer id])),
"No",
"Yes"
)
VAR ThirtyDays = SELECTEDVALUE('Calendar'[Day ranges]) = "30 days or less"
VAR SixtyDays = SELECTEDVALUE('Calendar'[Day ranges]) = "30 days or less" || SELECTEDVALUE('Calendar'[Day ranges]) = "60 days or less"
VAR NinetyDays = SELECTEDVALUE('Calendar'[Day ranges]) = "30 days or less" || SELECTEDVALUE('Calendar'[Day ranges]) = "60 days or less" || SELECTEDVALUE('Calendar'[Day ranges]) = "90 days or less"
RETURN
SWITCH(TRUE(),
AND(ThirtyDays = TRUE(), Yes_No = "No"), "No",
AND(SixtyDays = TRUE(), Yes_No = "No"), "No",
AND(NinetyDays = TRUE(), Yes_No = "No"), "No",
Yes_No = "No",
"Yes"
)
Steps 8 and 9
Create slicer with the newly created "Day range" column in the Date table and create a table visual with the "Yes - No order" measure as visual-level filter set at "No" as in screenshot attached below

Get count and list of cutomers (ID) that have no sales in the last 2 months

So, I've 2 tables as under
SALES table:
+----+------------+
| ID | SALE_DATE |
+----+------------+
| 1 | 09-21-2021 |
| 2 | 09-21-2021 |
| 3 | 09-21-2021 |
| 2 | 09-21-2021 |
| 3 | 09-21-2021 |
| 1 | 09-21-2021 |
| 5 | 07-22-2021 |
| 6 | 09-21-2021 |
| 9 | 09-21-2021 |
| 7 | 08-21-2021 |
| 8 | 05-21-2021 |
+----+------------+
CUSTOMER Table
+----+
| ID |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
+----+
I want to create 2 measures:
1st would be the count of customers that have no sales in the last 2 months, so in this case it would be 2 (8 and 10)
and second measure would give the list of all those customer ID's (8 and 10)
Right now I use this measure to get the list of all ID's that have no sales in last 2 months
show_hide =
VAR current_name = MIN(SALES[ID])
VAR chk_not_in =
IF(
COUNTROWS(
FILTER(
ALL(SALES),
SALES[ID]= current_name && SALES[SALE_DATE])> DATE(YEAR(NOW()),MONTH(NOW())-2, DAY(NOW()))
)
)= 0,
0,
1
)
VAR chk_in =
IF(
COUNTROWS(
FILTER(
ALL(CUSTOMER),
CUSTOMER[ID] = current_name
)
) = 0,
0,
1
)
RETURN IF(chk_in = 1 && chk_not_in = 1, 1, 0)
So every ID with a show_hide of "0" would be the ones that dont have any sales in the last 2 months
I was wondering if there's an easy way to do it and also, I'm not sure how to get the count of all those ID's
First off - I assume your test data was meant to be 2020 instead of 2021 and the ID in the SALES table is a CUSTOMER ID.
I would address this as a measure and a calculated column.
The measure would calculate the customers that have not sold in the past two months. From your data I think you are missing (4) who has not sold anything - bringing the total customers to three (4, 8, 10).
CustomersWithNoSalesIn2Months =
// Work out what date was 2 months ago
VAR twoMonthsAgo = DATE(YEAR(NOW()),MONTH(NOW())-2, DAY(NOW()))
// Count the total distinct customers in the customer table
VAR totalCustomers = CALCULATE(DISTINCTCOUNT(Customer[ID]))
// Count how many distinct customers did have sales in the past 2 months
VAR customersWithSalesInTheLast2Months = CALCULATE(DISTINCTCOUNT(Sales[ID]), Sales[SALE_DATE] > twoMonthsAgo)
// Subtract the customers who did have sales from the total to get the number of customers that did not have sales
RETURN totalCustomers - customersWithSalesInTheLast2Months
The calculated column would be places on the CUSTOMER table and would count how many sales customers had made in the last 2 months.
SalesMadeInTheLast2Months =
VAR MostRecentSale = CALCULATE(MAX(Sales[SALE_DATE]), FILTER(Sales, Customer[ID] = Sales[ID]))
VAR TwoMonthsAgo = DATE(YEAR(NOW()),MONTH(NOW())-2, DAY(NOW()))
RETURN CALCULATE(COUNTROWS(Sales), FILTER(Sales, Sales[SALE_DATE] > TwoMonthsAgo), FILTER(Sales, Sales[ID] = Customer[ID]))
Now you can filter on the Customers table for BLANK sales or use the counts in any other calculation you need. For example, customers 1,2 & 3 have made the most sales in the past 2 months.

DAX Cumulative Sum, reset by x period

I have a function for a cumulative sum as follows:
Actions closed cumulative =
IF(MAX(Dates[Date])<CALCULATE(MIN(Dates[Date]),
FILTER(all(Dates),Dates[PeriodFiscalYear]=[CurrentPeriod1])),
CALCULATE(Actions[Actions closed on time],
FILTER(ALL(Dates),
Dates[Date]<=max(Dates[Date])
)
))
Where CurrentPeriod1 is the period we're in, which returns something like this:
PeriodFiscalYear | Actions | Actions Closed Cumulative
P01-2018/19 | 4 | 608
P02-2018/19 | 19 | 627
P03-2018/19 | 17 | 644
P04-2018/19 | 6 | 650
P05-2018/19 | 7 | 657
So it's basically counting all the actions closed in the table at the moment but I'd like to reset on a certain number of periods, for example 3 periods would be:
PeriodFiscalYear | Actions | Actions Closed Cumulative
P12-2017/18 | 10 |
P13-2017/18 | 10 |
P01-2018/19 | 4 | 24
P02-2018/19 | 19 | 33
P03-2018/19 | 17 | 40
P04-2018/19 | 6 | 42
P05-2018/19 | 7 | 30
I'm struggling to understand how to do it, despite quite a lot of reading. I have a calendar table with dates by 13 periods per year and also pretty much every measure you could think of, month, monthyear, monthperiod etc etc. Any help would be appreciated. Ultimate goal is a moving average over a set number of periods.
Thanks
Assuming your Actions table uses date values and the periods are stored in the Dates table, I suggest first creating an index column for the periods to that they are much easier to work with:
PeriodIndex = 100 * VALUE(MID(Dates[PeriodFiscalYear], 5, 4)) +
VALUE(MID(Dates[PeriodFiscalYear], 2, 2))
These index values should be integers that look like 201804 instead of P04-2018/19, for example.
Now that you have the index column to work with, you can write a rolling cumulative sum like this:
Trailing3Periods =
VAR CurrentPeriod = MAX(Dates[PeriodIndex])
RETURN CALCULATE(SUM(Actions[Actions closed on time]),
FILTER(ALL(Dates),
Dates[PeriodIndex] <= CurrentPeriod &&
Dates[PeriodIndex] > CurrentPeriod - 3))

Row-wise count/sum of values in Stata

I have a dataset where each person (row) has values 0, 1 or . in a number of variables (columns).
I would like to create two variables. One that includes the count of all the 0 and one that has the count of all the 1 for each person (row).
In my case, there is no pattern in the variable names. For this reason I create a varlist of all the existing variables excluding the ones that need not to be counted.
+--------+--------+------+------+------+------+------+----------+--------+
| ID | region | Qa | Qb | C3 | C4 | Wa | count 0 | count 1|
+--------+--------+------+------+------+------+------+----------+--------+
| 1 | A | 1 | 1 | 1 | 1 | . | 0 | 4 |
| 2 | B | 0 | 0 | 0 | 1 | 1 | 3 | 2 |
| 3 | C | 0 | 0 | . | 0 | 0 | 4 | 0 |
| 4 | D | 1 | 1 | 1 | 1 | 0 | 0 | 4 |
+--------+--------+------+------+------+------+------+----------+--------+
The following works, however, I cannot add an if statement
ds ID region, not // all variables in the dataset apart from ID region
return list
local varlist = r(varlist)
egen count_of_1s = rowtotal(`varlist')
If I change the last line with the one below, I get an error of invalid syntax.
egen count_of_1s = rowtotal(`varlist') if `v' == 1
I turned from count to summing because I thought this is a sneaky way out of the problem. I could change the values from 0,1 to 1, 2, then sum all the two values separately in two different variables and then divide accordingly in order to get the actual count of 1 or 2 per row.
I found this Stata: Using egen, anycount() when values vary for each observation however Stata freezes as my dataset is quite large (100.000 rows and 3000 columns).
Any help will be very appreciated :-)
Solution based on the response of William
* number of total valid responses (0s and 1s, excluding . )
ds ID region, not // all variables in the dataset apart from ID region
return list
local varlist = r(varlist)
egen count_of_nonmiss = rownonmiss(`varlist') // this counts all the 0s and 1s (namely, the non missing values)
* total numbers of 1s per row
ds ID region count_of_nonmiss, not // CAUTION: count_of_nonmiss needs not to be taken into account for this!
return list
local varlist = r(varlist)
generate count_of_1s = rowtotal(`varlist')
How about
egen count_of_nonmiss = rownonmiss(`varlist')
generate count_of_0s = count_of_nonmiss - count_of_1s
When the value of the macro varlist is substituted into your if clause, the command expands to
egen count_of_1s = rowtotal(`varlist') if Qa Qb C3 C4 Wa == 1
Clearly a syntax error.
I had the same problem to count the occurrences of specifies values in each observation across a set of variables.
I could resolve that problem in the following ways: If you want to count the occurrences of 0 in the values across x1-x2, so
clear
input id x1 x2 x3
id x1 x2 x3
1. 1 1 0 2
2. 2 2 0 2
3. 3 2 0 3
4. end
egen count2 = anycount(x1-x3), value(0)

TINYINT data type to store signed numbers in mysql

I have a table MACRecord in MYSQL. I have 3 fields declared as TINYINT(4) (RSSI1, RSSI2, RSSI3) with a default value of 0. I use it to store signed negative values i-e -90, -84 etc. I am trying to understand how much length each number is taking in the column. I have a c++ code to output length of each column in bytes as follows:
lengths = mysql_fetch_lengths(result);
num_rows = mysql_num_rows(result);
for(i = 3; i < num_fields; i++)
{
if (strstr(fields[i].name, "RSSI") != NULL)
{
printf("Column %u is %lu bytes in length.\n",
i, lengths[i]);
}
So now for example if columns 3, 4 and 5 which are my RSSI's columns contain values such as -90, 0(default), -83, i get the output as follows:
Column 3 is 3 bytes in length
Column 4 is 1 bytes in length.
Column 5 is 3 bytes in length
I don't understand why having a value of for example -90 in my RSSI's columns which were declared as TINYINT(4) which can only store 1 byte values is displaying as having 3 bytes of data? The default value of 0 makes sense. If I describe my table I can see that the data type is TINYINT but still it says values 3 bytes in length.
| Field | Type | Null | Key | Default | Extra |
| RSSI1 | tinyint(4) | YES | | 0 | |
| RSSI2 | tinyint(4) | YES | | 0 | |
| RSSI3 | tinyint(4) | YES | | 0 | |
I am a bit confused. Any help will be appreciated.
don't understand why having a value of for example -90 in my RSSI's columns which were declared as TINYINT(4) which can only store 1 byte values
in binary ...
is displaying as having 3 bytes of data?
in decimal.
"-90" is three bytes in decimal, and -90 is one byte of binary.