# プロジェクト1
## 最終目標
+ Micro:bitの加速度センサの値をWebブラウザにリアルタイムに表示
+ Webブラウザのフォームに入力した英数字列をMicro:bitのLEDに表示
## 必要な手順
+ Bluetoothを使用し、PCとMicro:bitを接続
+ プログラムをC言語または子供用プログラミング環境を使用し、プログラムを作成
+ 加速度センサの値を出力する、英数字列を入力するWebフォームを作成
## 第1回(2023/09/21)
### 目標
+ HackMDでメモ用のWebフォームを作成
+ Micro:bitをPCに接続
### Webフォーム作成
Webフォームを使用するため、HackMDのアカウントを取得

とりあえず作った
作ったアカウントでWeb上のメモを作成

### Micro:bitをPCに接続
PC上のChromeブラウザでWeb-Bluetoothという,プラットフォームによらずブラウザからBLEデバイスと通信する機能を使用してMicro:bitとPC(Chromeブラウザ)間で無線通信を行う
今回は有線接続での接続(PCからの書き込み)のみにする
[マイクロソフトの子供向きプログラミング環境](https://makecode.microbit.org/)で書き込んでみる

Aを押すと顔文字が表示され、Bを押すと表示が消えるようにしてみる

わぁ...!
## 第2回(2023/09/28)
### 目標
+ Webページを作りたい
+ Bluetoothでの接続を試みる
### Webページの作成
Chrome DevTooLsを使ってHTMLで作成

とりあえずハリボテを作ってみた↓

ここにBluetoothでmicro:bitを接続できるようにプログラムを組んでいきたい
### Bluetoothでの接続を試みる
次にBluetoothを試みる
正直どうすればいいか見当もつかなかったので、JavaScript を介したBluetoothデバイスとの通信(https://developer.chrome.com/articles/bluetooth/)という資料を読んでみる

このあたりが参考になりそう
さっき作ったボタンのHTMLに付け足していく
参考資料ではバッテリーサービスをしようしている様子
今回はLEDのサービスを受けたいのでmicro:bitのサービスについて調べてみる
調べると、micro:bitのサービスについて書かれたものを見つけた
(https://lancaster-university.github.io/microbit-docs/resources/bluetooth/bluetooth_profile.html)

概要にLEDのテキストがうんたらみたいな項目を発見
このティッカーの部分をUUIDとして使用するみたい
## 第3回 (2023/10/5)
### 目標
+ 送信フォームを作成する
+ 送信フォームに書き込んだテキストを送信する
### 送信フォームを作成する
HTMLで作成

## 第4回 (2023/10/12)
### 目標
+ 送信フォームに書き込んだテキストを送信する(今回こそ)
### 送信フォームに書き込んだテキストを送信する
前回はUUIDサービスを使えるようにしたところまでで終わってしまった。
送信の方法は判らなかったので、まず作成したテキストがちゃんとidに入っているか試したみる。

するとコンソールに[Object HTMLInputElement]と表示され、入力された文字が確認できなかった。
調べたところ、表示させようとしたものがHTMLのinput要素であり、値が欲しいときはvalueプロパティにアクセスしなくてはいけないらしい(勉強不足)。
valueを追加し、改めて実行すると、

テキストボックスに入力されたものがしっかり格納されていることが確認できた。
いざ送信しようと思い、送信ボタンを押してみても何の反応もなし。
連打すると、接続が切れてしまう始末…
なので、submitで作ったボタンから、ocnclickでmicro:bit側に送信するためのプログラムを追加

上記のスクリプトを追加し、テキストを打って送信してみる。
## 第5回 (2023/10/19)
今までと何も変えていないプログラムでBluetoothが接続できなくなる
→なぜエラーが起こるか調べてもわからなかったためすべて書き直してみたところ改善した
UUIDの機能を読み込むとき受信機能を読み込まずに送信機能を読み込むと下記のようなエラー表示されることが何回かに一回起こった

このようなエラーが出てきたことから、削除ボタンを作らずサイトページの更新の連打で接続を無理やり切ろうとしていたことが原因なのではと考える
## 第6回 (2023/10/26)
### 目標
+ どのように送信するか考える
+ 送信を再び試みる
### どのように送信するか考える
どのように送信しているかわかっていなかったので、実際にデータの送受信をしているサイトを調べてみる
["micro:bitとブラウザ間で文字列をやり取りするまでの手順"](https://qiita.com/nakazawaken1/items/4a15480899722a33e8ee)
上記のサイトを参照すると、
const send = text => rx.writeValue(new TextEncoder().encode(text + '\n'))
sendという関数を作り、
document.getElementById('send').addEventListener('click', e => {
send(document.getElementById('send_text').value)
})
この部分で送信しているようである
sendの中身からnew TextEncoder().encode(text + '\n')で文字列をコードに変換し、マイクロビットに終了を伝えるために開業が付け足されている。
この部分を取り込む

送信ボタンを押すと、テキストボックスに入力された文字列がsend_boxに改行が足され、コードに変換されてたものがコンソールに表示されるようにしてみた

実行し、コンソールのコードを表で確認してみると正しく変換されていることが分かる
次に変換した文字コードの送信を試みる前に今まで作ったものは置いておき、上記のサイトだけを参考にしたプログラムを作ってみる。

このプログラムでは、文字列の送信が確認できた
このプログラムを参考に今まで書いてきたものに落とし込んでいきたい
### 送信を再び試みる
まずよくわかっていない所を書き出す
rx = characteristics[1]
このcharacteristics[1]になにがはいっているのかしらべてみる何が入っているのか調べてみる

コンソールには、
[object BluetoothmoteGATTCharacteristic]
と出てきた
## 第7回 (2023/11/02)
### 目標
+ LED送信を完成させる
+ 加速度の表示をできるところまでやる
### LED送信を完成させる
前回理解したことを踏まえ、プログラムを完成させる

rxに書き込み用のキャラクタを入れwriteValue()でテキストボックスに入力した文字列に改行を足して送信する

rx.writeValueという関数は存在しないと言われた
???
前回参考にした資料を見ても何かライブラリを参照している記述もないのになぜなんだろうか
[BlueJelly](https://github.com/electricbaka/bluejelly/blob/master/src/bluejelly.js)というBluetoothでデバイスとWEBの通信を行うプログラムを簡単に組むためのライブラリの中身をのぞいてみても

となっており、writeValueで送信していることがわかる
解決できないまま火曜日になってしまったため、大幅にテコ入れすることにした
buttonclickで関数へ移動するのではなく、前回使った資料1つだけを参考にして作成してみる
↓変更したプログラム

このプログラムではwriteValueは定義しなくても他の関数のように実行できてた
実行結果




しっかり送信されていることが確認できた
## 配布機材
- Micro:bit (**v1**)
- USBケーブル(開発時にMicro:bitとPCを接続)
# プロジェクト2
## 最終目標
ポインタのドラッグで図形を動かせるウェブページを関数型言語Elmで実現する。
## 必要な手順
+ Elmという言語への理解
+ Elmを使用したウェブページの作成
+ 図形のポインタによるドラッグ操作の実装
## 第1週(2023/11/16)
### 目標
+ Elmの書き方、構文の意味について調べてみる
+ 試しにElieを使ってウェブページを作ってみる
### Elmの書き方、構文の意味について調べてみる
初めて触る言語なので、Elmの[日本語訳サイト](https://guide.elm-lang.jp/types/reading_types.html)を使い、Elieを開いたときに最初に書いてある文にコメントアウトを入れながら理解を試みる。

本当に基礎の基礎はなんとなくつかめた
### 試しにElieを使ってウェブページを作ってみる
サンプルプログラムを書き換えて足し算のプログラムを作ってみる

```
module Main exposing (main)
import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
type alias Model =
{ count : Int
,count2: Int
,count3: Int}
initialModel : Model
initialModel =
{ count = 0
,count2 = 0
,count3 = 0}
type Msg
= Increment
| Decrement
| Increment2
| Decrement2
| Total
update : Msg -> Model -> Model
update msg model =
case msg of
Increment ->
{ model | count = model.count + 1 }
Decrement ->
{ model | count = model.count - 1 }
Increment2 ->
{ model | count2 = model.count2 + 1 }
Decrement2 ->
{ model | count2 = model.count2 - 1 }
Total ->
{ model | count3 = model.count + model.count2}
view : Model -> Html Msg
view model =
div []
[ button [ onClick Increment ] [ text "+1" ]
, div [] [ text <| String.fromInt model.count ]
, button [ onClick Decrement ] [ text "-1" ]
, div [] [ text " "]
, button [ onClick Increment2 ] [ text "+1" ]
, div [] [ text <| String.fromInt model.count2 ]
, button [ onClick Decrement2 ] [ text "-1" ]
, div [] [ text " "]
, button [ onClick Total ] [ text "Total" ]
, div [] [ text <| String.fromInt model.count3 ]
]
main : Program () Model Msg
main =
Browser.sandbox
{ init = initialModel
, view = view
, update = update
}
```
## 第2週(2023/11/30)
### 目標
+ Jsでプログラムを作ってみる
+ 作ったプログラムをElmに少しずつ置換してみる
### Jsでプログラムを作ってみる
やはりElmだとイマイチどう書いていいか分からないので、まずはJsでプログラムを書いてみることで、Elmに対してどうアプローチしていくか考えてみることにした。
以下、Jsでの図形ドラッグでのプログラム
```
<html>
<head>
<meta charset="UTF-8">
<title>図形</title>
</head>
<body>
<canvas id="Canvas" width="800" height="600"></canvas>
<script>
const canvas = document.getElementById('Canvas');
const ctx = canvas.getContext('2d');
// 図形を描画する関数
function Shikaku(x, y, width, height) {
ctx.beginPath();
ctx.rect(x, y, width, height);
ctx.fillStyle = 'red';
ctx.fill();
ctx.closePath();
}
// 図形を描画
Shikaku(50, 50, 100, 100);
// マウス操作
canvas.addEventListener('mousedown', Mousedown);
canvas.addEventListener('mousemove', Mousemove);
canvas.addEventListener('mouseup', Mouseup);
// 図形の位置情報
let shape = { x: 50, y: 50, width: 100, height: 100 };
// ドラッグ中の状態の保持
let Drag = false;
// マウスの関数
//ドラッグ開始
function Mousedown(i) {
//マウス座標
const mouseX = i.clientX - canvas.offsetLeft;
const mouseY = i.clientY - canvas.offsetTop;
//図形内でクリックされていたら
if (mouseX >= shape.x && mouseX <= shape.x + shape.width &&mouseY >= shape.y && mouseY <= shape.y + shape.height) {
Drag = true;
}
}
//ドラッグ中
function Mousemove(i) {
//ドラッグ中でなければ戻る
if (!Drag) return;
//マウス座標
const mouseX = i.clientX - canvas.offsetLeft;
const mouseY = i.clientY - canvas.offsetTop;
//移動後の座標計算
const dx = mouseX - shape.x;
const dy = mouseY - shape.y;
shape.x += dx;
shape.y += dy;
//キャンバスをクリア
ctx.clearRect(0, 0, canvas.width, canvas.height);
//図形を描画
Shikaku(shape.x, shape.y, shape.width, shape.height);
}
//ドラッグ終了
function Mouseup(i) {
Drag = false;
}
</script>
</body>
</html>
```
創成Dでお絵かきソフトを作った際に使ったサイトを参考にさせてもらっている
[canvasを使いお絵描きアプリを作る。(各機能ざっくり解説)](https://qiita.com/nakagami5963/items/41e8eaeae241650bc03e)
[【Javascript】マウスイベントの使い方](https://hataworakuni.net/how-to-handle-mouse-event-in-javascript)
このプログラムを実行すると以下のようになる

#### 作成時に起きた不具合
+ ドラッグするとペンの様に移動した軌道が描かれる

原因:ctx.clearRect(0, 0, canvas.width, canvas.height);
この文で移動前の図形を消さないと図形が増え続け、線の様になってしまう
+ 図形外をドラッグしてるのに動く
原因:条件式の不足
### 作ったプログラムをElmに少しずつ置換してみる
ここから少しずつElmに移植を試みる
まずHTMLの部分をサンプルコードに移す

Canvasに色を付けたことによりしっかりと表示さえていることが分かる
ここからどうすれは良いかわからず、取り合えずHTMLのイベント追加部分にaddEventListenerを追加してみると

と自分の求めていたものがでてきた
文字の字面的に
mousedown = onMouseEnter
mousemove = onMouseLeave
mouseup = onMouseOut
だろうか
次回はこれをが合っているか検証しながら進めていきたい
## 第3週(2023/12/07)
### 目標
+ 前回作ったプログラムの簡略化
+ 変更したプログラムの移植
### 前回作ったプログラムの簡略化
前回作ったプログラムを簡略化する。矢野君のプログラムを参考にしてプログラムを短くする。
変更点は、
+ キャンバスの削除
+ 図形内を指定する式の削除
+ addEventListenerの()にそのまま書き込む
変更後のプログラム
```
<html>
<head>
<meta charset="UTF-8">
<title>図形</title>
<style>
#akashikaku {
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
</head>
<body>
<div id='akashikaku'></div>
<script>
// 図形の位置情報
let shape = { x: 50, y: 50, width: 100, height: 100 };
// ドラッグ中の状態の保持
let Drag = false;
const akashikau = document.getElementById('akashikaku');
// マウスの関数
//ドラッグ開始
document.addEventListener('mousedown',(event) =>{
//マウス座標
const mouseX = event.clientX;
const mouseY = event.clientY;
//図形内でクリックされていたら
Drag = true;
});
//ドラッグ中
document.addEventListener('mousemove',(event) =>{
//ドラッグ中でなければ戻る
if (!Drag) return;
//マウス座標
const mouseX = event.clientX;
const mouseY = event.clientY;
//移動後の座標計算
akashikaku.style.left = mouseX + 'px';
akashikaku.style.top = mouseY + 'px';
});
//ドラッグ終了
document.addEventListener('mouseup',(event) =>{
Drag = false;
});
</script>
</body>
</html>
```

簡略化し前回と同じように動くプログラムを作成することができた。
変更前

変更後

### 変更したプログラムの移植
移植するにあたり、先週に先生がおっしゃていた'on'の使い方について調べてみた。すると、[Elmでmouseイベントを取得する覚書](https://blog.emattsan.org/entry/2019/05/26/093114)について発見した。
以下マウスの座標を表示するプログラム
```
module Main exposing (main)
import Browser
import Html exposing (Html, div, span, text)
import Html.Events exposing (on)
import Html.Attributes exposing (style)
import Json.Decode exposing (map2, field, int)
type alias Model = { x: Int , y: Int }
init : Model
init = { x = 0 , y = 0 }
type Msg = Move Int Int
update : Msg -> Model -> Model
update msg model =
case msg of
Move x y -> {x = x, y = y}
view : Model -> Html Msg
view model =
div []
[ span
[]
[ text ("(" ++ (String.fromInt model.x) ++ ", " ++ String.fromInt model.y ++ ")") ]
, div
[ style "background-color" "gray"
, style "height" "80vh"
, on "mousemove" (map2 Move (field "clientX" int) (field "clientY" int))
]
[]
]
main =
Browser.sandbox
{ init = init
, update = update
, view = view
}
```
mousemoveイベントのうちclientXとclientYの二つのフィールドをそれぞれIntとして取得し、Moveを適用するデコーダだそう
実行すると、このように表示される

このコードを実行するにあたり、第2週目あたりからjson decodeを使用したが、Elieには標準装備の物ではないらしく、パッケージをインストールする必要があった。

このサイトを参考に作ったものでは結局キャンバスのようなものを作ってしまっているので来週以降で改善したい
## 第4週(2023/12/14)
### 目標
+ 前回作成したJsのプログラムを活かしてElmでプログラムを作成する
### 前回作成したJsのコードを活かしてElmでプログラムを作成する
前回、Jsのプログラムの簡略化を行った。また、サイトからMouseイベントの扱い方について調べてきた。
今回はそれを組みわせて完成に近づけていきたい。
まずは、前回作成した座標を表示するプログラムを変更し、ページの中に図形を表示する。図形を表示するプログラムは矢野君の第2回の資料を参考にしている。
```
module Main exposing (main)
import Browser
import Html exposing (Html, div, span, text)
--mouseイベントに関する構文を取得
import Html.Events exposing (on, onMouseUp, onMouseDown)
import Html.Attributes exposing (style)
--json decodeでmousemoveに必要な関数を取得
import Json.Decode exposing (map2, field, int)
--x,y,dragの変数を作成
type alias Model = { x: Int
, y: Int
, drag: Int}
init : Model
--x,y,dragの初期値を設定
init = { x = 0
, y = 0
, drag = 0}
type Msg = Move Int Int --mousemoveに対応する関数を作成
update : Msg -> Model -> Model
update msg model =
case msg of
Move x0 y0 ->
{model | x = x0, y = y0}
view : Model -> Html Msg
view model =
let zukei =
[ --動かす図形を作成
style "position" "absolute"
, style "width" "100px"
, style "height" "100px"
, style "background-color" "blue
--図形座標をmodel内のx,yにする
, style "left" (String.fromInt model.x ++ "px")
, style "top" (String.fromInt model.y ++ "px")
]
in
div []
[ div
[ --
style "height" "100vh"
--マウスの座標をx0,y0に代入
, on "mousemove" (map2 Move (field "clientX" int) (field "clientY" int))
]
[ div
zukei []
]
]
main =
Browser.sandbox
{ init = init
, update = update
, view = view
}
```
これを実行すると以下のように表示される

だがこのプログラムでは、ドラッグしていなくてもマウスの位置に図形がついてきてしまう。よってここにmousedownとmouseupの文を書き加えていく
最初に、mousedownとmouseupに対応する関数をMsg内に用意する
```
Update内の追加文
case msg of
Up ->
{model | drag = 0}
Down ->
{model | drag = 1}
View内の追加文
view : Model -> Html Msg
let zukei =
[ --動かす図形を作成
style "position" "absolute"
, style "width" "100px"
, style "height" "100px"
, style "background-color" "blue"
--ドラッグ時にdragを1(true)に
, onMouseDown Down
--図形座標をmodel内のx,yにする
, style "left" (String.fromInt model.x ++ "px")
, style "top" (String.fromInt model.y ++ "px")
]
in
div []
[ div
[ --
style "height" "100vh"
--マウスの座標をx0,y0に代入
, on "mousemove" (map2 Move (field "clientX" int) (field "clientY" int))
view model =
--非ドラッグ時にdragを0(false)に
, onMouseUp Up
]
[ div
zukei []
]
]
```
mousedownとmouseupが起こった時にmodel内のdragに0or1を代入する文を作成した。
dragが1の時のみ図形が動くようにしたい
次にどこかにif文を書き込むのだがどこに書くのか分からない、、、



いろんな場所に入れてみたif文の供養
悩んだ結果、JsやCのswich文をもとに考えてみると
```
swich (x) of
case 1;
####(式)
break;
case 2;
####
break;
case 3;
break;
```
普通にcaseの中にif文を入れればいいのでは…???
Elm内でcaseに当たるのは、Msgに作成したUp、Down、Moveなのでこの中に作ってみる。
```
update : Msg -> Model -> Model
update msg model =
case msg of
Up ->
{model | drag = 0}
Down ->
{model | drag = 1}
Move x0 y0 ->
if model.drag == 1 then --drag=1のとき座標を現在のマウスの場所に変更
{model | x = x0, y = y0}
```
これで動かしてみる

エラーは出たが今までのエラーとは違いelse文がないから条件式に当てはまらなかったときの動作が書かれてないと言われた
つまり、if文の頭は正しく動作していることが分かるのでそのままelse文を追加する
```
module Main exposing (main)
import Browser
import Html exposing (Html, div, span, text)
--mouseイベントに関する構文を取得
import Html.Events exposing (on, onMouseUp, onMouseDown)
import Html.Attributes exposing (style)
--json decodeでmousemoveに必要な関数を取得
import Json.Decode exposing (map2, field, int)
--x,y,dragの変数を作成
type alias Model = { x: Int
, y: Int
, drag: Int}
init : Model
--x,y,dragの初期値を設定
init = { x = 100
, y = 100
, drag = 0}
type Msg = Move Int Int --mousemoveに対応する関数を作成
| Up --onMouseUp
| Down --onMouseDown
update : Msg -> Model -> Model
update msg model =
case msg of
Up ->
{model | drag = 0}
Down ->
{model | drag = 1}
Move x0 y0 ->
if model.drag == 1 then --drag=1のとき座標を現在のマウスの場所に変更
{model | x = x0, y = y0}
else
{model | x = model.x, y = model.y} --drag=0のとき座標を現在の位置で固定
view : Model -> Html Msg
view model =
let zukei =
[ --動かす図形を作成
style "position" "absolute"
, style "width" "100px"
, style "height" "100px"
, style "background-color" "blue"
--ドラッグ時にdragをtrueに
, onMouseDown Down
--図形座標をmodel内のx,yにする
, style "left" (String.fromInt model.x ++ "px")
, style "top" (String.fromInt model.y ++ "px")
]
in
div []
[ div
[ --
style "height" "100vh"
--マウスの座標をx0,y0に代入
, on "mousemove" (map2 Move (field "clientX" int) (field "clientY" int))
--非ドラッグ時にdragをfalseに
, onMouseUp Up
]
[ div
zukei []
]
]
main =
Browser.sandbox
{ init = init
, update = update
, view = view
}
```
これを実行すると、

しっかりと図形をドラッグしたときのみ動かすことができた