Skip to content

Commit

Permalink
use <random> library for RNG in Dice and include motion controller in…
Browse files Browse the repository at this point in the history
… seed

there are known problems with rand() and srand() (see https://en.cppreference.com/w/cpp/numeric/random/rand) and the <random> library is preferred for this reason. the function used from <random> also avoids a very rare bias that would occur using rand() and modulo, when RAND_MAX is not a multiple of d and the initially generated number falls in the last "short" segment. this commit also updates the seed to derive entropy (via seed_seq) from a mix of the system tick count and the x,y,z components of the pinetime motion controller-- taking inspiration from and with credit to @w4tsn (InfiniTimeOrg#1199)
  • Loading branch information
yusufmte committed Sep 19, 2022
1 parent f0cc97c commit c1b435b
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/displayapp/DisplayApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
currentScreen = std::make_unique<Screens::Steps>(this, motionController, settingsController);
break;
case Apps::Dice:
currentScreen = std::make_unique<Screens::Dice>(this);
currentScreen = std::make_unique<Screens::Dice>(this, motionController);
break;
}
currentApp = app;
Expand Down
9 changes: 6 additions & 3 deletions src/displayapp/screens/Dice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ namespace {
}
}

Dice::Dice(DisplayApp* app) : Screen(app) {
srand(xTaskGetTickCount() % (std::numeric_limits<unsigned int>::max()));
Dice::Dice(DisplayApp* app, Controllers::MotionController& motionController) : Screen(app) {
std::seed_seq sseq{xTaskGetTickCount(), static_cast<uint32_t>(motionController.X()), static_cast<uint32_t>(motionController.Y()), static_cast<uint32_t>(motionController.Z())};
gen.seed(sseq);

nCounter.Create();
lv_obj_align(nCounter.GetObject(), lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 24);
Expand Down Expand Up @@ -66,11 +67,12 @@ Dice::~Dice() {
void Dice::Roll() {
uint8_t resultIndividual;
uint16_t resultTotal = 0;
std::uniform_int_distribution<> distrib(1, dCounter.GetValue());

lv_label_set_text(resultIndividualLabel, "");

for (uint8_t i = 0; i < nCounter.GetValue(); i++) {
resultIndividual = ((rand() % dCounter.GetValue()) + 1);
resultIndividual = distrib(gen);
resultTotal += resultIndividual;
lv_label_ins_text(resultIndividualLabel, LV_LABEL_POS_LAST, std::to_string(resultIndividual).c_str());
if (i < (nCounter.GetValue() - 1)) {
Expand All @@ -87,3 +89,4 @@ void Dice::NextColor() {
lv_obj_set_style_local_text_color(resultTotalLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, resultColors[currentColorIndex]);
lv_obj_set_style_local_text_color(resultIndividualLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, resultColors[currentColorIndex]);
}

6 changes: 5 additions & 1 deletion src/displayapp/screens/Dice.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
#include "displayapp/screens/Screen.h"
#include "displayapp/widgets/Counter.h"
#include "systemtask/SystemTask.h"
#include <components/motion/MotionController.h>
#include <lvgl/lvgl.h>
#include <random>
#include <array>

namespace Pinetime::Applications::Screens {
class Dice : public Screen {
public:
Dice(DisplayApp* app);
Dice(DisplayApp* app, Controllers::MotionController& motionController);
~Dice() override;
void Roll();

Expand All @@ -19,6 +21,8 @@ namespace Pinetime::Applications::Screens {
lv_obj_t* resultTotalLabel;
lv_obj_t* resultIndividualLabel;

std::mt19937 gen;

std::array<lv_color_t, 3> resultColors = {LV_COLOR_YELLOW, LV_COLOR_MAGENTA, LV_COLOR_AQUA};
uint8_t currentColorIndex;
void NextColor();
Expand Down

0 comments on commit c1b435b

Please sign in to comment.