mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-21 05:50:18 +08:00
Merge branch '3.6.0' of https://github.com/Rsl1122/Plan-PlayerAnalytics
This commit is contained in:
commit
941fab9e9d
@ -1,5 +1,7 @@
|
||||
package main.java.com.djrapitops.plan.data.analysis;
|
||||
|
||||
import main.java.com.djrapitops.plan.ui.html.graphs.WorldMapCreator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -19,10 +21,12 @@ public class GeolocationPart extends RawData {
|
||||
|
||||
private final Map<String, Integer> geoLocations;
|
||||
private final Map<String, String> geoCodes;
|
||||
private final Map<String, Integer> geoCodeCounts;
|
||||
|
||||
public GeolocationPart() {
|
||||
geoLocations = new HashMap<>();
|
||||
geoCodes = new HashMap<>();
|
||||
geoCodeCounts = new HashMap<>();
|
||||
|
||||
String[] countries = new String[]{"Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas, The", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Brazil", "British Virgin Islands", "Brunei", "Bulgaria", "Burkina Faso", "Burma", "Burundi", "Cabo Verde", "Cambodia", "Cameroon", "Canada", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Colombia", "Comoros", "Congo, Democratic Republic of the", "Congo, Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba", "Curacao", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Islas Malvinas)", "Faroe Islands", "Fiji", "Finland", "France", "French Polynesia", "Gabon", "Gambia, The", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guam", "Guatemala", "Guernsey", "Guinea-Bissau", "Guinea", "Guyana", "Haiti", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea, North", "Korea, South", "Kosovo", "Kuwait", "Kyrgyzstan", "Laos", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", "Macau", "Macedonia", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Mauritania", "Mauritius", "Mexico", "Micronesia, Federated States of", "Moldova", "Monaco", "Mongolia", "Montenegro", "Morocco", "Mozambique", "Namibia", "Nepal", "Netherlands", "New Caledonia", "New Zealand", "Nicaragua", "Nigeria", "Niger", "Niue", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Poland", "Portugal", "Puerto Rico", "Qatar", "Romania", "Russia", "Rwanda", "Saint Kitts and Nevis", "Saint Lucia", "Saint Martin", "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Sint Maarten", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Sudan", "Spain", "Sri Lanka", "Sudan", "Suriname", "Swaziland", "Sweden", "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "Timor-Leste", "Togo", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela", "Vietnam", "Virgin Islands", "West Bank", "Yemen", "Zambia", "Zimbabwe"};
|
||||
String[] codes = new String[]{"AFG", "ALB", "DZA", "ASM", "AND", "AGO", "AIA", "ATG", "ARG", "ARM", "ABW", "AUS", "AUT", "AZE", "BHM", "BHR", "BGD", "BRB", "BLR", "BEL", "BLZ", "BEN", "BMU", "BTN", "BOL", "BIH", "BWA", "BRA", "VGB", "BRN", "BGR", "BFA", "MMR", "BDI", "CPV", "KHM", "CMR", "CAN", "CYM", "CAF", "TCD", "CHL", "CHN", "COL", "COM", "COD", "COG", "COK", "CRI", "CIV", "HRV", "CUB", "CUW", "CYP", "CZE", "DNK", "DJI", "DMA", "DOM", "ECU", "EGY", "SLV", "GNQ", "ERI", "EST", "ETH", "FLK", "FRO", "FJI", "FIN", "FRA", "PYF", "GAB", "GMB", "GEO", "DEU", "GHA", "GIB", "GRC", "GRL", "GRD", "GUM", "GTM", "GGY", "GNB", "GIN", "GUY", "HTI", "HND", "HKG", "HUN", "ISL", "IND", "IDN", "IRN", "IRQ", "IRL", "IMN", "ISR", "ITA", "JAM", "JPN", "JEY", "JOR", "KAZ", "KEN", "KIR", "KOR", "PRK", "KSV", "KWT", "KGZ", "LAO", "LVA", "LBN", "LSO", "LBR", "LBY", "LIE", "LTU", "LUX", "MAC", "MKD", "MDG", "MWI", "MYS", "MDV", "MLI", "MLT", "MHL", "MRT", "MUS", "MEX", "FSM", "MDA", "MCO", "MNG", "MNE", "MAR", "MOZ", "NAM", "NPL", "NLD", "NCL", "NZL", "NIC", "NGA", "NER", "NIU", "MNP", "NOR", "OMN", "PAK", "PLW", "PAN", "PNG", "PRY", "PER", "PHL", "POL", "PRT", "PRI", "QAT", "ROU", "RUS", "RWA", "KNA", "LCA", "MAF", "SPM", "VCT", "WSM", "SMR", "STP", "SAU", "SEN", "SRB", "SYC", "SLE", "SGP", "SXM", "SVK", "SVN", "SLB", "SOM", "ZAF", "SSD", "ESP", "LKA", "SDN", "SUR", "SWZ", "SWE", "CHE", "SYR", "TWN", "TJK", "TZA", "THA", "TLS", "TGO", "TON", "TTO", "TUN", "TUR", "TKM", "TUV", "UGA", "UKR", "ARE", "GBR", "USA", "URY", "UZB", "VUT", "VEN", "VNM", "VGB", "WBG", "YEM", "ZMB", "ZWE"};
|
||||
@ -32,6 +36,7 @@ public class GeolocationPart extends RawData {
|
||||
|
||||
geoLocations.put(country, 0);
|
||||
geoCodes.put(country, countryCode);
|
||||
geoCodeCounts.put(countryCode, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,38 +46,20 @@ public class GeolocationPart extends RawData {
|
||||
}
|
||||
|
||||
private void choroplethMapValues() {
|
||||
StringBuilder locations = new StringBuilder("[");
|
||||
StringBuilder z = new StringBuilder("[");
|
||||
StringBuilder text = new StringBuilder("[");
|
||||
String[] choropleth = WorldMapCreator.choroplethMapValues(geoLocations, geoCodes);
|
||||
|
||||
int i = 0;
|
||||
int size = geoLocations.size();
|
||||
for (Map.Entry<String, Integer> entrySet : geoLocations.entrySet()) {
|
||||
String country = entrySet.getKey();
|
||||
String code = geoCodes.getOrDefault(country, "UNK");
|
||||
int amount = entrySet.getValue();
|
||||
addValue("geomapseries", WorldMapCreator.createDataSeries(geoCodeCounts));
|
||||
|
||||
z.append("\"").append(amount).append("\"");
|
||||
locations.append("\"").append(country).append("\"");
|
||||
text.append("\"").append(code).append("\"");
|
||||
|
||||
if (i < size - 1) {
|
||||
locations.append(",");
|
||||
z.append(",");
|
||||
text.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
locations.append("]");
|
||||
z.append("]");
|
||||
text.append("]");
|
||||
|
||||
addValue("geomapz", z.toString());
|
||||
addValue("geomapcountries", locations.toString());
|
||||
addValue("geomapcodes", text.toString());
|
||||
addValue("geomapz", choropleth[0]);
|
||||
addValue("geomapcountries", choropleth[1]);
|
||||
addValue("geomapcodes", choropleth[2]);
|
||||
}
|
||||
|
||||
public void addGeoloc(String country) {
|
||||
geoLocations.computeIfPresent(country, (computedCountry, amount) -> amount + 1);
|
||||
String countryCode = geoCodes.get(country);
|
||||
if (countryCode != null) {
|
||||
geoCodeCounts.computeIfPresent(countryCode, (computedCountry, amount) -> amount + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ public class SeriesCreator {
|
||||
Point point = points.get(i);
|
||||
double y = point.getY();
|
||||
long date = (long) point.getX();
|
||||
arrayBuilder.append("{x:").append(date).append(",y:").append(y).append("}");
|
||||
arrayBuilder.append("[").append(date).append(",").append(y).append("]");
|
||||
if (i < size - 1) {
|
||||
arrayBuilder.append(",");
|
||||
}
|
||||
|
@ -0,0 +1,58 @@
|
||||
package main.java.com.djrapitops.plan.ui.html.graphs;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WorldMapCreator {
|
||||
|
||||
public static String createDataSeries(Map<String, Integer> geoCodeCounts) {
|
||||
StringBuilder arrayBuilder = new StringBuilder("[");
|
||||
|
||||
int i = 0;
|
||||
int size = geoCodeCounts.size();
|
||||
for (Map.Entry<String, Integer> entry : geoCodeCounts.entrySet()) {
|
||||
String geoCode = entry.getKey();
|
||||
Integer players = entry.getValue();
|
||||
if (players != 0) {
|
||||
arrayBuilder.append("{'code':'").append(geoCode).append("','value':").append(players).append("}");
|
||||
if (i < size - 1) {
|
||||
arrayBuilder.append(",");
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
|
||||
arrayBuilder.append("]");
|
||||
return arrayBuilder.toString();
|
||||
}
|
||||
|
||||
public static String[] choroplethMapValues(Map<String, Integer> geoLocations, Map<String, String> geoCodes) {
|
||||
StringBuilder locations = new StringBuilder("[");
|
||||
StringBuilder z = new StringBuilder("[");
|
||||
StringBuilder text = new StringBuilder("[");
|
||||
|
||||
int i = 0;
|
||||
int size = geoLocations.size();
|
||||
for (Map.Entry<String, Integer> entrySet : geoLocations.entrySet()) {
|
||||
String country = entrySet.getKey();
|
||||
String code = geoCodes.getOrDefault(country, "UNK");
|
||||
int amount = entrySet.getValue();
|
||||
|
||||
z.append("\"").append(amount).append("\"");
|
||||
locations.append("\"").append(country).append("\"");
|
||||
text.append("\"").append(code).append("\"");
|
||||
|
||||
if (i < size - 1) {
|
||||
locations.append(",");
|
||||
z.append(",");
|
||||
text.append(",");
|
||||
}
|
||||
}
|
||||
|
||||
locations.append("]");
|
||||
z.append("]");
|
||||
text.append("]");
|
||||
|
||||
return new String[]{z.toString(), locations.toString(), text.toString()};
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" href="https://puu.sh/tK0KL/6aa2ba141b.ico" type="image/x-icon"/>
|
||||
<script src="https://use.fontawesome.com/df48eb908b.js"></script>
|
||||
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
|
||||
<style>
|
||||
header {
|
||||
position: fixed;
|
||||
@ -656,7 +655,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div style="width:100%;">
|
||||
<div id="cloropleth"></div>
|
||||
<div id="choropleth" style="width: 100%; height: 700px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -667,7 +666,9 @@
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
|
||||
<script src="https://code.highcharts.com/stock/highstock.js"></script>
|
||||
<script src="https://code.highcharts.com/stock/highstock.js"></script>
|
||||
<script src="https://code.highcharts.com/maps/modules/map.js"></script>
|
||||
<script src="https://code.highcharts.com/mapdata/custom/world.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>
|
||||
<script>
|
||||
@ -726,6 +727,52 @@
|
||||
valueDecimals: 0
|
||||
}
|
||||
};
|
||||
var activitySeries = {
|
||||
name: 'Players',
|
||||
colorByPoint: true,
|
||||
data: [{
|
||||
name: 'Active',
|
||||
y: %active%
|
||||
}, {
|
||||
name: 'Inactive',
|
||||
y: %inactive%,
|
||||
sliced: true,
|
||||
selected: true
|
||||
}, {
|
||||
name: 'Single Join',
|
||||
y: %joinleaver%
|
||||
}, {
|
||||
name: 'Banned',
|
||||
y: %banned%
|
||||
}]
|
||||
};
|
||||
var gmData = %gmdata%;
|
||||
var gmSeries = {
|
||||
name: 'GM Usage',
|
||||
colorByPoint: true,
|
||||
data: [{
|
||||
name: 'Survival',
|
||||
y: gmData[0],
|
||||
sliced: true,
|
||||
selected: true
|
||||
}, {
|
||||
name: 'Creative',
|
||||
y: gmData[1]
|
||||
}, {
|
||||
name: 'Adventure',
|
||||
y: gmData[2]
|
||||
}, {
|
||||
name: 'Spectator',
|
||||
y: gmData[3]
|
||||
}]
|
||||
};
|
||||
var mapSeries = {
|
||||
name: 'Players',
|
||||
type: 'map',
|
||||
mapData: Highcharts.maps['custom/world'],
|
||||
data: %geomapseries%,
|
||||
joinBy: ['iso-a3', 'code']
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
function playersChart() {
|
||||
@ -905,31 +952,12 @@
|
||||
showInLegend: true
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'Players',
|
||||
colorByPoint: true,
|
||||
data: [{
|
||||
name: 'Active',
|
||||
y: %active%,
|
||||
sliced: true,
|
||||
selected: true
|
||||
}, {
|
||||
name: 'Inactive',
|
||||
y: %inactive%
|
||||
}, {
|
||||
name: 'Single Join',
|
||||
y: %joinleaver%
|
||||
}, {
|
||||
name: 'Banned',
|
||||
y: %banned%
|
||||
}]
|
||||
}]
|
||||
series: [activitySeries]
|
||||
});
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
function gmPie() {
|
||||
var gmData = %gmdata%;
|
||||
function gmPie() {
|
||||
var myChart = Highcharts.chart('gmPie', {
|
||||
chart: {
|
||||
plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false,
|
||||
@ -951,25 +979,7 @@
|
||||
showInLegend: true
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'GM Usage',
|
||||
colorByPoint: true,
|
||||
data: [{
|
||||
name: 'Survival',
|
||||
y: gmData[0],
|
||||
sliced: true,
|
||||
selected: true
|
||||
}, {
|
||||
name: 'Creative',
|
||||
y: gmData[1]
|
||||
}, {
|
||||
name: 'Adventure',
|
||||
y: gmData[2]
|
||||
}, {
|
||||
name: 'Spectator',
|
||||
y: gmData[3]
|
||||
}]
|
||||
}]
|
||||
series: [gmSeries]
|
||||
});
|
||||
};
|
||||
</script>
|
||||
@ -1109,47 +1119,23 @@
|
||||
|
||||
</script>
|
||||
<script>
|
||||
// Geolocation map
|
||||
CLOROPLETH = document.getElementById('cloropleth');
|
||||
var data = [{
|
||||
type: 'choropleth',
|
||||
locationmode: "country names",
|
||||
locations: %geomapcountries% ,
|
||||
z: %geomapz% ,
|
||||
text: %geomapcodes% ,
|
||||
colorscale: [
|
||||
[0, 'rgb(38, 127, 0)'], [1, 'rgb(220, 220, 220)']],
|
||||
autocolorscale: false,
|
||||
reversescale: true,
|
||||
marker: {
|
||||
line: {
|
||||
color: 'rgb(100,100,100)',
|
||||
width: 0.5
|
||||
}
|
||||
},
|
||||
tick0: 0,
|
||||
zmin: 0,
|
||||
dtick: 1000,
|
||||
colorbar: {
|
||||
autotic: false,
|
||||
tickprefix: '',
|
||||
title: 'Players'
|
||||
}
|
||||
}];
|
||||
var layout = {
|
||||
title: '',
|
||||
autosize: false,
|
||||
width: window.innerWidth*0.7,
|
||||
height: window.innerHeight*0.7,
|
||||
geo:{
|
||||
showframe: false,
|
||||
showcoastlines: false,
|
||||
projection:{
|
||||
type: 'mercator'
|
||||
}
|
||||
}
|
||||
};
|
||||
Plotly.plot(CLOROPLETH, data, layout, {showLink: false});
|
||||
function worldMap() {
|
||||
var myChart = Highcharts.mapChart('choropleth', {
|
||||
title: {
|
||||
text: 'Geolocation Map'
|
||||
},
|
||||
chart: {
|
||||
animation: true
|
||||
},
|
||||
colorAxis: {
|
||||
min: 1,
|
||||
type: 'logarithmic',
|
||||
minColor: '#EEFFEE',
|
||||
maxColor: '#267f00'
|
||||
},
|
||||
series: [mapSeries]
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
// Navigation & Refresh time clock
|
||||
@ -1187,7 +1173,7 @@
|
||||
playersChart2();
|
||||
tpsChart();
|
||||
resourceChart();
|
||||
worldChart();
|
||||
worldMap();
|
||||
countUpTimer();
|
||||
|
||||
function openFunc(i) {
|
||||
|
Loading…
Reference in New Issue
Block a user