PartyChartDataManagerImpl.java

  1. /*
  2.  * Copyright 2010-2025 James Pether Sörling
  3.  *
  4.  * Licensed under the Apache License, Version 2.0 (the "License");
  5.  * you may not use this file except in compliance with the License.
  6.  * You may obtain a copy of the License at
  7.  *
  8.  *   http://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  * Unless required by applicable law or agreed to in writing, software
  11.  * distributed under the License is distributed on an "AS IS" BASIS,
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  * See the License for the specific language governing permissions and
  14.  * limitations under the License.
  15.  *
  16.  *  $Id$
  17.  *  $HeadURL$
  18.  */
  19. package com.hack23.cia.web.impl.ui.application.views.common.chartfactory.impl;

  20. import java.time.ZoneId;
  21. import java.time.ZonedDateTime;
  22. import java.util.ArrayList;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.Map.Entry;
  26. import java.util.Objects;
  27. import java.util.Optional;
  28. import java.util.function.Function;
  29. import java.util.stream.Collectors;

  30. import org.dussan.vaadin.dcharts.DCharts;
  31. import org.dussan.vaadin.dcharts.base.elements.XYseries;
  32. import org.dussan.vaadin.dcharts.data.DataSeries;
  33. import org.dussan.vaadin.dcharts.options.Series;
  34. import org.springframework.stereotype.Service;

  35. import com.hack23.cia.model.internal.application.data.committee.impl.RiksdagenVoteDataBallotPartyPeriodSummaryEmbeddedId;
  36. import com.hack23.cia.model.internal.application.data.committee.impl.ViewRiksdagenVoteDataBallotPartySummaryDaily;
  37. import com.hack23.cia.service.api.DataContainer;
  38. import com.hack23.cia.web.impl.ui.application.views.common.chartfactory.api.PartyChartDataManager;
  39. import com.vaadin.ui.AbstractOrderedLayout;

  40. /**
  41.  * The Class ChartDataManagerImpl.
  42.  */
  43. @Service
  44. public final class PartyChartDataManagerImpl extends AbstractChartDataManagerImpl implements PartyChartDataManager {


  45.     /** The Constant NUMBER_BALLOTS. */
  46.     private static final String NUMBER_BALLOTS = "Number ballots";

  47.     /** The Constant PARTY_ABSENT. */
  48.     private static final String PARTY_ABSENT = "Party Absent";

  49.     /** The Constant PARTY_WON. */
  50.     private static final String PARTY_WON = "Party Won";

  51.     /** The party map. */
  52.     private Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> partyMap;

  53.     /**
  54.      * Instantiates a new party chart data manager impl.
  55.      */
  56.     public PartyChartDataManagerImpl() {
  57.         super();
  58.     }


  59.     /**
  60.      * Adds the party data.
  61.      *
  62.      * @param dataSeries       the data series
  63.      * @param list             the list
  64.      * @param dataValueFunction the data value function
  65.      */
  66.     private static void addPartyData(final DataSeries dataSeries,
  67.             final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list, final Function<ViewRiksdagenVoteDataBallotPartySummaryDaily, Object> dataValueFunction) {
  68.         dataSeries.newSeries();
  69.         for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
  70.             if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
  71.                 dataSeries.add(
  72.                         DateUtils.formatDate(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
  73.                         dataValueFunction.apply(viewRiksdagenVoteDataBallotPartySummaryDaily));
  74.             }
  75.         }
  76.     }


  77.     /**
  78.      * Adds the ballot data.
  79.      *
  80.      * @param dataValueCalculator the data value calculator
  81.      * @param dataSeries          the data series
  82.      * @param series              the series
  83.      * @param entry               the entry
  84.      */
  85.     private void addBallotData(final DataValueCalculator dataValueCalculator, final DataSeries dataSeries,
  86.             final Series series,
  87.             final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry) {
  88.         series.addSeries(new XYseries().setLabel(getPartyName(entry.getKey())));

  89.         dataSeries.newSeries();
  90.         final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = entry.getValue();
  91.         for (final ViewRiksdagenVoteDataBallotPartySummaryDaily viewRiksdagenVoteDataBallotPartySummaryDaily : list) {
  92.             if (viewRiksdagenVoteDataBallotPartySummaryDaily != null) {
  93.                 dataSeries.add(
  94.                         DateUtils.formatDate(viewRiksdagenVoteDataBallotPartySummaryDaily.getEmbeddedId().getVoteDate()),
  95.                                 dataValueCalculator.getDataValue(viewRiksdagenVoteDataBallotPartySummaryDaily));
  96.             }
  97.         }
  98.     }





  99.     /**
  100.      * Creates the party age chart.
  101.      *
  102.      * @param content the content
  103.      */
  104.     @Override
  105.     public void createPartyAgeChart(final AbstractOrderedLayout content) {
  106.             createPartyBallotChart(content,viewRiksdagenVoteDataBallotPartySummaryDaily -> ZonedDateTime.now(ZoneId.of("Europe/Stockholm")).getYear() - viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyAvgBornYear().intValue());
  107.     }

  108.     /**
  109.      * Creates the party ballot chart.
  110.      *
  111.      * @param content the content
  112.      * @param dataValueCalculator            the data value calculator
  113.      * @return the d charts
  114.      */
  115.     private void createPartyBallotChart(final AbstractOrderedLayout content,final DataValueCalculator dataValueCalculator) {
  116.         final Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> map = getPartyMap();

  117.         final DataSeries dataSeries = new DataSeries();

  118.         final Series series = new Series();

  119.         for (final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry : map.entrySet()) {

  120.             if (!"-".equals(entry.getKey())) {
  121.                 addBallotData(dataValueCalculator, dataSeries, series, entry);
  122.             }
  123.         }

  124.         ChartUtils.addChart(content,"Party ballot chart", new DCharts().setDataSeries(dataSeries).setOptions(getChartOptions().createOptionsXYDateFloatLegendInsideOneColumn(series)).show(), true);
  125.     }


  126.     /**
  127.      * Creates the party gender chart.
  128.      *
  129.      * @param content the content
  130.      */
  131.     @Override
  132.     public void createPartyGenderChart(final AbstractOrderedLayout content) {

  133.         createPartyBallotChart(content,viewRiksdagenVoteDataBallotPartySummaryDaily -> 100 - viewRiksdagenVoteDataBallotPartySummaryDaily.getPartyAvgPercentageMale().intValue());

  134.     }

  135.     /**
  136.      * Creates the party line chart.
  137.      *
  138.      * @param content the content
  139.      * @param partyId the party id
  140.      */
  141.     @Override
  142.     public void createPartyLineChart(final AbstractOrderedLayout content,final String partyId) {

  143.         final List<ViewRiksdagenVoteDataBallotPartySummaryDaily> list = getViewRiksdagenVoteDataBallotPartySummaryDaily(
  144.                 partyId);

  145.         if (list != null) {
  146.             final Series series = new Series().addSeries(new XYseries().setLabel(PARTY_WON))
  147.                     .addSeries(new XYseries().setLabel(PARTY_ABSENT));

  148.             final DataSeries dataSeries = new DataSeries();

  149.             addPartyData(dataSeries, list, ViewRiksdagenVoteDataBallotPartySummaryDaily::getPartyWonPercentage);
  150.             addPartyData(dataSeries, list, ViewRiksdagenVoteDataBallotPartySummaryDaily::getPartyPercentageAbsent);

  151.             ChartUtils.addChart(content,"Party result by", new DCharts().setDataSeries(dataSeries).setOptions(getChartOptions().createOptionsPartyLineChart(series)).show(), true);
  152.         }
  153.     }


  154.     /**
  155.      * Creates the party winner chart.
  156.      *
  157.      * @param content the content
  158.      */
  159.     @Override
  160.     public void createPartyWinnerChart(final AbstractOrderedLayout content) {

  161.         final Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> map = getPartyMap();

  162.         final DataSeries dataSeries = new DataSeries();

  163.         final Series series = new Series();

  164.         for (final Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> entry : map.entrySet()) {
  165.             series.addSeries(new XYseries().setLabel(getPartyName(entry.getKey())));
  166.             addPartyData(dataSeries, entry.getValue(), ViewRiksdagenVoteDataBallotPartySummaryDaily::getPartyWonPercentage);
  167.         }

  168.         series.addSeries(new XYseries().setLabel(NUMBER_BALLOTS));
  169.         addPartyData(dataSeries, getMaxSizeViewRiksdagenVoteDataBallotPartySummaryDaily(), ViewRiksdagenVoteDataBallotPartySummaryDaily::getNumberBallots);

  170.         ChartUtils.addChart(content,"Party winner by daily ballot average", new DCharts().setDataSeries(dataSeries).setOptions(getChartOptions().createOptionsXYDateFloatLegendInsideOneColumn(series)).show(), true);
  171.     }


  172.     /**
  173.      * Gets the max size view riksdagen vote data ballot party summary daily.
  174.      *
  175.      * @return the max size view riksdagen vote data ballot party summary daily
  176.      */
  177.     private List<ViewRiksdagenVoteDataBallotPartySummaryDaily> getMaxSizeViewRiksdagenVoteDataBallotPartySummaryDaily() {
  178.         initPartyMap();

  179.         final Optional<Entry<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>>> first = partyMap.entrySet()
  180.                 .stream().sorted((e1, e2) -> Integer.compare(e2.getValue().size(), e1.getValue().size())

  181.         ).findFirst();

  182.         if (first.isPresent()) {
  183.             return first.get().getValue();
  184.         } else {
  185.             return new ArrayList<>();
  186.         }
  187.     }


  188.     /**
  189.      * Gets the party map.
  190.      *
  191.      * @return the party map
  192.      */
  193.     private Map<String, List<ViewRiksdagenVoteDataBallotPartySummaryDaily>> getPartyMap() {
  194.         initPartyMap();

  195.         return partyMap;
  196.     }



  197.     /**
  198.      * Gets the view riksdagen vote data ballot party summary daily.
  199.      *
  200.      * @param party
  201.      *            the party
  202.      * @return the view riksdagen vote data ballot party summary daily
  203.      */
  204.     private List<ViewRiksdagenVoteDataBallotPartySummaryDaily> getViewRiksdagenVoteDataBallotPartySummaryDaily(
  205.             final String party) {
  206.         initPartyMap();

  207.         return partyMap.get(party);
  208.     }


  209.     /**
  210.      * Inits the party map.
  211.      */
  212.     private synchronized void initPartyMap() {
  213.         if (partyMap == null) {
  214.             final DataContainer<ViewRiksdagenVoteDataBallotPartySummaryDaily, RiksdagenVoteDataBallotPartyPeriodSummaryEmbeddedId> partyBallotSummaryDailyDataContainer = getApplicationManager()
  215.                     .getDataContainer(ViewRiksdagenVoteDataBallotPartySummaryDaily.class);

  216.             partyMap = partyBallotSummaryDailyDataContainer.getAll().parallelStream().filter(Objects::nonNull)
  217.                     .collect(Collectors.groupingBy(t -> t.getEmbeddedId().getParty()));
  218.         }
  219.     }

  220.     /**
  221.      * The Interface DataValueCalculator.
  222.      */
  223.     @FunctionalInterface
  224.     interface DataValueCalculator {

  225.         /**
  226.          * Gets the data value.
  227.          *
  228.          * @param item
  229.          *            the item
  230.          * @return the data value
  231.          */
  232.         Object getDataValue(ViewRiksdagenVoteDataBallotPartySummaryDaily item);
  233.     }


  234. }