From eb7ba92807afb7444c8d463f2bfd01be7177fbc0 Mon Sep 17 00:00:00 2001 From: devhyper <57877914+devhyper@users.noreply.github.com> Date: Mon, 29 May 2023 19:54:43 -0700 Subject: [PATCH] p2pool: Detailed statistics --- pages/Advanced.qml | 5 ++ pages/Mining.qml | 31 +++++++++ pages/MiningStats.qml | 129 +++++++++++++++++++++++++++++++++++ qml.qrc | 1 + src/p2pool/P2PoolManager.cpp | 18 +++++ src/p2pool/P2PoolManager.h | 4 +- 6 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 pages/MiningStats.qml diff --git a/pages/Advanced.qml b/pages/Advanced.qml index 6889607939..f6a407bc67 100644 --- a/pages/Advanced.qml +++ b/pages/Advanced.qml @@ -77,6 +77,7 @@ ColumnLayout { property Item currentView property Item previousView property Mining miningView: Mining { } + property MiningStats miningStatsView: MiningStats { } property TxKey prooveView: TxKey { } property SharedRingDB sharedRingDBView: SharedRingDB { } property Sign signView: Sign { } @@ -105,6 +106,10 @@ ColumnLayout { name: "Mining" PropertyChanges { target: stateView; currentView: stateView.miningView } PropertyChanges { target: root; panelHeight: stateView.miningView.miningHeight + 140 } + }, State { + name: "MiningStats" + PropertyChanges { target: stateView; currentView: stateView.miningStatsView } + PropertyChanges { target: root; panelHeight: stateView.miningStatsView.miningStatsHeight + 140 } }, State { name: "Prove" PropertyChanges { target: stateView; currentView: stateView.prooveView } diff --git a/pages/Mining.qml b/pages/Mining.qml index 025f8b92a5..f3cb9d4e83 100644 --- a/pages/Mining.qml +++ b/pages/Mining.qml @@ -379,6 +379,37 @@ Rectangle { } } + ColumnLayout { + Layout.fillWidth: true + Layout.alignment : Qt.AlignTop | Qt.AlignLeft + + MoneroComponents.Label { + id: statisticsLabel + visible: persistentSettings.allow_p2pool_mining + color: MoneroComponents.Style.defaultFontColor + text: qsTr("Statistics") + translationManager.emptyString + fontSize: 16 + } + } + + ColumnLayout { + Layout.fillWidth: true + spacing: 16 + + MoneroComponents.StandardButton { + id: miningStatsButton + small: true + primary: false + text: qsTr("Open mining statistics") + translationManager.emptyString + enabled: appWindow.isMining + visible: persistentSettings.allow_p2pool_mining + onClicked: { + p2poolManager.getStats(); + stateView.state = "MiningStats"; + } + } + } + ListModel { id: chainModel diff --git a/pages/MiningStats.qml b/pages/MiningStats.qml new file mode 100644 index 0000000000..29bb575f9e --- /dev/null +++ b/pages/MiningStats.qml @@ -0,0 +1,129 @@ +// Copyright (c) 2014-2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import QtQml.Models 2.2 +import QtQuick 2.9 +import QtQuick.Layouts 1.1 +import "../components" as MoneroComponents +import moneroComponents.P2PoolManager 1.0 + +Rectangle { + id: root + color: "transparent" + property alias miningStatsHeight: miningStatsView.height + property int entryHeight: 24 + property int entryPixelSize: 14 + + Timer { + id: timer + interval: 5000 + running: stateView.state === "MiningStats"; + repeat: true + onTriggered: update() + } + + function update() + { + if (persistentSettings.allow_p2pool_mining) { + p2poolManager.getStats(); + } + } + + function recursivelyFindPairs(statsMap, depth) + { + for (var key in statsMap) + { + var value = statsMap[key]; + if (typeof value === 'object') { + miningStatsModel.append({"key": key + ":", "value": "", "depth": depth}); + recursivelyFindPairs(value, depth + 1); + } + else { + miningStatsModel.append({"key": key + ":", "value": value.toString(), "depth": depth}); + } + } + } + + function updateMiningStats(statsMap) + { + miningStatsModel.clear(); + recursivelyFindPairs(statsMap, 0); + } + + ListModel { id: miningStatsModel } + + Column { + spacing: entryHeight + + MoneroComponents.StandardButton { + id: backButton + text: qsTr("Back") + translationManager.emptyString; + width: 100 + primary: false + onClicked: { + stateView.state = "Mining"; + } + } + + ListView { + visible: true + id: miningStatsView + width: 1500 + height: count * entryHeight + entryHeight + model: miningStatsModel + interactive: false + + delegate: Rectangle { + id: miningStatsDelegate + color: "transparent" + height: entryHeight + Layout.fillWidth: true + + RowLayout { + MoneroComponents.TextBlock { + Layout.fillWidth: true + Layout.leftMargin: depth * entryPixelSize + font.pixelSize: entryPixelSize + text: key + translationManager.emptyString + } + + MoneroComponents.TextBlock { + Layout.fillWidth: true + color: MoneroComponents.Style.dimmedFontColor + font.pixelSize: entryPixelSize + text: value + translationManager.emptyString + } + } + } + } + } + + Component.onCompleted: { + p2poolManager.p2poolStats.connect(updateMiningStats); + } +} diff --git a/qml.qrc b/qml.qrc index 37b180af25..e306a4a28b 100644 --- a/qml.qrc +++ b/qml.qrc @@ -26,6 +26,7 @@ pages/History.qml pages/AddressBook.qml pages/Mining.qml + pages/MiningStats.qml components/ContextMenu.qml components/ContextMenuItem.qml components/NetworkStatusItem.qml diff --git a/src/p2pool/P2PoolManager.cpp b/src/p2pool/P2PoolManager.cpp index e4655c14d1..7a77059f21 100644 --- a/src/p2pool/P2PoolManager.cpp +++ b/src/p2pool/P2PoolManager.cpp @@ -140,6 +140,24 @@ void P2PoolManager::getStatus() { return; } +void P2PoolManager::getStats() +{ + QVariantMap statsMap; + QString statsPath = m_p2poolPath + "/stats"; + QDirIterator it(statsPath, QDir::Filter::Files, QDirIterator::Subdirectories); + while (it.hasNext()) { + QFile statsFile(it.next()); + statsFile.open(QIODevice::ReadOnly); + QTextStream statsOut(&statsFile); + QByteArray data; + statsOut >> data; + statsFile.close(); + QVariantMap jsonMap = QJsonDocument::fromJson(data).object().toVariantMap(); + statsMap.insert(jsonMap); + } + emit p2poolStats(statsMap); +} + bool P2PoolManager::start(const QString &flags, const QString &address, const QString &chain, const QString &threads) { // prepare command line arguments and pass to p2pool diff --git a/src/p2pool/P2PoolManager.h b/src/p2pool/P2PoolManager.h index f16795678b..abd814000b 100644 --- a/src/p2pool/P2PoolManager.h +++ b/src/p2pool/P2PoolManager.h @@ -50,13 +50,15 @@ class P2PoolManager : public QObject Q_INVOKABLE void exit(); Q_INVOKABLE bool isInstalled(); Q_INVOKABLE void getStatus(); + Q_INVOKABLE void getStats(); Q_INVOKABLE void download(); + private: - bool running(NetworkType::Type nettype) const; signals: void p2poolStartFailure() const; void p2poolStatus(bool isMining, int hashrate) const; + void p2poolStats(QVariantMap statsMap) const; void p2poolDownloadFailure() const; void p2poolDownloadSuccess() const;