/** * Calculates the data sets for the specified {@link Stat}. * * @param stat stat to calculate the data sets for */ private void calculateDataSets(final Stat stat) { // Data points for each data set, inside being mapped from loop to value. final Map<LineChartDataSet, Map<Integer, Int>> dataSetPointsMap = new HashMap<>(); final boolean mergeMinGas = stat.hasMinGas && !separateMinsGasCheckBox.isSelected(); final String[] eventFields; // Event fields to query eventually if (stat.hasMinGas) { final boolean includeMins = minsCheckBox.isSelected(); final boolean includeGas = gasCheckBox.isSelected(); if (includeMins && includeGas) eventFields = stat.eventFields; else if (includeMins) eventFields = new String[] {stat.eventFields[0]}; else if (includeGas) eventFields = new String[] {stat.eventFields[1]}; else eventFields = new String[0]; } else eventFields = stat.eventFields; // Calculate data points maps for (final Event event : repProc.replay.trackerEvents.events) { if (event.id != ITrackerEvents.ID_PLAYER_STATS) continue; final DataModel<LineChartDataSet> model = modelByPlayerIds[event.getPlayerId()]; if (model == null) continue; // One extra player stat event is recorded when a user leaves (at the same loop) even if at // the same loop there was a // scheduled player stat event. So we have to exclude the last player stat event (to avoid the // chart getting // "screwed"). (This for example contains mineralsCurrent = 0.) // Note: if there's a scheduled stat event when the player left, this will be excluded // wrongly, // but I don't care, it won't make any noticable difference... if (event.loop == repProc.usersByPlayerId[event.getPlayerId()].leaveLoop) continue; // Data sets per event fields for (int i = 0; i < eventFields.length; i++) { final String field = eventFields[i]; final LineChartDataSet dataSet = model.getDataSetList().get(mergeMinGas ? 0 : i); Map<Integer, Int> pointsMap = dataSetPointsMap.get(dataSet); if (pointsMap == null) dataSetPointsMap.put(dataSet, pointsMap = new HashMap<>()); final Integer loop = Integer.valueOf(event.loop); Int point = pointsMap.get(loop); if (point == null) { pointsMap.put(loop, point = new Int()); } int value = ((PlayerStatsEvent) event).stats.<Integer>get(field); if (field == PlayerStatsEvent.F_FOOD_MADE || field == PlayerStatsEvent.F_FOOD_USED) value >>= 12; point.value += value; } } // Convert data points maps to arrays for (final Chart<LineChartDataSet> chart : chartList) { for (final DataModel<LineChartDataSet> model : chart.getDataModelList()) { for (final LineChartDataSet dataSet : model.getDataSetList()) { final Map<Integer, Int> pointsMap = dataSetPointsMap.get(dataSet); if (pointsMap == null) continue; // Data points are needed sorted by loop final List<Entry<Integer, Int>> dataPointList = new ArrayList<>(pointsMap.entrySet()); Collections.sort( dataPointList, new Comparator<Entry<Integer, Int>>() { @Override public int compare(Entry<Integer, Int> o1, Entry<Integer, Int> o2) { return o1.getKey().compareTo(o2.getKey()); } }); int i = 0; final int[] loops = new int[pointsMap.size()]; final int[] values = new int[pointsMap.size()]; for (final Entry<Integer, Int> dataPoint : dataPointList) { loops[i] = dataPoint.getKey(); values[i] = dataPoint.getValue().value; i++; } dataSet.setLoops(loops); dataSet.setValues(values); dataSet.calculateValueMax(); } } } }