From f72c5b781f88b65570dccb6434ff172e98f7dfee Mon Sep 17 00:00:00 2001 From: greek Date: Fri, 7 Jun 2024 18:03:22 +0100 Subject: [PATCH 01/10] Payout button stub. --- PlayerAreaModel.cpp | 7 ++++++- PlayerAreaModel.h | 1 + Root.qml | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/PlayerAreaModel.cpp b/PlayerAreaModel.cpp index ab6a2cd..2869511 100644 --- a/PlayerAreaModel.cpp +++ b/PlayerAreaModel.cpp @@ -76,7 +76,12 @@ void PlayerAreaModel::removeBet(BetType b, int n) } } -void PlayerAreaModel::cancelBet(BetType b, int n) { +void PlayerAreaModel::cancelBet(BetType b, int n) +{ emit betCanceled(b, n); } +void PlayerAreaModel::payout() +{ + printf("payout\n"); +} diff --git a/PlayerAreaModel.h b/PlayerAreaModel.h index 8e1112e..5dff5d2 100644 --- a/PlayerAreaModel.h +++ b/PlayerAreaModel.h @@ -49,6 +49,7 @@ public slots: void removeBet(BetType b, int n); QString getPlayerName(int n); void cancelBet(BetType b, int n); + void payout(); private: diff --git a/Root.qml b/Root.qml index 655ba4a..66ca9ad 100644 --- a/Root.qml +++ b/Root.qml @@ -32,5 +32,34 @@ Window { right: parent.right } } + + Button { + text: "Payout" + font.pointSize: 15 + highlighted: false + onClicked: PlayerAreaModel.payout() + + anchors { + left: roulette.left + bottom: parent.bottom + bottomMargin: 20 + } + + background: Rectangle { + implicitWidth: 150 + implicitHeight: 60 + opacity: { + if (parent.pressed) { + 1 + } else if (parent.hovered) { + 0.2 + } else { + 0.3 + } + } + color: "#CCCCCC" + border.width: 0 + } + } } } From ffcc5f892c7198812290db8aa0d932aad34cf54a Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 00:41:25 +0100 Subject: [PATCH 02/10] Calculate payouts. --- PlayerAreaModel.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++++- PlayerAreaModel.h | 6 +++ PlayerAreaView.qml | 2 +- 3 files changed, 96 insertions(+), 3 deletions(-) diff --git a/PlayerAreaModel.cpp b/PlayerAreaModel.cpp index 2869511..d77e10b 100644 --- a/PlayerAreaModel.cpp +++ b/PlayerAreaModel.cpp @@ -32,7 +32,7 @@ QString PlayerAreaModel::getPlayerName(int n) void PlayerAreaModel::setPlayerName(QString s, int n) { - this->players[n].playerName = s; + players[n].playerName = s; } void PlayerAreaModel::bet(BetType b, int n, int bet) @@ -83,5 +83,92 @@ void PlayerAreaModel::cancelBet(BetType b, int n) void PlayerAreaModel::payout() { - printf("payout\n"); + if (players.at(0).bet1.betType == NONE) { + printf("Select where the ball landed\n"); + } else { + int rollSpot = 36 - players.at(0).bet1.betSpot; + + for (int i = 1; i < 8; i++) { + int betType = players.at(i).bet1.betType; + int betSpot; + if (betType == SINGLE) { + betSpot = 36 - players.at(i).bet1.betSpot; + } else { + betSpot = players.at(i).bet1.betSpot + 1; + } + players[i].payout = 0; + printf("%d %d\n", betSpot, rollSpot); + + if (betType == SINGLE && betSpot == rollSpot) { + players[i].payout += players.at(i).bet1.betValue * 21; + } else if (betType == RED && ((1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == BLACK && !((1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == ODD && (rollSpot % 2)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == EVEN && !(rollSpot % 2)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == LOW && rollSpot <= 18 ) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == DOZEN) { + if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet1.betValue * 3; + } + } else if (betType == STREET) { + if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet1.betValue * 6; + } + } else if (betType == COLUMN) { + if (betSpot == 1 && ((1 << (rollSpot - 1)) & column1)) { + players[i].payout += players.at(i).bet1.betValue * 3; + } else if (betSpot == 2 && ((1 << (rollSpot - 1)) & column2)) { + players[i].payout += players.at(i).bet1.betValue * 3; + } else if (betSpot == 3 && ((1 << (rollSpot - 1)) & column3)) { + players[i].payout += players.at(i).bet1.betValue * 3; + } + } + + betType = players.at(i).bet2.betType; + if (betType == SINGLE) { + betSpot = 36 - players.at(i).bet1.betSpot; + } else { + betSpot = players.at(i).bet1.betSpot + 1; + } + if (betType == SINGLE && betSpot == rollSpot) { + players[i].payout += players.at(i).bet2.betValue * 21; + } else if (betType == RED && ((1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == BLACK && !((1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == ODD && (rollSpot % 2)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == EVEN && !(rollSpot % 2)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == LOW && rollSpot <= 18 ) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == DOZEN) { + if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet2.betValue * 3; + } + } else if (betType == STREET) { + if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet2.betValue * 6; + } + } else if (betType == COLUMN) { + if (betSpot == 1 && ((1 << (rollSpot - 1)) & column1)) { + players[i].payout += players.at(i).bet2.betValue * 3; + } else if (betSpot == 2 && ((1 << (rollSpot - 1)) & column2)) { + players[i].payout += players.at(i).bet2.betValue * 3; + } else if (betSpot == 3 && ((1 << (rollSpot - 1)) & column3)) { + players[i].payout += players.at(i).bet2.betValue * 3; + } + } + printf("Player %s got %d gil\n", players.at(i).playerName.toLocal8Bit().data(), players.at(i).payout); + } + } } diff --git a/PlayerAreaModel.h b/PlayerAreaModel.h index 5dff5d2..c32e87f 100644 --- a/PlayerAreaModel.h +++ b/PlayerAreaModel.h @@ -64,9 +64,15 @@ private: QString playerName = ""; Bet bet1; Bet bet2; + int payout; }; QList players; int focusedPlayer_; + + long long redNumbers = 45857548629; + long long column1 = 9817068105; + long long column2 = 19634136210; + long long column3 = 39268272420; }; diff --git a/PlayerAreaView.qml b/PlayerAreaView.qml index 493cba7..876797b 100644 --- a/PlayerAreaView.qml +++ b/PlayerAreaView.qml @@ -129,7 +129,7 @@ Item { topMargin: 6 } - onTextEdited: PlayerAreaModel.setPlayerName(text, index) + onTextEdited: PlayerAreaModel.setPlayerName(text, index + 1) onActiveFocusChanged: { /* focusReason 0, 1 and 2 are mouse, tab forward, and tab backward, respectively */ if (activeFocus && (focusReason == 0 || focusReason == 1 || focusReason == 2)) { From 4b19c904506357fc4b72238e8714470bd8b7b624 Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 10:58:34 +0100 Subject: [PATCH 03/10] Display payout results. Also fixed problem with some numbers not having enough bits. Fixed indexes on single bets being different from what was expected. --- CMakeLists.txt | 2 +- PlayerAreaModel.cpp | 158 +++++++++++++++++++++++--------------------- PlayerAreaModel.h | 10 +-- Root.qml | 4 ++ 4 files changed, 95 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 39d49f0..9e7f209 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,7 +45,7 @@ qt_add_qml_module(roulette-payout RedBlack.qml EvenOdd.qml LowHigh.qml - + Results.qml ) target_link_libraries(roulette-payout PRIVATE diff --git a/PlayerAreaModel.cpp b/PlayerAreaModel.cpp index d77e10b..5d126a3 100644 --- a/PlayerAreaModel.cpp +++ b/PlayerAreaModel.cpp @@ -1,4 +1,5 @@ #include "PlayerAreaModel.h" +#include PlayerAreaModel::PlayerAreaModel(QObject *parent) { @@ -43,7 +44,7 @@ void PlayerAreaModel::bet(BetType b, int n, int bet) player->bet1.betType = b; player->bet1.betValue = bet; player->bet1.betSpot = n; - if (b == 9 && n <= 35) { + if (b == SINGLE && n <= 35) { n = 35 - n; } emit betChanged(b, n, bet); @@ -51,7 +52,7 @@ void PlayerAreaModel::bet(BetType b, int n, int bet) player->bet2.betType = b; player->bet2.betValue = bet; player->bet2.betSpot = n; - if (b == 9 && n <= 35) { + if (b == SINGLE && n <= 35) { n = 35 - n; } emit betChanged(b, n, bet); @@ -61,15 +62,15 @@ void PlayerAreaModel::bet(BetType b, int n, int bet) void PlayerAreaModel::removeBet(BetType b, int n) { Player *player = &players[focusedPlayer_]; - if (player->bet1.betType != NONE) { + if (player->bet1.betType == b) { player->bet1.betType = NONE; - if (b == 9 && n <= 35) { + if (b == SINGLE && n <= 35) { n = 35 - n; } emit betRemoved(b, n); - } else { + } else if (player->bet2.betType == b) { player->bet2.betType = NONE; - if (b == 9 && n <= 35) { + if (b == SINGLE && n <= 35) { n = 35 - n; } emit betRemoved(b, n); @@ -91,84 +92,93 @@ void PlayerAreaModel::payout() for (int i = 1; i < 8; i++) { int betType = players.at(i).bet1.betType; int betSpot; - if (betType == SINGLE) { - betSpot = 36 - players.at(i).bet1.betSpot; - } else { - betSpot = players.at(i).bet1.betSpot + 1; - } players[i].payout = 0; - printf("%d %d\n", betSpot, rollSpot); - if (betType == SINGLE && betSpot == rollSpot) { - players[i].payout += players.at(i).bet1.betValue * 21; - } else if (betType == RED && ((1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == BLACK && !((1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == ODD && (rollSpot % 2)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == EVEN && !(rollSpot % 2)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == LOW && rollSpot <= 18 ) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == DOZEN) { - if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet1.betValue * 3; + if (betType != NONE) { + betSpot = players.at(i).bet1.betSpot; + if (betType == SINGLE && betSpot <= 35) { + betSpot = 36 - betSpot; + } else { + betSpot += 1; } - } else if (betType == STREET) { - if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet1.betValue * 6; - } - } else if (betType == COLUMN) { - if (betSpot == 1 && ((1 << (rollSpot - 1)) & column1)) { - players[i].payout += players.at(i).bet1.betValue * 3; - } else if (betSpot == 2 && ((1 << (rollSpot - 1)) & column2)) { - players[i].payout += players.at(i).bet1.betValue * 3; - } else if (betSpot == 3 && ((1 << (rollSpot - 1)) & column3)) { - players[i].payout += players.at(i).bet1.betValue * 3; + + if (betType == SINGLE && betSpot == rollSpot) { + players[i].payout += players.at(i).bet1.betValue * 21; + } else if (betType == RED && (((int64_t)1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == BLACK && !(((int64_t)1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == ODD && (rollSpot % 2)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == EVEN && !(rollSpot % 2)) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == LOW && rollSpot <= 18 ) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { + players[i].payout += players.at(i).bet1.betValue * 2; + } else if (betType == DOZEN) { + if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet1.betValue * 3; + } + } else if (betType == STREET) { + if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet1.betValue * 6; + } + } else if (betType == COLUMN) { + if (betSpot == 1 && (((int64_t)1 << (rollSpot - 1)) & column1)) { + players[i].payout += players.at(i).bet1.betValue * 3; + } else if (betSpot == 2 && (((int64_t)1 << (rollSpot - 1)) & column2)) { + players[i].payout += players.at(i).bet1.betValue * 3; + } else if (betSpot == 3 && (((int64_t)1 << (rollSpot - 1)) & column3)) { + players[i].payout += players.at(i).bet1.betValue * 3; + } } } betType = players.at(i).bet2.betType; - if (betType == SINGLE) { - betSpot = 36 - players.at(i).bet1.betSpot; - } else { - betSpot = players.at(i).bet1.betSpot + 1; - } - if (betType == SINGLE && betSpot == rollSpot) { - players[i].payout += players.at(i).bet2.betValue * 21; - } else if (betType == RED && ((1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == BLACK && !((1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == ODD && (rollSpot % 2)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == EVEN && !(rollSpot % 2)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == LOW && rollSpot <= 18 ) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == DOZEN) { - if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet2.betValue * 3; + + if (betType != NONE) { + betSpot = players.at(i).bet2.betSpot; + if (betType == SINGLE && betSpot <= 35) { + printf("SINGLLEEE\n"); + betSpot = 36 - betSpot; + } else { + betSpot += 1; } - } else if (betType == STREET) { - if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet2.betValue * 6; - } - } else if (betType == COLUMN) { - if (betSpot == 1 && ((1 << (rollSpot - 1)) & column1)) { - players[i].payout += players.at(i).bet2.betValue * 3; - } else if (betSpot == 2 && ((1 << (rollSpot - 1)) & column2)) { - players[i].payout += players.at(i).bet2.betValue * 3; - } else if (betSpot == 3 && ((1 << (rollSpot - 1)) & column3)) { - players[i].payout += players.at(i).bet2.betValue * 3; + + if (betType == SINGLE && betSpot == rollSpot) { + players[i].payout += players.at(i).bet2.betValue * 21; + } else if (betType == RED && (((int64_t)1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == BLACK && !(((int64_t)1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == ODD && (rollSpot % 2)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == EVEN && !(rollSpot % 2)) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == LOW && rollSpot <= 18 ) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { + players[i].payout += players.at(i).bet2.betValue * 2; + } else if (betType == DOZEN) { + if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet2.betValue * 3; + } + } else if (betType == STREET) { + if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bet2.betValue * 6; + } + } else if (betType == COLUMN) { + if (betSpot == 1 && (((int64_t)1 << (rollSpot - 1)) & column1)) { + players[i].payout += players.at(i).bet2.betValue * 3; + } else if (betSpot == 2 && (((int64_t)1 << (rollSpot - 1)) & column2)) { + players[i].payout += players.at(i).bet2.betValue * 3; + } else if (betSpot == 3 && (((int64_t)1 << (rollSpot - 1)) & column3)) { + players[i].payout += players.at(i).bet2.betValue * 3; + } } } - printf("Player %s got %d gil\n", players.at(i).playerName.toLocal8Bit().data(), players.at(i).payout); + emit results(players.at(i).playerName, i, players.at(i).payout); } } } diff --git a/PlayerAreaModel.h b/PlayerAreaModel.h index c32e87f..fe981d4 100644 --- a/PlayerAreaModel.h +++ b/PlayerAreaModel.h @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -42,6 +43,7 @@ signals: void betChanged(BetType b, int n, int bet); void betRemoved(BetType b, int n); void betCanceled(BetType b, uint n); + void results(QString name, int n, int payout); public slots: void setPlayerName(QString s, int n); @@ -71,8 +73,8 @@ private: int focusedPlayer_; - long long redNumbers = 45857548629; - long long column1 = 9817068105; - long long column2 = 19634136210; - long long column3 = 39268272420; + int64_t redNumbers = 45857548629; + int64_t column1 = 9817068105; + int64_t column2 = 19634136210; + int64_t column3 = 39268272420; }; diff --git a/Root.qml b/Root.qml index 66ca9ad..e24fcfc 100644 --- a/Root.qml +++ b/Root.qml @@ -34,6 +34,7 @@ Window { } Button { + id: payoutButton text: "Payout" font.pointSize: 15 highlighted: false @@ -61,5 +62,8 @@ Window { border.width: 0 } } + + Results { + } } } From 6e770239c86f38d79f839dc067519c09a341e1b1 Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 12:25:20 +0100 Subject: [PATCH 04/10] Only allow valid inputs as bets. --- BetInputDialog.qml | 2 ++ PlayerAreaModel.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BetInputDialog.qml b/BetInputDialog.qml index e686a1a..e9cff57 100644 --- a/BetInputDialog.qml +++ b/BetInputDialog.qml @@ -17,6 +17,8 @@ Dialog { TextField { id: input focus: true + /* No negative numners or leading 0s, and cap at 99 million */ + validator: RegularExpressionValidator { regularExpression: /[1-9][0-9]{0,7}/ } anchors { left: parent.left diff --git a/PlayerAreaModel.cpp b/PlayerAreaModel.cpp index 5d126a3..6af42dc 100644 --- a/PlayerAreaModel.cpp +++ b/PlayerAreaModel.cpp @@ -140,7 +140,6 @@ void PlayerAreaModel::payout() if (betType != NONE) { betSpot = players.at(i).bet2.betSpot; if (betType == SINGLE && betSpot <= 35) { - printf("SINGLLEEE\n"); betSpot = 36 - betSpot; } else { betSpot += 1; From 256d3740f912ba8dc5684bd307d73b1bc40cb040 Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 12:27:23 +0100 Subject: [PATCH 05/10] Forgot to stage Results.qml file. Also added thousands separators to numebrs where appropriate. --- PlayerAreaView.qml | 8 ++++---- Results.qml | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 Results.qml diff --git a/PlayerAreaView.qml b/PlayerAreaView.qml index 876797b..2edf14d 100644 --- a/PlayerAreaView.qml +++ b/PlayerAreaView.qml @@ -179,17 +179,17 @@ Item { currentBet1.betType = b currentBet1.n = n if (b < 7) { - currentBet1.text = betTypes[b] + ": " + bet + "g" + currentBet1.text = betTypes[b] + ": " + bet.toLocaleString(Qt.locale(), 'f', 0) + "g" } else { - currentBet1.text = betTypes[b] + " " + (n + 1) + ": " + bet + "g" + currentBet1.text = betTypes[b] + " " + (n + 1) + ": " + bet.toLocaleString(Qt.locale(), 'f', 0) + "g" } } else { currentBet2.betType = b currentBet2.n = n if (b < 7) { - currentBet2.text = betTypes[b] + ": " + bet + "g" + currentBet2.text = betTypes[b] + ": " + bet.toLocaleString(Qt.locale(), 'f', 0) + "g" } else { - currentBet2.text = betTypes[b] + " " + (n + 1) + ": " + bet + "g" + currentBet2.text = betTypes[b] + " " + (n + 1) + ": " + bet.toLocaleString(Qt.locale(), 'f', 0) + "g" } } } diff --git a/Results.qml b/Results.qml new file mode 100644 index 0000000..e66f561 --- /dev/null +++ b/Results.qml @@ -0,0 +1,39 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import roulette + +GridLayout { + rowSpacing: 20 + columnSpacing: 50 + flow: GridLayout.TopToBottom + rows: 3 + + anchors { + /* These random IDs com from Results' parent*/ + left: payoutButton.right + leftMargin: 30 + top: roulette.bottom + topMargin: 20 + } + + + Repeater { + model: 7 + + Text { + text: "" + + Connections { + target: PlayerAreaModel + + function onResults(name, n, payout) { + if (index + 1 == n && name != "") { + text = name + ": " + payout.toLocaleString(Qt.locale(), 'f', 0) + "g" + } + } + } + } + } +} From fd7a8fbd8ac18d0e537611bd333197fd9aadb157 Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 12:55:29 +0100 Subject: [PATCH 06/10] Payout button disabled until croupier has been set Fixed potential segfault on startup if focusedPlayer_ is out of bounds. --- PlayerAreaModel.cpp | 3 ++- Root.qml | 54 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/PlayerAreaModel.cpp b/PlayerAreaModel.cpp index 6af42dc..bd96ae7 100644 --- a/PlayerAreaModel.cpp +++ b/PlayerAreaModel.cpp @@ -8,6 +8,7 @@ PlayerAreaModel::PlayerAreaModel(QObject *parent) for(int i = 0; i < 8; i++){ players.append(defaultValues); } + focusedPlayer_ = 1; } uint PlayerAreaModel::focusedPlayer() @@ -85,7 +86,7 @@ void PlayerAreaModel::cancelBet(BetType b, int n) void PlayerAreaModel::payout() { if (players.at(0).bet1.betType == NONE) { - printf("Select where the ball landed\n"); + fprintf(stderr, "Select where the ball landed\n"); } else { int rollSpot = 36 - players.at(0).bet1.betSpot; diff --git a/Root.qml b/Root.qml index e24fcfc..9302ee1 100644 --- a/Root.qml +++ b/Root.qml @@ -35,10 +35,9 @@ Window { Button { id: payoutButton - text: "Payout" - font.pointSize: 15 highlighted: false onClicked: PlayerAreaModel.payout() + enabled: false anchors { left: roulette.left @@ -46,21 +45,62 @@ Window { bottomMargin: 20 } + contentItem: Text { + text: "Payout" + font.pointSize: 15 + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + + color: { + if (enabled == true) { + "#000000" + } else { + "#555555" + } + } + } + background: Rectangle { implicitWidth: 150 implicitHeight: 60 opacity: { - if (parent.pressed) { - 1 - } else if (parent.hovered) { - 0.2 + if (enabled == true) { + if (parent.pressed) { + 0.5 + } else if (parent.hovered) { + 0.2 + } else { + 0.3 + } } else { 0.3 } } - color: "#CCCCCC" + color: { + if (enabled == true) { + "#AAAAAA" + } else { + "#444444" + } + } border.width: 0 } + + Connections { + target: PlayerAreaModel + + function onBetChanged() { + if (PlayerAreaModel.focusedPlayer == 0) { + payoutButton.enabled = true; + } + } + + function onBetRemoved() { + if (PlayerAreaModel.focusedPlayer == 0) { + payoutButton.enabled = false; + } + } + } } Results { From b93630dff50d171d8ea7ca28c7f2325e1bd08042 Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 13:02:32 +0100 Subject: [PATCH 07/10] Only allow croupier to choose single numbers. --- BetButton.qml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/BetButton.qml b/BetButton.qml index 14fbe48..bb6a9a9 100644 --- a/BetButton.qml +++ b/BetButton.qml @@ -22,6 +22,8 @@ Item { color: { if (PlayerAreaModel.focusedPlayer == 0 && rouletteTable.numberOfBets == 1 && border.width != 3) { "#00000000" + } else if (PlayerAreaModel.focusedPlayer == 0 && betType != 9) { + "#00000000" } else if (rouletteTable.numberOfBets < 2 || border.width == 3) { if ((PlayerAreaModel.focusedPlayer == 0 && rouletteTable.numberOfBets < 1) || PlayerAreaModel.focusedPlayer != 0 || border.width == 3) { if (tapHandler.pressed) { @@ -48,7 +50,9 @@ Item { onTapped: { if (PlayerAreaModel.focusedPlayer == 0 && rouletteTable.numberOfBets == 1 && parent.border.width != 3) { - } else if (rouletteTable.numberOfBets < 2 && parent.border.width == 0) { + } else if (PlayerAreaModel.focusedPlayer == 0 && betType != 9) { + + }else if (rouletteTable.numberOfBets < 2 && parent.border.width == 0) { parent.border.width = 3 /* Don't show this dialog for the croupier */ From 982212806f837dba73ca064ae032dfd52ef8fa7f Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 13:04:26 +0100 Subject: [PATCH 08/10] Column bitmaps were swapped; unswapped them. --- PlayerAreaModel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PlayerAreaModel.h b/PlayerAreaModel.h index fe981d4..2df3644 100644 --- a/PlayerAreaModel.h +++ b/PlayerAreaModel.h @@ -74,7 +74,7 @@ private: int focusedPlayer_; int64_t redNumbers = 45857548629; - int64_t column1 = 9817068105; + int64_t column3 = 9817068105; int64_t column2 = 19634136210; - int64_t column3 = 39268272420; + int64_t column1 = 39268272420; }; From 810ca0d9f587f967dfd2148a5cba2279e898f9d0 Mon Sep 17 00:00:00 2001 From: greek Date: Sat, 8 Jun 2024 17:35:27 +0100 Subject: [PATCH 09/10] Do no allow resizing of window. Some small documenting. Removed old street bets files. --- MainWindow.cpp | 2 +- PlayerAreaModel.cpp | 4 ++++ PlayerAreaModel.h | 1 + Root.qml | 6 ++++-- StreetBetsModel.cpp | 6 ------ StreetBetsModel.h | 14 -------------- 6 files changed, 10 insertions(+), 23 deletions(-) delete mode 100644 StreetBetsModel.cpp delete mode 100644 StreetBetsModel.h diff --git a/MainWindow.cpp b/MainWindow.cpp index b78ca81..f1c74aa 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -11,7 +11,7 @@ MainWindow::MainWindow(QWindow *parent) { /* * MainWindow is a QQmlApplicationEngine, so a .show() isn't needed - * it will load a Window or ApplicationWindow that will set its own + * It will load a Window or ApplicationWindow that will set its own * visibility status */ load(QUrl("qrc:///Root.qml")); diff --git a/PlayerAreaModel.cpp b/PlayerAreaModel.cpp index bd96ae7..ca3d02d 100644 --- a/PlayerAreaModel.cpp +++ b/PlayerAreaModel.cpp @@ -45,6 +45,10 @@ void PlayerAreaModel::bet(BetType b, int n, int bet) player->bet1.betType = b; player->bet1.betValue = bet; player->bet1.betSpot = n; + /* + * This is needed because the visual roulette board is inverted from the actual QML grid we use to represent it. + * Here we use 35 because the grid is 0-indexed, but later we use 36 for convinience + */ if (b == SINGLE && n <= 35) { n = 35 - n; } diff --git a/PlayerAreaModel.h b/PlayerAreaModel.h index 2df3644..0a87aee 100644 --- a/PlayerAreaModel.h +++ b/PlayerAreaModel.h @@ -73,6 +73,7 @@ private: int focusedPlayer_; + /* bitmaps */ int64_t redNumbers = 45857548629; int64_t column3 = 9817068105; int64_t column2 = 19634136210; diff --git a/Root.qml b/Root.qml index 9302ee1..1fb17de 100644 --- a/Root.qml +++ b/Root.qml @@ -4,8 +4,10 @@ import QtQuick.Controls import roulette /* this is importing the target "roulette-payout" defined in CMakeLists.txt */ Window { - height: 500 - width: 1000 + maximumHeight: 500 + maximumWidth: 1000 + minimumHeight: 500 + minimumWidth: 1000 title: "Roulette Payout" visible: true diff --git a/StreetBetsModel.cpp b/StreetBetsModel.cpp deleted file mode 100644 index 18a60e6..0000000 --- a/StreetBetsModel.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "StreetBetsModel.h" - -StreetBetsModel::StreetBetsModel(QObject *parent) -{ - -} diff --git a/StreetBetsModel.h b/StreetBetsModel.h deleted file mode 100644 index d1ba119..0000000 --- a/StreetBetsModel.h +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -class StreetBetsModel : public QObject { - Q_OBJECT - QML_ELEMENT - - public: - explicit StreetBetsModel(QObject *parent = nullptr); -}; From b5db91addb35b26047e2c33ff040ed5812c951d1 Mon Sep 17 00:00:00 2001 From: greek Date: Sun, 9 Jun 2024 13:25:58 +0100 Subject: [PATCH 10/10] Optimised suboptimal code. --- BetButton.qml | 37 ++++----- PlayerAreaModel.cpp | 191 ++++++++++++++++++-------------------------- PlayerAreaModel.h | 5 +- Root.qml | 15 ++-- Singles.qml | 1 - 5 files changed, 102 insertions(+), 147 deletions(-) diff --git a/BetButton.qml b/BetButton.qml index bb6a9a9..e0000f4 100644 --- a/BetButton.qml +++ b/BetButton.qml @@ -20,19 +20,19 @@ Item { border.width: 0 color: { - if (PlayerAreaModel.focusedPlayer == 0 && rouletteTable.numberOfBets == 1 && border.width != 3) { - "#00000000" - } else if (PlayerAreaModel.focusedPlayer == 0 && betType != 9) { - "#00000000" - } else if (rouletteTable.numberOfBets < 2 || border.width == 3) { - if ((PlayerAreaModel.focusedPlayer == 0 && rouletteTable.numberOfBets < 1) || PlayerAreaModel.focusedPlayer != 0 || border.width == 3) { - if (tapHandler.pressed) { - "#88999999" - } else if (hoverHandler.hovered) { - "#88EEEEEE" - } else { - "#00000000" - } + /* + * A bit of a mess + * The left side of the OR is checking if the player is croupier, and if it is, if it hasn't made a bet that has to be a number. + * Even if the above isn't true, it still highlights if it's hovering a bet so that it can remove the bet. + * + * The right side of the OR is similar logic but for normal players that can make two bets on any square of the board + */ + if (((PlayerAreaModel.focusedPlayer == 0 && betType == 9) && (rouletteTable.numberOfBets < 1 || border.width == 3)) || + (PlayerAreaModel.focusedPlayer != 0 && (rouletteTable.numberOfBets < 2 || border.width == 3))) { + if (tapHandler.pressed) { + "#88999999" + } else if (hoverHandler.hovered) { + "#88EEEEEE" } else { "#00000000" } @@ -48,11 +48,12 @@ Item { id: tapHandler onTapped: { - if (PlayerAreaModel.focusedPlayer == 0 && rouletteTable.numberOfBets == 1 && parent.border.width != 3) { - - } else if (PlayerAreaModel.focusedPlayer == 0 && betType != 9) { - - }else if (rouletteTable.numberOfBets < 2 && parent.border.width == 0) { + /* + * Similar logic to what is used for setting the color attribute, but this time only go inside the "if" if a bet hasn't + * been made on the square that was clicked. + */ + if (((PlayerAreaModel.focusedPlayer == 0 && betType == 9) && (rouletteTable.numberOfBets < 1 && parent.border.width != 3)) || + (PlayerAreaModel.focusedPlayer != 0 && (rouletteTable.numberOfBets < 2 && parent.border.width != 3))) { parent.border.width = 3 /* Don't show this dialog for the croupier */ diff --git a/PlayerAreaModel.cpp b/PlayerAreaModel.cpp index ca3d02d..c6d59e2 100644 --- a/PlayerAreaModel.cpp +++ b/PlayerAreaModel.cpp @@ -4,10 +4,15 @@ PlayerAreaModel::PlayerAreaModel(QObject *parent) { Player defaultValues; + Bet defaultBets; for(int i = 0; i < 8; i++){ players.append(defaultValues); + for (int ii = 0; ii < 2; ii++) { + players[i].bets.append(defaultBets); + } } + /* This is set to avoid segfaults if the starting value is out of bounds */ focusedPlayer_ = 1; } @@ -20,10 +25,10 @@ void PlayerAreaModel::setFocusedPlayer(int n) { focusedPlayer_ = n; Player player = players.at(n); - BetType b1 = player.bet1.betType; - BetType b2 = player.bet2.betType; - uint n1 = player.bet1.betSpot; - uint n2 = player.bet2.betSpot; + BetType b1 = player.bets[0].betType; + BetType b2 = player.bets[1].betType; + uint n1 = player.bets[0].betSpot; + uint n2 = player.bets[1].betSpot; emit focusedPlayerChanged(b1, n1, b2, n2); } @@ -41,44 +46,38 @@ void PlayerAreaModel::bet(BetType b, int n, int bet) { Player *player = &players[focusedPlayer_]; - if (player->bet1.betType == NONE) { - player->bet1.betType = b; - player->bet1.betValue = bet; - player->bet1.betSpot = n; - /* - * This is needed because the visual roulette board is inverted from the actual QML grid we use to represent it. - * Here we use 35 because the grid is 0-indexed, but later we use 36 for convinience - */ - if (b == SINGLE && n <= 35) { - n = 35 - n; + for (int i = 0; i < 2; i++) { + if (player->bets[i].betType == NONE) { + player->bets[i].betType = b; + player->bets[i].betValue = bet; + player->bets[i].betSpot = n; + /* + * This is needed because the visual roulette board is inverted from the + * actual QML grid we use to represent it. + * Here we use 35 because the grid is 0-indexed, but later we use 36 when it is 1-indexed. + */ + if (b == SINGLE && n <= 35) { + n = 35 - n; + } + emit betChanged(b, n, bet); + break; } - emit betChanged(b, n, bet); - } else if (player->bet2.betType == NONE) { - player->bet2.betType = b; - player->bet2.betValue = bet; - player->bet2.betSpot = n; - if (b == SINGLE && n <= 35) { - n = 35 - n; - } - emit betChanged(b, n, bet); } } void PlayerAreaModel::removeBet(BetType b, int n) { Player *player = &players[focusedPlayer_]; - if (player->bet1.betType == b) { - player->bet1.betType = NONE; - if (b == SINGLE && n <= 35) { - n = 35 - n; + + + for (int i = 0; i < 2; i++) { + if (player->bets[i].betType == b && player->bets[i].betSpot == n) { + player->bets[i].betType = NONE; + if (b == SINGLE && n <= 35) { + n = 35 - n; + } + emit betRemoved(b, n); } - emit betRemoved(b, n); - } else if (player->bet2.betType == b) { - player->bet2.betType = NONE; - if (b == SINGLE && n <= 35) { - n = 35 - n; - } - emit betRemoved(b, n); } } @@ -89,99 +88,61 @@ void PlayerAreaModel::cancelBet(BetType b, int n) void PlayerAreaModel::payout() { - if (players.at(0).bet1.betType == NONE) { + if (players.at(0).bets[0].betType == NONE) { fprintf(stderr, "Select where the ball landed\n"); } else { - int rollSpot = 36 - players.at(0).bet1.betSpot; + int rollSpot = 36 - players.at(0).bets[0].betSpot; for (int i = 1; i < 8; i++) { - int betType = players.at(i).bet1.betType; - int betSpot; players[i].payout = 0; + for (int ii = 0; ii < 2; ii++) { + int betType = players.at(i).bets[ii].betType; + int betSpot; - if (betType != NONE) { - betSpot = players.at(i).bet1.betSpot; - if (betType == SINGLE && betSpot <= 35) { - betSpot = 36 - betSpot; - } else { - betSpot += 1; - } + if (betType != NONE) { + betSpot = players.at(i).bets[ii].betSpot; - if (betType == SINGLE && betSpot == rollSpot) { - players[i].payout += players.at(i).bet1.betValue * 21; - } else if (betType == RED && (((int64_t)1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == BLACK && !(((int64_t)1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == ODD && (rollSpot % 2)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == EVEN && !(rollSpot % 2)) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == LOW && rollSpot <= 18 ) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { - players[i].payout += players.at(i).bet1.betValue * 2; - } else if (betType == DOZEN) { - if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet1.betValue * 3; + if (betType == SINGLE && betSpot <= 35) { + betSpot = 36 - betSpot; + } else { + betSpot += 1; } - } else if (betType == STREET) { - if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet1.betValue * 6; - } - } else if (betType == COLUMN) { - if (betSpot == 1 && (((int64_t)1 << (rollSpot - 1)) & column1)) { - players[i].payout += players.at(i).bet1.betValue * 3; - } else if (betSpot == 2 && (((int64_t)1 << (rollSpot - 1)) & column2)) { - players[i].payout += players.at(i).bet1.betValue * 3; - } else if (betSpot == 3 && (((int64_t)1 << (rollSpot - 1)) & column3)) { - players[i].payout += players.at(i).bet1.betValue * 3; + + if (betType == SINGLE && betSpot == rollSpot) { + players[i].payout += players.at(i).bets[ii].betValue * 21; + } else if (betType == RED && (((int64_t)1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bets[ii].betValue * 2; + } else if (betType == BLACK && !(((int64_t)1 << (rollSpot - 1)) & redNumbers)) { + players[i].payout += players.at(i).bets[ii].betValue * 2; + } else if (betType == ODD && (rollSpot % 2)) { + players[i].payout += players.at(i).bets[ii].betValue * 2; + } else if (betType == EVEN && !(rollSpot % 2)) { + players[i].payout += players.at(i).bets[ii].betValue * 2; + } else if (betType == LOW && rollSpot <= 18 ) { + players[i].payout += players.at(i).bets[ii].betValue * 2; + } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { + players[i].payout += players.at(i).bets[ii].betValue * 2; + } else if (betType == DOZEN) { + printf("CHECK %d %d\n", betSpot, rollSpot); + if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bets[ii].betValue * 3; + } + } else if (betType == STREET) { + if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { + players[i].payout += players.at(i).bets[ii].betValue * 6; + } + } else if (betType == COLUMN) { + if (betSpot == 1 && (((int64_t)1 << (rollSpot - 1)) & column1)) { + players[i].payout += players.at(i).bets[ii].betValue * 3; + } else if (betSpot == 2 && (((int64_t)1 << (rollSpot - 1)) & column2)) { + players[i].payout += players.at(i).bets[ii].betValue * 3; + } else if (betSpot == 3 && (((int64_t)1 << (rollSpot - 1)) & column3)) { + players[i].payout += players.at(i).bets[ii].betValue * 3; + } } } } - betType = players.at(i).bet2.betType; - - if (betType != NONE) { - betSpot = players.at(i).bet2.betSpot; - if (betType == SINGLE && betSpot <= 35) { - betSpot = 36 - betSpot; - } else { - betSpot += 1; - } - - if (betType == SINGLE && betSpot == rollSpot) { - players[i].payout += players.at(i).bet2.betValue * 21; - } else if (betType == RED && (((int64_t)1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == BLACK && !(((int64_t)1 << (rollSpot - 1)) & redNumbers)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == ODD && (rollSpot % 2)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == EVEN && !(rollSpot % 2)) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == LOW && rollSpot <= 18 ) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == HIGH && rollSpot >= 19 && rollSpot < 37) { - players[i].payout += players.at(i).bet2.betValue * 2; - } else if (betType == DOZEN) { - if (rollSpot <= 12 * betSpot && rollSpot >= (12 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet2.betValue * 3; - } - } else if (betType == STREET) { - if (rollSpot <= 3 * betSpot && rollSpot >= (3 * (betSpot - 1)) + 1) { - players[i].payout += players.at(i).bet2.betValue * 6; - } - } else if (betType == COLUMN) { - if (betSpot == 1 && (((int64_t)1 << (rollSpot - 1)) & column1)) { - players[i].payout += players.at(i).bet2.betValue * 3; - } else if (betSpot == 2 && (((int64_t)1 << (rollSpot - 1)) & column2)) { - players[i].payout += players.at(i).bet2.betValue * 3; - } else if (betSpot == 3 && (((int64_t)1 << (rollSpot - 1)) & column3)) { - players[i].payout += players.at(i).bet2.betValue * 3; - } - } - } emit results(players.at(i).playerName, i, players.at(i).payout); } } diff --git a/PlayerAreaModel.h b/PlayerAreaModel.h index 0a87aee..2fc7706 100644 --- a/PlayerAreaModel.h +++ b/PlayerAreaModel.h @@ -11,6 +11,7 @@ class PlayerAreaModel : public QObject { Q_OBJECT + /* The name under which this "global variable" will be known in QML files */ QML_NAMED_ELEMENT(PlayerAreaModel) QML_SINGLETON @@ -55,7 +56,6 @@ public slots: private: - struct Bet { uint betValue = 0; BetType betType = NONE; @@ -64,8 +64,7 @@ private: struct Player { QString playerName = ""; - Bet bet1; - Bet bet2; + QList bets; int payout; }; diff --git a/Root.qml b/Root.qml index 1fb17de..a0d819d 100644 --- a/Root.qml +++ b/Root.qml @@ -14,9 +14,9 @@ Window { Pane { anchors.fill: parent + /* Exists exclusively to remove focus from TextFields by clicking anywhere else on the screen */ MouseArea { anchors.fill: parent - onClicked: focus = true } @@ -37,7 +37,6 @@ Window { Button { id: payoutButton - highlighted: false onClicked: PlayerAreaModel.payout() enabled: false @@ -66,14 +65,10 @@ Window { implicitWidth: 150 implicitHeight: 60 opacity: { - if (enabled == true) { - if (parent.pressed) { - 0.5 - } else if (parent.hovered) { - 0.2 - } else { - 0.3 - } + if (enabled == true && parent.pressed) { + 0.5 + } else if (enabled == true && parent.hovered) { + 0.2 } else { 0.3 } diff --git a/Singles.qml b/Singles.qml index af7f460..39388e4 100644 --- a/Singles.qml +++ b/Singles.qml @@ -8,7 +8,6 @@ Item { LayoutMirroring.enabled: true flow: GridLayout.TopToBottom rows: 3 - //rotation: 180 anchors { right: parent.right