第 1 章 Web データベース データベースは今日、企業の商品在庫管理システム、電子カルテ、スポーツのデータ分析システムなどに利用さ れている。商品在庫管理にはデータを管理、分析するには最適なソフトである Excel を利用することが多い。しか し Excel を用いて在庫管理をする場合、自分でマクロを組まなければ手計算が必要になりリアルタイムで在庫管 理を行うソフトとして使用するには不向きに思う。また第一に OFFICE を買わなければそれ自体利用できない。 そこで、簡単に商品管理を行うためにデータベースを扱ったソフトが多く開発されている。電子カルテでもこれま での紙のカルテから電子的なシステムに置き換えて、電子情報として一括してカルテを編集・管理しデータベー スに記録するようになっている。データベースに記録する電子カルテの利点として、カルテの物理的な管理が不 要になり、紛失の恐れがなくなり、また、USB メモリなどにコピーすることによって長期間かつ大容量での保存 も用意で収納スペースも抑えることができる。ほかにもテキストとして保存することによってデータベースに含 まれる任意のキーワードによるワード検索やデータの絞り込みが容易になる。この電子カルテシステムを導入は、 業務効率を向上させ、人員削減や経費削減、残業を減らす事などに貢献される。結果的に医療現場の環境改善が なされる事で、働く人のモチベーションの向上も期待出来るだろう。 スポーツのデータ分析システムについてだが、現代の多くのスポーツにおいてもデータベースは利用されてい るように思う。今回はこのスポーツにおいてのデータベース利用について特に考えていきたい。スポーツ分野に おけるデータ活用それ自体はそれほど新しいものではない。例えば、初めて統計データを駆使し蓄積された選手 データを分析・有効活用して大きな成功を収めたのは、メジャーリーグの Oakland Athletics というチームで今か ら 14 年ほども前になる(2011 年に公開された映画「マネーボール」で、この Oakland Athletics の活躍が映画化 された)。この映画の影響でデータマネジメントがスポーツに及ぼす影響力の可能性に多くの人が気付いたと思う。 それまでの直感や長年の経験に委ねられていた主観的な判断基準から、客観的なデータを分析することで得られ る洞察からの判断を重視する傾向が生まれた。それからというもの、野球はもちろんのこと、あらゆるスポーツ においてデータの活用が勝つための一つの要になっているように思える。今日ではそのデータが「ビッグデータ」 として、スポーツの勝敗への影響度がさらに大きくなっている。ここでの「ビッグデータ」とは構造化された数 値データだけでなく、音声や映像、テキストなどの非構造化された情報がリアルタイムに収集されたデータ集合 を指している。(ビッグデータとは、市販されているデータベース管理ツールや従来のデータ処理アプリケーショ ンで処理することが困難なほど巨大で複雑なデータ集合の集積物を表す用語である。その技術的な課題には収集、 取捨選択、保管、検索、共有、転送、解析、可視化が含まれる。)2014 年のサッカーブラジル W 杯で優勝したド イツにおいても、ビッグデータはドイツの「12人目」の選手と言われたほど、データ分析が試合の勝利に大きく 寄与したそうである。このことからもスポーツの世界において「データ」がいかに重要視されているかがわかる。 私がテレビでスポーツ観戦をしていて特によく目にするのが、オリンピックのバレーボールの試合を見ていると きに全日本監督であった真鍋監督が常にタブレットを手に持ち、そのタブレットを見ながらタイムアウトの時間 に選手にアドバイスをしている光景である。真鍋監督は 2009 年に全日本監督に就任した際に一番大きな課題と感 じたのが海外選手との身長差、体力差、リーチの長さなどの体格差でありそれが勝敗に大きく影響すると判断し、 真正面からぶつかったのではとても勝てない。そこでこの絶対的な差を埋めるヒントを探すために、過去の試合 データの徹底的な分析に取り組んだのが「データ」を重要視するきっかけのようだ。試合中の数値的なデータは すべてアナリストが手入力をして集め、それを随時監督のタブレットに転送している。そうすることによって試 合中でもデータを用いた正確なアドバイスができるのである。最近ではこういった日本代表やプロはもちろんの こと大学生でも多くのスポーツの試合でタブレットを利用し、手打ちで試合の記録を取っている。しかしリアル タイムで集計しデータ表で表示させるものはあまりないように思う。また一般的に集計ソフトや管理ソフトは商 用のものが多く、さらに値段のそれなりに高いので簡単に利用するのは難しい。このことから無料でデータがリ アルタイムで集計できるようなソフトがほしいと考えた。近年のスポーツの世界におけるデータの利用性の価値 の高さを知って、自分自身が小学校から取り組んでいたバスケットボールの試合で利用できるソフトがほしいと 考えた。そこでその一例としてバスケットボールの試合の記録データをリアルタイムで集計し Web にそのデータ を保存しデータ表で出力するソフトの作成を試みた。 1 1.1. 試作プログラム2‐バスケットボール試合記録ソフト 現代のバスケットボールの指導は昔に比べてより一層、データ(過去の試合記録(年間の試合)、試合中の記録 データ、試合後のデータすべてを指している)から作戦を考え、アドバイスをするようになってきているように 思う。特にアメリカのバスケットボールの試合(NBA) を見ていると、日本のバスケットボールの試合に比べて 試合中の作戦会議の時間が圧倒的に多い。これは NBA と日本の学生のバスケットボールの試合のルールが違う (NBA ではタイムアウトが前後半で合計8つ、日本では前後半で合計5つ)ので仕方ないが、これは大きな違い であり、さらに NBA ではビッグデータを用いた分析から監督が指示を出している。しかし日本の監督はその試合 を見ての印象をもとに指示を出しているのがほとんどである。NBA ではデータベースを利用して過去の莫大な情 報を扱い、日本人が考えもしないデータを引っ張り出してくる。例えば「ある A 選手がある B 体育館の右 45 度 の位置からフェイダーアウェイシュート(後ろに下がりながら飛んでシュートを打つこと)を打てば100%成 功する」のようなデータである。こういったデータまでも必要とするのが世界最高峰のバスケットボールリーグ NBA なのだ。私は試合中、選手のからだの状態、調子に加えてその選手の正確な試合の記録を踏まえて選手交代 などの起用を模索するのが良い指導者と思う。コーチや指導者が試合中に自チームを最も勝利に近づかせるため にすべきことは最も適切なアドバイスを選手たちにおくることである。そのためには試合を見て思った印象だけ で話すよりも実際にデータとして選手たちに見せて自覚させてアドバイスしたほうが、選手もそのアドバイスを 信頼するだろうし指導者としても容易にアドバイスが行える。今回作成したソフトは小学生、中学生、高校生の 指導者を対象に作成しており、ミニバス、中高の部活で使用してもらいたいと考えている。今後、バスケットボー ルの世界では益々データの分析から作戦を考えチームの勝率をあげていく考えが浸透していくようになると予想 できるので、小、中、高校生には部活動の段階からデータを用いた頭を使うバスケットボールをしてほしい。そ のきっかけになれば、という願いから今回のソフトを作成しようと思った。 今の部活動の基本的なスコアデータを記録する手段としてマネージャーや控え選手がスコアシートに試合を見 ながら手書きで書きこんでいることが多い。そしてそのデータを試合が終わった後に集計をしていたので試合中 ではそのデータをあまり生かすことはできていなかった。しかしこのソフトはタッチパネル式のソフトでタブレッ ト一つでデータを集計してその場で出力できるようになっている。これによって、集計データを試合中に瞬時に 見ることができ、コーチ、指導者の選手への指導がこれまでよりも高いレベルで行えるのではないかと考えた。こ のソフトを作成するときに特に気を付けたのがバスケットボールは瞬時にたくさんのプレーが行われるため、今 回はシュートのデータしか取っていないが、1 つのプレーに対してデータを取るのに 2 秒程度で取れるようにしな いといけないところである。もしデータを取るのにより時間がかかってしまえば連続した次のプレーを見逃して しまい正確なデータをとれなくなってしまう。本ソフトでは基本的な操作として選手をドラッグ、シュートの種類 を選択、成否の選択の 3 つの動作を必要とする。しかしパソコンで使うと動作が多少遅れてしまうが、本ソフト はタッチパネルで扱うことを考えているので問題はない。利点としては • Web データベースなので誰でも無料で使える。 • データはブラウザに保存しているので自分でデータを消さない限りデータは消えない。 • データ表にはソート機能があるため見たいデータだけを見ることができる • リアルタイムでデータ表を見ることができる。 などが挙げられる。このソフトを使って指導者がこれまでよりも適切かつ高度な選手への指導ができれば良いと 思う。また選手は部活動の段階で高度な指導を受けることで将来的にも活躍できる選手になってもらいたい。 2 1.2. ソフトの機能 このソフトはバスケットボールの試合において、リアルタイムにどの選手がどのタイミングで得点を決め、ま た、シュートを失敗したかを記録して、その記録したデータをテーブル表示させるソフトである。上記の画像は、 本ソフトの初期画面である。canvas によってバスケットボールコートと選手の背番号 4 から 18 番を描いた。選手 の背番号はいずれもドラッグができる。バスケットボールのシュートの種類 2P、3P、FT(フリースロー)はラジ オボタンで選択する。シュートの成功、失敗はボタンを押して選択する。保存のボタンは 1 クォータが終わった ごとにクリックし、ブラウザにデータを保存するときに使う。 取得したいデータは、選手の背番号、シュートの種類、その結果、その時の時刻である。 選手の交代はその都度、ドラッグして選手を入れ替える。バスケットボールの試合は 1 チーム 5 人しか出れな いので、出場していない選手は左のグレーの場所に移動させる。 例えば、4 番の選手がバスケットゴール付近でシュートを打って失敗し、続いて 6 番の選手が 3 ポイントシュー トを打って成功した場合は、 3 まず、4 番の選手をドラッグしバスケットゴール付近まで持っていき、そこでドラッグをやめる。そしてラジオ ボタンの2 p にチェックを入れて、最後に失敗のボタンを押す。また、同じように 6 番の選手をドラッグ、3 p に チェック、成功のボタンを押す、この動作をバスケットボールの試合(小学生の試合なら 6 分× 4 クォーター中学 生の試合なら 8 分× 4 クォーター、高校生の試合なら10分× 4 クォーター)を見ながら同時に行う。これで背 番号、シュートの種類、結果、時刻のすべてのデータが取れる。データを見たいとき(1 クォータの終了時など) に一度保存ボタンを押す。これによって集めたデータを localStorage(後で記述)に保存することができる。 4 「–データを見る–」、 「全削除」のアイコンについてだが、前者のボタンを押すと集めたデータをテーブルで見るこ とができる。後者のボタンは localStorage に保存させたデータすべてを削除するときに使うが、誤ってこのボタ ンを押してしまうとせっかく取ったデータを削除してしまい復元することができないので要注意すべきである。 上記の画像は、集めた背番号、シュート、結果、時刻のデータが見れる表である。データはランダムに入れたもの である。 ・フィルタリング機能 number をクリックすると、選手の背番号のフィルターをかけることができる。チェックボタンのチェックを外 せば、その選手の情報を除くことができる。また、「Filter results」のテキストエリアに番号を打ち込むとその番 号だけの情報を得ることができる。この機能については number だけの機能ではなく、shot、result、time すべて のデータでも行える機能である。 number,shot,result,time はすべてドラッグさせることができ、上記 1 つ目のテーブルを見ればわかるが time の データがテーブルには含まれていない。 5 そこでこの赤で囲まれた time を下の result,shot のある枠にドラッグして移動させることで、すべてのデータを 見ることができる。もともと time があった枠に各アイコンをドラッグさせ移動させるとそのデータを除外するこ とができる。 また、行と列を組み替えることもできる。 pivotall のソースは下記である。 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <script src="jquery-1.9.1.min.js"></script> <link rel="stylesheet" type="text/css" href="pivot.css"> <script src="jquery-ui-1.9.2.custom.js"></script> <script src="pivot.js"></script> </head> <script> 6 $(function(){ jsdata = JSON.parse(localStorage.getItem("testall")); var tpl = $.pivotUtilities.aggregatorTemplates; $("#output").pivotUI(jsdata, { rows: ["number"], //行に指定する json の key cols: ["result","shot"], //列に指定する json の key //どの json の key について集計するか vals: ["shot"], aggregators: { "シュート数": "合計": function() { return tpl.count()() }, function() { return tpl.sum()(["shot"]) }, }, rendererName: "Table" //テーブルの表示方法を指定 }, false ); }); </script> <body> <div id="output"></div> </body> </html> 1.2.1. pivottable について まず、下記のファイルをダウンロードする。 • pivot.css • jquery-1.9.1.min.js • jquery-ui-1.9.2.custom.min.js • pivot.js これらについては https://github.com/nicolaskruchten/pivottable からダウンロードする。 7 pivotUI(input [,options]) プログラムの書き方は前節の最後のソースを参考にする。$("#output").pivotUI(jsdata,{}) のソースで jsdata の部分に自分がテーブルにしたい JSON データを入れる。{}の中身は rows,cols,vals,aggregators,renderName が 用意されている。それぞれの説明は以下の表に記載している。 pivotUI の引数 引数 引数名 第1引数 input 第 2 引数 options 中身 説明 json データ 行列やどの key で集計するかやどうやって集計するかなど rows 行に指定する json の key cols 列に指定する json の key vals どの json の key について集計するか aggregatorName rendererName vals で指定した方法をどうやって集計するか ※ 1 テーブルの表示方法を指定 ※ 2 ※ 1…aggregatorName について 集計方法について。あらかじめ用意されたものが使える。最初から用意されているのは以下である。 8 指定する文字列 説明 レコードの数をカウント count countUnique vals で指定した値の一意なものをカウント vals で指定した値の一意なものをカンマで区切ったリストで表示 listUnique vals で指定した値の合計 sum intSum vals で指定した値の合計の小数点無し average vals で指定した値の平均 sumOverSum ある値 x の和をある値 y で割った値 ub80(lb80) sumAsFractionOfTotal Total(行列の) を 100 パーセントとしたときの合計構成比率 sumAsFractionOfRow Total(行の) を 100 パーセントとしたときの合計構成比率 sumAsFractionOfCol Total(列の) を 100 パーセントとしたときの合計構成比率 countAsFractionOfTotal Total(行列の) を 100 パーセントとしたときのカウント構成比率 countAsFractionOfRowl Total(行の) を 100 パーセントとしたときのカウント構成比率 countAsFractionOfRow Total(列の) を 100 パーセントとしたときのカウント構成比率 ※ 2…rendererName について テーブルの描画のタイプを選べる。あらかじめ用意されているのは以下である。 指定する文字列 Table Table Barchart Heatmap 説明 ノーマルのテーブルで表示 バーチャート付きで表示 行列のヒートマップで表示 Row Heatmap 行のヒートマップで表示 Col Heatmap 列のヒートマップで表示 ※今回ソフトで、この機能は「Table」のみしか使わない。 1.3. JSON データ作成 var datalist = []; $(function(){ $(".result").click(function(){ var shot = $("[name=shot]:checked").val(); var result = $(this).val(); var zikan = new Date(); var h = zikan.getHours(); var m = zikan.getMinutes(); var s = zikan.getSeconds(); var time = h+"時"+m+"分"+s+"秒"; datalist.push({"number": number, "shot" : shot, "result": result, "time": time}); }); }); 上記は成功、失敗どちらかのボタンをクリックしたときにそれぞれの変数(number に入るデータは Canvas 上 の番号をドラッグさせてドラッグをやめたときに該当する数値が入る、shot に入るデータはシュートの種類が書 いてあるラジオボタンのどれかにチェックしたときに入る、result には成功か失敗のボタンを押したときに文字列 としてデータが入る、time に入る時間のデータは成功か失敗のボタンを押した瞬間の時間が入る)が入り、結果 のボタンを押すたびに JSON データを作成するソースである。datalist が例えば、 9 [ { "number": 4, "shot" : "2P", "result":"成功", "time": 2"時"45"分"13"秒" }, { "number":5 , "shot" : "3P", "result":"失敗" , "time": 2"時"45"分"46"秒" }, ・ ・ ・ { "number": 7, "shot" : "1P", "result": "成功", "time": 2"時"55"分"09"秒" } ] のような JSON データを形成する。 1.4. JSON データの保存 集めた JSON データは WebStorage に保存する。WebStorage とはユーザーのローカル環境(ブラウザ)にデー タを保存するための仕組みで、Web Storage には、sessionStorage と localStorage の2種類のストレージが用意さ れている。その中でもデータを永続的に保存できる localStorage を今回は利用する。WebStorage についての説明 は後で記述する。JSON データを localStorage に保存するときには文字列にシリアライズしないといけない。そ こで第 3 章 JSON で紹介した JSON.stringify() を用いるのである。取得時は JSON.parse() でデシリアライズす るのがよい。 $(function(){ $("#botanhozon").click(function(){ datalist_string = JSON.stringify(datalist); localStorage.setItem("testall",datalist_string); }); }); 上記のソースは保存ボタンをクリックときにおこるイベントで、datalist という JSON データを入れた変数を JSON.stringify() で文字列化し、datalist _ string という新たな変数に入れ、 localStorage.setItem("testall",datalist_string); で、datalist _ string の中身をキー「testall」に保存 する形になっている。 1.4.1. WebStorage について ここで、WebStorage について説明する。WebStorage は、ユーザーのローカル環境(ブラウザ)にデータを保 存するための仕組みで、ブラウザよりアクセス可能なローカルの Key Value Store 型 (キーと値の組を書き込 み、 キーを指定することで値を読み出せる) のデータベースである。データの保存・上書き・削除・全クリアなど 10 の操作は、JavaScript で行うことができる。データはプロトコル、ドメイン、ポートの組み合わせであるオリジ ンの単位に管理される。単純な操作しかできないが、Web SQL Database や Indexed Database に比べ シンプルなことが最大の特徴である。利用法のイメージは、Cookie に近いが、Cookie に比べて、数 M バイト程 度のデータを保存でき、保存できる容量が大きいなど様々な点で Cookie よりも有効である。 Web Storage には、sessionStorage と localStorage の2種類のストレージが用意されている。 どちらもキー (key)と値(value)をペアにしたデータのリストを ユーザーのローカル環境に保存する key-value 型のデータ保存 形式である点は同じだが、 データの有効期限などが異なるので目的に応じて使い分けるのがよい。ここで Cookie と WebStorage(localStorage,sessionStorage) について比較をわかりやすくするため表でまとめる。 別ウィンドウでの データの有効期限 データ量の上限 データ共有 〇 Cookie サーバーへの データ送信 指定期限まで有効 4KB サーバーへアクセスするたびに 毎回自動送信 sessionStorage × ウィンドウやタブを 閉じるまで有効 localStorage 〇 1 オリジン当たり 5MB 永続的に 必要時のみスクリプトや フォームなどで送信 有効 このように Cookie ではリクエストの都度、データを送信することから盗聴の心配があり、また保存できるデー タ量が制限されるなどの問題があった。このような点を改善し、より高度な Web アプリケーションの開発に適し たデータ保存の仕組みとして考えられたのが WebStorage である。 sessionStorage と localStorage について説明する。 sessionStorage は、ウィンドウやタブ単位での一回限りのセッションで有効なストレージである。ウィンドウや タブが開いている間のみデータが保存され、閉じるとデータが失われる。 同じドメインのサイトを別々のウィン ドウで開いている場合には、それぞれが別の sessionStorage となる。 Cookie とは異なり、ウィンドウ間でデータ が共有されることはない。 localStorage は、オリジン単位でデータを永続的に保存するストレージである。 オリジンとは 「http://www.example.com:80」のような「プロトコル://ドメイン名:ポート番号」のことである。オリジンが 同じであれば別ウィンドウでもデータを共有でき、ブラウザを終了してもデータは失われない。しかし同じスト レージを共有するので誤って保存データを上書きしたり、消したりしないよう注意をしないといけない。 例えば、 「http://example.com/aaa.html」と「http://example.com/bbb/ccc.html」は、同じストレージを共有する。 デー タ保存量の上限はブラウザへの推奨値が 1 オリジン当たり 5MB とされており、 クッキーの 4KB に比べるとより 大きなデータを保存できるようになっている。localStorage を利用する一例を挙げる。ウェブメールにおけるメー ルの送受信データのような比較的大きなデータの場合、クッキーでは保存できるデータ量に上限があるため、すべ てのデータをローカル環境に保存することは困難である。また、クッキーではユーザーがアクセスする度にデー タがサーバーに送信されるため、セキュリティの観点からも好ましくない。localStorage では、ローカル環境に 5MB までのデータを永続的に保存でき、 ユーザーのアクセスの度にデータがサーバーに送信されることがない。 localStorage なら送受信データをローカル環境に保存でき、 オフラインウェブアプリケーションと組み合わせる ことで、オフラインでのメール閲覧なども可能となる。 1.4.1.1. ブラウザの対応 ブラウザ 対応状況 IE 8 以降 Chrome 8 以降 Firefox 3.6 以降 Safari 5 以降 Opera 11 以降 11 ・対応ブラウザの判定 「localStorage」 or 「sessionStorage」で判定が可能である。 window.onload = function () { // ローカルストレージ対応判定 if(!localStorage) { alert(’ ローカルストレージに対応していない’); } // セッションストレージ対応判定 if(!sessionStorage) { alert(’ セッションストレージに対応していない’); } } これでブラウザが対応していなければアラートが出る。 主要ブラウザは Web Storage を実装しているが、ストレージに保存された情報の内容を(開発者が)確認する 手順はブラウザにより異なる。なお、現在、Internet Explorer のみ、Web Storage に保存された情報を確認する 方法が提供されていない。また、Firefox はアドオン「Firebug」を入れることなどで確認ができる。それ以外のブ ラウザは、開発者ツールで確認することが可能である。 確認手順は以下のとおりである。 ブラウザ ストレージの 確認手順 確認手順 確認ができる バージョン IE 現在は ― できない Chrome 8 以降 デベロッパー ツールで 確認 バー上の[Google Chrome の設定]ボタンから [ツール] ‐ [デベロッパー ツール]を実行。表示された デベロッパー・ツールの [Application] タブを開き、ツリー表示から [Session Storage]や[Local Storage]の配下の項目を選択する。 Firefox アドオン が必要 Firebug アドオンなど で確認 Safari 5 以降 開発メニュー で確認 Firebug を起動して、上部のツールバーの[DOM]タブを開き、 [window]の配下にある[sessionStorage]や [localStorage]を選択する。 バー上[一般設定のメニュー]ボタンから[設定]を実行。 表示されるダイアログでダイアログを閉じる。[詳細]タブを開き、 [メニューバーに”開 発”メニューを表示]チェックボックスに チェックを入れ、バー上[現在のページのメニュー]ボタンから [開発] ‐ [Web インスペクタを表示]を実行。表示されるウィンドウで 上部の[リソース]タブを開き、ツリー表示から [セッションストレージ]や[ローカルストレージ]の 配下の項目を選択する。 Opera 11 以降 開発者用 ツールで確認 [メニュー]ボタンから[ページ] ‐ [開発者用ツール] ‐ [Opera Dragonfly]を実行。表示された開発者用ツールの 上部[ストレージ]タブを開き、そのタブの下に表示されるバーで [セッション ストレージ]や[ローカル ストレージ]を開く。 ・管理ツールを用いた確認 localStorage に保存されている値は、管理ツールから簡単に確認可能である。例えば Chrome の場合、上記にも 記してあるが、[表示]-[開発/管理]-[デベロッパーツール] で管理ツールを表示し、[Application] タブをクリックし、 左側のメニューから、[local Storage] を選ぶことで、データベースに保存されている値を確認することができる。 12 localStorage の利用方法 1.4.1.2. localStorage は KVS(Key Value Store) 型のデータベースを操作する API である。キーと値のペアでデータを管 理する。 以下に、API のリファレンスを記す。WebStorage(localStorage/sessionStorage) のプロパティとメソッドは以下 の通り。 プロパティ/メソッド length key(index) getItem(key) setItem(key, value) 説明 localStorage/sessionStorage に保存されているキーの数を返す。 index を数値で指定。index 値に対応するキー(文字列)を返す。 key に対応する値を返す。 key に対し、value をセットする。value としてオブジェクトも含め 任意の値を指定できることになっているが、ブラウザ実装では、 数値や文字列しか挿入できない。 removeItem(key) clear() key に対応する値を削除する。 localStorage/sessionStorage に保存されているデータをすべて消去する。 例えば、hoge をキーとして、値 test を保存、削除、取得する場合は、以下のように記述する。 データを保存する。 • localStorage.setItem(”hoge”, ”test”); //メソッドでのアクセッサー データを削除する。 • localStorage.removeItem(“ hoge ”) データを取得する。 • localStorage.getItem(”hoge”); すべてのデータを削除する。 • localStorage.clear(); なおプロパティやハッシュでアクセスもできるが、ブラウザ毎に挙動が異なるため非推奨である。 13 1.4.1.3. JSON.stringify と JSON.parse の利用 Web Storage に保存する際に、全ての値は内部的に文字列に変換した後に保存される。つまり、オブジェクト をそのまま保存しても文字列に変換されてしまい、意図した通りに保存・取得出来ない。例えば、オブジェクト が保存・取得出来ない例として、 var obj = { "hoge": "test" }; localStorage.setItem( "hogeData", obj ); localStorage.getItem( "hogeData" ); // -> "[object Object]" したがってオブジェクトを保存する場合は JSON.stringify() を用いて、文字列にシリアライズしなければなら ない。取得時は、JSON.parse() によりデシリアライズすれば良い。 オブジェクトを JSON.stringify で文字列に変換してから保存する。 localStorage.setItem( "hogeData", JSON.stringify(obj) ); JSON.parse( localStorage.getItem("hogeData") ); // -> { "hoge": "test" } 配列を保存しても文字列になる。 var array = ["abc", "def"]; localStorage.setItem("hoge", array); localStorage.getItem("hoge"); // -> "abc,def" 配列を JSON.stringify で文字列に変換してから保存し、 取り出した文字列を JSON.parse で JS オブジェクト に変換する。 var array = ["abc", "def"]; localStorage.setItem("hoge", JSON.stringify(array)); JSON.parse(localStorage.getItem("hoge")); // ->["abc,def"] 1.5. 考察・今後の課題 今回のソフトを作成するにあたって重要になったのはどういった形でデータを保存させていくか、またどういっ たテーブルを扱うかである。まずデータの形として JSON データのフォーマットにしたらどうかと思い、試して みた。JSON は配列の中にオブジェクトを入れることができ、さらに取り出すのもキーを呼び出せばよいだけで いいので扱いやすいフォーマットであった。今回必要となったデータはバスケットボールの試合においての選手、 シュート、その成否、その時の時刻であった。この 4 つのデータを扱うのに JSON のフォーマットだと容易に行え た。またテーブルを作成するのに使用した pivottable ライブラリは JSON データを読み込むだけでその集計デー タを簡単に表示するライブラリなので容易にテーブルを作成することができた。しかし pivottable には数多くの 機能が備えられている半面、自分で機能を追加するには難易度が高いのが欠点である。データ表ライブラリにつ いてだが、自分でデータを用意する場合でもインターネットから何かしらのほしいデータを取ってくる場合でも 簡単に、さらに高度なテーブルを作成することができるライブラリが多数存在した。自分ではじめからすべて組 んでテーブルを作成するよりも、インターネットで無料提供されているライブラリを利用する方がプログラムを 組む時間を削減することができる。 バスケットボールの試合では得点だけでなく、アシスト、リバウンド、スティール、ターンオーバー(スティー ルされたり、ヴァイオレーションなどの反則を犯すことにより攻撃権が相手チームに移ること。また、そのミスの こと)などたくさんの情報が存在する。今回の作成したソフトの機能では得点以外の情報を入れるのは困難だった ためこのような形式のソフトになった。本来ならそういった得点以外の情報もデータとして取れたほうがよかった のだがどうしてもバスケットボールの試合の形式からほとんどの場合一つのシュートにつきアシスト、リバウンド の情報も出てきてしまい、さらにプレーとプレーの間の時間差がほぼない場面だととてもたった 2,3 秒で記録す るのは難しかった。反省点としてもっとたくさんのデータを記録させることができるように、機能性から見つめ なおしていく必要があると感じた。以下で今後の課題をまとめておく。 14 • pivottable によって今回のソフトには必要のない機能が、自作のライブラリではないため仕方ないが、その まま残されてしまっている。自力でライブラリを組めるようにプログラミング能力をあげる必要がある。 • 得点以外のアシストなどの別の情報を入れることができなかったので、より効率よくデータを取ることがで きるようにする。 • タッチパネルと同じ仕様でパソコンのマウスを使ってでもできるようにする。 • シュートを放った時に取った時間のデータについてだが、リアルタイム(日本標準時)の時間を取るように なっているが理想としては、例えば高校生なら 1 クォーター 10 分なので開始何分何秒でシュートを放った かのデータをとれるようにしたかった。これは実際のタイマーとズレが生じてしまうと思いやめた。 以上の課題や反省を踏まえて今後、より高性能なソフトを作成できるように検討していきたい。 1.6. ソース <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=shift_jis"> <script src="jquery-1.9.1.min.js"></script> <link rel="stylesheet" type="text/css" href="pivot.css"> <script src="jquery-ui-1.9.2.custom.js"></script> <script src="pivot.js"></script> <script src="jcanvas.min.js" type="text/javascript"></script> <style type="text/css"> .select-box01 select { position:absolute; left: 900px; top: 750px; width: 10%; padding: 10px; -webkit-appearance: none; -moz-appearance: none; appearance: none; border: 1px solid #999; background: #eee; background: url(arrow01.png) right 50% no-repeat, -webkit-linear-gradient(top, #fff background: url(arrow01.png) right 50% no-repeat, linear-gradient(to bottom, #fff 0% background-size: 20px, 100%; } </style> </head> <body> <input type="radio" name="shot" value="2P" style="width:50px;height:50px; position:absolu <input type="radio" name="shot" value="3P" style="width:50px;height:50px; position:absolu <input type="radio" name="shot" value="1P" style="width:50px;height:50px; position:absolu <input type="button" class="result" value="成功" style="WIDTH: 90px; HEIGHT: 60px; backgro <input type="button" class="result" value="失敗" style="WIDTH: 90px; HEIGHT: 60px; backgro <input type="button" value="保存" id="botanhozon" 15 style="WIDTH: 70px; HEIGHT: 50px; backg <input type="button" value="全削除" id="botanallremove" style="WIDTH: 60px; HEIGHT: 40px; <div style="position:absolute; top:780px; left:310px"> 2P </div> <div style="position:absolute; top:780px; left:393px"> 3P </div> <div style="position:absolute; top:780px; left:542px"> FT </div> <div class="select-box01"> <select onChange="navi(this)"> <option value=""> --- データを見る -- <option value="./pivotall.html">全クォータのデータ </select> </div> </body> <canvas style="background-color:peru;"></canvas> <script language="javascript"> var number = 0; obj=$("canvas"); $.jCanvas.defaults.layer = true; obj.get(0).width = $(window).width()*1.0; //自宅 0.9,0.9 obj.get(0).height = $(window).height()*0.76; obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 60, y1: 5, x2: サイドライン上 obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 0, y1: 627, x2: サイドライン下 obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 60, y1: 0, x2:6 エンドライン左 obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 1200, y1: 0, x2 エンドライン右 obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 615, y1: 0, x2: センターライン obj.drawArc({draggable:false, strokeStyle:"#000", strokeWidth: 10, x:615, y:320, radiu strokeStyle:"#000", strokeWidth: 10, x:110, y:317, radiu センターサークル obj.drawArc({draggable:false, 左3ポイントライン obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 0, y1: 61, x2: 左コーナー上 obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 0, y1: 573, x2: 左コーナー下 obj.drawArc({draggable:false, strokeStyle:"#000", strokeWidth: 10, x:1140, y:317, radi 右3ポイントライン obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 1230, y1: 61, x 右コーナー上 16 obj.drawLine({draggable:false, strokeStyle: "#000", strokeWidth: 10, x1: 1230, y1: 573, 右コーナー下 obj.drawRect({draggable:false, strokeStyle:"#000", strokeWidth: 10, x:0, y:320, width:45 左ペイントエリア obj.drawRect({draggable:false, strokeStyle:"#000", strokeWidth: 10, x:1230, y:320,width: 右ペイントエリア obj.drawArc({ draggable:false, strokeStyle:"#000", strokeWidth: 10, x:220, y:320, radiu strokeWidth: 10, x:1030, y:320, radiu 左トップオブザキー obj.drawArc({draggable:false, strokeStyle:"#000", 右トップオブザキー obj.drawRect({draggable:false, fillStyle:’#DEB887’,x:500,y:666,width:1420,height:69}); 下の番号置き場 obj.drawRect({draggable:false, fillStyle:’#A9A9A9’,x:28,y:323,width:56,height:738}); 左の番号置き場 obj.drawRect({draggable:false, fillStyle:’#A9A9A9’,x:1238,y:323,width:70,height:738}); 右の番号置き場 obj.drawText({ draggable:true, x:170, y:660, text:"4", layer:true, fillStyle:’blue’, font dragstop }); : function(layer) {number = 4; x4=layer.x; y4=layer.y;} obj.drawText({ draggable:true, x:230, y:660, text:"5", layer:true, fillStyle:’blue’, font dragstop }); : function(layer) {number = 5;} obj.drawText({ draggable:true, x:290, y:660, text:"6", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 6;} }); obj.drawText({ draggable:true, x:350, y:660, text:"7", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 7;} }); obj.drawText({ draggable:true, x:410, y:660, text:"8", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 8;} }); obj.drawText({ draggable:true, x:30, y:40, text:"9", layer:true, fillStyle:’blue’, fontSi dragstop }); : function(layer) {number = 9;} obj.drawText({ draggable:true, x:30, y:100, text:"10", layer:true, fillStyle:’blue’, font dragstop }); : function(layer) {number = 10;} obj.drawText({ draggable:true, x:30, y:160, text:"11", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 11;} }); obj.drawText({ draggable:true, x:30, y:220, text:"12", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 12;} }); obj.drawText({ draggable:true, x:30, y:280, text:"13", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 13;} 17 }); obj.drawText({ draggable:true, x:30, y:340, text:"14", layer:true, fillStyle:’blue’, font dragstop }); : function(layer) {number = 14;} obj.drawText({ draggable:true, x:30, y:400, text:"15", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 15;} }); obj.drawText({ draggable:true, x:30, y:460, text:"16", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 16;} }); obj.drawText({ draggable:true, x:30, y:520, text:"17", layer:true, fillStyle:’blue’, font dragstop : function(layer) {number = 17;} }); obj.drawText({ draggable:true, x:30, y:580, text:"18", layer:true, fillStyle:’blue’, font dragstop }); : function(layer) {number = 18;} $(function(){ var datalist = []; var i = 1; $(function(){ $(".result").click(function(){ var shot = $("[name=shot]:checked").val(); // 点数 var result = $(this).val(); // 成功 or 失敗 var zikan = new Date(); var h = zikan.getHours(); var m = zikan.getMinutes(); var s = zikan.getSeconds(); var time = h+"時"+m+"分"+s+"秒"; datalist.push({"number": number, "shot" : shot, "result": result, "time": time }); }); }); $(function() { $("#botanhozon").click(function(){ datalist_string = JSON.stringify(datalist); localStorage.setItem("testall",datalist_string); localStorage.setItem("test"+i,datalist_string); i++; }); }); $(function() { $("#botanallremove").click(function(){ localStorage.clear(); }); 18 }); }); </script> </html> KMTEXEditor では、SHIFT-F1 で環境は楽に作れる。引用文献は、論文は [1]、本は [4] のように後述し、引用す ること。 1.7. 次の節 参考文献 [1] 著者名: 論文名, 論文誌名, 巻数(西洋年号), 開始ページ数–終了ページ数. [2] 著者名:「本の題名」, 出版社, 出版年度. [3] 著者名:北川貴清/佐藤とも子・サチヨ「j Query プラグイン徹底活用」, 出版社:エムディエヌコーポレーショ ン, 出版年度.2012 年 [4] https://www.halawata.net/2011/10/jquery-noconflict/ 19
© Copyright 2024 ExpyDoc