Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
d5d8f5cffc
42 changed files with 2461 additions and 7220 deletions
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "qt-openssl-encryption"]
|
||||
path = qt-openssl-encryption
|
||||
url = ssh://git@git.itsblue.de:2222/itsblue-development/qt-openssl-encryption.git
|
1
Qt-Secret/GMP/.gitignore
vendored
1
Qt-Secret/GMP/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/build/
|
|
@ -1,24 +0,0 @@
|
|||
#
|
||||
# Copyright (C) 2018-2019 QuasarApp.
|
||||
# Distributed under the lgplv3 software license, see the accompanying
|
||||
# Everyone is permitted to copy and distribute verbatim copies
|
||||
# of this license document, but changing it is not allowed.
|
||||
#
|
||||
|
||||
!isEmpty(Qt_GMP_LIB):error("GMP.pri already included")
|
||||
Qt_GMP_LIB = 1
|
||||
|
||||
DEFINES += MINIGMP_LIBRARY
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/bigint.h \
|
||||
$$PWD/mini-gmp.h \
|
||||
$$PWD/minigmp_global.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/bigint.cpp \
|
||||
$$PWD/mini-gmp.c
|
||||
|
||||
|
||||
INCLUDEPATH += $$PWD
|
|
@ -1,21 +0,0 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2019 QuasarApp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,618 +0,0 @@
|
|||
//#
|
||||
//# Copyright (C) 2018-2019 QuasarApp.
|
||||
//# Distributed under the lgplv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
#include "bigint.h"
|
||||
#include <limits>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
// constructors
|
||||
BigInt::BigInt() {
|
||||
mpz_init(data);
|
||||
}
|
||||
|
||||
BigInt::BigInt(const BigInt &val, int bitCount) {
|
||||
if (bitCount > 0) {
|
||||
mpz_init2(data, static_cast<unsigned int>(bitCount));
|
||||
} else {
|
||||
mpz_init(data);
|
||||
}
|
||||
|
||||
mpz_set(data, val.data);
|
||||
|
||||
}
|
||||
|
||||
BigInt::BigInt(const std::string &str, int base):
|
||||
BigInt() {
|
||||
mpz_set_str(data, str.c_str(), base);
|
||||
}
|
||||
|
||||
BigInt::BigInt(intMpz val):
|
||||
BigInt() {
|
||||
mpz_set_si(data, val);
|
||||
}
|
||||
|
||||
BigInt::BigInt(char item, unsigned int size, int base = 2):
|
||||
BigInt(std::string(size, item),base) {
|
||||
}
|
||||
|
||||
std::string BigInt::getString(int base) const {
|
||||
char *str = mpz_get_str(nullptr, base, data);
|
||||
return str;
|
||||
}
|
||||
|
||||
BigInt::~BigInt() {
|
||||
mpz_clear(data);
|
||||
}
|
||||
|
||||
BigInt &BigInt::powm(const BigInt &pow, const BigInt &mod) {
|
||||
mpz_powm(data, data, pow.data, mod.data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInt BigInt::powm(BigInt val, const BigInt &pow, const BigInt &mod) {
|
||||
return val.powm(pow, mod);
|
||||
}
|
||||
|
||||
BigInt &BigInt::pow(uIntMpz pow) {
|
||||
mpz_pow_ui(data, data, pow);
|
||||
return *this;
|
||||
}
|
||||
|
||||
int BigInt::sizeBits() const {
|
||||
return sizeBytes() * 8;
|
||||
}
|
||||
|
||||
int BigInt::sizeBytes() const {
|
||||
return static_cast<int>(mpz_size(data) * sizeof ((*data->_mp_d)));
|
||||
}
|
||||
|
||||
int BigInt::longBits() const {
|
||||
return static_cast<int>(getString(2).size());
|
||||
}
|
||||
|
||||
int BigInt::longBytes() const {
|
||||
return static_cast<int>(std::ceil(static_cast<double>(longBits()) / 8));
|
||||
}
|
||||
|
||||
#define GMP_ABS(x) ((x) >= 0 ? (x) : -(x))
|
||||
int BigInt::sizeType() const {
|
||||
return static_cast<int>(static_cast<size_t>(GMP_ABS( data->_mp_alloc)) *
|
||||
sizeof ((*data->_mp_d)));
|
||||
|
||||
}
|
||||
|
||||
bool BigInt::isPrime(bool absalut) const {
|
||||
return (mpz_probab_prime_p(data, 50) - (absalut? 1: 0)) > 0;
|
||||
}
|
||||
|
||||
BigInt& BigInt::gcd(const BigInt &a, const BigInt &b) {
|
||||
mpz_gcd(data, a.data, b.data);
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
void BigInt::fromHex(const std::string &hex) {
|
||||
mpz_set_str(data, hex.c_str(), 16);
|
||||
}
|
||||
|
||||
BigInt BigInt::bigPow10(unsigned short pow) {
|
||||
return "1" + std::string(pow, '0');
|
||||
}
|
||||
|
||||
BigInt &BigInt::toNegative() {
|
||||
mpz_neg(data, data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInt &BigInt::operator =(const BigInt &val) {
|
||||
mpz_set(data, val.data);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInt &BigInt::operator =(const std::string &imput) {
|
||||
mpz_set_str(data, imput.c_str(), 10);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInt &BigInt::operator =(intMpz val) {
|
||||
mpz_set_si(data, val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// add operators
|
||||
|
||||
BigInt operator +(BigInt left, intMpz right) {
|
||||
if (right >= 0) {
|
||||
mpz_add_ui(left.data, left.data, static_cast<uIntMpz>(right));
|
||||
return left;
|
||||
}
|
||||
|
||||
return left -= std::abs(right);
|
||||
}
|
||||
|
||||
BigInt operator +(intMpz left, BigInt right) {
|
||||
return right += left;
|
||||
}
|
||||
|
||||
BigInt operator +(BigInt left, const BigInt &right) {
|
||||
mpz_add(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator +(BigInt left, const std::string &right) {
|
||||
return left += BigInt(right);
|
||||
}
|
||||
|
||||
BigInt operator +(const std::string &left, const BigInt &right) {
|
||||
return BigInt(left) + right;
|
||||
}
|
||||
|
||||
BigInt& operator +=(BigInt &left, intMpz right) {
|
||||
if (right >= 0) {
|
||||
mpz_add_ui(left.data, left.data, static_cast<uIntMpz>(right));
|
||||
return left;
|
||||
}
|
||||
return left -= std::abs(right);
|
||||
}
|
||||
|
||||
BigInt& operator +=(BigInt &left, const BigInt &right) {
|
||||
mpz_add(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator +=(BigInt &left, const std::string &right) {
|
||||
return left += BigInt(right);
|
||||
}
|
||||
|
||||
// sub operators
|
||||
|
||||
BigInt operator -(BigInt left, const BigInt &right) {
|
||||
mpz_sub(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator -(BigInt left, intMpz right) {
|
||||
if (right >= 0) {
|
||||
mpz_sub_ui(left.data, left.data, static_cast<uIntMpz>(right));
|
||||
return left;
|
||||
}
|
||||
return left += std::abs(right);
|
||||
}
|
||||
|
||||
BigInt operator -(intMpz left, BigInt right) {
|
||||
if (left >= 0) {
|
||||
mpz_ui_sub(right.data, static_cast<uIntMpz>(left), right.data);
|
||||
return right;
|
||||
}
|
||||
return right += std::abs(left);
|
||||
}
|
||||
|
||||
BigInt operator-(BigInt val) {
|
||||
mpz_neg(val.data, val.data);
|
||||
return val;
|
||||
}
|
||||
|
||||
BigInt operator -(BigInt left, const std::string &right) {
|
||||
return left -= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt operator -(const std::string & left, const BigInt &right) {
|
||||
return BigInt(left) - right;
|
||||
}
|
||||
|
||||
BigInt& operator -=(BigInt &left, const BigInt &right) {
|
||||
mpz_sub(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator -=(BigInt &left, const std::string &right) {
|
||||
return left -= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt& operator -=(BigInt &left, intMpz right) {
|
||||
if (right >= 0) {
|
||||
mpz_sub_ui(left.data, left.data, static_cast<uIntMpz>(right));
|
||||
return left;
|
||||
}
|
||||
return left += std::abs(right);
|
||||
}
|
||||
|
||||
// div operators
|
||||
|
||||
BigInt operator /(BigInt left, const BigInt &right) {
|
||||
mpz_tdiv_q(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator /(BigInt left, intMpz right) {
|
||||
mpz_tdiv_q_ui(left.data, left.data, static_cast<uIntMpz>(std::abs(right)));
|
||||
|
||||
if (right >= 0) {
|
||||
return left;
|
||||
}
|
||||
return -left;
|
||||
}
|
||||
|
||||
BigInt operator /(BigInt left, const std::string &right) {
|
||||
return left /= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt operator /(intMpz left, BigInt right) {
|
||||
return BigInt(left) / right;
|
||||
}
|
||||
|
||||
BigInt operator /(const std::string & left, const BigInt &right) {
|
||||
return BigInt(left) / right;
|
||||
}
|
||||
|
||||
BigInt& operator /=(BigInt &left, const BigInt &right) {
|
||||
mpz_tdiv_q(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator /=(BigInt &left, const std::string &right) {
|
||||
return left /= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt& operator /=(BigInt &left, intMpz right) {
|
||||
mpz_tdiv_q_ui(left.data, left.data, static_cast<uIntMpz>(std::abs(right)));
|
||||
|
||||
if (right >= 0) {
|
||||
return left;
|
||||
}
|
||||
return left.toNegative();
|
||||
}
|
||||
|
||||
// mul operators
|
||||
BigInt operator *(BigInt left, const BigInt &right) {
|
||||
mpz_mul(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator *(BigInt left, intMpz right) {
|
||||
mpz_mul_ui(left.data, left.data, static_cast<uIntMpz>(std::abs(right)));
|
||||
|
||||
if (right >= 0) {
|
||||
return left;
|
||||
}
|
||||
return -left;
|
||||
}
|
||||
|
||||
BigInt operator *(intMpz left, BigInt right) {
|
||||
return right *= left;
|
||||
}
|
||||
|
||||
BigInt operator *(const std::string & left, BigInt right) {
|
||||
return right *= BigInt(left);
|
||||
}
|
||||
|
||||
BigInt operator *(BigInt left, const std::string &right) {
|
||||
return left *= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt& operator *=(BigInt &left, const BigInt &right) {
|
||||
mpz_mul(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator *=(BigInt &left, const std::string &right) {
|
||||
return left *= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt& operator *=(BigInt &left, intMpz right) {
|
||||
mpz_mul_ui(left.data, left.data, static_cast<uIntMpz>(std::abs(right)));
|
||||
|
||||
if (right >= 0) {
|
||||
return left;
|
||||
}
|
||||
return left.toNegative();
|
||||
}
|
||||
|
||||
//mod operations
|
||||
BigInt operator %(BigInt left, const BigInt &right) {
|
||||
mpz_tdiv_r(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator %(BigInt left, intMpz right) {
|
||||
mpz_tdiv_r_ui(left.data, left.data, static_cast<uIntMpz>(std::abs(right)));
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator %(intMpz left, BigInt right) {
|
||||
return BigInt(left) % right;
|
||||
}
|
||||
|
||||
BigInt operator %(BigInt left, const std::string & right) {
|
||||
return left %= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt operator %(const std::string & left, const BigInt &right) {
|
||||
return BigInt(left) % right;
|
||||
}
|
||||
|
||||
BigInt& operator %=(BigInt& left, const BigInt &right) {
|
||||
mpz_tdiv_r(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator %=(BigInt& left, intMpz right) {
|
||||
mpz_tdiv_r_ui(left.data, left.data, static_cast<uIntMpz>(std::abs(right)));
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator %=(BigInt &left, const std::string &right) {
|
||||
return left %= BigInt(right);
|
||||
}
|
||||
|
||||
// incriment and dicriment
|
||||
BigInt &BigInt::operator--() {
|
||||
*this -= 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInt &BigInt::operator++() {
|
||||
*this += 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigInt BigInt::operator--(int) {
|
||||
BigInt temp(*this);
|
||||
--*this;
|
||||
return temp;
|
||||
}
|
||||
|
||||
BigInt BigInt::operator++(int) {
|
||||
BigInt temp(*this);
|
||||
++*this;
|
||||
return temp;
|
||||
}
|
||||
|
||||
// move operators
|
||||
|
||||
BigInt operator >>(BigInt left, int right) {
|
||||
if (right >= 0) {
|
||||
mpn_rshift(left.data->_mp_d,
|
||||
left.data->_mp_d,
|
||||
left.data->_mp_size,
|
||||
static_cast<unsigned int>(std::abs(right)));
|
||||
return left;
|
||||
}
|
||||
|
||||
return left << right;
|
||||
}
|
||||
|
||||
BigInt operator <<(BigInt left, int right) {
|
||||
if (right >= 0) {
|
||||
mpn_lshift(left.data->_mp_d,
|
||||
left.data->_mp_d,
|
||||
left.data->_mp_size,
|
||||
static_cast<unsigned int>(std::abs(right)));
|
||||
return left;
|
||||
}
|
||||
|
||||
return left >> right;
|
||||
}
|
||||
|
||||
BigInt& operator >>=(BigInt &left, int right) {
|
||||
if (right >= 0) {
|
||||
mpn_rshift(left.data->_mp_d,
|
||||
left.data->_mp_d,
|
||||
left.data->_mp_size,
|
||||
static_cast<unsigned int>(std::abs(right)));
|
||||
return left;
|
||||
}
|
||||
|
||||
return left <<= right;
|
||||
}
|
||||
|
||||
BigInt& operator <<=(BigInt &left, int right) {
|
||||
if (right >= 0) {
|
||||
mpn_lshift(left.data->_mp_d,
|
||||
left.data->_mp_d,
|
||||
left.data->_mp_size,
|
||||
static_cast<unsigned int>(std::abs(right)));
|
||||
return left;
|
||||
}
|
||||
|
||||
return left >>= right;
|
||||
}
|
||||
|
||||
// other bin operators
|
||||
BigInt operator ~(BigInt left) {
|
||||
mpz_com(left.data, left.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator |(BigInt left, const BigInt &right) {
|
||||
mpz_ior(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator |(const BigInt &left, intMpz right) {
|
||||
return left | BigInt(right);
|
||||
}
|
||||
|
||||
BigInt& operator |=(BigInt &left, const BigInt &right) {
|
||||
mpz_ior(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator |=(BigInt &left, intMpz right) {
|
||||
return left |= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt operator &(BigInt left, const BigInt &right) {
|
||||
mpz_and(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator &(const BigInt &left, intMpz right) {
|
||||
return left & BigInt(right);
|
||||
}
|
||||
|
||||
|
||||
BigInt& operator &=(BigInt &left, const BigInt &right) {
|
||||
mpz_and(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator &=(BigInt &left, intMpz right) {
|
||||
return left &= BigInt(right);
|
||||
}
|
||||
|
||||
BigInt operator ^(BigInt left, const BigInt &right) {
|
||||
mpz_xor(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt operator ^(const BigInt &left, intMpz right) {
|
||||
return left ^ BigInt(right);
|
||||
}
|
||||
|
||||
BigInt& operator ^=(BigInt &left, const BigInt &right) {
|
||||
mpz_xor(left.data, left.data, right.data);
|
||||
return left;
|
||||
}
|
||||
|
||||
BigInt& operator ^=(BigInt &left, intMpz right) {
|
||||
return left ^= BigInt(right);
|
||||
}
|
||||
|
||||
|
||||
// logic operators
|
||||
|
||||
bool operator!(const BigInt &val) {
|
||||
return val == 0;
|
||||
}
|
||||
|
||||
bool operator == (const BigInt& left, const BigInt& right) {
|
||||
return mpz_cmp(left.data, right.data) == 0;
|
||||
}
|
||||
|
||||
bool operator == (const BigInt& left, intMpz right) {
|
||||
return mpz_cmp_si(left.data, right) == 0;
|
||||
}
|
||||
|
||||
bool operator == (const BigInt &left, const std::string &right) {
|
||||
return left == BigInt(right);
|
||||
}
|
||||
|
||||
bool operator == ( intMpz left, const BigInt & right) {
|
||||
return right == left;
|
||||
}
|
||||
|
||||
bool operator == ( const std::string & left, const BigInt & right) {
|
||||
return right == BigInt(left);
|
||||
}
|
||||
|
||||
bool operator != (const BigInt &left, const BigInt& right) {
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
bool operator != (const BigInt &left, intMpz right) {
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
bool operator != (const BigInt &left, const std::string &right) {
|
||||
return left != BigInt(right);
|
||||
}
|
||||
|
||||
bool operator != ( intMpz left, const BigInt & right) {
|
||||
return right != left;
|
||||
}
|
||||
|
||||
bool operator != ( const std::string & left, const BigInt & right) {
|
||||
return right != BigInt(left);
|
||||
}
|
||||
|
||||
bool operator < ( const BigInt &left, const BigInt& right) {
|
||||
return mpz_cmp(left.data, right.data) < 0;
|
||||
}
|
||||
|
||||
bool operator < ( const BigInt &left, intMpz right) {
|
||||
return mpz_cmp_si(left.data, right) < 0;
|
||||
}
|
||||
|
||||
bool operator < ( const BigInt &left, const std::string &right) {
|
||||
return left < BigInt(right);
|
||||
}
|
||||
|
||||
bool operator < ( intMpz left, const BigInt & right) {
|
||||
return right > left;
|
||||
}
|
||||
|
||||
bool operator < ( const std::string & left, const BigInt & right) {
|
||||
return right > BigInt(left);
|
||||
}
|
||||
|
||||
bool operator > ( const BigInt &left, const BigInt& right) {
|
||||
return mpz_cmp(left.data, right.data) > 0;
|
||||
}
|
||||
|
||||
bool operator > ( const BigInt &left, intMpz right) {
|
||||
return mpz_cmp_si(left.data, right) > 0;
|
||||
}
|
||||
|
||||
bool operator > ( const BigInt &left, const std::string &right) {
|
||||
return left > BigInt(right);
|
||||
}
|
||||
|
||||
bool operator > ( intMpz left, const BigInt & right) {
|
||||
return right < left;
|
||||
}
|
||||
|
||||
bool operator > ( const std::string & left, const BigInt & right) {
|
||||
return right < BigInt(left);
|
||||
}
|
||||
|
||||
bool operator <= ( const BigInt &left, const BigInt& right) {
|
||||
return mpz_cmp(left.data, right.data) <= 0;
|
||||
}
|
||||
|
||||
bool operator <= ( const BigInt &left, intMpz right) {
|
||||
return mpz_cmp_si(left.data, right) <= 0;
|
||||
}
|
||||
|
||||
bool operator <= ( const BigInt &left, const std::string &right) {
|
||||
return left <= BigInt(right);
|
||||
}
|
||||
|
||||
bool operator <= ( intMpz left, const BigInt & right) {
|
||||
return right >= left;
|
||||
}
|
||||
|
||||
bool operator <= ( const std::string & left, const BigInt & right) {
|
||||
return right >= BigInt(left);
|
||||
}
|
||||
|
||||
bool operator >= ( const BigInt &left, const BigInt& right) {
|
||||
return mpz_cmp(left.data, right.data) >= 0;
|
||||
}
|
||||
|
||||
bool operator >= ( const BigInt &left, intMpz right) {
|
||||
return mpz_cmp_si(left.data, right) >= 0;
|
||||
}
|
||||
|
||||
bool operator >= ( const BigInt &left, const std::string &right) {
|
||||
return left >= BigInt(right);
|
||||
}
|
||||
|
||||
bool operator >= ( intMpz left, const BigInt & right) {
|
||||
return right <= left;
|
||||
}
|
||||
|
||||
bool operator >= ( const std::string & left, const BigInt & right) {
|
||||
return right <= BigInt(left);
|
||||
}
|
||||
|
||||
//// cast operations
|
||||
|
||||
//BigInt::operator bool() const {
|
||||
// return *this != 0;
|
||||
//}
|
|
@ -1,206 +0,0 @@
|
|||
//#
|
||||
//# Copyright (C) 2018-2019 QuasarApp.
|
||||
//# Distributed under the lgplv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
|
||||
#ifndef BIGINT_H
|
||||
#define BIGINT_H
|
||||
#include "mini-gmp.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "minigmp_global.h"
|
||||
|
||||
/**
|
||||
* @brief The BigInt class - c++ minigmp wrapper
|
||||
*/
|
||||
|
||||
class MINIGMPSHARED_EXPORT BigInt
|
||||
{
|
||||
mpz_t data;
|
||||
public:
|
||||
BigInt();
|
||||
BigInt(const BigInt& val, int bitCount = -1);
|
||||
BigInt(const std::string &imput, int base = 10);
|
||||
BigInt(intMpz val);
|
||||
BigInt(char item, unsigned int size, int base);
|
||||
|
||||
std::string getString(int base = 10) const;
|
||||
~BigInt();
|
||||
|
||||
BigInt& powm(const BigInt &pow, const BigInt &mod);
|
||||
static BigInt powm(BigInt val, const BigInt & pow, const BigInt &mod);
|
||||
|
||||
BigInt& pow(uIntMpz pow);
|
||||
BigInt& log(int base);
|
||||
/**
|
||||
* @brief sizeBits
|
||||
* @return size of bits in memory
|
||||
*/
|
||||
int sizeBits() const;
|
||||
int sizeBytes() const;
|
||||
|
||||
/**
|
||||
* @brief longBits
|
||||
* @return current length in Bits of number
|
||||
*/
|
||||
int longBits() const;
|
||||
int longBytes() const;
|
||||
|
||||
int sizeType() const;
|
||||
bool isPrime(bool absalut = false) const;
|
||||
BigInt& gcd(const BigInt &a, const BigInt &b);
|
||||
void fromHex(const std::string& hex);
|
||||
|
||||
/**
|
||||
* @brief bigPow10
|
||||
* @param pow
|
||||
* @return number 10 ^ pow
|
||||
*/
|
||||
static BigInt bigPow10(unsigned short pow);
|
||||
|
||||
BigInt& toNegative();
|
||||
|
||||
BigInt& operator = (const BigInt& val);
|
||||
BigInt& operator = (const std::string &imput);
|
||||
BigInt& operator = (intMpz val);
|
||||
|
||||
friend BigInt operator + ( BigInt left, const BigInt& right);
|
||||
friend BigInt operator + ( BigInt left, const std::string &right);
|
||||
friend BigInt operator + ( BigInt left, intMpz right);
|
||||
|
||||
friend BigInt operator + ( intMpz left, BigInt right);
|
||||
friend BigInt operator + ( const std::string &left, const BigInt &right);
|
||||
|
||||
friend BigInt& operator += ( BigInt &left, intMpz right);
|
||||
friend BigInt& operator += ( BigInt &left, const BigInt& right);
|
||||
friend BigInt& operator += ( BigInt &left, const std::string &right);
|
||||
|
||||
friend BigInt operator - ( BigInt left, const BigInt& right);
|
||||
friend BigInt operator - ( BigInt left, intMpz right);
|
||||
friend BigInt operator - ( BigInt left, const std::string &right);
|
||||
|
||||
friend BigInt operator - ( intMpz right, BigInt left);
|
||||
friend BigInt operator - ( const std::string &right, const BigInt &left);
|
||||
|
||||
friend BigInt operator-(BigInt val);
|
||||
|
||||
friend BigInt& operator -= ( BigInt &left, intMpz right);
|
||||
|
||||
friend BigInt& operator -= ( BigInt &left, const BigInt& right);
|
||||
friend BigInt& operator -= ( BigInt &left, const std::string &right);
|
||||
|
||||
friend BigInt operator / ( BigInt left, const BigInt& right);
|
||||
friend BigInt operator / ( BigInt left, const std::string &right);
|
||||
friend BigInt operator / ( BigInt left, intMpz right);
|
||||
friend BigInt operator / ( intMpz left, BigInt right);
|
||||
friend BigInt operator / ( const std::string &left, const BigInt &right);
|
||||
|
||||
friend BigInt& operator /= ( BigInt &left, intMpz right);
|
||||
friend BigInt& operator /= ( BigInt &left, const std::string &right);
|
||||
friend BigInt& operator /= ( BigInt &left, const BigInt& right);
|
||||
|
||||
friend BigInt operator * ( BigInt left, const BigInt& right);
|
||||
friend BigInt operator * ( BigInt left, const std::string &right);
|
||||
friend BigInt operator * ( BigInt left, intMpz right);
|
||||
|
||||
friend BigInt operator * ( intMpz left, BigInt right);
|
||||
|
||||
friend BigInt& operator *= ( BigInt &left, const BigInt& right);
|
||||
friend BigInt& operator *= ( BigInt &left, intMpz right);
|
||||
friend BigInt& operator *= ( BigInt &left, const std::string &right);
|
||||
|
||||
friend BigInt operator % ( BigInt left, const BigInt& right);
|
||||
friend BigInt operator % ( BigInt left, const std::string &right);
|
||||
friend BigInt operator % ( BigInt left, intMpz right);
|
||||
|
||||
friend BigInt operator % ( intMpz left, BigInt right);
|
||||
friend BigInt operator % ( const std::string & left, const BigInt &right);
|
||||
|
||||
friend BigInt& operator %= ( BigInt &left, intMpz right);
|
||||
friend BigInt& operator %= ( BigInt &left, const std::string &right);
|
||||
|
||||
friend BigInt& operator %= ( BigInt &left, const BigInt& right);
|
||||
|
||||
friend BigInt operator << ( BigInt left, int right);
|
||||
friend BigInt operator >> ( BigInt left, int right);
|
||||
|
||||
friend BigInt& operator <<= ( BigInt &left, int right);
|
||||
friend BigInt& operator >>= ( BigInt &left, int right);
|
||||
|
||||
friend bool operator == ( const BigInt& left, const BigInt& right);
|
||||
friend bool operator == ( const BigInt& left, intMpz right);
|
||||
friend bool operator == ( const BigInt& left, const std::string& right);
|
||||
friend bool operator == ( const std::string& left, const BigInt& right);
|
||||
friend bool operator == ( const BigInt& left, const std::string& right);
|
||||
friend bool operator == ( intMpz left, const std::string& right);
|
||||
|
||||
friend bool operator != ( const BigInt& left, const BigInt& right);
|
||||
friend bool operator != ( const BigInt& left, intMpz right);
|
||||
friend bool operator != ( const BigInt& left, const std::string& str);
|
||||
friend bool operator != ( const std::string& left, const BigInt& right);
|
||||
friend bool operator != ( const BigInt& left, const std::string& right);
|
||||
friend bool operator != ( intMpz left, const std::string& right);
|
||||
|
||||
friend bool operator < ( const BigInt& left, const BigInt& right);
|
||||
friend bool operator < ( const BigInt& left, intMpz right);
|
||||
friend bool operator < ( const BigInt& left, const std::string& str);
|
||||
friend bool operator < ( const std::string& left, const BigInt& right);
|
||||
friend bool operator < ( const BigInt& left, const std::string& right);
|
||||
friend bool operator < ( intMpz left, const std::string& right);
|
||||
|
||||
friend bool operator > ( const BigInt& left, const BigInt& right);
|
||||
friend bool operator > ( const BigInt& left, intMpz right);
|
||||
friend bool operator > ( const BigInt& left, const std::string& str);
|
||||
friend bool operator > ( const std::string& left, const BigInt& right);
|
||||
friend bool operator > ( const BigInt& left, const std::string& right);
|
||||
friend bool operator > ( intMpz left, const std::string& right);
|
||||
|
||||
friend bool operator <= ( const BigInt& left, const BigInt& right);
|
||||
friend bool operator <= ( const BigInt& left, intMpz right);
|
||||
friend bool operator <= ( const BigInt& left, const std::string& str);
|
||||
friend bool operator <= ( const std::string& left, const BigInt& right);
|
||||
friend bool operator <= ( const BigInt& left, const std::string& right);
|
||||
friend bool operator <= ( intMpz left, const std::string& right);
|
||||
|
||||
friend bool operator >= ( const BigInt& left, const BigInt& right);
|
||||
friend bool operator >= ( const BigInt& left, intMpz right);
|
||||
friend bool operator >= ( const BigInt& left, const std::string& str);
|
||||
friend bool operator >= ( const std::string& left, const BigInt& right);
|
||||
friend bool operator >= ( const BigInt& left, const std::string& right);
|
||||
friend bool operator >= ( intMpz left, const std::string& right);
|
||||
|
||||
friend bool operator!(const BigInt& val);
|
||||
|
||||
BigInt& operator-- ();
|
||||
BigInt& operator++ ();
|
||||
|
||||
BigInt operator-- (int);
|
||||
BigInt operator++ (int);
|
||||
|
||||
|
||||
friend BigInt operator~ (BigInt val);
|
||||
|
||||
friend BigInt operator| (BigInt left, const BigInt& right);
|
||||
friend BigInt operator| (const BigInt &left, intMpz right);
|
||||
|
||||
friend BigInt& operator|= (BigInt &left, const BigInt& right);
|
||||
friend BigInt& operator|= (BigInt &left, intMpz right);
|
||||
|
||||
friend BigInt operator& (BigInt left, const BigInt& right);
|
||||
friend BigInt operator& (const BigInt &left, intMpz right);
|
||||
|
||||
friend BigInt& operator&= (BigInt &left, const BigInt& right);
|
||||
friend BigInt& operator&= (BigInt &left, intMpz right);
|
||||
|
||||
friend BigInt operator^ (BigInt left, const BigInt& right);
|
||||
friend BigInt operator^ (const BigInt &left, intMpz right);
|
||||
|
||||
friend BigInt& operator^= (BigInt &left, const BigInt& right);
|
||||
friend BigInt& operator^= (BigInt &left, intMpz right);
|
||||
|
||||
};
|
||||
|
||||
#endif // BIGINT_H
|
File diff suppressed because it is too large
Load diff
|
@ -1,303 +0,0 @@
|
|||
/* mini-gmp, a minimalistic implementation of a GNU GMP subset.
|
||||
|
||||
Copyright 2011-2015 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the GNU MP Library.
|
||||
|
||||
The GNU MP Library is free software; you can redistribute it and/or modify
|
||||
it under the terms of either:
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
or
|
||||
|
||||
* the GNU General Public License as published by the Free Software
|
||||
Foundation; either version 2 of the License, or (at your option) any
|
||||
later version.
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
The GNU MP Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received copies of the GNU General Public License and the
|
||||
GNU Lesser General Public License along with the GNU MP Library. If not,
|
||||
see https://www.gnu.org/licenses/. */
|
||||
|
||||
/* About mini-gmp: This is a minimal implementation of a subset of the
|
||||
GMP interface. It is intended for inclusion into applications which
|
||||
have modest bignums needs, as a fallback when the real GMP library
|
||||
is not installed.
|
||||
|
||||
This file defines the public interface. */
|
||||
|
||||
#ifndef MINI_GMP
|
||||
#define MINI_GMP
|
||||
|
||||
/* For size_t */
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define UN_USED(X) (void)X
|
||||
|
||||
void mp_set_memory_functions (void *(*) (size_t),
|
||||
void *(*) (void *, size_t, size_t),
|
||||
void (*) (void *, size_t));
|
||||
|
||||
void mp_get_memory_functions (void *(**) (size_t),
|
||||
void *(**) (void *, size_t, size_t),
|
||||
void (**) (void *, size_t));
|
||||
|
||||
typedef unsigned long long uIntMpz;
|
||||
typedef long long intMpz;
|
||||
|
||||
typedef uIntMpz mp_limb_t;
|
||||
typedef intMpz mp_size_t;
|
||||
typedef uIntMpz mp_bitcnt_t;
|
||||
|
||||
typedef mp_limb_t *mp_ptr;
|
||||
typedef const mp_limb_t *mp_srcptr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int _mp_alloc; /* Number of *limbs* allocated and pointed
|
||||
to by the _mp_d field. */
|
||||
int _mp_size; /* abs(_mp_size) is the number of limbs the
|
||||
last field points to. If _mp_size is
|
||||
negative this is a negative number. */
|
||||
mp_limb_t *_mp_d; /* Pointer to the limbs. */
|
||||
} __mpz_struct;
|
||||
|
||||
typedef __mpz_struct mpz_t[1];
|
||||
|
||||
typedef __mpz_struct *mpz_ptr;
|
||||
typedef const __mpz_struct *mpz_srcptr;
|
||||
|
||||
extern const int mp_bits_per_limb;
|
||||
|
||||
void mpn_copyi (mp_ptr, mp_srcptr, mp_size_t);
|
||||
void mpn_copyd (mp_ptr, mp_srcptr, mp_size_t);
|
||||
void mpn_zero (mp_ptr, mp_size_t);
|
||||
|
||||
int mpn_cmp (mp_srcptr, mp_srcptr, mp_size_t);
|
||||
int mpn_zero_p (mp_srcptr, mp_size_t);
|
||||
|
||||
mp_limb_t mpn_add_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||
mp_limb_t mpn_add_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
|
||||
mp_limb_t mpn_add (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
|
||||
|
||||
mp_limb_t mpn_sub_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||
mp_limb_t mpn_sub_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
|
||||
mp_limb_t mpn_sub (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
|
||||
|
||||
mp_limb_t mpn_mul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||
mp_limb_t mpn_addmul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||
mp_limb_t mpn_submul_1 (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t);
|
||||
|
||||
mp_limb_t mpn_mul (mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t);
|
||||
void mpn_mul_n (mp_ptr, mp_srcptr, mp_srcptr, mp_size_t);
|
||||
void mpn_sqr (mp_ptr, mp_srcptr, mp_size_t);
|
||||
int mpn_perfect_square_p (mp_srcptr, mp_size_t);
|
||||
mp_size_t mpn_sqrtrem (mp_ptr, mp_ptr, mp_srcptr, mp_size_t);
|
||||
|
||||
mp_limb_t mpn_lshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
|
||||
mp_limb_t mpn_rshift (mp_ptr, mp_srcptr, mp_size_t, unsigned int);
|
||||
|
||||
mp_bitcnt_t mpn_scan0 (mp_srcptr, mp_bitcnt_t);
|
||||
mp_bitcnt_t mpn_scan1 (mp_srcptr, mp_bitcnt_t);
|
||||
|
||||
void mpn_com (mp_ptr, mp_srcptr, mp_size_t);
|
||||
mp_limb_t mpn_neg (mp_ptr, mp_srcptr, mp_size_t);
|
||||
|
||||
mp_bitcnt_t mpn_popcount (mp_srcptr, mp_size_t);
|
||||
|
||||
mp_limb_t mpn_invert_3by2 (mp_limb_t, mp_limb_t);
|
||||
#define mpn_invert_limb(x) mpn_invert_3by2 ((x), 0)
|
||||
|
||||
size_t mpn_get_str (unsigned char *, int, mp_ptr, mp_size_t);
|
||||
mp_size_t mpn_set_str (mp_ptr, const unsigned char *, size_t, int);
|
||||
|
||||
void mpz_init (mpz_t);
|
||||
void mpz_init2 (mpz_t, mp_bitcnt_t);
|
||||
void mpz_clear (mpz_t);
|
||||
|
||||
#define mpz_odd_p(z) (((z)->_mp_size != 0) & (int) (z)->_mp_d[0])
|
||||
#define mpz_even_p(z) (! mpz_odd_p (z))
|
||||
|
||||
int mpz_sgn (const mpz_t);
|
||||
int mpz_cmp_si (const mpz_t, intMpz);
|
||||
int mpz_cmp_ui (const mpz_t, uIntMpz);
|
||||
int mpz_cmp (const mpz_t, const mpz_t);
|
||||
int mpz_cmpabs_ui (const mpz_t, uIntMpz);
|
||||
int mpz_cmpabs (const mpz_t, const mpz_t);
|
||||
int mpz_cmp_d (const mpz_t, double);
|
||||
int mpz_cmpabs_d (const mpz_t, double);
|
||||
|
||||
void mpz_abs (mpz_t, const mpz_t);
|
||||
void mpz_neg (mpz_t, const mpz_t);
|
||||
void mpz_swap (mpz_t, mpz_t);
|
||||
|
||||
void mpz_add_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_add (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_sub_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_ui_sub (mpz_t, uIntMpz, const mpz_t);
|
||||
void mpz_sub (mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
void mpz_mul_si (mpz_t, const mpz_t, intMpz);
|
||||
void mpz_mul_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_mul (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_mul_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||
void mpz_addmul_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_addmul (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_submul_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_submul (mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
void mpz_cdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_fdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_tdiv_qr (mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_cdiv_q (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_fdiv_q (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_tdiv_q (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_cdiv_r (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_fdiv_r (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_tdiv_r (mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
void mpz_cdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||
void mpz_fdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||
void mpz_tdiv_q_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||
void mpz_cdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||
void mpz_fdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||
void mpz_tdiv_r_2exp (mpz_t, const mpz_t, mp_bitcnt_t);
|
||||
|
||||
void mpz_mod (mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
void mpz_divexact (mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
int mpz_divisible_p (const mpz_t, const mpz_t);
|
||||
int mpz_congruent_p (const mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
uIntMpz mpz_cdiv_qr_ui (mpz_t, mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_fdiv_qr_ui (mpz_t, mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_tdiv_qr_ui (mpz_t, mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_cdiv_q_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_fdiv_q_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_tdiv_q_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_cdiv_r_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_fdiv_r_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_tdiv_r_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_cdiv_ui (const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_fdiv_ui (const mpz_t, uIntMpz);
|
||||
uIntMpz mpz_tdiv_ui (const mpz_t, uIntMpz);
|
||||
|
||||
uIntMpz mpz_mod_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
|
||||
void mpz_divexact_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
|
||||
int mpz_divisible_ui_p (const mpz_t, uIntMpz);
|
||||
|
||||
uIntMpz mpz_gcd_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_gcd (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_gcdext (mpz_t, mpz_t, mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_lcm_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_lcm (mpz_t, const mpz_t, const mpz_t);
|
||||
int mpz_invert (mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
void mpz_sqrtrem (mpz_t, mpz_t, const mpz_t);
|
||||
void mpz_sqrt (mpz_t, const mpz_t);
|
||||
int mpz_perfect_square_p (const mpz_t);
|
||||
|
||||
void mpz_pow_ui (mpz_t, const mpz_t, uIntMpz);
|
||||
void mpz_ui_pow_ui (mpz_t, uIntMpz, uIntMpz);
|
||||
void mpz_powm (mpz_t, const mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_powm_ui (mpz_t, const mpz_t, uIntMpz, const mpz_t);
|
||||
|
||||
void mpz_rootrem (mpz_t, mpz_t, const mpz_t, uIntMpz);
|
||||
int mpz_root (mpz_t, const mpz_t, uIntMpz);
|
||||
|
||||
void mpz_fac_ui (mpz_t, uIntMpz);
|
||||
void mpz_bin_uiui (mpz_t, uIntMpz, uIntMpz);
|
||||
|
||||
int mpz_probab_prime_p (const mpz_t, int);
|
||||
|
||||
int mpz_tstbit (const mpz_t, mp_bitcnt_t);
|
||||
void mpz_setbit (mpz_t, mp_bitcnt_t);
|
||||
void mpz_clrbit (mpz_t, mp_bitcnt_t);
|
||||
void mpz_combit (mpz_t, mp_bitcnt_t);
|
||||
|
||||
void mpz_com (mpz_t, const mpz_t);
|
||||
void mpz_and (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_ior (mpz_t, const mpz_t, const mpz_t);
|
||||
void mpz_xor (mpz_t, const mpz_t, const mpz_t);
|
||||
|
||||
mp_bitcnt_t mpz_popcount (const mpz_t);
|
||||
mp_bitcnt_t mpz_hamdist (const mpz_t, const mpz_t);
|
||||
mp_bitcnt_t mpz_scan0 (const mpz_t, mp_bitcnt_t);
|
||||
mp_bitcnt_t mpz_scan1 (const mpz_t, mp_bitcnt_t);
|
||||
|
||||
int mpz_fits_slong_p (const mpz_t);
|
||||
int mpz_fits_ulong_p (const mpz_t);
|
||||
intMpz mpz_get_si (const mpz_t);
|
||||
uIntMpz mpz_get_ui (const mpz_t);
|
||||
double mpz_get_d (const mpz_t);
|
||||
size_t mpz_size (const mpz_t);
|
||||
mp_limb_t mpz_getlimbn (const mpz_t, mp_size_t);
|
||||
|
||||
void mpz_realloc2 (mpz_t, mp_bitcnt_t);
|
||||
mp_srcptr mpz_limbs_read (mpz_srcptr);
|
||||
mp_ptr mpz_limbs_modify (mpz_t, mp_size_t);
|
||||
mp_ptr mpz_limbs_write (mpz_t, mp_size_t);
|
||||
void mpz_limbs_finish (mpz_t, mp_size_t);
|
||||
mpz_srcptr mpz_roinit_n (mpz_t, mp_srcptr, mp_size_t);
|
||||
|
||||
#define MPZ_ROINIT_N(xp, xs) {{0, (xs),(xp) }}
|
||||
|
||||
void mpz_set_si (mpz_t, intMpz);
|
||||
void mpz_set_ui (mpz_t, uIntMpz);
|
||||
void mpz_set (mpz_t, const mpz_t);
|
||||
void mpz_set_d (mpz_t, double);
|
||||
|
||||
void mpz_init_set_si (mpz_t, intMpz);
|
||||
void mpz_init_set_ui (mpz_t, uIntMpz);
|
||||
void mpz_init_set (mpz_t, const mpz_t);
|
||||
void mpz_init_set_d (mpz_t, double);
|
||||
|
||||
size_t mpz_sizeinbase (const mpz_t, int);
|
||||
char *mpz_get_str (char *, int, const mpz_t);
|
||||
int mpz_set_str (mpz_t, const char *, int);
|
||||
int mpz_init_set_str (mpz_t, const char *, int);
|
||||
|
||||
/* This long list taken from gmp.h. */
|
||||
/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4,
|
||||
<iostream> defines EOF but not FILE. */
|
||||
#if defined (FILE) \
|
||||
|| defined (H_STDIO) \
|
||||
|| defined (_H_STDIO) /* AIX */ \
|
||||
|| defined (_STDIO_H) /* glibc, Sun, SCO */ \
|
||||
|| defined (_STDIO_H_) /* BSD, OSF */ \
|
||||
|| defined (__STDIO_H) /* Borland */ \
|
||||
|| defined (__STDIO_H__) /* IRIX */ \
|
||||
|| defined (_STDIO_INCLUDED) /* HPUX */ \
|
||||
|| defined (__dj_include_stdio_h_) /* DJGPP */ \
|
||||
|| defined (_FILE_DEFINED) /* Microsoft */ \
|
||||
|| defined (__STDIO__) /* Apple MPW MrC */ \
|
||||
|| defined (_MSL_STDIO_H) /* Metrowerks */ \
|
||||
|| defined (_STDIO_H_INCLUDED) /* QNX4 */ \
|
||||
|| defined (_ISO_STDIO_ISO_H) /* Sun C++ */ \
|
||||
|| defined (__STDIO_LOADED) /* VMS */
|
||||
size_t mpz_out_str (FILE *, int, const mpz_t);
|
||||
#endif
|
||||
|
||||
void mpz_import (mpz_t, size_t, int, size_t, int, size_t, const void *);
|
||||
void *mpz_export (void *, size_t *, int, size_t, int, size_t, const mpz_t);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* MINI_GMP */
|
|
@ -1,21 +0,0 @@
|
|||
//#
|
||||
//# Copyright (C) 2018-2019 QuasarApp.
|
||||
//# Distributed under the lgplv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
#ifndef MINIGMP_GLOBAL_H
|
||||
#define MINIGMP_GLOBAL_H
|
||||
|
||||
#ifdef _WIN32
|
||||
# define MINIGMPSHARED_EXPORT __declspec(dllexport)
|
||||
#endif
|
||||
|
||||
#ifdef linux
|
||||
# define MINIGMPSHARED_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif //MINIGMP_GLOBAL_H
|
|
@ -1,165 +0,0 @@
|
|||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
|
@ -1,403 +0,0 @@
|
|||
//#
|
||||
//# Copyright (C) 2018-2019 QuasarApp.
|
||||
//# Distributed under the lgplv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
#include "qrsaencryption.h"
|
||||
|
||||
#include <QString>
|
||||
#include <iostream>
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
|
||||
#define KEY_GEN_LIMIT 10
|
||||
|
||||
const QString SIGN_MARKER = "-SIGN-";
|
||||
const int signMarkerLength = SIGN_MARKER.length();
|
||||
|
||||
QRSAEncryption::INT eulerFunc(const QRSAEncryption::INT &p, const QRSAEncryption::INT &q) {
|
||||
return (p - 1) * (q - 1);
|
||||
}
|
||||
|
||||
bool QRSAEncryption::isMutuallyPrime(const INT &a, const INT &b) {
|
||||
if ( (!(a % 2) && !(b % 2))
|
||||
|| (!(a % 3) && !(b % 3))
|
||||
|| (!(a % 5) && !(b % 5))
|
||||
|| (!(a % 7) && !(b % 7))
|
||||
) return false;
|
||||
|
||||
return INT().gcd(a, b) == 1;
|
||||
}
|
||||
|
||||
QRSAEncryption::Rsa QRSAEncryption::getBitsSize(const INT &i) const {
|
||||
int rsaBits = RSA_64;
|
||||
int intBits = i.sizeBits();
|
||||
|
||||
while (rsaBits < intBits) {
|
||||
rsaBits *= 2;
|
||||
}
|
||||
|
||||
return static_cast<QRSAEncryption::Rsa>(rsaBits);
|
||||
|
||||
}
|
||||
|
||||
QRSAEncryption::Rsa QRSAEncryption::getBitsSize(const QByteArray &key) const {
|
||||
if (isValidRsaKey(key)) {
|
||||
return static_cast<QRSAEncryption::Rsa>(key.size() * 4);
|
||||
}
|
||||
|
||||
return QRSAEncryption::Rsa::Invalid;
|
||||
}
|
||||
|
||||
QRSAEncryption::INT QRSAEncryption::fromArray(const QByteArray &array) const {
|
||||
INT res = 0;
|
||||
res.fromHex(array.toHex().toStdString());
|
||||
return res;
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::toArray(const INT &i, short sizeBlok) {
|
||||
QByteArray res;
|
||||
res = QByteArray::fromHex(QByteArray::fromStdString(i.getString(16)));
|
||||
|
||||
if (sizeBlok < 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
while (res.size() < sizeBlok) {
|
||||
res.push_front(char(0));
|
||||
}
|
||||
|
||||
return res.left(sizeBlok);
|
||||
}
|
||||
|
||||
QRSAEncryption::INT QRSAEncryption::randomNumber(bool fullFill) const {
|
||||
|
||||
srand(std::chrono::duration_cast<std::chrono::nanoseconds>
|
||||
(std::chrono::system_clock::now().time_since_epoch()).count()
|
||||
% std::numeric_limits<int>::max());
|
||||
|
||||
INT res{1};
|
||||
|
||||
if(fullFill) {
|
||||
|
||||
while(res.longBits() < _rsa) {
|
||||
res *= (rand() % (std::numeric_limits<int>::max() - 1)) + 1;
|
||||
}
|
||||
} else {
|
||||
|
||||
int longDiff = _rsa / (sizeof (int) * 8);
|
||||
|
||||
while (longDiff > 0) {
|
||||
longDiff--;
|
||||
res *= (rand() % (std::numeric_limits<int>::max() - 1)) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
QRSAEncryption::INT QRSAEncryption::toPrime(INT n) const {
|
||||
if (!(n % 2)) {
|
||||
++n;
|
||||
}
|
||||
|
||||
INT LN = n;
|
||||
INT RN = n;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (LN.isPrime(false)) return LN;
|
||||
|
||||
RN+=2;
|
||||
|
||||
if (RN.isPrime(false)) return RN;
|
||||
LN-=2;
|
||||
}
|
||||
}
|
||||
|
||||
QRSAEncryption::INT QRSAEncryption::randomPrimeNumber(INT no) const {
|
||||
srand(static_cast<unsigned int>(time(nullptr)));
|
||||
|
||||
// max INT
|
||||
INT max('1', _rsa / 2, 2);
|
||||
|
||||
auto p = toPrime(randomNumber() % max);
|
||||
while(p == no) p = toPrime(randomNumber() % max);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
QRSAEncryption::INT QRSAEncryption::extEuclid(INT a, INT b) const {
|
||||
INT x = 0, y = 1, u = 1, v = 0, gcd = b, m, n, q, r;
|
||||
while (a != 0) {
|
||||
q = gcd / a;
|
||||
r = gcd % a;
|
||||
m = x - u * q;
|
||||
n = y - v * q;
|
||||
gcd = a;
|
||||
a = r;
|
||||
x = u;
|
||||
y = v;
|
||||
u = m;
|
||||
v = n;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
short QRSAEncryption::getBlockSize(INT i) const {
|
||||
return static_cast<short>(i.longBytes()) - 1;
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::encodeBlok(const INT &block, const INT &e, const INT &m, short blockSize) {
|
||||
|
||||
return toArray(INT::powm(block, e, m), blockSize);
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::decodeBlok(const INT &block, const INT &d, const INT &m, short blockSize) {
|
||||
|
||||
return toArray(INT::powm(block, d, m), blockSize);
|
||||
}
|
||||
|
||||
QRSAEncryption::QRSAEncryption(Rsa rsa) {
|
||||
_rsa = rsa;
|
||||
}
|
||||
|
||||
bool QRSAEncryption::generatePairKeyS(QByteArray &pubKey, QByteArray &privKey, QRSAEncryption::Rsa rsa) {
|
||||
qWarning() << "method " << Q_FUNC_INFO <<
|
||||
" will be deleted in newxt version. please use generatePairKey method";
|
||||
return generatePairKey(pubKey, privKey, rsa);
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::encodeS(const QByteArray &rawData, const QByteArray &pubKey, QRSAEncryption::Rsa rsa, QRSAEncryption::BlockSize blockSizeMode) {
|
||||
qWarning() << "method " << Q_FUNC_INFO <<
|
||||
" will be deleted in newxt version. please use encode method";
|
||||
return encode(rawData, pubKey, rsa, blockSizeMode);
|
||||
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::decodeS(const QByteArray &rawData, const QByteArray &privKey, QRSAEncryption::Rsa rsa, QRSAEncryption::BlockSize blockSizeMode) {
|
||||
qWarning() << "method " << Q_FUNC_INFO <<
|
||||
" will be deleted in newxt version. please use decode method";
|
||||
return decode(rawData, privKey, rsa, blockSizeMode);
|
||||
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::signMessageS(QByteArray rawData, const QByteArray &privKey, QRSAEncryption::Rsa rsa) {
|
||||
qWarning() << "method " << Q_FUNC_INFO <<
|
||||
" will be deleted in newxt version. please use signMessage method";
|
||||
return signMessage(rawData, privKey, rsa);
|
||||
|
||||
}
|
||||
|
||||
bool QRSAEncryption::checkSignMessageS(const QByteArray &rawData, const QByteArray &pubKey, QRSAEncryption::Rsa rsa) {
|
||||
qWarning() << "method " << Q_FUNC_INFO <<
|
||||
" will be deleted in newxt version. please use signMessage method";
|
||||
return checkSignMessage(rawData, pubKey, rsa);
|
||||
}
|
||||
|
||||
unsigned int QRSAEncryption::getKeyBytesSize(QRSAEncryption::Rsa rsa) {
|
||||
|
||||
return rsa / 4;
|
||||
}
|
||||
|
||||
// --- static methods ---
|
||||
bool QRSAEncryption::generatePairKey(QByteArray &pubKey, QByteArray &privKey,
|
||||
QRSAEncryption::Rsa rsa) {
|
||||
|
||||
return QRSAEncryption(rsa).generatePairKey(pubKey, privKey);
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::encode(const QByteArray &rawData, const QByteArray &pubKey,
|
||||
Rsa rsa, BlockSize blockSizeMode) {
|
||||
|
||||
return QRSAEncryption(rsa).encode(rawData, pubKey, blockSizeMode);
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::decode(const QByteArray &rawData, const QByteArray &privKey,
|
||||
Rsa rsa, BlockSize blockSizeMode) {
|
||||
|
||||
return QRSAEncryption(rsa).decode(rawData, privKey, blockSizeMode);
|
||||
}
|
||||
|
||||
QByteArray QRSAEncryption::signMessage(QByteArray rawData, const QByteArray &privKey, Rsa rsa) {
|
||||
|
||||
return QRSAEncryption(rsa).signMessage(rawData, privKey);
|
||||
}
|
||||
|
||||
bool QRSAEncryption::checkSignMessage(const QByteArray &rawData, const QByteArray &pubKey, Rsa rsa) {
|
||||
|
||||
return QRSAEncryption(rsa).checkSignMessage(rawData, pubKey);
|
||||
}
|
||||
|
||||
// --- end of static methods ---
|
||||
|
||||
bool QRSAEncryption::generatePairKey(QByteArray &pubKey, QByteArray &privKey) {
|
||||
|
||||
int cnt{0};
|
||||
bool keyGenRes{false};
|
||||
INT p, q, modul, eilor, e, d;
|
||||
do {
|
||||
|
||||
pubKey.clear();
|
||||
privKey.clear();
|
||||
|
||||
p = randomPrimeNumber();
|
||||
q = randomPrimeNumber(p);
|
||||
|
||||
modul = 0;
|
||||
while ((modul = p * q) < 0) {
|
||||
p = toPrime((p - 1) / 2);
|
||||
}
|
||||
|
||||
eilor = eulerFunc(p, q);
|
||||
e = randomNumber() % eilor;
|
||||
|
||||
if (!(e % 2)) --e;
|
||||
|
||||
do {
|
||||
e -= 2;
|
||||
} while((!isMutuallyPrime(eilor, e)));
|
||||
|
||||
d = extEuclid(eilor , e);
|
||||
|
||||
while(d < 0 ) {
|
||||
d += eilor;
|
||||
}
|
||||
|
||||
pubKey.append(toArray(e, _rsa / 8));
|
||||
pubKey.append(toArray(modul, _rsa / 8));
|
||||
privKey.append(toArray(d, _rsa / 8));
|
||||
privKey.append(toArray(modul, _rsa / 8));
|
||||
|
||||
} while (!(keyGenRes = testKeyPair(pubKey, privKey)) && (++cnt < KEY_GEN_LIMIT));
|
||||
|
||||
if(cnt >= KEY_GEN_LIMIT) qWarning() << QString("(Warning): Exceeded limit of key generation (%0)!").arg(KEY_GEN_LIMIT);
|
||||
|
||||
return (keyGenRes && cnt < KEY_GEN_LIMIT);
|
||||
}
|
||||
|
||||
// --- non-static methods ---
|
||||
QByteArray QRSAEncryption::encode(const QByteArray &rawData, const QByteArray &pubKey, BlockSize blockSizeMode) {
|
||||
|
||||
if (getBitsSize(pubKey) != _rsa) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
|
||||
QByteArray block;
|
||||
|
||||
INT e = fromArray(pubKey.mid(0, pubKey.size() / 2));
|
||||
INT m = fromArray(pubKey.mid(pubKey.size() / 2));
|
||||
|
||||
short blockSizeOut = getBlockSize(m) + 1; // BlockSize::OneByte
|
||||
short blockSizeIn = 1; // BlockSize::OneByte
|
||||
|
||||
if (blockSizeMode == BlockSize::Auto) {
|
||||
blockSizeIn = getBlockSize(m);
|
||||
}
|
||||
|
||||
if (!blockSizeIn) {
|
||||
qDebug() << "module of key small! size = 1 byte, 2 byte is minimum";
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray res;
|
||||
|
||||
while ((block = rawData.mid(index, blockSizeIn)).size()) {
|
||||
|
||||
if (index + blockSizeIn > rawData.size() && block.size() && !block[0]) {
|
||||
qWarning() << "When trying to encrypt data, problems arose, the last block contains non-significant zeros."
|
||||
" These zeros will be deleted during the decryption process."
|
||||
" For encode and decode data with non-significant zeros use BlockSize::OneByte";
|
||||
}
|
||||
|
||||
res.append(encodeBlok(fromArray(block), e, m, blockSizeOut));
|
||||
index += blockSizeIn;
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
QByteArray QRSAEncryption::decode(const QByteArray &rawData, const QByteArray &privKey, BlockSize blockSizeMode) {
|
||||
|
||||
if (getBitsSize(privKey) != _rsa) {
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
|
||||
QByteArray block;
|
||||
|
||||
INT d = fromArray(privKey.mid(0, privKey.size() / 2));
|
||||
INT m = fromArray(privKey.mid(privKey.size() / 2));
|
||||
|
||||
short blockSizeIn = getBlockSize(m) + 1;
|
||||
|
||||
short blockSizeOut = 1; // BlockSize::OneByte
|
||||
if (blockSizeMode == BlockSize::Auto) {
|
||||
blockSizeOut = getBlockSize(m);
|
||||
}
|
||||
|
||||
QByteArray res;
|
||||
while ((block = rawData.mid(index, blockSizeIn)).size()) {
|
||||
bool isLastBlock = (index + blockSizeIn) >= rawData.size();
|
||||
|
||||
res.append(decodeBlok(fromArray(block), d, m,
|
||||
(isLastBlock && blockSizeMode == BlockSize::Auto)? -1 : blockSizeOut));
|
||||
index += blockSizeIn;
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
QByteArray QRSAEncryption::signMessage(QByteArray rawData, const QByteArray &privKey) {
|
||||
|
||||
QByteArray hash = QCryptographicHash::hash(rawData, HashAlgorithm::Sha256);
|
||||
|
||||
QByteArray signature = encode(hash, privKey, BlockSize::OneByte);
|
||||
|
||||
rawData.append(SIGN_MARKER + signature.toHex() + SIGN_MARKER);
|
||||
|
||||
return rawData;
|
||||
}
|
||||
bool QRSAEncryption::checkSignMessage(const QByteArray &rawData, const QByteArray &pubKey) {
|
||||
|
||||
// start position of SIGN_MARKER in rawData
|
||||
auto signStartPos = rawData.lastIndexOf(SIGN_MARKER, rawData.length() - signMarkerLength - 1);
|
||||
|
||||
// length of signature in rawData
|
||||
auto signLength = rawData.length() - signStartPos - signMarkerLength * 2;
|
||||
|
||||
// message, that was recieved from channel
|
||||
QByteArray message = rawData.left(signStartPos);
|
||||
|
||||
// hash, that was decrypt from recieved signature
|
||||
QByteArray recievedHash = decode(QByteArray::fromHex(rawData.mid(signStartPos + signMarkerLength, signLength)),
|
||||
pubKey, BlockSize::OneByte);
|
||||
|
||||
// if recievedHash == hashAlgorithm(recived message), then signed message is valid
|
||||
return recievedHash == QCryptographicHash::hash(message, HashAlgorithm::Sha256);
|
||||
}
|
||||
|
||||
QRSAEncryption::Rsa QRSAEncryption::getRsa() const {
|
||||
return _rsa;
|
||||
}
|
||||
|
||||
bool QRSAEncryption::testKeyPair(const QByteArray &pubKey, const QByteArray &privKey) {
|
||||
|
||||
QByteArray tesVal = "Test message of encrypkey";
|
||||
|
||||
bool result = tesVal == decode(encode(tesVal, pubKey), privKey);
|
||||
|
||||
if (!result) qWarning() << "(Warning): Testkey Fail, try generate new key pair!";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// --- end of non-static methods ---
|
||||
|
||||
bool QRSAEncryption::isValidRsaKey(const QByteArray &key) {
|
||||
return key.size() && ((static_cast<unsigned int>(key.size()) % getKeyBytesSize(RSA_64)) == 0);
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
//#
|
||||
//# Copyright (C) 2018-2019 QuasarApp.
|
||||
//# Distributed under the lgplv3 software license, see the accompanying
|
||||
//# Everyone is permitted to copy and distribute verbatim copies
|
||||
//# of this license document, but changing it is not allowed.
|
||||
//#
|
||||
|
||||
#ifndef QRSAENCRYPTION_H
|
||||
#define QRSAENCRYPTION_H
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QFile>
|
||||
#include <cmath>
|
||||
#include <QDebug>
|
||||
#include <QCryptographicHash> // to use sha256
|
||||
#include "./../qtsecret_global.h"
|
||||
|
||||
#include <bigint.h>
|
||||
|
||||
|
||||
class Qt_SECRETSHARED_EXPORT QRSAEncryption
|
||||
{
|
||||
public:
|
||||
typedef BigInt INT;
|
||||
typedef QCryptographicHash::Algorithm HashAlgorithm;
|
||||
|
||||
enum Rsa {
|
||||
Invalid = 0,
|
||||
RSA_64 = 64,
|
||||
RSA_128 = 128,
|
||||
RSA_256 = 256,
|
||||
RSA_512 = 512,
|
||||
RSA_1024 = 1024,
|
||||
RSA_2048 = 2048,
|
||||
RSA_4096 = 4096,
|
||||
RSA_8192 = 8192,
|
||||
|
||||
};
|
||||
|
||||
enum BlockSize {
|
||||
Auto = 0, // fast but not stable. (using by default)
|
||||
OneByte = 1 // stable but slow. (using for sig and check sig messages)
|
||||
};
|
||||
|
||||
|
||||
QRSAEncryption(Rsa rsa = Rsa::RSA_256);
|
||||
|
||||
// static methods
|
||||
|
||||
// OLDMETHODS DELETE IN next Version
|
||||
static bool generatePairKeyS(QByteArray &pubKey, QByteArray &privKey,
|
||||
QRSAEncryption::Rsa rsa = RSA_256);
|
||||
static QByteArray encodeS(const QByteArray &rawData, const QByteArray &pubKey,
|
||||
Rsa rsa = RSA_256, BlockSize blockSizeMode = BlockSize::Auto);
|
||||
static QByteArray decodeS(const QByteArray &rawData, const QByteArray &privKey,
|
||||
Rsa rsa = RSA_256, BlockSize blockSizeMode = BlockSize::Auto);
|
||||
static QByteArray signMessageS(QByteArray rawData, const QByteArray &privKey,
|
||||
Rsa rsa = RSA_256);
|
||||
static bool checkSignMessageS(const QByteArray &rawData, const QByteArray &pubKey,
|
||||
Rsa rsa);
|
||||
// OLDMETHODS END
|
||||
|
||||
static bool generatePairKey(QByteArray &pubKey, QByteArray &privKey,
|
||||
QRSAEncryption::Rsa rsa);
|
||||
static QByteArray encode(const QByteArray &rawData, const QByteArray &pubKey,
|
||||
Rsa rsa, BlockSize blockSizeMode = BlockSize::Auto);
|
||||
static QByteArray decode(const QByteArray &rawData, const QByteArray &privKey,
|
||||
Rsa rsa, BlockSize blockSizeMode = BlockSize::Auto);
|
||||
static QByteArray signMessage(QByteArray rawData, const QByteArray &privKey,
|
||||
Rsa rsa);
|
||||
static bool checkSignMessage(const QByteArray &rawData, const QByteArray &pubKey,
|
||||
Rsa rsa);
|
||||
static bool isValidRsaKey(const QByteArray& key);
|
||||
static unsigned int getKeyBytesSize(QRSAEncryption::Rsa rsa);
|
||||
|
||||
// non-static methods
|
||||
bool generatePairKey(QByteArray &pubKey, QByteArray &privKey);
|
||||
|
||||
QByteArray encode(const QByteArray &rawData, const QByteArray &pubKey,
|
||||
BlockSize blockSizeMode = BlockSize::Auto);
|
||||
|
||||
QByteArray decode(const QByteArray &rawData, const QByteArray &privKey,
|
||||
BlockSize blockSizeMode = BlockSize::Auto);
|
||||
|
||||
QByteArray signMessage(QByteArray rawData, const QByteArray &privKey);
|
||||
|
||||
bool checkSignMessage(const QByteArray &rawData, const QByteArray &pubKey);
|
||||
|
||||
Rsa getRsa() const;
|
||||
|
||||
private:
|
||||
|
||||
Rsa _rsa;
|
||||
|
||||
bool testKeyPair(const QByteArray &pubKey, const QByteArray &privKey);
|
||||
bool isMutuallyPrime(const INT &a, const INT &b);
|
||||
Rsa getBitsSize(const INT& i) const;
|
||||
Rsa getBitsSize(const QByteArray& array) const;
|
||||
|
||||
INT fromArray(const QByteArray& array) const;
|
||||
QByteArray toArray(const INT &i, short sizeBlok = -1);
|
||||
INT randomNumber(bool fullFilled = true) const;
|
||||
INT toPrime(INT) const;
|
||||
INT randomPrimeNumber(INT no = 0) const;
|
||||
INT extEuclid(INT a, INT b) const;
|
||||
|
||||
short getBlockSize(INT i) const;
|
||||
|
||||
QByteArray encodeBlok(const INT& block, const INT& e, const INT& m, short blockSize);
|
||||
QByteArray decodeBlok(const INT& block, const INT& d, const INT& m, short blockSize);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // QRSAENCRYPTION_H
|
|
@ -1,24 +0,0 @@
|
|||
#
|
||||
# Copyright (C) 2018-2019 QuasarApp.
|
||||
# Distributed under the lgplv3 software license, see the accompanying
|
||||
# Everyone is permitted to copy and distribute verbatim copies
|
||||
# of this license document, but changing it is not allowed.
|
||||
#
|
||||
|
||||
!isEmpty(Qt_SECRET_LIB):error("Qt-Secret.pri already included")
|
||||
Qt_SECRET_LIB = 1
|
||||
|
||||
DEFINES += Qt_SECRET_LIBRARY
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/qtsecret_global.h \
|
||||
$$PWD/Qt-RSA/qrsaencryption.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/Qt-RSA/qrsaencryption.cpp
|
||||
|
||||
|
||||
INCLUDEPATH += $$PWD $$PWD/Qt-RSA
|
||||
|
||||
include($$PWD/GMP/GMP.pri)
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef QTSECRET_GLOBAL_H
|
||||
#define QTSECRET_GLOBAL_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#if defined(Qt_SECRET_LIBRARY)
|
||||
# define Qt_SECRETSHARED_EXPORT Q_DECL_EXPORT
|
||||
#else
|
||||
# define Qt_SECRETSHARED_EXPORT Q_DECL_IMPORT
|
||||
#endif
|
||||
|
||||
#endif // QTSECRET_GLOBAL_H
|
|
@ -17,31 +17,44 @@ ScStwLibraries_ClientLibs {
|
|||
DEFINES += ScStwLibraries_ClientLibs
|
||||
}
|
||||
|
||||
ScStwLibraries_Raspi {
|
||||
LIBS += -lasound
|
||||
DEFINES += ScStwLibraries_Raspi
|
||||
}
|
||||
|
||||
INCLUDEPATH += $$PWD/headers $$PWD
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/sources/ScStw.cpp \
|
||||
$$PWD/sources/scstwsettings.cpp \
|
||||
$$PWD/sources/scstwsoundplayer.cpp \
|
||||
$$PWD/sources/scstwlibraries.cpp \
|
||||
$$PWD/sources/scstwrace.cpp \
|
||||
$$PWD/sources/scstwtimer.cpp
|
||||
$$PWD/sources/scstwtimer.cpp \
|
||||
$$PWD/sources/scstwsetting.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/headers/ScStw.hpp \
|
||||
$$PWD/headers/ScStwLibraries_global.h \
|
||||
$$PWD/headers/scstwlibraries.h \
|
||||
$$PWD/headers/scstwrace.h \
|
||||
$$PWD/headers/scstwsettings.h \
|
||||
$$PWD/headers/scstwsoundplayer.h \
|
||||
$$PWD/headers/scstwtimer.h
|
||||
$$PWD/headers/scstwtimer.h \
|
||||
$$PWD/headers/scstwsetting.h
|
||||
|
||||
ScStwLibraries_ClientLibs {
|
||||
SOURCES += \
|
||||
$$PWD/sources/client/scstwclient.cpp \
|
||||
$$PWD/sources/client/scstwremotemonitorrace.cpp
|
||||
$$PWD/sources/client/scstwremoterace.cpp \
|
||||
$$PWD/sources/client/scstwremotetimer.cpp \
|
||||
$$PWD/sources/client/scstwremotesettings.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/headers/client/scstwclient.h \
|
||||
$$PWD/headers/client/scstwremotemonitorrace.h
|
||||
$$PWD/headers/client/scstwremoterace.h \
|
||||
$$PWD/headers/client/scstwremotetimer.h \
|
||||
$$PWD/headers/client/scstwremotesettings.h
|
||||
|
||||
INCLUDEPATH += $$PWD/headers/client
|
||||
}
|
||||
|
|
|
@ -61,28 +61,12 @@ public:
|
|||
RaceStateChanged = 9000,
|
||||
TimersChanged = 9001,
|
||||
ExtensionsChanged = 9002,
|
||||
NextStartActionChanged = 9003 /*, ProfilesChanged*/
|
||||
CurrentStartDelayChanged = 9003, /*, ProfilesChanged*/
|
||||
SettingChanged = 9004,
|
||||
RaceDetailsChanged = 9005
|
||||
};
|
||||
Q_ENUM(SignalKey)
|
||||
|
||||
/*!
|
||||
* \brief The BaseStationSetting enum contains all settings of the base station that can be changed by a client
|
||||
*
|
||||
* \see ScStw::baseStationSettingFromInt()
|
||||
* \see ScStw::baseStationSettingToString()
|
||||
* \see ScStw::baseStationSettingFromString()
|
||||
* \see ScStw::baseStationSettings
|
||||
*/
|
||||
enum BaseStationSetting {
|
||||
InvalidSetting = -1,
|
||||
ReadySoundEnableSetting,
|
||||
ReadySoundDelaySetting,
|
||||
AtYourMarksSoundEnableSetting,
|
||||
AtYourMarksSoundDelaySetting,
|
||||
SoundVolumeSetting
|
||||
};
|
||||
Q_ENUM(BaseStationSetting)
|
||||
|
||||
/*!
|
||||
* \brief The SocketCommand enum contains all commands the base station can handle
|
||||
*
|
||||
|
@ -93,15 +77,17 @@ public:
|
|||
|
||||
InitializeSessionCommand = 1,
|
||||
|
||||
StartTimersCommand = 1000,
|
||||
StopTimersCommand = 1001,
|
||||
ResetTimersCommand = 1002,
|
||||
StartRaceCommand = 1000,
|
||||
StopRaceCommand = 1001,
|
||||
ResetRaceCommand = 1002,
|
||||
CancelRaceCommand = 1003,
|
||||
SetTimerDisabledCommand = 1004,
|
||||
|
||||
GetRaceStateCommand = 2000,
|
||||
GetNextStartActionCommand = 2005,
|
||||
GetRaceDetailsCommand = 2001,
|
||||
GetExtensionsCommand = 2006,
|
||||
GetTimersCommand = 2007,
|
||||
GetNextStartActionDetailsCommand = 2009,
|
||||
GetCurrentStartDelayCommand = 2009,
|
||||
|
||||
WriteSettingCommand = 3000,
|
||||
ReadSettingCommand = 3001,
|
||||
|
@ -126,15 +112,16 @@ public:
|
|||
|
||||
FirmwareAlreadyUpToDateInfo = 304,
|
||||
|
||||
|
||||
CommandNotFoundError = 404,
|
||||
ClientSessionAlreadyActiveError = 407,
|
||||
UpdateSignatureInvalidError = 402,
|
||||
TimestampTooSmallError = 406,
|
||||
RequiredParameterNotGivenError = 405,
|
||||
CurrentStateNotVaildForOperationError = 403,
|
||||
AccessDeniedError = 401,
|
||||
UpdateSignatureInvalidError = 402,
|
||||
CurrentStateNotVaildForOperationError = 403,
|
||||
CommandNotFoundError = 404,
|
||||
RequiredParameterNotGivenError = 405,
|
||||
TimestampTooSmallError = 406,
|
||||
ClientSessionAlreadyActiveError = 407,
|
||||
NoSessionActiveError = 408,
|
||||
ItemNotFoundError = 409,
|
||||
LastTimerCannotBeDisabledError = 410,
|
||||
|
||||
UpdateFailedError = 500,
|
||||
|
||||
|
@ -143,10 +130,59 @@ public:
|
|||
TimeoutError = 911,
|
||||
SettingNotAccessibleError = 901,
|
||||
InternalError = 950,
|
||||
InternalErrorTimerOperationFailed = 951
|
||||
InternalErrorTimerOperationFailed = 951,
|
||||
ApiVersionNotSupportedError = 952,
|
||||
CompetitionModeProhibitsThisError = 953,
|
||||
FirmwareUpdateFormatInvalidError = 954,
|
||||
TimersNotReadyError = 501 /*!< One or more timer is not ready */
|
||||
};
|
||||
Q_ENUM(ScStw::StatusCode)
|
||||
|
||||
/*!
|
||||
* \brief The ExtensionType enum contains all types of extensions
|
||||
*/
|
||||
enum ExtensionType {
|
||||
StartPad,
|
||||
TopPad
|
||||
};
|
||||
Q_ENUM(ExtensionType);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief The ExtensionState enum contains all possible states of an extension
|
||||
*/
|
||||
enum ExtensionState {
|
||||
ExtensionDisconnected = 0,
|
||||
ExtensionConnecting = 1,
|
||||
ExtensionInitialising = 2,
|
||||
ExtensionConnected = 3
|
||||
};
|
||||
Q_ENUM(ExtensionState);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief The ExtensionBatteryState enum contains all possible battery states of an extension
|
||||
*/
|
||||
enum ExtensionBatteryState {
|
||||
BatteryUnknown = -1,
|
||||
BatteryCritical = 0,
|
||||
BatteryWarning = 1,
|
||||
BatteryFine = 2,
|
||||
BatteryCharging = 3,
|
||||
BatteryNotCharging = 4
|
||||
};
|
||||
Q_ENUM(ExtensionBatteryState);
|
||||
|
||||
/*!
|
||||
* \brief The PadState enum contains whether a pad is currently pressed or not
|
||||
*/
|
||||
enum PadState {
|
||||
PadNotPressed = 0,
|
||||
PadPressed = 1
|
||||
};
|
||||
Q_ENUM(PadState);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief SOCKET_MESSAGE_START_KEY contains the key, a message is supposed to start with
|
||||
*/
|
||||
|
@ -157,44 +193,6 @@ public:
|
|||
*/
|
||||
static const char* SOCKET_MESSAGE_END_KEY;
|
||||
|
||||
/*!
|
||||
* \brief baseStationSettings contains a string with reference to all BaseStationSetting values
|
||||
*
|
||||
* \see ScStw::BaseStationSetting
|
||||
* \see ScStw::baseStationSettingToString()
|
||||
* \see ScStw::baseStationSettingFromString()
|
||||
*/
|
||||
static const QMap<QString, ScStw::BaseStationSetting> baseStationSettings;
|
||||
|
||||
/*!
|
||||
* \brief Function to convert an int to a BaseStationSetting
|
||||
* \param i the int to convert
|
||||
* \return a BaseStationSetting
|
||||
*
|
||||
* \see ScStw::BaseStationSetting
|
||||
*/
|
||||
static BaseStationSetting baseStationSettingfromInt(int i);
|
||||
|
||||
/*!
|
||||
* \brief Function to convert a QString to a BaseStationSetting
|
||||
* \param s the string to convert
|
||||
* \return a BaseStationSetting
|
||||
*
|
||||
* \see ScStw::BaseStationSetting
|
||||
* \see ScStw::baseStationSettingToString()
|
||||
*/
|
||||
static BaseStationSetting baseStationSettingFromString(QString s);
|
||||
|
||||
/*!
|
||||
* \brief Function to convert BaseStationSetting to a QString
|
||||
* \param s the BaseStationSetting to convert
|
||||
* \return a QString
|
||||
*
|
||||
* \see ScStw::BaseStationSetting
|
||||
* \see ScStw::baseStationSettingFromString()
|
||||
*/
|
||||
Q_INVOKABLE static QString baseStationSettingToString(BaseStationSetting s);
|
||||
|
||||
/*!
|
||||
* \brief Function to convert an int to a SignalKey
|
||||
* \param i the int to convert
|
||||
|
@ -213,6 +211,15 @@ public:
|
|||
*/
|
||||
static SocketCommand socketCommandFromInt(int i);
|
||||
|
||||
/*!
|
||||
* \brief Function to convert an ExtensionType to a string
|
||||
* \param t the ExtensionType to convert
|
||||
* \return String
|
||||
*
|
||||
* \see ScStwExtensionType
|
||||
*/
|
||||
static QString extensionTypeToString(ExtensionType t);
|
||||
|
||||
/*!
|
||||
* \brief Function to compare to string firmware versions in <major>.<minor>.<patch> formar
|
||||
* \param a version a
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <QByteArray>
|
||||
|
||||
#include "ScStw.hpp"
|
||||
#include "scstwsettings.h"
|
||||
|
||||
/*!
|
||||
* This class is used to connect and talk to the ScStw basestation.
|
||||
|
@ -50,7 +51,7 @@ class ScStwClient : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(State state READ getState NOTIFY stateChanged)
|
||||
Q_PROPERTY(QVariantList extensions READ getExtensions NOTIFY extensionsChanged)
|
||||
Q_PROPERTY(QVariantMap extensions READ getExtensions NOTIFY extensionsChanged)
|
||||
Q_PROPERTY(QString ipAddress READ getIP WRITE setIP)
|
||||
|
||||
public:
|
||||
|
@ -59,7 +60,10 @@ public:
|
|||
*
|
||||
* \brief ScStwClient
|
||||
*/
|
||||
explicit ScStwClient(QObject *parent = nullptr);
|
||||
explicit ScStwClient(
|
||||
QObject *parent = nullptr,
|
||||
QList<ScStw::SignalKey> signalSubscriptions = {ScStw::ExtensionsChanged}
|
||||
);
|
||||
|
||||
enum State {DISCONNECTED, CONNECTING, INITIALISING, CONNECTED};
|
||||
Q_ENUM(State);
|
||||
|
@ -73,7 +77,9 @@ private:
|
|||
int errors;
|
||||
const static int ERRORS_UNTIL_DISCONNECT = 4;
|
||||
|
||||
QVariantList extensions;
|
||||
QVariantMap extensions;
|
||||
|
||||
QList<ScStw::SignalKey> signalSubscriptions;
|
||||
|
||||
//---general status values---//
|
||||
|
||||
|
@ -95,15 +101,14 @@ private:
|
|||
|
||||
QString readBuffer;
|
||||
|
||||
int nextConnectionId;
|
||||
unsigned int currentRequestId;
|
||||
|
||||
struct waitingRequest {
|
||||
int id;
|
||||
struct WaitingRequest {
|
||||
QEventLoop * loop;
|
||||
QJsonObject reply;
|
||||
};
|
||||
|
||||
QList<waitingRequest> waitingRequests;
|
||||
QMap<int, WaitingRequest> waitingRequests;
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -139,14 +144,14 @@ public slots:
|
|||
* \param value the value to write to
|
||||
* \return the status code returned by the command
|
||||
*/
|
||||
ScStw::StatusCode writeRemoteSetting(ScStw::BaseStationSetting key, QString value);
|
||||
ScStw::StatusCode writeRemoteSetting(ScStwSettings::BaseStationSetting key, QVariant value);
|
||||
|
||||
/*!
|
||||
* \brief Function to read a setting on the base station
|
||||
* \param key the key to read from
|
||||
* \return the value of the key or "false" if the key is not found or an error occured
|
||||
*/
|
||||
QString readRemoteSetting(ScStw::BaseStationSetting key);
|
||||
QVariant readRemoteSetting(ScStwSettings::BaseStationSetting key, ScStw::StatusCode* status = nullptr);
|
||||
|
||||
/*! Getter fuctions */
|
||||
|
||||
|
@ -167,7 +172,7 @@ public slots:
|
|||
* \brief Function to get the extensions and their state from the base station
|
||||
* \return a list with all configured extensions and their state
|
||||
*/
|
||||
QVariantList getExtensions();
|
||||
QVariantMap getExtensions();
|
||||
|
||||
/*!
|
||||
* \brief Function to get the time offset of the base station relative to the clients time
|
||||
|
@ -199,6 +204,8 @@ public slots:
|
|||
*/
|
||||
void setIP(QString ipAdress);
|
||||
|
||||
void addSignalSubscription(ScStw::SignalKey key);
|
||||
|
||||
private slots:
|
||||
/*!
|
||||
* \brief called when timeout timer times out
|
||||
|
@ -279,7 +286,7 @@ private slots:
|
|||
* \see gotSignal()
|
||||
* \param connections the list to set the chache to
|
||||
*/
|
||||
void setExtensions(QVariantList extensions);
|
||||
void setExtensions(QVariantMap extensions);
|
||||
|
||||
/*!
|
||||
* \brief Function to set the local state.
|
||||
|
|
86
ScStwLibraries/headers/client/scstwremoterace.h
Normal file
86
ScStwLibraries/headers/client/scstwremoterace.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SCSTWREMOTEMONITORRACE_H
|
||||
#define SCSTWREMOTEMONITORRACE_H
|
||||
|
||||
#include <QObject>
|
||||
#include "scstwrace.h"
|
||||
#include "scstwclient.h"
|
||||
#include "scstwremotetimer.h"
|
||||
#include "scstwsoundplayer.h"
|
||||
|
||||
class ScStwRemoteRace : public ScStwRace
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ScStwClient* scStwClient READ getScStwClient WRITE setScStwClient NOTIFY scStwClientChanged)
|
||||
|
||||
public:
|
||||
ScStwRemoteRace(QObject *parent = nullptr);
|
||||
ScStwRemoteRace(ScStwClient *scStwClient, ScStwSettings *settings = nullptr, QObject *parent = nullptr);
|
||||
|
||||
enum RaceMode {
|
||||
LOCAL,
|
||||
REMOTE
|
||||
};
|
||||
|
||||
protected:
|
||||
double currentStartTotalDelay;
|
||||
double currentStartDelayStartedAt;
|
||||
double latestStartDelayProgress;
|
||||
bool isReadyForNextState;
|
||||
bool readySoundEnabled;
|
||||
|
||||
private:
|
||||
ScStwClient *scStwClient;
|
||||
QList<ScStwRemoteTimer*> remoteTimers;
|
||||
QList<ScStwTimer*> localTimers;
|
||||
|
||||
public slots:
|
||||
ScStw::StatusCode start(bool asyncronous = true);
|
||||
ScStw::StatusCode cancel();
|
||||
ScStw::StatusCode stop();
|
||||
ScStw::StatusCode reset();
|
||||
ScStw::StatusCode setTimerDisabled(int id, bool disabled);
|
||||
bool addTimer(ScStwTimer *timer);
|
||||
QVariantMap getCurrentStartDelay();
|
||||
bool getIsReadyForNextState();
|
||||
bool getReadySoundEnabled();
|
||||
|
||||
ScStwClient *getScStwClient();
|
||||
void setScStwClient(ScStwClient *client);
|
||||
|
||||
private slots:
|
||||
void handleBaseStationSignal(ScStw::SignalKey key, QVariant data);
|
||||
|
||||
bool refreshRemoteTimers(QVariantList remoteTimers);
|
||||
void rebuildRemoteTimers(QVariantList remoteTimers);
|
||||
void refreshDetails(QVariantMap details);
|
||||
void handleClientStateChange();
|
||||
|
||||
void refreshCompetitionMode();
|
||||
RaceMode getMode();
|
||||
bool local();
|
||||
|
||||
void setTimers(QList<ScStwTimer*> timers, bool deleteOldTimers);
|
||||
|
||||
signals:
|
||||
void scStwClientChanged();
|
||||
};
|
||||
|
||||
#endif // SCSTWREMOTEMONITORRACE_H
|
62
ScStwLibraries/headers/client/scstwremotesettings.h
Normal file
62
ScStwLibraries/headers/client/scstwremotesettings.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SCSTWREMOTESETTINGS_H
|
||||
#define SCSTWREMOTESETTINGS_H
|
||||
|
||||
#include <QObject>
|
||||
#include "scstwsettings.h"
|
||||
#include "scstwclient.h"
|
||||
#include <QMetaEnum>
|
||||
|
||||
class ScStwRemoteSettings : public ScStwSettings
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ScStwClient* scStwClient READ getScStwClient WRITE setScStwClient NOTIFY scStwClientChanged)
|
||||
|
||||
public:
|
||||
ScStwRemoteSettings(QObject * parent = nullptr);
|
||||
ScStwRemoteSettings(ScStwClient * scStwClient, QObject * parent = nullptr);
|
||||
|
||||
enum SettingsMode {
|
||||
LOCAL,
|
||||
REMOTE
|
||||
};
|
||||
|
||||
protected:
|
||||
QVariant readSetting(QString key, int keyInt, int keyLevel);
|
||||
bool writeSetting(QString key, QVariant value, int keyInt,int keyLevel = -1);
|
||||
bool setDefaultSetting(QString key, QVariant defaultVariant, int keyInt,int keyLevel = -1);
|
||||
|
||||
private:
|
||||
ScStwClient * scStwClient;
|
||||
|
||||
public slots:
|
||||
ScStwClient *getScStwClient();
|
||||
void setScStwClient(ScStwClient *client);
|
||||
|
||||
private slots:
|
||||
void handleClientStateChange();
|
||||
void handleBaseStationSignal(ScStw::SignalKey key, QVariant data);
|
||||
SettingsMode getMode();
|
||||
|
||||
signals:
|
||||
void scStwClientChanged();
|
||||
};
|
||||
|
||||
#endif // SCSTWREMOTESETTINGS_H
|
79
ScStwLibraries/headers/client/scstwremotetimer.h
Normal file
79
ScStwLibraries/headers/client/scstwremotetimer.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef SCSTWREMOTETIMER_H
|
||||
#define SCSTWREMOTETIMER_H
|
||||
|
||||
#include <scstwtimer.h>
|
||||
#include <QObject>
|
||||
|
||||
class ScStwRemoteTimer : public ScStwTimer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScStwRemoteTimer(QObject *parent = nullptr);
|
||||
|
||||
friend class ScStwRemoteRace;
|
||||
|
||||
private:
|
||||
ScStwTimer::ReadyState readyState;
|
||||
|
||||
public slots:
|
||||
/*!
|
||||
* \brief Function to get the current ready status of a timer
|
||||
* \return The current ready status
|
||||
*/
|
||||
virtual ScStwTimer::ReadyState getReadyState();
|
||||
|
||||
protected slots:
|
||||
/*!
|
||||
* \brief Function to dircetly change the start time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param startTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the startTime was therefore not modified, true otherwise
|
||||
*/
|
||||
void setStartTime(double startTime);
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the stop time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param stopTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the stopTime was therefore not modified, true otherwise
|
||||
*/
|
||||
void setStopTime(double stopTime);
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the rection time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param reactionTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the reactionTime was therefore not modified, true otherwise
|
||||
*/
|
||||
void setReactionTime(double rectionTime);
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the letter
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param newLetter the letter to change to
|
||||
* \return false when directControlEnabled is set to false and the letter was therefore not modified, true otherwise
|
||||
*/
|
||||
void setLetter(QString newLetter);
|
||||
|
||||
void setReadyState(ScStwTimer::ReadyState);
|
||||
|
||||
/*!
|
||||
* \brief Function to change the state of the timer
|
||||
*
|
||||
* Doing this will emit the ScStwTimer::stateChanged() signal (only if the new state differs from the current one)
|
||||
*
|
||||
* \param newState The new state
|
||||
*/
|
||||
void setState(TimerState newState);
|
||||
|
||||
};
|
||||
|
||||
#endif // SCSTWREMOTETIMER_H
|
|
@ -31,9 +31,12 @@
|
|||
#endif
|
||||
#include "scstwtimer.h"
|
||||
#include "scstwrace.h"
|
||||
#include "scstwsettings.h"
|
||||
#ifdef ScStwLibraries_ClientLibs
|
||||
#include "scstwremotemonitorrace.h"
|
||||
#include "scstwsetting.h"
|
||||
#include "scstwremoterace.h"
|
||||
#include "scstwclient.h"
|
||||
#include "scstwremotesettings.h"
|
||||
#endif
|
||||
|
||||
class ScStwLibraries : public QObject
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <QEventLoop>
|
||||
#include "scstwtimer.h"
|
||||
#include "scstwsoundplayer.h"
|
||||
#include "scstwsettings.h"
|
||||
|
||||
class ScStwRemoteRace;
|
||||
|
||||
/*!
|
||||
* \brief The ScStwRace class can be used to measure timings of climbing races with multiple lanes at once.
|
||||
|
@ -50,51 +53,49 @@ class ScStwRace : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(RaceState state READ getState NOTIFY stateChanged)
|
||||
Q_PROPERTY(QVariantList timers READ getTimerDetailList NOTIFY timersChanged)
|
||||
Q_PROPERTY(QVariantList nextStartActionDetails READ getNextStartActionDetails NOTIFY nextStartActionDetailsChanged)
|
||||
Q_PROPERTY(QVariantList timers READ getTimerDetailList NOTIFY timersChanged)
|
||||
Q_PROPERTY(QVariantMap currentStartDelay READ getCurrentStartDelay NOTIFY currentStartDelayChanged)
|
||||
Q_PROPERTY(bool isReadyForNextState READ getIsReadyForNextState NOTIFY isReadyForNextStateChanged)
|
||||
Q_PROPERTY(bool competitionMode READ getCompetitionMode NOTIFY competitionModeChanged)
|
||||
Q_PROPERTY(bool readySoundEnabled READ getReadySoundEnabled NOTIFY readySoundEnabledChanged)
|
||||
Q_PROPERTY(QVariantMap details READ getDetails NOTIFY detailsChanged)
|
||||
Q_PROPERTY(ScStwSettings* settings READ getSettings WRITE setSettings NOTIFY settingsChanged)
|
||||
Q_PROPERTY(bool autoRefreshTimerText READ getAutoRefreshTimerText WRITE setAutoRefreshTimerText NOTIFY autoRefreshTimerTextChanged)
|
||||
|
||||
public:
|
||||
explicit ScStwRace(QObject *parent = nullptr);
|
||||
explicit ScStwRace(ScStwSettings *settings, QObject *parent = nullptr);
|
||||
|
||||
enum RaceState { IDLE, STARTING, WAITING, RUNNING, STOPPED };
|
||||
friend class ScStwRemoteRace;
|
||||
|
||||
enum RaceState { IDLE, PREPAIRING, WAITING, STARTING, RUNNING, STOPPED, INCIDENT };
|
||||
Q_ENUM(RaceState)
|
||||
|
||||
enum StartAction { None = -1, AtYourMarks = 0, Ready = 1, Start = 2 };
|
||||
Q_ENUM(StartAction)
|
||||
|
||||
enum NextStartActionDetailAttributes {
|
||||
NextStartAction = 0,
|
||||
NextStartActionTotalDelay = 1,
|
||||
NextStartActionDelayProgress = 2
|
||||
};
|
||||
Q_ENUM(NextStartActionDetailAttributes);
|
||||
|
||||
protected:
|
||||
StartAction nextStartAction;
|
||||
QList<ScStwTimer *> timers;
|
||||
void setState(RaceState newState);
|
||||
|
||||
private:
|
||||
RaceState state;
|
||||
|
||||
QList<ScStwTimer*> timerEnableQueque;
|
||||
|
||||
QTimer *nextActionTimer;
|
||||
QEventLoop *nextActionLoop;
|
||||
QTimer *startDelayTimer;
|
||||
QTimer *timerTextRefreshTimer;
|
||||
QEventLoop *startWaitLoop;
|
||||
|
||||
// sounds
|
||||
ScStwSoundPlayer * soundPlayer;
|
||||
|
||||
// settings
|
||||
ScStwSettings *settings;
|
||||
bool competitionMode;
|
||||
bool autoRefreshTimerText;
|
||||
|
||||
// some settings
|
||||
double soundVolume;
|
||||
|
||||
/*!
|
||||
* \brief stores the start action settings
|
||||
*
|
||||
* \details Stores the settings for the action ScStwRace::AtYourMarks and ScStwRace::Ready. The settings keys are: "Enabled" and "Delay"
|
||||
*/
|
||||
QMap<StartAction, QVariantMap> startActionSettings;
|
||||
enum LoopExitTypes {
|
||||
LoopAutomaticExit = 0,
|
||||
LoopReadyStateChangeExit = 1,
|
||||
LoopManualExit = 2,
|
||||
LoopCancelExit = 3
|
||||
};
|
||||
|
||||
|
||||
public slots:
|
||||
|
@ -105,57 +106,84 @@ public slots:
|
|||
* or if if should wait until the start sequence is over and quit after that (false)
|
||||
* \return 200: OK; 904: state not matching
|
||||
*/
|
||||
int start(bool asyncronous = true);
|
||||
virtual ScStw::StatusCode start(bool asyncronous = true);
|
||||
|
||||
/*!
|
||||
* \brief Function to stop the currently running race
|
||||
*
|
||||
* \return 200: OK; 904: state not matching
|
||||
*/
|
||||
virtual int stop();
|
||||
virtual ScStw::StatusCode stop();
|
||||
|
||||
/*!
|
||||
* \brief Function to reset a stopped race
|
||||
* \return
|
||||
*/
|
||||
virtual int reset();
|
||||
virtual int cancel();
|
||||
virtual ScStw::StatusCode reset();
|
||||
virtual ScStw::StatusCode cancel();
|
||||
|
||||
// setters
|
||||
bool writeStartActionSetting(StartAction action, bool enabled, int delay);
|
||||
bool setSoundVolume(double volume);
|
||||
virtual bool addTimer(ScStwTimer *timer);
|
||||
virtual ScStw::StatusCode setTimerDisabled(int id, bool disabled);
|
||||
|
||||
Q_INVOKABLE virtual bool addTimer(ScStwTimer *timer);
|
||||
|
||||
// getters
|
||||
RaceState getState();
|
||||
StartAction getNextStartAction();
|
||||
virtual QVariantList getNextStartActionDetails();
|
||||
virtual QVariantMap getCurrentStartDelay();
|
||||
QList<ScStwTimer*> getTimers();
|
||||
QVariantList getTimerDetailList();
|
||||
QVariantMap getDetails();
|
||||
bool getCompetitionMode();
|
||||
virtual bool getReadySoundEnabled();
|
||||
|
||||
ScStwSettings* getSettings();
|
||||
void setSettings(ScStwSettings* settings);
|
||||
|
||||
bool getAutoRefreshTimerText();
|
||||
void setAutoRefreshTimerText(bool autoRefresh);
|
||||
|
||||
protected slots:
|
||||
|
||||
|
||||
private slots:
|
||||
void refreshTimerStates();
|
||||
void handleTimerEnable(ScStwTimer* timer);
|
||||
int handleFalseStart();
|
||||
bool playSoundsAndStartTimers(StartAction thisAction);
|
||||
|
||||
void handleTimerStateChange(ScStwTimer::TimerState newState);
|
||||
|
||||
/**
|
||||
* \brief Function to declare the winner and looser timers after a timer has been stopped
|
||||
*/
|
||||
void handleTimerStop();
|
||||
void handleFalseStart();
|
||||
|
||||
|
||||
void handleTimerWantsToBeDisabledChange(ScStwTimer* timer, bool wantsToBeDisabled);
|
||||
bool playSoundsAndStartTimers();
|
||||
ScStwSoundPlayer::PlayResult doDelayAndSoundOfCurrentStartState(double *timeOfSoundPlaybackStart = nullptr);
|
||||
void technicalIncident();
|
||||
ScStw::StatusCode setTimerDisabled(ScStwTimer* timer, bool disabled);
|
||||
|
||||
virtual void refreshCompetitionMode();
|
||||
|
||||
double getSoundVolume();
|
||||
ScStwSoundPlayer::StartSound getSoundForState(ScStwRace::RaceState state);
|
||||
bool getSoundEnabledSetting(ScStwSoundPlayer::StartSound sound);
|
||||
int getSoundDelaySetting(ScStwSoundPlayer::StartSound sound);
|
||||
|
||||
|
||||
bool isStarting();
|
||||
virtual bool getIsReadyForNextState();
|
||||
void handleTimerReadyStateChange(ScStwTimer::ReadyState readyState);
|
||||
|
||||
signals:
|
||||
void startTimers();
|
||||
void stopTimers(int type);
|
||||
void resetTimers();
|
||||
void stateChanged(RaceState state);
|
||||
void nextStartActionChanged();
|
||||
void nextStartActionDetailsChanged();
|
||||
void currentStartDelayChanged();
|
||||
void timersChanged();
|
||||
|
||||
void isReadyForNextStateChanged();
|
||||
void detailsChanged();
|
||||
void competitionModeChanged();
|
||||
void readySoundEnabledChanged();
|
||||
void settingsChanged();
|
||||
void autoRefreshTimerTextChanged();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -16,39 +16,43 @@
|
|||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SCSTWREMOTEMONITORRACE_H
|
||||
#define SCSTWREMOTEMONITORRACE_H
|
||||
#ifndef SCSTWQMLSETTING_H
|
||||
#define SCSTWQMLSETTING_H
|
||||
|
||||
#include <QObject>
|
||||
#include "scstwrace.h"
|
||||
#include "scstwclient.h"
|
||||
#include <QVariant>
|
||||
|
||||
class ScStwRemoteMonitorRace : public ScStwRace
|
||||
class ScStwSettings;
|
||||
|
||||
class ScStwSetting : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScStwRemoteMonitorRace(ScStwClient *monitorClient, QObject *parent = nullptr);
|
||||
Q_PROPERTY(QVariant value READ getValue WRITE setValue NOTIFY valueChanged)
|
||||
Q_PROPERTY(QVariant readonlyValue READ getValue NOTIFY valueChanged)
|
||||
|
||||
protected:
|
||||
double nextStartActionTotalDelay;
|
||||
double nextStartActionDelayStartedAt;
|
||||
explicit ScStwSetting(int key, int keyLevel, ScStwSettings*scStwSettings, QObject *parent);
|
||||
|
||||
friend class ScStwSettings;
|
||||
|
||||
int key;
|
||||
int keyLevel;
|
||||
bool hasToReload;
|
||||
|
||||
private:
|
||||
ScStwClient *scStwClient;
|
||||
QVariant valueCache;
|
||||
ScStwSettings *scStwSettings;
|
||||
|
||||
public slots:
|
||||
int start();
|
||||
int cancel();
|
||||
int stop();
|
||||
int reset();
|
||||
bool addTimer(ScStwTimer *timer);
|
||||
QVariantList getNextStartActionDetails();
|
||||
QVariant getValue();
|
||||
void setValue(QVariant value);
|
||||
|
||||
private slots:
|
||||
void handleClientStateChanged();
|
||||
void handleBaseStationSignal(ScStw::SignalKey key, QVariant data);
|
||||
bool refreshRemoteTimers(QVariantList remoteTimers);
|
||||
protected slots:
|
||||
void handleSettingChange(int key, int keyLevel, QVariant value);
|
||||
|
||||
signals:
|
||||
void valueChanged();
|
||||
|
||||
};
|
||||
|
||||
#endif // SCSTWREMOTEMONITORRACE_H
|
||||
#endif // SCSTWQMLSETTING_H
|
124
ScStwLibraries/headers/scstwsettings.h
Normal file
124
ScStwLibraries/headers/scstwsettings.h
Normal file
|
@ -0,0 +1,124 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef SCSTWSETTINGS_H
|
||||
#define SCSTWSETTINGS_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QVariant>
|
||||
#include <QMetaEnum>
|
||||
#include <QtDebug>
|
||||
#include <QFile>
|
||||
#include <QStandardPaths>
|
||||
#include <QJsonDocument>
|
||||
#include <ScStw.hpp>
|
||||
#include <QDir>
|
||||
#include <scstwsetting.h>
|
||||
|
||||
class ScStwSettings : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScStwSettings(QObject *parent = nullptr);
|
||||
|
||||
typedef QString(*keyToStringConverter)(int);
|
||||
typedef QVariant::Type(*keyToTypeConverter)(int);
|
||||
|
||||
/*!
|
||||
* \brief The BaseStationSetting enum contains all settings of the base station that can be changed by a client
|
||||
*
|
||||
* \see ScStw::baseStationSettingFromInt()
|
||||
* \see ScStw::baseStationSettingToString()
|
||||
* \see ScStw::baseStationSettingFromString()
|
||||
* \see ScStw::baseStationSettings
|
||||
*/
|
||||
enum BaseStationSetting {
|
||||
InvalidSetting = -1,
|
||||
ReadySoundEnableSetting,
|
||||
ReadySoundDelaySetting,
|
||||
AtYourMarksSoundEnableSetting,
|
||||
AtYourMarksSoundDelaySetting,
|
||||
SoundVolumeSetting,
|
||||
CompetitionModeSetting
|
||||
};
|
||||
Q_ENUM(BaseStationSetting)
|
||||
|
||||
enum KeyLevelEnum {
|
||||
KeyLevel = 0
|
||||
};
|
||||
Q_ENUM(KeyLevelEnum)
|
||||
|
||||
virtual QVariant readSetting(BaseStationSetting key);
|
||||
Q_INVOKABLE virtual QVariant readSetting(int key, int keyLevel);
|
||||
virtual bool writeSetting(BaseStationSetting key, QVariant value);
|
||||
Q_INVOKABLE virtual bool writeSetting(int key, int keyLevel, QVariant value);
|
||||
virtual bool setDefaultSetting(BaseStationSetting key, QVariant defaultValue);
|
||||
Q_INVOKABLE virtual bool setDefaultSetting(int key, int keyLevel, QVariant defaultValue);
|
||||
|
||||
Q_INVOKABLE ScStwSetting * getSetting(int key, int keyLevel);
|
||||
|
||||
static BaseStationSetting keyFromInt(int i) {
|
||||
QMetaEnum enumeration = QMetaEnum::fromType<BaseStationSetting>();
|
||||
return static_cast<BaseStationSetting>(enumeration.keyToValue(enumeration.valueToKey(i)));
|
||||
}
|
||||
|
||||
static QString keyToString(int key) {
|
||||
return QMetaEnum::fromType<BaseStationSetting>().valueToKey(key);
|
||||
}
|
||||
|
||||
static QVariant::Type keyToType(int key) {
|
||||
QMap<BaseStationSetting, QVariant::Type> types = {
|
||||
{ReadySoundEnableSetting, QVariant::Bool},
|
||||
{ReadySoundDelaySetting, QVariant::Double},
|
||||
{AtYourMarksSoundEnableSetting, QVariant::Bool},
|
||||
{AtYourMarksSoundDelaySetting, QVariant::Double},
|
||||
{SoundVolumeSetting, QVariant::Double},
|
||||
{CompetitionModeSetting, QVariant::Bool}
|
||||
};
|
||||
|
||||
if(types.contains(BaseStationSetting(key)))
|
||||
return types[BaseStationSetting(key)];
|
||||
|
||||
return QVariant::Invalid;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual QVariant readSetting(QString key, int keyInt = -1, int keyLevel = -1);
|
||||
virtual bool writeSetting(QString key, QVariant value, int keyInt = -1,int keyLevel = -1);
|
||||
virtual bool setDefaultSetting(QString key, QVariant defaultValue, int keyInt,int keyLevel = -1);
|
||||
bool registerKeyLevelConverters(int keyLevel, keyToStringConverter, keyToTypeConverter);
|
||||
|
||||
private:
|
||||
QFile * settingsFile;
|
||||
QVariantMap settingsCache;
|
||||
|
||||
bool loadSettingsFromFile();
|
||||
|
||||
QMap<int, keyToStringConverter> keyToStringConverters;
|
||||
QMap<int, keyToTypeConverter> keyToTypeConverters;
|
||||
QMap<int, QMap<int, ScStwSetting*>> internalSettingHandlers;
|
||||
|
||||
private slots:
|
||||
bool writeSettingsToFile();
|
||||
|
||||
signals:
|
||||
void settingChanged(int key, int keyLevel, QVariant value);
|
||||
|
||||
};
|
||||
|
||||
#endif // SCSTWSETTINGS_H
|
|
@ -27,6 +27,11 @@
|
|||
#include <QTimer>
|
||||
#include <QDateTime>
|
||||
#include <QSoundEffect>
|
||||
#include <QAudioDeviceInfo>
|
||||
|
||||
#ifdef ScStwLibraries_Raspi
|
||||
#include <alsa/asoundlib.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \brief The ScStwSoundPlayer class is used for ultra low latency sound playback of the speed clibing start tones and commands
|
||||
|
@ -41,7 +46,26 @@ public:
|
|||
*/
|
||||
explicit ScStwSoundPlayer(QObject *parent = nullptr);
|
||||
|
||||
enum StartSound {
|
||||
None = -1,
|
||||
AtYourMarks = 0,
|
||||
Ready = 1,
|
||||
Start = 2,
|
||||
FalseStart = 3
|
||||
};
|
||||
|
||||
enum PlayResult {
|
||||
Success = 0,
|
||||
Cancelled = -1,
|
||||
Error = -2
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
bool _setSoundVolume(double volume);
|
||||
|
||||
void _initializeSondEffect();
|
||||
|
||||
/*!
|
||||
* \brief A map containing all sound files
|
||||
* 0: AtYourMarksSound
|
||||
|
@ -49,13 +73,15 @@ private:
|
|||
* 2: StartSound
|
||||
* 3: FalseStartSound
|
||||
*/
|
||||
QMap<int, QVariantMap> soundFiles;
|
||||
QMap<StartSound, QVariantMap> soundFiles;
|
||||
|
||||
/*!
|
||||
* \brief The sound effect object
|
||||
*/
|
||||
QSoundEffect *soundEffect;
|
||||
|
||||
QAudioDeviceInfo *_audioOutputDevice;
|
||||
|
||||
/*!
|
||||
* \brief The QEventLoop used to wait for the sound to finish
|
||||
*/
|
||||
|
@ -69,7 +95,7 @@ private:
|
|||
/*!
|
||||
* \brief The action that is currently played
|
||||
*/
|
||||
int currentlyPlayingAction;
|
||||
StartSound currentlyPlayingSound;
|
||||
|
||||
/*!
|
||||
* \brief Holds the time the playback started at
|
||||
|
@ -83,16 +109,16 @@ public slots:
|
|||
* \param action The action to play (0: AtYourMarks, 1:Ready, 2:Start)
|
||||
* \param volume The volume to play at
|
||||
* \param timeOfStop The time the playback actually started (msecs since epoch)
|
||||
* \return true if the playback was successfully started, false otherwise
|
||||
* \return TODO true if the playback was successfully started, false otherwise
|
||||
*/
|
||||
bool play(int action, double volume, double *timeOfStart = nullptr);
|
||||
ScStwSoundPlayer::PlayResult play(StartSound sound, double volume, double *timeOfStart = nullptr);
|
||||
|
||||
/*!
|
||||
* \brief Function to wait for the playback to finish
|
||||
* \param timeOfStop the point in time when the plyback actually stopped (msecs since epoch)
|
||||
* \return false if there was any error (eg. there was no playback currently), true otherwise
|
||||
*/
|
||||
bool waitForSoundFinish(double *timeOfStop = nullptr);
|
||||
ScStwSoundPlayer::PlayResult waitForSoundFinish(double *timeOfStop = nullptr);
|
||||
|
||||
/*!
|
||||
* \brief Function to cancel the current playback
|
||||
|
@ -102,7 +128,9 @@ public slots:
|
|||
* \param volume the volume to play the false start sound at
|
||||
* \return true if the playback was successfully stopped, false otherwise
|
||||
*/
|
||||
bool cancel(double volume = 0);
|
||||
bool cancel();
|
||||
|
||||
bool isPlaying();
|
||||
|
||||
private slots:
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@
|
|||
#include <QTimer>
|
||||
#include "ScStw.hpp"
|
||||
|
||||
class ScStwRace;
|
||||
class ScStwRemoteRace;
|
||||
|
||||
/*!
|
||||
* \brief The ScStwTimer class is used for advanced time measurement.
|
||||
*
|
||||
|
@ -62,13 +65,18 @@ class ScStwTimer : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit ScStwTimer(QObject *parent = nullptr);
|
||||
|
||||
/*!
|
||||
* \brief ScStwTimer constructor
|
||||
* \param parent the parent object
|
||||
* \param directControlEnabled Defines if protected properties (startTimer, stopTime, reactionTime and state) can be directly set from outside.
|
||||
* \param letter the letter of the timer (only first char will be used!)
|
||||
*/
|
||||
explicit ScStwTimer(QObject *parent = nullptr, bool directControlEnabled = false, QString letter = "" );
|
||||
explicit ScStwTimer(QString letter, QObject *parent = nullptr);
|
||||
|
||||
friend class ScStwRace;
|
||||
|
||||
/*!
|
||||
* \brief The TimerState enum contains all state the timer can be in
|
||||
|
@ -77,24 +85,30 @@ public:
|
|||
IDLE, /*!< Timer is waiting to be started */
|
||||
STARTING, /*!< Timer is starting and will react with a false start if the climber starts */
|
||||
RUNNING, /*!< Timer is running */
|
||||
WAITING, /*!< Timer was stopped and is waiting for the result */
|
||||
WAITING, /*!< Timer was stopped and is waiting to be set to either WON or LOST */
|
||||
WON, /*!< Timer has won */
|
||||
LOST, /*!< Timer has lost */
|
||||
FAILING, /*!< Timer encountered a false start and is waiting to be set to either FAILED or WILDCARD */
|
||||
WILDCARD, /*!< The opponent has done a false start */
|
||||
FAILED, /*!< A false start occured */
|
||||
CANCELLED, /*!< Timer was cancelled */
|
||||
INCIDENT, /*!< There was a technical incident (most likely a disconnected extension) */
|
||||
DISABLED /*!< Timer is disabled */
|
||||
};
|
||||
Q_ENUM(TimerState);
|
||||
|
||||
/*!
|
||||
* \brief The StopReason enum contains all possible reasons for a stop
|
||||
* \brief The ReadyStatus enum contains all possible reasons for a timer not to be ready (>0) and the case that it is ready (0)
|
||||
*/
|
||||
enum StopReason {
|
||||
ManualStop, /*!< Timer was stopped manually */
|
||||
CancelStop, /*!< Timer was cancelled */
|
||||
FailStop, /*!< A false start occured */
|
||||
TopPadStop /*!< Timer was stopped by a physical trigger (eg. a ScStwExtension) */
|
||||
enum ReadyState {
|
||||
IsReady = 0, /*!< Timer is ready for start */
|
||||
NotInIdleState, /*!< Timer is not in IDLE state */
|
||||
IsDisabled, /*!< Timer is disabled */
|
||||
ExtensionIsNotConnected, /*!< Not all extension of the timer are conneted */
|
||||
ExtensionBatteryIsCritical, /*!< The battery level of one or more extension is critical or unknown */
|
||||
ClimberIsNotReady /*!< The startpad of the timer is not triggered */
|
||||
};
|
||||
Q_ENUM(ReadyState)
|
||||
|
||||
protected:
|
||||
/*!
|
||||
|
@ -117,16 +131,16 @@ protected:
|
|||
*/
|
||||
double reactionTime;
|
||||
|
||||
/*!
|
||||
* \brief Defines if protected properties (startTimer, stopTime, reactionTime and state) can be directly set from outside.
|
||||
*/
|
||||
bool directControlEnabled;
|
||||
|
||||
/*!
|
||||
* \brief The letter (eg. "A" or "B") of the Timer (only one char)
|
||||
*/
|
||||
QString letter;
|
||||
|
||||
/*!
|
||||
* \brief Defines if the timer currently wants to be disabled or not
|
||||
*/
|
||||
bool wantsToBeDisabled;
|
||||
|
||||
public slots:
|
||||
|
||||
/*!
|
||||
|
@ -243,56 +257,20 @@ public slots:
|
|||
void setDisabled(bool disabled);
|
||||
|
||||
/*!
|
||||
* \brief Function to change the state of the timer
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
* Doing this will emit the ScStwTimer::stateChanged() signal (only if the new state differs from the current one)
|
||||
*
|
||||
* \param newState The new state
|
||||
* \param force whether to force the state change (just to distinguish between protected and public function)
|
||||
* \return false when directControlEnabled or force is set to false and the startTime was therefore not modified, true otherwise
|
||||
* \brief Function to check if the timer currently wants to be disabled
|
||||
* \return true or false
|
||||
*/
|
||||
bool setState(TimerState newState, bool force);
|
||||
bool getWantsToBeDisabled();
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the start time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param startTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the startTime was therefore not modified, true otherwise
|
||||
* \brief Function to get the current ready status of a timer
|
||||
* \return The current ready status
|
||||
*/
|
||||
bool setStartTime(double startTime);
|
||||
virtual ScStwTimer::ReadyState getReadyState();
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the stop time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param stopTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the stopTime was therefore not modified, true otherwise
|
||||
*/
|
||||
bool setStopTime(double stopTime);
|
||||
bool isRunning();
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the rection time
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param reactionTime the time to change to
|
||||
* \return false when directControlEnabled is set to false and the reactionTime was therefore not modified, true otherwise
|
||||
*/
|
||||
bool setReactionTime(double rectionTime);
|
||||
|
||||
/*!
|
||||
* \brief Function to dircetly change the letter
|
||||
*
|
||||
* Only works when directControlEnabled is set to true!
|
||||
*
|
||||
* \param newLetter the letter to change to
|
||||
* \return false when directControlEnabled is set to false and the letter was therefore not modified, true otherwise
|
||||
*/
|
||||
bool setLetter(QString newLetter);
|
||||
bool isDisabled();
|
||||
|
||||
protected slots:
|
||||
|
||||
|
@ -302,33 +280,6 @@ protected slots:
|
|||
*/
|
||||
void handleClimberStart(double timeOfStart);
|
||||
|
||||
/*!
|
||||
* \brief Function to stop the timer at a given point in time (past or future)
|
||||
*
|
||||
* To do this, the timer has to be in ScStwTimer::RUNNING state!
|
||||
*
|
||||
* \param reason reason for the timer stop
|
||||
* \param timeOfStop the point in time (msecs since epoch) when the timer is supposted to be stopped
|
||||
*
|
||||
* \return false if the timer was not in the required state and therefore not stopped, true otherwise
|
||||
*
|
||||
* \see ScStwTimer::StopReason
|
||||
*/
|
||||
virtual bool stop(StopReason reason, double timeOfStop);
|
||||
|
||||
/*!
|
||||
* \brief Function to stop the timer
|
||||
*
|
||||
* To do this, the timer has to be in ScStwTimer::RUNNING state!
|
||||
*
|
||||
* \param reason reason for the timer stop
|
||||
*
|
||||
* \return false if the timer was not in the required state and therefore not stopped, true otherwise
|
||||
*
|
||||
* \see ScStwTimer::StopReason
|
||||
*/
|
||||
bool stop(StopReason reason);
|
||||
|
||||
/*!
|
||||
* \brief Function to change the state of the timer
|
||||
*
|
||||
|
@ -338,12 +289,36 @@ protected slots:
|
|||
*/
|
||||
void setState(TimerState newState);
|
||||
|
||||
/*!
|
||||
* \brief Function to set whether the timer currently wants to be disabled
|
||||
* \param wantsToBeDisabled true or false
|
||||
*/
|
||||
void setWantsToBeDisabled(bool wantsToBeDisabled);
|
||||
|
||||
/*!
|
||||
* \brief Function to set the timer into INCIDENT state immidieately
|
||||
*
|
||||
* The current state of the timer will be ignored! It can only get out of this state by calling ScStwTimer::reset
|
||||
*
|
||||
* \see reset
|
||||
*/
|
||||
void technicalIncident();
|
||||
|
||||
/*!
|
||||
* \brief Function to set the timer into WILDCARD state
|
||||
*
|
||||
* Only works when the timer is in STARTING state.
|
||||
*
|
||||
* \return false if not in STARTING state
|
||||
*/
|
||||
bool wildcard();
|
||||
|
||||
|
||||
signals:
|
||||
/*!
|
||||
* \brief Emitted when the state of the timer changed
|
||||
*/
|
||||
void stateChanged();
|
||||
void stateChanged(TimerState state);
|
||||
|
||||
/*!
|
||||
* \brief Emitted when the reaction time changed
|
||||
|
@ -354,7 +329,13 @@ signals:
|
|||
* \brief Emitted when the timer wants its state to be changed by the external handler
|
||||
* \param timer the timer object
|
||||
*/
|
||||
void requestEnableChange(ScStwTimer* timer);
|
||||
void wantsToBeDisabledChanged(ScStwTimer* timer, bool wantsToBeDisabled);
|
||||
|
||||
/*!
|
||||
* \brief Emitted when the ready state of the timer changes
|
||||
* \param readyState the new ReadyState
|
||||
*/
|
||||
void readyStateChanged(ReadyState readyState);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ class ScStwAppThemeManager : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(ScStwAppTheme* theme READ getTheme NOTIFY themeChanged)
|
||||
Q_PROPERTY(QString themeName READ getThemeName WRITE setTheme NOTIFY themeChanged)
|
||||
|
||||
public:
|
||||
explicit ScStwAppThemeManager(QObject *parent = nullptr);
|
||||
|
@ -45,6 +46,7 @@ signals:
|
|||
public slots:
|
||||
ScStwAppTheme* getTheme();
|
||||
Q_INVOKABLE bool setTheme(QString themeName);
|
||||
Q_INVOKABLE QString getThemeName();
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ Column {
|
|||
width: parent.width * 0.8
|
||||
height: parent.height * 0.8
|
||||
|
||||
color: ([ScStwTimer.WON].indexOf(control.timers[index]["state"]) >= 0 ? control.colors.success :
|
||||
color: ([ScStwTimer.WON,ScStwTimer.WILDCARD].indexOf(control.timers[index]["state"]) >= 0 ? control.colors.success :
|
||||
[ScStwTimer.FAILED,ScStwTimer.LOST].indexOf(control.timers[index]["state"]) >= 0 ? control.colors.error:
|
||||
control.colors.text)
|
||||
|
||||
|
|
|
@ -21,38 +21,6 @@
|
|||
const char *ScStw::SOCKET_MESSAGE_START_KEY = "<message>";
|
||||
const char *ScStw::SOCKET_MESSAGE_END_KEY = "</message>";
|
||||
|
||||
const QMap<QString, ScStw::BaseStationSetting> ScStw::baseStationSettings = {
|
||||
{"ReadySoundEnable", ScStw::ReadySoundEnableSetting},
|
||||
{"ReadySoundDelay", ScStw::ReadySoundDelaySetting},
|
||||
{"AtYourMarksSoundEnable", ScStw::AtYourMarksSoundEnableSetting},
|
||||
{"AtYourMarksSoundDelay", ScStw::AtYourMarksSoundDelaySetting},
|
||||
{"SoundVolume", ScStw::SoundVolumeSetting}
|
||||
};
|
||||
|
||||
ScStw::BaseStationSetting ScStw::baseStationSettingFromString(QString s) {
|
||||
if(!ScStw::baseStationSettings.contains(s))
|
||||
return ScStw::InvalidSetting;
|
||||
|
||||
return ScStw::baseStationSettings[s];
|
||||
}
|
||||
|
||||
QString ScStw::baseStationSettingToString(ScStw::BaseStationSetting s) {
|
||||
for(QString key: ScStw::baseStationSettings.keys()) {
|
||||
if(ScStw::baseStationSettings[key] == s)
|
||||
return key;
|
||||
}
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
ScStw::BaseStationSetting ScStw::baseStationSettingfromInt(int i) {
|
||||
bool ok;
|
||||
BaseStationSetting s = ScStw::toEnumValue<ScStw::BaseStationSetting>(i, &ok);
|
||||
if(!ok)
|
||||
return InvalidSetting;
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
ScStw::SignalKey ScStw::signalKeyFromInt(int i) {
|
||||
bool ok;
|
||||
ScStw::SignalKey k = ScStw::toEnumValue<ScStw::SignalKey>(i, &ok);
|
||||
|
@ -71,6 +39,17 @@ ScStw::SocketCommand ScStw::socketCommandFromInt(int i) {
|
|||
return c;
|
||||
}
|
||||
|
||||
QString ScStw::extensionTypeToString(ExtensionType t) {
|
||||
switch (t) {
|
||||
case StartPad:
|
||||
return "StartPad";
|
||||
case TopPad:
|
||||
return "TopPad";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
int ScStw::firmwareCompare(QString a, QString b) {
|
||||
/*
|
||||
* * \return -3: major of a is lower than b
|
||||
|
|
|
@ -20,11 +20,12 @@
|
|||
|
||||
ScStwClient * pGlobalScStwClient = nullptr;
|
||||
|
||||
ScStwClient::ScStwClient(QObject * parent) : QObject(parent)
|
||||
ScStwClient::ScStwClient(QObject * parent, QList<ScStw::SignalKey> signalSubscriptions) : QObject(parent)
|
||||
{
|
||||
this->state = DISCONNECTED;
|
||||
this->nextConnectionId = 1;
|
||||
this->extensions = QVariantList({});
|
||||
this->currentRequestId = 1;
|
||||
this->extensions = QVariantMap({});
|
||||
this->signalSubscriptions = signalSubscriptions;
|
||||
|
||||
this->socket = new QTcpSocket(this);
|
||||
|
||||
|
@ -49,6 +50,9 @@ ScStwClient::ScStwClient(QObject * parent) : QObject(parent)
|
|||
|
||||
void ScStwClient::connectToHost() {
|
||||
|
||||
if(this->state != DISCONNECTED)
|
||||
return;
|
||||
|
||||
setState(CONNECTING);
|
||||
|
||||
//connect
|
||||
|
@ -72,21 +76,24 @@ bool ScStwClient::init() {
|
|||
this->setState(INITIALISING);
|
||||
this->timeoutTimer->stop();
|
||||
|
||||
QJsonArray signalSubs;
|
||||
foreach (ScStw::SignalKey key, this->signalSubscriptions) {
|
||||
signalSubs.append(key);
|
||||
}
|
||||
|
||||
// init remote session
|
||||
QJsonArray updateSubs = {ScStw::RaceStateChanged, ScStw::TimersChanged, ScStw::ExtensionsChanged, ScStw::NextStartActionChanged};
|
||||
QJsonObject sessionParams = {{"updateSubs", updateSubs}, {"init", true}, {"usingTerminationKeys", true}};
|
||||
QJsonObject sessionParams = {{"apiVersion", this->API_VERSION}, {"signalSubscriptions", signalSubs}, {"init", true}, {"usingTerminationKeys", true}};
|
||||
|
||||
QVariantMap initResponse = this->sendCommand(1, sessionParams, 3000, false);
|
||||
|
||||
if(initResponse["status"] != 200) {
|
||||
this->closeConnection();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->apiVersion = initResponse["data"].toMap()["apiVersion"].toString();
|
||||
qDebug() << "[INFO][CLIENT] base station api version is: " << this->apiVersion;
|
||||
int compareResult = ScStw::firmwareCompare(this->API_VERSION, this->apiVersion);
|
||||
qDebug() << "compare result is: " << compareResult;
|
||||
//qDebug() << "compare result is: " << compareResult;
|
||||
if( compareResult == -3 ){
|
||||
// the client version is out of date!!
|
||||
this->closeConnection();
|
||||
|
@ -116,7 +123,17 @@ void ScStwClient::deInit() {
|
|||
if(this->state == DISCONNECTED)
|
||||
return;
|
||||
|
||||
this->setExtensions(QVariantList({}));
|
||||
this->currentRequestId = 1;
|
||||
this->firmwareVersion = "";
|
||||
this->apiVersion = "";
|
||||
this->setExtensions(QVariantMap({}));
|
||||
|
||||
for(WaitingRequest waitingRequest : this->waitingRequests.values())
|
||||
if(waitingRequest.loop != nullptr)
|
||||
waitingRequest.loop->exit(ScStw::NotConnectedError);
|
||||
|
||||
this->waitingRequests.clear();
|
||||
|
||||
this->setState(DISCONNECTED);
|
||||
}
|
||||
|
||||
|
@ -155,16 +172,22 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
|
|||
return {{"status", ScStw::NotConnectedError}, {"data", "not connected"}};
|
||||
}
|
||||
|
||||
// generate id and witing requests entry
|
||||
int thisId = nextConnectionId;
|
||||
// pick a new request id that is not already active
|
||||
do {
|
||||
if(this->currentRequestId >= 99)
|
||||
this->currentRequestId = 0;
|
||||
else
|
||||
this->currentRequestId ++;
|
||||
} while(this->waitingRequests.contains(this->currentRequestId));
|
||||
|
||||
int thisId = currentRequestId;
|
||||
//qDebug() << "sending command: " << header << " with data: " << data << " and id: " << thisId;
|
||||
nextConnectionId ++;
|
||||
|
||||
QEventLoop *loop = new QEventLoop(this);
|
||||
QTimer *timer = new QTimer(this);
|
||||
QJsonObject reply;
|
||||
|
||||
this->waitingRequests.append({thisId, loop, reply});
|
||||
this->waitingRequests.insert(thisId, {loop, reply});
|
||||
|
||||
QJsonObject requestObj;
|
||||
requestObj.insert("id", thisId);
|
||||
|
@ -175,7 +198,7 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
|
|||
|
||||
timer->setSingleShot(true);
|
||||
// quit the loop when the timer times out
|
||||
loop->connect(timer, SIGNAL(timeout()), loop, SLOT(quit()));
|
||||
connect(timer, &QTimer::timeout, [=]{loop->exit(ScStw::TimeoutError);});
|
||||
// start the timer before starting to connect
|
||||
timer->start(timeout);
|
||||
|
||||
|
@ -186,37 +209,38 @@ QVariantMap ScStwClient::sendCommand(int header, QJsonValue data, int timeout, b
|
|||
socket->write(jsonRequest.toUtf8());
|
||||
|
||||
//wait for an answer to finish (programm gets stuck in here)
|
||||
loop->exec();
|
||||
ScStw::StatusCode statusCode = ScStw::StatusCode(loop->exec());
|
||||
|
||||
|
||||
|
||||
bool replyFound = false;
|
||||
// delete the timer
|
||||
timer->deleteLater();
|
||||
|
||||
// find reply and delete the request from waiting list
|
||||
for(int i = 0; i<this->waitingRequests.length(); i++){
|
||||
if(this->waitingRequests[i].id == thisId){
|
||||
// request was found
|
||||
replyFound = true;
|
||||
// delete event loop
|
||||
if(this->waitingRequests[i].loop != nullptr) {
|
||||
delete this->waitingRequests[i].loop;
|
||||
}
|
||||
// store reply
|
||||
reply = this->waitingRequests[i].reply;
|
||||
// remove reply from waiting list
|
||||
this->waitingRequests.removeAt(i);
|
||||
if(this->waitingRequests.contains(thisId)) {
|
||||
// request was found
|
||||
// delete event loop
|
||||
if(this->waitingRequests[thisId].loop != nullptr) {
|
||||
this->waitingRequests[thisId].loop->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
if(!replyFound) {
|
||||
// store reply
|
||||
reply = this->waitingRequests[thisId].reply;
|
||||
|
||||
// remove reply from waiting list
|
||||
this->waitingRequests.remove(thisId);
|
||||
}
|
||||
else {
|
||||
// some internal error occured
|
||||
return {{"status", ScStw::Error}, {"data", ""}};
|
||||
return {{"status", ScStw::InternalError}, {"data", ""}};
|
||||
}
|
||||
|
||||
if(timer->remainingTime() == -1){
|
||||
if(statusCode == ScStw::TimeoutError){
|
||||
//the time has been triggered -> timeout
|
||||
return {{"status", ScStw::TimeoutError}, {"data", ""}};
|
||||
}
|
||||
else if(statusCode == ScStw::NotConnectedError) {
|
||||
// connection was closed during request
|
||||
return {{"status", ScStw::NotConnectedError}, {"data", ""}};
|
||||
}
|
||||
|
||||
delete timer;
|
||||
return {{"status", reply.value("header").toInt()}, {"data", reply.value("data").toVariant()}};
|
||||
|
@ -268,7 +292,6 @@ void ScStwClient::handleReadyRead() {
|
|||
|
||||
//qDebug() << "ready to ready " << socket->bytesAvailable() << " bytes" ;
|
||||
QString reply = socket->readAll();
|
||||
|
||||
//qWarning() << "socket read: " << reply;
|
||||
|
||||
processSocketMessage(reply);
|
||||
|
@ -330,7 +353,7 @@ void ScStwClient::handleSocketMessage(QString reply) {
|
|||
reply.replace(ScStw::SOCKET_MESSAGE_START_KEY, "");
|
||||
reply.replace(ScStw::SOCKET_MESSAGE_END_KEY, "");
|
||||
|
||||
//qDebug() << "got message: " << reply;
|
||||
qDebug() << "got message: " << qPrintable(reply);
|
||||
|
||||
int id = 0;
|
||||
|
||||
|
@ -347,14 +370,12 @@ void ScStwClient::handleSocketMessage(QString reply) {
|
|||
}
|
||||
|
||||
// this message is the reply to a command!
|
||||
for(int i = 0; i < this->waitingRequests.length(); i++){
|
||||
if(this->waitingRequests[i].id == id){
|
||||
this->waitingRequests[i].reply = replyObj;
|
||||
if(this->waitingRequests[i].loop != nullptr){
|
||||
this->waitingRequests[i].loop->quit();
|
||||
}
|
||||
return;
|
||||
if(this->waitingRequests.contains(id)){
|
||||
this->waitingRequests[id].reply = replyObj;
|
||||
if(this->waitingRequests[id].loop != nullptr){
|
||||
this->waitingRequests[id].loop->exit(ScStw::Success);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -375,7 +396,7 @@ void ScStwClient::handleSignal(QVariantMap data) {
|
|||
{
|
||||
// the extension connections have changed
|
||||
// -> handle locally
|
||||
this->setExtensions(data["data"].toList());
|
||||
this->setExtensions(data["data"].toMap());
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
@ -392,19 +413,24 @@ void ScStwClient::handleSignal(QVariantMap data) {
|
|||
// --- helper functions ---
|
||||
// ------------------------
|
||||
|
||||
ScStw::StatusCode ScStwClient::writeRemoteSetting(ScStw::BaseStationSetting key, QString value) {
|
||||
ScStw::StatusCode ScStwClient::writeRemoteSetting(ScStwSettings::BaseStationSetting key, QVariant value) {
|
||||
QJsonArray requestData;
|
||||
requestData.append(key);
|
||||
requestData.append(value);
|
||||
requestData.append(int(key));
|
||||
requestData.append(QJsonValue::fromVariant(value));
|
||||
return ScStw::StatusCode(this->sendCommand(3000, requestData)["status"].toInt());
|
||||
}
|
||||
|
||||
QString ScStwClient::readRemoteSetting(ScStw::BaseStationSetting key) {
|
||||
QVariantMap reply = this->sendCommand(3001, key);
|
||||
QVariant ScStwClient::readRemoteSetting(ScStwSettings::BaseStationSetting key, ScStw::StatusCode* status) {
|
||||
QVariantMap reply = this->sendCommand(3001, int(key), 10000);
|
||||
qDebug() << "Setting read status is: " << reply["status"];
|
||||
|
||||
if(status != nullptr)
|
||||
*status = ScStw::StatusCode(reply["status"].toInt());
|
||||
|
||||
if(reply["status"] != 200){
|
||||
return "false";
|
||||
}
|
||||
return reply["data"].toString();
|
||||
return reply["data"];
|
||||
}
|
||||
|
||||
void ScStwClient::setIP(QString newIp){
|
||||
|
@ -429,7 +455,7 @@ void ScStwClient::setState(ScStwClient::State newState){
|
|||
}
|
||||
}
|
||||
|
||||
QVariantList ScStwClient::getExtensions() {
|
||||
QVariantMap ScStwClient::getExtensions() {
|
||||
return this->extensions;
|
||||
}
|
||||
|
||||
|
@ -445,10 +471,18 @@ QString ScStwClient::getApiVersion() {
|
|||
return this->apiVersion;
|
||||
}
|
||||
|
||||
void ScStwClient::setExtensions(QVariantList extensions) {
|
||||
void ScStwClient::setExtensions(QVariantMap extensions) {
|
||||
qDebug() << "[CLIENT][DEBUG] Extensions changed: " << extensions;
|
||||
|
||||
if(this->extensions != extensions){
|
||||
this->extensions = extensions;
|
||||
emit this->gotSignal(ScStw::ExtensionsChanged, this->getExtensions());
|
||||
emit this->extensionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ScStwClient::addSignalSubscription(ScStw::SignalKey key) {
|
||||
if(!this->signalSubscriptions.contains(key))
|
||||
this->signalSubscriptions.append(key);
|
||||
}
|
||||
|
|
|
@ -1,241 +0,0 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include "scstwremotemonitorrace.h"
|
||||
|
||||
ScStwRemoteMonitorRace::ScStwRemoteMonitorRace(ScStwClient *monitorClient, QObject *parent) : ScStwRace(parent)
|
||||
{
|
||||
this->scStwClient = monitorClient;
|
||||
|
||||
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ScStwRemoteMonitorRace::handleClientStateChanged);
|
||||
connect(this->scStwClient, &ScStwClient::gotSignal, this, &ScStwRemoteMonitorRace::handleBaseStationSignal);
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// --- Main Functionality ---
|
||||
// --------------------------
|
||||
|
||||
int ScStwRemoteMonitorRace::start() {
|
||||
|
||||
if(this->getState() != ScStwRace::IDLE) {
|
||||
return 904;
|
||||
}
|
||||
|
||||
qDebug() << "+ --- starting race";
|
||||
|
||||
int returnCode = 900;
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(1000);
|
||||
|
||||
if(reply["status"] != 200){
|
||||
//handle Error!!
|
||||
returnCode = reply["status"].toInt();
|
||||
}
|
||||
else {
|
||||
|
||||
returnCode = 200;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
int ScStwRemoteMonitorRace::cancel() {
|
||||
return this->stop();
|
||||
|
||||
}
|
||||
|
||||
int ScStwRemoteMonitorRace::stop() {
|
||||
|
||||
if(this->getState() != ScStwRace::RUNNING && this->getState() != ScStwRace::STARTING) {
|
||||
return 904;
|
||||
}
|
||||
|
||||
// type can be:
|
||||
// 0: stopp
|
||||
// 1: cancel
|
||||
// 2: fail (fase start)
|
||||
|
||||
qDebug() << "+ --- stopping race";
|
||||
|
||||
int returnCode = 900;
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(1001);
|
||||
|
||||
if(reply["status"] != 200){
|
||||
returnCode = reply["status"].toInt();
|
||||
}
|
||||
else {
|
||||
returnCode = 200;
|
||||
}
|
||||
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
int ScStwRemoteMonitorRace::reset() {
|
||||
|
||||
if(this->getState() != ScStwRace::STOPPED) {
|
||||
return 904;
|
||||
}
|
||||
|
||||
qDebug() << "+ --- resetting race";
|
||||
|
||||
int returnCode = 900;
|
||||
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(1002);
|
||||
|
||||
if(reply["status"] != 200){
|
||||
//handle Error!!
|
||||
returnCode = reply["status"].toInt();
|
||||
}
|
||||
else {
|
||||
returnCode = 200;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------
|
||||
// --- Base Station sync ---
|
||||
// -------------------------
|
||||
|
||||
void ScStwRemoteMonitorRace::handleClientStateChanged() {
|
||||
// TODO
|
||||
switch (this->scStwClient->getState()) {
|
||||
case ScStwClient::CONNECTED:
|
||||
break;
|
||||
default:
|
||||
this->timers.clear();
|
||||
this->setState(IDLE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ScStwAppBackend::handleBaseStationUpdate
|
||||
*
|
||||
* Function to handle an update, sent by the base station, which indicates
|
||||
* that some remote value (like a state) has changed
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
void ScStwRemoteMonitorRace::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {
|
||||
//qDebug() << "got signal: " << data;
|
||||
switch (key) {
|
||||
case ScStw::RaceStateChanged:
|
||||
{
|
||||
// the remote race state has changed
|
||||
this->setState( ScStwRace::RaceState( data.toInt() ) );
|
||||
break;
|
||||
}
|
||||
case ScStw::TimersChanged:
|
||||
{
|
||||
// the remote timers have changed
|
||||
this->refreshRemoteTimers(data.toList());
|
||||
break;
|
||||
}
|
||||
case ScStw::NextStartActionChanged:
|
||||
{
|
||||
// the next start action has changed
|
||||
this->nextStartActionTotalDelay = data.toList()[ScStwRace::NextStartActionTotalDelay].toDouble();
|
||||
this->nextStartActionDelayStartedAt = QDateTime::currentMSecsSinceEpoch() - (this->nextStartActionTotalDelay * data.toList()[ScStwRace::NextStartActionDelayProgress].toDouble());
|
||||
this->nextStartAction = ScStwRace::StartAction( data.toList()[ScStwRace::NextStartAction].toInt() );
|
||||
|
||||
emit this->nextStartActionChanged();
|
||||
break;
|
||||
}
|
||||
case ScStw::InvalidSignal:
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScStwRemoteMonitorRace::refreshRemoteTimers(QVariantList remoteTimers) {
|
||||
|
||||
if(remoteTimers.length() != this->timers.length()){
|
||||
// local timers are out of sync
|
||||
|
||||
// delete all current timers
|
||||
foreach(ScStwTimer * locTimer, this->timers){
|
||||
delete locTimer;
|
||||
}
|
||||
|
||||
this->timers.clear();
|
||||
|
||||
foreach(QVariant remoteTimer, remoteTimers){
|
||||
// create a local timer for each remote timer
|
||||
ScStwTimer * timer = new ScStwTimer(this, true);
|
||||
this->timers.append(timer);
|
||||
connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged);
|
||||
connect(timer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(QVariant remoteTimer, remoteTimers){
|
||||
int currId = remoteTimer.toMap()["id"].toInt();
|
||||
ScStwTimer::TimerState newState = ScStwTimer::TimerState(remoteTimer.toMap()["state"].toInt());
|
||||
double currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
this->timers[currId]->setStartTime(currentMSecsSinceEpoch - remoteTimer.toMap()["currentTime"].toDouble());
|
||||
|
||||
if(newState >= ScStwTimer::WAITING)
|
||||
this->timers[currId]->setStopTime(currentMSecsSinceEpoch);
|
||||
|
||||
this->timers[currId]->setReactionTime(remoteTimer.toMap()["reactionTime"].toDouble());
|
||||
|
||||
this->timers[currId]->setState(newState, true);
|
||||
|
||||
this->timers[currId]->setLetter(remoteTimer.toMap()["letter"].toString());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwRemoteMonitorRace::addTimer(ScStwTimer* timer) {
|
||||
Q_UNUSED(timer)
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantList ScStwRemoteMonitorRace::getNextStartActionDetails() {
|
||||
int nextActionDelay = 0;
|
||||
double nextActionDelayProg = -1;
|
||||
|
||||
if(this->nextStartAction == AtYourMarks || this->nextStartAction == Ready) {
|
||||
// get the total delay and the delay progress of the next action timer
|
||||
double elapsed = QDateTime::currentMSecsSinceEpoch() - this->nextStartActionDelayStartedAt;
|
||||
nextActionDelay = this->nextStartActionTotalDelay;
|
||||
if(elapsed < 0 || elapsed > nextActionDelay) {
|
||||
elapsed = nextActionDelay;
|
||||
}
|
||||
nextActionDelayProg = elapsed / nextActionDelay;
|
||||
}
|
||||
|
||||
return {
|
||||
this->nextStartAction,
|
||||
nextActionDelay,
|
||||
nextActionDelayProg
|
||||
};
|
||||
}
|
370
ScStwLibraries/sources/client/scstwremoterace.cpp
Normal file
370
ScStwLibraries/sources/client/scstwremoterace.cpp
Normal file
|
@ -0,0 +1,370 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include "scstwremoterace.h"
|
||||
|
||||
ScStwRemoteRace::ScStwRemoteRace(QObject* parent) : ScStwRemoteRace(nullptr, nullptr, parent)
|
||||
{
|
||||
}
|
||||
|
||||
ScStwRemoteRace::ScStwRemoteRace(ScStwClient *scStwClient, ScStwSettings *settings, QObject *parent) : ScStwRace(settings, parent)
|
||||
{
|
||||
this->isReadyForNextState = true;
|
||||
|
||||
this->remoteTimers = {};
|
||||
this->localTimers = {};
|
||||
|
||||
this->setScStwClient(scStwClient);
|
||||
}
|
||||
|
||||
// --------------------------
|
||||
// --- Main Functionality ---
|
||||
// --------------------------
|
||||
|
||||
ScStw::StatusCode ScStwRemoteRace::start(bool asyncronous) {
|
||||
if(this->local())
|
||||
return ScStwRace::start(asyncronous);
|
||||
|
||||
if(this->getState() != ScStwRace::IDLE && this->getState() != ScStwRace::WAITING)
|
||||
return ScStw::CurrentStateNotVaildForOperationError;
|
||||
|
||||
qDebug() << "+ --- starting race";
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(ScStw::StartRaceCommand);
|
||||
|
||||
return ScStw::StatusCode(reply["status"].toInt());
|
||||
}
|
||||
|
||||
ScStw::StatusCode ScStwRemoteRace::cancel() {
|
||||
if(this->local())
|
||||
return ScStwRace::cancel();
|
||||
|
||||
if(this->getState() != PREPAIRING && this->getState() != WAITING && this->getState() != STARTING && this->getState() != RUNNING)
|
||||
return ScStw::CurrentStateNotVaildForOperationError;
|
||||
|
||||
qDebug() << "+ --- stopping race";
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(ScStw::CancelRaceCommand);
|
||||
|
||||
return ScStw::StatusCode(reply["status"].toInt());
|
||||
}
|
||||
|
||||
ScStw::StatusCode ScStwRemoteRace::stop() {
|
||||
if(this->local())
|
||||
return ScStwRace::stop();
|
||||
|
||||
if(this->getState() != ScStwRace::RUNNING && this->getState() != ScStwRace::STARTING)
|
||||
return ScStw::CurrentStateNotVaildForOperationError;
|
||||
|
||||
qDebug() << "+ --- stopping race";
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(ScStw::StopRaceCommand);
|
||||
|
||||
return ScStw::StatusCode(reply["status"].toInt());
|
||||
}
|
||||
|
||||
ScStw::StatusCode ScStwRemoteRace::reset() {
|
||||
if(this->local())
|
||||
return ScStwRace::reset();
|
||||
|
||||
if(this->getState() != ScStwRace::STOPPED && this->getState() != ScStwRace::INCIDENT)
|
||||
return ScStw::CurrentStateNotVaildForOperationError;
|
||||
|
||||
qDebug() << "+ --- resetting race";
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(ScStw::ResetRaceCommand);
|
||||
|
||||
return ScStw::StatusCode(reply["status"].toInt());
|
||||
}
|
||||
|
||||
ScStw::StatusCode ScStwRemoteRace::setTimerDisabled(int timerId, bool disabled) {
|
||||
if(this->state != IDLE && this->state != WAITING)
|
||||
return ScStw::CurrentStateNotVaildForOperationError;
|
||||
|
||||
if(timerId < 0 || timerId - 1 > this->timers.length())
|
||||
return ScStw::ItemNotFoundError;
|
||||
|
||||
qDebug() << "+ --- setting timer " << timerId << " to disabled: " << disabled;
|
||||
|
||||
QVariantMap requestData = {
|
||||
{"timerId", timerId},
|
||||
{"disabled", disabled}
|
||||
};
|
||||
|
||||
QVariantMap reply = this->scStwClient->sendCommand(ScStw::SetTimerDisabledCommand, QJsonValue::fromVariant(requestData));
|
||||
|
||||
qDebug() << "+ --- timer disabled command returned: " << reply;
|
||||
|
||||
return ScStw::StatusCode(reply["status"].toInt());
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// --- Base Station sync ---
|
||||
// -------------------------
|
||||
|
||||
void ScStwRemoteRace::handleClientStateChange() {
|
||||
switch (this->scStwClient->getState()) {
|
||||
case ScStwClient::INITIALISING:
|
||||
// disconnect all local timers from race
|
||||
this->setTimers({}, false);
|
||||
// delete all obsolete remote timers
|
||||
for(ScStwRemoteTimer* oldRemoteTimer : this->remoteTimers)
|
||||
oldRemoteTimer->deleteLater();
|
||||
|
||||
this->remoteTimers.clear();
|
||||
break;
|
||||
case ScStwClient::DISCONNECTED:
|
||||
this->remoteTimers.clear();
|
||||
this->setTimers(this->localTimers, false);
|
||||
emit this->timersChanged();
|
||||
emit this->detailsChanged();
|
||||
emit this->currentStartDelayChanged();
|
||||
this->competitionMode = false;
|
||||
this->setState(IDLE);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ScStwRemoteRace::setTimers(QList<ScStwTimer*> timers, bool deleteOldTimers) {
|
||||
|
||||
// disconnect all signals of all current timers
|
||||
//qDebug() << "SETTING TIMERS";
|
||||
|
||||
foreach(ScStwTimer *existingTimer, this->timers) {
|
||||
disconnect(existingTimer, &ScStwTimer::stateChanged, this, &ScStwRace::handleTimerStateChange);
|
||||
disconnect(existingTimer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged);
|
||||
disconnect(existingTimer, &ScStwTimer::wantsToBeDisabledChanged, this, &ScStwRace::handleTimerWantsToBeDisabledChange);
|
||||
disconnect(existingTimer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged);
|
||||
disconnect(existingTimer, &ScStwTimer::readyStateChanged, this, &ScStwRace::handleTimerReadyStateChange);
|
||||
disconnect(existingTimer, &ScStwTimer::readyStateChanged, this, &ScStwRace::isReadyForNextStateChanged);
|
||||
|
||||
if(deleteOldTimers)
|
||||
existingTimer->deleteLater();
|
||||
}
|
||||
|
||||
this->timers.clear();
|
||||
|
||||
for(ScStwTimer* timer : timers) {
|
||||
this->addTimer(timer);
|
||||
}
|
||||
}
|
||||
|
||||
ScStwRemoteRace::RaceMode ScStwRemoteRace::getMode() {
|
||||
if(this->scStwClient == nullptr || this->scStwClient->getState() != ScStwClient::CONNECTED)
|
||||
return LOCAL;
|
||||
else
|
||||
return REMOTE;
|
||||
}
|
||||
|
||||
bool ScStwRemoteRace::local() {
|
||||
return this->getMode() == LOCAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ScStwAppBackend::handleBaseStationUpdate
|
||||
*
|
||||
* Function to handle an update, sent by the base station, which indicates
|
||||
* that some remote value (like a state) has changed
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
void ScStwRemoteRace::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {
|
||||
switch (key) {
|
||||
case ScStw::RaceDetailsChanged:
|
||||
{
|
||||
this->refreshDetails(data.toMap());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ScStwRemoteRace::refreshDetails(QVariantMap details) {
|
||||
// the details of the race have changed:
|
||||
|
||||
qDebug() << "RACE DETAILS: " << details;
|
||||
|
||||
// competition mode
|
||||
if(this->competitionMode != details["competitionMode"].toBool()) {
|
||||
this->competitionMode = details["competitionMode"].toBool();
|
||||
emit this->competitionModeChanged();
|
||||
}
|
||||
|
||||
// ready sound enabled
|
||||
if(this->readySoundEnabled != details["readySoundEnabled"].toBool()) {
|
||||
this->readySoundEnabled = details["readySoundEnabled"].toBool();
|
||||
emit this->readySoundEnabledChanged();
|
||||
}
|
||||
|
||||
// current start delay
|
||||
this->currentStartTotalDelay = details["currentStartDelay"].toMap()["total"].toInt();
|
||||
this->latestStartDelayProgress = details["currentStartDelay"].toMap()["progress"].toDouble();
|
||||
this->currentStartDelayStartedAt = QDateTime::currentMSecsSinceEpoch() - (this->currentStartTotalDelay * this->latestStartDelayProgress);
|
||||
|
||||
emit this->currentStartDelayChanged();
|
||||
|
||||
// timers
|
||||
this->refreshRemoteTimers(details["timers"].toList());
|
||||
|
||||
// state
|
||||
this->setState(ScStwRace::RaceState(details["state"].toInt()));
|
||||
|
||||
// isReady
|
||||
if(this->state == WAITING) {
|
||||
this->isReadyForNextState = details["isReadyForNextState"].toBool();
|
||||
emit this->isReadyForNextStateChanged();
|
||||
}
|
||||
|
||||
emit this->detailsChanged();
|
||||
}
|
||||
|
||||
void ScStwRemoteRace::rebuildRemoteTimers(QVariantList remoteTimers) {
|
||||
|
||||
qDebug() << "REBUILDING TIMERS";
|
||||
|
||||
// delete all current timers
|
||||
foreach(ScStwTimer * oldTimer, this->timers){
|
||||
oldTimer->deleteLater();
|
||||
}
|
||||
|
||||
this->remoteTimers.clear();
|
||||
this->timers.clear();
|
||||
|
||||
foreach(QVariant remoteTimer, remoteTimers){
|
||||
// create a local timer for each remote timer
|
||||
ScStwRemoteTimer * timer = new ScStwRemoteTimer(this);
|
||||
this->timers.append(timer);
|
||||
this->remoteTimers.append(timer);
|
||||
connect(timer, &ScStwTimer::stateChanged, this, &ScStwRace::timersChanged);
|
||||
connect(timer, &ScStwTimer::reactionTimeChanged, this, &ScStwRace::timersChanged);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScStwRemoteRace::refreshRemoteTimers(QVariantList newRemoteTimers) {
|
||||
|
||||
qDebug() << "REFRESHING TIMERS";
|
||||
|
||||
if(newRemoteTimers.length() != this->remoteTimers.length()){
|
||||
// local timers are out of sync
|
||||
this->rebuildRemoteTimers(newRemoteTimers);
|
||||
qDebug() << "rebuilding remote timers";
|
||||
}
|
||||
|
||||
for(QVariant remoteTimer : newRemoteTimers){
|
||||
int currId = remoteTimer.toMap()["id"].toInt();
|
||||
|
||||
if(this->remoteTimers.length() <= currId)
|
||||
this->rebuildRemoteTimers(newRemoteTimers);
|
||||
|
||||
ScStwTimer::TimerState newState = ScStwTimer::TimerState(remoteTimer.toMap()["state"].toInt());
|
||||
|
||||
qDebug() << "refreshing timers: id: " << currId << " state: " << newState << " readyState: " << remoteTimer.toMap()["readyState"].toInt() << " currentTime: " << remoteTimer.toMap()["currentTime"].toDouble();
|
||||
|
||||
double currentMSecsSinceEpoch = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
this->remoteTimers[currId]->setStartTime(currentMSecsSinceEpoch - remoteTimer.toMap()["currentTime"].toDouble());
|
||||
|
||||
if(newState >= ScStwTimer::WAITING)
|
||||
this->remoteTimers[currId]->setStopTime(currentMSecsSinceEpoch);
|
||||
|
||||
this->remoteTimers[currId]->setReactionTime(remoteTimer.toMap()["reactionTime"].toDouble());
|
||||
this->remoteTimers[currId]->setLetter(remoteTimer.toMap()["letter"].toString());
|
||||
this->remoteTimers[currId]->setReadyState(ScStwTimer::ReadyState(remoteTimer.toMap()["readyState"].toInt()));
|
||||
|
||||
this->remoteTimers[currId]->setState(newState);
|
||||
}
|
||||
|
||||
emit this->timersChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwRemoteRace::addTimer(ScStwTimer* timer) {
|
||||
if(this->local()) {
|
||||
this->localTimers.append(timer);
|
||||
return ScStwRace::addTimer(timer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariantMap ScStwRemoteRace::getCurrentStartDelay() {
|
||||
if(this->local())
|
||||
return ScStwRace::getCurrentStartDelay();
|
||||
|
||||
QVariantMap currentStartDelay = {
|
||||
{"total", -1.0},
|
||||
{"progress", -1.0}
|
||||
};
|
||||
|
||||
if(this->currentStartTotalDelay == -1) {
|
||||
currentStartDelay["progress"] = this->latestStartDelayProgress;
|
||||
}
|
||||
else if(this->getState() == PREPAIRING || this->getState() == WAITING) {
|
||||
// get the total delay and the delay progress of the next action timer
|
||||
double elapsed = QDateTime::currentMSecsSinceEpoch() - this->currentStartDelayStartedAt;
|
||||
currentStartDelay["total"] = this->currentStartTotalDelay;
|
||||
if(elapsed < 0 || elapsed > currentStartDelay["total"].toDouble()) {
|
||||
elapsed = currentStartDelay["total"].toDouble();
|
||||
}
|
||||
currentStartDelay["progress"] = elapsed / currentStartDelay["total"].toDouble();
|
||||
}
|
||||
|
||||
return currentStartDelay;
|
||||
}
|
||||
|
||||
bool ScStwRemoteRace::getIsReadyForNextState() {
|
||||
if(this->local())
|
||||
return ScStwRace::getIsReadyForNextState();
|
||||
|
||||
return this->isReadyForNextState;
|
||||
}
|
||||
|
||||
bool ScStwRemoteRace::getReadySoundEnabled() {
|
||||
if(this->local())
|
||||
return ScStwRace::getReadySoundEnabled();
|
||||
|
||||
return this->readySoundEnabled;
|
||||
}
|
||||
|
||||
void ScStwRemoteRace::refreshCompetitionMode() {
|
||||
if(this->local())
|
||||
return ScStwRace::refreshCompetitionMode();
|
||||
}
|
||||
|
||||
ScStwClient* ScStwRemoteRace::getScStwClient() {
|
||||
return this->scStwClient;
|
||||
}
|
||||
|
||||
void ScStwRemoteRace::setScStwClient(ScStwClient* client) {
|
||||
if(client == this->scStwClient)
|
||||
return;
|
||||
|
||||
this->scStwClient = client;
|
||||
|
||||
if(this->scStwClient != nullptr) {
|
||||
this->scStwClient->addSignalSubscription(ScStw::RaceDetailsChanged);
|
||||
|
||||
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ScStwRemoteRace::handleClientStateChange);
|
||||
connect(this->scStwClient, &ScStwClient::gotSignal, this, &ScStwRemoteRace::handleBaseStationSignal);
|
||||
|
||||
}
|
||||
}
|
104
ScStwLibraries/sources/client/scstwremotesettings.cpp
Normal file
104
ScStwLibraries/sources/client/scstwremotesettings.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include "../../headers/client/scstwremotesettings.h"
|
||||
|
||||
ScStwRemoteSettings::ScStwRemoteSettings(QObject* parent) : ScStwSettings(parent)
|
||||
{
|
||||
this->scStwClient = nullptr;
|
||||
}
|
||||
|
||||
ScStwRemoteSettings::ScStwRemoteSettings(ScStwClient * scStwClient, QObject * parent) : ScStwSettings(parent)
|
||||
{
|
||||
this->setScStwClient(scStwClient);
|
||||
}
|
||||
|
||||
ScStwRemoteSettings::SettingsMode ScStwRemoteSettings::getMode() {
|
||||
if(this->scStwClient == nullptr || this->scStwClient->getState() != ScStwClient::CONNECTED)
|
||||
return LOCAL;
|
||||
else
|
||||
return REMOTE;
|
||||
}
|
||||
|
||||
QVariant ScStwRemoteSettings::readSetting(QString key, int keyInt, int keyLevel) {
|
||||
if(this->getMode() == LOCAL || keyLevel > ScStwSettings::KeyLevel)
|
||||
return ScStwSettings::readSetting(key, keyInt, keyLevel);
|
||||
|
||||
qDebug() << "Setting read: keyLevel: " << keyLevel << " key: " << key;
|
||||
|
||||
ScStw::StatusCode status;
|
||||
QVariant value = this->scStwClient->readRemoteSetting(ScStwSettings::BaseStationSetting(keyInt), &status);
|
||||
|
||||
if(status == ScStw::Success)
|
||||
return value;
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ScStwRemoteSettings::writeSetting(QString key, QVariant value, int keyInt, int keyLevel) {
|
||||
if(this->getMode() == LOCAL || keyLevel > ScStwSettings::KeyLevel)
|
||||
return ScStwSettings::writeSetting(key, value, keyInt, keyLevel);
|
||||
|
||||
|
||||
qDebug() << "Setting write: keyLevel: " << keyLevel << " key: " << key << " value: " << value;
|
||||
|
||||
ScStw::StatusCode res = this->scStwClient->writeRemoteSetting(ScStwSettings::BaseStationSetting(keyInt), value);
|
||||
|
||||
return res == ScStw::Success;
|
||||
}
|
||||
|
||||
bool ScStwRemoteSettings::setDefaultSetting(QString key, QVariant defaultVariant, int keyInt, int keyLevel) {
|
||||
if(this->getMode() == LOCAL || keyLevel > ScStwSettings::KeyLevel)
|
||||
return ScStwSettings::setDefaultSetting(key, defaultVariant, keyInt, keyLevel);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScStwRemoteSettings::handleClientStateChange() {
|
||||
if(this->scStwClient->getState() == ScStwClient::DISCONNECTED)
|
||||
emit this->settingChanged(-1, ScStwSettings::KeyLevel, QVariant());
|
||||
// Dont't need to do that when changing to connected,
|
||||
// as the basestation emits a wildcrd setting changed on connect anyway
|
||||
}
|
||||
|
||||
void ScStwRemoteSettings::handleBaseStationSignal(ScStw::SignalKey key, QVariant data) {
|
||||
switch (key) {
|
||||
case ScStw::SettingChanged:
|
||||
emit this->settingChanged(data.toMap()["key"].toInt(), ScStwSettings::KeyLevel, data.toMap()["value"]);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ScStwClient* ScStwRemoteSettings::getScStwClient() {
|
||||
return this->scStwClient;
|
||||
}
|
||||
|
||||
void ScStwRemoteSettings::setScStwClient(ScStwClient* client) {
|
||||
if(client == this->scStwClient)
|
||||
return;
|
||||
|
||||
this->scStwClient = client;
|
||||
|
||||
if(this->scStwClient != nullptr) {
|
||||
this->scStwClient->addSignalSubscription(ScStw::SettingChanged);
|
||||
|
||||
connect(this->scStwClient, &ScStwClient::stateChanged, this, &ScStwRemoteSettings::handleClientStateChange);
|
||||
connect(this->scStwClient, &ScStwClient::gotSignal, this, &ScStwRemoteSettings::handleBaseStationSignal);
|
||||
}
|
||||
}
|
42
ScStwLibraries/sources/client/scstwremotetimer.cpp
Normal file
42
ScStwLibraries/sources/client/scstwremotetimer.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "../../headers/client/scstwremotetimer.h"
|
||||
|
||||
ScStwRemoteTimer::ScStwRemoteTimer(QObject *parent) : ScStwTimer(parent)
|
||||
{
|
||||
this->readyState = ScStwTimer::getReadyState();
|
||||
}
|
||||
|
||||
ScStwTimer::ReadyState ScStwRemoteTimer::getReadyState() {
|
||||
return this->readyState;
|
||||
}
|
||||
|
||||
void ScStwRemoteTimer::setStartTime(double startTime) {
|
||||
this->startTime = startTime;
|
||||
}
|
||||
|
||||
void ScStwRemoteTimer::setStopTime(double stopTime) {
|
||||
this->stopTime = stopTime;
|
||||
}
|
||||
|
||||
void ScStwRemoteTimer::setReactionTime(double reactionTime) {
|
||||
this->reactionTime = reactionTime;
|
||||
emit this->reactionTimeChanged();
|
||||
}
|
||||
|
||||
void ScStwRemoteTimer::setLetter(QString newLetter) {
|
||||
this->letter = newLetter;
|
||||
}
|
||||
|
||||
void ScStwRemoteTimer::setReadyState(ScStwTimer::ReadyState readyState) {
|
||||
if(this->readyState != readyState) {
|
||||
this->readyState = readyState;
|
||||
emit this->readyStateChanged(readyState);
|
||||
}
|
||||
}
|
||||
|
||||
void ScStwRemoteTimer::setState(TimerState newState){
|
||||
if(this->state != newState) {
|
||||
this->state = newState;
|
||||
qDebug() << "+ [INFO][REMOTETIMER] timer state changed: " << newState;
|
||||
emit this->stateChanged(this->state);
|
||||
}
|
||||
}
|
|
@ -26,16 +26,23 @@ ScStwLibraries::ScStwLibraries(QObject *parent) : QObject(parent)
|
|||
void ScStwLibraries::init() {
|
||||
#ifdef ScStwLibraries_QML
|
||||
qmlRegisterType<ScStw>("de.itsblue.ScStw", 2, 0, "ScStw");
|
||||
qRegisterMetaType<ScStw::BaseStationSetting>("ScStw::BaseStationSetting");
|
||||
qRegisterMetaType<ScStwSettings::BaseStationSetting>("ScStwSettings::BaseStationSetting");
|
||||
qRegisterMetaType<ScStw::SocketCommand>("ScStw::SocketCommand");
|
||||
qRegisterMetaType<ScStw::StatusCode>("ScStw::StatusCode");
|
||||
|
||||
qmlRegisterType<ScStwRace>("de.itsblue.ScStw", 2, 0, "ScStwRace");
|
||||
qmlRegisterType<ScStwTimer>("de.itsblue.ScStw", 2, 0, "ScStwTimer");
|
||||
|
||||
#ifdef ScStwLibraries_ClientLibs
|
||||
qmlRegisterType<ScStwClient>("de.itsblue.ScStw", 2, 0, "ScStwClient");
|
||||
qmlRegisterType<ScStwSettings>("de.itsblue.ScStw", 2, 0, "ScStwSettings");
|
||||
qmlRegisterUncreatableType<ScStwSetting>("de.itsblue.ScStw", 2, 0, "ScStwSetting", "The ScStwSetting is manage by a ScStwSettings instance and therefore not creatable");
|
||||
qmlRegisterType<ScStwRemoteRace>("de.itsblue.ScStw", 2, 0, "ScStwRemoteRace");
|
||||
qmlRegisterType<ScStwRemoteSettings>("de.itsblue.ScStw", 2, 0, "ScStwRemoteSettings");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
qRegisterMetaType<ScStw::PadState>("ScStw::PadState");
|
||||
}
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
59
ScStwLibraries/sources/scstwsetting.cpp
Normal file
59
ScStwLibraries/sources/scstwsetting.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include "scstwsetting.h"
|
||||
#include "scstwsettings.h"
|
||||
#include <QtDebug>
|
||||
|
||||
ScStwSetting::ScStwSetting(int key, int keyLevel, ScStwSettings*scStwSettings, QObject *parent) : QObject(parent)
|
||||
{
|
||||
this->scStwSettings = scStwSettings;
|
||||
connect(this->scStwSettings, &ScStwSettings::settingChanged, this, &ScStwSetting::handleSettingChange);
|
||||
this->key = key;
|
||||
this->keyLevel = keyLevel;
|
||||
this->handleSettingChange(-1, this->keyLevel, QVariant());
|
||||
}
|
||||
|
||||
QVariant ScStwSetting::getValue() {
|
||||
qDebug() << "Getting setting: " << this->key << " has to reload: " << this->hasToReload;
|
||||
if(this->hasToReload) {
|
||||
this->valueCache = this->scStwSettings->readSetting(this->key, this->keyLevel);
|
||||
this->hasToReload = false;
|
||||
}
|
||||
|
||||
return this->valueCache;
|
||||
}
|
||||
|
||||
void ScStwSetting::setValue(QVariant value) {
|
||||
if(value != this->valueCache) {
|
||||
this->scStwSettings->writeSetting(this->key, this->keyLevel, value);
|
||||
}
|
||||
}
|
||||
|
||||
void ScStwSetting::handleSettingChange(int key, int keyLevel, QVariant value) {
|
||||
if(keyLevel == this->keyLevel && key == this->key) {
|
||||
this->valueCache = value;
|
||||
qDebug() << "value changed!!! key: " << key << " new value " << value;
|
||||
emit this->valueChanged();
|
||||
}
|
||||
else if(key == -1 && this->key != -1 && this->keyLevel != -1 && this->keyLevel == keyLevel) {
|
||||
qDebug() << "value changed!!! key: " << key << " new value " << value;
|
||||
this->hasToReload = true;
|
||||
emit this->valueChanged();
|
||||
}
|
||||
}
|
165
ScStwLibraries/sources/scstwsettings.cpp
Normal file
165
ScStwLibraries/sources/scstwsettings.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
/****************************************************************************
|
||||
** ScStw Libraries
|
||||
** Copyright (C) 2020 Itsblue development
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
#include "../headers/scstwsettings.h"
|
||||
|
||||
ScStwSettings::ScStwSettings(QObject *parent) : QObject(parent)
|
||||
{
|
||||
#ifdef RASPI
|
||||
QString path = "/root/.config/ScStwBasestation";
|
||||
#else
|
||||
QString path = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
|
||||
#endif
|
||||
QDir dir(path);
|
||||
if(!dir.mkpath(path))
|
||||
qFatal("[FATAL] Failed to create writable directory for settings at %s", qPrintable(path));
|
||||
|
||||
this->settingsFile = new QFile(path + "/settings.json");
|
||||
|
||||
if(!this->settingsFile->open(QFile::ReadWrite))
|
||||
qFatal("[FATAL] Couldn't open settings file %s", qPrintable(path + "/settings.json"));
|
||||
|
||||
if(!this->loadSettingsFromFile() && this->settingsFile->size() != 0) {
|
||||
this->writeSettingsToFile();
|
||||
qWarning("[WARNING] Settings file (%s) was of invalid format and therefore overwritten!", qPrintable(path + "/settings.json"));
|
||||
}
|
||||
|
||||
connect(this, &ScStwSettings::settingChanged, this, &ScStwSettings::writeSettingsToFile);
|
||||
|
||||
this->registerKeyLevelConverters(ScStwSettings::KeyLevel, &ScStwSettings::keyToString, &ScStwSettings::keyToType);
|
||||
|
||||
this->setDefaultSetting(ScStwSettings::BaseStationSetting::ReadySoundEnableSetting, false);
|
||||
this->setDefaultSetting(ScStwSettings::BaseStationSetting::ReadySoundDelaySetting, 0);
|
||||
this->setDefaultSetting(ScStwSettings::BaseStationSetting::AtYourMarksSoundEnableSetting, false);
|
||||
this->setDefaultSetting(ScStwSettings::BaseStationSetting::AtYourMarksSoundDelaySetting, 0);
|
||||
this->setDefaultSetting(ScStwSettings::SoundVolumeSetting, 1);
|
||||
this->setDefaultSetting(ScStwSettings::CompetitionModeSetting, false);
|
||||
}
|
||||
|
||||
QVariant ScStwSettings::readSetting(BaseStationSetting key) {
|
||||
return this->readSetting(key, 0);
|
||||
}
|
||||
|
||||
QVariant ScStwSettings::readSetting(int key, int keyLevel) {
|
||||
if(this->keyToStringConverters.contains(keyLevel))
|
||||
return this->readSetting(this->keyToStringConverters[keyLevel](key), key, keyLevel);
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ScStwSettings::writeSetting(BaseStationSetting key, QVariant value) {
|
||||
return this->writeSetting(key, 0, value);
|
||||
}
|
||||
|
||||
bool ScStwSettings::writeSetting(int key, int keyLevel, QVariant value) {
|
||||
if(this->keyToStringConverters.contains(keyLevel))
|
||||
return this->writeSetting(this->keyToStringConverters[keyLevel](key), value, key, keyLevel);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScStwSettings::setDefaultSetting(BaseStationSetting key, QVariant defaultValue) {
|
||||
return this->setDefaultSetting(key, 0, defaultValue);
|
||||
}
|
||||
|
||||
bool ScStwSettings::setDefaultSetting(int key, int keyLevel, QVariant defaultValue) {
|
||||
if(this->keyToStringConverters.contains(keyLevel))
|
||||
return this->setDefaultSetting(this->keyToStringConverters[keyLevel](key), defaultValue, key, keyLevel);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant ScStwSettings::readSetting(QString key, int keyInt, int keyLevel) {
|
||||
Q_UNUSED(keyInt)
|
||||
Q_UNUSED(keyLevel)
|
||||
|
||||
if(this->settingsCache.contains(key))
|
||||
return this->settingsCache[key];
|
||||
else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ScStwSettings::writeSetting(QString key, QVariant value, int keyInt, int keyLevel) {
|
||||
|
||||
// check if the value type is valid
|
||||
if(!this->keyToTypeConverters.contains(keyLevel) || !value.convert(this->keyToTypeConverters[keyLevel](keyInt)) || value.type() == QVariant::Invalid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// write the setting
|
||||
if(!this->settingsCache.contains(key))
|
||||
this->settingsCache.insert(key, value);
|
||||
else if (this->settingsCache[key] == value)
|
||||
return true;
|
||||
else
|
||||
this->settingsCache[key] = value;
|
||||
|
||||
emit this->settingChanged(keyInt, keyLevel, value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwSettings::setDefaultSetting(QString key, QVariant defaultValue, int keyInt, int keyLevel) {
|
||||
if(!this->settingsCache.contains(key))
|
||||
return this->writeSetting(key, defaultValue, keyInt, keyLevel);
|
||||
return true;
|
||||
}
|
||||
|
||||
ScStwSetting * ScStwSettings::getSetting(int key, int keyLevel) {
|
||||
if(!this->internalSettingHandlers.contains(keyLevel))
|
||||
this->internalSettingHandlers.insert(keyLevel, {});
|
||||
|
||||
if(!this->internalSettingHandlers[keyLevel].contains(key))
|
||||
this->internalSettingHandlers[keyLevel].insert(key, new ScStwSetting(key, keyLevel, this, this));
|
||||
|
||||
return this->internalSettingHandlers[keyLevel][key];
|
||||
}
|
||||
|
||||
bool ScStwSettings::registerKeyLevelConverters(int keyLevel, keyToStringConverter keyToStringConverterFunction, keyToTypeConverter keyToTypeConverterFunction) {
|
||||
if(this->keyToStringConverters.contains(keyLevel))
|
||||
return false;
|
||||
|
||||
this->keyToStringConverters.insert(keyLevel, keyToStringConverterFunction);
|
||||
this->keyToTypeConverters.insert(keyLevel, keyToTypeConverterFunction);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* File handling
|
||||
*/
|
||||
|
||||
bool ScStwSettings::writeSettingsToFile() {
|
||||
QJsonDocument doc = QJsonDocument::fromVariant(this->settingsCache);
|
||||
|
||||
// overwrite file
|
||||
this->settingsFile->reset();
|
||||
this->settingsFile->write(doc.toJson(QJsonDocument::Indented));
|
||||
this->settingsFile->flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwSettings::loadSettingsFromFile() {
|
||||
QJsonDocument doc = QJsonDocument::fromJson(this->settingsFile->readAll());
|
||||
|
||||
if(doc.toVariant().type() != QVariant::Map)
|
||||
return false;
|
||||
|
||||
this->settingsCache = doc.toVariant().toMap();
|
||||
return true;
|
||||
}
|
|
@ -23,45 +23,46 @@ ScStwSoundPlayer::ScStwSoundPlayer(QObject *parent) : QObject(parent)
|
|||
this->waitLoop = new QEventLoop(this);
|
||||
this->waitTimer = new QTimer(this);
|
||||
|
||||
this->soundFiles.insert(0, {{"path","qrc:/sound/AtYourMarksSound.wav"}, {"duration", 1000}});
|
||||
this->soundFiles.insert(1, {{"path","qrc:/sound/ReadySound.wav"}, {"duration", 570}});
|
||||
this->soundFiles.insert(2, {{"path","qrc:/sound/StartsignalSoundExtended.wav"}, {"duration", 3200}});
|
||||
this->soundFiles.insert(3, {{"path","qrc:/sound/FalseStartSound.wav"}, {"duration", 2000}});
|
||||
this->soundFiles.insert(AtYourMarks, {{"path","qrc:/sound/AtYourMarksSound.wav"}, {"duration", 1000}});
|
||||
this->soundFiles.insert(Ready, {{"path","qrc:/sound/ReadySound.wav"}, {"duration", 570}});
|
||||
this->soundFiles.insert(Start, {{"path","qrc:/sound/StartsignalSoundExtended.wav"}, {"duration", 3200}});
|
||||
this->soundFiles.insert(FalseStart, {{"path","qrc:/sound/FalseStartSound.wav"}, {"duration", 2000}});
|
||||
|
||||
this->soundEffect = new QSoundEffect(this);
|
||||
this->soundEffect->setLoopCount(1);
|
||||
this->_initializeSondEffect();
|
||||
|
||||
connect(this, &ScStwSoundPlayer::playbackStarted, this->waitLoop, &QEventLoop::quit);
|
||||
connect(this->soundEffect, &QSoundEffect::playingChanged, this->waitLoop, &QEventLoop::quit);
|
||||
}
|
||||
|
||||
bool ScStwSoundPlayer::play(int action, double volume, double *timeOfStart) {
|
||||
if(!this->soundFiles.contains(action))
|
||||
return false;
|
||||
|
||||
if(action > 2 || action < 0)
|
||||
return false;
|
||||
ScStwSoundPlayer::PlayResult ScStwSoundPlayer::play(ScStwSoundPlayer::StartSound sound, double volume, double *timeOfStart) {
|
||||
if(!this->soundFiles.contains(sound)) {
|
||||
qDebug() << "[ERROR][SoundPlayer] Sound file was not found for sound" << sound;
|
||||
return ScStwSoundPlayer::Error;
|
||||
}
|
||||
|
||||
// stop playback
|
||||
if(this->soundEffect->isPlaying())
|
||||
this->soundEffect->stop();
|
||||
|
||||
// update currently playing action
|
||||
this->currentlyPlayingAction = action;
|
||||
this->currentlyPlayingSound = sound;
|
||||
|
||||
// update volume
|
||||
this->soundEffect->setVolume(volume);
|
||||
if(!this->_setSoundVolume(volume))
|
||||
return Error;
|
||||
|
||||
// load
|
||||
this->soundEffect->setSource(this->soundFiles[action]["path"].toString());
|
||||
this->soundEffect->setSource(this->soundFiles[sound]["path"].toString());
|
||||
|
||||
// wait for the effect to load
|
||||
QEventLoop loop;
|
||||
while(this->soundEffect->status() != QSoundEffect::Ready) {
|
||||
qDebug() << "[DEBUG][Sound] Sound is not ready yet, status is: " << this->soundEffect->status();
|
||||
QObject::connect(this->soundEffect, &QSoundEffect::statusChanged, &loop, &QEventLoop::quit);
|
||||
loop.exec();
|
||||
}
|
||||
|
||||
qDebug() << "[DEBUG][Sound] Playing sound now: " << sound;
|
||||
|
||||
// start
|
||||
this->soundEffect->play();
|
||||
|
||||
|
@ -76,45 +77,34 @@ bool ScStwSoundPlayer::play(int action, double volume, double *timeOfStart) {
|
|||
*timeOfStart = this->playingStartedAt;
|
||||
}
|
||||
|
||||
if(action < 2)
|
||||
if(sound < Start)
|
||||
return this->waitForSoundFinish();
|
||||
|
||||
return true;
|
||||
return ScStwSoundPlayer::Success;
|
||||
}
|
||||
|
||||
bool ScStwSoundPlayer::cancel(double volume) {
|
||||
bool ScStwSoundPlayer::cancel() {
|
||||
if(!this->soundEffect->isPlaying() )
|
||||
return false;
|
||||
|
||||
// stop playback
|
||||
this->soundEffect->stop();
|
||||
this->waitLoop->quit();
|
||||
|
||||
if(this->currentlyPlayingAction != 2)
|
||||
return true;
|
||||
|
||||
// update volume
|
||||
this->soundEffect->setVolume(volume);
|
||||
|
||||
// load
|
||||
this->soundEffect->setSource(this->soundFiles[3]["path"].toString());
|
||||
|
||||
// play
|
||||
this->soundEffect->play();
|
||||
this->waitLoop->exit(-1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {
|
||||
ScStwSoundPlayer::PlayResult ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {
|
||||
if(!this->soundEffect->isPlaying())
|
||||
return false;
|
||||
return ScStwSoundPlayer::Error;
|
||||
|
||||
// wait until the audio output reports the sound is over
|
||||
waitLoop->exec();
|
||||
if(waitLoop->exec() == -1)
|
||||
return ScStwSoundPlayer::Cancelled;
|
||||
|
||||
// wait until the sound is actually over
|
||||
// the timeOffset is the buffer time before the audio started!
|
||||
int timeOffset = this->soundFiles[this->currentlyPlayingAction]["duration"].toDouble() - (QDateTime::currentMSecsSinceEpoch() - playingStartedAt);
|
||||
int timeOffset = this->soundFiles[this->currentlyPlayingSound]["duration"].toDouble() - (QDateTime::currentMSecsSinceEpoch() - playingStartedAt);
|
||||
|
||||
if(timeOffset > 0) {
|
||||
QTimer timer;
|
||||
|
@ -124,9 +114,99 @@ bool ScStwSoundPlayer::waitForSoundFinish(double *timeOfStop) {
|
|||
|
||||
// calculate the point in time where the sound playback actually ended
|
||||
if(timeOfStop != nullptr) {
|
||||
int latency = this->playingStartedAt + this->soundFiles[this->currentlyPlayingAction]["duration"].toDouble();
|
||||
int latency = this->playingStartedAt + this->soundFiles[this->currentlyPlayingSound]["duration"].toDouble();
|
||||
*timeOfStop = QDateTime::currentMSecsSinceEpoch() - latency;
|
||||
}
|
||||
|
||||
return ScStwSoundPlayer::Success;
|
||||
}
|
||||
|
||||
bool ScStwSoundPlayer::isPlaying() {
|
||||
return this->soundEffect->isPlaying();
|
||||
}
|
||||
|
||||
#ifdef ScStwLibraries_Raspi
|
||||
void ScStwSoundPlayer::_initializeSondEffect() {
|
||||
this->_audioOutputDevice = nullptr;
|
||||
for(QAudioDeviceInfo info : QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) {
|
||||
qDebug() << info.deviceName();
|
||||
if(info.deviceName().contains("Headphones"))
|
||||
this->_audioOutputDevice = new QAudioDeviceInfo(info);
|
||||
}
|
||||
|
||||
if(this->_audioOutputDevice == nullptr)
|
||||
this->_audioOutputDevice = new QAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice());
|
||||
|
||||
this->soundEffect = new QSoundEffect(*this->_audioOutputDevice, this);
|
||||
this->soundEffect->setLoopCount(1);
|
||||
}
|
||||
#else
|
||||
void ScStwSoundPlayer::_initializeSondEffect() {
|
||||
this->_audioOutputDevice = new QAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice());
|
||||
this->soundEffect = new QSoundEffect(*this->_audioOutputDevice, this);
|
||||
this->soundEffect->setLoopCount(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ScStwLibraries_Raspi
|
||||
bool ScStwSoundPlayer::_setSoundVolume(double volume) {
|
||||
|
||||
QString cardName = this->_audioOutputDevice->deviceName();
|
||||
QStringRef shortCardName = cardName.midRef(cardName.indexOf(QLatin1String("="), 0) + 1);
|
||||
|
||||
int cardIndex = snd_card_get_index(shortCardName.toLocal8Bit().constData());
|
||||
QString soundDevice = QString(QLatin1String("hw:%1")).arg(cardIndex);
|
||||
qDebug() << "[INFO][SoundPlayer] Using audio device: " << soundDevice;
|
||||
|
||||
long min, max;
|
||||
snd_mixer_t *handle;
|
||||
snd_mixer_selem_id_t *sid;
|
||||
snd_mixer_elem_t *elem;
|
||||
|
||||
if(snd_mixer_open(&handle, 0) < 0) {
|
||||
qDebug() << "[ERROR][SoundPlayer] Could not open mixer";
|
||||
return false;
|
||||
}
|
||||
if(snd_mixer_selem_register(handle, NULL, NULL) < 0) {
|
||||
qDebug() << "[ERROR][SoundPlayer] Could not register selem";
|
||||
return false;
|
||||
}
|
||||
if(snd_mixer_attach(handle, soundDevice.toStdString().c_str()) < 0) {
|
||||
qDebug() << "[ERROR][SoundPlayer] Could not attach mixer";
|
||||
return false;
|
||||
}
|
||||
if(snd_mixer_load(handle) < 0) {
|
||||
qDebug() << "[ERROR][SoundPlayer] Could not load mixer";
|
||||
return false;
|
||||
}
|
||||
|
||||
// set volume for all channels
|
||||
snd_mixer_selem_id_alloca(&sid);
|
||||
bool success = false;
|
||||
for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) {
|
||||
snd_mixer_selem_get_id(elem, sid);
|
||||
if (!snd_mixer_selem_is_active(elem))
|
||||
continue;
|
||||
|
||||
elem = snd_mixer_find_selem(handle, sid);
|
||||
if(!elem)
|
||||
continue;
|
||||
|
||||
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
|
||||
snd_mixer_selem_set_playback_volume_all(elem, min + (volume) * (max - min));
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
snd_mixer_close(handle);
|
||||
|
||||
this->soundEffect->setVolume(1);
|
||||
|
||||
return success;
|
||||
}
|
||||
#else
|
||||
bool ScStwSoundPlayer::_setSoundVolume(double volume) {
|
||||
this->soundEffect->setVolume(volume);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,18 +18,23 @@
|
|||
|
||||
#include "../headers/scstwtimer.h"
|
||||
|
||||
ScStwTimer::ScStwTimer(QObject *parent, bool directControlEnabled, QString letter) : QObject(parent)
|
||||
ScStwTimer::ScStwTimer(QObject* parent) : ScStwTimer("", parent)
|
||||
{
|
||||
this->directControlEnabled = directControlEnabled;
|
||||
}
|
||||
|
||||
ScStwTimer::ScStwTimer(QString letter, QObject *parent) : QObject(parent)
|
||||
{
|
||||
if(letter.length() > 1)
|
||||
this->letter = letter[0];
|
||||
else
|
||||
this->letter = letter;
|
||||
|
||||
//qDebug() << "Timer created with letter: " << letter;
|
||||
|
||||
this->startTime = 0;
|
||||
this->stopTime = 0;
|
||||
this->reactionTime = 0;
|
||||
this->wantsToBeDisabled = false;
|
||||
|
||||
this->state = IDLE;
|
||||
}
|
||||
|
@ -48,7 +53,7 @@ bool ScStwTimer::start(double timeOfStart) {
|
|||
|
||||
if(timeOfStart - QDateTime::currentMSecsSinceEpoch() > 0) {
|
||||
this->setState(STARTING);
|
||||
QTimer::singleShot(timeOfStart - QDateTime::currentMSecsSinceEpoch(), [=](){
|
||||
QTimer::singleShot(timeOfStart - QDateTime::currentMSecsSinceEpoch(), [=]() {
|
||||
if(this->state == STARTING)
|
||||
this->setState(RUNNING);
|
||||
});
|
||||
|
@ -64,13 +69,27 @@ bool ScStwTimer::start(double timeOfStart) {
|
|||
}
|
||||
}
|
||||
|
||||
void ScStwTimer::technicalIncident() {
|
||||
qDebug() << "[INFO][TIMER] Timer got a technical incident";
|
||||
|
||||
this->setState(INCIDENT);
|
||||
}
|
||||
|
||||
bool ScStwTimer::wildcard() {
|
||||
if(this->state != STARTING)
|
||||
return false;
|
||||
|
||||
this->setState(WILDCARD);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScStwTimer::handleClimberStart(double timeOfStart) {
|
||||
this->reactionTime = timeOfStart - this->startTime;
|
||||
qDebug() << "+ [INFO][TIMER] reaction time: " << this->reactionTime;
|
||||
|
||||
if(this->reactionTime <= 0){
|
||||
this->stop(FailStop);
|
||||
return;
|
||||
if(this->reactionTime <= 100 && this->reactionTime) {
|
||||
qDebug() << "[INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime;
|
||||
this->setState(FAILING);
|
||||
}
|
||||
|
||||
emit this->reactionTimeChanged();
|
||||
|
@ -80,6 +99,11 @@ bool ScStwTimer::cancel() {
|
|||
if(!(this->state == IDLE || this->state == STARTING || this->state == RUNNING))
|
||||
return false;
|
||||
|
||||
qDebug() << "[INFO][TIMER] Timer was cancelled";
|
||||
this->reactionTime = 0;
|
||||
this->startTime = 0;
|
||||
this->stopTime = 0;
|
||||
|
||||
this->setState(CANCELLED);
|
||||
return true;
|
||||
}
|
||||
|
@ -89,63 +113,66 @@ bool ScStwTimer::stop() {
|
|||
}
|
||||
|
||||
bool ScStwTimer::stop(double timeOfStop) {
|
||||
return this->stop(ManualStop, timeOfStop);
|
||||
}
|
||||
|
||||
bool ScStwTimer::stop(StopReason reason) {
|
||||
return this->stop(reason, QDateTime::currentMSecsSinceEpoch());
|
||||
}
|
||||
|
||||
bool ScStwTimer::stop(StopReason reason, double timeOfStop) {
|
||||
if(this->state != STARTING && this->state != RUNNING && this->state != WAITING){
|
||||
if(this->state != RUNNING)
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (reason) {
|
||||
case ManualStop: {
|
||||
if(this->state == STARTING){
|
||||
this->setState(CANCELLED);
|
||||
}
|
||||
else {
|
||||
this->stopTime = timeOfStop;
|
||||
this->stopTime = timeOfStop;
|
||||
|
||||
// trigger an external state refresh to set the state to either WON or LOST depending on the other timers values (see ScStwRace::refreshTimerStates())
|
||||
this->setState(WAITING);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FailStop: {
|
||||
qDebug() << "[INFO][TIMER] False Start detected: " << "start Time: " << startTime << " reactionTime: " << reactionTime;
|
||||
this->setState(FAILED);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// trigger an external state refresh to set the state to either WON or LOST depending on the other timers values (see ScStwRace::refreshTimerStates())
|
||||
this->setState(WAITING);
|
||||
|
||||
qDebug() << "[INFO][TIMER] Stopped: " << "start Time: " << startTime << " stopTime: " << stopTime << " stoppedTime: " << this->getCurrentTime() << " reactionTime: " << reactionTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwTimer::setResult(TimerState result) {
|
||||
if(this->state != WAITING)
|
||||
|
||||
QList<ScStwTimer::TimerState> allowedStates = {
|
||||
STARTING,
|
||||
RUNNING,
|
||||
WAITING,
|
||||
WON,
|
||||
FAILING,
|
||||
FAILED
|
||||
};
|
||||
|
||||
if(!allowedStates.contains(this->state))
|
||||
return false;
|
||||
|
||||
/* The reasons why it has to accept all these states:
|
||||
*
|
||||
* STARTING: To set a timer to WILDCARD when its opponent has done a false start
|
||||
* RUNNING: To set a timer to WILDCARD when its opponent has done a false start that was received with a delay
|
||||
* WAITING: To set a timer to either WON or LOST
|
||||
* WON: To set a timer to LOST when its opponent has won the race but their trigger was delayed
|
||||
* FAILING: To set a timer to either FAILED or WILDCARD
|
||||
* FAILED: To set a timer to WILDCARD when its opponent did an earlier false start but their tirgger was delayed
|
||||
*/
|
||||
|
||||
switch (result) {
|
||||
case WON:
|
||||
this->setState(WON);
|
||||
return true;
|
||||
case LOST:
|
||||
this->setState(LOST);
|
||||
return true;
|
||||
case WON:
|
||||
if(this->state == WAITING || this->state == WON) {
|
||||
this->setState(result);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case WILDCARD:
|
||||
case FAILED:
|
||||
if(this->state == STARTING || this->state == RUNNING || this->state == FAILED || this->state == FAILING) {
|
||||
this->setState(result);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScStwTimer::reset(){
|
||||
if( this->state < WON || this->state == DISABLED ){
|
||||
bool ScStwTimer::reset() {
|
||||
if( this->state < WON || this->state == DISABLED ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -157,61 +184,28 @@ bool ScStwTimer::reset(){
|
|||
return true;
|
||||
}
|
||||
|
||||
ScStwTimer::ReadyState ScStwTimer::getReadyState() {
|
||||
return this->state == IDLE ? ScStwTimer::IsReady : ScStwTimer::NotInIdleState;
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// --- helper functions ---
|
||||
// ------------------------
|
||||
|
||||
bool ScStwTimer::setStartTime(double startTime) {
|
||||
if(!this->directControlEnabled)
|
||||
return false;
|
||||
|
||||
this->startTime = startTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwTimer::setStopTime(double stopTime) {
|
||||
if(!this->directControlEnabled)
|
||||
return false;
|
||||
|
||||
this->stopTime = stopTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwTimer::setReactionTime(double reactionTime) {
|
||||
if(!this->directControlEnabled)
|
||||
return false;
|
||||
|
||||
this->reactionTime = reactionTime;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScStwTimer::setState(TimerState newState, bool force) {
|
||||
if(!this->directControlEnabled || !force)
|
||||
return false;
|
||||
|
||||
this->setState(newState);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ScStwTimer::setState(TimerState newState){
|
||||
void ScStwTimer::setState(TimerState newState) {
|
||||
if(this->state == DISABLED && newState != IDLE)
|
||||
return;
|
||||
|
||||
if(this->state == INCIDENT && newState != IDLE)
|
||||
return;
|
||||
|
||||
if(this->state != newState) {
|
||||
this->state = newState;
|
||||
qDebug() << "+ [INFO][TIMER] timer state changed: " << newState;
|
||||
emit this->stateChanged();
|
||||
qDebug() << "[INFO][TIMER] timer state changed: " << newState;
|
||||
emit this->stateChanged(newState);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScStwTimer::setLetter(QString newLetter) {
|
||||
if(!this->directControlEnabled)
|
||||
return false;
|
||||
|
||||
this->letter = newLetter;
|
||||
return true;
|
||||
}
|
||||
|
||||
ScStwTimer::TimerState ScStwTimer::getState() {
|
||||
return this->state;
|
||||
}
|
||||
|
@ -238,7 +232,6 @@ QString ScStwTimer::getLetter() {
|
|||
}
|
||||
|
||||
QString ScStwTimer::getText() {
|
||||
|
||||
QString newText = "";
|
||||
int newTime = 0;
|
||||
switch (this->state) {
|
||||
|
@ -248,24 +241,33 @@ QString ScStwTimer::getText() {
|
|||
case ScStwTimer::STARTING:
|
||||
newTime = 0;
|
||||
break;
|
||||
case ScStwTimer::WAITING:
|
||||
newText = "please wait...";
|
||||
break;
|
||||
case ScStwTimer::RUNNING:
|
||||
newTime = this->getCurrentTime();
|
||||
break;
|
||||
case ScStwTimer::WAITING:
|
||||
newText = "please wait...";
|
||||
break;
|
||||
case ScStwTimer::WON:
|
||||
newTime = this->getCurrentTime();
|
||||
break;
|
||||
case ScStwTimer::LOST:
|
||||
newTime = this->getCurrentTime();
|
||||
break;
|
||||
case ScStwTimer::FAILING:
|
||||
newText = "please wait...";
|
||||
break;
|
||||
case ScStwTimer::FAILED:
|
||||
newText = "false start";
|
||||
break;
|
||||
case ScStwTimer::WILDCARD:
|
||||
newText = "wildcard";
|
||||
break;
|
||||
case ScStwTimer::CANCELLED:
|
||||
newText = "cancelled";
|
||||
break;
|
||||
case ScStwTimer::INCIDENT:
|
||||
newText = "Technical incident!";
|
||||
break;
|
||||
case ScStwTimer::DISABLED:
|
||||
newText = "---";
|
||||
break;
|
||||
|
@ -278,8 +280,37 @@ QString ScStwTimer::getText() {
|
|||
}
|
||||
|
||||
void ScStwTimer::setDisabled(bool disabled) {
|
||||
if(this->isDisabled() == disabled)
|
||||
return;
|
||||
|
||||
if(disabled)
|
||||
this->setState(DISABLED);
|
||||
else
|
||||
this->setState(IDLE);
|
||||
|
||||
emit this->readyStateChanged(this->getReadyState());
|
||||
|
||||
}
|
||||
|
||||
void ScStwTimer::setWantsToBeDisabled(bool wantsToBeDisabled) {
|
||||
if(this->wantsToBeDisabled == wantsToBeDisabled)
|
||||
return;
|
||||
|
||||
qDebug() << "Wants to be disabled changed: " << wantsToBeDisabled;
|
||||
|
||||
this->wantsToBeDisabled = wantsToBeDisabled;
|
||||
|
||||
emit this->wantsToBeDisabledChanged(this, wantsToBeDisabled);
|
||||
}
|
||||
|
||||
bool ScStwTimer::getWantsToBeDisabled() {
|
||||
return this->wantsToBeDisabled;
|
||||
}
|
||||
|
||||
bool ScStwTimer::isRunning() {
|
||||
return this->state == RUNNING;
|
||||
}
|
||||
|
||||
bool ScStwTimer::isDisabled() {
|
||||
return this->state == DISABLED;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@ ScStwAppThemeManager::ScStwAppThemeManager(QObject *parent) : QObject(parent)
|
|||
|
||||
{"success", "#6bd43b"},
|
||||
{"error", "#e03b2f"},
|
||||
{"warning", "#e0b928"},
|
||||
{"warning", "#d6ae1e"},
|
||||
|
||||
{"line", "grey"},
|
||||
|
||||
|
@ -174,3 +174,7 @@ QString ScStwAppThemeManager::lighter(QString color, double factor) {
|
|||
qcolor.setHsv(h,s,v * factor);
|
||||
return qcolor.name();
|
||||
}
|
||||
|
||||
QString ScStwAppThemeManager::getThemeName() {
|
||||
return this->currentTheme->getName();
|
||||
}
|
||||
|
|
1
qt-openssl-encryption
Submodule
1
qt-openssl-encryption
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 05fbf562c3435f3bbff10a68c031ff465e81d337
|
Reference in a new issue