【java】ロト6で夢を見よう～過去データの表示と照合～

#１．初めに
ロト6のキャリーオーバーが発生しました。
これで夢も膨らむところでしょう。
一方ロト７ではついに、一等当選が3人出ました。
しかも。。。
###9億円！！！どうしよう、当選したんだ！！
一瞬夢を見ているのではないかと思いました。
でもこれがキャリーオーバーの威力なのです。
__`『この時のロト7に申し込んでさえいない』`__のに、ドキドキが止まりません。
気持ちだけは一等当選者です。

[前回](https://qiita.com/xmorning777/items/1538e5b667a685949a51)はロト6の申し込み番号を任意の個数表示してみました。
クイックピックを自作したというところでした。
なかなか当選は難しいけど、自分の運命を決められるところが面白味かもしれません。
今回は過去のデータをもとに、申し込み番号を決めることを考えようと
思っています。
申し込みを決めた数字が、今までの傾向から出現率の少ない数字の組み合わせか、前回の当選数字とほぼ同じ番号かなど知りたいことが出てきました。

自分の運命はとことん自分で決めたいものです。
そして。。。その結果外れたとしても、
「個人でできる小さな寄付をした」と考えて次に進めます。

#２．目標

+ __初回から今までどの数字がどれだけ出現したか__
+ __指定データ数で各数字がどれだけ出現したか__
+ __最新から指定データ数の当選番号の組み合わせ__
+ __入力した数字の組み合わせが過去データに存在するか__

を表示したい。

下記は入力画面のイメージ。
![loto6_2_input.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/076f69dc-08fa-af6b-e496-ccda760f1487.jpeg)

#３．実行環境

xamppのバージョン：7.2.3
eclipseのバージョン：Version: 2019-12 (4.14.0)
mariadbのバージョン:10.1.31
java:11
OS:windows10 home 64bit


#４．メモ

__`(1)select n1,n2 from tbl_loto order by date1 desc limit 20;`__
->tbl_lotoから最新の20件の項目n1,n2を取得したい。
__`(2)Map<key型名,value型名> hm1 = new HashMap<>()`__
->keyとvalueを持つHashmap配列hm1を宣言
要素数が可変の時、かつ配列の要素に文字列も設定できる。
__`(3)hm1.put(key1,value1) hm1はHashMap配列`__
->HashMap配列にkeyのkey1とvalueのvalue1を追加する。
おなじkeyに対してputを再度使うと、後で設定した値に更新される。
例)hm1.put("a",3)
hm1.put("a",2)
"a"のに対するvalueは2になる
__`(4)hm1.get(key1) hm1はHashMap配列`__
->key1に対するvalueを取得する。
__`(5)hm1.containsKey(key1) hm1はHashMap配列`__
->key1というキーがhm1に存在するかを確かめる。存在すればtrue
、存在しなければfalseを返す。


※上記が工夫ポイントとなっています。
ここから先のソースは大変長くなっています。
内容としては、高度な予想ではなく、照合、データ取得、件数表示というありきたりのものになっています。
ほしい情報でない場合、引き返していただいたほうが有益です。

#５.実装

##５-１．Model

###入力画面で受け取るデータと出力するデータ

```java:Loto6SearchBean.java
package model;
public class Loto6SearchBean {
  String select_input;//どこを選択したか
  String loto6search_cnt;//集計したい件数
  String loto6disp_cnt;//表示したい件数
  String loto6_result;//結果
  String loto6_input;//照合
  public String getSelect_input() {
    return select_input;
  }
  public void setSelect_input(String select_input) {
    this.select_input = select_input;
  }
  public String getLoto6search_cnt() {
    return loto6search_cnt;
  }
  public void setLoto6search_cnt(String loto6search_cnt) {
    this.loto6search_cnt = loto6search_cnt;
  }
  public String getLoto6disp_cnt() {
    return loto6disp_cnt;
  }
  public void setLoto6disp_cnt(String loto6disp_cnt) {
    this.loto6disp_cnt = loto6disp_cnt;
  }
  public String getLoto6_result() {
    return loto6_result;
  }
  public void setLoto6_result(String loto6_result) {
    this.loto6_result = loto6_result;
  }
  public String getLoto6_input() {
    return loto6_input;
  }
  public void setLoto6_input(String loto6_input) {
    this.loto6_input = loto6_input;
  }
}

```

###入力画面で受け取ったデータを加工するロジック
```java:Loto6DispBean.java
package model;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Loto6DispBean {
  public final int LOTO_TYPE=6;
  public final int MAX_NUM=43;
  public void execute(Loto6SearchBean loto_sch) {
    String selectstr1=loto_sch.getSelect_input();
    String input_str1=loto_sch.getLoto6_input();
    String disp_cnt1=loto_sch.getLoto6disp_cnt();
    String search_cnt1=loto_sch.getLoto6search_cnt();
    String lot6_retstr=getLoto6_info(selectstr1,input_str1,disp_cnt1,search_cnt1);
    loto_sch.setLoto6_result(lot6_retstr);
  }
  private String getLoto6_info(String selstr,String in_str,String disp_cnt,String search_cnt) {
    String retstr="";
    int flg=0;
    String titlestr="";
    //指定件数分のデータ表示
    if(selstr=="disp") {
      titlestr=disp_cnt+"件のデータ<br>";
      if(check_inputstr(disp_cnt)==1) {
        return titlestr+"表示数は半角数字を指定してください。";
      }
      if(Integer.parseInt(disp_cnt)<1) {
        return titlestr+"表示数は1以上を指定してください。";
      }
      retstr=get_recentdata(disp_cnt);
    //データ照合
    }else if(selstr=="compare"){
      titlestr="入力データ照合<br>";
      if(check_6string(in_str)==0) {
        flg=check_uniqedata(in_str);
        if(flg==0) {
          retstr=in_str+"は申込できます。<br>";
        }else if(flg==1) {
          retstr=in_str+"は既に使われています.<br>";
        }else {
          retstr="その他のエラー発生<br>";
        }
      }else {
        retstr=""+LOTO_TYPE+""+"つの違う数字で、1から"+""+MAX_NUM+""+"の数字を指定してください<br>";
      }
    //指定件数での数字の出現回数
    }else {
      retstr=get_countnumber(selstr);
    }
    return titlestr+retstr;
  }


  //既にDBに登録されている番号と重複していないかチェック
  private int check_uniqedata(String checkstr) {
    final String URL
    = "jdbc:mariadb://localhost:3306/loto6_db?useUnicode=true&characterEncoding=utf8mb4";
    String USER = "root";
    String PASS = "";
    int [] chknum={0,0,0,0,0,0};
    String[] tmpstr0=checkstr.split(",");
    for(int i=0;i<LOTO_TYPE;i++) {
      chknum[i]=Integer.parseInt(tmpstr0[i]);
    }
    Arrays.sort(chknum);
    final String sql = "select * from loto6_tbl where num1=? and num2=? and num3=? and num4=? and num5=? and num6=?";
    try(Connection conn =
      DriverManager.getConnection(URL, USER, PASS)){

      conn.setAutoCommit(false);

      PreparedStatement ps = conn.prepareStatement(sql);

      for(int i=0;i<LOTO_TYPE;i++) {
        ps.setInt(i+1,chknum[i]);
      }
      try(ResultSet rs = ps.executeQuery()){
        //条件を満たすレコードが存在しないとき
        if(!rs.next()) {
          return 0;
        //条件を満たしたレコードが存在するとき
        }else {
          return 1;
        }
      } catch (Exception e) {
        conn.rollback();
        System.out.println("rollback");
        return 2;
      }
    }catch(Exception e) {
      e.printStackTrace();
      return 2;
    }finally {
      System.out.println("処理が完了しました");
    }
  }
  //文字列のチェック
  private int check_6string(String chkstr0) {
    int flg=0;

    String[] tmpstr=chkstr0.split(",");

    //同じ数字を指定しているとき
    for(int i=0;i<LOTO_TYPE-1;i++) {
      for(int j=i+1;j<LOTO_TYPE;j++) {
        if(Integer.parseInt(tmpstr[i])==Integer.parseInt(tmpstr[j])) {
          return 1;
        }
      }
    }
    return flg;
  }

  //入力文字列の数字型チェック
  private int check_inputstr(String chkstr1) {
    int flg=0;
    //半角数字
    String numstr="0123456789";
    String tmpstr1="";
    if(chkstr1.isEmpty()==true) {
      return 1;
    }

    for(int i=0;i<chkstr1.length();i++) {
      if(i<chkstr1.length()-1) {
        tmpstr1=chkstr1.substring(i, i+1);
      }else {
        tmpstr1=chkstr1.substring(i);
      }
      //数値でないものがある場合
      if(numstr.indexOf(tmpstr1)==-1) {
        flg++;
        break;
      }
    }
    return flg;
  }

  //指定数のデータを表示
  private String get_recentdata(String disp_cnt0) {
    final String URL
    = "jdbc:mariadb://localhost:3306/loto6_db?useUnicode=true&characterEncoding=utf8mb4";
    String USER = "root";
    String PASS = "";
    String datestr="";
    String loto_str="";
    String[] tmpnum= new String[LOTO_TYPE];

    final String sql = "select num1,num2,num3,num4,num5,num6,date1 from loto6_tbl order by date1 desc limit "+disp_cnt0;
    try(Connection conn =
    DriverManager.getConnection(URL, USER, PASS)){

      conn.setAutoCommit(false);

      PreparedStatement ps = conn.prepareStatement(sql);
      try(ResultSet rs = ps.executeQuery()){
        while(rs.next()) {
          tmpnum[0]=String.valueOf(rs.getInt("num1"));
          tmpnum[1]=String.valueOf(rs.getInt("num2"));
          tmpnum[2]=String.valueOf(rs.getInt("num3"));
          tmpnum[3]=String.valueOf(rs.getInt("num4"));
          tmpnum[4]=String.valueOf(rs.getInt("num5"));
          tmpnum[5]=String.valueOf(rs.getInt("num6"));
          datestr=rs.getString("date1");
          loto_str=loto_str+String.join(",",tmpnum);
          loto_str=loto_str+","+datestr+"<br>";
        }

      } catch (Exception e) {
        conn.rollback();
        System.out.println("rollback");
        return "その他のエラー";
      }
    }catch(Exception e) {
      e.printStackTrace();
      return "その他のエラー2";
    }finally {
      System.out.println("処理が完了しました");
    }
    return loto_str;
  }

  //指定したのデータ件数の数字の出現回数を表示
  private String get_countnumber(String selstr) {
    final String URL
    = "jdbc:mariadb://localhost:3306/loto6_db?useUnicode=true&characterEncoding=utf8mb4";
    String USER = "root";
    String PASS = "";
    String loto_str="";

    //数字
    int[] chknum= new int[LOTO_TYPE];
    //各数字(第一からMAX_NUM数字までの)の出現数字
    int[] cntnum= new int[MAX_NUM];
    String[] tmpstr=new String[MAX_NUM];
    int cnt2= selstr.indexOf("cnt");
    String limitstr=selstr.substring(0, cnt2);
    String sql="";
    String titlestr="";
    Map<Integer,Integer> nummap = new HashMap<>();

    if(limitstr.equals("all")==false) {
      titlestr=limitstr+"件の番号出現回数<br>";

      if(check_inputstr(limitstr)==1) {
        return titlestr+"件数は半角数字を入れてください";
      }
      if(Integer.parseInt(limitstr)<1) {
        return titlestr+"件数は一以上の数字を入れてください";
      }

      sql = "select num1,num2,num3,num4,num5,num6 from loto6_tbl order by date1 desc limit "+limitstr;

    }else {
      sql = "select num1,num2,num3,num4,num5,num6 from loto6_tbl";
      titlestr="全件の番号出現回数<br>";
    }

    for(int i=0;i<cntnum.length;i++) {
      cntnum[i]=0;
    }

    try(Connection conn =
      DriverManager.getConnection(URL, USER, PASS)){

      conn.setAutoCommit(false);
      PreparedStatement ps = conn.prepareStatement(sql);
      try(ResultSet rs = ps.executeQuery()){

        while(rs.next()) {
          chknum[0]=rs.getInt("num1");
          chknum[1]=rs.getInt("num2");
          chknum[2]=rs.getInt("num3");
          chknum[3]=rs.getInt("num4");
          chknum[4]=rs.getInt("num5");
          chknum[5]=rs.getInt("num6");
          for(int i=0;i<LOTO_TYPE;i++) {
          //キーがない場合
            if(nummap.containsKey(chknum[i])==false) {
              nummap.put(chknum[i],1);
            }else {
              int tmpval=nummap.get(chknum[i]);
              nummap.put(chknum[i], tmpval+1);
            }
          }
        }
      } catch (Exception e) {
        conn.rollback();
        System.out.println("rollback");
        return titlestr+"その他のエラー";
      }
    }catch(Exception e) {
      e.printStackTrace();
      return titlestr+"その他のエラー2";
    }finally {
      System.out.println("処理が完了しました");
    }
    for (Map.Entry<Integer, Integer> entry : nummap.entrySet()) {
      loto_str=loto_str+entry.getKey() + " : " + entry.getValue()+"<br>";
    }

    return titlestr+loto_str;
  }
}

```
##５-２．Servlet
1.入力画面で入力された内容と、どのボタンを押されたかをもとに
、Loto6DispBeanで各ボタンに対する処理を行い、viewに結果が渡す。

```java:Loto6SearchServlet.java
package servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import model.Loto6DispBean;
import model.Loto6SearchBean;

/**
 * Servlet implementation class Loto6SearchServlet
 */
@WebServlet("/Loto6SearchServlet")
public class Loto6SearchServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;

  /**
   * @see HttpServlet#HttpServlet()
   */
  public Loto6SearchServlet() {
    super();
    // TODO Auto-generated constructor stub
  }

  /**
   * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // TODO Auto-generated method stub
    RequestDispatcher dispatchar=request.getRequestDispatcher("loto6_input2.jsp");
    dispatchar.forward(request, response);

  }

  /**
   * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
   */
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    Loto6SearchBean loto6_2 = new Loto6SearchBean();
    //選択メニュー
    String sel_str="";
    //照合データ
    String tmp_input="";
    //表示件数
    String disp_str="";
    //集計件数
    String search_str="";

    request.setCharacterEncoding("utf-8");
    if (request.getParameter("compare_btn") != null) {
      sel_str="compare";
      String lot_1=request.getParameter("loto_1");
      String lot_2=request.getParameter("loto_2");
      String lot_3=request.getParameter("loto_3");
      String lot_4=request.getParameter("loto_4");
      String lot_5=request.getParameter("loto_5");
      String lot_6=request.getParameter("loto_6");
      tmp_input=lot_1+","+lot_2+","+lot_3+","+lot_4+","+lot_5+","+lot_6;

    }
    if (request.getParameter("search_btn1") != null) {
      search_str=request.getParameter("search_cnt");
      sel_str=search_str+"cnt1";
    }
    if (request.getParameter("search_btn2") != null) {
      sel_str="allcnt";
    }
    if (request.getParameter("disp_btn") != null) {
      sel_str="disp";
      disp_str=request.getParameter("disp_cnt");
    }

    loto6_2.setLoto6_input(tmp_input);
    loto6_2.setSelect_input(sel_str);
    loto6_2.setLoto6search_cnt(search_str);
    loto6_2.setLoto6disp_cnt(disp_str);
    Loto6DispBean disploto6=new Loto6DispBean();
    disploto6.execute(loto6_2);
    request.setAttribute("loto6_result", loto6_2);
    RequestDispatcher dispatchar2=request.getRequestDispatcher("loto6_result2.jsp");
    dispatchar2.forward(request, response);
  }
}

```

##５-３.JSP

###入力画面
```jsp:loto6_input2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>情報入力</title>
</head>
<body>
<h1>情報入力</h1>
<form action="/loto6_2/Loto6SearchServlet" method="post">
<h2>A.入力データの照合</h2>
<h3>
第1数字  :
<select name="loto_1">
<% for(int i=0;i<43;i++){ %>
	<option><%= i+1 %></option>
<% } %>
</select>
第2数字  :
<select name="loto_2">
<% for(int i=0;i<43;i++){ %>
	<option><%= i+1 %></option>
<% } %>
</select>
第3数字  :
<select name="loto_3">
<% for(int i=0;i<43;i++){ %>
	<option><%= i+1 %></option>
<% } %>
</select><br>
第4数字  :
<select name="loto_4">
<% for(int i=0;i<43;i++){ %>
	<option><%= i+1 %></option>
<% } %>
</select>
第5数字  :
<select name="loto_5">
<% for(int i=0;i<43;i++){ %>
	<option><%= i+1 %></option>
<% } %>
</select>
第6数字  :
<select name="loto_6">
<% for(int i=0;i<43;i++){ %>
	<option><%= i+1 %></option>
<% } %>
</select><br>
</h3>
<input type="submit" name="compare_btn" value="照合"><br>
<h2>B.指定した件数の数字出現回数</h2>
<input type="text" name="search_cnt" maxlength=3>
<input type="submit" name="search_btn1" value="件の数字出現回数">
<input type="submit" name="search_btn2" value="全体の数字出現回数">
<h2>C.指定した件数のデータ表示</h2>
<input type="text" name="disp_cnt" maxlength=3>
<input type="submit" name="disp_btn" value="件の表示">
</form>
</body>
</html>
```
###結果画面
```jsp:loto6_result2.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%-- 下記でモデルを指定するとモデル内のデータを取得できるようになる --%>
<%@ page import ="model.Loto6SearchBean" %>
<% Loto6SearchBean loto6_r=(Loto6SearchBean) request.getAttribute("loto6_result"); %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>結果</title>
</head>
<body>
<h1>結果</h1>
<h2>
<%= loto6_r.getLoto6_result() %><br><br>
<a href="/loto6_2/loto6_input2.jsp">戻る</a>
</h2>
</body>
</html>

```
#６．結果

##6-1.入力データの照合
入力データ(第1数字～第6数字)を入力後に照合ボタンを押したとき
![loto6_2_result1j.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/f0fad08a-3e3d-8a34-6f33-fdb9325c5bd4.jpeg)

##6-2.全件のデータからの番号出現回数
「全件の数字出現回数」ボタンを押したとき

![loto6_2_result2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/61475026-87e9-1329-c4a0-8060810031f3.jpeg)

##6-3.最新の2件のデータからの番号出現回数
件数を入力後に「件の数字出現回数」ボタンを押したとき
![loto6_2_result3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/404c2697-920f-e158-5c1e-e98322c13da1.jpeg)

##6-4.最新の7件のデータ表示
表示したい件数を入力後に「件の表示」ボタンを押したとき
![loto6_2_result4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/dd63db9e-927a-cd68-c572-37fac5e8b972.jpeg)

#７．今後

###高額当選したい！
以上です