JFreeChart-参議院議員選挙(2019)開票速報


・参議院議員選挙が近づいてきたので、JFreeChartでテレヴィで見かける開票速報を作成しました。
・念のためですが、数値は私の希望を表現するものではありません。
・StackedBarRendererを使って与党、未開票、野党の分を表示しています。

目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java
package jp.avaj.lib.chart;

import java.awt.Color;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.StackedBarRenderer;
import org.jfree.data.category.DefaultCategoryDataset;

import jp.avaj.lib.algo.ArCreator;
import jp.avaj.lib.algo.ArMap;
import jp.avaj.lib.algo.ArTuple;
import jp.avaj.lib.algo.ArValidator;

/**
■ JFreeChart-参議院議員選挙(2019)開票速報

・開票の途中のデータを与党を左から、野党を右から積み上げて、状況を把握する.

 */
public class Chart90_参議院選挙開票速報 {
  // 目次-雑多
  A_Chart90 a_Chart90;
  // 目次-Artery-JFreeChart用のライブラリ
  A_Chart00 a_LibChartSampeContents;

  public static void main(String[] args) throws Exception {
    // 棒グラフなのでDefaultCategoryDatasetを使用する
    DefaultCategoryDataset ds = createData();
    // 軸の設定
    CategoryAxis catAxis = new CategoryAxis();
    NumberAxis numAxis = new NumberAxis();
    // 積上棒グラフにはStackedBarRendererを使用する
    StackedBarRenderer renderer = new StackedBarRenderer();
    // Plotを作成してグラフを表示する
    CategoryPlot catPlot = new CategoryPlot(ds,catAxis,numAxis,(CategoryItemRenderer)renderer);
    catPlot.setOrientation(PlotOrientation.HORIZONTAL);
    JFreeChart jfreeChart = new JFreeChart("参議院議員選挙(2019)開票速報",(Plot)catPlot);
    ChartFrame cFrame = new ChartFrame("参議院議員選挙(2019)開票速報",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);
    // 未開票をグレイにする(目立つ色だと感じが悪いので)
    renderer.setSeriesPaint(ds.getRowIndex("未開票"),Color.LIGHT_GRAY);
  }

  /** 開票速報データからDefaultCategoryDatasetを作成する */
  private static DefaultCategoryDataset createData() throws Exception {
    // 与野党を抽出するArValidator
    MyValidator validator = new MyValidator();
    // 作成するDataset
    DefaultCategoryDataset ds = new DefaultCategoryDataset();
    // 開票データの取得
    Map<String,ArTuple<Integer,Status>> kaihyouData = kaihyouData();
    // 与党分をDatasetに設定する
    {
      validator.setStatus(Status.YOTOU);
      Map<String,ArTuple<Integer,Status>> yotou = ArMap.selectByValue(kaihyouData,validator);
      addToDataset(ds,yotou);
    }
    // 未開票分をDatasetに設定する
    {
      validator.setStatus(Status.MIKAIHYOU);
      Map<String,ArTuple<Integer,Status>> yotou = ArMap.selectByValue(kaihyouData,validator);
      addToDataset(ds,yotou);
    }
    // 野党分をDatasetに設定する
    {
      validator.setStatus(Status.YATOU);
      Map<String,ArTuple<Integer,Status>> yotou = ArMap.selectByValue(kaihyouData,validator);
      addToDataset(ds,yotou);
    }
    return ds;
  }

  private static void addToDataset(DefaultCategoryDataset ds,Map<String,ArTuple<Integer,Status>> data) {
    Set<String> parties = data.keySet();
    for (String party : parties) {
      ds.addValue(data.get(party).getV0(),party,"");
    }
  }

  /** 開票速報データの設定 */
  private static Map<String,ArTuple<Integer,Status>> kaihyouData() throws Exception {
    Map<String,ArTuple<Integer,Status>> map = new HashMap<String,ArTuple<Integer,Status>>();
    // 速報されたデータを入力する
    {
      // 与党分
      map.put("自民党",new ArTuple<Integer,Status>(40,Status.YOTOU));
      map.put("公明党",new ArTuple<Integer,Status>(15,Status.YOTOU));
      // 野党分
      map.put("立憲民主党",new ArTuple<Integer,Status>(20,Status.YATOU));
      map.put("共産党",new ArTuple<Integer,Status>(10,Status.YATOU));
      map.put("国民民主党",new ArTuple<Integer,Status>(3,Status.YATOU));
    }
    //
    // 未開票分の計算
    {
      // 改選数
      final int KAISENSUU = 124;
      // 確定済みの数を求める
      ArCreator<ArTuple<Integer,Status>,Integer> creator = new ArCreator<ArTuple<Integer,Status>,Integer>() {
        @Override
        public Integer convert(ArTuple<Integer, Status> obj) throws Exception {
          return obj.getV0();
        }
      };
      int kakutei = (Integer)ArMap.sum(map,creator);
      //
      // 未開票分を追加する
      map.put("未開票",new ArTuple<Integer,Status>(KAISENSUU-kakutei,Status.MIKAIHYOU));
    }
    return map;
  }

  /** 与野党抽出のArValidator */
  private static class MyValidator implements ArValidator<ArTuple<Integer,Status>>  {
    @Override
    public boolean check(ArTuple<Integer, Status> value) {
      return value.getV1() == status;
    }
    public void setStatus(Status status) {
      this.status = status;
    }
    private Status status;
  }

  /** 与党、野党、未開票の定義 */
  private static enum Status {
    /** 与党 */
    YOTOU,
    /** 野党 */
	YATOU,
	/** 未開票 */
    MIKAIHYOU;
  }
}


```
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/f247254e-335e-3da0-5f9a-8a36bce9274d.png)