Ethereumについて学んでみる
Ethereum(イーサリアム)ってなに?
Etherreumはそもそも分散アプリケーションのためのプラットフォームです。(公式サイト)
分散アプリケーションと中央管理型
gitなどのバージョン管理システムでも、中央管理型と分離型とありますが、それと似たようなものです。
※中央管理型
具体例としては、インスタにアップロードした画像データはFacebook(開発元)が中央で一元管理することにより、サービスが成り立っています。これらのサービスを運営するにあたって、中央で管理するシステムが必須でした。
中央管理型の欠点として良く言われるのが、
・中央管理システムが何かしらの理由で機能しなくなったり、障害が発生した場合のデータ消失などのリスクが大きい
・私的企業が一手に個々のデータを握ることはプライバシーの観点から好ましくない
そこで、Ethereumは「ブロックチェーン」と呼ばれる技術を用いて、特別な管理者のいらないP2P※システム上で、様々なサービス(仮想通貨を扱ったりなど)を実現するためのプラットフォームを提供するものです。
※対等な関係にある端末間を相互に直接接続し、データを送受信する通信方式。Facebookのメッセなど
どういうことかというと、Facebookといったような、中央で管理する機関(企業)を必要とせずに同様のサービスを実現できるプラットフォームを提供します。
ブロックチェーンとは?
ブロックチェーンの技術を一言でいうと、「不正が難しい取引台帳」です。
ここでいう不正は、取引の改ざんや二重取引などです。
仮想通貨のビットコインを使って説明していきます。
※取引改ざん
※二重取引
二重取引のようにAさんが10コインを持っていると仮定して、Bさんに5コインを送金し、Cさんに2コイン送金したとします。
取引内容としては下記のようになり、取引を1つ1つ管理せずに、1つのまとまり(ブロック)として管理します。まとめ方は一定時間内に発生した取引毎です。
・取引:A→B
・取引:A→C
さらに、このブロックにハッシュを付与します。
※ハッシュ:メッセージを特定するための暗号化技術
・取引:A→B ハッシュ
・取引:A→C
一定時間を過ぎた後に新たな取引があった場合には新規にブロックを生成します。
では、BさんからCさんへ送金・CさんからAさんへ送金があったとします。
・取引:B→C ハッシュ
・取引:C→A
この時(新規ブロックを生成時)に、ひとつ前のブロックのハッシュも含めます
ただし、ハッシュはブロックごとに異なります(当たり前ですが)。
この関係により各ブロックは時系列でつながります。
・取引:A→B ハッシュ
・取引:A→C
↓
・取引:B→C ハッシュ
・取引:C→A
改ざんするには後続にあるブロックも改ざんしていく必要があります。
そうしないと整合性がとれないからです。
ブロックがどんどん鎖のようにつながっていく様子からブロックチェーンと名づけられました。
上記では「データ構造」について説明してきましたが、実はブロックチェーンにはもう一つ重要な仕組みがあります。それは「データの管理方法」です。
ブロックチェーンは、「データ構造」と「データの管理方法」で成り立ってます。
次回はデータの管理方法について見て行きます。
ファイルアップロードをドラッグ&ドロップでも可能にする
ファイルアップロードするには?
フロント側のHTMLもしくはPHPファイルにフォームの記述をします。
<form action="" method="post" enctype="multipart/form-data"> <input type="file" value="ファイルを選択" name="image"> <input type="value" value="送信"> </form>
画像を扱う場合にはenctype部分が必須になります。他にもinputタグにaccept属性を指定することにより、画像の形式をpng、jpgのみ受け付けるようにすることなどもできますが、今回は必要最低限で説明していきます。
次に画像ファイルを受け取る裏側を書いていきます。詳しくは説明しないんですが、1行目のif文で画像データが問題なく送られているかチェックします。問題がなければ4・5行目でアップロードしたファイル名と拡張子を取得します
ex)test.png→$filename=test、$extension=png
$tmp_pathでアップロード画像が仮で置かれているパスを取得します。
$file_dir_pathでアップロードした画像をどこに置くかを選択。今回は同階層のuploadフォルダに格納するようにする。
$uniq_nameは同じファイル名でアップロードした場合は上書きされて古い画像が消えてしまうのを避けるために格納する際にユニークな名前をつけて画像が上書きされるのを避けます。
入れ子になった最初のif文でPOSTでアップロードされたファイルか確認。次のif文でアップロードされたファイルを新しい位置に移動する。
移動できたら、パーミッション(アクセス権限)を設定。所有者は読み書きOK、それ以外は読み込みだけOK
if (!isset($_FILES['image']['error']) || !is_int($_FILES['image']['error'])){ echo "ファイルアップロードエラー"; } else { $file_name = $_FILES['image']['name']; $extension = pathinfo($file_name, PATHINFO_EXTENSION); //拡張子取得 $tmp_path = $_FILES['image']['tmp_name']; $file_dir_path = "upload/"; $uniq_name = date("YmdHis").md5(uniqid(microtime(),1)).session_id() . "." . $extension; if (is_uploaded_file($tmp_path)) { if(move_uploaded_file( $tmp_path, $file_dir_path . $uniq_name)) { chmod($file_dir_path . $uniq_name, 0644); } else { echo "Error:アップロードできませんでした。"; } } }
これで必要最低限のシステムはできました。
ファイルアップロードをドラッグ&ドロップでも可能にするには?
今回のゴールは下記のようなドラッグ&ドロップでもアップロードを可能にするシステムです。
簡単な話ではありますが、上記で作ったシステムとjsを使えば実装できます。
jQueryは使わずに生のjsで書いてみます。その前に、フロント部分の記述を少し変更します。
cssは各々で調整してください。
<form action="" method="post" enctype="multipart/form-data"> <div id="drag-drop-area"> <div class="drag-drop-inside"> <p class="drag-drop-info">ここにファイルをドロップ</p> <p>または</p> <input type="file" value="ファイルを選択" name="image"> <p class="drag-drop-buttons"><input id="fileInput" type="file" value="ファイルを選択" name="image"></p> <input type="value" value="送信"> </div> </div> </form>
fileAreaでドラッグ&ドロップの有効範囲を設定。fileInputにfile属性のinputタグを代入しておく。
dragoverイベントはドラッグしている要素がドロップ領域にある間に発生
dragleaveイベントはドラッグしている要素がドロップ領域から出たときに発生
dropイベントはドラッグしている要素がドロップ領域にドロップされたときに発生
その他にもドラッグ&ドロップのイベントはあります。もっと知りたい方は下記のリンクを参考にしてください。
https://app.codegrid.net/entry/dnd-api-1
files変数にドロップされた画像のデータ情報が入り、そのデータをfileInputに渡しているだけです。
これで完成です。
※ドロップした時点でアップロードしたい際には、changeイベントを使えば可能です
var fileArea = document.getElementById('drag-drop-area'); var fileInput = document.getElementById('fileInput'); fileArea.addEventListener('dragover', function(evt){ evt.preventDefault(); fileArea.classList.add('dragover'); }); fileArea.addEventListener('dragleave', function(evt){ evt.preventDefault(); fileArea.classList.remove('dragover'); }); fileArea.addEventListener('drop', function(evt){ evt.preventDefault(); fileArea.classList.remove('dragenter'); var files = evt.dataTransfer.files; fileInput.files = files; });
スマホRPGで例えてみるオブジェクト指向
そもそもオブジェクト指向って何?
オブジェクトとは、物体(スマホとか)を、属性(データ)と操作(メソッド)の集合として、定義して、コンピューターで扱えるようにしたもの。
このオブジェクトを組み合わせて、開発を行うことをオブジェクト指向プログラミングと呼びます。
何を言っているか分かりませんね。
オブジェクト指向の考え方
・クラス/インスタンス化/オブジェクト
・継承
クラス
たとえば、キャラ毎の詳細を見てみます。
これをレア度が「レジェンド」のクラスと呼びます。
レジェンドキャラの設計図、つまり「クラス」
インスタンス化
?の箇所を埋めないと使えるキャラとして成り立ちませんよね。
設計図=クラスの空白部分を埋めて実体化(使えるよう)することをインスタンス化といいます。
元になっている設計図=クラスさえあれば量産することが可能です。
※キャラ画像とステータスさえ変えれば、別物になる
↓
オブジェクトを組み合わせて、1つのソフトウェアを構築するのがオブジェクト指向!
ex)上のオブジェクトを組み合わせてパーティー作ったり
継承
オブジェクトの定義を定めた雛型を「クラス」と呼び、上位のクラスを性質を引き継いだ上で、他の性質を加えた新しいクラスを作成することを「継承」と呼ぶ。
ノーマルキャラ
↑スーパークラス(基本クラス)
レジェンドキャラ(ノーマルキャラにはないスキルが使えたりetc...)
カプセル化
データとそれを動かす(メソッド)操作を一体化して「オブジェクト」として定義し、オブジェクト内の細かい仕様や構造を外部から隠ぺいすること。
外部からは公開された手続きを利用することでしかデータを操作できないようにすることで、ここのオブジェクトの独立性が高まる。
※カプセル化を進めることによりオブジェクト内部の仕様変更が外部に影響しなくなり、ソフトウェアの保守性や開発効率が高まり、プログラムの部分的な再利用が容易になる。
HPのデータに直接減算するようなことはしない
ダメージを与えるメソッドを呼ぶことでHPを減らす処理を行う
ポリモーフィズム
「多様性」「多態性」「多様性」
オブジェクト指向プログラミング言語の持つ性質のひとつであり、同盟のメソッドや型などをオブジェクトの種類に応じて使い分けることができる性質のこと
オブジェクト指向プログラミングでは、関連するひとまとまりのデータとそれを操作する関数などの組み合わせ「オブジェクト」として定義していき、これを組み合わせてプログラムを記述していく。
継承を行う際に、上位のクラスの関数を新しい関数の定義で置き換えることを「オーバーライド」と呼び、クラスによって同一のメソッドで異なる処理が行われる性質をポリモーフィズムといいます。
※ポリモーフィズムの利点としては、メソッド名を統一することで名前を覚える必要がなくなることや、記述ミスを減らせることなどが挙げられます。
/*-----------------------------------
ex)攻撃のメソッドで考えてみる。
①敵のHPにダメージ与える
②敵の攻撃力にダメージを与える(弱体化)
-----------------------------------*/
同じ攻撃でも処理が異なる。
ポリモーフィズムという考え方を使わないと、同じ攻撃でも異なるメソッドを使わなくてはならない。
スキルと攻撃みたいに明確に分ける必要があれば、ポリモーフィズムを使わない方がいい。
JavaScriptで現在から数日~数週間前の日時を取得するには?
まず、JavaScriptで日時を扱うには?
js側で用意している組み込み関数のDateオブジェクトを使用します。
使用方法は
var 変数名 = new Date();
で、Dateオブジェクトを生成します。
今回、次のような日時を使ったグラフを作っていきます。
ステップ1
グラフを簡単に作成するjsのライブラリとしてchart.jsを使っていきます。
リンクをクリックしたら、下の画面に飛ぶので、Get Startedをクリック
ステップ3
今回使うファイルは、Chart.js-master→distフォルダ→Chart.min.jsのみを使います
Chart.min.jsを任意の場所に移動して置いてください。
上記ような操作が面倒な方はCDNも公開されているのでそちらを使っても大丈夫です
https://cdnjs.com/libraries/Chart.js
まず、HTMLファイルの雛型を用意して、グラフを描画するためのcanvasタグを書きつつ、chart.jsを読み込んでおきます
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <div style="width:600px;height: 450px;margin: 0 auto;"> <canvas id="canvas" height="450" width="600"></canvas> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js"></script> <script> </script> </body> </html>
ステップ4
次に、scriptタグの中にchart.jsを使用するためのコードを書いてあげます
chart.jsの解説はしませんが、興味がある方は調べてみてください
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.1.6/Chart.min.js"></script> <script> var config = { type: 'line', data: { labels : ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'], datasets: [{ label: "ページビュー数", fill: false, backgroundColor: "#3A7AC9", borderWidth: 2, borderColor: "rgba(2,63,138,0.8)", pointBorderColor: "#fff", pointBackgroundColor: "rgba(2,63,138,0.8)", pointBorderWidth: 2, pointHoverRadius: 5, pointHoverBackgroundColor: "#1D5191", pointHoverBorderColor: "#fff", pointHoverBorderWidth: 2, tension: 0, data: [1, 59, 90, 81, 56, 55, 40, 30, 10, 40, 48, 58] }, { label: "セッション", fill: false, backgroundColor: "#DB514E", borderWidth: 2, borderColor: "rgba(201,60,58,0.8)", pointBorderColor: "#fff", pointBackgroundColor: "rgba(201,60,58,0.8)", pointBorderWidth: 2, pointHoverRadius: 5, pointHoverBackgroundColor: "#9A1B19", pointHoverBorderColor: "#fff", pointHoverBorderWidth: 2, tension: 0, data: [28, 48, 40, 19, 96, 27, 100, 33, 63, 31, 64, 51] }] }, options: { responsive: true, scales: { xAxes: [{ display: true, stacked: false, gridLines: { display: false } }], yAxes: [{ display: true, ticks: { reverse: false, callback: function(value){ return value; } } }] } } }; // ▼上記のグラフを描画するための記述 window.onload = function() { var ctx = document.getElementById("canvas").getContext("2d"); window.myLine = new Chart(ctx, config); }; </script> </body> </html>
上記のコードを書いてあげてブラウザで見てみると、グラフが出来上がっていると思います
ステップ5
赤枠で囲ってる部分を現在の月と日時に書き換えてあげたいと思います
var config = { の上にscriptを記述していきます
2つDateオブジェクトを生成してあげます
空の配列を用意して、for文で今日の日付から1週間前の経過日数を出して、配列に挿入しています。
<script> var date = new Date(); var before = new Date(); var week = []; for(var i = 0;i < 7;i++) { week.unshift(date.getDate() - i); } var config = { </script>
ステップ6
出力結果が下記になります。今日が21日なので、1週間分がしっかりと取れてますね
ただ、これだと問題があります。今回は月をまたいでいないので、問題が無いように見えますが、例えば、6/1の前日の日付を取ろうとした場合に本来であれば、5/31にならなければならないのに、5/0になります。試してみましょう
for文で回す値を大きくしてあげます。
<script> var date = new Date(); var before = new Date(); var week = []; for(var i = 0;i < 25;i++) { week.unshift(date.getDate() - i); } var config = { </script>
ステップ7
そうすると意図した結果にならないのが分かると思います。これを避けるためには、setDate()メソッドを使用します。
簡単に説明すると、指定した値が1から31の範囲外の場合は、Dateオブジェクトの日付の情報の更新を試みます。例えば0が値として指定された場合、前月の最終日に設定されます。
<script> var date = new Date(); var before = new Date(); var week = []; for(var i = 0;i < 25;i++) { before.setDate(date.getDate() - i); week.unshift(before.getDate()); } var config = { </script>
ステップ8
先月の日時がしっかりとれてますね。
そしたら、配列に月も挿入してあげつつ、chart.jsのlabelsの中身をweekに変更してあげれば完成です
getMonth()に+1している理由はgetMonthメソッドでは1月が0、2月が1といった具合に、1つ下にずれた数字が取得されるからです
※for文の値も直しておきます
<script> var date = new Date(); var before = new Date(); var week = []; for(var i = 0;i < 7;i++) { before.setDate(date.getDate() - i); week.unshift(before.getMonth() + 1 + '月' + before.getDate() + '日'); } var config = { type: 'line', data: { labels : week, </script>
英語のみ横幅(width)をはみ出る挙動
HTMLの「div」タグなどでボックスを作り、classやidを用いてcssのwidthプロパティを使用して横幅を指定したとしても、英語は枠におさまらない場合があります。
※今回の場合はoverflow:hiddenをかけているので、文字が途切れている
結論から言ってしまえば、
を使用すれば英語であっても折り返し可能です。
大手のサービスであってもこういった対策していないところもあるので注意が必要です。日本であっても英単語を羅列する場合はあるので(IT業界では多い)、多様なパターンでデバックするようにしましょう。