【JavaScript】ロト6とロト7の当選データの傾向(フォーム部品の値取得,値設定～ファイル読み込みと出力)

# 1.はじめに

今までjava,pythonでロト６(ロト７)について投稿してきた。
そして、ここにきても高額当選の波は来ていない。

「ロト6、ロト7の当選データを、他の言語の勉強に役立てなさい。」
というメッセージが天から降ってきているのだろう。
以下のようなものを満たすプログラムを作ろうと考えた。

__(1)loto6かloto7かを、入力しないで選択したい。__

__(2)過去の当選実績のファイルを選択できるようにしたい。__

__(3)特定開催間における、前回の番号と次回の番号の出現回数、出現率の集計データをダウンロードできるようにしたい。__

__(4)出力したいタイプと選択されたファイルのフォーマットが違う場合は、メッセージを出して開始回などを入力できないようにする。__

昔に、他部署に依頼されてツール作成のために勉強した事があったが、再勉強のために[前回](https://qiita.com/xmorning777/items/b1ad45cd6e00f2e82249)の内容のJavaScript版として記事を書くことにした。


# 2.入門メモ（フォーム部品関連）

今回使うフォーム。
(ファイル選択ボタン、ラジオボタン、テキストボックス、ボタン等を配置）

```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="encoding.js"></script>
<title>Lotoデータcsv出力</title> 
</head>

<body>
<h1>Lotoデータcsv出力</h1>

<form name="test">
<label><input type="radio" name="loto_r" value="6" checked>Loto6</label>
<label><input type="radio" name="loto_r" value="7">Loto7</label><br>
<input type="file" id="selfile"><br>
<input type="button" id="csvbtn" value="csv読み込み" onclick="OnCSVReadBtnClick();"/ disabled>
<div id="lotodiv"></div><br>
開始回：<input type="text" id="st" disabled><br>
終了回：<input type="text" id="ed" disabled><br>
<input type="button" id="csvoutbtn" value="csv出力" onclick="OnCSVOutBtnClick();"/ disabled>
<div id="csvmsgdiv"></div><br>

</form>
```
動作環境：Windows10 
ブラウザ:chrome

### 2-1.ラジオボタンのi番目の要素の選択状態

__`document.getElementsByName("ラジオボタンのname").item(i).checked`__
trueなら選択状態、falseなら未選択状態

```html
<label><input type="radio" name="loto_r" value="6" checked>Loto6</label>
<label><input type="radio" name="loto_r" value="7">Loto7</label><br>
```
例）上記Loto6の選択状態を取得するときは
document.getElementsByName("loto_r").item(0).checked

### 2-2.ラジオボタンの選択項目取得
i番目の項目が設定されている場合、

__`document.getElementsByName("ラジオボタンのname").item(i-1).value`__
で選択項目のvalue項目が取得できる。

### 2-3.テキストボックスの値取得

```html
開始回：<input type="text" id="st" disabled><br>
```
__`document.getElementsById("テキストボックスのid").value`__
でテキストボックスのvalue項目が取得できる。

### 2-4.ボタン等の活性化/非活性化

__`オブジェクト(ボタン、テキストボックス等).disabled`__
で設定し、活性(false),非活性(true)

### 2-5.divタグの要素の設定

__`document.getElementById("divタグのID名").innderHTML=設定したい内容`__

設定例：
```javascript
var csvmsg_div = document.getElementById("csvmsgdiv");
csvmsg_div.innerHTML="";
```

### 2-6 encoding.js
文字コード変換が必要な時使うプログラム。
今回はプログラムと同じフォルダに格納している。

# 3.流れ

### 3.1 ファイル選択
![js_lotodl1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/13960d91-b18a-c2e1-d80f-693b14c03867.jpeg)

![js_lotodl1_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/d36af033-4f71-0dd7-a27f-d8b7fd779d34.jpeg)

ロト6かロト7の分析データかを選んでから、ファイルを選択する。
(デフォルトはロト6)

ロト6のファイルの構成項目は
[開催回、日付、第1数字、第2数字、第3数字、第4数字、第5数字、第6数字]

ロト7のファイルの構成項目は
[開催回、日付、第1数字、第2数字、第3数字、第4数字、第5数字、第6数字、第7数字]


csv読み込みボタンを押すと、ファイルの列数、データ総数をチェックする。

### 3.2 集計開始回と集計終了回の入力

![js_lotodl3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/daa40753-c912-5941-634a-ac46bdeb3afd.jpeg)


ファイルの形式のチェックが終わると、データ総数を表示する。
開始回と終了回を入力できるようになる。

### 3.3 csvファイル出力

![js_lotodl4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689780/26dda505-ef19-6b1f-cce3-289e76c958df.jpeg)


開始回と終了回を入力し、csv出力ボタンを押下。
__1<=開始回<終了回<=総開催数__ の関係を満たす場合、csvファイルの
ダウンロードが始まる。


# 4.ソース

```html:download_loto67data.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<script src="encoding.js"></script>
<title>Lotoデータcsv出力</title> 
</head>

<body>
<h1>Lotoデータcsv出力</h1>

<form name="test">
<label><input type="radio" name="loto_r" value="6" checked>Loto6</label>
<label><input type="radio" name="loto_r" value="7">Loto7</label><br>
<input type="file" id="selfile"><br>
<input type="button" id="csvbtn" value="csv読み込み" onclick="OnCSVReadBtnClick();"/ disabled>
<div id="lotodiv"></div><br>
開始回：<input type="text" id="st" disabled><br>
終了回：<input type="text" id="ed" disabled><br>
<input type="button" id="csvoutbtn" value="csv出力" onclick="OnCSVOutBtnClick();"/ disabled>
<div id="csvmsgdiv"></div><br>

</form>

<script> 
var obj1 = document.getElementById("selfile");
var btn_csv = document.getElementById("csvbtn");
var btn_csvout = document.getElementById("csvoutbtn");
var loto_div = document.getElementById("lotodiv");
var csvmsg_div = document.getElementById("csvmsgdiv");
var text_st=document.getElementById("st");
var text_ed=document.getElementById("ed");
var radio_loto=document.getElementsByName("loto_r");
var filetext1="";
var loto_type="";
var last_cnt=0;
var splitstr=[];
var arr_status=[btn_csv,text_st,text_ed,btn_csvout];

//ダイアログでファイルが選択された時
obj1.addEventListener("change",function(evt){

 text_st.value="";
 text_ed.value="";
 csvmsg_div.innerHTML="";
 
 var file = evt.target.files;
 
 //FileReaderの作成
 var reader = new FileReader();
 //テキスト形式で文字コードsjisで読み込む
 reader.readAsText(file[0],"sjis");
 
 //読込終了後の処理
 reader.onload = function(ev){
  //読み込んだテキストの内容をfiletext1に代入
  filetext1=reader.result;
  confirm("読み込み完了");
  loto_div.innerHTML="";
  csvmsg_div.innerHTML="";
 }
  set_objstatus(arr_status,1); 
},false);


function OnCSVReadBtnClick(){

 var flg0=0;
 textdata=filetext1;
 delimit0="\r\n";
 delimit1=",";
 text_st.value="";
 text_ed.value="";
 csvmsg_div.innerHTML="";

 //csvを読み込んでデータ総数を見る
 splitstr=textdata.split(delimit0);
 for(i=0;i<splitstr.length;i++){
  arrtmp=splitstr[i].split(delimit1);
  if(splitstr[i].indexOf(delimit1)== -1){
   confirm(i-1+"個のデータを表示");
   last_cnt=i-1;
   break;
  }
 }

 arrtmp=splitstr[0].split(delimit1); 
 
 for(i=0;i<2;i++){
  if(radio_loto.item(i).checked){
   //選択されているvalueの値を取得
   loto_type=radio_loto.item(i).value
  }
 } 
 
 if(radio_loto.item(0).checked && arrtmp.length !== 8){
  confirm("列数が違います");
  flg0=1;
 }

 if(radio_loto.item(1).checked && arrtmp.length !== 9){
  confirm("列数が違います");
  flg0=1;
 }
 

 if(flg0==0){
  loto_div.innerHTML=last_cnt;
  set_objstatus(arr_status,4);
 }else{
  set_objstatus(arr_status,1);
  loto_div.innerHTML="";
 }
}


function OnCSVOutBtnClick(){

 st=text_st.value;
 ed=text_ed.value; 
 var flg0=0;

 if(isNaN(st)==false && isNaN(ed)==false){
 
  if(Number(st)< 1 || Number(ed) < 1){
   confirm("開始回、終了回は１以上を指定してください");
   flg0=1;
  }else if(Number(st)>=Number(ed)){
   confirm("開始回は終了解より小さい値を指定してください");
   flg0=1;
  }else if(Number(st)>=last_cnt+1 || Number(ed)>=last_cnt+1){
   confirm("データがありません");
   flg0=1;
  }else{
   csvmsg_div.innerHTML="csv作成中";
  }
 }else{
  confirm("数字を入力してください");
  flg0=1;
 }
 if(flg0==1){
  csvmsg_div.innerHTML="";
 }else{
  dict1=disp_lotopare(loto_type,st,ed);
  dict2=count_lotonum(loto_type,st,ed);
  var str1="前回数字,今回数字,カウント,出現率\r\n";
  for (var key1 in dict1) {
   val1=Number(dict1[key1]);
   keys2=String(key1).split(",");
   val2=Math.floor(val1*100/Number(dict2[keys2[0]]));
   str1=str1+String(key1)+","+String(val1)+","+String(val2)+"\r\n";
  }
  //ファイル名の指定
  var file_name = "Loto"+loto_type+"_"+st+"_"+ed+".csv";

  //CSVのバイナリデータを作る

  var toEnc = 'sjis';

  var codes = str_to_unicode_array(str1);
  var shiftJisCodeList = Encoding.convert(codes, toEnc, 'Unicode');
  var uInt8List = new Uint8Array(shiftJisCodeList);

  var blob = new Blob([uInt8List], {type: 'text/plain'});
  
  var uri = URL.createObjectURL(blob);

  //リンクタグを作る
  var link = document.createElement("a");
  link.download = file_name;
  link.href = uri;

  //作ったリンクタグをクリックさせる
  document.body.appendChild(link);
  link.click();

  //クリックしたら即リンクタグを消す
  document.body.removeChild(link);
  delete link;
 } 
}

// 文字列から，Unicodeコードポイントの配列を作る
function str_to_unicode_array(str){
 var arr = [];
 for(var i = 0; i<str.length; i++){
  arr.push(str.charCodeAt(i));
 }
 return arr;
}

//活性・非活性の設定
function set_objstatus(arr1,n1){
 for(i=0;i<4;i++){
  arr1[i].disabled=true;
 }
 for(i=0;i<n1;i++){
  arr1[i].disabled=false;
 }
}

//前回出力番号と今回出力番号の組み合わせ数
function disp_lotopare(loto_type0,st0,ed0){
 st1=Number(st0);
 ed1=Number(ed0);
 //連想配列初期化
 dict_loto={};
 loto_type1=Number(loto_type0);
 
 for(cnt=st1;cnt<ed1;cnt++){
  arrtmp=splitstr[cnt].split(",");
  arrtmp2=splitstr[cnt+1].split(",");
  for(i=2;i<loto_type1+2;i++){
   for(j=2;j<loto_type1+2;j++){
    key1=String(arrtmp[i])+","+String(arrtmp2[j]);
    if(key1 in dict_loto){
     dict_loto[key1]=Number(dict_loto[key1])+1; 
    }else{
     dict_loto[key1]=1;
    }
   }
  }
 }
 return dict_loto;
}

//各回毎の番号の出力数の合計
function count_lotonum(loto_type0,st0,ed0){
 st1=Number(st0);
 ed1=Number(ed0);
 //連想配列初期化
 dict_loto={};
 loto_type1=Number(loto_type0);
 
 for(cnt=st1;cnt<ed1;cnt++){
  arrtmp=splitstr[cnt].split(",");
  for(i=1;i<loto_type1+2;i++){
   key1=String(arrtmp[i]);
   if(key1 in dict_loto){
    dict_loto[key1]=Number(dict_loto[key1])+1; 
   }else{
    dict_loto[key1]=1;
   }
  }
 }
 return dict_loto;
}

</script>
</body>
</html>
```

# 5.さいごに

JavaScriptで、当選データファイルを読み込んで、前回の数字と
次回にでやすくなる数字の傾向を出力することができた。
普段使い慣れていないこともあり、フォーム部品の制御は
なかなか苦戦した。


# 6.参考URL

1.[KYO's LOTO](https://loto6.thekyo.jp/download/index)
当選番号データのcsvファイルだけではなく、各数字の出現回数など様々なデータを収集されています。

2.[モバイル通信とIT技術をコツコツ勉強するブログ](https://computer-technology.hateblo.jp/entry/20150710/p2)
sjis変換をしてから、csvダウンロードの部分が参考になります。