Multiple ranges for QDoubleSpinBoxes in QT - c++

I am building an application that makes use of multiple frequency ranges. I need the user to be able to increase/decrease the values in the QDoubleSpinBox, as well as type in the value. If I increase the value to a number out of one range, I would like the value to jump to the next range (same principle for decreasing a value).
Does a QDoubleSpinBox provide this kind of behavior? I can't seem to find an answer for what I'm looking for. I've tried setting a range using QDoubleValidator, but I don't think it supports multiple ranges (unless I'm missing something). I've also tried using range checks with if statements with the valueChanged() signal that gets emitted, but there must be a simpler way, right?
Here's an example of how I'd like the doubleSpinBox to behave:
Starting Value: 9.75
Range 1: 9.75 - 9.95
Range 2: 10.15 - 10.40
Range 3: 17.2 - 20.4
If value goes above 9.95, jump to 10.15.
If value goes above 10.40, jump to 17.2, etc.
I would also like to have the same behavior when decreasing the value (jumping back down to Range 1 if value drops below 10.15).
I would like to do this without writing multiple if/else if statements if I can avoid it.

Trying to create multiple ranges is not a good solution. You should consider your problem in a different way: you have a single range from 9.75 to 20.40 with forbidden values.
So, if you override method such as QDoubleSpinBox::stepsBy() and QDoubleSpinBox::valueFromText(), you will be able to discard the values outside your ranges:
class Spinbox: public QDoubleSpinBox
{
public:
Spinbox(): QDoubleSpinBox()
{
setRange(9.75, 20.4);
setSingleStep(0.1);
}
virtual void stepBy(int steps) override
{
double const newValue = checkValue(value() + (steps * singleStep()));
setValue(newValue);
}
virtual double valueFromText(QString const& text) const override
{
qDebug() << text;
double const newValue = QDoubleSpinBox::valueFromText(text);
return checkValue(newValue);
}
double checkValue(double newValue) const
{
qDebug() << newValue << value();
if (9.95 < newValue && newValue < 10.15)
{
if (newValue > value())
return 10.15;
else
return 9.95;
}
else if (10.4 < newValue && newValue < 17.2)
{
if (newValue > value())
return 17.2;
else
return 10.4;
}
return newValue;
}
};

Related

How do I implement linear probing in C++?

I'm new to Hash Maps and I have an assignment due tomorrow. I implemented everything and it all worked out fine, except for when I get a collision. I cant quite understand the idea of linear probing, I did try to implement it based on what I understood, but the program stopped working for table size < 157, for some reason.
void hashEntry(string key, string value, entry HashTable[], int p)
{
key_de = key;
val_en = value;
for (int i = 0; i < sizeof(HashTable); i++)
{
HashTable[Hash(key, p) + i].key_de = value;
}
}
I thought that by adding a number each time to the hash function, 2 buckets would never get the same Hash index. But that didn't work.
A hash table with linear probing requires you
Initiate a linear search starting at the hashed-to location for an empty slot in which to store your key+value.
If the slot encountered is empty, store your key+value; you're done.
Otherwise, if they keys match, replace the value; you're done.
Otherwise, move to the next slot, hunting for any empty or key-matching slot, at which point (2) or (3) transpires.
To prevent overrun, the loop doing all of this wraps modulo the table size.
If you run all the way back to the original hashed-to location and still have no empty slot or matching-key overwrite, your table is completely populated (100% load) and you cannot insert more key+value pairs.
That's it. In practice it looks something like this:
bool hashEntry(string key, string value, entry HashTable[], int p)
{
bool inserted = false;
int hval = Hash(key, p);
for (int i = 0; !inserted && i < p; i++)
{
if (HashTable[(hval + i) % p].key_de.empty())
{
HashTable[(hval + i) % p].key_de = key;
}
if (HashTable[(hval + i) % p].key_de == key)
{
HashTable[(hval + i) % p].val_en = value;
inserted = true;
}
}
return inserted;
}
Note that expanding the table in a linear-probing hash algorithm is tedious. I suspect that will be forthcoming in your studies. Eventually you need to track how many slots are taken so when the table exceeds a specified load factor (say, 80%), you expand the table, rehashing all entries on the new p size, which will change where they all end up residing.
Anyway, hope it makes sense.

How to generate a boolean condition during runtime in C++?

I want to be able to generate a boolean condition during the runtime based on the states of some variables. My task looks simple at first. I have a large if () else if () statement what needs to determine if the number is in a certain range. It then does something depending on whether that number is inside that range.
Here's pseudocode to demonstrate what I want:
void fun(int num, int offset = 0) {
if (0...60) {
// do something
} else if (60...180) {
// do something else
} else if (180...240) {
} else if (240...360) {
}
}
The first if statement should work like this:
if (0 >= num && num <= 20) {
// do something
}
The caveat here is that in addition to int num, there is another parameter passed in, which I call the offset. The structure of the code here, including the do something inside the { } is the same. The only things that need to change are are ranges, based on the value of the offset. By the way, this is not a default parameter here, it is just pseudocode demonstrating what the value of int offset was passed in.
void fun(int num, int offset = 120) {
if (120...180) {
// do something
} else if (180...300) {
// do something else
} else if (300...360) {
} else if (360...120) {
}
}
That last else if () statement has been giving me some trouble.
} else if (360...120) {
}
What I'm actually trying to write here is:
} else if (num >= 360 || num <= 120) {
}
The reason for this is that my int num may have a value > 360. However, in that case for the purpose of my application it has to "wrap around" and be treated as a value 0...120.
This is for a mathematical application here. Whenever you have int num > 360, you go around the full circle and you end back at 0 where you started. So that is the effect which I want to achieve.
I don't want to write extra functions. I want my code to be generic because many different values for int num and int offset may be passed into my function. I want to generate the necessary conditions during the runtime based on the value of int offset.
The main problem here is that in the first situations, when int offset = 0 my condition is
} else if (240 >= num && num <= 360) {
}
However, for a different offset we wrap around and so I have to change the format of the entire condition! For example, when int offset = 120, as shown above:
} else if (num >= 360 || num <= 120) {
}
The problem is that in the first situation I had the && in the last else if (), but now I have the || to convey the same meaning. What I'm looking for is a way to be able to manipulate the operators inside the conditional statements as mere chars in a string, then "paste" the completed condition into the if () statements during the runtime!
What's even worse is that this "wrapping around" can occur inside any one of the if () statements, not just the last one. It is based on the value of the offset.
I can't use preprocessor tricks, because I want this to work during the runtime. Maybe it is possible to use function pointers or something for this, but I don't know how to do that. Please note that the ... above is not real C++ code, it is pseudocode! I'm aware that there is a "range-based" switch statement in C++, but I can't use that because of the "wrapping around" property mentioned above.

Crash in std::sort - sorting without strict weak ordering

I'm trying to sort a vector of items. As mentioned in the code comments, the ordering should be:
Participants with more action points (mAp) go first. When there is a tie, participants with the same disposition (mDisposition) as the initiator of the battle (mBattleInitiator) go first.
The following code (simplified example) crashes on macOS, presumably due to my sort implementation being incorrect:
#include <QtCore>
class AiComponent
{
public:
enum Disposition {
Friendly,
Hostile
};
AiComponent(Disposition disposition) : mDisposition(disposition) {}
~AiComponent() { qDebug() << "Destroying AiComponent"; }
Disposition mDisposition;
};
class BattleManager
{
public:
BattleManager() : mBattleInitiator(AiComponent::Hostile) {}
class Turn {
public:
Turn() : mAp(1) {}
Turn(QSharedPointer<AiComponent> aiComponent) :
mAiComponent(aiComponent),
mAp(1)
{
}
Turn(const Turn &rhs) :
mAiComponent(rhs.mAiComponent),
mAp(1)
{
}
QSharedPointer<AiComponent> mAiComponent;
int mAp;
};
void addToTurnQueue(QSet<QSharedPointer<AiComponent>> aiComponents);
AiComponent::Disposition mBattleInitiator;
QVector<Turn> mTurnQueue;
Turn mActive;
};
void BattleManager::addToTurnQueue(QSet<QSharedPointer<AiComponent> > aiComponents)
{
foreach (auto aiComponent, aiComponents) {
mTurnQueue.append(Turn(aiComponent));
}
// Sort the participants so that ones with more action points (mAp) go first.
// When there is a tie, participants with the same disposition (mDisposition)
// as the initiator of the battle (mBattleInitiator) go first.
std::sort(mTurnQueue.begin(), mTurnQueue.end(), [=](const Turn &a, const Turn &b) {
if (a.mAp > b.mAp)
return true;
if (a.mAp < b.mAp)
return false;
// At this point, a.mAp is equal to b.mAp, so we must resolve the tie
// based on mDisposition.
if (a.mAiComponent->mDisposition == mBattleInitiator)
return true;
if (b.mAiComponent->mDisposition == mBattleInitiator)
return false;
return false;
});
}
int main(int /*argc*/, char */*argv*/[])
{
BattleManager battleManager;
for (int i = 0; i < 20; ++i) {
qDebug() << "iteration" << i;
QSet<QSharedPointer<AiComponent>> participants;
AiComponent::Disposition disposition = i % 2 == 0 ? AiComponent::Hostile : AiComponent::Friendly;
QSharedPointer<AiComponent> ai(new AiComponent(disposition));
participants.insert(ai);
battleManager.addToTurnQueue(participants);
}
// This should print (1 1), (1 1), ... (1 0), (1 0)
foreach (auto turn, battleManager.mTurnQueue) {
qDebug() << "(" << turn.mAp << turn.mAiComponent->mDisposition << ")";
}
return 0;
}
I've looked into other answers on the topic. Most of them just say "implement it as a > b", which won't work in my case. There are a few that seem relevant but don't help me:
https://stackoverflow.com/a/16824720/904422 - says that other standard algorithms will work but doesn't mention any concrete examples
https://stackoverflow.com/a/33508373/904422 - confusing, seems like overkill
What is the simplest way to achieve what I'm after?
The reason for the crash hasn't been explained yet. Most implementations of std::sort are based on quick sort, specifically Hoare partition scheme, which scans an array from left towards the right as long as element values < pivot values, and scans the array from right towards the left as long as element values > pivot values. These scans are counting on the fact that finding an element value = pivot value will stop a scan, so there's no check for scanning beyond the boundaries of an array. If the user supplied less than compare function returns true in the case of equal elements, then either of the scans may go beyond the array boundaries and cause a crash.
In the case of a debug build, testing of the user compare function may be done to ensure that the compare is less than and not less than or equal, but for a release build, the goal is speed, so these checks are not performed.
I'll just go off of the comment in your code and explain what's wrong with it (if anything), and how you would fix it.
// Sort the participants so that ones with more action points (mAp) go first.
Good so far
// When there is a tie, participants with the same disposition (mDisposition) as the initiator of the battle (mBattleInitiator) go first.
What if both participants have the same disposition as the initiator? Even if you can guarantee that no 2 elements will satisfy this condition, the sort algorithm is allowed to compare an element against itself. This test would return true in that case, violating one of the conditions of a strict-weak ordering, which is that an element must compare equal to itself (i.e. compare(a,a) must always be false).
Perhaps instead you want to say that if a has the same disposition as the initiator, and b does not, then a should be considered less than b. This can be encoded as:
return dispositionOfA == mBattleInitiator && dispsitionOfB != mBattleInitiator;
So your full test would look like this:
if (a.mAp > b.mAp)
return true;
if (a.mAp < b.mAp)
return false;
return a.mAiComponent->mDisposition == mBattleInitiator &&
b.mAiComponent->mDisposition != mBattleInitiator;

Sitrecore MinValue

I need to sort very large number of item in Sitecore.
So I used negative number, something like this:
item.sortOrder = int.MinValue + someId
minValue = -2147483647
but sitecore sort correctly only for value greater then -2143053648 so there is a difference of 4430001
so now my code is
item.sortOrder = int.MinValue + 4430001 + someId
and it sorts correctly
does anyone ever experienced something like this, am I doing something wrong?
I'm not sure what exactly you are trying to achieve but it would be better to define a public constant for Sitecore SortOrder Minimum value somewhere accessible.
public const int SortOrderMinimumValue = -2143053648;
And then reference like this
item.Fields["__Sortorder"].Value = SortOrderMinimumValue + someId;
That way the minimum value can be accessed any other code and can be altered at one location should you want to change the minimum value for your sorting.
To sort Items by sort order you then will need to do the following
public class ItemComparer : IComparer
{
public int CompareSortOrder(Item item1, Item item2)
{
int sortOrder1;
bool parsed1 = int.TryParse(item1["__Sortorder"], out sortOrder1);
int sortOrder2;
bool parsed2 = int.TryParse(item2["__Sortorder"], out sortOrder2);
if (!parsed1 || !parsed2)
throw new Exception("Sort order value is incorrect type");
if (sortOrder1 < sortOrder2)
return -1;
if (sortOrder1 > sortOrder2)
return 1;
else
return 0;
}
}
And then reference the code when sorting;
var itemComparer = new ItemComparer();
items.Sort(itemComparer.CompareSortOrder);

Efficient way to retrieve count of number of times a flag set since last n seconds

I need to track how many times a flag is enabled in last n seconds. Below is the example code I can come up with.StateHandler maintains the value of the flag in active array for last n(360 here) seconds. In my case update function is called from outside every second. So when I need to know how many times it set since last 360 seconds I call getEnabledInLast360Seconds. Is it possible to do it more efficiently like not using an array size of n for booleans ?
#include <map>
#include <iostream>
class StateHandler
{
bool active[360];
int index;
public:
StateHandler() :
index(0),
active()
{
}
void update(bool value)
{
if (index >= 360)
{
index = 0;
}
active[index % 360] = value;
index++;
}
int getEnabledInLast360Seconds()
{
int value = 0;
for (int i = 0; i < 360; i++)
{
if (active[i])
{
value++;
}
}
return value;
}
};
int main()
{
StateHandler handler;
handler.update(true);
handler.update(true);
handler.update(true);
std::cout << handler.getEnabledInLast360Seconds();
}
Yes. Use the fact that numberOfOccurrences(0,360) and numberOfOccurrences(1,361) have 359 common terms. So remember the sum, calculate the common term, and calculate the new sum.
void update(bool value)
{
if (index >= 360)
{
index = 0;
}
// invariant: count reflects t-360...t-1
if (active[index]) count--;
// invariant: count reflects t-359...t-1
active[index] = value;
if (value) count++;
// invariant: count reflects t-359...t
index++;
}
(Note that the if block resetting index removes the need for the modulo operator % so I removed that)
Another approach would be to use subset sums:
subsum[0] = count(0...19)
subsum[1] = count(20...39)
subsum[17] = count(340...359)
Now you only have to add 18 numbers each time, and you can entirely replace a subsum every 20 seconds.
Instead of fixing the buffer, you can simply use std::set<timestamp> (Or perhaps std::queue). Every time you check, pop off the elements older than 360s and count the remaining ones.
If you check scarcely but update often, you might want to add the "popping" to the update itself, to prevent the set from growing too big.